@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.
Files changed (151) hide show
  1. package/.docs/organized/code-examples/waterfall.md +8 -6
  2. package/.docs/organized/code-examples/with-a2a.md +676 -0
  3. package/.docs/organized/code-examples/with-ag-ui.md +10 -11
  4. package/.docs/organized/code-examples/with-ai-sdk-v6.md +31 -19
  5. package/.docs/organized/code-examples/with-artifacts.md +8 -8
  6. package/.docs/organized/code-examples/with-assistant-transport.md +6 -6
  7. package/.docs/organized/code-examples/with-chain-of-thought.md +37 -29
  8. package/.docs/organized/code-examples/with-cloud-standalone.md +14 -11
  9. package/.docs/organized/code-examples/with-cloud.md +8 -8
  10. package/.docs/organized/code-examples/with-custom-thread-list.md +10 -10
  11. package/.docs/organized/code-examples/with-elevenlabs-scribe.md +11 -11
  12. package/.docs/organized/code-examples/with-expo.md +571 -520
  13. package/.docs/organized/code-examples/with-external-store.md +6 -6
  14. package/.docs/organized/code-examples/with-ffmpeg.md +8 -8
  15. package/.docs/organized/code-examples/with-google-adk.md +353 -0
  16. package/.docs/organized/code-examples/with-heat-graph.md +304 -0
  17. package/.docs/organized/code-examples/with-interactables.md +778 -0
  18. package/.docs/organized/code-examples/with-langgraph.md +28 -26
  19. package/.docs/organized/code-examples/with-parent-id-grouping.md +7 -7
  20. package/.docs/organized/code-examples/with-react-hook-form.md +9 -9
  21. package/.docs/organized/code-examples/with-react-ink.md +265 -0
  22. package/.docs/organized/code-examples/with-react-router.md +12 -12
  23. package/.docs/organized/code-examples/with-store.md +33 -22
  24. package/.docs/organized/code-examples/with-tanstack.md +10 -10
  25. package/.docs/organized/code-examples/with-tap-runtime.md +12 -10
  26. package/.docs/raw/blog/2025-01-31-changelog/index.mdx +1 -1
  27. package/.docs/raw/blog/2026-03-launch-week/index.mdx +258 -0
  28. package/.docs/raw/docs/(docs)/architecture.mdx +1 -1
  29. package/.docs/raw/docs/(docs)/cli.mdx +74 -9
  30. package/.docs/raw/docs/(docs)/copilots/make-assistant-tool-ui.mdx +8 -3
  31. package/.docs/raw/docs/(docs)/copilots/make-assistant-tool.mdx +5 -1
  32. package/.docs/raw/docs/(docs)/copilots/{make-assistant-readable.mdx → make-assistant-visible.mdx} +14 -5
  33. package/.docs/raw/docs/(docs)/copilots/model-context.mdx +11 -11
  34. package/.docs/raw/docs/(docs)/copilots/motivation.mdx +2 -2
  35. package/.docs/raw/docs/(docs)/devtools.mdx +3 -2
  36. package/.docs/raw/docs/(docs)/guides/attachments.mdx +74 -15
  37. package/.docs/raw/docs/(docs)/guides/branching.mdx +11 -6
  38. package/.docs/raw/docs/(docs)/guides/chain-of-thought.mdx +18 -16
  39. package/.docs/raw/docs/(docs)/guides/context-api.mdx +81 -43
  40. package/.docs/raw/docs/(docs)/guides/dictation.mdx +5 -5
  41. package/.docs/raw/docs/(docs)/guides/editing.mdx +16 -7
  42. package/.docs/raw/docs/(docs)/guides/interactables.mdx +292 -0
  43. package/.docs/raw/docs/(docs)/guides/latex.mdx +3 -0
  44. package/.docs/raw/docs/(docs)/guides/message-timing.mdx +5 -4
  45. package/.docs/raw/docs/(docs)/guides/multi-agent.mdx +174 -0
  46. package/.docs/raw/docs/(docs)/guides/quoting.mdx +55 -206
  47. package/.docs/raw/docs/(docs)/guides/speech.mdx +1 -4
  48. package/.docs/raw/docs/(docs)/guides/suggestions.mdx +9 -15
  49. package/.docs/raw/docs/(docs)/guides/tool-ui.mdx +17 -7
  50. package/.docs/raw/docs/(docs)/guides/tools.mdx +24 -9
  51. package/.docs/raw/docs/(docs)/index.mdx +3 -3
  52. package/.docs/raw/docs/(docs)/installation.mdx +69 -46
  53. package/.docs/raw/docs/(reference)/api-reference/context-providers/text-message-part-provider.mdx +20 -6
  54. package/.docs/raw/docs/(reference)/api-reference/integrations/react-data-stream.mdx +24 -4
  55. package/.docs/raw/docs/(reference)/api-reference/integrations/react-hook-form.mdx +1 -1
  56. package/.docs/raw/docs/(reference)/api-reference/integrations/vercel-ai-sdk.mdx +20 -19
  57. package/.docs/raw/docs/(reference)/api-reference/overview.mdx +28 -53
  58. package/.docs/raw/docs/(reference)/api-reference/primitives/action-bar.mdx +4 -4
  59. package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-modal.mdx +7 -1
  60. package/.docs/raw/docs/(reference)/api-reference/primitives/attachment.mdx +20 -14
  61. package/.docs/raw/docs/(reference)/api-reference/primitives/branch-picker.mdx +1 -1
  62. package/.docs/raw/docs/(reference)/api-reference/primitives/composer.mdx +226 -44
  63. package/.docs/raw/docs/(reference)/api-reference/primitives/message-part.mdx +52 -40
  64. package/.docs/raw/docs/(reference)/api-reference/primitives/message.mdx +343 -23
  65. package/.docs/raw/docs/(reference)/api-reference/primitives/suggestion.mdx +4 -6
  66. package/.docs/raw/docs/(reference)/api-reference/primitives/thread-list-item.mdx +4 -2
  67. package/.docs/raw/docs/(reference)/api-reference/primitives/thread-list.mdx +3 -5
  68. package/.docs/raw/docs/(reference)/api-reference/primitives/thread.mdx +169 -22
  69. package/.docs/raw/docs/(reference)/api-reference/runtimes/assistant-runtime.mdx +14 -4
  70. package/.docs/raw/docs/(reference)/api-reference/runtimes/attachment-runtime.mdx +15 -26
  71. package/.docs/raw/docs/(reference)/api-reference/runtimes/composer-runtime.mdx +39 -21
  72. package/.docs/raw/docs/(reference)/api-reference/runtimes/message-part-runtime.mdx +33 -9
  73. package/.docs/raw/docs/(reference)/api-reference/runtimes/message-runtime.mdx +48 -21
  74. package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-list-item-runtime.mdx +36 -7
  75. package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-list-runtime.mdx +30 -10
  76. package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-runtime.mdx +12 -10
  77. package/.docs/raw/docs/(reference)/migrations/deprecation-policy.mdx +1 -1
  78. package/.docs/raw/docs/(reference)/migrations/react-langgraph-v0-7.mdx +9 -4
  79. package/.docs/raw/docs/(reference)/migrations/v0-11.mdx +7 -5
  80. package/.docs/raw/docs/(reference)/migrations/v0-12.mdx +9 -7
  81. package/.docs/raw/docs/(reference)/migrations/v0-14.mdx +159 -0
  82. package/.docs/raw/docs/(reference)/react-compatibility.mdx +5 -134
  83. package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +90 -6
  84. package/.docs/raw/docs/cloud/ai-sdk.mdx +95 -5
  85. package/.docs/raw/docs/cloud/langgraph.mdx +13 -3
  86. package/.docs/raw/docs/ink/adapters.mdx +41 -0
  87. package/.docs/raw/docs/ink/custom-backend.mdx +203 -0
  88. package/.docs/raw/docs/ink/hooks.mdx +448 -0
  89. package/.docs/raw/docs/ink/index.mdx +239 -0
  90. package/.docs/raw/docs/ink/migration.mdx +140 -0
  91. package/.docs/raw/docs/ink/primitives.mdx +840 -0
  92. package/.docs/raw/docs/primitives/action-bar.mdx +351 -0
  93. package/.docs/raw/docs/primitives/assistant-modal.mdx +215 -0
  94. package/.docs/raw/docs/primitives/attachment.mdx +216 -0
  95. package/.docs/raw/docs/primitives/branch-picker.mdx +221 -0
  96. package/.docs/raw/docs/primitives/chain-of-thought.mdx +311 -0
  97. package/.docs/raw/docs/primitives/composer.mdx +526 -0
  98. package/.docs/raw/docs/primitives/error.mdx +141 -0
  99. package/.docs/raw/docs/primitives/index.mdx +98 -0
  100. package/.docs/raw/docs/primitives/message.mdx +524 -0
  101. package/.docs/raw/docs/primitives/selection-toolbar.mdx +165 -0
  102. package/.docs/raw/docs/primitives/suggestion.mdx +242 -0
  103. package/.docs/raw/docs/primitives/thread-list.mdx +404 -0
  104. package/.docs/raw/docs/primitives/thread.mdx +482 -0
  105. package/.docs/raw/docs/react-native/adapters.mdx +63 -87
  106. package/.docs/raw/docs/react-native/custom-backend.mdx +11 -14
  107. package/.docs/raw/docs/react-native/hooks.mdx +214 -232
  108. package/.docs/raw/docs/react-native/index.mdx +118 -159
  109. package/.docs/raw/docs/react-native/migration.mdx +144 -0
  110. package/.docs/raw/docs/react-native/primitives.mdx +431 -302
  111. package/.docs/raw/docs/runtimes/a2a/index.mdx +294 -0
  112. package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +9 -9
  113. package/.docs/raw/docs/runtimes/ai-sdk/v5-legacy.mdx +14 -3
  114. package/.docs/raw/docs/runtimes/assistant-transport.mdx +59 -25
  115. package/.docs/raw/docs/runtimes/custom/custom-thread-list.mdx +13 -6
  116. package/.docs/raw/docs/runtimes/custom/external-store.mdx +138 -38
  117. package/.docs/raw/docs/runtimes/custom/local.mdx +184 -42
  118. package/.docs/raw/docs/runtimes/data-stream.mdx +92 -19
  119. package/.docs/raw/docs/runtimes/google-adk/index.mdx +624 -0
  120. package/.docs/raw/docs/runtimes/helicone.mdx +6 -6
  121. package/.docs/raw/docs/runtimes/langgraph/index.mdx +38 -27
  122. package/.docs/raw/docs/runtimes/langgraph/tutorial/introduction.mdx +1 -1
  123. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-1.mdx +15 -20
  124. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +7 -11
  125. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-3.mdx +8 -11
  126. package/.docs/raw/docs/runtimes/langserve.mdx +6 -7
  127. package/.docs/raw/docs/runtimes/pick-a-runtime.mdx +18 -3
  128. package/.docs/raw/docs/ui/file.mdx +5 -4
  129. package/.docs/raw/docs/ui/image.mdx +5 -4
  130. package/.docs/raw/docs/ui/markdown.mdx +3 -1
  131. package/.docs/raw/docs/ui/mention.mdx +168 -0
  132. package/.docs/raw/docs/ui/model-selector.mdx +8 -8
  133. package/.docs/raw/docs/ui/part-grouping.mdx +7 -10
  134. package/.docs/raw/docs/ui/quote.mdx +210 -0
  135. package/.docs/raw/docs/ui/reasoning.mdx +12 -11
  136. package/.docs/raw/docs/ui/sources.mdx +88 -17
  137. package/.docs/raw/docs/ui/streamdown.mdx +16 -7
  138. package/.docs/raw/docs/ui/thread-list.mdx +11 -13
  139. package/.docs/raw/docs/ui/thread.mdx +28 -33
  140. package/.docs/raw/docs/ui/tool-fallback.mdx +5 -6
  141. package/.docs/raw/docs/ui/tool-group.mdx +9 -8
  142. package/.docs/raw/docs/utilities/heat-graph.mdx +236 -0
  143. package/.docs/raw/docs/utilities/tw-shimmer.mdx +211 -0
  144. package/package.json +5 -5
  145. package/.docs/raw/docs/(reference)/legacy/styled/assistant-modal.mdx +0 -77
  146. package/.docs/raw/docs/(reference)/legacy/styled/decomposition.mdx +0 -635
  147. package/.docs/raw/docs/(reference)/legacy/styled/markdown.mdx +0 -77
  148. package/.docs/raw/docs/(reference)/legacy/styled/scrollbar.mdx +0 -72
  149. package/.docs/raw/docs/(reference)/legacy/styled/thread-width.mdx +0 -22
  150. package/.docs/raw/docs/(reference)/legacy/styled/thread.mdx +0 -77
  151. /package/.docs/raw/docs/cloud/{overview.mdx → index.mdx} +0 -0
@@ -94,14 +94,31 @@ const UserMessage = () => {
94
94
 
95
95
  ## Built-in Attachment Adapters
96
96
 
97
+ ### AI SDK Runtime (Default)
98
+
99
+ When using `useChatRuntime`, the built-in adapter accepts all file types and converts them to base64 data URLs. This works well for images and small files.
100
+
101
+ <Callout type="warn">
102
+ Most models only support **image** attachments. Sending unsupported file types (audio, video, PDF, etc.) will result in an API error. Check your model provider's documentation for supported input types.
103
+ </Callout>
104
+
105
+ To restrict accepted file types, pass a custom adapter:
106
+
107
+ ```tsx
108
+ const runtime = useChatRuntime({
109
+ adapters: {
110
+ attachments: new SimpleImageAttachmentAdapter(), // only images
111
+ },
112
+ });
113
+ ```
114
+
97
115
  ### SimpleImageAttachmentAdapter
98
116
 
99
- Handles image files and converts them to data URLs for display in the chat UI. By default, images are shown inline but not sent to the LLM - use the VisionImageAdapter example above to send images to vision-capable models.
117
+ Handles image files and converts them to data URLs for display in the chat UI.
100
118
 
101
119
  ```tsx
102
120
  const imageAdapter = new SimpleImageAttachmentAdapter();
103
121
  // Accepts: image/* (JPEG, PNG, GIF, etc.)
104
- // Output: { type: "image", url: "data:image/..." }
105
122
  ```
106
123
 
107
124
  ### SimpleTextAttachmentAdapter
@@ -111,7 +128,6 @@ Processes text files and wraps content in formatted tags:
111
128
  ```tsx
112
129
  const textAdapter = new SimpleTextAttachmentAdapter();
113
130
  // Accepts: text/plain, text/html, text/markdown, etc.
114
- // Output: Content wrapped in <attachment>...</attachment> tags
115
131
  ```
116
132
 
117
133
  ### CompositeAttachmentAdapter
@@ -122,7 +138,6 @@ Combines multiple adapters to support various file types:
122
138
  const compositeAdapter = new CompositeAttachmentAdapter([
123
139
  new SimpleImageAttachmentAdapter(),
124
140
  new SimpleTextAttachmentAdapter(),
125
- // Add more adapters as needed
126
141
  ]);
127
142
  ```
128
143
 
@@ -157,7 +172,7 @@ class VisionImageAdapter implements AttachmentAdapter {
157
172
  type: "image",
158
173
  name: file.name,
159
174
  file,
160
- status: { type: "running" },
175
+ status: { type: "requires-action", reason: "composer-send" },
161
176
  };
162
177
  }
163
178
 
@@ -224,7 +239,7 @@ class PDFAttachmentAdapter implements AttachmentAdapter {
224
239
  type: "document",
225
240
  name: file.name,
226
241
  file,
227
- status: { type: "running" },
242
+ status: { type: "requires-action", reason: "composer-send" },
228
243
  };
229
244
  }
230
245
 
@@ -360,7 +375,7 @@ class UploadAttachmentAdapter implements AttachmentAdapter {
360
375
  type: "file",
361
376
  name: file.name,
362
377
  file,
363
- status: { type: "running", progress: 0 },
378
+ status: { type: "running", reason: "uploading", progress: 0 },
364
379
  } as PendingAttachment;
365
380
 
366
381
  // Simulate upload progress
@@ -372,7 +387,7 @@ class UploadAttachmentAdapter implements AttachmentAdapter {
372
387
  type: "file",
373
388
  name: file.name,
374
389
  file,
375
- status: { type: "running", progress },
390
+ status: { type: "running", reason: "uploading", progress },
376
391
  } as PendingAttachment;
377
392
  }
378
393
 
@@ -382,7 +397,7 @@ class UploadAttachmentAdapter implements AttachmentAdapter {
382
397
  type: "file",
383
398
  name: file.name,
384
399
  file,
385
- status: { type: "running", progress: 100 },
400
+ status: { type: "running", reason: "uploading", progress: 100 },
386
401
  } as PendingAttachment;
387
402
  }
388
403
 
@@ -436,7 +451,6 @@ class ValidatedImageAdapter implements AttachmentAdapter {
436
451
  status: {
437
452
  type: "incomplete",
438
453
  reason: "error",
439
- error: new Error("File size exceeds 5MB limit"),
440
454
  },
441
455
  };
442
456
  }
@@ -456,7 +470,6 @@ class ValidatedImageAdapter implements AttachmentAdapter {
456
470
  status: {
457
471
  type: "incomplete",
458
472
  reason: "error",
459
- error,
460
473
  },
461
474
  };
462
475
  }
@@ -467,7 +480,7 @@ class ValidatedImageAdapter implements AttachmentAdapter {
467
480
  type: "image",
468
481
  name: file.name,
469
482
  file,
470
- status: { type: "running" },
483
+ status: { type: "requires-action", reason: "composer-send" },
471
484
  };
472
485
  }
473
486
 
@@ -514,7 +527,7 @@ const handleMultipleFiles = async (files: FileList) => {
514
527
  const filesToAdd = Array.from(files).slice(0, maxFiles);
515
528
 
516
529
  for (const file of filesToAdd) {
517
- await aui.composer().addAttachment({ file });
530
+ await aui.composer().addAttachment(file);
518
531
  }
519
532
  };
520
533
  ```
@@ -529,7 +542,7 @@ Attachments are sent to the backend as file content parts.
529
542
 
530
543
  Attachments work with all assistant-ui runtimes:
531
544
 
532
- - **AI SDK Runtime**: `useChatRuntime`, `useAssistantRuntime`
545
+ - **AI SDK Runtime**: `useChatRuntime`
533
546
  - **External Store**: `useExternalStoreRuntime`
534
547
  - **LangGraph**: `useLangGraphRuntime`
535
548
  - **Custom Runtimes**: Any runtime implementing the attachment interface
@@ -540,6 +553,52 @@ Attachments work with all assistant-ui runtimes:
540
553
  processing logic to fit your specific needs.
541
554
  </Callout>
542
555
 
556
+ ## Large File Uploads
557
+
558
+ The built-in adapters convert files to base64 data URLs in memory. For large files (long audio, video, etc.), this can cause performance issues. Instead, upload to a server and pass the URL:
559
+
560
+ ```tsx
561
+ class ServerUploadAdapter implements AttachmentAdapter {
562
+ accept = "*";
563
+ private urls = new Map<string, string>();
564
+
565
+ async *add({ file }: { file: File }) {
566
+ const id = crypto.randomUUID();
567
+ yield {
568
+ id, type: "file" as const, name: file.name, file,
569
+ contentType: file.type,
570
+ status: { type: "running" as const, reason: "uploading" as const, progress: 0 },
571
+ };
572
+
573
+ const form = new FormData();
574
+ form.append("file", file);
575
+ const { url } = await fetch("/api/upload", { method: "POST", body: form }).then(r => r.json());
576
+ this.urls.set(id, url);
577
+
578
+ yield {
579
+ id, type: "file" as const, name: file.name, file,
580
+ contentType: file.type,
581
+ status: { type: "requires-action" as const, reason: "composer-send" as const },
582
+ };
583
+ }
584
+
585
+ async send(attachment: PendingAttachment): Promise<CompleteAttachment> {
586
+ const url = this.urls.get(attachment.id)!;
587
+ this.urls.delete(attachment.id);
588
+ return {
589
+ ...attachment, status: { type: "complete" },
590
+ content: [{ type: "file", data: url, mimeType: attachment.contentType ?? "", filename: attachment.name }],
591
+ };
592
+ }
593
+
594
+ async remove() {}
595
+ }
596
+ ```
597
+
598
+ <Callout type="tip">
599
+ [assistant-ui Cloud](/docs/cloud/ai-sdk-assistant-ui) includes `CloudFileAttachmentAdapter` which handles large file uploads via presigned URLs out of the box.
600
+ </Callout>
601
+
543
602
  ## Best Practices
544
603
 
545
604
  1. **File Size Limits**: Always validate file sizes to prevent memory issues
@@ -552,4 +611,4 @@ Attachments work with all assistant-ui runtimes:
552
611
  ## Resources
553
612
 
554
613
  - [Attachment UI Components](/docs/ui/attachment) - UI implementation details
555
- - [API Reference](/docs/api-reference) - Detailed type definitions
614
+ - [API Reference](/docs/api-reference/overview) - Detailed type definitions
@@ -30,7 +30,7 @@ const Message = () => {
30
30
  ...
31
31
  <BranchPicker /> {/* <-- show the branch picker */}
32
32
  ...
33
- </EditComposerPrimitive.Root>
33
+ </MessagePrimitive.Root>
34
34
  );
35
35
  };
36
36
 
@@ -48,13 +48,18 @@ const BranchPicker = () => {
48
48
 
49
49
  ## API
50
50
 
51
- You can access the current branch state or navigate via the API as well.
52
- These APIs rely on the message state and may only be called inside a message component.
51
+ You can access the current branch state or navigate via the API as well.
52
+ These APIs rely on the message scope and may only be called inside a message component.
53
53
 
54
54
  ```tsx
55
- const hasBranches = useMessageIf({ hasBranches: true }); // whether branchCount is >= 2
55
+ import { useAui, useAuiState } from "@assistant-ui/react";
56
+
57
+ // read branch state
58
+ const { branchNumber, branchCount } = useAuiState((s) => s.message);
56
59
 
57
60
  // navigation
58
- const goToNextBranch = useGoToNextBranch(); // null if there is no next branch
59
- const goToPreviousBranch = useGoToPreviousBranch(); // null if there is no previous branch
61
+ const aui = useAui();
62
+ aui.message().switchToBranch({ position: "next" });
63
+ aui.message().switchToBranch({ position: "previous" });
64
+ aui.message().switchToBranch({ branchId: "some-id" });
60
65
  ```
@@ -47,9 +47,13 @@ const ChainOfThought: FC = () => {
47
47
  Thinking
48
48
  </ChainOfThoughtPrimitive.AccordionTrigger>
49
49
  <AuiIf condition={(s) => !s.chainOfThought.collapsed}>
50
- <ChainOfThoughtPrimitive.Parts
51
- components={{ Reasoning, tools: { Fallback: ToolFallback } }}
52
- />
50
+ <ChainOfThoughtPrimitive.Parts>
51
+ {({ part }) => {
52
+ if (part.type === "reasoning") return <Reasoning {...part} />;
53
+ if (part.type === "tool-call") return <ToolFallback {...part} />;
54
+ return null;
55
+ }}
56
+ </ChainOfThoughtPrimitive.Parts>
53
57
  </AuiIf>
54
58
  </ChainOfThoughtPrimitive.Root>
55
59
  );
@@ -58,12 +62,12 @@ const ChainOfThought: FC = () => {
58
62
  const AssistantMessage: FC = () => {
59
63
  return (
60
64
  <MessagePrimitive.Root>
61
- <MessagePrimitive.Parts
62
- components={{
63
- Text: MarkdownText,
64
- ChainOfThought, // groups reasoning + tool parts
65
+ <MessagePrimitive.Parts>
66
+ {({ part }) => {
67
+ if (part.type === "text") return <MarkdownText />;
68
+ return null;
65
69
  }}
66
- />
70
+ </MessagePrimitive.Parts>
67
71
  </MessagePrimitive.Root>
68
72
  );
69
73
  };
@@ -111,15 +115,13 @@ Renders the grouped parts when expanded (nothing when collapsed).
111
115
 
112
116
  ```tsx
113
117
  <AuiIf condition={(s) => !s.chainOfThought.collapsed}>
114
- <ChainOfThoughtPrimitive.Parts
115
- components={{
116
- Reasoning,
117
- tools: { Fallback: ToolFallback },
118
- Layout: ({ children }) => (
119
- <div className="border-l-2 border-muted pl-4">{children}</div>
120
- ),
118
+ <ChainOfThoughtPrimitive.Parts>
119
+ {({ part }) => {
120
+ if (part.type === "reasoning") return <Reasoning {...part} />;
121
+ if (part.type === "tool-call") return <ToolFallback {...part} />;
122
+ return null;
121
123
  }}
122
- />
124
+ </ChainOfThoughtPrimitive.Parts>
123
125
  </AuiIf>
124
126
  ```
125
127
 
@@ -30,13 +30,18 @@ assistant-ui organizes state into **scopes** - logical boundaries that provide a
30
30
  └── 💬 Thread (thread) - Active conversation with messages
31
31
  ├── 🔵 Message (message) - User or assistant message
32
32
  │ ├── 📝 Part (part) - Content within a message (text, tool calls, etc.)
33
+ │ ├── 🧠 ChainOfThought (chainOfThought) - Reasoning steps within a message
34
+ │ │ └── 📝 Part (part) - Individual reasoning/tool-call step
33
35
  │ ├── 📎 Attachment (attachment) - Files attached to messages
34
36
  │ └── ✏️ Composer (composer) - Edit mode for existing messages
35
37
  │ └── 📎 Attachment (attachment) - Files in edit mode
36
38
  └── ✏️ Composer (composer) - New message input
37
39
  └── 📎 Attachment (attachment) - Files being added
38
40
 
41
+ 💡 Suggestions (suggestions) - Follow-up message suggestions
42
+ └── 💬 Suggestion (suggestion) - Individual suggestion item
39
43
  🔧 Tools (tools) - Custom UI components for tool calls
44
+ 🧩 ModelContext (modelContext) - Model context and tool registration
40
45
  ```
41
46
 
42
47
  **How scopes work:**
@@ -166,12 +171,12 @@ The API object is stable and doesn't cause re-renders. Use it for:
166
171
  // Thread actions
167
172
  aui.thread().append(message);
168
173
  aui.thread().startRun(config);
174
+ aui.thread().resumeRun(config);
169
175
  aui.thread().cancelRun();
170
- aui.thread().switchToNewThread();
171
- aui.thread().switchToThread(threadId);
172
176
  aui.thread().getState();
173
- aui.thread().message(idOrIndex);
174
- aui.thread().composer;
177
+ aui.thread().message({ index: idx });
178
+ aui.thread().message({ id: messageId });
179
+ aui.thread().composer();
175
180
 
176
181
  // Message actions
177
182
  aui.message().reload();
@@ -180,12 +185,14 @@ aui.message().stopSpeaking();
180
185
  aui.message().submitFeedback({ type: "positive" | "negative" });
181
186
  aui.message().switchToBranch({ position, branchId });
182
187
  aui.message().getState();
183
- aui.message().part(indexOrToolCallId);
184
- aui.message().composer;
188
+ aui.message().part({ index: idx });
189
+ aui.message().part({ toolCallId });
190
+ aui.message().composer();
185
191
 
186
192
  // Part actions
187
- api.part().addResult(result);
188
- api.part().getState();
193
+ aui.part().addToolResult(result);
194
+ aui.part().resumeToolCall(result);
195
+ aui.part().getState();
189
196
 
190
197
  // Composer actions
191
198
  aui.composer().send();
@@ -193,8 +200,8 @@ aui.composer().setText(text);
193
200
  aui.composer().setRole(role);
194
201
  aui.composer().addAttachment(file); // File object
195
202
  aui.composer().addAttachment({ name, content }); // external source
196
- aui.composer().clearAttachments();
197
- aui.composer().reset();
203
+ await aui.composer().clearAttachments();
204
+ await aui.composer().reset();
198
205
  aui.composer().getState();
199
206
 
200
207
  // Attachment actions
@@ -212,7 +219,23 @@ aui.threadListItem().rename(title);
212
219
  aui.threadListItem().archive();
213
220
  aui.threadListItem().unarchive();
214
221
  aui.threadListItem().delete();
215
- aui.threads().getState();
222
+ aui.threadListItem().getState();
223
+
224
+ // Suggestions actions
225
+ aui.suggestions().getState();
226
+ aui.suggestions().suggestion({ index: 0 });
227
+
228
+ // Suggestion actions
229
+ aui.suggestion().getState();
230
+
231
+ // ChainOfThought actions
232
+ aui.chainOfThought().getState();
233
+ aui.chainOfThought().setCollapsed(collapsed);
234
+ aui.chainOfThought().part({ index: 0 });
235
+
236
+ // ModelContext actions
237
+ aui.modelContext().getState();
238
+ aui.modelContext().register(provider);
216
239
 
217
240
  // Tools actions
218
241
  aui.tools().setToolUI(toolName, render);
@@ -228,26 +251,29 @@ import { useAuiEvent } from "@assistant-ui/react";
228
251
 
229
252
  // Listen to current scope events (most common)
230
253
  useAuiEvent("composer.send", (event) => {
231
- console.log("Current composer sent message:", event.message);
254
+ console.log("Composer sent message in thread:", event.threadId);
255
+ });
256
+
257
+ // Listen to thread events
258
+ useAuiEvent("thread.runStart", (event) => {
259
+ console.log("Run started in thread:", event.threadId);
232
260
  });
233
261
 
234
262
  // Listen to all events of a type across all scopes
235
263
  useAuiEvent({ event: "composer.send", scope: "*" }, (event) => {
236
- console.log("Any composer sent a message:", event);
264
+ console.log("Any composer sent a message:", event.threadId);
237
265
  });
238
266
 
239
267
  // Listen to ALL events (useful for debugging or analytics)
240
268
  useAuiEvent("*", (event) => {
241
- console.log("Event occurred:", event.type, "from:", event.source);
242
- // Send to analytics, logging, etc.
269
+ console.log("Event occurred:", event.event, event.payload);
243
270
  });
244
271
 
245
272
  // Practical example: Track user interactions
246
273
  function AnalyticsTracker() {
247
274
  useAuiEvent("composer.send", (event) => {
248
275
  analytics.track("message_sent", {
249
- messageLength: event.message.content.length,
250
- hasAttachments: event.message.attachments.length > 0,
276
+ threadId: event.threadId,
251
277
  });
252
278
  });
253
279
 
@@ -272,9 +298,13 @@ Each scope provides access to specific state and actions:
272
298
  - **Thread** (`thread`): Conversation with messages
273
299
  - **Message** (`message`): Individual message (user or assistant)
274
300
  - **Part** (`part`): Content part within a message (text, tool calls, etc.)
301
+ - **ChainOfThought** (`chainOfThought`): Reasoning steps grouped within a message
275
302
  - **Composer** (`composer`): Text input for sending or editing messages
276
303
  - **Attachment** (`attachment`): File or media attached to a message or composer
304
+ - **Suggestions** (`suggestions`): Collection of follow-up message suggestions
305
+ - **Suggestion** (`suggestion`): Individual follow-up suggestion
277
306
  - **Tools** (`tools`): Tool UI components
307
+ - **ModelContext** (`modelContext`): Model context and tool registration
278
308
 
279
309
  ### Scope Resolution
280
310
 
@@ -301,7 +331,7 @@ Before accessing a scope, check if it's available:
301
331
  const aui = useAui();
302
332
 
303
333
  // Check if message scope exists
304
- if (api.message.source) {
334
+ if (aui.message.source) {
305
335
  // Safe to use message scope
306
336
  const { role } = aui.message().getState();
307
337
  }
@@ -325,9 +355,9 @@ const partByToolCall = aui.message().part({ toolCallId: "call_123" });
325
355
  // Access attachment by index
326
356
  const attachment = aui.composer().attachment({ index: 0 }).getState();
327
357
 
328
- // Access thread from thread list
329
- const thread = aui.threads().thread("main");
358
+ // Access thread list item by ID or index
330
359
  const threadItem = aui.threads().item({ id: "thread_123" });
360
+ const threadByIndex = aui.threads().item({ index: 0 });
331
361
  ```
332
362
 
333
363
  ## Common Patterns
@@ -400,7 +430,7 @@ function MessageCounter() {
400
430
 
401
431
  ### Resolution Dynamics
402
432
 
403
- When you call `api.scope()`, the API resolves the current scope at that moment. This resolution happens each time you call the function, which matters when dealing with changing contexts:
433
+ When you call `aui.scope()`, the API resolves the current scope at that moment. This resolution happens each time you call the function, which matters when dealing with changing contexts:
404
434
 
405
435
  ```tsx
406
436
  const aui = useAui();
@@ -458,27 +488,35 @@ const isRunning = useAuiState((s) => s.thread.isRunning);
458
488
 
459
489
  ### Scope States
460
490
 
461
- | Scope | Key State Properties | Description |
462
- | -------------- | --------------------------------------------------------------------------------- | ------------------------------------------------ |
463
- | ThreadList | `mainThreadId`, `threadIds`, `isLoading`, `threadItems` | Manages all available conversation threads |
464
- | ThreadListItem | `id`, `title`, `status`, `remoteId`, `externalId` | Individual thread metadata and status |
465
- | Thread | `isRunning`, `isLoading`, `isDisabled`, `messages`, `capabilities`, `suggestions` | Active conversation state and message history |
466
- | Message | `role`, `content`, `status`, `attachments`, `parentId`, `branchNumber`, `isLast` | Individual message content and metadata |
467
- | Composer | `text`, `role`, `attachments`, `isEmpty`, `canCancel`, `type`, `isEditing` | Text input state for new/edited messages |
468
- | Part | `type`, `content`, `status`, `text`, `toolCallId`, `toolName` | Content parts within messages (text, tool calls) |
469
- | Attachment | `id`, `type`, `name`, `url`, `size`, `mimeType` | File attachments metadata and content |
491
+ | Scope | Key State Properties | Description |
492
+ | -------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------- |
493
+ | ThreadList | `mainThreadId`, `newThreadId`, `threadIds`, `archivedThreadIds`, `isLoading`, `threadItems` | Manages all available conversation threads |
494
+ | ThreadListItem | `id`, `title`, `status`, `remoteId`, `externalId` | Individual thread metadata and status |
495
+ | Thread | `isRunning`, `isLoading`, `isDisabled`, `isEmpty`, `messages`, `capabilities`, `suggestions` | Active conversation state and message history |
496
+ | Message | `role`, `content`, `status`, `attachments`, `parts`, `parentId`, `branchNumber`, `branchCount`, `isLast`, `index` | Individual message content and metadata |
497
+ | Part | `type`, `status`, `text`, `toolCallId`, `toolName` | Content parts within messages (text, tool calls) |
498
+ | ChainOfThought | `parts`, `collapsed`, `status` | Reasoning steps grouped within a message |
499
+ | Composer | `text`, `role`, `attachments`, `isEmpty`, `canCancel`, `type`, `isEditing` | Text input state for new/edited messages |
500
+ | Attachment | `id`, `type`, `name`, `contentType`, `status` | File attachments metadata and content |
501
+ | Suggestions | `suggestions` | Collection of follow-up message suggestions |
502
+ | Suggestion | `title`, `label`, `prompt` | Individual suggestion with title, label, and prompt |
503
+ | ModelContext | *(empty — use `register()` / `getToolCallParams()` methods)* | Model context and tool registration |
470
504
 
471
505
  ### Available Actions by Scope
472
506
 
473
- | Scope | Actions | Use Cases |
474
- | -------------- | ------------------------------------------------------------------------- | ----------------------------------------- |
475
- | ThreadList | `switchToNewThread()`, `switchToThread(id)`, `getState()` | Thread navigation and creation |
476
- | ThreadListItem | `switchTo()`, `rename(title)`, `archive()`, `unarchive()`, `delete()` | Thread management operations |
477
- | Thread | `append(message)`, `startRun()`, `cancelRun()`, `switchToNewThread()` | Message handling and conversation control |
478
- | Message | `reload()`, `speak()`, `stopSpeaking()`, `submitFeedback(feedback)` | Message interactions and regeneration |
479
- | Composer | `send()`, `setText(text)`, `addAttachment(file \| attachment)`, `reset()` | Text input and message composition |
480
- | Part | `addResult(result)`, `getState()` | Tool call result handling |
481
- | Attachment | `remove()`, `getState()` | File management |
507
+ | Scope | Actions | Use Cases |
508
+ | -------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
509
+ | ThreadList | `switchToNewThread()`, `switchToThread(id)`, `item(selector)`, `thread("main")`, `getState()` | Thread navigation and creation |
510
+ | ThreadListItem | `switchTo()`, `rename(title)`, `archive()`, `unarchive()`, `delete()`, `getState()` | Thread management operations |
511
+ | Thread | `append(message)`, `startRun(config)`, `resumeRun(config)`, `cancelRun()`, `reset()`, `export()`, `import(repository)`, `message(selector)`, `composer()`, `getState()` | Message handling and conversation control |
512
+ | Message | `reload()`, `speak()`, `stopSpeaking()`, `submitFeedback(feedback)`, `switchToBranch(options)`, `getCopyText()`, `part(selector)`, `attachment(selector)`, `composer()`, `setIsCopied(value)`, `setIsHovering(value)`, `getState()` | Message interactions and regeneration |
513
+ | Part | `addToolResult(result)`, `resumeToolCall(result)`, `getState()` | Tool call result handling |
514
+ | ChainOfThought | `setCollapsed(collapsed)`, `part({ index })`, `getState()` | Expand/collapse reasoning steps |
515
+ | Composer | `send()`, `setText(text)`, `setRole(role)`, `addAttachment(file \| attachment)`, `clearAttachments()` (async), `reset()` (async), `getState()` | Text input and message composition |
516
+ | Attachment | `remove()`, `getState()` | File management |
517
+ | Suggestions | `suggestion({ index })`, `getState()` | Access follow-up suggestions |
518
+ | Suggestion | `getState()` | Read individual suggestion data |
519
+ | ModelContext | `register(provider)`, `getState()` | Register model context providers |
482
520
 
483
521
  ### Common Events
484
522
 
@@ -508,7 +546,7 @@ function SafeMessageButton() {
508
546
  const aui = useAui();
509
547
 
510
548
  const role = useAuiState((s) =>
511
- api.message.source !== undefined ? s.message.role : "none",
549
+ aui.message.source !== undefined ? s.message.role : "none",
512
550
  );
513
551
 
514
552
  return <div>Role: {role}</div>;
@@ -558,18 +596,18 @@ const value = useAuiState((s) => s.scope.property);
558
596
 
559
597
  // Perform action
560
598
  const aui = useAui();
561
- api.scope().action();
599
+ aui.scope().action();
562
600
 
563
601
  // Listen to events
564
602
  useAuiEvent("source.event", (e) => {});
565
603
 
566
604
  // Check scope availability
567
- if (api.scope.source) {
605
+ if (aui.scope.source) {
568
606
  /* scope exists */
569
607
  }
570
608
 
571
609
  // Get state imperatively
572
- const state = api.scope().getState();
610
+ const state = aui.scope().getState();
573
611
 
574
612
  // Navigate scopes
575
613
  aui.thread().message({ id: "..." }).getState();
@@ -38,7 +38,7 @@ const runtime = useChatRuntime({
38
38
  The dictation feature uses `ComposerPrimitive.Dictate` and `ComposerPrimitive.StopDictation` components.
39
39
 
40
40
  ```tsx
41
- import { ComposerPrimitive } from "@assistant-ui/react";
41
+ import { AuiIf, ComposerPrimitive } from "@assistant-ui/react";
42
42
  import { MicIcon, SquareIcon } from "lucide-react";
43
43
 
44
44
  const ComposerWithDictation = () => (
@@ -46,18 +46,18 @@ const ComposerWithDictation = () => (
46
46
  <ComposerPrimitive.Input />
47
47
 
48
48
  {/* Show Dictate button when not dictating */}
49
- <ComposerPrimitive.If dictation={false}>
49
+ <AuiIf condition={(s) => s.composer.dictation == null}>
50
50
  <ComposerPrimitive.Dictate>
51
51
  <MicIcon />
52
52
  </ComposerPrimitive.Dictate>
53
- </ComposerPrimitive.If>
53
+ </AuiIf>
54
54
 
55
55
  {/* Show Stop button when dictating */}
56
- <ComposerPrimitive.If dictation>
56
+ <AuiIf condition={(s) => s.composer.dictation != null}>
57
57
  <ComposerPrimitive.StopDictation>
58
58
  <SquareIcon className="animate-pulse" />
59
59
  </ComposerPrimitive.StopDictation>
60
- </ComposerPrimitive.If>
60
+ </AuiIf>
61
61
 
62
62
  <ComposerPrimitive.Send />
63
63
  </ComposerPrimitive.Root>
@@ -9,8 +9,8 @@ Give the user the ability to edit their message.
9
9
 
10
10
  You can show an editor interface by using `ComposerPrimitive`.
11
11
 
12
- ```tsx {1,11,25,31-43}
13
- import { ComposerPrimitive } from "@assistant-ui/react";
12
+ ```tsx {1-2,11,25,31-52}
13
+ import { ComposerPrimitive, useAuiState } from "@assistant-ui/react";
14
14
  ...
15
15
 
16
16
  const Thread = () => {
@@ -18,10 +18,12 @@ const Thread = () => {
18
18
  <ThreadPrimitive.Root>
19
19
  <ThreadPrimitive.Viewport>
20
20
  ...
21
- <ThreadPrimitive.Messages components={{
22
- ...,
23
- EditComposer, // <-- Show our new component during edit mode
24
- }} />
21
+ <ThreadPrimitive.Messages>
22
+ {({ message }) => {
23
+ // Show our new component during edit mode
24
+ return <MessageWithEditComposer />;
25
+ }}
26
+ </ThreadPrimitive.Messages>
25
27
  </ThreadPrimitive.Viewport>
26
28
  ...
27
29
  </ThreadPrimitive.Root>
@@ -40,7 +42,14 @@ const UserMessage = () => {
40
42
  );
41
43
  };
42
44
 
43
- // define a new component
45
+ // define a wrapper component that handles both display and edit mode
46
+ const MessageWithEditComposer = () => {
47
+ const isEditing = useAuiState((s) => s.composer.isEditing);
48
+ if (isEditing) return <EditComposer />;
49
+ return <UserMessage />;
50
+ };
51
+
52
+ // define the edit composer component
44
53
  const EditComposer = () => {
45
54
  return (
46
55
  // you can return a MessagePrimitive including a ComposerPrimitive, or only a ComposerPrimitive