diff --git a/apps/docs/components/examples-showcase.tsx b/apps/docs/components/examples-showcase.tsx index 9c09735..a853f9d 100644 --- a/apps/docs/components/examples-showcase.tsx +++ b/apps/docs/components/examples-showcase.tsx @@ -17,6 +17,28 @@ interface Example { const VIDEO_BASE_URL = "https://assets.yourgpt.ai/web/copilot-sdk"; const examples: Example[] = [ + { + id: "skills-demo", + title: "Skills System", + description: + "Dynamic skill loading for domain-specific AI behavior. Skills are markdown files that get loaded on-demand — the AI discovers and activates them when relevant. Drag & drop to add skills at runtime.", + preview: "/images/skills-demo.png", + tags: ["Skills", "Dynamic Loading", "Drag & Drop", "HR Copilot"], + github: + "https://github.com/YourGPT/copilot-sdk/tree/main/examples/skills-demo", + video: `${VIDEO_BASE_URL}/skills-demo.mp4`, + }, + { + id: "generative-ui-demo", + title: "Generative UI", + description: + "AI-generated interactive UI components rendered in real-time. Tables, charts, metric cards, and insights — all generated dynamically from natural language queries.", + preview: "/images/gen-ui-demo.png", + tags: ["Generative UI", "Charts", "Tables", "Data Visualization"], + github: + "https://github.com/YourGPT/copilot-sdk/tree/main/examples/generative-ui-demo", + video: `${VIDEO_BASE_URL}/gen-ui-demo.mp4`, + }, { id: "mcp-demo", title: "MCP Integration", diff --git a/apps/docs/content/docs/chat/attachments.mdx b/apps/docs/content/docs/chat/attachments.mdx index bf2ba81..3ed3643 100644 --- a/apps/docs/content/docs/chat/attachments.mdx +++ b/apps/docs/content/docs/chat/attachments.mdx @@ -482,6 +482,6 @@ function ChatWithAttachments() { ## Next Steps -- [Streaming](/docs/streaming) - Real-time responses -- [AI Context](/docs/ai-context) - Provide app context -- [Custom Tools](/docs/custom-tools) - Build tools that use attachments +- [Streaming](/docs/llm-sdk/stream-text) - Real-time responses +- [AI Context](/docs/skills) - Provide app context +- [Custom Tools](/docs/tools/frontend-tools) - Build tools that use attachments diff --git a/apps/docs/content/docs/index.mdx b/apps/docs/content/docs/index.mdx index 548a6ce..fa73070 100644 --- a/apps/docs/content/docs/index.mdx +++ b/apps/docs/content/docs/index.mdx @@ -116,7 +116,7 @@ You define tools, we handle the rest. }> OpenAI, Anthropic, Google, xAI, and more - }> + }> Share app state with AI diff --git a/apps/docs/content/docs/overview.mdx b/apps/docs/content/docs/overview.mdx index 9ba7712..5932fe0 100644 --- a/apps/docs/content/docs/overview.mdx +++ b/apps/docs/content/docs/overview.mdx @@ -79,7 +79,7 @@ AI calls `search_products({ query: "wireless headphones" })` → Shows results. | [**Chat UI**](/docs/chat) | Pre-built chat with streaming, markdown, code blocks | | [**Frontend Tools**](/docs/tools/frontend-tools) | Give AI abilities in your app | | [**Generative UI**](/docs/generative-ui) | Render React components as tool results | -| [**Smart AI Context**](/docs/smart-ai-context) | AI understands your app state | +| [**Smart AI Context**](/docs/skills) | AI understands your app state | | [**Agentic Loop**](/docs/tools/agentic-loop) | Multi-step reasoning and tool chains | | [**Attachments**](/docs/attachments) | Images, PDFs, and files in chat | | [**4+ Providers**](/docs/providers) | OpenAI, Anthropic, Google, xAI... | diff --git a/apps/docs/content/docs/tools/agentic-loop.mdx b/apps/docs/content/docs/tools/agentic-loop.mdx index 4fb6962..8c19775 100644 --- a/apps/docs/content/docs/tools/agentic-loop.mdx +++ b/apps/docs/content/docs/tools/agentic-loop.mdx @@ -498,6 +498,5 @@ Tools use reference counting so React StrictMode double-invocations don't leave ## Next Steps -- [Tool Approval](/docs/tool-approval) - Add human confirmation -- [AI Response Control](/docs/ai-response-control) - Control AI responses -- [Streaming](/docs/streaming) - Real-time updates +- [Tool Approval](/docs/tools/frontend-tools) - Add human confirmation +- [Streaming](/docs/llm-sdk/stream-text) - Real-time updates diff --git a/apps/docs/content/docs/tools/built-in/console.mdx b/apps/docs/content/docs/tools/built-in/console.mdx index 54b06d3..86ced0d 100644 --- a/apps/docs/content/docs/tools/built-in/console.mdx +++ b/apps/docs/content/docs/tools/built-in/console.mdx @@ -232,6 +232,6 @@ function DebugTools() { ## Next Steps -- [Screenshot Tool](/docs/tools/screenshot) - Capture visual context -- [Tool Approval](/docs/tool-approval) - Approval flow details -- [Custom Tools](/docs/custom-tools) - Build more debugging tools +- [Screenshot Tool](/docs/tools/built-in/screenshot) - Capture visual context +- [Tool Approval](/docs/tools/frontend-tools) - Approval flow details +- [Custom Tools](/docs/tools/frontend-tools) - Build more debugging tools diff --git a/apps/docs/next.config.mjs b/apps/docs/next.config.mjs index b001bcb..263a486 100644 --- a/apps/docs/next.config.mjs +++ b/apps/docs/next.config.mjs @@ -31,7 +31,37 @@ const config = { }, { source: "/docs/smart-ai-context", - destination: "/docs/advanced", + destination: "/docs/skills", + permanent: true, + }, + { + source: "/docs/ai-context", + destination: "/docs/skills", + permanent: true, + }, + { + source: "/docs/custom-tools", + destination: "/docs/tools/frontend-tools", + permanent: true, + }, + { + source: "/docs/streaming", + destination: "/docs/llm-sdk/stream-text", + permanent: true, + }, + { + source: "/docs/ai-response-control", + destination: "/docs/tools/agentic-loop", + permanent: true, + }, + { + source: "/docs/tool-approval", + destination: "/docs/tools/frontend-tools", + permanent: true, + }, + { + source: "/docs/tools/screenshot", + destination: "/docs/tools/built-in/screenshot", permanent: true, }, // ── context/ → advanced/ ───────────────────────────────────────────── diff --git a/apps/docs/public/design-system/assets/fonts/Geist-VariableFont_wght.ttf b/apps/docs/public/design-system/assets/fonts/Geist-VariableFont_wght.ttf new file mode 100644 index 0000000..40532a1 Binary files /dev/null and b/apps/docs/public/design-system/assets/fonts/Geist-VariableFont_wght.ttf differ diff --git a/apps/docs/public/design-system/assets/fonts/GeistMono-VariableFont_wght.ttf b/apps/docs/public/design-system/assets/fonts/GeistMono-VariableFont_wght.ttf new file mode 100644 index 0000000..f478387 Binary files /dev/null and b/apps/docs/public/design-system/assets/fonts/GeistMono-VariableFont_wght.ttf differ diff --git a/apps/docs/public/design-system/assets/fonts/OFL.txt b/apps/docs/public/design-system/assets/fonts/OFL.txt new file mode 100644 index 0000000..b48941f --- /dev/null +++ b/apps/docs/public/design-system/assets/fonts/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2024 The Geist Project Authors (https://github.com/vercel/geist-font.git) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/docs/public/design-system/assets/fonts/README.txt b/apps/docs/public/design-system/assets/fonts/README.txt new file mode 100644 index 0000000..78e0564 --- /dev/null +++ b/apps/docs/public/design-system/assets/fonts/README.txt @@ -0,0 +1,71 @@ +Geist Variable Font +=================== + +This download contains Geist as both a variable font and static fonts. + +Geist is a variable font with this axis: + wght + +This means all the styles are contained in a single file: + Geist-VariableFont_wght.ttf + +If your app fully supports variable fonts, you can now pick intermediate styles +that aren’t available as static fonts. Not all apps support variable fonts, and +in those cases you can use the static font files for Geist: + static/Geist-Thin.ttf + static/Geist-ExtraLight.ttf + static/Geist-Light.ttf + static/Geist-Regular.ttf + static/Geist-Medium.ttf + static/Geist-SemiBold.ttf + static/Geist-Bold.ttf + static/Geist-ExtraBold.ttf + static/Geist-Black.ttf + +Get started +----------- + +1. Install the font files you want to use + +2. Use your app's font picker to view the font family and all the +available styles + +Learn more about variable fonts +------------------------------- + + https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts + https://variablefonts.typenetwork.com + https://medium.com/variable-fonts + +In desktop apps + + https://theblog.adobe.com/can-variable-fonts-illustrator-cc + https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts + +Online + + https://developers.google.com/fonts/docs/getting_started + https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide + https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts + +Installing fonts + + MacOS: https://support.apple.com/en-us/HT201749 + Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux + Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows + +Android Apps + + https://developers.google.com/fonts/docs/android + https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts + +License +------- +Please read the full license text (OFL.txt) to understand the permissions, +restrictions and requirements for usage, redistribution, and modification. + +You can use them in your products & projects – print or digital, +commercial or otherwise. + +This isn't legal advice, please consider consulting a lawyer and see the full +license for all details. diff --git a/apps/docs/public/design-system/assets/fonts/static/Geist-Black.ttf b/apps/docs/public/design-system/assets/fonts/static/Geist-Black.ttf new file mode 100644 index 0000000..5552d16 Binary files /dev/null and b/apps/docs/public/design-system/assets/fonts/static/Geist-Black.ttf differ diff --git a/apps/docs/public/design-system/assets/fonts/static/Geist-Bold.ttf b/apps/docs/public/design-system/assets/fonts/static/Geist-Bold.ttf new file mode 100644 index 0000000..71dc002 Binary files /dev/null and b/apps/docs/public/design-system/assets/fonts/static/Geist-Bold.ttf differ diff --git a/apps/docs/public/design-system/assets/fonts/static/Geist-ExtraBold.ttf b/apps/docs/public/design-system/assets/fonts/static/Geist-ExtraBold.ttf new file mode 100644 index 0000000..5327eb0 Binary files /dev/null and b/apps/docs/public/design-system/assets/fonts/static/Geist-ExtraBold.ttf differ diff --git a/apps/docs/public/design-system/assets/fonts/static/Geist-ExtraLight.ttf b/apps/docs/public/design-system/assets/fonts/static/Geist-ExtraLight.ttf new file mode 100644 index 0000000..943cb76 Binary files /dev/null and b/apps/docs/public/design-system/assets/fonts/static/Geist-ExtraLight.ttf differ diff --git a/apps/docs/public/design-system/assets/fonts/static/Geist-Light.ttf b/apps/docs/public/design-system/assets/fonts/static/Geist-Light.ttf new file mode 100644 index 0000000..cd3835d Binary files /dev/null and b/apps/docs/public/design-system/assets/fonts/static/Geist-Light.ttf differ diff --git a/apps/docs/public/design-system/assets/fonts/static/Geist-Medium.ttf b/apps/docs/public/design-system/assets/fonts/static/Geist-Medium.ttf new file mode 100644 index 0000000..97712e5 Binary files /dev/null and b/apps/docs/public/design-system/assets/fonts/static/Geist-Medium.ttf differ diff --git a/apps/docs/public/design-system/assets/fonts/static/Geist-Regular.ttf b/apps/docs/public/design-system/assets/fonts/static/Geist-Regular.ttf new file mode 100644 index 0000000..88c6d70 Binary files /dev/null and b/apps/docs/public/design-system/assets/fonts/static/Geist-Regular.ttf differ diff --git a/apps/docs/public/design-system/assets/fonts/static/Geist-SemiBold.ttf b/apps/docs/public/design-system/assets/fonts/static/Geist-SemiBold.ttf new file mode 100644 index 0000000..42d34ff Binary files /dev/null and b/apps/docs/public/design-system/assets/fonts/static/Geist-SemiBold.ttf differ diff --git a/apps/docs/public/design-system/assets/fonts/static/Geist-Thin.ttf b/apps/docs/public/design-system/assets/fonts/static/Geist-Thin.ttf new file mode 100644 index 0000000..79ee487 Binary files /dev/null and b/apps/docs/public/design-system/assets/fonts/static/Geist-Thin.ttf differ diff --git a/apps/docs/public/design-system/assets/logo-icon.svg b/apps/docs/public/design-system/assets/logo-icon.svg new file mode 100644 index 0000000..d2bc462 --- /dev/null +++ b/apps/docs/public/design-system/assets/logo-icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/docs/public/design-system/assets/logo-width.png b/apps/docs/public/design-system/assets/logo-width.png new file mode 100644 index 0000000..a22bea9 Binary files /dev/null and b/apps/docs/public/design-system/assets/logo-width.png differ diff --git a/apps/docs/public/design-system/assets/logo-wordmark-white.svg b/apps/docs/public/design-system/assets/logo-wordmark-white.svg new file mode 100644 index 0000000..60c5484 --- /dev/null +++ b/apps/docs/public/design-system/assets/logo-wordmark-white.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/docs/public/design-system/assets/logo-wordmark.svg b/apps/docs/public/design-system/assets/logo-wordmark.svg new file mode 100644 index 0000000..203afc8 --- /dev/null +++ b/apps/docs/public/design-system/assets/logo-wordmark.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/docs/public/design-system/assets/logo.png b/apps/docs/public/design-system/assets/logo.png new file mode 100644 index 0000000..0dad15c Binary files /dev/null and b/apps/docs/public/design-system/assets/logo.png differ diff --git a/apps/docs/public/design-system/assets/og-image.png b/apps/docs/public/design-system/assets/og-image.png new file mode 100644 index 0000000..56c14b8 Binary files /dev/null and b/apps/docs/public/design-system/assets/og-image.png differ diff --git a/apps/docs/public/design-system/index.html b/apps/docs/public/design-system/index.html new file mode 100644 index 0000000..a8afb79 --- /dev/null +++ b/apps/docs/public/design-system/index.html @@ -0,0 +1,755 @@ + + + + + + Copilot SDK — Design System + + + + + + + + + +
+ +

Logo

+

The wordmark lockup used across all surfaces. Always use SVG for sharpness.

+ +
+ +
+ On White +
+ + + + + + + +
+
+ + +
+ On Dark +
+ + + + + + + +
+
+ + +
+ On Brand +
+ + + + + + + +
+
+ + +
+ Icon Mark + + + + +
+
+
+ + + +
+ +

Brand Colors

+

The purple-violet brand palette extracted from the logo and docs primary.

+ +
+
+
+
Brand Dark
+
#4A3BCC
+
+
+
+
Brand
+
#6352FF
+
+
+
+
Brand Light
+
#8B7EFF
+
+
+
+
Brand Muted
+
#B8AFFF
+
+
+
+
Brand Pale
+
#D9D5FF
+
+
+
+
Brand Subtle
+
#EEF0FF
+
+
+
+ + + +
+ +

Light Mode Surfaces

+

Semantic surface tokens used by the SDK components via CSS custom properties.

+ +
+
+
+
+
Background
+
--background
+
hsl(0 0% 100%)
+
+
+
+
+
+
Card
+
--card
+
hsl(0 0% 100%)
+
+
+
+
+
+
Secondary
+
--secondary
+
hsl(240 4.8% 95.9%)
+
+
+
+
+
+
Muted
+
--muted
+
hsl(240 4.8% 95.9%)
+
+
+
+
+
+
Border / Input
+
--border
+
hsl(240 5.9% 90%)
+
+
+
+
+
+
Primary
+
--primary
+
hsl(240 5.9% 10%)
+
+
+
+
+ + + +
+ +

Text Colors

+

Foreground tokens for all text rendering scenarios, light and dark.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TokenLight ValueDark ValueUsage
--foregroundhsl(240 10% 3.9%)hsl(0 0% 98%)Primary body text
--muted-foregroundhsl(240 3.8% 46.1%)hsl(240 5% 64.9%)Secondary / helper text
--primary-foregroundhsl(0 0% 98%)hsl(240 5.9% 10%)Text on primary surface
--secondary-foregroundhsl(240 5.9% 10%)hsl(0 0% 98%)Text on secondary surface
--csdk-link-color#2563eb#60a5faInline hyperlinks
--destructivehsl(0 84.2% 60.2%)hsl(0 62.8% 30.6%)Error / danger states
+
+ + +
+

Preview

+

Foreground — hsl(240 10% 3.9%)

+

Muted foreground — secondary labels and captions

+

Link color — inline anchor example

+

Destructive — error message text

+
+
+ + + +
+ +

Dark Mode Surfaces

+

All surface and text tokens in dark mode. Enable via .dark class on a parent.

+ +
+
+
+
Background
+
hsl(240 10% 3.9%)
+
+
+
+
Card
+
hsl(240 10% 3.9%)
+
+
+
+
Secondary / Muted
+
hsl(240 3.7% 15.9%)
+
+
+
+
Border / Input
+
hsl(240 3.7% 15.9%)
+
+
+
+
Primary
+
hsl(0 0% 98%)
+
+
+
+
Muted fg
+
hsl(240 5% 64.9%)
+
+
+
+ + + +
+ +

Typography

+

Geist Sans for UI and body text, Geist Mono for code and tokens.

+ +
+
+
+
Display
+
32px / 700 / −0.03em
+
+
Build AI Copilots
+
+
+
+
Heading 1
+
24px / 700 / −0.02em
+
+
Getting Started with Copilot SDK
+
+
+
+
Heading 2
+
20px / 600 / −0.01em
+
+
Installation & Configuration
+
+
+
+
Body
+
14px / 400 / 0em
+
+
Production-ready AI Copilots for any product. Connect any LLM, deploy on your infrastructure, own your data. Built for speed and control.
+
+
+
+
Label
+
11px / 600 / 0.08em / uppercase
+
+
Section Label · Category
+
+
+
+
Mono
+
12px / 400 / Geist Mono
+
+
npm install @yourgpt/copilot-sdk
+
+
+
+ + + +
+ +

Border Radius

+

Base radius is 0.5rem (8px). Stepped scale for different component sizes.

+ +
+
+
+
None
+
0
+
+
+
+
SM
+
0.25rem / 4px
+
+
+
+
Default
+
0.5rem / 8px
--radius
+
+
+
+
LG
+
0.75rem / 12px
+
+
+
+
XL
+
1rem / 16px
+
+
+
+
Full
+
9999px
+
+
+
+ + + +
+ +

Full Token Reference

+

Complete list of CSS custom properties defined by the SDK base layer.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TokenLightDark
--backgroundhsl(0 0% 100%)hsl(240 10% 3.9%)
--foregroundhsl(240 10% 3.9%)hsl(0 0% 98%)
--cardhsl(0 0% 100%)hsl(240 10% 3.9%)
--card-foregroundhsl(240 10% 3.9%)hsl(0 0% 98%)
--popoverhsl(0 0% 100%)hsl(240 10% 3.9%)
--primaryhsl(240 5.9% 10%)hsl(0 0% 98%)
--primary-foregroundhsl(0 0% 98%)hsl(240 5.9% 10%)
--secondaryhsl(240 4.8% 95.9%)hsl(240 3.7% 15.9%)
--secondary-foregroundhsl(240 5.9% 10%)hsl(0 0% 98%)
--mutedhsl(240 4.8% 95.9%)hsl(240 3.7% 15.9%)
--muted-foregroundhsl(240 3.8% 46.1%)hsl(240 5% 64.9%)
--accenthsl(240 4.8% 95.9%)hsl(240 3.7% 15.9%)
--destructivehsl(0 84.2% 60.2%)hsl(0 62.8% 30.6%)
--borderhsl(240 5.9% 90%)hsl(240 3.7% 15.9%)
--inputhsl(240 5.9% 90%)hsl(240 3.7% 15.9%)
--ringhsl(240 5.9% 10%)hsl(240 4.9% 83.9%)
--csdk-link-color#2563eb#60a5fa
--radius0.5rem (8px)
+
+
+ + + + + diff --git a/apps/docs/public/images/gen-ui-demo.png b/apps/docs/public/images/gen-ui-demo.png new file mode 100644 index 0000000..9527b94 Binary files /dev/null and b/apps/docs/public/images/gen-ui-demo.png differ diff --git a/apps/docs/public/images/skills-demo.png b/apps/docs/public/images/skills-demo.png new file mode 100644 index 0000000..3dea899 Binary files /dev/null and b/apps/docs/public/images/skills-demo.png differ diff --git a/examples/skills-demo/src/App.tsx b/examples/skills-demo/src/App.tsx index 6df4f3b..37bf2d9 100644 --- a/examples/skills-demo/src/App.tsx +++ b/examples/skills-demo/src/App.tsx @@ -372,7 +372,7 @@ const INITIAL_MESSAGES = [ id: "welcome-1", role: "assistant" as const, content: - "Hey! I'm your **HR Copilot** — your AI assistant for people operations.\n\nI can help you with:\n- **Employee Onboarding** — checklists, Day 1 plans, 30/60/90 milestones\n- **Performance Reviews** — review cycles, calibration, feedback frameworks\n\nJust ask me anything to get started.", + "Hey! I'm your **HR Copilot** — your AI assistant for people operations.\n\nJust ask me anything to get started.", createdAt: new Date(), }, ]; diff --git a/packages/copilot-sdk/package.json b/packages/copilot-sdk/package.json index ae0c793..6659712 100644 --- a/packages/copilot-sdk/package.json +++ b/packages/copilot-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@yourgpt/copilot-sdk", - "version": "2.5.0", + "version": "2.5.1-beta.1", "description": "Copilot SDK for building Production-ready AI Copilots for any product. Connect any LLM, deploy on your infrastructure, own your data.", "type": "module", "types": "./dist/core/index.d.ts", diff --git a/packages/copilot-sdk/src/react/provider/CopilotProvider.tsx b/packages/copilot-sdk/src/react/provider/CopilotProvider.tsx index 2bc0dd3..30c737c 100644 --- a/packages/copilot-sdk/src/react/provider/CopilotProvider.tsx +++ b/packages/copilot-sdk/src/react/provider/CopilotProvider.tsx @@ -409,6 +409,8 @@ export interface CopilotContextValue { status: "ready" | "submitted" | "streaming" | "error"; error: Error | null; isLoading: boolean; + /** True from when stop() is called until the next sendMessage(). */ + wasStopped: boolean; // Chat actions sendMessage: ( @@ -950,12 +952,16 @@ export function CopilotProvider(props: CopilotProviderProps) { async (content: string, attachments?: MessageAttachment[]) => { debugLog("Sending message:", content); setAgentIteration(0); // reset before each new user message + setWasStopped(false); // reset for new run await chatRef.current?.sendMessage(content, attachments); }, [debugLog], ); + const [wasStopped, setWasStopped] = useState(false); + const stop = useCallback(() => { + setWasStopped(true); chatRef.current?.stop(); }, []); @@ -1055,6 +1061,7 @@ export function CopilotProvider(props: CopilotProviderProps) { status, error, isLoading, + wasStopped, // Chat actions sendMessage, @@ -1114,6 +1121,7 @@ export function CopilotProvider(props: CopilotProviderProps) { status, error, isLoading, + wasStopped, sendMessage, stop, clearMessages, diff --git a/packages/copilot-sdk/src/ui/components/composed/chat/chat.tsx b/packages/copilot-sdk/src/ui/components/composed/chat/chat.tsx index 33832c3..5f8fd20 100644 --- a/packages/copilot-sdk/src/ui/components/composed/chat/chat.tsx +++ b/packages/copilot-sdk/src/ui/components/composed/chat/chat.tsx @@ -545,6 +545,8 @@ function ChatComponent({ followUpButtonClassName, // Citations/Sources citations, + // Message Actions + allowToCopyMessage = false, // Custom rendering messageView, renderMessage, @@ -953,6 +955,13 @@ function ChatComponent({ {/* Root-level custom Header (shows in both views) */} {rootHeader} + {/* Built-in copy action — auto-registered when allowToCopyMessage is true */} + {allowToCopyMessage && ( + + + + )} + {/* Behavior children — always mounted (MessageActions registrars, hook components) */} {behaviorChildren.length > 0 && behaviorChildren} diff --git a/packages/copilot-sdk/src/ui/components/composed/chat/default-message.tsx b/packages/copilot-sdk/src/ui/components/composed/chat/default-message.tsx index eacc9ee..221430f 100644 --- a/packages/copilot-sdk/src/ui/components/composed/chat/default-message.tsx +++ b/packages/copilot-sdk/src/ui/components/composed/chat/default-message.tsx @@ -35,11 +35,16 @@ function FloatingActions({ role, align = "left", onEdit, + className, + copyContent, }: { message: ChatMessage; role: "user" | "assistant"; align?: "left" | "right"; onEdit?: () => void; + className?: string; + /** Text to copy. When provided, copy button uses this instead of message.content. When explicitly null, copy button is hidden. */ + copyContent?: string | null; }) { const ctx = useMessageActionsContext(); const [copiedId, setCopiedId] = React.useState(null); @@ -51,9 +56,10 @@ function FloatingActions({ return (
{actions.map((action) => { @@ -61,6 +67,10 @@ function FloatingActions({ typeof action.hidden === "function" ? action.hidden({ message }) : action.hidden; + // Hide copy button when there is no displayable text content + if (action.id === "copy" && copyContent != null && !copyContent.trim()) + return null; + if (action.id === "copy" && copyContent === null) return null; if (isHidden) return null; const isCopied = copiedId === action.id; @@ -72,7 +82,9 @@ function FloatingActions({ title={action.tooltip} aria-label={action.tooltip} className={cn( - "flex items-center justify-center size-6 rounded-md", + "csdk-message-action-btn", + action.id === "copy" && "csdk-copy-btn", + "flex items-center justify-center size-6 rounded-md cursor-pointer", "text-muted-foreground hover:text-foreground hover:bg-muted", "transition-colors", action.className, @@ -83,7 +95,11 @@ function FloatingActions({ return; } if (action.id === "copy") { - navigator.clipboard.writeText(message.content ?? ""); + const text = + copyContent !== undefined + ? (copyContent ?? "") + : (message.content ?? ""); + navigator.clipboard.writeText(text); setCopiedId("copy"); setTimeout(() => setCopiedId(null), 1500); return; @@ -663,19 +679,29 @@ export function DefaultMessage({
) : ( - <> +
{/* Message Content - show FIRST (AI's words before tool calls) */} {cleanContent?.trim() && ( - - {cleanContent} - +
+ + {cleanContent} + + {/* Copy button — positioned inside the content bubble */} + +
)} {/* Custom Tool Renderers - Priority: tool.render > fallbackToolRenderer > toolRenderers */} @@ -929,10 +955,7 @@ export function DefaultMessage({ buttonClassName={followUpButtonClassName} /> )} - - {/* Floating actions for assistant messages */} - - +
)} diff --git a/packages/copilot-sdk/src/ui/components/composed/chat/types.ts b/packages/copilot-sdk/src/ui/components/composed/chat/types.ts index ba4849a..4cc5f66 100644 --- a/packages/copilot-sdk/src/ui/components/composed/chat/types.ts +++ b/packages/copilot-sdk/src/ui/components/composed/chat/types.ts @@ -548,6 +548,13 @@ export type ChatProps = { footer?: string; }; + // === Message Actions === + /** + * Show a copy-to-clipboard button below assistant messages on hover. + * @default false + */ + allowToCopyMessage?: boolean; + // === Citations/Sources (Web Search) === /** * Configuration for displaying citations from web search results.