@assistant-ui/mcp-docs-server 0.1.24 → 0.1.25
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 +4 -2
- package/.docs/organized/code-examples/with-a2a.md +676 -0
- package/.docs/organized/code-examples/with-ag-ui.md +5 -6
- package/.docs/organized/code-examples/with-ai-sdk-v6.md +27 -15
- package/.docs/organized/code-examples/with-artifacts.md +4 -4
- package/.docs/organized/code-examples/with-assistant-transport.md +2 -2
- package/.docs/organized/code-examples/with-chain-of-thought.md +33 -25
- package/.docs/organized/code-examples/with-cloud-standalone.md +9 -6
- package/.docs/organized/code-examples/with-cloud.md +4 -4
- package/.docs/organized/code-examples/with-custom-thread-list.md +6 -6
- package/.docs/organized/code-examples/with-elevenlabs-scribe.md +7 -7
- package/.docs/organized/code-examples/with-expo.md +565 -514
- package/.docs/organized/code-examples/with-external-store.md +2 -2
- package/.docs/organized/code-examples/with-ffmpeg.md +4 -4
- package/.docs/organized/code-examples/with-google-adk.md +353 -0
- package/.docs/organized/code-examples/with-heat-graph.md +304 -0
- package/.docs/organized/code-examples/with-langgraph.md +24 -22
- package/.docs/organized/code-examples/with-parent-id-grouping.md +3 -3
- package/.docs/organized/code-examples/with-react-hook-form.md +4 -4
- package/.docs/organized/code-examples/with-react-ink.md +265 -0
- package/.docs/organized/code-examples/with-react-router.md +5 -5
- package/.docs/organized/code-examples/with-store.md +28 -17
- package/.docs/organized/code-examples/with-tanstack.md +7 -7
- package/.docs/organized/code-examples/with-tap-runtime.md +5 -3
- package/.docs/raw/blog/2025-01-31-changelog/index.mdx +1 -1
- package/.docs/raw/blog/2026-03-launch-week/index.mdx +227 -0
- package/.docs/raw/docs/(docs)/architecture.mdx +1 -1
- package/.docs/raw/docs/(docs)/cli.mdx +14 -9
- package/.docs/raw/docs/(docs)/copilots/make-assistant-tool-ui.mdx +8 -3
- package/.docs/raw/docs/(docs)/copilots/make-assistant-tool.mdx +5 -1
- package/.docs/raw/docs/(docs)/copilots/{make-assistant-readable.mdx → make-assistant-visible.mdx} +14 -5
- package/.docs/raw/docs/(docs)/copilots/model-context.mdx +11 -11
- package/.docs/raw/docs/(docs)/copilots/motivation.mdx +2 -2
- package/.docs/raw/docs/(docs)/devtools.mdx +3 -2
- package/.docs/raw/docs/(docs)/guides/attachments.mdx +9 -11
- package/.docs/raw/docs/(docs)/guides/branching.mdx +11 -6
- package/.docs/raw/docs/(docs)/guides/chain-of-thought.mdx +18 -16
- package/.docs/raw/docs/(docs)/guides/context-api.mdx +81 -43
- package/.docs/raw/docs/(docs)/guides/dictation.mdx +5 -5
- package/.docs/raw/docs/(docs)/guides/editing.mdx +16 -7
- package/.docs/raw/docs/(docs)/guides/latex.mdx +3 -0
- package/.docs/raw/docs/(docs)/guides/message-timing.mdx +2 -1
- package/.docs/raw/docs/(docs)/guides/multi-agent.mdx +173 -0
- package/.docs/raw/docs/(docs)/guides/quoting.mdx +55 -206
- package/.docs/raw/docs/(docs)/guides/speech.mdx +1 -4
- package/.docs/raw/docs/(docs)/guides/suggestions.mdx +9 -15
- package/.docs/raw/docs/(docs)/guides/tool-ui.mdx +17 -7
- package/.docs/raw/docs/(docs)/guides/tools.mdx +24 -9
- package/.docs/raw/docs/(docs)/index.mdx +3 -3
- package/.docs/raw/docs/(docs)/installation.mdx +69 -46
- package/.docs/raw/docs/(reference)/api-reference/context-providers/text-message-part-provider.mdx +20 -6
- package/.docs/raw/docs/(reference)/api-reference/integrations/react-data-stream.mdx +24 -4
- package/.docs/raw/docs/(reference)/api-reference/integrations/react-hook-form.mdx +1 -1
- package/.docs/raw/docs/(reference)/api-reference/integrations/vercel-ai-sdk.mdx +20 -19
- package/.docs/raw/docs/(reference)/api-reference/overview.mdx +28 -53
- package/.docs/raw/docs/(reference)/api-reference/primitives/action-bar.mdx +4 -4
- package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-modal.mdx +7 -1
- package/.docs/raw/docs/(reference)/api-reference/primitives/attachment.mdx +20 -14
- package/.docs/raw/docs/(reference)/api-reference/primitives/branch-picker.mdx +1 -1
- package/.docs/raw/docs/(reference)/api-reference/primitives/composer.mdx +99 -45
- package/.docs/raw/docs/(reference)/api-reference/primitives/message-part.mdx +52 -40
- package/.docs/raw/docs/(reference)/api-reference/primitives/message.mdx +343 -23
- package/.docs/raw/docs/(reference)/api-reference/primitives/suggestion.mdx +4 -6
- package/.docs/raw/docs/(reference)/api-reference/primitives/thread-list-item.mdx +4 -2
- package/.docs/raw/docs/(reference)/api-reference/primitives/thread-list.mdx +3 -5
- package/.docs/raw/docs/(reference)/api-reference/primitives/thread.mdx +169 -22
- package/.docs/raw/docs/(reference)/api-reference/runtimes/assistant-runtime.mdx +14 -4
- package/.docs/raw/docs/(reference)/api-reference/runtimes/attachment-runtime.mdx +15 -26
- package/.docs/raw/docs/(reference)/api-reference/runtimes/composer-runtime.mdx +39 -21
- package/.docs/raw/docs/(reference)/api-reference/runtimes/message-part-runtime.mdx +33 -9
- package/.docs/raw/docs/(reference)/api-reference/runtimes/message-runtime.mdx +48 -21
- package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-list-item-runtime.mdx +36 -7
- package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-list-runtime.mdx +30 -10
- package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-runtime.mdx +12 -10
- package/.docs/raw/docs/(reference)/migrations/deprecation-policy.mdx +1 -1
- package/.docs/raw/docs/(reference)/migrations/react-langgraph-v0-7.mdx +9 -4
- package/.docs/raw/docs/(reference)/migrations/v0-11.mdx +7 -5
- package/.docs/raw/docs/(reference)/migrations/v0-12.mdx +9 -7
- package/.docs/raw/docs/(reference)/migrations/v0-14.mdx +159 -0
- package/.docs/raw/docs/(reference)/react-compatibility.mdx +5 -134
- package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +84 -6
- package/.docs/raw/docs/cloud/ai-sdk.mdx +14 -4
- package/.docs/raw/docs/cloud/langgraph.mdx +13 -3
- package/.docs/raw/docs/ink/adapters.mdx +41 -0
- package/.docs/raw/docs/ink/custom-backend.mdx +203 -0
- package/.docs/raw/docs/ink/hooks.mdx +448 -0
- package/.docs/raw/docs/ink/index.mdx +239 -0
- package/.docs/raw/docs/ink/migration.mdx +140 -0
- package/.docs/raw/docs/ink/primitives.mdx +699 -0
- package/.docs/raw/docs/react-native/adapters.mdx +63 -87
- package/.docs/raw/docs/react-native/custom-backend.mdx +11 -14
- package/.docs/raw/docs/react-native/hooks.mdx +214 -232
- package/.docs/raw/docs/react-native/index.mdx +118 -159
- package/.docs/raw/docs/react-native/migration.mdx +144 -0
- package/.docs/raw/docs/react-native/primitives.mdx +431 -302
- package/.docs/raw/docs/runtimes/a2a/index.mdx +294 -0
- package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +9 -9
- package/.docs/raw/docs/runtimes/ai-sdk/v5-legacy.mdx +14 -3
- package/.docs/raw/docs/runtimes/assistant-transport.mdx +59 -25
- package/.docs/raw/docs/runtimes/custom/custom-thread-list.mdx +13 -6
- package/.docs/raw/docs/runtimes/custom/external-store.mdx +138 -38
- package/.docs/raw/docs/runtimes/custom/local.mdx +184 -42
- package/.docs/raw/docs/runtimes/data-stream.mdx +92 -19
- package/.docs/raw/docs/runtimes/google-adk/index.mdx +624 -0
- package/.docs/raw/docs/runtimes/helicone.mdx +6 -6
- package/.docs/raw/docs/runtimes/langgraph/index.mdx +38 -27
- package/.docs/raw/docs/runtimes/langgraph/tutorial/introduction.mdx +1 -1
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-1.mdx +15 -20
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +7 -11
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-3.mdx +8 -11
- package/.docs/raw/docs/runtimes/langserve.mdx +6 -7
- package/.docs/raw/docs/runtimes/pick-a-runtime.mdx +18 -3
- package/.docs/raw/docs/ui/file.mdx +5 -4
- package/.docs/raw/docs/ui/image.mdx +5 -4
- package/.docs/raw/docs/ui/markdown.mdx +3 -1
- package/.docs/raw/docs/ui/model-selector.mdx +8 -8
- package/.docs/raw/docs/ui/part-grouping.mdx +7 -10
- package/.docs/raw/docs/ui/quote.mdx +210 -0
- package/.docs/raw/docs/ui/reasoning.mdx +12 -11
- package/.docs/raw/docs/ui/sources.mdx +88 -17
- package/.docs/raw/docs/ui/streamdown.mdx +16 -7
- package/.docs/raw/docs/ui/thread-list.mdx +11 -13
- package/.docs/raw/docs/ui/thread.mdx +28 -33
- package/.docs/raw/docs/ui/tool-fallback.mdx +5 -6
- package/.docs/raw/docs/ui/tool-group.mdx +9 -8
- package/.docs/raw/docs/utilities/heat-graph.mdx +236 -0
- package/.docs/raw/docs/utilities/tw-shimmer.mdx +211 -0
- package/package.json +4 -4
- package/.docs/raw/docs/(reference)/legacy/styled/assistant-modal.mdx +0 -77
- package/.docs/raw/docs/(reference)/legacy/styled/decomposition.mdx +0 -635
- package/.docs/raw/docs/(reference)/legacy/styled/markdown.mdx +0 -77
- package/.docs/raw/docs/(reference)/legacy/styled/scrollbar.mdx +0 -72
- package/.docs/raw/docs/(reference)/legacy/styled/thread-width.mdx +0 -22
- package/.docs/raw/docs/(reference)/legacy/styled/thread.mdx +0 -77
- /package/.docs/raw/docs/cloud/{overview.mdx → index.mdx} +0 -0
|
@@ -26,7 +26,7 @@ The `useChatRuntime` hook from `@assistant-ui/react-ai-sdk` wraps AI SDK's `useC
|
|
|
26
26
|
3. Generates a conversation title after the assistant's first response
|
|
27
27
|
4. Loads historical messages when switching threads via `<ThreadList />`
|
|
28
28
|
|
|
29
|
-
You provide the
|
|
29
|
+
You provide the cloud configuration—everything else is handled. The default `AssistantChatTransport` automatically sends requests to `/api/chat`.
|
|
30
30
|
|
|
31
31
|
## Prerequisites
|
|
32
32
|
|
|
@@ -84,16 +84,21 @@ Create a client-side AssistantCloud instance and integrate it with your AI SDK r
|
|
|
84
84
|
```tsx title="app/chat/page.tsx"
|
|
85
85
|
"use client";
|
|
86
86
|
|
|
87
|
+
import { useMemo } from "react";
|
|
87
88
|
import { AssistantCloud, AssistantRuntimeProvider } from "@assistant-ui/react";
|
|
88
89
|
import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
|
|
89
90
|
import { ThreadList } from "@/components/assistant-ui/thread-list";
|
|
90
91
|
import { Thread } from "@/components/assistant-ui/thread";
|
|
91
92
|
|
|
92
93
|
export default function ChatPage() {
|
|
93
|
-
const cloud =
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
const cloud = useMemo(
|
|
95
|
+
() =>
|
|
96
|
+
new AssistantCloud({
|
|
97
|
+
baseUrl: process.env.NEXT_PUBLIC_ASSISTANT_BASE_URL!,
|
|
98
|
+
anonymous: true, // Creates browser-session based user ID
|
|
99
|
+
}),
|
|
100
|
+
[],
|
|
101
|
+
);
|
|
97
102
|
|
|
98
103
|
const runtime = useChatRuntime({
|
|
99
104
|
cloud,
|
|
@@ -114,6 +119,74 @@ export default function ChatPage() {
|
|
|
114
119
|
|
|
115
120
|
</Steps>
|
|
116
121
|
|
|
122
|
+
## `useChatRuntime` Options
|
|
123
|
+
|
|
124
|
+
<ParametersTable
|
|
125
|
+
parameters={[
|
|
126
|
+
{
|
|
127
|
+
name: "cloud",
|
|
128
|
+
type: "AssistantCloud",
|
|
129
|
+
description:
|
|
130
|
+
"Optional AssistantCloud instance for chat persistence and thread management.",
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: "adapters",
|
|
134
|
+
type: "RuntimeAdapters",
|
|
135
|
+
description:
|
|
136
|
+
"Optional runtime adapters to extend or override built-in functionality.",
|
|
137
|
+
children: [
|
|
138
|
+
{
|
|
139
|
+
type: "RuntimeAdapters",
|
|
140
|
+
parameters: [
|
|
141
|
+
{
|
|
142
|
+
name: "attachments",
|
|
143
|
+
type: "AttachmentAdapter",
|
|
144
|
+
description:
|
|
145
|
+
"Custom attachment adapter for file uploads. Defaults to the Vercel AI SDK attachment adapter.",
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: "speech",
|
|
149
|
+
type: "SpeechSynthesisAdapter",
|
|
150
|
+
description:
|
|
151
|
+
"Adapter for text-to-speech functionality.",
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: "dictation",
|
|
155
|
+
type: "DictationAdapter",
|
|
156
|
+
description:
|
|
157
|
+
"Adapter for speech-to-text dictation input.",
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
name: "feedback",
|
|
161
|
+
type: "FeedbackAdapter",
|
|
162
|
+
description:
|
|
163
|
+
"Adapter for collecting user feedback on messages.",
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: "history",
|
|
167
|
+
type: "ThreadHistoryAdapter",
|
|
168
|
+
description:
|
|
169
|
+
"Adapter for loading and saving thread history. Used to restore previous messages when switching threads.",
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
name: "toCreateMessage",
|
|
177
|
+
type: "(message: AppendMessage) => CreateUIMessage",
|
|
178
|
+
description:
|
|
179
|
+
"Optional custom function to convert an assistant-ui AppendMessage into an AI SDK CreateUIMessage before sending. Use this to customize how outgoing messages are formatted, for example to add custom metadata or transform content parts.",
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
name: "transport",
|
|
183
|
+
type: "ChatTransport",
|
|
184
|
+
description:
|
|
185
|
+
"Custom transport implementation. Defaults to AssistantChatTransport which sends requests to '/api/chat'.",
|
|
186
|
+
},
|
|
187
|
+
]}
|
|
188
|
+
/>
|
|
189
|
+
|
|
117
190
|
## Telemetry
|
|
118
191
|
|
|
119
192
|
The `useChatRuntime` hook captures full run telemetry including timing data. This integrates with the assistant-ui runtime to provide:
|
|
@@ -134,10 +207,13 @@ To capture model and usage data, add the `messageMetadata` callback to your AI S
|
|
|
134
207
|
|
|
135
208
|
```tsx title="app/api/chat/route.ts"
|
|
136
209
|
import { streamText } from "ai";
|
|
210
|
+
import { openai } from "@ai-sdk/openai";
|
|
137
211
|
|
|
138
212
|
export async function POST(req: Request) {
|
|
213
|
+
const { messages } = await req.json();
|
|
214
|
+
|
|
139
215
|
const result = streamText({
|
|
140
|
-
model: openai("gpt-
|
|
216
|
+
model: openai("gpt-4o-mini"),
|
|
141
217
|
messages,
|
|
142
218
|
});
|
|
143
219
|
|
|
@@ -168,6 +244,7 @@ Use the `beforeReport` hook to add custom metadata or filter reports:
|
|
|
168
244
|
```tsx
|
|
169
245
|
const cloud = new AssistantCloud({
|
|
170
246
|
baseUrl: process.env.NEXT_PUBLIC_ASSISTANT_BASE_URL!,
|
|
247
|
+
anonymous: true,
|
|
171
248
|
telemetry: {
|
|
172
249
|
beforeReport: (report) => ({
|
|
173
250
|
...report,
|
|
@@ -184,6 +261,7 @@ Return `null` from `beforeReport` to skip reporting a specific run. To disable t
|
|
|
184
261
|
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:
|
|
185
262
|
|
|
186
263
|
```tsx
|
|
264
|
+
import { useMemo } from "react";
|
|
187
265
|
import { useAuth } from "@clerk/nextjs";
|
|
188
266
|
import { AssistantCloud } from "@assistant-ui/react";
|
|
189
267
|
import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
|
|
@@ -49,7 +49,7 @@ NEXT_PUBLIC_ASSISTANT_BASE_URL=https://proj-[YOUR-ID].assistant-api.com
|
|
|
49
49
|
|
|
50
50
|
### Install Dependencies
|
|
51
51
|
|
|
52
|
-
<InstallCommand npm={["@assistant-ui/cloud-ai-sdk", "
|
|
52
|
+
<InstallCommand npm={["@assistant-ui/cloud-ai-sdk", "@ai-sdk/react", "ai"]} />
|
|
53
53
|
|
|
54
54
|
</Step>
|
|
55
55
|
|
|
@@ -151,7 +151,7 @@ const chat = useCloudChat({ threads: myThreads });
|
|
|
151
151
|
| `options.threads` | `UseThreadsResult` | External thread management from `useThreads()`. Use when you need thread operations in a separate component or custom thread options like `includeArchived` |
|
|
152
152
|
| `options.onSyncError` | `(error: Error) => void` | Callback invoked when a sync error occurs |
|
|
153
153
|
|
|
154
|
-
|
|
154
|
+
A subset of [AI SDK `useChat` options](https://sdk.vercel.ai/docs/reference/ai-sdk-ui/use-chat) are also accepted (those defined on `ChatInit`). Some options available on `useChat` such as `experimental_throttle` and `resume` are not supported.
|
|
155
155
|
|
|
156
156
|
**Returns:** `UseCloudChatResult`
|
|
157
157
|
|
|
@@ -169,12 +169,15 @@ Plus all other properties from AI SDK's [`UseChatHelpers`](https://sdk.vercel.ai
|
|
|
169
169
|
|
|
170
170
|
| Value | Type | Description |
|
|
171
171
|
|-------|------|-------------|
|
|
172
|
+
| `threads.cloud` | `AssistantCloud` | The cloud instance used for thread operations |
|
|
172
173
|
| `threads.threads` | `CloudThread[]` | Active threads sorted by recency |
|
|
173
174
|
| `threads.threadId` | `string \| null` | Current thread ID (`null` for a new unsaved chat) |
|
|
174
175
|
| `threads.selectThread` | `(id: string \| null) => void` | Switch threads or pass `null` for a new chat |
|
|
175
176
|
| `threads.isLoading` | `boolean` | `true` during initial load or refresh |
|
|
176
177
|
| `threads.error` | `Error \| null` | Last error, if any |
|
|
177
178
|
| `threads.refresh` | `() => Promise<boolean>` | Re-fetch the thread list |
|
|
179
|
+
| `threads.get` | `(id: string) => Promise<CloudThread \| null>` | Fetch a single thread by ID |
|
|
180
|
+
| `threads.create` | `(options?: \{ externalId?: string \}) => Promise<CloudThread \| null>` | Create a new thread |
|
|
178
181
|
| `threads.delete` | `(id: string) => Promise<boolean>` | Delete a thread |
|
|
179
182
|
| `threads.rename` | `(id: string, title: string) => Promise<boolean>` | Rename a thread |
|
|
180
183
|
| `threads.archive` | `(id: string) => Promise<boolean>` | Archive a thread |
|
|
@@ -206,22 +209,27 @@ The `useCloudChat` hook automatically reports run telemetry to Assistant Cloud a
|
|
|
206
209
|
|
|
207
210
|
**Automatically captured:**
|
|
208
211
|
- `status` — `"completed"` or `"incomplete"` based on response content
|
|
209
|
-
- `tool_calls` — Tool invocations with name, arguments,
|
|
212
|
+
- `tool_calls` — Tool invocations with name, arguments, and results. MCP tool calls are explicitly tagged with `tool_source: "mcp"`
|
|
210
213
|
- `total_steps` — Number of reasoning/tool steps in the response
|
|
211
214
|
- `output_text` — Full response text (truncated at 50K characters)
|
|
212
215
|
|
|
213
216
|
**Requires route configuration:**
|
|
214
217
|
- `model_id` — The model used for the response
|
|
215
218
|
- `input_tokens` / `output_tokens` — Token usage statistics
|
|
219
|
+
- `reasoning_tokens` — Tokens used for chain-of-thought reasoning (e.g. o1/o3 models)
|
|
220
|
+
- `cached_input_tokens` — Input tokens served from the provider's prompt cache
|
|
216
221
|
|
|
217
222
|
To capture model and usage data, configure the `messageMetadata` callback in your AI SDK route:
|
|
218
223
|
|
|
219
224
|
```tsx title="app/api/chat/route.ts"
|
|
220
225
|
import { streamText } from "ai";
|
|
226
|
+
import { openai } from "@ai-sdk/openai";
|
|
221
227
|
|
|
222
228
|
export async function POST(req: Request) {
|
|
229
|
+
const { messages } = await req.json();
|
|
230
|
+
|
|
223
231
|
const result = streamText({
|
|
224
|
-
model: openai("gpt-
|
|
232
|
+
model: openai("gpt-4o-mini"),
|
|
225
233
|
messages,
|
|
226
234
|
});
|
|
227
235
|
|
|
@@ -254,6 +262,7 @@ Use the `beforeReport` hook to enrich or filter telemetry:
|
|
|
254
262
|
```tsx
|
|
255
263
|
const cloud = new AssistantCloud({
|
|
256
264
|
baseUrl: process.env.NEXT_PUBLIC_ASSISTANT_BASE_URL!,
|
|
265
|
+
anonymous: true,
|
|
257
266
|
telemetry: {
|
|
258
267
|
beforeReport: (report) => ({
|
|
259
268
|
...report,
|
|
@@ -270,6 +279,7 @@ Return `null` from `beforeReport` to skip reporting a specific run. To disable t
|
|
|
270
279
|
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:
|
|
271
280
|
|
|
272
281
|
```tsx
|
|
282
|
+
import { useMemo } from "react";
|
|
273
283
|
import { useAuth } from "@clerk/nextjs";
|
|
274
284
|
import { AssistantCloud } from "assistant-cloud";
|
|
275
285
|
import { useCloudChat } from "@assistant-ui/cloud-ai-sdk";
|
|
@@ -74,7 +74,7 @@ import {
|
|
|
74
74
|
AssistantRuntimeProvider,
|
|
75
75
|
} from "@assistant-ui/react";
|
|
76
76
|
import { useLangGraphRuntime } from "@assistant-ui/react-langgraph";
|
|
77
|
-
import { createThread, getThreadState, sendMessage } from "@/lib/chatApi";
|
|
77
|
+
import { createThread, deleteThread, getThreadState, sendMessage } from "@/lib/chatApi";
|
|
78
78
|
import { LangChainMessage } from "@assistant-ui/react-langgraph";
|
|
79
79
|
import { useMemo } from "react";
|
|
80
80
|
|
|
@@ -114,6 +114,9 @@ export function MyRuntimeProvider({
|
|
|
114
114
|
(state.values as { messages?: LangChainMessage[] }).messages ?? [],
|
|
115
115
|
};
|
|
116
116
|
},
|
|
117
|
+
delete: async (externalId) => {
|
|
118
|
+
await deleteThread(externalId);
|
|
119
|
+
},
|
|
117
120
|
});
|
|
118
121
|
|
|
119
122
|
return (
|
|
@@ -136,7 +139,7 @@ import {
|
|
|
136
139
|
AssistantRuntimeProvider,
|
|
137
140
|
} from "@assistant-ui/react";
|
|
138
141
|
import { useLangGraphRuntime } from "@assistant-ui/react-langgraph";
|
|
139
|
-
import { createThread, getThreadState, sendMessage } from "@/lib/chatApi";
|
|
142
|
+
import { createThread, deleteThread, getThreadState, sendMessage } from "@/lib/chatApi";
|
|
140
143
|
import { LangChainMessage } from "@assistant-ui/react-langgraph";
|
|
141
144
|
import { useAuth } from "@clerk/nextjs";
|
|
142
145
|
import { useMemo } from "react";
|
|
@@ -179,6 +182,9 @@ export function MyRuntimeProvider({
|
|
|
179
182
|
(state.values as { messages?: LangChainMessage[] }).messages ?? [],
|
|
180
183
|
};
|
|
181
184
|
},
|
|
185
|
+
delete: async (externalId) => {
|
|
186
|
+
await deleteThread(externalId);
|
|
187
|
+
},
|
|
182
188
|
});
|
|
183
189
|
|
|
184
190
|
return (
|
|
@@ -199,7 +205,11 @@ export function MyRuntimeProvider({
|
|
|
199
205
|
</Tabs>
|
|
200
206
|
|
|
201
207
|
<Callout type="info">
|
|
202
|
-
The `useLangGraphRuntime` hook
|
|
208
|
+
The `useLangGraphRuntime` hook accepts `cloud`, `create`, `load`, and `delete` parameters for simplified thread management. The runtime handles the thread lifecycle internally.
|
|
209
|
+
|
|
210
|
+
- **`create`**: Called when creating a new thread. Returns `{ externalId }` with your backend's thread ID.
|
|
211
|
+
- **`load`**: Called when switching to an existing thread. Returns the thread's messages (and optionally interrupts).
|
|
212
|
+
- **`delete`**: Called when deleting a thread. Receives the thread's `externalId`. When provided, users can delete threads from the thread list UI.
|
|
203
213
|
</Callout>
|
|
204
214
|
|
|
205
215
|
</Step>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Adapters
|
|
3
|
+
description: Title generation adapters for React Ink.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Adapters customize runtime behavior. They can be passed as options to `useLocalRuntime` or `useRemoteThreadListRuntime`.
|
|
7
|
+
|
|
8
|
+
## RemoteThreadListAdapter
|
|
9
|
+
|
|
10
|
+
Title generation is configured via the `generateTitle` method on `RemoteThreadListAdapter`. See the [Custom Backend](/docs/ink/custom-backend) page for a full example.
|
|
11
|
+
|
|
12
|
+
```tsx
|
|
13
|
+
import type { RemoteThreadListAdapter } from "@assistant-ui/react-ink";
|
|
14
|
+
import { createAssistantStream } from "assistant-stream";
|
|
15
|
+
|
|
16
|
+
const myAdapter: RemoteThreadListAdapter = {
|
|
17
|
+
// ... other methods ...
|
|
18
|
+
|
|
19
|
+
async generateTitle(remoteId, unstable_messages) {
|
|
20
|
+
return createAssistantStream(async (controller) => {
|
|
21
|
+
const res = await fetch(`/api/threads/${remoteId}/title`, {
|
|
22
|
+
method: "POST",
|
|
23
|
+
headers: { "Content-Type": "application/json" },
|
|
24
|
+
body: JSON.stringify({ messages: unstable_messages }),
|
|
25
|
+
});
|
|
26
|
+
const { title } = await res.json();
|
|
27
|
+
controller.appendText(title);
|
|
28
|
+
});
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Which option to choose?
|
|
34
|
+
|
|
35
|
+
| | ChatModelAdapter + `useLocalRuntime` | RemoteThreadListAdapter + `useRemoteThreadListRuntime` |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| **Thread storage** | In-memory | Your backend |
|
|
38
|
+
| **Message storage** | In-memory | In-memory (can add history adapter for server-side) |
|
|
39
|
+
| **Cross-session persistence** | No | Yes |
|
|
40
|
+
| **Setup complexity** | Minimal | Moderate |
|
|
41
|
+
| **Best for** | CLI tools, demos, prototypes | Production apps with persistence |
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Custom Backend
|
|
3
|
+
description: Connect your terminal app to your own backend API.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
By default, `useLocalRuntime` manages threads and messages in memory. You can connect to your own backend in two ways depending on your needs.
|
|
7
|
+
|
|
8
|
+
## Option 1: ChatModelAdapter only
|
|
9
|
+
|
|
10
|
+
The simplest approach — keep thread management local, but send messages to your backend for inference.
|
|
11
|
+
|
|
12
|
+
```tsx title="adapters/my-chat-adapter.ts"
|
|
13
|
+
import type { ChatModelAdapter } from "@assistant-ui/react-ink";
|
|
14
|
+
|
|
15
|
+
export const myChatAdapter: ChatModelAdapter = {
|
|
16
|
+
async *run({ messages, abortSignal }) {
|
|
17
|
+
const response = await fetch("https://my-api.com/chat", {
|
|
18
|
+
method: "POST",
|
|
19
|
+
headers: { "Content-Type": "application/json" },
|
|
20
|
+
body: JSON.stringify({ messages }),
|
|
21
|
+
signal: abortSignal,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const reader = response.body?.getReader();
|
|
25
|
+
if (!reader) throw new Error("No response body");
|
|
26
|
+
|
|
27
|
+
const decoder = new TextDecoder();
|
|
28
|
+
let fullText = "";
|
|
29
|
+
|
|
30
|
+
while (true) {
|
|
31
|
+
const { done, value } = await reader.read();
|
|
32
|
+
if (done) break;
|
|
33
|
+
|
|
34
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
35
|
+
fullText += chunk;
|
|
36
|
+
yield { content: [{ type: "text", text: fullText }] };
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
```tsx title="app.tsx"
|
|
43
|
+
import { useLocalRuntime, AssistantRuntimeProvider } from "@assistant-ui/react-ink";
|
|
44
|
+
import { myChatAdapter } from "./adapters/my-chat-adapter.js";
|
|
45
|
+
|
|
46
|
+
export function App() {
|
|
47
|
+
const runtime = useLocalRuntime(myChatAdapter);
|
|
48
|
+
return (
|
|
49
|
+
<AssistantRuntimeProvider runtime={runtime}>
|
|
50
|
+
{/* your chat UI */}
|
|
51
|
+
</AssistantRuntimeProvider>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
This gives you:
|
|
57
|
+
|
|
58
|
+
- Streaming chat responses from your API
|
|
59
|
+
- In-memory thread list (lost on process exit)
|
|
60
|
+
- Multi-thread support
|
|
61
|
+
|
|
62
|
+
## Option 2: Full backend thread management
|
|
63
|
+
|
|
64
|
+
When you want your backend to own thread state (e.g. for persistence across sessions, team sharing, or server-side history), implement a `RemoteThreadListAdapter`.
|
|
65
|
+
|
|
66
|
+
<Steps>
|
|
67
|
+
<Step>
|
|
68
|
+
|
|
69
|
+
### Implement the adapter
|
|
70
|
+
|
|
71
|
+
```tsx title="adapters/my-thread-list-adapter.ts"
|
|
72
|
+
import type { RemoteThreadListAdapter } from "@assistant-ui/react-ink";
|
|
73
|
+
import { createAssistantStream } from "assistant-stream";
|
|
74
|
+
|
|
75
|
+
const API_BASE = "https://my-api.com";
|
|
76
|
+
|
|
77
|
+
export const myThreadListAdapter: RemoteThreadListAdapter = {
|
|
78
|
+
async list() {
|
|
79
|
+
const res = await fetch(`${API_BASE}/threads`);
|
|
80
|
+
const threads = await res.json();
|
|
81
|
+
return {
|
|
82
|
+
threads: threads.map((t: any) => ({
|
|
83
|
+
remoteId: t.id,
|
|
84
|
+
status: t.archived ? "archived" : "regular",
|
|
85
|
+
title: t.title,
|
|
86
|
+
})),
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
async initialize(localId) {
|
|
91
|
+
const res = await fetch(`${API_BASE}/threads`, {
|
|
92
|
+
method: "POST",
|
|
93
|
+
headers: { "Content-Type": "application/json" },
|
|
94
|
+
body: JSON.stringify({ localId }),
|
|
95
|
+
});
|
|
96
|
+
const { id } = await res.json();
|
|
97
|
+
return { remoteId: id, externalId: undefined };
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
async rename(remoteId, title) {
|
|
101
|
+
await fetch(`${API_BASE}/threads/${remoteId}`, {
|
|
102
|
+
method: "PATCH",
|
|
103
|
+
headers: { "Content-Type": "application/json" },
|
|
104
|
+
body: JSON.stringify({ title }),
|
|
105
|
+
});
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
async archive(remoteId) {
|
|
109
|
+
await fetch(`${API_BASE}/threads/${remoteId}/archive`, {
|
|
110
|
+
method: "POST",
|
|
111
|
+
});
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
async unarchive(remoteId) {
|
|
115
|
+
await fetch(`${API_BASE}/threads/${remoteId}/unarchive`, {
|
|
116
|
+
method: "POST",
|
|
117
|
+
});
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
async delete(remoteId) {
|
|
121
|
+
await fetch(`${API_BASE}/threads/${remoteId}`, { method: "DELETE" });
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
async fetch(remoteId) {
|
|
125
|
+
const res = await fetch(`${API_BASE}/threads/${remoteId}`);
|
|
126
|
+
const t = await res.json();
|
|
127
|
+
return {
|
|
128
|
+
remoteId: t.id,
|
|
129
|
+
status: t.archived ? "archived" : "regular",
|
|
130
|
+
title: t.title,
|
|
131
|
+
};
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
async generateTitle(remoteId, unstable_messages) {
|
|
135
|
+
return createAssistantStream(async (controller) => {
|
|
136
|
+
const res = await fetch(`${API_BASE}/threads/${remoteId}/title`, {
|
|
137
|
+
method: "POST",
|
|
138
|
+
headers: { "Content-Type": "application/json" },
|
|
139
|
+
body: JSON.stringify({ messages: unstable_messages }),
|
|
140
|
+
});
|
|
141
|
+
const { title } = await res.json();
|
|
142
|
+
controller.appendText(title);
|
|
143
|
+
});
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
</Step>
|
|
149
|
+
<Step>
|
|
150
|
+
|
|
151
|
+
### Compose the runtime
|
|
152
|
+
|
|
153
|
+
```tsx title="app.tsx"
|
|
154
|
+
import {
|
|
155
|
+
useLocalRuntime,
|
|
156
|
+
useRemoteThreadListRuntime,
|
|
157
|
+
AssistantRuntimeProvider,
|
|
158
|
+
} from "@assistant-ui/react-ink";
|
|
159
|
+
import { myChatAdapter } from "./adapters/my-chat-adapter.js";
|
|
160
|
+
import { myThreadListAdapter } from "./adapters/my-thread-list-adapter.js";
|
|
161
|
+
|
|
162
|
+
function useAppRuntime() {
|
|
163
|
+
return useRemoteThreadListRuntime({
|
|
164
|
+
runtimeHook: () => useLocalRuntime(myChatAdapter),
|
|
165
|
+
adapter: myThreadListAdapter,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function App() {
|
|
170
|
+
const runtime = useAppRuntime();
|
|
171
|
+
return (
|
|
172
|
+
<AssistantRuntimeProvider runtime={runtime}>
|
|
173
|
+
{/* your chat UI */}
|
|
174
|
+
</AssistantRuntimeProvider>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
</Step>
|
|
180
|
+
</Steps>
|
|
181
|
+
|
|
182
|
+
## Adapter methods
|
|
183
|
+
|
|
184
|
+
| Method | Description |
|
|
185
|
+
|--------|-------------|
|
|
186
|
+
| `list()` | Return all threads on mount |
|
|
187
|
+
| `initialize(localId)` | Create a thread server-side, return `{ remoteId }` |
|
|
188
|
+
| `rename(remoteId, title)` | Persist title changes |
|
|
189
|
+
| `archive(remoteId)` | Mark thread as archived |
|
|
190
|
+
| `unarchive(remoteId)` | Restore archived thread |
|
|
191
|
+
| `delete(remoteId)` | Permanently remove thread |
|
|
192
|
+
| `fetch(remoteId)` | Fetch single thread metadata |
|
|
193
|
+
| `generateTitle(remoteId, unstable_messages)` | Return an `AssistantStream` with the generated title |
|
|
194
|
+
|
|
195
|
+
## Which option to choose?
|
|
196
|
+
|
|
197
|
+
| | Option 1: ChatModelAdapter | Option 2: RemoteThreadListAdapter |
|
|
198
|
+
|---|---|---|
|
|
199
|
+
| **Thread storage** | In-memory (process lifetime) | Your backend |
|
|
200
|
+
| **Message storage** | In-memory | On-device (can add history adapter for server-side) |
|
|
201
|
+
| **Cross-session persistence** | No | Yes |
|
|
202
|
+
| **Setup complexity** | Minimal | Moderate |
|
|
203
|
+
| **Best for** | CLI tools, demos, prototypes | Production apps with persistence |
|