@assistant-ui/mcp-docs-server 0.1.36 → 0.1.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.docs/organized/code-examples/waterfall.md +8 -9
- package/.docs/organized/code-examples/with-a2a.md +16 -11
- package/.docs/organized/code-examples/with-ag-ui.md +16 -11
- package/.docs/organized/code-examples/{with-ai-sdk-v6.md → with-ai-sdk-v7.md} +32 -21
- package/.docs/organized/code-examples/with-artifacts.md +17 -10
- package/.docs/organized/code-examples/with-assistant-transport.md +15 -8
- package/.docs/organized/code-examples/with-browser-extension.md +15 -8
- package/.docs/organized/code-examples/with-chain-of-thought.md +17 -10
- package/.docs/organized/code-examples/with-cloud-standalone.md +10 -9
- package/.docs/organized/code-examples/with-cloud.md +18 -13
- package/.docs/organized/code-examples/with-custom-thread-list.md +17 -10
- package/.docs/organized/code-examples/with-elevenlabs-conversational.md +20 -13
- package/.docs/organized/code-examples/with-elevenlabs-scribe.md +20 -13
- package/.docs/organized/code-examples/with-eve.md +16 -9
- package/.docs/organized/code-examples/with-expo.md +26 -23
- package/.docs/organized/code-examples/with-external-store.md +16 -11
- package/.docs/organized/code-examples/with-ffmpeg.md +18 -13
- package/.docs/organized/code-examples/with-generative-ui.md +20 -15
- package/.docs/organized/code-examples/with-google-adk.md +16 -9
- package/.docs/organized/code-examples/with-heat-graph.md +8 -9
- package/.docs/organized/code-examples/with-image-generation.md +17 -10
- package/.docs/organized/code-examples/with-interactables.md +19 -15
- package/.docs/organized/code-examples/with-langchain.md +17 -10
- package/.docs/organized/code-examples/with-langgraph.md +17 -10
- package/.docs/organized/code-examples/with-livekit.md +21 -14
- package/.docs/organized/code-examples/with-mcp.md +40 -18
- package/.docs/organized/code-examples/with-opencode.md +22 -17
- package/.docs/organized/code-examples/with-pi.md +47 -12
- package/.docs/organized/code-examples/with-react-hook-form.md +19 -14
- package/.docs/organized/code-examples/with-react-ink-web.md +6 -6
- package/.docs/organized/code-examples/with-react-ink.md +2 -2
- package/.docs/organized/code-examples/with-react-router.md +20 -15
- package/.docs/organized/code-examples/with-resumable-stream.md +19 -12
- package/.docs/organized/code-examples/with-store.md +8 -9
- package/.docs/organized/code-examples/with-tanstack.md +17 -11
- package/.docs/organized/code-examples/with-tap-runtime.md +16 -11
- package/.docs/organized/code-examples/with-virtualized-thread.md +17 -12
- package/.docs/raw/docs/(docs)/base-ui.mdx +39 -0
- package/.docs/raw/docs/(docs)/cli.mdx +18 -2
- package/.docs/raw/docs/(docs)/installation.mdx +15 -1
- package/.docs/raw/docs/(docs)/rtl.mdx +2 -4
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/actions.mdx +56 -0
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/components.mdx +86 -0
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/index.mdx +19 -1
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/json-generative-ui.mdx +42 -0
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/rendering.mdx +53 -2
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/slack.mdx +81 -0
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/teams.mdx +86 -0
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/tokens.mdx +62 -0
- package/.docs/raw/docs/(reference)/api-reference/integrations/index.mdx +4 -1
- package/.docs/raw/docs/(reference)/api-reference/integrations/react-ai-sdk.mdx +4 -2
- package/.docs/raw/docs/(reference)/api-reference/integrations/react-data-stream.mdx +37 -0
- package/.docs/raw/docs/(reference)/api-reference/overview.mdx +1 -0
- package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-if.mdx +29 -29
- package/.docs/raw/docs/(reference)/api-reference/primitives/composition.mdx +1 -0
- package/.docs/raw/docs/(reference)/api-reference/primitives/index.mdx +3 -0
- package/.docs/raw/docs/(reference)/api-reference/primitives/selection-toolbar.mdx +2 -0
- package/.docs/raw/docs/(reference)/api-reference/tools/status.mdx +0 -2
- package/.docs/raw/docs/(reference)/api-reference/tools/toolkits.mdx +12 -9
- package/.docs/raw/docs/(reference)/api-reference/utilities/miscellaneous.mdx +4 -0
- package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +7 -1
- package/.docs/raw/docs/cloud/langgraph.mdx +4 -2
- package/.docs/raw/docs/guides/chatgpt-subscription.mdx +108 -0
- package/.docs/raw/docs/guides/dictation.mdx +185 -257
- package/.docs/raw/docs/guides/index.mdx +10 -0
- package/.docs/raw/docs/guides/mentions.mdx +31 -3
- package/.docs/raw/docs/guides/resumable-streams.mdx +12 -1
- package/.docs/raw/docs/guides/speech.mdx +47 -29
- package/.docs/raw/docs/guides/suggestions.mdx +70 -1
- package/.docs/raw/docs/guides/voice.mdx +197 -267
- package/.docs/raw/docs/ink/primitives.mdx +35 -1
- package/.docs/raw/docs/integrations/frameworks/ai-sdk.mdx +13 -7
- package/.docs/raw/docs/integrations/frameworks/cloudflare-agents/overview.mdx +3 -3
- package/.docs/raw/docs/integrations/frameworks/mastra/full-stack.mdx +1 -1
- package/.docs/raw/docs/integrations/frameworks/mastra/overview.mdx +3 -3
- package/.docs/raw/docs/integrations/frameworks/mastra/separate-server.mdx +1 -1
- package/.docs/raw/docs/integrations/gateways/index.mdx +2 -2
- package/.docs/raw/docs/integrations/index.mdx +1 -1
- package/.docs/raw/docs/integrations/observability/helicone.mdx +1 -1
- package/.docs/raw/docs/integrations/observability/langfuse.mdx +1 -1
- package/.docs/raw/docs/integrations/observability/langsmith.mdx +3 -3
- package/.docs/raw/docs/migrations/index.mdx +50 -0
- package/.docs/raw/docs/migrations/react-langgraph-v0-7.mdx +2 -2
- package/.docs/raw/docs/migrations/toolkit-tools.mdx +4 -2
- package/.docs/raw/docs/primitives/chain-of-thought.mdx +6 -1
- package/.docs/raw/docs/primitives/composer.mdx +16 -0
- package/.docs/raw/docs/primitives/selection-toolbar.mdx +25 -0
- package/.docs/raw/docs/primitives/thread-list.mdx +30 -6
- package/.docs/raw/docs/react-native/primitives.mdx +23 -0
- package/.docs/raw/docs/runtimes/a2a/quickstart.mdx +1 -1
- package/.docs/raw/docs/runtimes/ag-ui/agent-state.mdx +124 -0
- package/.docs/raw/docs/runtimes/ag-ui/quickstart.mdx +1 -1
- package/.docs/raw/docs/runtimes/ag-ui/runtime-options.mdx +13 -2
- package/.docs/raw/docs/runtimes/ai-sdk/overview.mdx +13 -4
- package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +11 -11
- package/.docs/raw/docs/runtimes/ai-sdk/v5-legacy.mdx +5 -5
- package/.docs/raw/docs/runtimes/ai-sdk/{v6.mdx → v6-legacy.mdx} +8 -6
- package/.docs/raw/docs/runtimes/ai-sdk/v7.mdx +717 -0
- package/.docs/raw/docs/runtimes/concepts/adapters.mdx +1 -1
- package/.docs/raw/docs/runtimes/concepts/architecture.mdx +1 -1
- package/.docs/raw/docs/runtimes/custom/data-stream.mdx +10 -19
- package/.docs/raw/docs/runtimes/custom/external-store.mdx +1 -1
- package/.docs/raw/docs/runtimes/custom/local-runtime.mdx +2 -0
- package/.docs/raw/docs/runtimes/eve/overview.mdx +1 -1
- package/.docs/raw/docs/runtimes/google-adk/quickstart.mdx +1 -1
- package/.docs/raw/docs/runtimes/langchain.mdx +2 -2
- package/.docs/raw/docs/runtimes/langgraph/agent-state.mdx +181 -0
- package/.docs/raw/docs/runtimes/opencode/hooks.mdx +1 -1
- package/.docs/raw/docs/tools/backend.mdx +6 -3
- package/.docs/raw/docs/tools/defining-tools.mdx +12 -1
- package/.docs/raw/docs/tools/generative-ui.mdx +95 -0
- package/.docs/raw/docs/tools/mcp-apps.mdx +37 -10
- package/.docs/raw/docs/tools/mcp.mdx +105 -3
- package/.docs/raw/docs/tools/tool-ui.mdx +6 -4
- package/.docs/raw/docs/tools/user-managed-mcp.mdx +41 -4
- package/.docs/raw/docs/ui/accordion.mdx +16 -10
- package/.docs/raw/docs/ui/assistant-modal.mdx +8 -4
- package/.docs/raw/docs/ui/attachment.mdx +5 -1
- package/.docs/raw/docs/ui/badge.mdx +23 -12
- package/.docs/raw/docs/ui/follow-up-suggestions.mdx +80 -0
- package/.docs/raw/docs/ui/model-selector.mdx +69 -6
- package/.docs/raw/docs/ui/select.mdx +22 -14
- package/.docs/raw/docs/ui/sources.mdx +1 -1
- package/.docs/raw/docs/ui/tabs.mdx +25 -14
- package/.docs/raw/docs/utilities/heat-graph.mdx +2 -2
- package/README.md +1 -1
- package/dist/constants.d.ts +2 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +2 -1
- package/dist/constants.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -1
- package/dist/prepare-docs/code-examples.d.ts.map +1 -1
- package/dist/prepare-docs/copy-raw.d.ts.map +1 -1
- package/dist/prepare-docs/copy-raw.js +0 -4
- package/dist/prepare-docs/copy-raw.js.map +1 -1
- package/dist/prompts/xulux-playground.d.ts +12 -0
- package/dist/prompts/xulux-playground.d.ts.map +1 -0
- package/dist/prompts/xulux-playground.js +33 -0
- package/dist/prompts/xulux-playground.js.map +1 -0
- package/dist/tools/docs.d.ts +2 -4
- package/dist/tools/docs.d.ts.map +1 -1
- package/dist/tools/docs.js +38 -10
- package/dist/tools/docs.js.map +1 -1
- package/dist/tools/examples.d.ts +5 -5
- package/dist/tools/examples.d.ts.map +1 -1
- package/dist/tools/examples.js +10 -7
- package/dist/tools/examples.js.map +1 -1
- package/dist/tools/resources.d.ts +6 -0
- package/dist/tools/resources.d.ts.map +1 -0
- package/dist/tools/resources.js +74 -0
- package/dist/tools/resources.js.map +1 -0
- package/dist/tools/search.d.ts +30 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +39 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/tests/test-setup.d.ts.map +1 -1
- package/dist/tools/tests/test-setup.js +7 -1
- package/dist/tools/tests/test-setup.js.map +1 -1
- package/dist/tools/xulux-templates.d.ts +72 -0
- package/dist/tools/xulux-templates.d.ts.map +1 -0
- package/dist/tools/xulux-templates.js +82 -0
- package/dist/tools/xulux-templates.js.map +1 -0
- package/dist/utils/cache.d.ts +5 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +18 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/mcp-format.d.ts +1 -0
- package/dist/utils/mcp-format.d.ts.map +1 -1
- package/dist/utils/mcp-format.js +7 -4
- package/dist/utils/mcp-format.js.map +1 -1
- package/dist/utils/mdx.d.ts +2 -1
- package/dist/utils/mdx.d.ts.map +1 -1
- package/dist/utils/mdx.js +19 -2
- package/dist/utils/mdx.js.map +1 -1
- package/dist/utils/paths.d.ts +2 -1
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +20 -1
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/search.d.ts +10 -0
- package/dist/utils/search.d.ts.map +1 -0
- package/dist/utils/search.js +97 -0
- package/dist/utils/search.js.map +1 -0
- package/dist/utils/security.d.ts.map +1 -1
- package/dist/xulux/catalog-client.d.ts +14 -0
- package/dist/xulux/catalog-client.d.ts.map +1 -0
- package/dist/xulux/catalog-client.js +67 -0
- package/dist/xulux/catalog-client.js.map +1 -0
- package/dist/xulux/fallback-catalog.d.ts +7 -0
- package/dist/xulux/fallback-catalog.d.ts.map +1 -0
- package/dist/xulux/fallback-catalog.js +47 -0
- package/dist/xulux/fallback-catalog.js.map +1 -0
- package/dist/xulux/fetch-sandbox.d.ts +5 -0
- package/dist/xulux/fetch-sandbox.d.ts.map +1 -0
- package/dist/xulux/fetch-sandbox.js +40 -0
- package/dist/xulux/fetch-sandbox.js.map +1 -0
- package/dist/xulux/template-service.d.ts +84 -0
- package/dist/xulux/template-service.d.ts.map +1 -0
- package/dist/xulux/template-service.js +223 -0
- package/dist/xulux/template-service.js.map +1 -0
- package/dist/xulux/types.d.ts +55 -0
- package/dist/xulux/types.d.ts.map +1 -0
- package/dist/xulux/types.js +6 -0
- package/dist/xulux/types.js.map +1 -0
- package/package.json +5 -5
- package/src/constants.ts +2 -0
- package/src/index.ts +67 -0
- package/src/prepare-docs/copy-raw.ts +0 -5
- package/src/prompts/xulux-playground.ts +36 -0
- package/src/tools/docs.ts +52 -4
- package/src/tools/examples.ts +18 -11
- package/src/tools/resources.ts +114 -0
- package/src/tools/search.ts +46 -0
- package/src/tools/tests/completions.test.ts +46 -0
- package/src/tools/tests/directory-size-cap.test.ts +50 -0
- package/src/tools/tests/docs.test.ts +20 -0
- package/src/tools/tests/examples.test.ts +5 -5
- package/src/tools/tests/listings-cache.test.ts +19 -0
- package/src/tools/tests/mcp-protocol.test.ts +92 -1
- package/src/tools/tests/resources.test.ts +102 -0
- package/src/tools/tests/search.test.ts +37 -0
- package/src/tools/tests/test-setup.ts +10 -0
- package/src/tools/tests/xulux-templates.test.ts +262 -0
- package/src/tools/xulux-templates.ts +141 -0
- package/src/utils/cache.ts +20 -0
- package/src/utils/mcp-format.ts +8 -6
- package/src/utils/mdx.ts +21 -1
- package/src/utils/paths.ts +25 -0
- package/src/utils/search.ts +131 -0
- package/src/utils/tests/cache.test.ts +51 -0
- package/src/utils/tests/mcp-format.test.ts +22 -0
- package/src/utils/tests/security.test.ts +1 -1
- package/src/xulux/catalog-client.ts +105 -0
- package/src/xulux/fallback-catalog.ts +63 -0
- package/src/xulux/fetch-sandbox.ts +56 -0
- package/src/xulux/template-service.ts +406 -0
- package/src/xulux/types.ts +60 -0
- package/.docs/raw/blog/2024-07-29-hello/index.mdx +0 -64
- package/.docs/raw/blog/2024-09-11/index.mdx +0 -10
- package/.docs/raw/blog/2024-12-15/index.mdx +0 -10
- package/.docs/raw/blog/2025-01-31-changelog/index.mdx +0 -127
- package/.docs/raw/blog/2026-03-launch-week/index.mdx +0 -258
- package/.docs/raw/docs/(reference)/api-reference/hooks/utilities.mdx +0 -464
|
@@ -81,7 +81,8 @@ const mcpClient = await createMCPClient({
|
|
|
81
81
|
|
|
82
82
|
In a generative toolkit, spread `defineMcpToolkit({ ... })` with one entry per
|
|
83
83
|
MCP server. The entry key names the server connection; the MCP server publishes
|
|
84
|
-
the actual tool names.
|
|
84
|
+
the actual tool names. Use a readable key because it appears in connection,
|
|
85
|
+
tool-listing, and close errors for debugging.
|
|
85
86
|
|
|
86
87
|
```tsx title="app/toolkit.tsx"
|
|
87
88
|
"use generative";
|
|
@@ -93,14 +94,75 @@ export default defineToolkit({
|
|
|
93
94
|
github: {
|
|
94
95
|
type: "http",
|
|
95
96
|
url: "https://mcp.example.com/mcp",
|
|
97
|
+
connectionTimeout: 10_000,
|
|
96
98
|
},
|
|
97
99
|
}),
|
|
98
100
|
});
|
|
99
101
|
```
|
|
100
102
|
|
|
103
|
+
Use `{ server, disabled }` when a whole MCP server should stay configured but
|
|
104
|
+
not expose tools for the current request, such as missing credentials, feature
|
|
105
|
+
flags, or plan gating:
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
defineMcpToolkit({
|
|
109
|
+
docs: {
|
|
110
|
+
server: {
|
|
111
|
+
type: "http",
|
|
112
|
+
url: process.env.DOCS_MCP_URL!,
|
|
113
|
+
},
|
|
114
|
+
disabled: !process.env.DOCS_MCP_URL,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Use `tools` when the server should stay enabled but specific MCP tools should
|
|
120
|
+
be hidden from the model:
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
defineMcpToolkit({
|
|
124
|
+
docs: {
|
|
125
|
+
server: {
|
|
126
|
+
type: "http",
|
|
127
|
+
url: process.env.DOCS_MCP_URL!,
|
|
128
|
+
},
|
|
129
|
+
tools: {
|
|
130
|
+
deleteDocument: {
|
|
131
|
+
disabled: !userCanDelete,
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
If multiple MCP servers expose the same tool name, wrap the entry with
|
|
139
|
+
`{ server, prefix }` to give each server's tools distinct model-visible names:
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
export default defineToolkit({
|
|
143
|
+
...defineMcpToolkit({
|
|
144
|
+
docs: {
|
|
145
|
+
server: { type: "http", url: "https://docs.example.com/mcp" },
|
|
146
|
+
prefix: "docs_",
|
|
147
|
+
},
|
|
148
|
+
github: {
|
|
149
|
+
server: { type: "http", url: "https://github.example.com/mcp" },
|
|
150
|
+
prefix: "github_",
|
|
151
|
+
},
|
|
152
|
+
}),
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
If both servers publish `search`, the model receives `docs_search` and
|
|
157
|
+
`github_search` instead of an ambiguous duplicate.
|
|
158
|
+
|
|
101
159
|
Use `AISDKToolkit` in the route. It opens the MCP clients, merges their tools
|
|
102
160
|
with the rest of your toolkit, and closes them when you call `close()`:
|
|
103
161
|
|
|
162
|
+
`connectionTimeout` is optional and measured in milliseconds. Set it to fail
|
|
163
|
+
the server-side MCP readiness flow (`createMCPClient()` plus `tools()`) before
|
|
164
|
+
a bad URL or hanging local process can stall the route.
|
|
165
|
+
|
|
104
166
|
```ts title="app/api/chat/route.ts"
|
|
105
167
|
import { AISDKToolkit } from "@assistant-ui/react-ai-sdk";
|
|
106
168
|
import { openai } from "@ai-sdk/openai";
|
|
@@ -314,7 +376,7 @@ import type { ReactNode } from "react";
|
|
|
314
376
|
import { toolkit } from "./GitHubIssueToolUI";
|
|
315
377
|
|
|
316
378
|
export function MyRuntimeProvider({ children }: { children: ReactNode }) {
|
|
317
|
-
const runtime = useChatRuntime(
|
|
379
|
+
const runtime = useChatRuntime();
|
|
318
380
|
const aui = useAui({ tools: Tools({ toolkit }) });
|
|
319
381
|
|
|
320
382
|
return (
|
|
@@ -325,6 +387,46 @@ export function MyRuntimeProvider({ children }: { children: ReactNode }) {
|
|
|
325
387
|
}
|
|
326
388
|
```
|
|
327
389
|
|
|
390
|
+
`useChatRuntime()` targets `/api/chat` by default. To point at a different endpoint or customize requests, see [Custom transport](/docs/runtimes/ai-sdk/v7#custom-transport).
|
|
391
|
+
|
|
392
|
+
</Step>
|
|
393
|
+
<Step>
|
|
394
|
+
|
|
395
|
+
### Require approval before an MCP tool runs
|
|
396
|
+
|
|
397
|
+
MCP tools execute on the server, so approval is a server-side tool gate, not a `humanTool()` result. Gate the call with AI SDK v7's call-level `toolApproval` option, keyed by the tool's model-visible name. The tool name stays the same, so your custom renderer or the default `ToolFallback` receives `approval` and `respondToApproval` like any other backend tool:
|
|
398
|
+
|
|
399
|
+
```ts title="app/api/chat/route.ts"
|
|
400
|
+
const tools = await mcpClient.tools();
|
|
401
|
+
|
|
402
|
+
const result = streamText({
|
|
403
|
+
model: openai("gpt-5.4-mini"),
|
|
404
|
+
messages: await convertToModelMessages(messages),
|
|
405
|
+
tools,
|
|
406
|
+
toolApproval: {
|
|
407
|
+
github_delete_repository: "user-approval",
|
|
408
|
+
},
|
|
409
|
+
onFinish: async () => {
|
|
410
|
+
await mcpClient.close();
|
|
411
|
+
},
|
|
412
|
+
});
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
With `AISDKToolkit`, pass the same `toolApproval` option alongside the tools returned by `await aiToolkit.tools(...)`; key it by the prefixed name when the entry sets one.
|
|
416
|
+
|
|
417
|
+
On the client, let the AI SDK send the recorded approval decision back to the
|
|
418
|
+
route:
|
|
419
|
+
|
|
420
|
+
```tsx title="app/components/RuntimeProvider.tsx"
|
|
421
|
+
import { lastAssistantMessageIsCompleteWithApprovalResponses } from "ai";
|
|
422
|
+
|
|
423
|
+
const runtime = useChatRuntime({
|
|
424
|
+
sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithApprovalResponses,
|
|
425
|
+
});
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
Use this pattern for backend-owned actions such as deleting, writing, deploying, or calling privileged MCP tools. Use `humanTool()` only when the user supplies the tool result itself. For custom approval UIs, see [Server-side approval gates](/docs/tools/tool-ui#server-side-approval-gates); for the full wire setup, see [Server-side tool approval](/docs/runtimes/ai-sdk/v7#server-side-tool-approval).
|
|
429
|
+
|
|
328
430
|
</Step>
|
|
329
431
|
<Step>
|
|
330
432
|
|
|
@@ -352,7 +454,7 @@ Start the app and trigger a tool call (e.g., ask the assistant to do something t
|
|
|
352
454
|
<Card
|
|
353
455
|
title="AI SDK runtime"
|
|
354
456
|
description="The runtime that ferries MCP tool calls to the chat UI."
|
|
355
|
-
href="/docs/runtimes/ai-sdk/
|
|
457
|
+
href="/docs/runtimes/ai-sdk/v7"
|
|
356
458
|
/>
|
|
357
459
|
<Card
|
|
358
460
|
title="Tools and tool UI"
|
|
@@ -74,7 +74,7 @@ import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
|
|
|
74
74
|
import toolkit from "./toolkit";
|
|
75
75
|
|
|
76
76
|
function MyRuntimeProvider({ children }: { children: React.ReactNode }) {
|
|
77
|
-
const runtime = useChatRuntime(
|
|
77
|
+
const runtime = useChatRuntime();
|
|
78
78
|
const aui = useAui({ tools: Tools({ toolkit }) });
|
|
79
79
|
return (
|
|
80
80
|
<AssistantRuntimeProvider aui={aui} runtime={runtime}>
|
|
@@ -84,6 +84,8 @@ function MyRuntimeProvider({ children }: { children: React.ReactNode }) {
|
|
|
84
84
|
}
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
+
`useChatRuntime()` targets `/api/chat` by default. To point at a different endpoint or customize requests, see [Custom transport](/docs/runtimes/ai-sdk/v7#custom-transport).
|
|
88
|
+
|
|
87
89
|
<Callout type="tip">
|
|
88
90
|
Frontend toolkit entries can be passed to your backend using the
|
|
89
91
|
`frontendTools` utility.
|
|
@@ -537,7 +539,7 @@ export default defineToolkit({
|
|
|
537
539
|
|
|
538
540
|
### Server-side approval gates
|
|
539
541
|
|
|
540
|
-
Some runtimes (notably AI SDK
|
|
542
|
+
Some runtimes (notably AI SDK v7's `toolApproval`-gated tools) pause on the server and emit an approval request that the client must acknowledge before the tool runs. assistant-ui surfaces this on the tool part as `approval` and exposes `respondToApproval({ approved, reason? })` on the renderer:
|
|
541
543
|
|
|
542
544
|
```tsx
|
|
543
545
|
const toolkit = defineToolkit({
|
|
@@ -581,9 +583,9 @@ const toolkit = defineToolkit({
|
|
|
581
583
|
|
|
582
584
|
`approval.isAutomatic` is `true` when the runtime granted the decision from a server-side policy rather than the user; render a "auto-approved" badge instead of buttons in that case.
|
|
583
585
|
|
|
584
|
-
Approval gates require a runtime that implements them: the AI SDK
|
|
586
|
+
Approval gates require a runtime that implements them: the AI SDK v7 runtime emits them for `toolApproval`-gated tools, and `LocalRuntime` supports gates emitted by your `ChatModelAdapter`; see [LocalRuntime approval gates](/docs/runtimes/custom/local-runtime#approval-gates). For tools where the user supplies the result itself, use `unstable_humanToolNames` with `addResult` instead; see [human-in-the-loop tools](/docs/runtimes/custom/local-runtime#human-in-the-loop-tools).
|
|
585
587
|
|
|
586
|
-
For the wire-side setup (`needsApproval`, `sendAutomaticallyWhen`), see [AI SDK
|
|
588
|
+
For the wire-side setup (`needsApproval`, `sendAutomaticallyWhen`), see [AI SDK v7 server-side tool approval](/docs/runtimes/ai-sdk/v7#server-side-tool-approval).
|
|
587
589
|
|
|
588
590
|
### Approval options
|
|
589
591
|
|
|
@@ -59,20 +59,28 @@ const connectors = [
|
|
|
59
59
|
name: "Weather",
|
|
60
60
|
url: "https://mcp.example.com/weather",
|
|
61
61
|
auth: { type: "none" },
|
|
62
|
+
connectionTimeout: 10_000,
|
|
62
63
|
}),
|
|
63
64
|
];
|
|
64
65
|
|
|
65
66
|
export function Providers({ children }: { children: React.ReactNode }) {
|
|
66
|
-
const aui = useAui({
|
|
67
|
+
const aui = useAui({
|
|
68
|
+
mcp: McpManagerResource({
|
|
69
|
+
connectors,
|
|
70
|
+
connectionTimeout: 15_000,
|
|
71
|
+
}),
|
|
72
|
+
});
|
|
67
73
|
return <AuiProvider value={aui}>{children}</AuiProvider>;
|
|
68
74
|
}
|
|
69
75
|
```
|
|
70
76
|
|
|
71
|
-
Defaults
|
|
77
|
+
Defaults and useful options:
|
|
72
78
|
|
|
73
79
|
- `storage` — `McpLocalStorage()` (override for production; see [Storage](#storage))
|
|
74
80
|
- `oauthRedirectUri` — `${window.location.origin}/mcp/callback`
|
|
75
81
|
- `autoConnect` — `true` (connect on mount when usable auth is persisted)
|
|
82
|
+
- `connectionTimeout` — optional timeout in milliseconds. Set it on the manager as a default or on a connector/custom server to bound the MCP readiness flow (`connect()` plus `listTools()`) with a clear error.
|
|
83
|
+
- Connector `id` values must be unique. The id is used for server lookup, OAuth routing, and model-visible tool names such as `linear__search`.
|
|
76
84
|
|
|
77
85
|
</Step>
|
|
78
86
|
<Step>
|
|
@@ -208,14 +216,19 @@ The callback reads `?state=...&code=...` from the URL, derives the target server
|
|
|
208
216
|
|
|
209
217
|
```tsx
|
|
210
218
|
"use client";
|
|
219
|
+
import { lastAssistantMessageIsCompleteWithToolCalls } from "ai";
|
|
211
220
|
import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
|
|
212
221
|
|
|
213
222
|
export function Chat() {
|
|
214
|
-
const runtime = useChatRuntime({
|
|
223
|
+
const runtime = useChatRuntime({
|
|
224
|
+
sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls,
|
|
225
|
+
});
|
|
215
226
|
/* … */
|
|
216
227
|
}
|
|
217
228
|
```
|
|
218
229
|
|
|
230
|
+
`sendAutomaticallyWhen` sends completed frontend tool results back to the server so the model can continue after a tool call. `useChatRuntime()` targets `/api/chat` by default; to point at a different endpoint, see [Custom transport](/docs/runtimes/ai-sdk/v7#custom-transport).
|
|
231
|
+
|
|
219
232
|
Tool names are prefixed `serverId__toolName` to avoid collisions across connected servers. The toolkit re-registers whenever a server connects / disconnects or its tool list changes.
|
|
220
233
|
|
|
221
234
|
If no chat runtime is mounted, `McpManagerResource` brings its own minimal `modelContext` along. Tools are still callable directly:
|
|
@@ -302,6 +315,29 @@ const aui = useAui();
|
|
|
302
315
|
await aui.mcp().addCustomServer({ name, url, auth: { type: "bearer", token } });
|
|
303
316
|
await aui.mcp().server({ id }).connect();
|
|
304
317
|
await aui.mcp().server({ id }).callTool("echo", { text: "hi" });
|
|
318
|
+
|
|
319
|
+
// Build a paginated resource browser/preview UI.
|
|
320
|
+
type ResourcePage = {
|
|
321
|
+
resources: Array<{ uri: string; name?: string }>;
|
|
322
|
+
nextCursor?: string;
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
const server = aui.mcp().server({ id });
|
|
326
|
+
const resources: ResourcePage["resources"] = [];
|
|
327
|
+
let nextCursor: string | undefined;
|
|
328
|
+
|
|
329
|
+
do {
|
|
330
|
+
const page = (await (nextCursor === undefined
|
|
331
|
+
? server.listResources()
|
|
332
|
+
: server.listResources({ cursor: nextCursor }))) as ResourcePage;
|
|
333
|
+
resources.push(...page.resources);
|
|
334
|
+
nextCursor = page.nextCursor;
|
|
335
|
+
} while (nextCursor !== undefined);
|
|
336
|
+
|
|
337
|
+
const firstResource = resources[0];
|
|
338
|
+
if (firstResource) {
|
|
339
|
+
const preview = await server.readResource(firstResource.uri);
|
|
340
|
+
}
|
|
305
341
|
```
|
|
306
342
|
|
|
307
343
|
## v1 scope
|
|
@@ -309,13 +345,14 @@ await aui.mcp().server({ id }).callTool("echo", { text: "hi" });
|
|
|
309
345
|
What ships:
|
|
310
346
|
|
|
311
347
|
- Tool listing and invocation, auto-registered as frontend tools
|
|
348
|
+
- Resource listing and reads for app-built browsers or preview panes
|
|
312
349
|
- OAuth (PKCE + DCR), bearer, none
|
|
313
350
|
- StreamableHTTP transport
|
|
314
351
|
- Manual connect/disconnect
|
|
315
352
|
|
|
316
353
|
What's deferred:
|
|
317
354
|
|
|
318
|
-
-
|
|
355
|
+
- Prompts, sampling
|
|
319
356
|
- Auto-reconnect with backoff
|
|
320
357
|
- Per-tool enable/disable persistence
|
|
321
358
|
- Per-tool consent prompts
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
title: Accordion
|
|
3
3
|
description: A vertically stacked set of interactive headings that reveal or hide content sections.
|
|
4
4
|
links:
|
|
5
|
-
- label: Radix UI Accordion
|
|
5
|
+
- label: Radix UI Accordion (Radix styles)
|
|
6
6
|
url: https://www.radix-ui.com/primitives/docs/components/accordion
|
|
7
|
+
- label: Base UI Accordion (base styles)
|
|
8
|
+
url: https://base-ui.com/react/components/accordion
|
|
7
9
|
platforms: ["react"]
|
|
8
10
|
---
|
|
9
11
|
|
|
@@ -16,12 +18,16 @@ import {
|
|
|
16
18
|
AccordionControlledSample,
|
|
17
19
|
AccordionFAQSample,
|
|
18
20
|
} from "@/components/docs/samples/accordion";
|
|
21
|
+
import * as AccordionRadixSamples from "@/components/docs/samples/accordion.radix";
|
|
22
|
+
import { Flavored, FlavorSwitcher } from "@/components/docs/contexts/flavor.server";
|
|
19
23
|
|
|
20
24
|
<Callout>
|
|
21
25
|
This is a **standalone component** that does not depend on the assistant-ui runtime. Use it anywhere in your application.
|
|
22
26
|
</Callout>
|
|
23
27
|
|
|
24
|
-
<
|
|
28
|
+
<FlavorSwitcher />
|
|
29
|
+
|
|
30
|
+
<Flavored radix={<AccordionRadixSamples.AccordionSample />} base={<AccordionSample />} />
|
|
25
31
|
|
|
26
32
|
## Installation
|
|
27
33
|
|
|
@@ -59,7 +65,7 @@ export function Example() {
|
|
|
59
65
|
|
|
60
66
|
Use the `variant` prop on `Accordion` to change the visual style. Child components inherit the variant automatically.
|
|
61
67
|
|
|
62
|
-
<AccordionVariantsSample />
|
|
68
|
+
<Flavored radix={<AccordionRadixSamples.AccordionVariantsSample />} base={<AccordionVariantsSample />} />
|
|
63
69
|
|
|
64
70
|
```tsx
|
|
65
71
|
// Default - border-bottom separator
|
|
@@ -91,7 +97,7 @@ Use the `variant` prop on `Accordion` to change the visual style. Child componen
|
|
|
91
97
|
|
|
92
98
|
Use `type="multiple"` to allow multiple items to be open simultaneously.
|
|
93
99
|
|
|
94
|
-
<AccordionMultipleSample />
|
|
100
|
+
<Flavored radix={<AccordionRadixSamples.AccordionMultipleSample />} base={<AccordionMultipleSample />} />
|
|
95
101
|
|
|
96
102
|
```tsx
|
|
97
103
|
<Accordion type="multiple">
|
|
@@ -110,24 +116,24 @@ Use `type="multiple"` to allow multiple items to be open simultaneously.
|
|
|
110
116
|
|
|
111
117
|
Add icons or custom elements inside the trigger.
|
|
112
118
|
|
|
113
|
-
<PreviewCode file="components/docs/samples/accordion" name="AccordionWithIconsSample">
|
|
114
|
-
<AccordionWithIconsSample />
|
|
119
|
+
<PreviewCode file="components/docs/samples/accordion" name="AccordionWithIconsSample" base={<AccordionWithIconsSample />}>
|
|
120
|
+
<AccordionRadixSamples.AccordionWithIconsSample />
|
|
115
121
|
</PreviewCode>
|
|
116
122
|
|
|
117
123
|
### Controlled
|
|
118
124
|
|
|
119
125
|
Use `value` and `onValueChange` for controlled accordion state.
|
|
120
126
|
|
|
121
|
-
<PreviewCode file="components/docs/samples/accordion" name="AccordionControlledSample">
|
|
122
|
-
<AccordionControlledSample />
|
|
127
|
+
<PreviewCode file="components/docs/samples/accordion" name="AccordionControlledSample" base={<AccordionControlledSample />}>
|
|
128
|
+
<AccordionRadixSamples.AccordionControlledSample />
|
|
123
129
|
</PreviewCode>
|
|
124
130
|
|
|
125
131
|
### FAQ Section
|
|
126
132
|
|
|
127
133
|
A practical example of using accordion for a FAQ section.
|
|
128
134
|
|
|
129
|
-
<PreviewCode file="components/docs/samples/accordion" name="AccordionFAQSample">
|
|
130
|
-
<AccordionFAQSample />
|
|
135
|
+
<PreviewCode file="components/docs/samples/accordion" name="AccordionFAQSample" base={<AccordionFAQSample />}>
|
|
136
|
+
<AccordionRadixSamples.AccordionFAQSample />
|
|
131
137
|
</PreviewCode>
|
|
132
138
|
|
|
133
139
|
## API Reference
|
|
@@ -5,10 +5,14 @@ platforms: ["react"]
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
import { AssistantModalSample } from "@/components/docs/samples/assistant-modal";
|
|
8
|
+
import * as AssistantModalRadixSamples from "@/components/docs/samples/assistant-modal.radix";
|
|
9
|
+
import { Flavored, FlavorSwitcher } from "@/components/docs/contexts/flavor.server";
|
|
8
10
|
|
|
9
|
-
A floating chat modal built on Radix UI Popover. Ideal for support widgets, help desks, and embedded assistants.
|
|
11
|
+
A floating chat modal built on the popover primitive of your configured style (Radix UI Popover on Radix styles, Base UI Popover on `base-*` styles). Ideal for support widgets, help desks, and embedded assistants.
|
|
10
12
|
|
|
11
|
-
<
|
|
13
|
+
<FlavorSwitcher />
|
|
14
|
+
|
|
15
|
+
<Flavored radix={<AssistantModalRadixSamples.AssistantModalSample />} base={<AssistantModalSample />} />
|
|
12
16
|
|
|
13
17
|
## Getting Started
|
|
14
18
|
|
|
@@ -43,7 +47,7 @@ export default function Home() {
|
|
|
43
47
|
|
|
44
48
|
## Anatomy
|
|
45
49
|
|
|
46
|
-
The `AssistantModal`
|
|
50
|
+
The Radix flavor of `AssistantModal` is built with the following primitives. The Base UI flavor composes your project's Base UI Popover instead.
|
|
47
51
|
|
|
48
52
|
```tsx
|
|
49
53
|
import { AssistantModalPrimitive } from "@assistant-ui/react";
|
|
@@ -61,7 +65,7 @@ import { AssistantModalPrimitive } from "@assistant-ui/react";
|
|
|
61
65
|
|
|
62
66
|
### Root
|
|
63
67
|
|
|
64
|
-
Contains all parts of the modal
|
|
68
|
+
Contains all parts of the modal when using `AssistantModalPrimitive` (the Radix flavor). The Base UI flavor uses your project's Base UI Popover instead.
|
|
65
69
|
|
|
66
70
|
<ParametersTable
|
|
67
71
|
type="AssistantModalPrimitiveRootProps"
|
|
@@ -5,8 +5,12 @@ platforms: ["react"]
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
import { AttachmentSample } from "@/components/docs/samples/attachment";
|
|
8
|
+
import * as AttachmentRadixSamples from "@/components/docs/samples/attachment.radix";
|
|
9
|
+
import { Flavored, FlavorSwitcher } from "@/components/docs/contexts/flavor.server";
|
|
8
10
|
|
|
9
|
-
<
|
|
11
|
+
<FlavorSwitcher />
|
|
12
|
+
|
|
13
|
+
<Flavored radix={<AttachmentRadixSamples.AttachmentSample />} base={<AttachmentSample />} />
|
|
10
14
|
|
|
11
15
|
<Callout type="info">
|
|
12
16
|
**Note:** These components provide the UI for attachments, but you also need
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
title: Badge
|
|
3
3
|
description: A small label component for displaying status, categories, or metadata.
|
|
4
4
|
links:
|
|
5
|
-
- label: Radix UI Slot
|
|
5
|
+
- label: Radix UI Slot (Radix styles)
|
|
6
6
|
url: https://www.radix-ui.com/primitives/docs/utilities/slot
|
|
7
|
+
- label: Base UI useRender (base styles)
|
|
8
|
+
url: https://base-ui.com/react/utils/use-render
|
|
7
9
|
platforms: ["react"]
|
|
8
10
|
---
|
|
9
11
|
|
|
@@ -15,12 +17,16 @@ import {
|
|
|
15
17
|
BadgeAsLinkSample,
|
|
16
18
|
BadgeAnimatedSample,
|
|
17
19
|
} from "@/components/docs/samples/badge";
|
|
20
|
+
import * as BadgeRadixSamples from "@/components/docs/samples/badge.radix";
|
|
21
|
+
import { Flavored, FlavorSwitcher } from "@/components/docs/contexts/flavor.server";
|
|
18
22
|
|
|
19
23
|
<Callout>
|
|
20
24
|
This is a **standalone component** that does not depend on the assistant-ui runtime. Use it anywhere in your application.
|
|
21
25
|
</Callout>
|
|
22
26
|
|
|
23
|
-
<
|
|
27
|
+
<FlavorSwitcher />
|
|
28
|
+
|
|
29
|
+
<Flavored radix={<BadgeRadixSamples.BadgeSample />} base={<BadgeSample />} />
|
|
24
30
|
|
|
25
31
|
## Installation
|
|
26
32
|
|
|
@@ -42,7 +48,7 @@ export function Example() {
|
|
|
42
48
|
|
|
43
49
|
Use the `variant` prop to change the visual style.
|
|
44
50
|
|
|
45
|
-
<BadgeSample />
|
|
51
|
+
<Flavored radix={<BadgeRadixSamples.BadgeSample />} base={<BadgeSample />} />
|
|
46
52
|
|
|
47
53
|
```tsx
|
|
48
54
|
<Badge variant="outline" /> // Border (default)
|
|
@@ -59,7 +65,7 @@ Use the `variant` prop to change the visual style.
|
|
|
59
65
|
|
|
60
66
|
Use the `size` prop to change the badge size.
|
|
61
67
|
|
|
62
|
-
<BadgeSizesSample />
|
|
68
|
+
<Flavored radix={<BadgeRadixSamples.BadgeSizesSample />} base={<BadgeSizesSample />} />
|
|
63
69
|
|
|
64
70
|
```tsx
|
|
65
71
|
<Badge size="sm" /> // Small
|
|
@@ -71,24 +77,24 @@ Use the `size` prop to change the badge size.
|
|
|
71
77
|
|
|
72
78
|
Badges automatically style SVG icons.
|
|
73
79
|
|
|
74
|
-
<PreviewCode file="components/docs/samples/badge" name="BadgeWithIconSample">
|
|
75
|
-
<BadgeWithIconSample />
|
|
80
|
+
<PreviewCode file="components/docs/samples/badge" name="BadgeWithIconSample" base={<BadgeWithIconSample />}>
|
|
81
|
+
<BadgeRadixSamples.BadgeWithIconSample />
|
|
76
82
|
</PreviewCode>
|
|
77
83
|
|
|
78
84
|
### As Link
|
|
79
85
|
|
|
80
|
-
|
|
86
|
+
Compose with `render` (Base UI) or `asChild` (Radix) to render the badge as a different element, like a link.
|
|
81
87
|
|
|
82
|
-
<PreviewCode file="components/docs/samples/badge" name="BadgeAsLinkSample">
|
|
83
|
-
<BadgeAsLinkSample />
|
|
88
|
+
<PreviewCode file="components/docs/samples/badge" name="BadgeAsLinkSample" base={<BadgeAsLinkSample />}>
|
|
89
|
+
<BadgeRadixSamples.BadgeAsLinkSample />
|
|
84
90
|
</PreviewCode>
|
|
85
91
|
|
|
86
92
|
### Animated
|
|
87
93
|
|
|
88
94
|
Combine with CSS transitions for scroll and color animations.
|
|
89
95
|
|
|
90
|
-
<PreviewCode file="components/docs/samples/badge" name="BadgeAnimatedSample">
|
|
91
|
-
<BadgeAnimatedSample />
|
|
96
|
+
<PreviewCode file="components/docs/samples/badge" name="BadgeAnimatedSample" base={<BadgeAnimatedSample />}>
|
|
97
|
+
<BadgeRadixSamples.BadgeAnimatedSample />
|
|
92
98
|
</PreviewCode>
|
|
93
99
|
|
|
94
100
|
## API Reference
|
|
@@ -110,11 +116,16 @@ Combine with CSS transitions for scroll and color animations.
|
|
|
110
116
|
default: '"default"',
|
|
111
117
|
description: "The size of the badge.",
|
|
112
118
|
},
|
|
119
|
+
{
|
|
120
|
+
name: "render",
|
|
121
|
+
type: "ReactElement | function",
|
|
122
|
+
description: "Base UI: compose as a different element instead of rendering a span.",
|
|
123
|
+
},
|
|
113
124
|
{
|
|
114
125
|
name: "asChild",
|
|
115
126
|
type: "boolean",
|
|
116
127
|
default: "false",
|
|
117
|
-
description: "
|
|
128
|
+
description: "Radix: merge props with a child element instead of rendering a span.",
|
|
118
129
|
},
|
|
119
130
|
{
|
|
120
131
|
name: "className",
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Follow-Up Suggestions
|
|
3
|
+
description: Render runtime-generated follow-up prompt chips after an assistant response.
|
|
4
|
+
platforms: ["react"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
import { FollowUpSuggestionsSample } from "@/components/docs/samples/follow-up-suggestions";
|
|
8
|
+
|
|
9
|
+
<FollowUpSuggestionsSample />
|
|
10
|
+
|
|
11
|
+
`ThreadFollowupSuggestions` renders the current thread's runtime suggestions as clickable prompt chips. Use it for follow-up prompts that arrive after a response, such as suggested next questions, refinements, or task shortcuts.
|
|
12
|
+
|
|
13
|
+
<Callout type="info">
|
|
14
|
+
This component reads from `thread.suggestions`. For static welcome-screen prompts, use `ThreadPrimitive.Suggestions` instead.
|
|
15
|
+
</Callout>
|
|
16
|
+
|
|
17
|
+
## Getting Started
|
|
18
|
+
|
|
19
|
+
<Steps>
|
|
20
|
+
<Step>
|
|
21
|
+
|
|
22
|
+
### Add `follow-up-suggestions`
|
|
23
|
+
|
|
24
|
+
<InstallCommand shadcn={["follow-up-suggestions"]} />
|
|
25
|
+
|
|
26
|
+
This adds a `/components/assistant-ui/follow-up-suggestions.tsx` file to your project. The default `thread` component already renders `ThreadFollowupSuggestions`, so installing it standalone is only needed when you build your own thread layout.
|
|
27
|
+
|
|
28
|
+
</Step>
|
|
29
|
+
<Step>
|
|
30
|
+
|
|
31
|
+
### Provide runtime suggestions
|
|
32
|
+
|
|
33
|
+
Pass suggestions through your runtime. External-store runtimes, AI SDK runtimes, and local runtimes can all surface follow-up prompts through `thread.suggestions`.
|
|
34
|
+
|
|
35
|
+
```tsx title="/app/assistant.tsx" {7-10}
|
|
36
|
+
const runtime = useExternalStoreRuntime({
|
|
37
|
+
messages,
|
|
38
|
+
convertMessage,
|
|
39
|
+
onNew: async (message) => {
|
|
40
|
+
// append the message in your store
|
|
41
|
+
},
|
|
42
|
+
suggestions: [
|
|
43
|
+
{ prompt: "Summarize this as action items" },
|
|
44
|
+
{ prompt: "Write a shorter version" },
|
|
45
|
+
],
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
</Step>
|
|
50
|
+
<Step>
|
|
51
|
+
|
|
52
|
+
### Render after messages
|
|
53
|
+
|
|
54
|
+
Place `ThreadFollowupSuggestions` near the bottom of your thread viewport, after the assistant message list and before the composer.
|
|
55
|
+
|
|
56
|
+
```tsx title="/components/assistant-ui/thread.tsx" {1,10}
|
|
57
|
+
import { ThreadFollowupSuggestions } from "@/components/assistant-ui/follow-up-suggestions";
|
|
58
|
+
|
|
59
|
+
const ThreadViewportFooter = () => {
|
|
60
|
+
return (
|
|
61
|
+
<ThreadPrimitive.ViewportFooter>
|
|
62
|
+
<ThreadPrimitive.ScrollToBottom />
|
|
63
|
+
<ThreadFollowupSuggestions />
|
|
64
|
+
<Composer />
|
|
65
|
+
</ThreadPrimitive.ViewportFooter>
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
</Step>
|
|
71
|
+
</Steps>
|
|
72
|
+
|
|
73
|
+
## Behavior
|
|
74
|
+
|
|
75
|
+
The component only renders when the thread is not empty, not currently running, and has at least one suggestion. Each suggestion uses `ThreadPrimitive.Suggestion`, replaces the composer text with the prompt, and sends it immediately.
|
|
76
|
+
|
|
77
|
+
## Related Components
|
|
78
|
+
|
|
79
|
+
- [Thread](/docs/ui/thread) - Complete chat interface with message list and composer
|
|
80
|
+
- [Suggestions guide](/docs/guides/suggestions) - Runtime and static suggestion patterns
|