@assistant-ui/mcp-docs-server 0.1.39 → 0.2.1
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 +17 -18
- package/.docs/organized/code-examples/with-a2a.md +20 -15
- package/.docs/organized/code-examples/with-ag-ui.md +19 -17
- package/.docs/organized/code-examples/with-ai-sdk-v7.md +17 -16
- package/.docs/organized/code-examples/with-artifacts.md +471 -145
- package/.docs/organized/code-examples/with-assistant-transport.md +23 -31
- package/.docs/organized/code-examples/with-browser-extension.md +21 -14
- package/.docs/organized/code-examples/with-chain-of-thought.md +22 -20
- package/.docs/organized/code-examples/with-cloud-standalone.md +13 -14
- package/.docs/organized/code-examples/with-cloud.md +22 -17
- package/.docs/organized/code-examples/with-custom-thread-list.md +17 -16
- package/.docs/organized/code-examples/with-elevenlabs-conversational.md +17 -17
- package/.docs/organized/code-examples/with-elevenlabs-scribe.md +21 -19
- package/.docs/organized/code-examples/with-eve.md +70 -16
- package/.docs/organized/code-examples/with-expo.md +32 -51
- package/.docs/organized/code-examples/with-external-store.md +20 -15
- package/.docs/organized/code-examples/with-ffmpeg.md +24 -18
- package/.docs/organized/code-examples/with-generative-ui.md +20 -21
- package/.docs/organized/code-examples/with-google-adk.md +21 -16
- package/.docs/organized/code-examples/with-heat-graph.md +10 -11
- package/.docs/organized/code-examples/with-image-generation.md +13 -14
- package/.docs/organized/code-examples/with-interactables.md +17 -16
- package/.docs/organized/code-examples/with-langchain.md +13 -14
- package/.docs/organized/code-examples/with-langgraph.md +23 -17
- package/.docs/organized/code-examples/with-livekit.md +17 -17
- package/.docs/organized/code-examples/with-mcp.md +36 -32
- package/.docs/organized/code-examples/with-nuxt.md +2492 -0
- package/.docs/organized/code-examples/with-opencode.md +27 -21
- package/.docs/organized/code-examples/with-pi.md +69 -67
- package/.docs/organized/code-examples/with-react-hook-form.md +18 -17
- package/.docs/organized/code-examples/with-react-ink-web.md +10 -11
- package/.docs/organized/code-examples/with-react-ink.md +7 -7
- package/.docs/organized/code-examples/with-react-router.md +23 -17
- package/.docs/organized/code-examples/with-resumable-stream.md +15 -16
- package/.docs/organized/code-examples/with-store.md +31 -20
- package/.docs/organized/code-examples/with-tanstack.md +22 -16
- package/.docs/organized/code-examples/with-tap-runtime.md +19 -19
- package/.docs/organized/code-examples/with-virtualized-thread.md +12 -13
- package/.docs/organized/code-examples/with-vue.md +408 -0
- package/.docs/raw/docs/(docs)/cli.mdx +3 -1
- package/.docs/raw/docs/(docs)/devtools.mdx +7 -2
- package/.docs/raw/docs/(docs)/index.mdx +9 -76
- package/.docs/raw/docs/(docs)/installation.mdx +4 -18
- package/.docs/raw/docs/(reference)/api-reference/context-providers/assistant-runtime-provider.mdx +24 -4
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/a2ui.mdx +40 -0
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/index.mdx +3 -0
- package/.docs/raw/docs/(reference)/api-reference/hooks/primitives.mdx +19 -420
- package/.docs/raw/docs/(reference)/api-reference/hooks/state.mdx +4 -1
- package/.docs/raw/docs/(reference)/api-reference/integrations/eve.mdx +8 -0
- package/.docs/raw/docs/(reference)/api-reference/integrations/react-ai-sdk.mdx +21 -0
- package/.docs/raw/docs/(reference)/api-reference/model-context/context.mdx +1 -9
- package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-if.mdx +1 -18
- package/.docs/raw/docs/(reference)/api-reference/utilities/miscellaneous.mdx +24 -1
- package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +1 -1
- package/.docs/raw/docs/cloud/ai-sdk.mdx +2 -2
- package/.docs/raw/docs/cloud/langgraph.mdx +1 -1
- package/.docs/raw/docs/copilots/model-context.mdx +5 -4
- package/.docs/raw/docs/copilots/motivation.mdx +5 -5
- package/.docs/raw/docs/guides/attachments.mdx +3 -3
- package/.docs/raw/docs/guides/branching.mdx +2 -2
- package/.docs/raw/docs/guides/chain-of-thought.mdx +1 -1
- package/.docs/raw/docs/guides/context-api.mdx +89 -111
- package/.docs/raw/docs/guides/editing.mdx +5 -5
- package/.docs/raw/docs/guides/electron.mdx +369 -0
- package/.docs/raw/docs/guides/index.mdx +10 -0
- package/.docs/raw/docs/guides/quoting.mdx +3 -3
- package/.docs/raw/docs/guides/resumable-stream-deployment.mdx +2 -2
- package/.docs/raw/docs/guides/resumable-streams.mdx +74 -3
- package/.docs/raw/docs/guides/suggestions.mdx +9 -9
- package/.docs/raw/docs/ink/hooks.mdx +12 -7
- package/.docs/raw/docs/ink/primitives.mdx +18 -10
- package/.docs/raw/docs/integrations/attachments/custom-adapter.mdx +16 -0
- package/.docs/raw/docs/integrations/auth/better-auth.mdx +3 -3
- package/.docs/raw/docs/integrations/auth/clerk.mdx +3 -3
- package/.docs/raw/docs/integrations/auth/next-auth.mdx +4 -4
- package/.docs/raw/docs/integrations/frameworks/cloudflare-agents/overview.mdx +1 -1
- package/.docs/raw/docs/integrations/frameworks/mastra/full-stack.mdx +2 -2
- 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/observability/helicone.mdx +2 -2
- package/.docs/raw/docs/integrations/observability/langfuse.mdx +1 -1
- package/.docs/raw/docs/integrations/observability/langsmith.mdx +3 -3
- package/.docs/raw/docs/integrations/persistence/custom-adapter.mdx +36 -9
- package/.docs/raw/docs/migrations/toolkit-tools.mdx +15 -13
- package/.docs/raw/docs/migrations/v0-15.mdx +236 -0
- package/.docs/raw/docs/primitives/attachment.mdx +2 -2
- package/.docs/raw/docs/primitives/composer.mdx +3 -3
- package/.docs/raw/docs/primitives/message.mdx +33 -1
- package/.docs/raw/docs/primitives/suggestion.mdx +1 -1
- package/.docs/raw/docs/primitives/thread-list.mdx +2 -2
- package/.docs/raw/docs/react-native/hooks.mdx +17 -7
- package/.docs/raw/docs/react-native/index.mdx +3 -3
- package/.docs/raw/docs/react-native/primitives.mdx +41 -7
- package/.docs/raw/docs/runtimes/ai-sdk/overview.mdx +3 -3
- package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +5 -5
- package/.docs/raw/docs/runtimes/ai-sdk/v5-legacy.mdx +5 -5
- package/.docs/raw/docs/runtimes/ai-sdk/v6-legacy.mdx +13 -14
- package/.docs/raw/docs/runtimes/ai-sdk/v7.mdx +11 -12
- package/.docs/raw/docs/runtimes/concepts/threads.mdx +50 -11
- package/.docs/raw/docs/runtimes/custom/assistant-transport.mdx +20 -2
- package/.docs/raw/docs/runtimes/custom/external-store.mdx +31 -2
- package/.docs/raw/docs/runtimes/custom/local-runtime.mdx +39 -12
- package/.docs/raw/docs/runtimes/eve/overview.mdx +51 -0
- package/.docs/raw/docs/runtimes/eve/quickstart.mdx +51 -2
- package/.docs/raw/docs/runtimes/google-adk/hooks.mdx +9 -12
- package/.docs/raw/docs/runtimes/langchain.mdx +2 -2
- package/.docs/raw/docs/runtimes/langgraph/overview.mdx +1 -1
- package/.docs/raw/docs/runtimes/langgraph/streaming.mdx +1 -1
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +7 -7
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-3.mdx +4 -4
- package/.docs/raw/docs/runtimes/opencode/hooks.mdx +4 -1
- package/.docs/raw/docs/runtimes/opencode/overview.mdx +10 -0
- package/.docs/raw/docs/tools/a2ui.mdx +107 -0
- package/.docs/raw/docs/tools/backend.mdx +2 -2
- package/.docs/raw/docs/tools/defining-tools.mdx +9 -7
- package/.docs/raw/docs/tools/dynamic-tools.mdx +6 -4
- package/.docs/raw/docs/tools/interactables-legacy.mdx +28 -15
- package/.docs/raw/docs/tools/interactables.mdx +27 -16
- package/.docs/raw/docs/tools/mcp-apps.mdx +96 -8
- package/.docs/raw/docs/tools/mcp.mdx +9 -7
- package/.docs/raw/docs/tools/tool-ui.mdx +26 -22
- package/.docs/raw/docs/tools/user-managed-mcp.mdx +64 -14
- package/.docs/raw/docs/ui/file.mdx +6 -1
- package/.docs/raw/docs/ui/follow-up-suggestions.mdx +2 -0
- package/.docs/raw/docs/ui/mcp-config.mdx +8 -3
- package/.docs/raw/docs/ui/model-selector.mdx +9 -9
- package/.docs/raw/docs/ui/part-grouping.mdx +1 -5
- package/.docs/raw/docs/ui/reasoning.mdx +1 -1
- package/.docs/raw/docs/ui/thread.mdx +24 -5
- package/.docs/raw/docs/utilities/react-o11y.mdx +7 -9
- package/dist/constants.js +2 -2
- package/dist/constants.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/prepare-docs/code-examples.js.map +1 -1
- package/dist/prepare-docs/prepare.d.ts +1 -1
- package/dist/prepare-docs/prepare.js.map +1 -1
- package/dist/stdio.d.ts +1 -1
- package/dist/tools/docs.d.ts +6 -10
- package/dist/tools/docs.d.ts.map +1 -1
- package/dist/tools/docs.js +6 -4
- package/dist/tools/docs.js.map +1 -1
- package/dist/tools/examples.d.ts +4 -8
- package/dist/tools/examples.d.ts.map +1 -1
- package/dist/tools/examples.js +4 -3
- package/dist/tools/examples.js.map +1 -1
- package/dist/tools/resources.d.ts +1 -1
- package/dist/tools/resources.d.ts.map +1 -1
- package/dist/tools/resources.js +3 -2
- package/dist/tools/resources.js.map +1 -1
- package/dist/tools/search.d.ts +4 -10
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/search.js +2 -2
- package/dist/tools/search.js.map +1 -1
- package/dist/tools/tests/mcp-test-client.d.ts +15 -0
- package/dist/tools/tests/mcp-test-client.d.ts.map +1 -0
- package/dist/tools/tests/mcp-test-client.js +68 -0
- package/dist/tools/tests/mcp-test-client.js.map +1 -0
- package/dist/tools/tests/test-setup.d.ts.map +1 -1
- package/dist/tools/tests/test-setup.js +2 -1
- package/dist/tools/tests/test-setup.js.map +1 -1
- package/dist/tools/xulux-templates.d.ts +9 -23
- package/dist/tools/xulux-templates.d.ts.map +1 -1
- package/dist/tools/xulux-templates.js +8 -6
- package/dist/tools/xulux-templates.js.map +1 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/mdx.js +2 -1
- package/dist/utils/mdx.js.map +1 -1
- package/dist/utils/security.js.map +1 -1
- package/dist/xulux/catalog-client.js +1 -1
- package/dist/xulux/catalog-client.js.map +1 -1
- package/package.json +6 -5
- package/src/index.ts +2 -2
- package/src/tools/docs.ts +2 -2
- package/src/tools/examples.ts +2 -2
- package/src/tools/resources.ts +1 -4
- package/src/tools/search.ts +2 -2
- package/src/tools/tests/completions.test.ts +40 -26
- package/src/tools/tests/docs.test.ts +2 -2
- package/src/tools/tests/integration.test.ts +3 -4
- package/src/tools/tests/mcp-protocol.test.ts +160 -175
- package/src/tools/tests/mcp-test-client.ts +111 -0
- package/src/tools/tests/resources.test.ts +97 -66
- package/src/tools/xulux-templates.ts +4 -4
|
@@ -396,7 +396,7 @@ Renders the quoted text from `s.composer.quote?.text`. Pass `children` to overri
|
|
|
396
396
|
|
|
397
397
|
### QuoteDismiss
|
|
398
398
|
|
|
399
|
-
Pressable that clears the active quote by calling `aui.composer
|
|
399
|
+
Pressable that clears the active quote by calling `aui.composer.setQuote(undefined)`.
|
|
400
400
|
|
|
401
401
|
```tsx
|
|
402
402
|
<ComposerPrimitive.QuoteDismiss>
|
|
@@ -666,10 +666,11 @@ Container `Box` for an attachment. Forwards all `Box` props.
|
|
|
666
666
|
|
|
667
667
|
### Thumb
|
|
668
668
|
|
|
669
|
-
`Text` component displaying a short identifier for the attachment. Renders the file extension (`.pdf`, `.png`, …) when the name has one. Falls back to the attachment `type` (e.g. `image`, `document`) otherwise, and finally to `file`.
|
|
669
|
+
`Text` component displaying a short identifier for the attachment. Renders the file extension (`.pdf`, `.png`, …) when the name has one. Falls back to the attachment `type` (e.g. `image`, `document`) otherwise, and finally to `file`. Passing `children` overrides the automatic label.
|
|
670
670
|
|
|
671
671
|
| Prop | Type | Description |
|
|
672
672
|
|------|------|-------------|
|
|
673
|
+
| `children` | `ReactNode` | Overrides the automatic extension/type label |
|
|
673
674
|
| `...rest` | `ComponentProps<typeof Text>` | Forwarded to the underlying Ink `Text` |
|
|
674
675
|
|
|
675
676
|
### Status
|
|
@@ -683,7 +684,7 @@ Container `Box` for an attachment. Forwards all `Box` props.
|
|
|
683
684
|
|
|
684
685
|
### Remove
|
|
685
686
|
|
|
686
|
-
`Pressable` that calls `aui.attachment
|
|
687
|
+
`Pressable` that calls `aui.attachment.remove()` when activated (Enter while focused). Disabled when not focused or when the `disabled` prop is set.
|
|
687
688
|
|
|
688
689
|
| Prop | Type | Description |
|
|
689
690
|
|------|------|-------------|
|
|
@@ -712,7 +713,7 @@ Primitives for rendering individual queued composer items. Use inside a `Compose
|
|
|
712
713
|
|
|
713
714
|
### Text
|
|
714
715
|
|
|
715
|
-
Renders the queue item's
|
|
716
|
+
Renders the queue item's text with Ink `<Text>`. Pass `children` to override the displayed value.
|
|
716
717
|
|
|
717
718
|
```tsx
|
|
718
719
|
<QueueItemPrimitive.Text color="gray" />
|
|
@@ -720,12 +721,12 @@ Renders the queue item's prompt with Ink `<Text>`. Pass `children` to override t
|
|
|
720
721
|
|
|
721
722
|
| Prop | Type | Description |
|
|
722
723
|
|------|------|-------------|
|
|
723
|
-
| `children` | `ReactNode` | Override content; defaults to `s.queueItem.
|
|
724
|
+
| `children` | `ReactNode` | Override content; defaults to the text parts of `s.queueItem.parts` |
|
|
724
725
|
| `...rest` | `TextProps` | Standard Ink Text props |
|
|
725
726
|
|
|
726
727
|
### Remove
|
|
727
728
|
|
|
728
|
-
Pressable that removes the queue item by calling `aui.queueItem
|
|
729
|
+
Pressable that removes the queue item by calling `aui.queueItem.remove()`.
|
|
729
730
|
|
|
730
731
|
```tsx
|
|
731
732
|
<QueueItemPrimitive.Remove>
|
|
@@ -742,7 +743,7 @@ Remaining props are forwarded to the underlying `Pressable` (Ink `Box` props).
|
|
|
742
743
|
|
|
743
744
|
### Steer
|
|
744
745
|
|
|
745
|
-
Pressable that promotes the queue item to run next by calling `aui.queueItem
|
|
746
|
+
Pressable that promotes the queue item to run next by calling `aui.queueItem.steer()`.
|
|
746
747
|
|
|
747
748
|
```tsx
|
|
748
749
|
<QueueItemPrimitive.Steer>
|
|
@@ -765,10 +766,17 @@ import { ActionBarPrimitive } from "@assistant-ui/react-ink";
|
|
|
765
766
|
|
|
766
767
|
### Copy
|
|
767
768
|
|
|
768
|
-
Pressable that copies the message content. Supports function-as-children for copy state feedback.
|
|
769
|
+
Pressable that copies the message content. Pass a platform clipboard writer through `copyToClipboard`. Supports function-as-children for copy state feedback.
|
|
770
|
+
|
|
771
|
+
<InstallCommand npm={["clipboardy"]} />
|
|
769
772
|
|
|
770
773
|
```tsx
|
|
771
|
-
|
|
774
|
+
import clipboard from "clipboardy";
|
|
775
|
+
|
|
776
|
+
<ActionBarPrimitive.Copy
|
|
777
|
+
copiedDuration={3000}
|
|
778
|
+
copyToClipboard={clipboard.write}
|
|
779
|
+
>
|
|
772
780
|
{({ isCopied }) => <Text>{isCopied ? "[Copied!]" : "[Copy]"}</Text>}
|
|
773
781
|
</ActionBarPrimitive.Copy>
|
|
774
782
|
```
|
|
@@ -776,7 +784,7 @@ Pressable that copies the message content. Supports function-as-children for cop
|
|
|
776
784
|
| Prop | Type | Description |
|
|
777
785
|
|------|------|-------------|
|
|
778
786
|
| `copiedDuration` | `number` | Duration in ms to show "copied" state (default: 3000) |
|
|
779
|
-
| `copyToClipboard` | `(text: string) => void
|
|
787
|
+
| `copyToClipboard` | `(text: string) => void \| Promise<void>` | Platform clipboard writer |
|
|
780
788
|
|
|
781
789
|
### Edit
|
|
782
790
|
|
|
@@ -489,6 +489,22 @@ In the adapter's `add`, call Uploadthing's client upload and read `url` from the
|
|
|
489
489
|
</Tab>
|
|
490
490
|
</Tabs>
|
|
491
491
|
|
|
492
|
+
### Opaque file references (LangGraph / LangChain)
|
|
493
|
+
|
|
494
|
+
When the backend resolves stored files itself and the browser never holds a usable URL, send the storage id instead: set `sourceType: "id"` on the file part in `send()`, and the LangChain-family runtimes emit a `source_type: "id"` block with the value in the `id` key. `sourceType: "url"` similarly forces a url reference for non-http data and is honored by the LangChain-family, A2A, AG-UI, and Google ADK runtimes. `sourceType: "id"` is LangChain-family only; runtimes without the concept ignore the field.
|
|
495
|
+
|
|
496
|
+
```ts
|
|
497
|
+
const content = [
|
|
498
|
+
{
|
|
499
|
+
type: "file" as const,
|
|
500
|
+
filename: name,
|
|
501
|
+
mimeType: contentType ?? "application/octet-stream",
|
|
502
|
+
data: fileId,
|
|
503
|
+
sourceType: "id" as const,
|
|
504
|
+
},
|
|
505
|
+
];
|
|
506
|
+
```
|
|
507
|
+
|
|
492
508
|
## Notes
|
|
493
509
|
|
|
494
510
|
- **Persistence.** A URL the model sees on Monday must still resolve next week if the thread is reloaded. Either use storage with no expiry on the public URL, or have your [history adapter](/docs/integrations/persistence/custom-adapter) regenerate signed URLs on `load`. Don't store presigned URLs in the message row.
|
|
@@ -22,7 +22,7 @@ Three integration points:
|
|
|
22
22
|
|
|
23
23
|
1. **Auth handlers** mounted at `/api/auth/[...all]/route.ts` via `toNextJsHandler(auth)`.
|
|
24
24
|
2. **API routes** read the session server-side with `auth.api.getSession({ headers: await headers() })`.
|
|
25
|
-
3. **Reload-on-auth** uses better-auth's React client to detect sign-in and trigger `aui.threads
|
|
25
|
+
3. **Reload-on-auth** uses better-auth's React client to detect sign-in and trigger `aui.threads.reload()`.
|
|
26
26
|
|
|
27
27
|
`session.user.id` is exposed on the session object directly, so route handlers can scope queries against it.
|
|
28
28
|
|
|
@@ -66,7 +66,7 @@ export async function POST(req: Request) {
|
|
|
66
66
|
|
|
67
67
|
const { messages }: { messages: UIMessage[] } = await req.json();
|
|
68
68
|
const result = streamText({
|
|
69
|
-
model: openai("gpt-5.
|
|
69
|
+
model: openai("gpt-5.6-luna"),
|
|
70
70
|
messages: await convertToModelMessages(messages),
|
|
71
71
|
});
|
|
72
72
|
return result.toUIMessageStreamResponse();
|
|
@@ -136,7 +136,7 @@ export function ReloadOnAuth() {
|
|
|
136
136
|
const aui = useAui();
|
|
137
137
|
const { data: session, isPending } = authClient.useSession();
|
|
138
138
|
useEffect(() => {
|
|
139
|
-
if (!isPending && session) aui.threads
|
|
139
|
+
if (!isPending && session) aui.threads.reload();
|
|
140
140
|
}, [isPending, session?.user?.id]);
|
|
141
141
|
return null;
|
|
142
142
|
}
|
|
@@ -45,7 +45,7 @@ export async function POST(req: Request) {
|
|
|
45
45
|
|
|
46
46
|
const { messages }: { messages: UIMessage[] } = await req.json();
|
|
47
47
|
const result = streamText({
|
|
48
|
-
model: openai("gpt-5.
|
|
48
|
+
model: openai("gpt-5.6-luna"),
|
|
49
49
|
messages: await convertToModelMessages(messages),
|
|
50
50
|
});
|
|
51
51
|
return result.toUIMessageStreamResponse();
|
|
@@ -102,7 +102,7 @@ const rows = await db
|
|
|
102
102
|
|
|
103
103
|
### Reload threads after async auth
|
|
104
104
|
|
|
105
|
-
The first render of `<MyProvider>` may run before Clerk resolves the user on the client. Drop a small effect inside `<AssistantRuntimeProvider>` that calls `aui.threads
|
|
105
|
+
The first render of `<MyProvider>` may run before Clerk resolves the user on the client. Drop a small effect inside `<AssistantRuntimeProvider>` that calls `aui.threads.reload()` once the user is loaded:
|
|
106
106
|
|
|
107
107
|
```tsx title="app/components/ReloadOnAuth.tsx"
|
|
108
108
|
"use client";
|
|
@@ -115,7 +115,7 @@ export function ReloadOnAuth() {
|
|
|
115
115
|
const aui = useAui();
|
|
116
116
|
const { isLoaded, isSignedIn, user } = useUser();
|
|
117
117
|
useEffect(() => {
|
|
118
|
-
if (isLoaded && isSignedIn) aui.threads
|
|
118
|
+
if (isLoaded && isSignedIn) aui.threads.reload();
|
|
119
119
|
}, [isLoaded, isSignedIn, user?.id]);
|
|
120
120
|
return null;
|
|
121
121
|
}
|
|
@@ -18,7 +18,7 @@ Three places auth touches the integration:
|
|
|
18
18
|
|
|
19
19
|
1. **API routes** (`/api/chat`, `/api/threads/*`) call `auth()` server-side, return 401 if no session, then scope DB queries by `session.user.id`.
|
|
20
20
|
2. **`RemoteThreadListAdapter`** does nothing auth-specific; the cookie travels with the `fetch` calls automatically (same origin).
|
|
21
|
-
3. **Reload-on-auth**: if the session resolves after the initial render, call `aui.threads
|
|
21
|
+
3. **Reload-on-auth**: if the session resolves after the initial render, call `aui.threads.reload()` so the list re-fetches with the new identity.
|
|
22
22
|
|
|
23
23
|
## Setup
|
|
24
24
|
|
|
@@ -72,7 +72,7 @@ export async function POST(req: Request) {
|
|
|
72
72
|
|
|
73
73
|
const { messages }: { messages: UIMessage[] } = await req.json();
|
|
74
74
|
const result = streamText({
|
|
75
|
-
model: openai("gpt-5.
|
|
75
|
+
model: openai("gpt-5.6-luna"),
|
|
76
76
|
messages: await convertToModelMessages(messages),
|
|
77
77
|
});
|
|
78
78
|
return result.toUIMessageStreamResponse();
|
|
@@ -113,7 +113,7 @@ Apply the same pattern to `POST`, `PATCH`, and `DELETE` handlers. Always verify
|
|
|
113
113
|
|
|
114
114
|
### Reload threads after async auth
|
|
115
115
|
|
|
116
|
-
The first render of `<MyProvider>` may run before `auth()` resolves on the client. The thread list will be empty until the user refreshes. Drop a small effect into the layout to call `aui.threads
|
|
116
|
+
The first render of `<MyProvider>` may run before `auth()` resolves on the client. The thread list will be empty until the user refreshes. Drop a small effect into the layout to call `aui.threads.reload()` once the session resolves.
|
|
117
117
|
|
|
118
118
|
`useSession` requires `<SessionProvider>` higher in the tree. Wrap your root layout's client subtree once:
|
|
119
119
|
|
|
@@ -140,7 +140,7 @@ export function ReloadOnAuth() {
|
|
|
140
140
|
const aui = useAui();
|
|
141
141
|
const { status, data } = useSession();
|
|
142
142
|
useEffect(() => {
|
|
143
|
-
if (status === "authenticated") aui.threads
|
|
143
|
+
if (status === "authenticated") aui.threads.reload();
|
|
144
144
|
}, [status, data?.user?.id]);
|
|
145
145
|
return null;
|
|
146
146
|
}
|
|
@@ -68,7 +68,7 @@ export type Env = {
|
|
|
68
68
|
export class Chat extends AIChatAgent<Env> {
|
|
69
69
|
async onChatMessage(onFinish: Parameters<typeof streamText>[0]["onFinish"]) {
|
|
70
70
|
return streamText({
|
|
71
|
-
model: openai("gpt-5.
|
|
71
|
+
model: openai("gpt-5.6-luna"),
|
|
72
72
|
messages: await convertToModelMessages(this.messages),
|
|
73
73
|
onFinish,
|
|
74
74
|
});
|
|
@@ -81,11 +81,11 @@ export const chefAgent = new Agent({
|
|
|
81
81
|
instructions:
|
|
82
82
|
"You are Michel, a practical and experienced home chef. " +
|
|
83
83
|
"You help people cook with whatever ingredients they have available.",
|
|
84
|
-
model: "openai/gpt-5.
|
|
84
|
+
model: "openai/gpt-5.6-luna",
|
|
85
85
|
});
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
`model: "openai/gpt-5.
|
|
88
|
+
`model: "openai/gpt-5.6-luna"` uses Mastra's model router. Set the provider key in `.env.local` so Next.js auto-loads it:
|
|
89
89
|
|
|
90
90
|
```sh title=".env.local"
|
|
91
91
|
OPENAI_API_KEY=sk-...
|
|
@@ -50,7 +50,7 @@ export const chefAgent = new Agent({
|
|
|
50
50
|
instructions:
|
|
51
51
|
"You are Michel, a practical and experienced home chef. " +
|
|
52
52
|
"You help people cook with whatever ingredients they have available.",
|
|
53
|
-
model: "openai/gpt-5.
|
|
53
|
+
model: "openai/gpt-5.6-luna",
|
|
54
54
|
});
|
|
55
55
|
```
|
|
56
56
|
|
|
@@ -48,7 +48,7 @@ The rest of this page is what to put in `baseURL`, `headers`, and `model(...)` f
|
|
|
48
48
|
|
|
49
49
|
## OpenRouter
|
|
50
50
|
|
|
51
|
-
[OpenRouter](https://openrouter.ai/) aggregates 100+ models behind one OpenAI-compatible endpoint. The model ID is `provider/model` (e.g., `anthropic/claude-sonnet-4.6`, `openai/gpt-5.
|
|
51
|
+
[OpenRouter](https://openrouter.ai/) aggregates 100+ models behind one OpenAI-compatible endpoint. The model ID is `provider/model` (e.g., `anthropic/claude-sonnet-4.6`, `openai/gpt-5.6-luna`, `meta-llama/llama-3.3-70b-instruct`).
|
|
52
52
|
|
|
53
53
|
```sh title=".env.local"
|
|
54
54
|
OPENROUTER_API_KEY=sk-or-...
|
|
@@ -129,7 +129,7 @@ const litellm = createOpenAI({
|
|
|
129
129
|
});
|
|
130
130
|
|
|
131
131
|
const result = streamText({
|
|
132
|
-
model: litellm("gpt-5.
|
|
132
|
+
model: litellm("gpt-5.6-luna"),
|
|
133
133
|
messages: await convertToModelMessages(messages),
|
|
134
134
|
});
|
|
135
135
|
```
|
|
@@ -57,7 +57,7 @@ const openai = createOpenAI({
|
|
|
57
57
|
export async function POST(req: Request) {
|
|
58
58
|
const { messages }: { messages: UIMessage[] } = await req.json();
|
|
59
59
|
const result = streamText({
|
|
60
|
-
model: openai("gpt-5.
|
|
60
|
+
model: openai("gpt-5.6-luna"),
|
|
61
61
|
messages: await convertToModelMessages(messages),
|
|
62
62
|
});
|
|
63
63
|
return result.toUIMessageStreamResponse();
|
|
@@ -80,7 +80,7 @@ const openai = new OpenAI({
|
|
|
80
80
|
export async function POST(req: Request) {
|
|
81
81
|
const { messages } = await req.json();
|
|
82
82
|
const stream = await openai.chat.completions.create({
|
|
83
|
-
model: "gpt-5.
|
|
83
|
+
model: "gpt-5.6-luna",
|
|
84
84
|
messages,
|
|
85
85
|
stream: true,
|
|
86
86
|
});
|
|
@@ -101,7 +101,7 @@ export async function POST(req: Request) {
|
|
|
101
101
|
{ traceName: "chat-completion", userId, sessionId },
|
|
102
102
|
async () =>
|
|
103
103
|
streamText({
|
|
104
|
-
model: openai("gpt-5.
|
|
104
|
+
model: openai("gpt-5.6-luna"),
|
|
105
105
|
messages: await convertToModelMessages(messages),
|
|
106
106
|
experimental_telemetry: { isEnabled: true },
|
|
107
107
|
}),
|
|
@@ -35,7 +35,7 @@ LANGSMITH_API_KEY=lsv2_pt_...
|
|
|
35
35
|
LANGSMITH_PROJECT=assistant-ui
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
`LANGSMITH_PROJECT` controls which project receives traces; the default project applies if you omit it. See LangSmith's [
|
|
38
|
+
`LANGSMITH_PROJECT` controls which project receives traces; the default project applies if you omit it. See LangSmith's [project configuration guide](https://docs.langchain.com/langsmith/log-traces-to-project) for details.
|
|
39
39
|
|
|
40
40
|
</Step>
|
|
41
41
|
<Step>
|
|
@@ -63,7 +63,7 @@ export async function POST(req: Request) {
|
|
|
63
63
|
const { messages }: { messages: UIMessage[] } = await req.json();
|
|
64
64
|
|
|
65
65
|
const result = streamText({
|
|
66
|
-
model: openai("gpt-5.
|
|
66
|
+
model: openai("gpt-5.6-luna"),
|
|
67
67
|
messages: await ai.convertToModelMessages(messages),
|
|
68
68
|
});
|
|
69
69
|
|
|
@@ -84,7 +84,7 @@ Pass a `langsmith` provider option to tag traces with user, session, or run iden
|
|
|
84
84
|
import { createLangSmithProviderOptions } from "langsmith/experimental/vercel";
|
|
85
85
|
|
|
86
86
|
const result = streamText({
|
|
87
|
-
model: openai("gpt-5.
|
|
87
|
+
model: openai("gpt-5.6-luna"),
|
|
88
88
|
messages: await ai.convertToModelMessages(messages),
|
|
89
89
|
providerOptions: {
|
|
90
90
|
langsmith: createLangSmithProviderOptions({
|
|
@@ -305,7 +305,7 @@ export const threadListAdapter: RemoteThreadListAdapter = {
|
|
|
305
305
|
async append() {},
|
|
306
306
|
withFormat: (fmt) => ({
|
|
307
307
|
async load() {
|
|
308
|
-
const { remoteId } = aui.threadListItem
|
|
308
|
+
const { remoteId } = aui.threadListItem.getState();
|
|
309
309
|
if (!remoteId) return { messages: [] };
|
|
310
310
|
const rows = await fetch(
|
|
311
311
|
`/api/threads/${remoteId}/messages`,
|
|
@@ -322,7 +322,7 @@ export const threadListAdapter: RemoteThreadListAdapter = {
|
|
|
322
322
|
};
|
|
323
323
|
},
|
|
324
324
|
async append(item) {
|
|
325
|
-
const { remoteId } = await aui.threadListItem
|
|
325
|
+
const { remoteId } = await aui.threadListItem.initialize();
|
|
326
326
|
await fetch(`/api/threads/${remoteId}/messages`, {
|
|
327
327
|
method: "POST",
|
|
328
328
|
body: JSON.stringify({
|
|
@@ -422,7 +422,7 @@ export const threadListAdapter: RemoteThreadListAdapter = {
|
|
|
422
422
|
async append() {},
|
|
423
423
|
withFormat: (fmt) => ({
|
|
424
424
|
async load() {
|
|
425
|
-
const { remoteId } = aui.threadListItem
|
|
425
|
+
const { remoteId } = aui.threadListItem.getState();
|
|
426
426
|
if (!remoteId) return { messages: [] };
|
|
427
427
|
const rows = await fetch(
|
|
428
428
|
`${API_URL}/threads/${remoteId}/messages`,
|
|
@@ -439,7 +439,7 @@ export const threadListAdapter: RemoteThreadListAdapter = {
|
|
|
439
439
|
};
|
|
440
440
|
},
|
|
441
441
|
async append(item) {
|
|
442
|
-
const { remoteId } = await aui.threadListItem
|
|
442
|
+
const { remoteId } = await aui.threadListItem.initialize();
|
|
443
443
|
await fetch(`${API_URL}/threads/${remoteId}/messages`, {
|
|
444
444
|
method: "POST",
|
|
445
445
|
body: JSON.stringify({
|
|
@@ -541,7 +541,7 @@ export const threadListAdapter: RemoteThreadListAdapter = {
|
|
|
541
541
|
async append() {},
|
|
542
542
|
withFormat: (fmt) => ({
|
|
543
543
|
async load() {
|
|
544
|
-
const { remoteId } = aui.threadListItem
|
|
544
|
+
const { remoteId } = aui.threadListItem.getState();
|
|
545
545
|
if (!remoteId) return { messages: [] };
|
|
546
546
|
const rows = await fetch(
|
|
547
547
|
`${API_URL}/threads/${remoteId}/messages`,
|
|
@@ -558,7 +558,7 @@ export const threadListAdapter: RemoteThreadListAdapter = {
|
|
|
558
558
|
};
|
|
559
559
|
},
|
|
560
560
|
async append(item) {
|
|
561
|
-
const { remoteId } = await aui.threadListItem
|
|
561
|
+
const { remoteId } = await aui.threadListItem.initialize();
|
|
562
562
|
await fetch(`${API_URL}/threads/${remoteId}/messages`, {
|
|
563
563
|
method: "POST",
|
|
564
564
|
body: JSON.stringify({
|
|
@@ -592,6 +592,32 @@ The top-level `load`/`append` on the history adapter are required by the type bu
|
|
|
592
592
|
</Step>
|
|
593
593
|
<Step>
|
|
594
594
|
|
|
595
|
+
### Support in-place updates (optional)
|
|
596
|
+
|
|
597
|
+
The optional `update(item, localMessageId)` method on the object returned from `withFormat` lets the runtime rewrite an already-persisted message in place. It receives the same `{ parentId, message }` item shape as `append`, plus the id of the row to rewrite.
|
|
598
|
+
|
|
599
|
+
The runtime calls `update` after a run for persisted messages whose content changed, to finalize assistant messages persisted early while waiting for tool call approval, and to refresh run timing metadata.
|
|
600
|
+
|
|
601
|
+
`update` is opt-in. When it is absent, messages paused for tool approval are not persisted until the run reaches a terminal status, so a page refresh during the pause loses the pending approval state. Implementing `update` enables early persistence.
|
|
602
|
+
|
|
603
|
+
```tsx title="runtime/thread-adapter.tsx"
|
|
604
|
+
async update(item, localMessageId) {
|
|
605
|
+
const { remoteId } = await aui.threadListItem.initialize();
|
|
606
|
+
await fetch(`${API_URL}/threads/${remoteId}/messages/${localMessageId}`, {
|
|
607
|
+
method: "PATCH",
|
|
608
|
+
body: JSON.stringify({
|
|
609
|
+
format: fmt.format,
|
|
610
|
+
content: fmt.encode(item),
|
|
611
|
+
}),
|
|
612
|
+
});
|
|
613
|
+
},
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
The backend needs a matching update route keyed by message id, mirroring the append route from the earlier step.
|
|
617
|
+
|
|
618
|
+
</Step>
|
|
619
|
+
<Step>
|
|
620
|
+
|
|
595
621
|
### Mount the runtime
|
|
596
622
|
|
|
597
623
|
Wrap the app in a `useRemoteThreadListRuntime` that delegates per-thread runtime to `useChatRuntime`:
|
|
@@ -694,7 +720,7 @@ Send a message in a fresh thread. Check the database:
|
|
|
694
720
|
|
|
695
721
|
- The `threads` table has a new row with the current `userId`.
|
|
696
722
|
- The `messages` table has at least two rows (user + assistant) for that thread.
|
|
697
|
-
- `format` matches what `fmt.format` wrote (`"ai-sdk/v6"`
|
|
723
|
+
- `format` matches what `fmt.format` wrote (`"ai-sdk/v6"`) and `content` is the encoded `UIMessage` (a `role` plus `parts`), not a placeholder blob. The format string names the stored `UIMessage` shape, not the installed AI SDK major; it stays `"ai-sdk/v6"` on AI SDK v7 and must never be renamed, or previously stored history stops matching.
|
|
698
724
|
- Reload the page; the thread list and the messages survive.
|
|
699
725
|
|
|
700
726
|
</Step>
|
|
@@ -702,9 +728,10 @@ Send a message in a fresh thread. Check the database:
|
|
|
702
728
|
|
|
703
729
|
## Notes
|
|
704
730
|
|
|
705
|
-
- **First-message race.** `append` may fire before the thread row exists. The `unstable_Provider` example above always awaits `aui.threadListItem
|
|
706
|
-
- **Reload after async auth.** If `auth()` resolves after the initial `list()` call, threads won't appear until the user refreshes. Call `aui.threads
|
|
731
|
+
- **First-message race.** `append` may fire before the thread row exists. The `unstable_Provider` example above always awaits `aui.threadListItem.initialize()` before writing; do the same in any custom implementation.
|
|
732
|
+
- **Reload after async auth.** If `auth()` resolves after the initial `list()` call, threads won't appear until the user refreshes. Call `aui.threads.reload()` from a `useEffect` watching the session. Pattern is documented in [threads](/docs/runtimes/concepts/threads#reloading-after-async-authentication).
|
|
707
733
|
- **Format string.** The `format` column is *not* a free-text label; it identifies the on-disk shape so multiple runtimes can coexist. Don't strip it. Don't make assumptions about its value (`useChatRuntime` is responsible for setting and decoding it).
|
|
734
|
+
- **Pending approvals need `update`.** Tool call approvals persist across reloads only when the formatted adapter implements `update`; omitting it keeps the pre-approval snapshot out of storage by design.
|
|
708
735
|
- **`unstable_Provider` synchronous-children rule.** The Provider must render `children` on first commit; do not gate them behind suspense, loading state, or `useEffect`. Load data inside an always-rendered child.
|
|
709
736
|
|
|
710
737
|
## Related
|
|
@@ -73,20 +73,18 @@ export default defineToolkit({
|
|
|
73
73
|
|
|
74
74
|
import {
|
|
75
75
|
AssistantRuntimeProvider,
|
|
76
|
+
AuiConfig,
|
|
76
77
|
Tools,
|
|
77
|
-
useAui,
|
|
78
78
|
} from "@assistant-ui/react";
|
|
79
79
|
import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
|
|
80
80
|
import toolkit from "./toolkit";
|
|
81
81
|
|
|
82
82
|
export function App() {
|
|
83
83
|
const runtime = useChatRuntime();
|
|
84
|
-
const
|
|
85
|
-
tools: Tools({ toolkit }),
|
|
86
|
-
});
|
|
84
|
+
const config = AuiConfig({ tools: Tools({ toolkit }) });
|
|
87
85
|
|
|
88
86
|
return (
|
|
89
|
-
<AssistantRuntimeProvider
|
|
87
|
+
<AssistantRuntimeProvider runtime={runtime} config={config}>
|
|
90
88
|
<Thread />
|
|
91
89
|
</AssistantRuntimeProvider>
|
|
92
90
|
);
|
|
@@ -100,7 +98,7 @@ export function App() {
|
|
|
100
98
|
1. Create a `Toolkit` object.
|
|
101
99
|
2. Move each `toolName` into the toolkit key.
|
|
102
100
|
3. Move `description`, `parameters`, `execute`, `providerOptions`, `render`, `renderText`, and `display` onto the toolkit entry.
|
|
103
|
-
4. Register the toolkit once with `
|
|
101
|
+
4. Register the toolkit once with `config={config}` on your runtime provider, where `const config = AuiConfig({ tools: Tools({ toolkit }) })`.
|
|
104
102
|
5. Remove `<Tool />`, `<ToolUI />`, `useAssistantTool(...)`, and `useAssistantToolUI(...)` registrations.
|
|
105
103
|
|
|
106
104
|
## UI-Only Tool Renderers
|
|
@@ -126,7 +124,7 @@ export default defineToolkit({
|
|
|
126
124
|
});
|
|
127
125
|
```
|
|
128
126
|
|
|
129
|
-
Register it like any toolkit: `
|
|
127
|
+
Register it like any toolkit: `config={config}` where `const config = AuiConfig({ tools: Tools({ toolkit }) })`.
|
|
130
128
|
Render-only entries upload no schema and run no browser code — they only attach
|
|
131
129
|
UI for matching tool-call message parts. For MCP server catalogs, spread
|
|
132
130
|
`defineMcpToolkit({ ... })` in the same generative toolkit.
|
|
@@ -163,20 +161,24 @@ export default defineToolkit({
|
|
|
163
161
|
```
|
|
164
162
|
|
|
165
163
|
```tsx title="TaskBoard.tsx"
|
|
166
|
-
import {
|
|
164
|
+
import {
|
|
165
|
+
AuiConfig,
|
|
166
|
+
AuiProvider,
|
|
167
|
+
Tools,
|
|
168
|
+
useAui,
|
|
169
|
+
useAuiToolOverrides,
|
|
170
|
+
} from "@assistant-ui/react";
|
|
167
171
|
import { useState, type Dispatch, type SetStateAction } from "react";
|
|
168
172
|
import type { Task } from "./task-board-toolkit";
|
|
169
173
|
import toolkit from "./task-board-toolkit";
|
|
170
174
|
|
|
171
175
|
function TaskBoard() {
|
|
172
176
|
const [tasks, setTasks] = useState<Task[]>([]);
|
|
173
|
-
|
|
174
|
-
const
|
|
175
|
-
tools: Tools({ toolkit }),
|
|
176
|
-
});
|
|
177
|
+
const aui = useAui();
|
|
178
|
+
const config = AuiConfig({ tools: Tools({ toolkit }) });
|
|
177
179
|
|
|
178
180
|
return (
|
|
179
|
-
<AuiProvider
|
|
181
|
+
<AuiProvider extends={aui} config={config}>
|
|
180
182
|
<TaskBoardToolOverrides setTasks={setTasks} />
|
|
181
183
|
<TaskList tasks={tasks} />
|
|
182
184
|
</AuiProvider>
|