@assistant-ui/mcp-docs-server 0.1.24 → 0.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.docs/organized/code-examples/waterfall.md +8 -6
- package/.docs/organized/code-examples/with-a2a.md +676 -0
- package/.docs/organized/code-examples/with-ag-ui.md +10 -11
- package/.docs/organized/code-examples/with-ai-sdk-v6.md +31 -19
- package/.docs/organized/code-examples/with-artifacts.md +8 -8
- package/.docs/organized/code-examples/with-assistant-transport.md +6 -6
- package/.docs/organized/code-examples/with-chain-of-thought.md +37 -29
- package/.docs/organized/code-examples/with-cloud-standalone.md +14 -11
- package/.docs/organized/code-examples/with-cloud.md +8 -8
- package/.docs/organized/code-examples/with-custom-thread-list.md +10 -10
- package/.docs/organized/code-examples/with-elevenlabs-scribe.md +11 -11
- package/.docs/organized/code-examples/with-expo.md +571 -520
- package/.docs/organized/code-examples/with-external-store.md +6 -6
- package/.docs/organized/code-examples/with-ffmpeg.md +8 -8
- 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-interactables.md +778 -0
- package/.docs/organized/code-examples/with-langgraph.md +28 -26
- package/.docs/organized/code-examples/with-parent-id-grouping.md +7 -7
- package/.docs/organized/code-examples/with-react-hook-form.md +9 -9
- package/.docs/organized/code-examples/with-react-ink.md +265 -0
- package/.docs/organized/code-examples/with-react-router.md +12 -12
- package/.docs/organized/code-examples/with-store.md +33 -22
- package/.docs/organized/code-examples/with-tanstack.md +10 -10
- package/.docs/organized/code-examples/with-tap-runtime.md +12 -10
- package/.docs/raw/blog/2025-01-31-changelog/index.mdx +1 -1
- package/.docs/raw/blog/2026-03-launch-week/index.mdx +258 -0
- package/.docs/raw/docs/(docs)/architecture.mdx +1 -1
- package/.docs/raw/docs/(docs)/cli.mdx +74 -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 +74 -15
- 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/interactables.mdx +292 -0
- package/.docs/raw/docs/(docs)/guides/latex.mdx +3 -0
- package/.docs/raw/docs/(docs)/guides/message-timing.mdx +5 -4
- package/.docs/raw/docs/(docs)/guides/multi-agent.mdx +174 -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 +226 -44
- 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 +90 -6
- package/.docs/raw/docs/cloud/ai-sdk.mdx +95 -5
- 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 +840 -0
- package/.docs/raw/docs/primitives/action-bar.mdx +351 -0
- package/.docs/raw/docs/primitives/assistant-modal.mdx +215 -0
- package/.docs/raw/docs/primitives/attachment.mdx +216 -0
- package/.docs/raw/docs/primitives/branch-picker.mdx +221 -0
- package/.docs/raw/docs/primitives/chain-of-thought.mdx +311 -0
- package/.docs/raw/docs/primitives/composer.mdx +526 -0
- package/.docs/raw/docs/primitives/error.mdx +141 -0
- package/.docs/raw/docs/primitives/index.mdx +98 -0
- package/.docs/raw/docs/primitives/message.mdx +524 -0
- package/.docs/raw/docs/primitives/selection-toolbar.mdx +165 -0
- package/.docs/raw/docs/primitives/suggestion.mdx +242 -0
- package/.docs/raw/docs/primitives/thread-list.mdx +404 -0
- package/.docs/raw/docs/primitives/thread.mdx +482 -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/mention.mdx +168 -0
- 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 +5 -5
- 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
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Overview
|
|
3
|
+
description: Unstyled, accessible building blocks for AI chat interfaces.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Primitives are the foundation of assistant-ui. They are unstyled, accessible React components that handle all the wiring for AI chat, including state management, keyboard shortcuts, auto-scrolling, streaming, and tool calls, so you can focus entirely on your UI.
|
|
7
|
+
|
|
8
|
+
## Why Primitives?
|
|
9
|
+
|
|
10
|
+
Every assistant-ui [Component](/docs/ui/thread) is built from primitives. When you install a component like `Thread`, you get a pre-styled composition of primitives with default styling and behavior included.
|
|
11
|
+
|
|
12
|
+
But when you need a UI that doesn't fit the defaults, such as a floating composer, a custom message layout, or an inline editing experience, you reach for the primitives directly.
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import { ComposerPrimitive } from "@assistant-ui/react";
|
|
16
|
+
|
|
17
|
+
<ComposerPrimitive.Root>
|
|
18
|
+
<ComposerPrimitive.Input placeholder="Ask anything..." />
|
|
19
|
+
<ComposerPrimitive.Send>Send</ComposerPrimitive.Send>
|
|
20
|
+
</ComposerPrimitive.Root>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
This renders an unstyled `<form>` with a `<textarea>` and a `<button>`. No styles, no opinions, but it already handles submit-on-enter, focus management, empty-state disabling, and streaming state.
|
|
24
|
+
|
|
25
|
+
## How They Work
|
|
26
|
+
|
|
27
|
+
Every primitive follows the same pattern inspired by [Radix UI](https://www.radix-ui.com/):
|
|
28
|
+
|
|
29
|
+
- **`Primitive.Root`**: container that provides context to child parts
|
|
30
|
+
- **`Primitive.PartName`**: individual elements (input, button, text, etc.)
|
|
31
|
+
- **`asChild`**: merge primitive behavior onto your own element instead of rendering a wrapper
|
|
32
|
+
- **`AuiIf`**: conditional rendering based on state
|
|
33
|
+
|
|
34
|
+
Primitives read from the nearest runtime context. Place them inside an `AssistantRuntimeProvider` and they work without prop drilling or manual state wiring.
|
|
35
|
+
|
|
36
|
+
## Available Primitives
|
|
37
|
+
|
|
38
|
+
<Cards>
|
|
39
|
+
<Card title="Composer" href="/docs/primitives/composer">
|
|
40
|
+
Text input, send button, attachments, and dictation. The interface for composing new messages or editing existing ones.
|
|
41
|
+
</Card>
|
|
42
|
+
<Card title="Thread" href="/docs/primitives/thread">
|
|
43
|
+
The scrollable message container with auto-scroll, empty states, and message rendering.
|
|
44
|
+
</Card>
|
|
45
|
+
<Card title="Message" href="/docs/primitives/message">
|
|
46
|
+
Individual message rendering with role-based content, parts, and metadata.
|
|
47
|
+
</Card>
|
|
48
|
+
<Card title="ActionBar" href="/docs/primitives/action-bar">
|
|
49
|
+
Copy, reload, edit, and other message actions.
|
|
50
|
+
</Card>
|
|
51
|
+
<Card title="BranchPicker" href="/docs/primitives/branch-picker">
|
|
52
|
+
Navigate between message branches (alternative responses).
|
|
53
|
+
</Card>
|
|
54
|
+
<Card title="ThreadList" href="/docs/primitives/thread-list">
|
|
55
|
+
Multi-thread management: list, create, switch, and archive threads.
|
|
56
|
+
</Card>
|
|
57
|
+
<Card title="AssistantModal" href="/docs/primitives/assistant-modal">
|
|
58
|
+
Floating chat popover built on Radix UI Popover.
|
|
59
|
+
</Card>
|
|
60
|
+
<Card title="Attachment" href="/docs/primitives/attachment">
|
|
61
|
+
File and image attachment rendering.
|
|
62
|
+
</Card>
|
|
63
|
+
<Card title="Suggestion" href="/docs/primitives/suggestion">
|
|
64
|
+
Suggested prompts and quick actions.
|
|
65
|
+
</Card>
|
|
66
|
+
<Card title="SelectionToolbar" href="/docs/primitives/selection-toolbar">
|
|
67
|
+
Floating toolbar for text selection actions like quoting.
|
|
68
|
+
</Card>
|
|
69
|
+
<Card title="Error" href="/docs/primitives/error">
|
|
70
|
+
Error display with accessible alert role and automatic error text.
|
|
71
|
+
</Card>
|
|
72
|
+
<Card title="ChainOfThought" href="/docs/primitives/chain-of-thought">
|
|
73
|
+
Collapsible reasoning accordion for thinking steps and tool calls.
|
|
74
|
+
</Card>
|
|
75
|
+
</Cards>
|
|
76
|
+
|
|
77
|
+
`MessagePartPrimitive` (for rendering individual text, image, and streaming parts) is documented within the [Message](/docs/primitives/message#messagepartprimitive) primitive page.
|
|
78
|
+
|
|
79
|
+
## Related Primitive References
|
|
80
|
+
|
|
81
|
+
Additional primitive references:
|
|
82
|
+
|
|
83
|
+
- [MessagePartPrimitive](/docs/api-reference/primitives/message-part)
|
|
84
|
+
- [ThreadListItemPrimitive](/docs/api-reference/primitives/thread-list-item)
|
|
85
|
+
- [ThreadListItemMorePrimitive](/docs/api-reference/primitives/thread-list-item-more)
|
|
86
|
+
- [ActionBarMorePrimitive](/docs/api-reference/primitives/action-bar-more)
|
|
87
|
+
- [AssistantIf (`AuiIf`)](/docs/api-reference/primitives/assistant-if)
|
|
88
|
+
|
|
89
|
+
## Common Mistakes
|
|
90
|
+
|
|
91
|
+
- Forgetting to wrap primitives with runtime context (`AssistantRuntimeProvider` + runtime hook)
|
|
92
|
+
- Mixing deprecated props with current APIs (`submitOnEnter`, `autoSend`, legacy `Suggestion`)
|
|
93
|
+
- Mounting primitives in the wrong context (`ActionBarPrimitive` / `BranchPickerPrimitive` outside `MessagePrimitive.Root`)
|
|
94
|
+
- Using unstable props unintentionally (`unstable_*` APIs)
|
|
95
|
+
|
|
96
|
+
## Next Steps
|
|
97
|
+
|
|
98
|
+
Start with the [Composer](/docs/primitives/composer) primitive to see how primitives work in practice, or jump to the [API Reference](/docs/api-reference/primitives/composer) for full prop details.
|
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Message
|
|
3
|
+
description: Build custom message rendering with content parts, attachments, and hover state.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
import { MessagePrimitiveSample } from "@/components/docs/samples/message-primitive";
|
|
7
|
+
import { MessagePrimitive as MessagePrimitiveDocs } from "@/generated/primitiveDocs";
|
|
8
|
+
|
|
9
|
+
The Message primitive handles individual message rendering: content parts, attachments, quotes, hover state, and error display. It's the building block inside each message bubble, resolving text, images, tool calls, and more through a parts pipeline.
|
|
10
|
+
|
|
11
|
+
<Tabs items={["Preview", "Code"]}>
|
|
12
|
+
<Tab>
|
|
13
|
+
<MessagePrimitiveSample />
|
|
14
|
+
</Tab>
|
|
15
|
+
<Tab>
|
|
16
|
+
```tsx
|
|
17
|
+
import {
|
|
18
|
+
MessagePrimitive,
|
|
19
|
+
MessagePartPrimitive,
|
|
20
|
+
} from "@assistant-ui/react";
|
|
21
|
+
|
|
22
|
+
function UserMessage() {
|
|
23
|
+
return (
|
|
24
|
+
<MessagePrimitive.Root className="flex justify-end">
|
|
25
|
+
<div className="max-w-[80%] rounded-2xl bg-primary px-4 py-2.5 text-sm text-primary-foreground">
|
|
26
|
+
<MessagePrimitive.Parts>
|
|
27
|
+
{({ part }) => {
|
|
28
|
+
if (part.type === "text") return <UserText />;
|
|
29
|
+
return null;
|
|
30
|
+
}}
|
|
31
|
+
</MessagePrimitive.Parts>
|
|
32
|
+
</div>
|
|
33
|
+
</MessagePrimitive.Root>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function AssistantMessage() {
|
|
38
|
+
return (
|
|
39
|
+
<MessagePrimitive.Root className="flex justify-start gap-3">
|
|
40
|
+
<div className="flex size-8 items-center justify-center rounded-full bg-primary/10 text-xs font-medium text-primary">
|
|
41
|
+
AI
|
|
42
|
+
</div>
|
|
43
|
+
<div className="max-w-[80%] rounded-2xl bg-muted px-4 py-2.5 text-sm">
|
|
44
|
+
<MessagePrimitive.Parts>
|
|
45
|
+
{({ part }) => {
|
|
46
|
+
if (part.type === "text") return <AssistantText />;
|
|
47
|
+
return part.toolUI ?? null;
|
|
48
|
+
}}
|
|
49
|
+
</MessagePrimitive.Parts>
|
|
50
|
+
</div>
|
|
51
|
+
</MessagePrimitive.Root>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function UserText() {
|
|
56
|
+
return (
|
|
57
|
+
<p>
|
|
58
|
+
<MessagePartPrimitive.Text />
|
|
59
|
+
</p>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function AssistantText() {
|
|
64
|
+
return (
|
|
65
|
+
<p className="leading-relaxed">
|
|
66
|
+
<MessagePartPrimitive.Text />
|
|
67
|
+
</p>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
</Tab>
|
|
72
|
+
</Tabs>
|
|
73
|
+
|
|
74
|
+
## Quick Start
|
|
75
|
+
|
|
76
|
+
A minimal message with parts rendering:
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
import { MessagePrimitive } from "@assistant-ui/react";
|
|
80
|
+
|
|
81
|
+
<MessagePrimitive.Root>
|
|
82
|
+
<MessagePrimitive.Parts />
|
|
83
|
+
</MessagePrimitive.Root>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
`Root` renders a `<div>` that provides message context and tracks hover state. `Parts` iterates over the message's content parts and renders each one. Without custom components, parts render with sensible defaults: `Text` renders a `<p>` with `white-space: pre-line` and a streaming indicator, `Image` renders via `MessagePartPrimitive.Image`, and tool calls render nothing unless a tool UI is registered globally or inline. Reasoning, source, file, and audio parts render nothing by default.
|
|
87
|
+
|
|
88
|
+
<Callout type="info">
|
|
89
|
+
Runtime setup: primitives require runtime context. Wrap your UI in `AssistantRuntimeProvider` with a runtime (for example `useLocalRuntime(...)`). See [Pick a Runtime](/docs/runtimes/pick-a-runtime).
|
|
90
|
+
</Callout>
|
|
91
|
+
|
|
92
|
+
## Core Concepts
|
|
93
|
+
|
|
94
|
+
### Parts Pipeline
|
|
95
|
+
|
|
96
|
+
`MessagePrimitive.Parts` now prefers a children render function. It gives you the current enriched part state directly, so you can branch inline and return exactly the UI you want:
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
<MessagePrimitive.Parts>
|
|
100
|
+
{({ part }) => {
|
|
101
|
+
if (part.type === "text") return <MyTextRenderer />;
|
|
102
|
+
if (part.type === "image") return <MyImageRenderer />;
|
|
103
|
+
if (part.type === "tool-call")
|
|
104
|
+
return part.toolUI ?? <GenericToolUI {...part} />;
|
|
105
|
+
return null;
|
|
106
|
+
}}
|
|
107
|
+
</MessagePrimitive.Parts>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
<Callout type="info">
|
|
111
|
+
For most new `MessagePrimitive.Parts` code, prefer the `children` render function. Grouped Chain of Thought is the current exception: it plugs into `MessagePrimitive.Parts` via `components.ChainOfThought`.
|
|
112
|
+
</Callout>
|
|
113
|
+
|
|
114
|
+
### Tool Resolution
|
|
115
|
+
|
|
116
|
+
Tool call parts resolve in this order:
|
|
117
|
+
|
|
118
|
+
1. **`tools.Override`**: if provided inline through the deprecated `components` prop, handles **all** tool calls
|
|
119
|
+
2. **Globally registered tools**: tools registered via `makeAssistantTool` / `useAssistantToolUI`
|
|
120
|
+
3. **`tools.by_name[toolName]`**: per-`MessagePrimitive.Parts` inline overrides from the deprecated `components` prop
|
|
121
|
+
4. **`tools.Fallback`**: catch-all for unmatched tool calls from the deprecated `components` prop
|
|
122
|
+
5. **`part.toolUI`**: the resolved tool UI exposed directly in the children render function
|
|
123
|
+
|
|
124
|
+
In the children API, tool and data parts expose resolved UI helpers directly:
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
<MessagePrimitive.Parts>
|
|
128
|
+
{({ part }) => {
|
|
129
|
+
if (part.type === "tool-call")
|
|
130
|
+
return part.toolUI ?? <ToolFallback {...part} />;
|
|
131
|
+
|
|
132
|
+
if (part.type === "data")
|
|
133
|
+
return part.dataRendererUI ?? null;
|
|
134
|
+
|
|
135
|
+
return null;
|
|
136
|
+
}}
|
|
137
|
+
</MessagePrimitive.Parts>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Returning `null` still allows registered tool UIs and data renderer UIs to render automatically. Return `<></>` if you want to suppress them entirely.
|
|
141
|
+
|
|
142
|
+
### Components Prop (Deprecated)
|
|
143
|
+
|
|
144
|
+
`components` is deprecated. This section only documents it so older code is still understandable:
|
|
145
|
+
|
|
146
|
+
- `ToolGroup` wraps consecutive tool-call parts
|
|
147
|
+
- `ReasoningGroup` wraps consecutive reasoning parts
|
|
148
|
+
- `components.ChainOfThought` takes over all reasoning and tool-call rendering (mutually exclusive with `ToolGroup`, `ReasoningGroup`, `tools`, and `Reasoning`). Despite the deprecation of `components` in general, this is still the current way to wire grouped Chain of Thought.
|
|
149
|
+
- `data.by_name` and `data.Fallback` let you route custom data part types
|
|
150
|
+
- `Quote` renders quoted message references from metadata
|
|
151
|
+
- `Empty` and `Unstable_Audio` are available for edge and experimental rendering paths
|
|
152
|
+
|
|
153
|
+
```tsx
|
|
154
|
+
<MessagePrimitive.Parts
|
|
155
|
+
components={{
|
|
156
|
+
Text: () => (
|
|
157
|
+
<p className="whitespace-pre-wrap">
|
|
158
|
+
<MessagePartPrimitive.Text />
|
|
159
|
+
</p>
|
|
160
|
+
),
|
|
161
|
+
Image: () => <MessagePartPrimitive.Image className="max-w-sm rounded-xl" />,
|
|
162
|
+
File: () => <div className="rounded-md border px-2 py-1 text-xs">File part</div>,
|
|
163
|
+
tools: {
|
|
164
|
+
by_name: {
|
|
165
|
+
get_weather: () => <div>Weather tool</div>,
|
|
166
|
+
},
|
|
167
|
+
Fallback: ({ toolName }) => <div>Unknown tool: {toolName}</div>,
|
|
168
|
+
},
|
|
169
|
+
data: {
|
|
170
|
+
by_name: {
|
|
171
|
+
"my-event": ({ data }) => <pre>{JSON.stringify(data, null, 2)}</pre>,
|
|
172
|
+
},
|
|
173
|
+
Fallback: ({ name }) => <div>Unknown data event: {name}</div>,
|
|
174
|
+
},
|
|
175
|
+
ToolGroup: ({ children }) => (
|
|
176
|
+
<div className="space-y-2 rounded-lg border p-2">{children}</div>
|
|
177
|
+
),
|
|
178
|
+
ReasoningGroup: ({ children }) => (
|
|
179
|
+
<details className="rounded-lg border p-2">
|
|
180
|
+
<summary>Reasoning</summary>
|
|
181
|
+
{children}
|
|
182
|
+
</details>
|
|
183
|
+
),
|
|
184
|
+
Empty: () => <span className="text-muted-foreground">...</span>,
|
|
185
|
+
Unstable_Audio: () => null,
|
|
186
|
+
}}
|
|
187
|
+
/>
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
For new code, use the `children` render function instead.
|
|
191
|
+
|
|
192
|
+
### Hover State
|
|
193
|
+
|
|
194
|
+
`MessagePrimitive.Root` automatically tracks mouse enter/leave events. This hover state is consumed by `ActionBarPrimitive` to implement auto-hide behavior, with no extra wiring needed.
|
|
195
|
+
|
|
196
|
+
### MessagePartPrimitive
|
|
197
|
+
|
|
198
|
+
Inside your custom part components, use these sub-primitives to access the actual content:
|
|
199
|
+
|
|
200
|
+
- **`MessagePartPrimitive.Text`**: renders the text content of a text part
|
|
201
|
+
- **`MessagePartPrimitive.Image`**: renders the image of an image part
|
|
202
|
+
- **`MessagePartPrimitive.InProgress`**: renders only while the part is still streaming
|
|
203
|
+
|
|
204
|
+
```tsx
|
|
205
|
+
function MyText() {
|
|
206
|
+
return (
|
|
207
|
+
<p className="whitespace-pre-wrap">
|
|
208
|
+
<MessagePartPrimitive.Text />
|
|
209
|
+
<MessagePartPrimitive.InProgress>
|
|
210
|
+
<span className="animate-pulse">▊</span>
|
|
211
|
+
</MessagePartPrimitive.InProgress>
|
|
212
|
+
</p>
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Parts
|
|
218
|
+
|
|
219
|
+
### Root
|
|
220
|
+
|
|
221
|
+
Container for a single message. Renders a `<div>` element unless `asChild` is set.
|
|
222
|
+
|
|
223
|
+
```tsx
|
|
224
|
+
<MessagePrimitive.Root className="flex flex-col gap-2">
|
|
225
|
+
<MessagePrimitive.Quote>
|
|
226
|
+
{({ text }) => <blockquote className="mb-2 border-l pl-3 italic">{text}</blockquote>}
|
|
227
|
+
</MessagePrimitive.Quote>
|
|
228
|
+
<MessagePrimitive.Parts />
|
|
229
|
+
</MessagePrimitive.Root>
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Parts
|
|
233
|
+
|
|
234
|
+
Renders each content part with type-based component resolution.
|
|
235
|
+
|
|
236
|
+
```tsx
|
|
237
|
+
<MessagePrimitive.Parts>
|
|
238
|
+
{({ part }) => {
|
|
239
|
+
if (part.type === "text") return <MyTextRenderer />;
|
|
240
|
+
if (part.type === "image") return <MyImageRenderer />;
|
|
241
|
+
if (part.type === "tool-call")
|
|
242
|
+
return part.toolUI ?? <GenericToolUI {...part} />;
|
|
243
|
+
return null;
|
|
244
|
+
}}
|
|
245
|
+
</MessagePrimitive.Parts>
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
<PrimitivesTypeTable type="MessagePrimitivePartsProps" parameters={MessagePrimitiveDocs.Parts.props} />
|
|
249
|
+
|
|
250
|
+
### Content
|
|
251
|
+
|
|
252
|
+
Legacy alias for `Parts`.
|
|
253
|
+
|
|
254
|
+
```tsx
|
|
255
|
+
<MessagePrimitive.Content>
|
|
256
|
+
{({ part }) => {
|
|
257
|
+
if (part.type === "text") return <MyTextRenderer />;
|
|
258
|
+
return null;
|
|
259
|
+
}}
|
|
260
|
+
</MessagePrimitive.Content>
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### PartByIndex
|
|
264
|
+
|
|
265
|
+
Renders a single part at a specific index.
|
|
266
|
+
|
|
267
|
+
```tsx
|
|
268
|
+
<MessagePrimitive.PartByIndex
|
|
269
|
+
index={0}
|
|
270
|
+
components={{ Text: MyTextRenderer }}
|
|
271
|
+
/>
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Attachments
|
|
275
|
+
|
|
276
|
+
Renders all user message attachments.
|
|
277
|
+
|
|
278
|
+
```tsx
|
|
279
|
+
<MessagePrimitive.Attachments>
|
|
280
|
+
{({ attachment }) => {
|
|
281
|
+
if (attachment.type === "image") {
|
|
282
|
+
const imageSrc = attachment.content?.find((part) => part.type === "image")?.image;
|
|
283
|
+
if (!imageSrc) return null;
|
|
284
|
+
return <img src={imageSrc} alt={attachment.name} className="max-w-xs rounded-lg" />;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (attachment.type === "document") {
|
|
288
|
+
return (
|
|
289
|
+
<div className="rounded-lg border p-2 text-sm">
|
|
290
|
+
{attachment.name}
|
|
291
|
+
</div>
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return null;
|
|
296
|
+
}}
|
|
297
|
+
</MessagePrimitive.Attachments>
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
<PrimitivesTypeTable type="MessagePrimitiveAttachmentsProps" parameters={MessagePrimitiveDocs.Attachments.props} />
|
|
301
|
+
|
|
302
|
+
### AttachmentByIndex
|
|
303
|
+
|
|
304
|
+
Renders a single attachment at the specified index within the current message.
|
|
305
|
+
|
|
306
|
+
```tsx
|
|
307
|
+
<MessagePrimitive.AttachmentByIndex
|
|
308
|
+
index={0}
|
|
309
|
+
components={{ Attachment: MyAttachment }}
|
|
310
|
+
/>
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
<PrimitivesTypeTable type="MessagePrimitiveAttachmentByIndexProps" parameters={MessagePrimitiveDocs.AttachmentByIndex.props} />
|
|
314
|
+
|
|
315
|
+
### Error
|
|
316
|
+
|
|
317
|
+
Renders children only when the message has an error.
|
|
318
|
+
|
|
319
|
+
```tsx
|
|
320
|
+
<MessagePrimitive.Error>
|
|
321
|
+
<ErrorPrimitive.Root className="mt-2 rounded-md border border-destructive/20 bg-destructive/5 p-3">
|
|
322
|
+
<ErrorPrimitive.Message />
|
|
323
|
+
</ErrorPrimitive.Root>
|
|
324
|
+
</MessagePrimitive.Error>
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Quote
|
|
328
|
+
|
|
329
|
+
Renders quote metadata when the current message includes a quote. Place it above `MessagePrimitive.Parts`.
|
|
330
|
+
|
|
331
|
+
```tsx
|
|
332
|
+
<MessagePrimitive.Quote>
|
|
333
|
+
{({ text, messageId }) => (
|
|
334
|
+
<blockquote className="mb-2 border-l pl-3 italic" data-message-id={messageId}>
|
|
335
|
+
{text}
|
|
336
|
+
</blockquote>
|
|
337
|
+
)}
|
|
338
|
+
</MessagePrimitive.Quote>
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Unstable_PartsGrouped
|
|
342
|
+
|
|
343
|
+
Groups consecutive parts by a custom grouping function *(unstable)*.
|
|
344
|
+
|
|
345
|
+
```tsx
|
|
346
|
+
<MessagePrimitive.Unstable_PartsGrouped
|
|
347
|
+
groupingFunction={myGroupFn}
|
|
348
|
+
components={{ Text: MyText, Group: MyGroupWrapper }}
|
|
349
|
+
/>
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
<PrimitivesTypeTable type="MessagePrimitiveUnstablePartsGroupedProps" parameters={MessagePrimitiveDocs.Unstable_PartsGrouped.props} />
|
|
353
|
+
|
|
354
|
+
### Unstable_PartsGroupedByParentId
|
|
355
|
+
|
|
356
|
+
Groups parts by parent ID *(unstable, deprecated; use `Unstable_PartsGrouped`)*.
|
|
357
|
+
|
|
358
|
+
```tsx
|
|
359
|
+
<MessagePrimitive.Unstable_PartsGroupedByParentId
|
|
360
|
+
components={{ Text: MyText, Group: MyGroupWrapper }}
|
|
361
|
+
/>
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### If (deprecated)
|
|
365
|
+
|
|
366
|
+
<Callout type="warn">
|
|
367
|
+
Deprecated. Use [`AuiIf`](/docs/api-reference/primitives/assistant-if) instead.
|
|
368
|
+
</Callout>
|
|
369
|
+
|
|
370
|
+
```tsx
|
|
371
|
+
// Before (deprecated)
|
|
372
|
+
<MessagePrimitive.If user>...</MessagePrimitive.If>
|
|
373
|
+
<MessagePrimitive.If assistant>...</MessagePrimitive.If>
|
|
374
|
+
|
|
375
|
+
// After
|
|
376
|
+
<AuiIf condition={(s) => s.message.role === "user"}>...</AuiIf>
|
|
377
|
+
<AuiIf condition={(s) => s.message.role === "assistant"}>...</AuiIf>
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## Patterns
|
|
381
|
+
|
|
382
|
+
### Custom Text Rendering
|
|
383
|
+
|
|
384
|
+
```tsx
|
|
385
|
+
function MarkdownText() {
|
|
386
|
+
return (
|
|
387
|
+
<div className="prose prose-sm">
|
|
388
|
+
<MessagePartPrimitive.Text />
|
|
389
|
+
</div>
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
<MessagePrimitive.Parts>
|
|
394
|
+
{({ part }) => {
|
|
395
|
+
if (part.type === "text") return <MarkdownText />;
|
|
396
|
+
return null;
|
|
397
|
+
}}
|
|
398
|
+
</MessagePrimitive.Parts>
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### Tool UI with by_name
|
|
402
|
+
|
|
403
|
+
```tsx
|
|
404
|
+
<MessagePrimitive.Parts
|
|
405
|
+
components={{
|
|
406
|
+
Text: MyText,
|
|
407
|
+
tools: {
|
|
408
|
+
by_name: {
|
|
409
|
+
get_weather: ({ result }) => (
|
|
410
|
+
<div className="rounded-lg border p-3">
|
|
411
|
+
<p className="font-medium">Weather</p>
|
|
412
|
+
<p>{result?.temperature}°F, {result?.condition}</p>
|
|
413
|
+
</div>
|
|
414
|
+
),
|
|
415
|
+
},
|
|
416
|
+
Fallback: ({ toolName, status }) => (
|
|
417
|
+
<div className="text-muted-foreground text-sm">
|
|
418
|
+
{status.type === "running" ? `Running ${toolName}...` : `${toolName} completed`}
|
|
419
|
+
</div>
|
|
420
|
+
),
|
|
421
|
+
},
|
|
422
|
+
}}
|
|
423
|
+
/>
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### Error Display
|
|
427
|
+
|
|
428
|
+
```tsx
|
|
429
|
+
<MessagePrimitive.Root>
|
|
430
|
+
<MessagePrimitive.Parts />
|
|
431
|
+
<MessagePrimitive.Error>
|
|
432
|
+
<div className="mt-2 rounded-md bg-destructive/10 p-2 text-sm text-destructive">
|
|
433
|
+
Something went wrong. Please try again.
|
|
434
|
+
</div>
|
|
435
|
+
</MessagePrimitive.Error>
|
|
436
|
+
</MessagePrimitive.Root>
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### Error Display with ErrorPrimitive
|
|
440
|
+
|
|
441
|
+
For more control over error rendering, `ErrorPrimitive` provides a dedicated component that auto-reads the error string from the message status:
|
|
442
|
+
|
|
443
|
+
```tsx
|
|
444
|
+
import { ErrorPrimitive, MessagePrimitive } from "@assistant-ui/react";
|
|
445
|
+
|
|
446
|
+
<MessagePrimitive.Root>
|
|
447
|
+
<MessagePrimitive.Parts />
|
|
448
|
+
<ErrorPrimitive.Root className="mt-2 rounded-md bg-destructive/10 p-2 text-sm text-destructive" role="alert">
|
|
449
|
+
<ErrorPrimitive.Message />
|
|
450
|
+
</ErrorPrimitive.Root>
|
|
451
|
+
</MessagePrimitive.Root>
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
`ErrorPrimitive.Root` renders a `<div>` container with `role="alert"` and `ErrorPrimitive.Message` renders a `<span>` that displays the error text. `Root` always renders. Only `Message` conditionally returns `null` when there is no error. Wrap in `<MessagePrimitive.Error>` if you want the entire block to be conditional. See the [ErrorPrimitive API Reference](/docs/api-reference/primitives/error) for full details.
|
|
455
|
+
|
|
456
|
+
### Legacy and Unstable APIs
|
|
457
|
+
|
|
458
|
+
- `MessagePrimitive.Unstable_PartsGrouped` and `MessagePrimitive.Unstable_PartsGroupedByParentId` are unstable APIs for custom grouping.
|
|
459
|
+
- `Unstable_PartsGroupedByParentId` is deprecated in favor of `Unstable_PartsGrouped`.
|
|
460
|
+
|
|
461
|
+
### Role-Based Styling
|
|
462
|
+
|
|
463
|
+
`MessagePrimitive.Root` sets `data-message-id` automatically but does not set a `data-role` attribute. Style by role in your message components:
|
|
464
|
+
|
|
465
|
+
```tsx
|
|
466
|
+
// In your ThreadPrimitive.Messages children render function:
|
|
467
|
+
function UserMessage() {
|
|
468
|
+
return (
|
|
469
|
+
<MessagePrimitive.Root data-role="user" className="flex justify-end">
|
|
470
|
+
<MessagePrimitive.Parts />
|
|
471
|
+
</MessagePrimitive.Root>
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
function AssistantMessage() {
|
|
476
|
+
return (
|
|
477
|
+
<MessagePrimitive.Root data-role="assistant" className="flex justify-start">
|
|
478
|
+
<MessagePrimitive.Parts />
|
|
479
|
+
</MessagePrimitive.Root>
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
### Attachments
|
|
485
|
+
|
|
486
|
+
```tsx
|
|
487
|
+
<MessagePrimitive.Root>
|
|
488
|
+
<MessagePrimitive.Attachments>
|
|
489
|
+
{({ attachment }) => {
|
|
490
|
+
if (attachment.type === "image") {
|
|
491
|
+
const imageSrc = attachment.content?.find((part) => part.type === "image")?.image;
|
|
492
|
+
if (!imageSrc) return null;
|
|
493
|
+
return <img src={imageSrc} alt={attachment.name} className="max-w-xs rounded-lg" />;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
if (attachment.type === "document") {
|
|
497
|
+
return (
|
|
498
|
+
<div className="flex items-center gap-2 rounded-lg border p-2 text-sm">
|
|
499
|
+
📄 {attachment.name}
|
|
500
|
+
</div>
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
return null;
|
|
505
|
+
}}
|
|
506
|
+
</MessagePrimitive.Attachments>
|
|
507
|
+
<MessagePrimitive.Parts />
|
|
508
|
+
</MessagePrimitive.Root>
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
## Relationship to Components
|
|
512
|
+
|
|
513
|
+
The shadcn [Thread](/docs/ui/thread) component renders user and assistant messages built from these primitives. The pre-built `AssistantMessage` and `UserMessage` components handle text rendering, tool UIs, error display, and action bars, all using `MessagePrimitive` under the hood.
|
|
514
|
+
|
|
515
|
+
Messages are commonly paired with [ActionBar](/docs/primitives/action-bar) for copy/reload/edit actions and [BranchPicker](/docs/primitives/branch-picker) for navigating between alternative responses.
|
|
516
|
+
|
|
517
|
+
## API Reference
|
|
518
|
+
|
|
519
|
+
For full prop details on every part, see the [MessagePrimitive API Reference](/docs/api-reference/primitives/message).
|
|
520
|
+
|
|
521
|
+
Related:
|
|
522
|
+
- [MessagePartPrimitive API Reference](/docs/api-reference/primitives/message-part)
|
|
523
|
+
- [ActionBarPrimitive API Reference](/docs/api-reference/primitives/action-bar)
|
|
524
|
+
- [BranchPickerPrimitive API Reference](/docs/api-reference/primitives/branch-picker)
|