@assistant-ui/mcp-docs-server 0.1.2 → 0.1.4
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/local-ollama.md +7 -7
- package/.docs/organized/code-examples/search-agent-for-e-commerce.md +9 -9
- package/.docs/organized/code-examples/with-ai-sdk.md +7 -7
- package/.docs/organized/code-examples/with-cloud.md +7 -7
- package/.docs/organized/code-examples/with-external-store.md +6 -6
- package/.docs/organized/code-examples/with-ffmpeg.md +10 -10
- package/.docs/organized/code-examples/with-langgraph.md +10 -10
- package/.docs/organized/code-examples/with-openai-assistants.md +7 -7
- package/.docs/organized/code-examples/with-react-hook-form.md +10 -10
- package/.docs/organized/code-examples/with-vercel-ai-rsc.md +7 -7
- package/.docs/raw/docs/api-reference/context-providers/{TextContentPartProvider.mdx → TextMessagePartProvider.mdx} +3 -3
- package/.docs/raw/docs/api-reference/integrations/react-hook-form.mdx +2 -2
- package/.docs/raw/docs/api-reference/overview.mdx +23 -23
- package/.docs/raw/docs/api-reference/primitives/Error.mdx +5 -3
- package/.docs/raw/docs/api-reference/primitives/Message.mdx +32 -0
- package/.docs/raw/docs/api-reference/primitives/{ContentPart.mdx → MessagePart.mdx} +41 -41
- package/.docs/raw/docs/api-reference/runtimes/MessagePartRuntime.mdx +22 -0
- package/.docs/raw/docs/api-reference/runtimes/ThreadListRuntime.mdx +1 -0
- package/.docs/raw/docs/api-reference/runtimes/ThreadRuntime.mdx +1 -0
- package/.docs/raw/docs/concepts/runtime-layer.mdx +7 -7
- package/.docs/raw/docs/copilots/make-assistant-tool-ui.mdx +79 -16
- package/.docs/raw/docs/copilots/make-assistant-tool.mdx +111 -7
- package/.docs/raw/docs/copilots/model-context.mdx +4 -1
- package/.docs/raw/docs/copilots/motivation.mdx +4 -1
- package/.docs/raw/docs/getting-started.mdx +11 -10
- package/.docs/raw/docs/guides/Attachments.mdx +24 -21
- package/.docs/raw/docs/guides/ToolUI.mdx +48 -8
- package/.docs/raw/docs/guides/Tools.mdx +24 -6
- package/.docs/raw/docs/mcp-docs-server.mdx +1 -3
- package/.docs/raw/docs/migrations/v0-11.mdx +169 -0
- package/.docs/raw/docs/migrations/v0-7.mdx +8 -8
- package/.docs/raw/docs/migrations/v0-8.mdx +14 -14
- package/.docs/raw/docs/migrations/v0-9.mdx +3 -3
- package/.docs/raw/docs/runtimes/ai-sdk/rsc.mdx +2 -2
- package/.docs/raw/docs/runtimes/ai-sdk/use-assistant-hook.mdx +1 -1
- package/.docs/raw/docs/runtimes/ai-sdk/use-chat-hook.mdx +2 -2
- package/.docs/raw/docs/runtimes/ai-sdk/use-chat.mdx +2 -2
- package/.docs/raw/docs/runtimes/custom/external-store.mdx +5 -5
- package/.docs/raw/docs/runtimes/custom/local.mdx +3 -3
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +2 -2
- package/.docs/raw/docs/ui/Attachment.mdx +5 -2
- package/.docs/raw/docs/ui/Markdown.mdx +2 -3
- package/.docs/raw/docs/ui/ToolFallback.mdx +2 -2
- package/dist/{chunk-CZCDQ3YH.js → chunk-JS4PWCVA.js} +1 -1
- package/dist/{chunk-C7O7EFKU.js → chunk-M2RKUM66.js} +1 -1
- package/dist/index.js +1 -1
- package/dist/prepare-docs/prepare.js +1 -1
- package/dist/stdio.js +1 -1
- package/package.json +5 -5
- package/.docs/raw/docs/api-reference/runtimes/ContentPartRuntime.mdx +0 -22
|
@@ -15,6 +15,7 @@ import { Card, Cards } from "fumadocs-ui/components/card";
|
|
|
15
15
|
<Step>
|
|
16
16
|
|
|
17
17
|
### Initialize assistant-ui
|
|
18
|
+
|
|
18
19
|
**Create a new project:**
|
|
19
20
|
|
|
20
21
|
```sh
|
|
@@ -349,7 +350,7 @@ const UserMessage: FC = () => {
|
|
|
349
350
|
<UserActionBar />
|
|
350
351
|
|
|
351
352
|
<div className="aui-user-message-content">
|
|
352
|
-
<MessagePrimitive.
|
|
353
|
+
<MessagePrimitive.Parts />
|
|
353
354
|
</div>
|
|
354
355
|
|
|
355
356
|
<BranchPicker className="aui-user-branch-picker" />
|
|
@@ -394,7 +395,7 @@ const AssistantMessage: FC = () => {
|
|
|
394
395
|
return (
|
|
395
396
|
<MessagePrimitive.Root className="aui-assistant-message-root">
|
|
396
397
|
<div className="aui-assistant-message-content">
|
|
397
|
-
<MessagePrimitive.
|
|
398
|
+
<MessagePrimitive.Parts components={{ Text: MarkdownText }} />
|
|
398
399
|
</div>
|
|
399
400
|
|
|
400
401
|
<AssistantActionBar />
|
|
@@ -1110,23 +1111,23 @@ const MyApp = () => {
|
|
|
1110
1111
|
## What's Next?
|
|
1111
1112
|
|
|
1112
1113
|
<Cards>
|
|
1113
|
-
<Card
|
|
1114
|
-
title="Pick a Runtime"
|
|
1114
|
+
<Card
|
|
1115
|
+
title="Pick a Runtime"
|
|
1115
1116
|
description="Choose the right runtime for your needs"
|
|
1116
1117
|
href="/docs/runtimes/pick-a-runtime"
|
|
1117
1118
|
/>
|
|
1118
|
-
<Card
|
|
1119
|
-
title="Generative UI"
|
|
1119
|
+
<Card
|
|
1120
|
+
title="Generative UI"
|
|
1120
1121
|
description="Create rich UI components for tool executions"
|
|
1121
1122
|
href="/docs/guides/ToolUI"
|
|
1122
1123
|
/>
|
|
1123
|
-
<Card
|
|
1124
|
-
title="Add Persistence"
|
|
1124
|
+
<Card
|
|
1125
|
+
title="Add Persistence"
|
|
1125
1126
|
description="Save and restore chat conversations"
|
|
1126
1127
|
href="/docs/cloud/overview"
|
|
1127
1128
|
/>
|
|
1128
|
-
<Card
|
|
1129
|
-
title="Examples"
|
|
1129
|
+
<Card
|
|
1130
|
+
title="Examples"
|
|
1130
1131
|
description="Explore full implementations and demos"
|
|
1131
1132
|
href="https://github.com/assistant-ui/assistant-ui/tree/main/examples"
|
|
1132
1133
|
/>
|
|
@@ -34,7 +34,8 @@ npx shadcn@latest add "https://r.assistant-ui.com/attachment"
|
|
|
34
34
|
This adds `/components/assistant-ui/attachment.tsx` to your project.
|
|
35
35
|
|
|
36
36
|
<Callout type="tip">
|
|
37
|
-
**Next steps:** Feel free to adjust these auto-generated components (styling,
|
|
37
|
+
**Next steps:** Feel free to adjust these auto-generated components (styling,
|
|
38
|
+
layout, behavior) to match your application's design system.
|
|
38
39
|
</Callout>
|
|
39
40
|
|
|
40
41
|
</Step>
|
|
@@ -94,7 +95,7 @@ const UserMessage = () => {
|
|
|
94
95
|
return (
|
|
95
96
|
<MessagePrimitive.Root>
|
|
96
97
|
<UserMessageAttachments />
|
|
97
|
-
<MessagePrimitive.
|
|
98
|
+
<MessagePrimitive.Parts />
|
|
98
99
|
</MessagePrimitive.Root>
|
|
99
100
|
);
|
|
100
101
|
};
|
|
@@ -242,7 +243,7 @@ class PDFAttachmentAdapter implements AttachmentAdapter {
|
|
|
242
243
|
async send(attachment: PendingAttachment): Promise<CompleteAttachment> {
|
|
243
244
|
// Option 1: Extract text from PDF (requires pdf parsing library)
|
|
244
245
|
// const text = await this.extractTextFromPDF(attachment.file);
|
|
245
|
-
|
|
246
|
+
|
|
246
247
|
// Option 2: Convert to base64 for API processing
|
|
247
248
|
const base64Data = await this.fileToBase64(attachment.file);
|
|
248
249
|
|
|
@@ -253,8 +254,8 @@ class PDFAttachmentAdapter implements AttachmentAdapter {
|
|
|
253
254
|
content: [
|
|
254
255
|
{
|
|
255
256
|
type: "text",
|
|
256
|
-
text: `[PDF Document: ${attachment.name}]\nBase64 data: ${base64Data.substring(0, 50)}
|
|
257
|
-
}
|
|
257
|
+
text: `[PDF Document: ${attachment.name}]\nBase64 data: ${base64Data.substring(0, 50)}...`,
|
|
258
|
+
},
|
|
258
259
|
],
|
|
259
260
|
status: { type: "complete" },
|
|
260
261
|
};
|
|
@@ -268,12 +269,12 @@ class PDFAttachmentAdapter implements AttachmentAdapter {
|
|
|
268
269
|
const arrayBuffer = await file.arrayBuffer();
|
|
269
270
|
const bytes = new Uint8Array(arrayBuffer);
|
|
270
271
|
let binary = "";
|
|
271
|
-
bytes.forEach(byte => {
|
|
272
|
+
bytes.forEach((byte) => {
|
|
272
273
|
binary += String.fromCharCode(byte);
|
|
273
274
|
});
|
|
274
275
|
return btoa(binary);
|
|
275
276
|
}
|
|
276
|
-
|
|
277
|
+
|
|
277
278
|
// Optional: Extract text from PDF using a library like pdf.js
|
|
278
279
|
private async extractTextFromPDF(file: File): Promise<string> {
|
|
279
280
|
// Implementation would use pdf.js or similar
|
|
@@ -296,33 +297,36 @@ import { useLocalRuntime, ChatModelAdapter } from "@assistant-ui/react";
|
|
|
296
297
|
const MyModelAdapter: ChatModelAdapter = {
|
|
297
298
|
async run({ messages, abortSignal }) {
|
|
298
299
|
// Convert messages to format expected by your vision-capable API
|
|
299
|
-
const formattedMessages = messages.map(msg => {
|
|
300
|
-
if (
|
|
300
|
+
const formattedMessages = messages.map((msg) => {
|
|
301
|
+
if (
|
|
302
|
+
msg.role === "user" &&
|
|
303
|
+
msg.content.some((part) => part.type === "image")
|
|
304
|
+
) {
|
|
301
305
|
// Format for GPT-4V or similar vision models
|
|
302
306
|
return {
|
|
303
307
|
role: "user",
|
|
304
|
-
content: msg.content.map(part => {
|
|
308
|
+
content: msg.content.map((part) => {
|
|
305
309
|
if (part.type === "text") {
|
|
306
310
|
return { type: "text", text: part.text };
|
|
307
311
|
}
|
|
308
312
|
if (part.type === "image") {
|
|
309
313
|
return {
|
|
310
314
|
type: "image_url",
|
|
311
|
-
image_url: { url: part.image }
|
|
315
|
+
image_url: { url: part.image },
|
|
312
316
|
};
|
|
313
317
|
}
|
|
314
318
|
return part;
|
|
315
|
-
})
|
|
319
|
+
}),
|
|
316
320
|
};
|
|
317
321
|
}
|
|
318
|
-
|
|
322
|
+
|
|
319
323
|
// Regular text messages
|
|
320
324
|
return {
|
|
321
325
|
role: msg.role,
|
|
322
326
|
content: msg.content
|
|
323
|
-
.filter(c => c.type === "text")
|
|
324
|
-
.map(c => c.text)
|
|
325
|
-
.join("\n")
|
|
327
|
+
.filter((c) => c.type === "text")
|
|
328
|
+
.map((c) => c.text)
|
|
329
|
+
.join("\n"),
|
|
326
330
|
};
|
|
327
331
|
});
|
|
328
332
|
|
|
@@ -343,8 +347,8 @@ const MyModelAdapter: ChatModelAdapter = {
|
|
|
343
347
|
|
|
344
348
|
// Create runtime with vision image adapter
|
|
345
349
|
const runtime = useLocalRuntime(MyModelAdapter, {
|
|
346
|
-
adapters: {
|
|
347
|
-
attachments: new VisionImageAdapter()
|
|
350
|
+
adapters: {
|
|
351
|
+
attachments: new VisionImageAdapter(),
|
|
348
352
|
},
|
|
349
353
|
});
|
|
350
354
|
```
|
|
@@ -363,12 +367,12 @@ export async function POST(req: Request) {
|
|
|
363
367
|
|
|
364
368
|
const result = streamText({
|
|
365
369
|
model: openai("gpt-4-vision-preview"),
|
|
366
|
-
messages: messages.map(msg => {
|
|
370
|
+
messages: messages.map((msg) => {
|
|
367
371
|
if (msg.experimental_attachments?.length) {
|
|
368
372
|
// Images are automatically formatted for the model
|
|
369
373
|
return {
|
|
370
374
|
...msg,
|
|
371
|
-
experimental_attachments: msg.experimental_attachments
|
|
375
|
+
experimental_attachments: msg.experimental_attachments,
|
|
372
376
|
};
|
|
373
377
|
}
|
|
374
378
|
return msg;
|
|
@@ -637,4 +641,3 @@ Attachments work with all assistant-ui runtimes:
|
|
|
637
641
|
|
|
638
642
|
- [Attachment UI Components](/docs/ui/Attachment) - UI implementation details
|
|
639
643
|
- [API Reference](/docs/api-reference) - Detailed type definitions
|
|
640
|
-
|
|
@@ -43,11 +43,14 @@ const weatherTool = tool({
|
|
|
43
43
|
execute: async ({ location, unit }) => {
|
|
44
44
|
const weather = await fetchWeatherAPI(location, unit);
|
|
45
45
|
return weather;
|
|
46
|
-
}
|
|
46
|
+
},
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
// Register the tool
|
|
50
|
-
const WeatherTool = makeAssistantTool(
|
|
50
|
+
const WeatherTool = makeAssistantTool({
|
|
51
|
+
...weatherTool,
|
|
52
|
+
toolName: "getWeather",
|
|
53
|
+
});
|
|
51
54
|
|
|
52
55
|
// Create the UI
|
|
53
56
|
const WeatherToolUI = makeAssistantToolUI<
|
|
@@ -74,7 +77,8 @@ const WeatherToolUI = makeAssistantToolUI<
|
|
|
74
77
|
```
|
|
75
78
|
|
|
76
79
|
<Callout type="tip">
|
|
77
|
-
Tools defined with `makeAssistantTool` can be passed to your backend using the
|
|
80
|
+
Tools defined with `makeAssistantTool` can be passed to your backend using the
|
|
81
|
+
`frontendTools` utility
|
|
78
82
|
</Callout>
|
|
79
83
|
|
|
80
84
|
Learn more about creating tools in the [Tools Guide](/docs/guides/Tools).
|
|
@@ -302,8 +306,9 @@ function DynamicToolUI() {
|
|
|
302
306
|
For tools that need access to parent component props:
|
|
303
307
|
|
|
304
308
|
<Callout type="tip">
|
|
305
|
-
**Why `useInlineRender`?**
|
|
306
|
-
|
|
309
|
+
**Why `useInlineRender`?** By default, a tool UI's `render` function is
|
|
310
|
+
static. Use `useInlineRender` when your UI needs access to dynamic component
|
|
311
|
+
props (for example, to pass in an `id` or other contextual data).
|
|
307
312
|
</Callout>
|
|
308
313
|
|
|
309
314
|
```tsx
|
|
@@ -337,7 +342,9 @@ function ProductPage({ productId, productName }) {
|
|
|
337
342
|
Create tools that collect user input during execution:
|
|
338
343
|
|
|
339
344
|
<Callout type="tip">
|
|
340
|
-
**Pro tip:** Call `addResult(...)` exactly once to complete the tool call.
|
|
345
|
+
**Pro tip:** Call `addResult(...)` exactly once to complete the tool call.
|
|
346
|
+
After it's invoked, the assistant will resume the conversation with your
|
|
347
|
+
provided data.
|
|
341
348
|
</Callout>
|
|
342
349
|
|
|
343
350
|
```tsx
|
|
@@ -572,7 +579,7 @@ type ToolUIRenderProps<TArgs, TResult> = {
|
|
|
572
579
|
argsText: string; // JSON stringified args
|
|
573
580
|
|
|
574
581
|
// Execution status
|
|
575
|
-
status:
|
|
582
|
+
status: ToolCallMessagePartStatus;
|
|
576
583
|
isError?: boolean;
|
|
577
584
|
|
|
578
585
|
// Tool result (may be partial during streaming)
|
|
@@ -656,8 +663,41 @@ useAssistantToolUI({
|
|
|
656
663
|
server.
|
|
657
664
|
</Callout>
|
|
658
665
|
|
|
666
|
+
### Collapsible Tool Groups
|
|
667
|
+
|
|
668
|
+
Create collapsible sections for consecutive tool calls:
|
|
669
|
+
|
|
670
|
+
```tsx
|
|
671
|
+
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
### Advanced Tool Group UI
|
|
675
|
+
|
|
676
|
+
Add progress indicators and enhanced styling:
|
|
677
|
+
|
|
678
|
+
```tsx
|
|
679
|
+
const ToolGroup = ({ startIndex, endIndex, children }) => {
|
|
680
|
+
return (
|
|
681
|
+
<details className="tool-group my-4">
|
|
682
|
+
<summary className="cursor-pointer rounded bg-gray-50 p-3 hover:bg-gray-100">
|
|
683
|
+
<span className="font-medium">
|
|
684
|
+
{endIndex - startIndex + 1} tool calls executed
|
|
685
|
+
</span>
|
|
686
|
+
<span className="ml-2 text-sm text-gray-500">
|
|
687
|
+
(#{startIndex + 1}-{endIndex + 1})
|
|
688
|
+
</span>
|
|
689
|
+
</summary>
|
|
690
|
+
<div className="mt-2 space-y-2 pl-4">{children}</div>
|
|
691
|
+
</details>
|
|
692
|
+
);
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
<Thread components={{ ToolGroup }} />;
|
|
696
|
+
```
|
|
697
|
+
|
|
659
698
|
## Related Guides
|
|
660
699
|
|
|
661
700
|
- [Tools Guide](/docs/guides/Tools) - Learn how to create and use tools with AI models
|
|
662
701
|
- [Tool Fallback](/docs/ui/ToolFallback) - Default UI for tools without custom components
|
|
663
|
-
- [API Reference](/docs/api-reference/primitives/
|
|
702
|
+
- [API Reference](/docs/api-reference/primitives/MessagePart) - Detailed type definitions and component APIs
|
|
703
|
+
- [Message Primitive](/docs/api-reference/primitives/Message) - Complete Message component documentation
|
|
@@ -52,7 +52,10 @@ const weatherTool = tool({
|
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
// Create the component
|
|
55
|
-
const WeatherTool = makeAssistantTool(
|
|
55
|
+
const WeatherTool = makeAssistantTool({
|
|
56
|
+
...weatherTool,
|
|
57
|
+
toolName: "getWeather"
|
|
58
|
+
});
|
|
56
59
|
|
|
57
60
|
// Place the tool component inside AssistantRuntimeProvider
|
|
58
61
|
function App() {
|
|
@@ -214,7 +217,10 @@ const screenshotTool = tool({
|
|
|
214
217
|
}
|
|
215
218
|
});
|
|
216
219
|
|
|
217
|
-
const ScreenshotTool = makeAssistantTool(
|
|
220
|
+
const ScreenshotTool = makeAssistantTool({
|
|
221
|
+
...screenshotTool,
|
|
222
|
+
toolName: "screenshot"
|
|
223
|
+
});
|
|
218
224
|
```
|
|
219
225
|
|
|
220
226
|
### Backend Tools
|
|
@@ -267,7 +273,10 @@ const calculateTool = tool({
|
|
|
267
273
|
}
|
|
268
274
|
});
|
|
269
275
|
|
|
270
|
-
const CalculateTool = makeAssistantTool(
|
|
276
|
+
const CalculateTool = makeAssistantTool({
|
|
277
|
+
...calculateTool,
|
|
278
|
+
toolName: "calculate"
|
|
279
|
+
});
|
|
271
280
|
|
|
272
281
|
// Backend: Use frontendTools to receive client tools
|
|
273
282
|
import { frontendTools } from "@assistant-ui/react-ai-sdk";
|
|
@@ -329,7 +338,10 @@ const refundTool = tool({
|
|
|
329
338
|
}
|
|
330
339
|
});
|
|
331
340
|
|
|
332
|
-
const RefundTool = makeAssistantTool(
|
|
341
|
+
const RefundTool = makeAssistantTool({
|
|
342
|
+
...refundTool,
|
|
343
|
+
toolName: "requestRefund"
|
|
344
|
+
});
|
|
333
345
|
```
|
|
334
346
|
|
|
335
347
|
### MCP (Model Context Protocol) Tools
|
|
@@ -393,7 +405,10 @@ const travelPlannerTool = tool({
|
|
|
393
405
|
}
|
|
394
406
|
});
|
|
395
407
|
|
|
396
|
-
const TravelPlannerTool = makeAssistantTool(
|
|
408
|
+
const TravelPlannerTool = makeAssistantTool({
|
|
409
|
+
...travelPlannerTool,
|
|
410
|
+
toolName: "planTrip"
|
|
411
|
+
});
|
|
397
412
|
```
|
|
398
413
|
|
|
399
414
|
### Conditional Tool Availability
|
|
@@ -461,7 +476,10 @@ const resilientTool = tool({
|
|
|
461
476
|
}
|
|
462
477
|
});
|
|
463
478
|
|
|
464
|
-
const ResilientTool = makeAssistantTool(
|
|
479
|
+
const ResilientTool = makeAssistantTool({
|
|
480
|
+
...resilientTool,
|
|
481
|
+
toolName: "fetchWithRetries"
|
|
482
|
+
});
|
|
465
483
|
```
|
|
466
484
|
|
|
467
485
|
## Best Practices
|
|
@@ -7,9 +7,7 @@ import { Tabs, Tab } from "fumadocs-ui/components/tabs";
|
|
|
7
7
|
|
|
8
8
|
`@assistant-ui/mcp-docs-server` provides direct access to assistant-ui's documentation and examples in Cursor, Windsurf, VSCode, Zed, Claude Code, or any other IDE or tool that supports MCP.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
The MCP server tools have been designed to allow an agent to query the specific information it needs to complete an assistant-ui related task - for example: implementing chat components, integrating with different runtimes, or understanding component architecture.
|
|
10
|
+
The MCP server tools have been designed to allow an agent to query the specific information it needs to complete an assistant-ui related task - for example: implementing chat components, integrating with different runtimes, understanding component architecture, and troubleshooting issues.
|
|
13
11
|
|
|
14
12
|
## How it works
|
|
15
13
|
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Migration to v0.11
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## ContentPart renamed to MessagePart
|
|
6
|
+
|
|
7
|
+
All ContentPart-related types, hooks, and components have been renamed to MessagePart for better semantic clarity and consistency.
|
|
8
|
+
|
|
9
|
+
### What changed
|
|
10
|
+
|
|
11
|
+
The following types and components have been renamed:
|
|
12
|
+
|
|
13
|
+
#### Core Types
|
|
14
|
+
|
|
15
|
+
- `TextContentPart` → `TextMessagePart`
|
|
16
|
+
- `ReasoningContentPart` → `ReasoningMessagePart`
|
|
17
|
+
- `SourceContentPart` → `SourceMessagePart`
|
|
18
|
+
- `ImageContentPart` → `ImageMessagePart`
|
|
19
|
+
- `FileContentPart` → `FileMessagePart`
|
|
20
|
+
- `Unstable_AudioContentPart` → `Unstable_AudioMessagePart`
|
|
21
|
+
- `ToolCallContentPart` → `ToolCallMessagePart`
|
|
22
|
+
- `ContentPartStatus` → `MessagePartStatus`
|
|
23
|
+
- `ToolCallContentPartStatus` → `ToolCallMessagePartStatus`
|
|
24
|
+
|
|
25
|
+
#### Thread Message Parts
|
|
26
|
+
|
|
27
|
+
- `ThreadUserContentPart` → `ThreadUserMessagePart`
|
|
28
|
+
- `ThreadAssistantContentPart` → `ThreadAssistantMessagePart`
|
|
29
|
+
|
|
30
|
+
#### Runtime and State Types
|
|
31
|
+
|
|
32
|
+
- `ContentPartRuntime` → `MessagePartRuntime`
|
|
33
|
+
- `ContentPartState` → `MessagePartState`
|
|
34
|
+
|
|
35
|
+
#### Hooks
|
|
36
|
+
|
|
37
|
+
- `useContentPart` → `useMessagePart`
|
|
38
|
+
- `useContentPartRuntime` → `useMessagePartRuntime`
|
|
39
|
+
- `useContentPartText` → `useMessagePartText`
|
|
40
|
+
- `useContentPartReasoning` → `useMessagePartReasoning`
|
|
41
|
+
- `useContentPartSource` → `useMessagePartSource`
|
|
42
|
+
- `useContentPartFile` → `useMessagePartFile`
|
|
43
|
+
- `useContentPartImage` → `useMessagePartImage`
|
|
44
|
+
- `useTextContentPart` → `useTextMessagePart`
|
|
45
|
+
|
|
46
|
+
#### Component Types
|
|
47
|
+
|
|
48
|
+
- `EmptyContentPartComponent` → `EmptyMessagePartComponent`
|
|
49
|
+
- `TextContentPartComponent` → `TextMessagePartComponent`
|
|
50
|
+
- `ReasoningContentPartComponent` → `ReasoningMessagePartComponent`
|
|
51
|
+
- `SourceContentPartComponent` → `SourceMessagePartComponent`
|
|
52
|
+
- `ImageContentPartComponent` → `ImageMessagePartComponent`
|
|
53
|
+
- `FileContentPartComponent` → `FileMessagePartComponent`
|
|
54
|
+
- `Unstable_AudioContentPartComponent` → `Unstable_AudioMessagePartComponent`
|
|
55
|
+
- `ToolCallContentPartComponent` → `ToolCallMessagePartComponent`
|
|
56
|
+
|
|
57
|
+
#### Props Types
|
|
58
|
+
|
|
59
|
+
- `EmptyContentPartProps` → `EmptyMessagePartProps`
|
|
60
|
+
- `TextContentPartProps` → `TextMessagePartProps`
|
|
61
|
+
- `ReasoningContentPartProps` → `ReasoningMessagePartProps`
|
|
62
|
+
- `SourceContentPartProps` → `SourceMessagePartProps`
|
|
63
|
+
- `ImageContentPartProps` → `ImageMessagePartProps`
|
|
64
|
+
- `FileContentPartProps` → `FileMessagePartProps`
|
|
65
|
+
- `Unstable_AudioContentPartProps` → `Unstable_AudioMessagePartProps`
|
|
66
|
+
- `ToolCallContentPartProps` → `ToolCallMessagePartProps`
|
|
67
|
+
|
|
68
|
+
#### Providers and Context
|
|
69
|
+
|
|
70
|
+
- `TextContentPartProvider` → `TextMessagePartProvider`
|
|
71
|
+
- `TextContentPartProviderProps` → `TextMessagePartProviderProps`
|
|
72
|
+
- `ContentPartRuntimeProvider` → `MessagePartRuntimeProvider`
|
|
73
|
+
- `ContentPartContext` → `MessagePartContext`
|
|
74
|
+
- `ContentPartContextValue` → `MessagePartContextValue`
|
|
75
|
+
|
|
76
|
+
#### Primitives
|
|
77
|
+
|
|
78
|
+
- `ContentPartPrimitive` → `MessagePartPrimitive`
|
|
79
|
+
- `ContentPartPrimitiveText` → `MessagePartPrimitiveText`
|
|
80
|
+
- `ContentPartPrimitiveImage` → `MessagePartPrimitiveImage`
|
|
81
|
+
- `ContentPartPrimitiveInProgress` → `MessagePartPrimitiveInProgress`
|
|
82
|
+
|
|
83
|
+
### MessagePrimitive.Content renamed to MessagePrimitive.Parts
|
|
84
|
+
|
|
85
|
+
The `MessagePrimitive.Content` component has been renamed to `MessagePrimitive.Parts` to better reflect its purpose of rendering message parts.
|
|
86
|
+
|
|
87
|
+
```diff
|
|
88
|
+
-<MessagePrimitive.Content components={{ Text: MyText }} />
|
|
89
|
+
+<MessagePrimitive.Parts components={{ Text: MyText }} />
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Migration
|
|
93
|
+
|
|
94
|
+
To migrate your codebase automatically, use the migration codemod:
|
|
95
|
+
|
|
96
|
+
```sh
|
|
97
|
+
# IMPORTANT: make sure to commit all changes to git / create a backup before running the codemod
|
|
98
|
+
npx @assistant-ui/cli upgrade
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Or run the specific migration:
|
|
102
|
+
|
|
103
|
+
```sh
|
|
104
|
+
npx @assistant-ui/cli codemod v0-11/content-part-to-message-part .
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### Manual Migration Examples
|
|
108
|
+
|
|
109
|
+
If you prefer to migrate manually, here are some examples:
|
|
110
|
+
|
|
111
|
+
**Imports:**
|
|
112
|
+
|
|
113
|
+
```diff
|
|
114
|
+
-import { TextContentPart, useContentPart, ToolCallContentPartComponent } from "@assistant-ui/react";
|
|
115
|
+
+import { TextMessagePart, useMessagePart, ToolCallMessagePartComponent } from "@assistant-ui/react";
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**Type annotations:**
|
|
119
|
+
|
|
120
|
+
```diff
|
|
121
|
+
-function processContent(part: TextContentPart): void {
|
|
122
|
+
+function processContent(part: TextMessagePart): void {
|
|
123
|
+
console.log(part.text);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
-const MyTool: ToolCallContentPartComponent = ({ toolName }) => {
|
|
127
|
+
+const MyTool: ToolCallMessagePartComponent = ({ toolName }) => {
|
|
128
|
+
return <div>{toolName}</div>;
|
|
129
|
+
};
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Hooks:**
|
|
133
|
+
|
|
134
|
+
```diff
|
|
135
|
+
function MyComponent() {
|
|
136
|
+
- const part = useContentPart();
|
|
137
|
+
- const text = useContentPartText();
|
|
138
|
+
- const runtime = useContentPartRuntime();
|
|
139
|
+
+ const part = useMessagePart();
|
|
140
|
+
+ const text = useMessagePartText();
|
|
141
|
+
+ const runtime = useMessagePartRuntime();
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**JSX Components:**
|
|
147
|
+
|
|
148
|
+
```diff
|
|
149
|
+
-<ContentPartPrimitive.Text />
|
|
150
|
+
-<ContentPartPrimitive.Image />
|
|
151
|
+
+<MessagePartPrimitive.Text />
|
|
152
|
+
+<MessagePartPrimitive.Image />
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Providers:**
|
|
156
|
+
|
|
157
|
+
```diff
|
|
158
|
+
-<TextContentPartProvider text="Hello" isRunning={false}>
|
|
159
|
+
+<TextMessagePartProvider text="Hello" isRunning={false}>
|
|
160
|
+
<div>Content</div>
|
|
161
|
+
-</TextContentPartProvider>
|
|
162
|
+
+</TextMessagePartProvider>
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Why this change?
|
|
166
|
+
|
|
167
|
+
The ContentPart naming was inconsistent with the rest of the codebase, where "message parts" are used throughout. This change improves semantic clarity and makes the API more intuitive by aligning terminology across the entire library.
|
|
168
|
+
|
|
169
|
+
The old ContentPart APIs continue to work but are now deprecated and will be removed in a future major version.
|
|
@@ -24,7 +24,7 @@ Component property types are now neatly organized under the component itself.
|
|
|
24
24
|
|
|
25
25
|
### `useThreadContext`, `useMessageContext`, ... replaced with direct imports of stores
|
|
26
26
|
|
|
27
|
-
`useAssistantContext`, `useThreadContext`, `useMessageContext` and `
|
|
27
|
+
`useAssistantContext`, `useThreadContext`, `useMessageContext` and `useMessagePartContext` have been removed in favor of direct exports from `@assistant-ui/react`;
|
|
28
28
|
|
|
29
29
|
```diff
|
|
30
30
|
-const { useThread } = useThreadContext();
|
|
@@ -56,7 +56,7 @@ Component property types are now neatly organized under the component itself.
|
|
|
56
56
|
```diff
|
|
57
57
|
-useSwitchToNewThread();
|
|
58
58
|
+const runtime = useAssistantRuntime()
|
|
59
|
-
+runtime.switchToNewThread();
|
|
59
|
+
+runtime.switchToNewThread();
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
### `runtime.subscribe` removed, `subscribeToMainThread` removed
|
|
@@ -106,7 +106,7 @@ The branch IDs are an internal implementation detail. The new Message Runtime AP
|
|
|
106
106
|
A few methods from `useThreadRuntime` have been moved to `useMessageRuntime()`.
|
|
107
107
|
|
|
108
108
|
- `threadRuntime.switchToBranch()` has been removed in favor of `useThreadRuntime().getMessageByIndex(idx).switchToBranch()`.
|
|
109
|
-
- `threadRuntime.addToolResult()` has been removed in favor of `useThreadRuntime().getMessageByIndex(idx).
|
|
109
|
+
- `threadRuntime.addToolResult()` has been removed in favor of `useThreadRuntime().getMessageByIndex(idx).getMessagePartByToolCallId(toolCallId).addToolResult()`.
|
|
110
110
|
- `threadRuntime.speak()` has been removed in favor of `useThreadRuntime().getMessageByIndex(idx).speak()`.
|
|
111
111
|
- `threadRuntime.submitFeedback()` has been removed in favor of `useThreadRuntime().getMessageByIndex(idx).submitFeedback()`.
|
|
112
112
|
- `threadRuntime.getEditComposer()` has been removed in favor of `useThreadRuntime().getMessageById(id).getMessageByIndex(idx).composer`.
|
|
@@ -149,15 +149,15 @@ These methods have been removed.
|
|
|
149
149
|
|
|
150
150
|
`useMessageStore` has been removed in favor of `useMessageRuntime().getState()`.
|
|
151
151
|
|
|
152
|
-
##
|
|
152
|
+
## Message part Context API simplifications
|
|
153
153
|
|
|
154
|
-
### Flattened context values `
|
|
154
|
+
### Flattened context values `useMessagePart().part` -> `useMessagePart()`
|
|
155
155
|
|
|
156
|
-
`
|
|
156
|
+
`MessagePartState` is now itself a message part, so you no longer need to access the nested `useMessagePart().part` field.
|
|
157
157
|
|
|
158
158
|
```diff
|
|
159
|
-
-
|
|
160
|
-
+
|
|
159
|
+
-useMessagePart(c => c.part.type);
|
|
160
|
+
+useMessagePart(c => c.type);
|
|
161
161
|
```
|
|
162
162
|
|
|
163
163
|
This also applies to tool UI render functions:
|
|
@@ -27,10 +27,10 @@ import { RSCDisplay } from "@assistant-ui/react-ai-sdk";
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
// if you are using unstyled primitives, update MyThread.tsx
|
|
30
|
-
<MessagePrimitive.
|
|
30
|
+
<MessagePrimitive.Parts components={{ Text: RSCDisplay }} />
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
## Migrate away from
|
|
33
|
+
## Migrate away from UIMessagePart
|
|
34
34
|
|
|
35
35
|
For instructions on migrating for Vercel AI SDK RSC, see section above.
|
|
36
36
|
This migration guide is for users of `useExternalStoreRuntime`.
|
|
@@ -40,13 +40,13 @@ This migration guide is for users of `useExternalStoreRuntime`.
|
|
|
40
40
|
First, reconsider your approach.
|
|
41
41
|
|
|
42
42
|
Creating UI components in the `convertMessage` callback is considered an anti-pattern.
|
|
43
|
-
The recommended alternative approach is to pass tool-call
|
|
43
|
+
The recommended alternative approach is to pass tool-call message parts, and use `makeAssistantToolUI` to map these tool calls to UI components.
|
|
44
44
|
|
|
45
45
|
This ensures that the data layer is separate and decoupled from the UI layer.
|
|
46
46
|
|
|
47
47
|
#### Example
|
|
48
48
|
|
|
49
|
-
Consider the following example, where you are using a
|
|
49
|
+
Consider the following example, where you are using a UIMessagePart to show a loading indicator.
|
|
50
50
|
|
|
51
51
|
```ts title="bad.ts"
|
|
52
52
|
// THIS IS BAD
|
|
@@ -66,11 +66,11 @@ const convertMessage = (message: MyMessage): ThreadMessageLike => {
|
|
|
66
66
|
// ...
|
|
67
67
|
};
|
|
68
68
|
|
|
69
|
-
// use the empty
|
|
69
|
+
// use the empty message part to show the loading indicator
|
|
70
70
|
<Thread assistantMessage={{ components: { Empty: MyLoader } }} />;
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
(if you are using unstyled primitives, update MyThread.tsx, and pass the component to MessagePrimitive.
|
|
73
|
+
(if you are using unstyled primitives, update MyThread.tsx, and pass the component to MessagePrimitive.Parts)
|
|
74
74
|
|
|
75
75
|
#### Example 2
|
|
76
76
|
|
|
@@ -107,13 +107,13 @@ const ChartToolUI = makeAssistantToolUI({
|
|
|
107
107
|
|
|
108
108
|
(if you are using unstyled primitives, render the `<ChartToolUI />` component anywhere inside your AssistantRuntimeProvider)
|
|
109
109
|
|
|
110
|
-
### Fallback Approach: Override
|
|
110
|
+
### Fallback Approach: Override MessagePartText
|
|
111
111
|
|
|
112
112
|
However, sometimes you receive UI components from an external source.
|
|
113
113
|
|
|
114
114
|
The example below assumes that your custom `MyMessage` type has a `display` field.
|
|
115
115
|
|
|
116
|
-
First, we define a dummy `UI_PLACEHOLDER`
|
|
116
|
+
First, we define a dummy `UI_PLACEHOLDER` message part, which we will replace with the UI component later:
|
|
117
117
|
|
|
118
118
|
```ts
|
|
119
119
|
const UI_PLACEHOLDER = Object.freeze({
|
|
@@ -122,17 +122,17 @@ const UI_PLACEHOLDER = Object.freeze({
|
|
|
122
122
|
});
|
|
123
123
|
const convertMessage = (message: MyMessage): ThreadMessageLike => ({
|
|
124
124
|
content: [
|
|
125
|
-
// other
|
|
125
|
+
// other message parts,
|
|
126
126
|
UI_PLACEHOLDER,
|
|
127
127
|
],
|
|
128
128
|
});
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
-
Then, we define a custom `
|
|
131
|
+
Then, we define a custom `TextMessagePartComponent`:
|
|
132
132
|
|
|
133
133
|
```tsx
|
|
134
|
-
const MyText:
|
|
135
|
-
const isUIPlaceholder =
|
|
134
|
+
const MyText: TextMessagePartComponent = () => {
|
|
135
|
+
const isUIPlaceholder = useMessagePart((p) => p === UI_PLACEHOLDER);
|
|
136
136
|
|
|
137
137
|
// this assumes that you have a `display` field on your original message objects before conversion.
|
|
138
138
|
const ui = useMessage((m) =>
|
|
@@ -155,6 +155,6 @@ We pass this component to our Thread:
|
|
|
155
155
|
/>
|
|
156
156
|
```
|
|
157
157
|
|
|
158
|
-
(if you are using unstyled primitives, update MyThread.tsx, and pass the component to MessagePrimitive.
|
|
158
|
+
(if you are using unstyled primitives, update MyThread.tsx, and pass the component to MessagePrimitive.Parts)
|
|
159
159
|
|
|
160
|
-
Now, the `UI_PLACEHOLDER`
|
|
160
|
+
Now, the `UI_PLACEHOLDER` message part is replaced with the UI component we defined earlier.
|