@assistant-ui/mcp-docs-server 0.1.22 → 0.1.23
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 +801 -0
- package/.docs/organized/code-examples/with-ag-ui.md +38 -26
- package/.docs/organized/code-examples/with-ai-sdk-v6.md +38 -28
- package/.docs/organized/code-examples/with-artifacts.md +467 -0
- package/.docs/organized/code-examples/with-assistant-transport.md +31 -24
- package/.docs/organized/code-examples/with-chain-of-thought.md +41 -32
- package/.docs/organized/code-examples/with-cloud-standalone.md +675 -0
- package/.docs/organized/code-examples/with-cloud.md +34 -27
- package/.docs/organized/code-examples/with-custom-thread-list.md +34 -27
- package/.docs/organized/code-examples/with-elevenlabs-scribe.md +41 -30
- package/.docs/organized/code-examples/with-expo.md +2031 -0
- package/.docs/organized/code-examples/with-external-store.md +32 -25
- package/.docs/organized/code-examples/with-ffmpeg.md +31 -27
- package/.docs/organized/code-examples/with-langgraph.md +96 -38
- package/.docs/organized/code-examples/with-parent-id-grouping.md +32 -25
- package/.docs/organized/code-examples/with-react-hook-form.md +63 -58
- package/.docs/organized/code-examples/with-react-router.md +38 -30
- package/.docs/organized/code-examples/with-store.md +16 -24
- package/.docs/organized/code-examples/with-tanstack.md +36 -26
- package/.docs/organized/code-examples/with-tap-runtime.md +10 -24
- package/.docs/raw/docs/(docs)/cli.mdx +13 -6
- package/.docs/raw/docs/(docs)/guides/attachments.mdx +26 -3
- package/.docs/raw/docs/(docs)/guides/chain-of-thought.mdx +5 -5
- package/.docs/raw/docs/(docs)/guides/context-api.mdx +53 -52
- package/.docs/raw/docs/(docs)/guides/dictation.mdx +0 -2
- package/.docs/raw/docs/(docs)/guides/message-timing.mdx +169 -0
- package/.docs/raw/docs/(docs)/guides/quoting.mdx +327 -0
- package/.docs/raw/docs/(docs)/guides/speech.mdx +0 -1
- package/.docs/raw/docs/(docs)/index.mdx +12 -2
- package/.docs/raw/docs/(docs)/installation.mdx +8 -2
- package/.docs/raw/docs/(docs)/llm.mdx +9 -7
- package/.docs/raw/docs/(reference)/api-reference/primitives/action-bar-more.mdx +1 -1
- package/.docs/raw/docs/(reference)/api-reference/primitives/action-bar.mdx +2 -2
- package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-if.mdx +27 -27
- package/.docs/raw/docs/(reference)/api-reference/primitives/composer.mdx +60 -0
- package/.docs/raw/docs/(reference)/api-reference/primitives/message-part.mdx +78 -4
- package/.docs/raw/docs/(reference)/api-reference/primitives/message.mdx +32 -0
- package/.docs/raw/docs/(reference)/api-reference/primitives/selection-toolbar.mdx +61 -0
- package/.docs/raw/docs/(reference)/api-reference/primitives/thread.mdx +1 -1
- package/.docs/raw/docs/(reference)/legacy/styled/assistant-modal.mdx +1 -6
- package/.docs/raw/docs/(reference)/legacy/styled/decomposition.mdx +2 -2
- package/.docs/raw/docs/(reference)/legacy/styled/markdown.mdx +1 -6
- package/.docs/raw/docs/(reference)/legacy/styled/thread.mdx +1 -5
- package/.docs/raw/docs/(reference)/migrations/v0-12.mdx +17 -17
- package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +205 -0
- package/.docs/raw/docs/cloud/ai-sdk.mdx +292 -0
- package/.docs/raw/docs/cloud/authorization.mdx +178 -79
- package/.docs/raw/docs/cloud/{persistence/langgraph.mdx → langgraph.mdx} +2 -2
- package/.docs/raw/docs/cloud/overview.mdx +29 -39
- package/.docs/raw/docs/react-native/adapters.mdx +118 -0
- package/.docs/raw/docs/react-native/custom-backend.mdx +210 -0
- package/.docs/raw/docs/react-native/hooks.mdx +364 -0
- package/.docs/raw/docs/react-native/index.mdx +332 -0
- package/.docs/raw/docs/react-native/primitives.mdx +653 -0
- package/.docs/raw/docs/runtimes/ai-sdk/v6.mdx +7 -15
- package/.docs/raw/docs/runtimes/assistant-transport.mdx +103 -0
- package/.docs/raw/docs/runtimes/custom/external-store.mdx +25 -2
- package/.docs/raw/docs/runtimes/data-stream.mdx +1 -3
- package/.docs/raw/docs/runtimes/langgraph/index.mdx +113 -9
- package/.docs/raw/docs/runtimes/pick-a-runtime.mdx +1 -4
- package/.docs/raw/docs/ui/attachment.mdx +4 -2
- package/.docs/raw/docs/ui/message-timing.mdx +92 -0
- package/.docs/raw/docs/ui/part-grouping.mdx +1 -1
- package/.docs/raw/docs/ui/reasoning.mdx +4 -4
- package/.docs/raw/docs/ui/scrollbar.mdx +2 -2
- package/.docs/raw/docs/ui/syntax-highlighting.mdx +55 -50
- package/.docs/raw/docs/ui/thread.mdx +16 -9
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/tools/tests/integration.test.ts +2 -2
- package/src/tools/tests/json-parsing.test.ts +1 -1
- package/src/tools/tests/mcp-protocol.test.ts +1 -3
- package/.docs/raw/docs/cloud/persistence/ai-sdk.mdx +0 -108
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "@/generated/typeDocs";
|
|
12
12
|
|
|
13
13
|
Each message can have any number of message parts.
|
|
14
|
-
Message parts are usually one of text, reasoning, audio
|
|
14
|
+
Message parts are usually one of text, reasoning, audio, tool-call, or data.
|
|
15
15
|
|
|
16
16
|
## Message part Types
|
|
17
17
|
|
|
@@ -31,6 +31,12 @@ Audio content that can be played back.
|
|
|
31
31
|
|
|
32
32
|
Interactive elements that represent tool operations.
|
|
33
33
|
|
|
34
|
+
### Data
|
|
35
|
+
|
|
36
|
+
Custom data events that can be rendered as UI at their position in the message stream. Each data part has a `name` and a `data` payload.
|
|
37
|
+
|
|
38
|
+
You can use either the explicit format `{ type: "data", name: "workflow", data: {...} }` or the shorthand `data-*` prefixed format `{ type: "data-workflow", data: {...} }`. The prefixed format is automatically converted to a `DataMessagePart` (stripping the `data-` prefix as the `name`). Unknown message part types that don't match any built-in type are silently skipped with a console warning.
|
|
39
|
+
|
|
34
40
|
## Anatomy
|
|
35
41
|
|
|
36
42
|
```tsx
|
|
@@ -46,7 +52,7 @@ const TextMessagePart = () => {
|
|
|
46
52
|
### Plain Text
|
|
47
53
|
|
|
48
54
|
```tsx
|
|
49
|
-
import { MessagePartPrimitive } from "@assistant/react";
|
|
55
|
+
import { MessagePartPrimitive } from "@assistant-ui/react";
|
|
50
56
|
|
|
51
57
|
<MessagePartPrimitive.Text />;
|
|
52
58
|
```
|
|
@@ -70,7 +76,7 @@ Coming soon.
|
|
|
70
76
|
Renders children only if the message part is in progress.
|
|
71
77
|
|
|
72
78
|
```tsx
|
|
73
|
-
import { MessagePartPrimitive } from "@assistant/react";
|
|
79
|
+
import { MessagePartPrimitive } from "@assistant-ui/react";
|
|
74
80
|
|
|
75
81
|
<MessagePartPrimitive.InProgress>
|
|
76
82
|
<LoadingIndicator />
|
|
@@ -101,6 +107,68 @@ const MyWeatherToolUI = makeAssistantToolUI({
|
|
|
101
107
|
});
|
|
102
108
|
```
|
|
103
109
|
|
|
110
|
+
### Data UI
|
|
111
|
+
|
|
112
|
+
You can map data events to UI components, similar to tool UIs. There are two approaches:
|
|
113
|
+
|
|
114
|
+
#### Inline configuration
|
|
115
|
+
|
|
116
|
+
Pass a `data` config to `MessagePrimitive.Parts`:
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
<MessagePrimitive.Parts
|
|
120
|
+
components={{
|
|
121
|
+
data: {
|
|
122
|
+
by_name: {
|
|
123
|
+
my_chart: ({ name, data }) => <ChartComponent data={data} />,
|
|
124
|
+
},
|
|
125
|
+
Fallback: ({ name, data }) => (
|
|
126
|
+
<pre>{JSON.stringify(data, null, 2)}</pre>
|
|
127
|
+
),
|
|
128
|
+
},
|
|
129
|
+
}}
|
|
130
|
+
/>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
#### Global registration
|
|
134
|
+
|
|
135
|
+
Use `makeAssistantDataUI` or `useAssistantDataUI` to register data UIs globally. Global registrations take priority over inline configuration.
|
|
136
|
+
|
|
137
|
+
```tsx
|
|
138
|
+
import { makeAssistantDataUI } from "@assistant-ui/react";
|
|
139
|
+
|
|
140
|
+
const MyChartUI = makeAssistantDataUI({
|
|
141
|
+
name: "my_chart",
|
|
142
|
+
render: ({ name, data }) => <ChartComponent data={data} />,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// Place inside AssistantRuntimeProvider
|
|
146
|
+
function App() {
|
|
147
|
+
return (
|
|
148
|
+
<AssistantRuntimeProvider runtime={runtime}>
|
|
149
|
+
<Thread />
|
|
150
|
+
<MyChartUI />
|
|
151
|
+
</AssistantRuntimeProvider>
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The hook variant allows access to component state:
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
import { useAssistantDataUI } from "@assistant-ui/react";
|
|
160
|
+
|
|
161
|
+
function MyComponent() {
|
|
162
|
+
useAssistantDataUI({
|
|
163
|
+
name: "my_chart",
|
|
164
|
+
render: ({ name, data }) => <ChartComponent data={data} />,
|
|
165
|
+
});
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Each data component receives the full data part as props: `{ type: "data", name: string, data: T, status: MessagePartStatus }`.
|
|
171
|
+
|
|
104
172
|
## Context Provider
|
|
105
173
|
|
|
106
174
|
Message part context is provided by `MessagePrimitive.Parts` or `TextMessagePartProvider`
|
|
@@ -108,7 +176,7 @@ Message part context is provided by `MessagePrimitive.Parts` or `TextMessagePart
|
|
|
108
176
|
### MessagePrimitive.Parts
|
|
109
177
|
|
|
110
178
|
```tsx
|
|
111
|
-
import { MessagePrimitive } from "@assistant/react";
|
|
179
|
+
import { MessagePrimitive } from "@assistant-ui/react";
|
|
112
180
|
|
|
113
181
|
<MessagePrimitive.Parts
|
|
114
182
|
components={{
|
|
@@ -121,6 +189,12 @@ import { MessagePrimitive } from "@assistant/react";
|
|
|
121
189
|
},
|
|
122
190
|
Fallback: MyFallbackToolUI,
|
|
123
191
|
},
|
|
192
|
+
data: {
|
|
193
|
+
by_name: {
|
|
194
|
+
my_chart: MyChartComponent,
|
|
195
|
+
},
|
|
196
|
+
Fallback: GenericDataComponent,
|
|
197
|
+
},
|
|
124
198
|
}}
|
|
125
199
|
/>;
|
|
126
200
|
```
|
|
@@ -259,6 +259,38 @@ Renders a single attachment at the specified index within the message.
|
|
|
259
259
|
]}
|
|
260
260
|
/>
|
|
261
261
|
|
|
262
|
+
### useMessageQuote()
|
|
263
|
+
|
|
264
|
+
A hook that returns the quote info attached to the current message, if any. Reads from `message.metadata.custom.quote`.
|
|
265
|
+
|
|
266
|
+
```tsx
|
|
267
|
+
import { useMessageQuote } from "@assistant-ui/react";
|
|
268
|
+
|
|
269
|
+
const QuoteBlock = () => {
|
|
270
|
+
const quote = useMessageQuote();
|
|
271
|
+
if (!quote) return null;
|
|
272
|
+
|
|
273
|
+
return (
|
|
274
|
+
<div className="mb-2 flex items-start gap-1.5 text-sm italic text-muted-foreground">
|
|
275
|
+
{quote.text}
|
|
276
|
+
</div>
|
|
277
|
+
);
|
|
278
|
+
};
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
**Returns:** `QuoteInfo | undefined`
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
type QuoteInfo = {
|
|
285
|
+
readonly text: string; // the quoted plain text
|
|
286
|
+
readonly messageId: string; // the source message ID
|
|
287
|
+
};
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
<Callout type="info">
|
|
291
|
+
See the [Quoting guide](/docs/guides/quoting) for a complete walkthrough.
|
|
292
|
+
</Callout>
|
|
293
|
+
|
|
262
294
|
### Error
|
|
263
295
|
|
|
264
296
|
Renders children only if the message has an error status.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: SelectionToolbarPrimitive
|
|
3
|
+
description: A floating toolbar that appears when text is selected within a message.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
A floating toolbar that appears near the user's text selection within a message. Used to provide contextual actions like quoting selected text.
|
|
7
|
+
|
|
8
|
+
## Anatomy
|
|
9
|
+
|
|
10
|
+
```tsx
|
|
11
|
+
import { SelectionToolbarPrimitive } from "@assistant-ui/react";
|
|
12
|
+
|
|
13
|
+
const FloatingSelectionToolbar = () => (
|
|
14
|
+
<SelectionToolbarPrimitive.Root>
|
|
15
|
+
<SelectionToolbarPrimitive.Quote>Quote</SelectionToolbarPrimitive.Quote>
|
|
16
|
+
</SelectionToolbarPrimitive.Root>
|
|
17
|
+
);
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Place this component inside `ThreadPrimitive.Root`:
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
<ThreadPrimitive.Root>
|
|
24
|
+
<ThreadPrimitive.Viewport>...</ThreadPrimitive.Viewport>
|
|
25
|
+
<FloatingSelectionToolbar />
|
|
26
|
+
</ThreadPrimitive.Root>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## API Reference
|
|
30
|
+
|
|
31
|
+
### Root
|
|
32
|
+
|
|
33
|
+
A floating container that renders as a portal positioned above the text selection. Only renders when there is a valid text selection within a single message.
|
|
34
|
+
|
|
35
|
+
This primitive renders a `<div>` element.
|
|
36
|
+
|
|
37
|
+
**Behavior:**
|
|
38
|
+
|
|
39
|
+
- Listens for `mouseup` and `keyup` events to detect completed selections
|
|
40
|
+
- Validates the selection is within a single message using `data-message-id` attributes
|
|
41
|
+
- Renders a portal with `position: fixed`, centered above the selection
|
|
42
|
+
- Prevents `mousedown` from clearing the text selection when clicking the toolbar
|
|
43
|
+
- Hides automatically on scroll or when the selection is cleared
|
|
44
|
+
- Cross-message selections are ignored
|
|
45
|
+
|
|
46
|
+
### Quote
|
|
47
|
+
|
|
48
|
+
A button that captures the currently selected text and sets it as a quote in the thread composer.
|
|
49
|
+
|
|
50
|
+
This primitive renders a `<button>` element.
|
|
51
|
+
|
|
52
|
+
**Behavior:**
|
|
53
|
+
|
|
54
|
+
- Reads selection info from the Root context (not `window.getSelection()`)
|
|
55
|
+
- Calls `composer.setQuote({ text, messageId })` on the thread composer
|
|
56
|
+
- Clears the text selection after quoting
|
|
57
|
+
- Disabled when no selection info is available
|
|
58
|
+
|
|
59
|
+
<Callout type="info">
|
|
60
|
+
See the [Quoting guide](/docs/guides/quoting) for a complete walkthrough including composer preview, sent message display, and backend handling.
|
|
61
|
+
</Callout>
|
|
@@ -14,7 +14,7 @@ import { ThreadPrimitive } from "@assistant-ui/react";
|
|
|
14
14
|
const Thread = () => (
|
|
15
15
|
<ThreadPrimitive.Root>
|
|
16
16
|
<ThreadPrimitive.Viewport>
|
|
17
|
-
<
|
|
17
|
+
<AuiIf condition={(s) => s.thread.isEmpty}>...</AuiIf>
|
|
18
18
|
<ThreadPrimitive.Messages components={...} />
|
|
19
19
|
</ThreadPrimitive.Viewport>
|
|
20
20
|
<Composer />
|
|
@@ -24,7 +24,7 @@ A chat bubble shown in the bottom right corner of the screen. Useful for support
|
|
|
24
24
|
|
|
25
25
|
Add the following to your `tailwind.config.ts`:
|
|
26
26
|
|
|
27
|
-
<Tabs items={["Tailwind", "Tailwind + shadcn-ui"
|
|
27
|
+
<Tabs items={["Tailwind", "Tailwind + shadcn-ui"]}>
|
|
28
28
|
|
|
29
29
|
```ts title="/tailwind.config.ts" tab="Tailwind"
|
|
30
30
|
{
|
|
@@ -49,11 +49,6 @@ Add the following to your `tailwind.config.ts`:
|
|
|
49
49
|
}
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
```ts title="/app/layout.tsx" tab="Not using Tailwind"
|
|
53
|
-
import "@assistant-ui/react-ui/styles/index.css";
|
|
54
|
-
import "@assistant-ui/react-ui/styles/modal.css";
|
|
55
|
-
```
|
|
56
|
-
|
|
57
52
|
</Tabs>
|
|
58
53
|
|
|
59
54
|
</Step>
|
|
@@ -181,10 +181,10 @@ import { AuiIf } from "@assistant-ui/react";
|
|
|
181
181
|
const MyComposerAction: FC = () => {
|
|
182
182
|
return (
|
|
183
183
|
<>
|
|
184
|
-
<AuiIf condition={(
|
|
184
|
+
<AuiIf condition={(s) => !s.thread.isRunning}>
|
|
185
185
|
<Composer.Send />
|
|
186
186
|
</AuiIf>
|
|
187
|
-
<AuiIf condition={(
|
|
187
|
+
<AuiIf condition={(s) => s.thread.isRunning}>
|
|
188
188
|
<Composer.Cancel />
|
|
189
189
|
</AuiIf>
|
|
190
190
|
</>
|
|
@@ -20,7 +20,7 @@ Allow the assistant to display rich text using markdown.
|
|
|
20
20
|
|
|
21
21
|
### Setup styles
|
|
22
22
|
|
|
23
|
-
<Tabs items={["Tailwind", "Tailwind + shadcn-ui"
|
|
23
|
+
<Tabs items={["Tailwind", "Tailwind + shadcn-ui"]}>
|
|
24
24
|
|
|
25
25
|
```ts {3} title="/tailwind.config.ts" tab="Tailwind"
|
|
26
26
|
{
|
|
@@ -40,11 +40,6 @@ Allow the assistant to display rich text using markdown.
|
|
|
40
40
|
}
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
```ts title="/app/layout.tsx" tab="Not using Tailwind"
|
|
44
|
-
import "@assistant-ui/react-ui/styles/index.css";
|
|
45
|
-
import "@assistant-ui/react-ui/styles/markdown.css";
|
|
46
|
-
```
|
|
47
|
-
|
|
48
43
|
</Tabs>
|
|
49
44
|
|
|
50
45
|
</Step>
|
|
@@ -24,7 +24,7 @@ The raw message list and message composer UI. Useful for full screen chat use ca
|
|
|
24
24
|
|
|
25
25
|
Add the following to your `tailwind.config.ts`:
|
|
26
26
|
|
|
27
|
-
<Tabs items={["Tailwind", "Tailwind + shadcn-ui"
|
|
27
|
+
<Tabs items={["Tailwind", "Tailwind + shadcn-ui"]}>
|
|
28
28
|
|
|
29
29
|
```ts title="/tailwind.config.ts" tab="Tailwind"
|
|
30
30
|
{
|
|
@@ -49,10 +49,6 @@ Add the following to your `tailwind.config.ts`:
|
|
|
49
49
|
}
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
```ts title="/app/layout.tsx" tab="Not using Tailwind"
|
|
53
|
-
import "@assistant-ui/react-ui/styles/index.css";
|
|
54
|
-
```
|
|
55
|
-
|
|
56
52
|
</Tabs>
|
|
57
53
|
|
|
58
54
|
</Step>
|
|
@@ -63,7 +63,7 @@ import { useAui, useAuiState, useAuiEvent } from "@assistant-ui/react";
|
|
|
63
63
|
|
|
64
64
|
function MyComponent() {
|
|
65
65
|
const aui = useAui();
|
|
66
|
-
const isRunning = useAuiState((
|
|
66
|
+
const isRunning = useAuiState((s) => s.thread.isRunning);
|
|
67
67
|
|
|
68
68
|
useAuiEvent("thread.started", () => {
|
|
69
69
|
console.log("Thread started");
|
|
@@ -116,30 +116,30 @@ The following hooks have been removed:
|
|
|
116
116
|
|
|
117
117
|
**Removed Hooks:**
|
|
118
118
|
|
|
119
|
-
- `useMessageUtils` → Use `useAuiState((
|
|
119
|
+
- `useMessageUtils` → Use `useAuiState((s) => s.message.isHovering)` / `useAuiState((s) => s.message.isCopied)`
|
|
120
120
|
- `useMessageUtilsStore` → Use `useAui()` with `aui.message().setIsHovering()` / `aui.message().setIsCopied()`
|
|
121
|
-
- `useToolUIs` → Use `useAuiState((
|
|
121
|
+
- `useToolUIs` → Use `useAuiState((s) => s.tools)` and `useAui()` with `aui.tools()`
|
|
122
122
|
- `useToolUIsStore` → Use `useAui()` with `aui.tools()`
|
|
123
123
|
|
|
124
124
|
**Deprecated Hooks:**
|
|
125
125
|
|
|
126
126
|
- `useAssistantRuntime` → Use `useAui()`
|
|
127
|
-
- `useThread` → Use `useAuiState((
|
|
127
|
+
- `useThread` → Use `useAuiState((s) => s.thread)`
|
|
128
128
|
- `useThreadRuntime` → Use `useAui()` with `aui.thread()`
|
|
129
|
-
- `useMessage` → Use `useAuiState((
|
|
129
|
+
- `useMessage` → Use `useAuiState((s) => s.message)`
|
|
130
130
|
- `useMessageRuntime` → Use `useAui()` with `aui.message()`
|
|
131
|
-
- `useComposer` → Use `useAuiState((
|
|
131
|
+
- `useComposer` → Use `useAuiState((s) => s.composer)`
|
|
132
132
|
- `useComposerRuntime` → Use `useAui()` with `aui.composer()`
|
|
133
|
-
- `useEditComposer` → Use `useAuiState((
|
|
134
|
-
- `useThreadListItem` → Use `useAuiState((
|
|
133
|
+
- `useEditComposer` → Use `useAuiState((s) => s.message.composer)`
|
|
134
|
+
- `useThreadListItem` → Use `useAuiState((s) => s.threadListItem)`
|
|
135
135
|
- `useThreadListItemRuntime` → Use `useAui()` with `aui.threadListItem()`
|
|
136
|
-
- `useMessagePart` → Use `useAuiState((
|
|
136
|
+
- `useMessagePart` → Use `useAuiState((s) => s.part)`
|
|
137
137
|
- `useMessagePartRuntime` → Use `useAui()` with `aui.part()`
|
|
138
|
-
- `useAttachment` → Use `useAuiState((
|
|
138
|
+
- `useAttachment` → Use `useAuiState((s) => s.attachment)`
|
|
139
139
|
- `useAttachmentRuntime` → Use `useAui()` with `aui.attachment()`
|
|
140
|
-
- `useThreadModelContext` / `useThreadModelConfig` → Use `useAuiState((
|
|
141
|
-
- `useThreadComposer` → Use `useAuiState((
|
|
142
|
-
- `useThreadList` → Use `useAuiState((
|
|
140
|
+
- `useThreadModelContext` / `useThreadModelConfig` → Use `useAuiState((s) => s.thread.modelContext)`
|
|
141
|
+
- `useThreadComposer` → Use `useAuiState((s) => s.thread.composer)`
|
|
142
|
+
- `useThreadList` → Use `useAuiState((s) => s.threads)`
|
|
143
143
|
|
|
144
144
|
#### Migration Examples
|
|
145
145
|
|
|
@@ -190,10 +190,10 @@ import { useAuiState, useAui } from "@assistant-ui/react";
|
|
|
190
190
|
|
|
191
191
|
function MyComponent() {
|
|
192
192
|
// Reading state - all through single hook
|
|
193
|
-
const messages = useAuiState((
|
|
194
|
-
const isRunning = useAuiState((
|
|
195
|
-
const composerText = useAuiState((
|
|
196
|
-
const messageRole = useAuiState((
|
|
193
|
+
const messages = useAuiState((s) => s.thread.messages);
|
|
194
|
+
const isRunning = useAuiState((s) => s.thread.isRunning);
|
|
195
|
+
const composerText = useAuiState((s) => s.composer.text);
|
|
196
|
+
const messageRole = useAuiState((s) => s.message.role);
|
|
197
197
|
|
|
198
198
|
// Using client for actions
|
|
199
199
|
const aui = useAui();
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: AI SDK + assistant-ui
|
|
3
|
+
description: Integrate cloud persistence using assistant-ui runtime and pre-built components.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
This guide shows how to integrate Assistant Cloud with the [AI SDK](https://sdk.vercel.ai/) using assistant-ui's runtime system and pre-built UI components.
|
|
10
|
+
|
|
11
|
+
## What You Get
|
|
12
|
+
|
|
13
|
+
This integration provides:
|
|
14
|
+
|
|
15
|
+
- **`<Thread />`** — A complete chat interface with messages, composer, and status indicators
|
|
16
|
+
- **`<ThreadList />`** — A sidebar showing all conversations with auto-generated titles, plus new/delete/manage actions
|
|
17
|
+
- **Automatic Persistence** — Messages save as they stream. Threads are created automatically on first message.
|
|
18
|
+
- **Runtime Integration** — The assistant-ui runtime handles all cloud synchronization behind the scenes.
|
|
19
|
+
|
|
20
|
+
## How It Works
|
|
21
|
+
|
|
22
|
+
The `useChatRuntime` hook from `@assistant-ui/react-ai-sdk` wraps AI SDK's `useChat` and adds cloud persistence via the `cloud` parameter. The runtime automatically:
|
|
23
|
+
|
|
24
|
+
1. Creates a cloud thread on the first user message
|
|
25
|
+
2. Persists messages as they complete streaming
|
|
26
|
+
3. Generates a conversation title after the assistant's first response
|
|
27
|
+
4. Loads historical messages when switching threads via `<ThreadList />`
|
|
28
|
+
|
|
29
|
+
You provide the AI SDK endpoint (`api: "/api/chat"`) and the cloud configuration—everything else is handled.
|
|
30
|
+
|
|
31
|
+
## Prerequisites
|
|
32
|
+
|
|
33
|
+
<Callout type="info">
|
|
34
|
+
You need an assistant-cloud account to follow this guide. [Sign up here](https://cloud.assistant-ui.com/) to get started.
|
|
35
|
+
</Callout>
|
|
36
|
+
|
|
37
|
+
## Setup Guide
|
|
38
|
+
|
|
39
|
+
<Steps>
|
|
40
|
+
|
|
41
|
+
<Step>
|
|
42
|
+
|
|
43
|
+
### Create a Cloud Project
|
|
44
|
+
|
|
45
|
+
Create a new project in the [assistant-cloud dashboard](https://cloud.assistant-ui.com/) and from the settings page, copy:
|
|
46
|
+
|
|
47
|
+
- **Frontend API URL**: `https://proj-[ID].assistant-api.com`
|
|
48
|
+
- **Assistant Cloud API Key**: `sk_aui_proj_*`
|
|
49
|
+
|
|
50
|
+
</Step>
|
|
51
|
+
|
|
52
|
+
<Step>
|
|
53
|
+
|
|
54
|
+
### Configure Environment Variables
|
|
55
|
+
|
|
56
|
+
Add the following environment variables to your project:
|
|
57
|
+
|
|
58
|
+
```bash title=".env.local"
|
|
59
|
+
# Frontend API URL from your cloud project settings
|
|
60
|
+
NEXT_PUBLIC_ASSISTANT_BASE_URL=https://proj-[YOUR-ID].assistant-api.com
|
|
61
|
+
|
|
62
|
+
# API key for server-side operations
|
|
63
|
+
ASSISTANT_API_KEY=your-api-key-here
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
</Step>
|
|
67
|
+
|
|
68
|
+
<Step>
|
|
69
|
+
|
|
70
|
+
### Install Dependencies
|
|
71
|
+
|
|
72
|
+
Install the required packages:
|
|
73
|
+
|
|
74
|
+
<InstallCommand npm={["@assistant-ui/react", "@assistant-ui/react-ai-sdk"]} />
|
|
75
|
+
|
|
76
|
+
</Step>
|
|
77
|
+
|
|
78
|
+
<Step>
|
|
79
|
+
|
|
80
|
+
### Set Up the Cloud Runtime
|
|
81
|
+
|
|
82
|
+
Create a client-side AssistantCloud instance and integrate it with your AI SDK runtime:
|
|
83
|
+
|
|
84
|
+
```tsx title="app/chat/page.tsx"
|
|
85
|
+
"use client";
|
|
86
|
+
|
|
87
|
+
import { AssistantCloud, AssistantRuntimeProvider } from "@assistant-ui/react";
|
|
88
|
+
import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
|
|
89
|
+
import { ThreadList } from "@/components/assistant-ui/thread-list";
|
|
90
|
+
import { Thread } from "@/components/assistant-ui/thread";
|
|
91
|
+
|
|
92
|
+
export default function ChatPage() {
|
|
93
|
+
const cloud = new AssistantCloud({
|
|
94
|
+
baseUrl: process.env.NEXT_PUBLIC_ASSISTANT_BASE_URL!,
|
|
95
|
+
anonymous: true, // Creates browser-session based user ID
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const runtime = useChatRuntime({
|
|
99
|
+
cloud,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<AssistantRuntimeProvider runtime={runtime}>
|
|
104
|
+
<div className="grid h-dvh grid-cols-[200px_1fr] gap-x-2 px-4 py-4">
|
|
105
|
+
<ThreadList />
|
|
106
|
+
<Thread />
|
|
107
|
+
</div>
|
|
108
|
+
</AssistantRuntimeProvider>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
</Step>
|
|
114
|
+
|
|
115
|
+
</Steps>
|
|
116
|
+
|
|
117
|
+
## Telemetry
|
|
118
|
+
|
|
119
|
+
The `useChatRuntime` hook captures full run telemetry including timing data. This integrates with the assistant-ui runtime to provide:
|
|
120
|
+
|
|
121
|
+
**Automatically captured:**
|
|
122
|
+
- `status` — `"completed"`, `"incomplete"`, or `"error"`
|
|
123
|
+
- `duration_ms` — Total run duration (measured client-side)
|
|
124
|
+
- `steps` — Per-step breakdowns with timing, usage, and tool calls
|
|
125
|
+
- `tool_calls` — Tool invocations with name, arguments, results, and source
|
|
126
|
+
- `total_steps` — Number of reasoning/tool steps
|
|
127
|
+
- `output_text` — Full response text (truncated at 50K characters)
|
|
128
|
+
|
|
129
|
+
**Requires route configuration:**
|
|
130
|
+
- `model_id` — The model used
|
|
131
|
+
- `input_tokens` / `output_tokens` — Token usage statistics
|
|
132
|
+
|
|
133
|
+
To capture model and usage data, add the `messageMetadata` callback to your AI SDK route:
|
|
134
|
+
|
|
135
|
+
```tsx title="app/api/chat/route.ts"
|
|
136
|
+
import { streamText } from "ai";
|
|
137
|
+
|
|
138
|
+
export async function POST(req: Request) {
|
|
139
|
+
const result = streamText({
|
|
140
|
+
model: openai("gpt-5-mini"),
|
|
141
|
+
messages,
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
return result.toUIMessageStreamResponse({
|
|
145
|
+
messageMetadata: ({ part }) => {
|
|
146
|
+
if (part.type === "finish-step") {
|
|
147
|
+
return {
|
|
148
|
+
modelId: part.response.modelId,
|
|
149
|
+
usage: part.usage,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
return undefined;
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Without this configuration, model and token data will be omitted from telemetry reports.
|
|
159
|
+
|
|
160
|
+
### Customizing Reports
|
|
161
|
+
|
|
162
|
+
Use the `beforeReport` hook to add custom metadata or filter reports:
|
|
163
|
+
|
|
164
|
+
```tsx
|
|
165
|
+
const cloud = new AssistantCloud({
|
|
166
|
+
baseUrl: process.env.NEXT_PUBLIC_ASSISTANT_BASE_URL!,
|
|
167
|
+
telemetry: {
|
|
168
|
+
beforeReport: (report) => ({
|
|
169
|
+
...report,
|
|
170
|
+
metadata: { userTier: "pro", region: "us-east" },
|
|
171
|
+
}),
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Return `null` from `beforeReport` to skip reporting a specific run. To disable telemetry entirely, pass `telemetry: false`.
|
|
177
|
+
|
|
178
|
+
## Authentication
|
|
179
|
+
|
|
180
|
+
The example above uses anonymous mode (browser session-based user ID) via the env var. For production apps with user accounts, pass an explicit cloud instance:
|
|
181
|
+
|
|
182
|
+
```tsx
|
|
183
|
+
import { useAuth } from "@clerk/nextjs";
|
|
184
|
+
import { AssistantCloud } from "@assistant-ui/react";
|
|
185
|
+
import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
|
|
186
|
+
|
|
187
|
+
function Chat() {
|
|
188
|
+
const { getToken } = useAuth();
|
|
189
|
+
|
|
190
|
+
const cloud = useMemo(() => new AssistantCloud({
|
|
191
|
+
baseUrl: process.env.NEXT_PUBLIC_ASSISTANT_BASE_URL!,
|
|
192
|
+
authToken: async () => getToken({ template: "assistant-ui" }),
|
|
193
|
+
}), [getToken]);
|
|
194
|
+
|
|
195
|
+
const runtime = useChatRuntime({ cloud });
|
|
196
|
+
// ...
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
See the [Cloud Authorization](/docs/cloud/authorization) guide for other auth providers.
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
## Complete Example
|
|
204
|
+
|
|
205
|
+
Check out the [with-cloud example](https://github.com/assistant-ui/assistant-ui/tree/main/examples/with-cloud) on GitHub for a fully working implementation.
|