@assistant-ui/mcp-docs-server 0.1.22 → 0.1.24

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 (75) hide show
  1. package/.docs/organized/code-examples/waterfall.md +801 -0
  2. package/.docs/organized/code-examples/with-ag-ui.md +39 -27
  3. package/.docs/organized/code-examples/with-ai-sdk-v6.md +39 -29
  4. package/.docs/organized/code-examples/with-artifacts.md +467 -0
  5. package/.docs/organized/code-examples/with-assistant-transport.md +32 -25
  6. package/.docs/organized/code-examples/with-chain-of-thought.md +42 -33
  7. package/.docs/organized/code-examples/with-cloud-standalone.md +674 -0
  8. package/.docs/organized/code-examples/with-cloud.md +35 -28
  9. package/.docs/organized/code-examples/with-custom-thread-list.md +35 -28
  10. package/.docs/organized/code-examples/with-elevenlabs-scribe.md +42 -31
  11. package/.docs/organized/code-examples/with-expo.md +2012 -0
  12. package/.docs/organized/code-examples/with-external-store.md +32 -26
  13. package/.docs/organized/code-examples/with-ffmpeg.md +32 -28
  14. package/.docs/organized/code-examples/with-langgraph.md +97 -39
  15. package/.docs/organized/code-examples/with-parent-id-grouping.md +33 -26
  16. package/.docs/organized/code-examples/with-react-hook-form.md +63 -61
  17. package/.docs/organized/code-examples/with-react-router.md +38 -31
  18. package/.docs/organized/code-examples/with-store.md +17 -25
  19. package/.docs/organized/code-examples/with-tanstack.md +36 -26
  20. package/.docs/organized/code-examples/with-tap-runtime.md +11 -25
  21. package/.docs/raw/docs/(docs)/cli.mdx +13 -6
  22. package/.docs/raw/docs/(docs)/guides/attachments.mdx +26 -3
  23. package/.docs/raw/docs/(docs)/guides/chain-of-thought.mdx +5 -5
  24. package/.docs/raw/docs/(docs)/guides/context-api.mdx +53 -52
  25. package/.docs/raw/docs/(docs)/guides/dictation.mdx +0 -2
  26. package/.docs/raw/docs/(docs)/guides/message-timing.mdx +169 -0
  27. package/.docs/raw/docs/(docs)/guides/quoting.mdx +327 -0
  28. package/.docs/raw/docs/(docs)/guides/speech.mdx +0 -1
  29. package/.docs/raw/docs/(docs)/index.mdx +12 -2
  30. package/.docs/raw/docs/(docs)/installation.mdx +8 -2
  31. package/.docs/raw/docs/(docs)/llm.mdx +9 -7
  32. package/.docs/raw/docs/(reference)/api-reference/primitives/action-bar-more.mdx +1 -1
  33. package/.docs/raw/docs/(reference)/api-reference/primitives/action-bar.mdx +2 -2
  34. package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-if.mdx +27 -27
  35. package/.docs/raw/docs/(reference)/api-reference/primitives/composer.mdx +60 -0
  36. package/.docs/raw/docs/(reference)/api-reference/primitives/message-part.mdx +78 -4
  37. package/.docs/raw/docs/(reference)/api-reference/primitives/message.mdx +32 -0
  38. package/.docs/raw/docs/(reference)/api-reference/primitives/selection-toolbar.mdx +61 -0
  39. package/.docs/raw/docs/(reference)/api-reference/primitives/thread.mdx +1 -1
  40. package/.docs/raw/docs/(reference)/legacy/styled/assistant-modal.mdx +1 -6
  41. package/.docs/raw/docs/(reference)/legacy/styled/decomposition.mdx +2 -2
  42. package/.docs/raw/docs/(reference)/legacy/styled/markdown.mdx +1 -6
  43. package/.docs/raw/docs/(reference)/legacy/styled/thread.mdx +1 -5
  44. package/.docs/raw/docs/(reference)/migrations/v0-12.mdx +17 -17
  45. package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +209 -0
  46. package/.docs/raw/docs/cloud/ai-sdk.mdx +296 -0
  47. package/.docs/raw/docs/cloud/authorization.mdx +178 -79
  48. package/.docs/raw/docs/cloud/{persistence/langgraph.mdx → langgraph.mdx} +2 -2
  49. package/.docs/raw/docs/cloud/overview.mdx +29 -39
  50. package/.docs/raw/docs/react-native/adapters.mdx +118 -0
  51. package/.docs/raw/docs/react-native/custom-backend.mdx +210 -0
  52. package/.docs/raw/docs/react-native/hooks.mdx +364 -0
  53. package/.docs/raw/docs/react-native/index.mdx +332 -0
  54. package/.docs/raw/docs/react-native/primitives.mdx +653 -0
  55. package/.docs/raw/docs/runtimes/ai-sdk/v6.mdx +60 -15
  56. package/.docs/raw/docs/runtimes/assistant-transport.mdx +103 -0
  57. package/.docs/raw/docs/runtimes/custom/external-store.mdx +25 -2
  58. package/.docs/raw/docs/runtimes/data-stream.mdx +1 -3
  59. package/.docs/raw/docs/runtimes/langgraph/index.mdx +113 -9
  60. package/.docs/raw/docs/runtimes/pick-a-runtime.mdx +1 -4
  61. package/.docs/raw/docs/ui/attachment.mdx +4 -2
  62. package/.docs/raw/docs/ui/context-display.mdx +147 -0
  63. package/.docs/raw/docs/ui/message-timing.mdx +92 -0
  64. package/.docs/raw/docs/ui/part-grouping.mdx +1 -1
  65. package/.docs/raw/docs/ui/reasoning.mdx +4 -4
  66. package/.docs/raw/docs/ui/scrollbar.mdx +2 -2
  67. package/.docs/raw/docs/ui/syntax-highlighting.mdx +55 -50
  68. package/.docs/raw/docs/ui/thread.mdx +16 -9
  69. package/dist/index.d.ts +1 -1
  70. package/dist/index.d.ts.map +1 -1
  71. package/package.json +3 -3
  72. package/src/tools/tests/integration.test.ts +2 -2
  73. package/src/tools/tests/json-parsing.test.ts +1 -1
  74. package/src/tools/tests/mcp-protocol.test.ts +1 -3
  75. package/.docs/raw/docs/cloud/persistence/ai-sdk.mdx +0 -108
@@ -0,0 +1,92 @@
1
+ ---
2
+ title: Message Timing
3
+ description: Display streaming performance stats — TTFT, total time, tok/s, and chunk count — as a badge with hover popover.
4
+ ---
5
+
6
+ import { MessageTimingSample } from "@/components/docs/samples/message-timing";
7
+
8
+ <MessageTimingSample />
9
+
10
+ <Callout type="warn">
11
+ This component is experimental. The API and displayed metrics may change in future versions. When used with the Vercel AI SDK, token counts and tok/s are **estimated** client-side and may be inaccurate — see [Accuracy](#accuracy) below.
12
+ </Callout>
13
+
14
+ ## Getting Started
15
+
16
+ <Steps>
17
+ <Step>
18
+
19
+ ### Add `message-timing`
20
+
21
+ <InstallCommand shadcn={["message-timing"]} />
22
+
23
+ This adds a `/components/assistant-ui/message-timing.tsx` file to your project.
24
+
25
+ </Step>
26
+ <Step>
27
+
28
+ ### Use in your application
29
+
30
+ Place `MessageTiming` inside `ActionBarPrimitive.Root` in your `thread.tsx`. It will inherit the action bar's auto-hide behaviour and only renders after the stream completes.
31
+
32
+ ```tsx title="/components/assistant-ui/thread.tsx" {2,12}
33
+ import { ActionBarPrimitive } from "@assistant-ui/react";
34
+ import { MessageTiming } from "@/components/assistant-ui/message-timing";
35
+
36
+ const AssistantActionBar: FC = () => {
37
+ return (
38
+ <ActionBarPrimitive.Root
39
+ hideWhenRunning
40
+ autohide="not-last"
41
+ >
42
+ <ActionBarPrimitive.Copy />
43
+ <ActionBarPrimitive.Reload />
44
+ <MessageTiming />
45
+ </ActionBarPrimitive.Root>
46
+ );
47
+ };
48
+ ```
49
+
50
+ </Step>
51
+ </Steps>
52
+
53
+ ## What It Shows
54
+
55
+ The badge displays `totalStreamTime` inline and reveals a popover on hover with the full breakdown:
56
+
57
+ | Metric | Description |
58
+ |--------|-------------|
59
+ | **First token** | Time from request start to first text chunk (TTFT) |
60
+ | **Total** | Total wall-clock time from start to stream end |
61
+ | **Speed** | Output tokens per second (hidden for very short messages) |
62
+ | **Chunks** | Number of stream chunks received |
63
+
64
+ ## Accuracy
65
+
66
+ Timing accuracy depends on how your backend is connected.
67
+
68
+ ### assistant-stream (accurate)
69
+
70
+ When using `assistant-stream` on the backend, token counts come directly from the model's usage data sent in `step-finish` chunks. The `tokensPerSecond` metric is exact whenever your backend reports `outputTokens`.
71
+
72
+ ### Vercel AI SDK (estimated)
73
+
74
+ When using the AI SDK integration (`useChatRuntime`), token counts are **estimated** client-side using a 4 characters per token approximation. This can overcount significantly for short messages.
75
+
76
+ ## API Reference
77
+
78
+ ### `MessageTiming` component
79
+
80
+ | Prop | Type | Default | Description |
81
+ |------|------|---------|-------------|
82
+ | `className` | `string` | — | Additional class names on the root element |
83
+ | `side` | `"top" \| "right" \| "bottom" \| "left"` | `"right"` | Side of the tooltip relative to the badge |
84
+
85
+ Renders `null` until `totalStreamTime` is available (i.e., while streaming or for user messages).
86
+
87
+ For the underlying `useMessageTiming()` hook, field definitions, and runtime-specific setup (LocalRuntime, ExternalStore, etc.), see the [Message Timing guide](/docs/guides/message-timing).
88
+
89
+ ## Related
90
+
91
+ - [Message Timing guide](/docs/guides/message-timing) — `useMessageTiming()` hook, runtime support table, and custom timing UI
92
+ - [Thread](/docs/ui/thread) — The action bar context that `MessageTiming` is typically placed inside
@@ -517,7 +517,7 @@ import { useAuiState } from "@assistant-ui/react";
517
517
  const DynamicGroup: FC<
518
518
  PropsWithChildren<{ groupKey: string | undefined; indices: number[] }>
519
519
  > = ({ groupKey, indices, children }) => {
520
- const parts = useAuiState(({ message }) => message.content);
520
+ const parts = useAuiState((s) => s.message.content);
521
521
  const groupParts = indices.map((i) => parts[i]);
522
522
 
523
523
  // Analyze group content
@@ -90,11 +90,11 @@ const ReasoningGroupImpl: ReasoningGroupComponent = ({
90
90
  startIndex,
91
91
  endIndex,
92
92
  }) => {
93
- const isReasoningStreaming = useAuiState(({ message }) => {
94
- if (message.status?.type !== "running") return false;
95
- const lastIndex = message.parts.length - 1;
93
+ const isReasoningStreaming = useAuiState((s) => {
94
+ if (s.message.status?.type !== "running") return false;
95
+ const lastIndex = s.message.parts.length - 1;
96
96
  if (lastIndex < 0) return false;
97
- const lastType = message.parts[lastIndex]?.type;
97
+ const lastType = s.message.parts[lastIndex]?.type;
98
98
  if (lastType !== "reasoning") return false;
99
99
  return lastIndex >= startIndex && lastIndex <= endIndex;
100
100
  });
@@ -7,7 +7,7 @@ import { ScrollbarSample } from "@/components/docs/samples/scrollbar";
7
7
 
8
8
  <ScrollbarSample />
9
9
 
10
- If you want to show a custom scrollbar UI of the `ThreadPrimitive.Viewport` in place of the system default, you can integrate `@radix-ui/react-scroll-area`.
10
+ If you want to show a custom scrollbar UI of the `ThreadPrimitive.Viewport` in place of the system default, you can integrate `radix-ui`'s Scroll Area.
11
11
  An example implementation of this is [shadcn/ui's Scroll Area](https://ui.shadcn.com/docs/components/scroll-area).
12
12
 
13
13
  <Steps>
@@ -48,7 +48,7 @@ Add the following CSS to your `globals.css`:
48
48
  The resulting MyThread component should look like this:
49
49
 
50
50
  ```tsx {1-2,6,8,12-13,15}
51
- import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
51
+ import { ScrollArea as ScrollAreaPrimitive } from "radix-ui";
52
52
  import { ScrollBar } from "@/components/ui/scroll-area";
53
53
 
54
54
  const MyThread: FC = () => {
@@ -5,10 +5,10 @@ description: Code block syntax highlighting with react-shiki or react-syntax-hig
5
5
 
6
6
  import { SyntaxHighlightingSample } from "@/components/docs/samples/syntax-highlighting";
7
7
 
8
- <SyntaxHighlightingSample />
9
-
10
8
  <Callout type="warn">Syntax highlighting is not enabled in markdown by default.</Callout>
11
9
 
10
+ <SyntaxHighlightingSample />
11
+
12
12
  <Callout type="info">
13
13
  `assistant-ui` provides two options for syntax highlighting:
14
14
  - **react-shiki** (recommended for performance & dynamic language support)
@@ -53,11 +53,61 @@ export const defaultComponents = memoizeMarkdownComponents({
53
53
  See [react-shiki documentation](https://github.com/AVGVSTVS96/react-shiki#props) for all available options.
54
54
 
55
55
  Key options:
56
- - `theme` - Shiki theme (default: `"github-dark"`)
56
+ - `theme` - Shiki theme or multi-theme object (`{ light, dark, ... }`)
57
57
  - `language` - Language for highlighting (default: `"text"`)
58
+ - `defaultColor` - Default color mode (`string | false`, e.g. `light-dark()`)
58
59
  - `delay` - Delay between highlights, useful for streaming (default: `0`)
59
- - `customLanguages` - Custom languages to preload
60
- - `codeToHastOptions` - Options passed to Shiki's `codeToHast`
60
+ - `customLanguages` - Custom languages to preload for dynamic support
61
+ - `codeToHastOptions` - All other options accepted by Shiki's [`codeToHast`](https://github.com/shikijs/shiki/blob/main/packages/types/src/options.ts#L121)
62
+
63
+ ### Dual/multi theme support
64
+
65
+ To use multiple themes, pass a theme object:
66
+
67
+ ```tsx title="/components/assistant-ui/shiki-highlighter.tsx"
68
+ <ShikiHighlighter
69
+ /* ... */
70
+ theme={{
71
+ light: "github-light",
72
+ dark: "github-dark",
73
+ }}
74
+ defaultColor="light-dark()"
75
+ /* ... */
76
+ >
77
+ ```
78
+
79
+ > **Note:** The `shiki-highlighter` component sets `defaultColor="light-dark()"` automatically.
80
+ > Only set this manually if using `ShikiHighlighter` directly.
81
+
82
+ With `defaultColor="light-dark()"`, theme switching is automatic based on your site's `color-scheme`.
83
+ No custom Shiki CSS overrides are required.
84
+
85
+ Set `color-scheme` on your app root:
86
+
87
+ System-based (follows OS/browser preference):
88
+
89
+ ```css title="globals.css"
90
+ :root {
91
+ color-scheme: light dark;
92
+ }
93
+ ```
94
+
95
+ Class-based theme switching:
96
+
97
+ ```css title="globals.css"
98
+ :root {
99
+ color-scheme: light;
100
+ }
101
+ :root.dark {
102
+ color-scheme: dark;
103
+ }
104
+ ```
105
+
106
+ If you need broader support for older browsers, you can still use the manual CSS-variable switching approach from the Shiki dual-theme docs.
107
+
108
+ For more information:
109
+ - [react-shiki multi-theme/reactive themes](https://github.com/AVGVSTVS96/react-shiki)
110
+ - [Shiki dual themes + `light-dark()`](https://shiki.style/guide/dual-themes)
61
111
 
62
112
  ### Bundle Optimization
63
113
 
@@ -100,51 +150,6 @@ const customHighlighter = await createHighlighterCore({
100
150
  For more information, see [react-shiki - bundle options](https://github.com/avgvstvs96/react-shiki#bundle-options).
101
151
  </Callout>
102
152
 
103
- ### Dual/multi theme support
104
-
105
- To use multiple theme modes, pass an object with your multi-theme configuration to the `theme` prop in the `ShikiHighlighter` component:
106
-
107
- ```tsx title="/components/assistant-ui/shiki-highlighter.tsx"
108
- <ShikiHighlighter
109
- /* ... */
110
- theme={{
111
- light: "github-light",
112
- dark: "github-dark",
113
- }}
114
- /* ... */
115
- >
116
- ```
117
-
118
- To make themes responsive to your site's theme mode, add one of the following CSS snippets to your project:
119
-
120
- ```css title="shiki.css"
121
- /* for class based dark mode */
122
- html.dark .shiki,
123
- html.dark .shiki span {
124
- color: var(--shiki-dark) !important;
125
- background-color: var(--shiki-dark-bg) !important;
126
- /* Optional, if you also want font styles */
127
- font-style: var(--shiki-dark-font-style) !important;
128
- font-weight: var(--shiki-dark-font-weight) !important;
129
- text-decoration: var(--shiki-dark-text-decoration) !important;
130
- }
131
-
132
- /* for query based dark mode */
133
- @media (prefers-color-scheme: dark) {
134
- .shiki,
135
- .shiki span {
136
- color: var(--shiki-dark) !important;
137
- background-color: var(--shiki-dark-bg) !important;
138
- /* Optional, if you also want font styles */
139
- font-style: var(--shiki-dark-font-style) !important;
140
- font-weight: var(--shiki-dark-font-weight) !important;
141
- text-decoration: var(--shiki-dark-text-decoration) !important;
142
- }
143
- }
144
- ```
145
-
146
- For more information, see [Shiki's documentation on dual and multi themes](https://shiki.style/guide/dual-themes).
147
-
148
153
  ---
149
154
 
150
155
  ## react-syntax-highlighter
@@ -16,11 +16,11 @@ attachments, and conditional UI states. Fully customizable and composable.
16
16
  The `Thread` component is built with the following primitives:
17
17
 
18
18
  ```tsx
19
- import { ThreadPrimitive, AuiIf } from "@assistant-ui/react";
19
+ import { ThreadPrimitive, SelectionToolbarPrimitive, AuiIf } from "@assistant-ui/react";
20
20
 
21
21
  <ThreadPrimitive.Root>
22
22
  <ThreadPrimitive.Viewport>
23
- <ThreadPrimitive.Empty />
23
+ <AuiIf condition={(s) => s.thread.isEmpty} />
24
24
  <ThreadPrimitive.Messages
25
25
  components={{
26
26
  EditComposer,
@@ -32,6 +32,11 @@ import { ThreadPrimitive, AuiIf } from "@assistant-ui/react";
32
32
  </ThreadPrimitive.Viewport>
33
33
  <ThreadPrimitive.Suggestions />
34
34
  <AuiIf condition={...} />
35
+
36
+ {/* Floating toolbar — appears when text is selected in a message */}
37
+ <SelectionToolbarPrimitive.Root>
38
+ <SelectionToolbarPrimitive.Quote>Quote</SelectionToolbarPrimitive.Quote>
39
+ </SelectionToolbarPrimitive.Root>
35
40
  </ThreadPrimitive.Root>
36
41
  ```
37
42
 
@@ -71,7 +76,7 @@ export default function Chat() {
71
76
  ### Welcome Screen
72
77
 
73
78
  ```tsx
74
- <AuiIf condition={({ thread }) => thread.isEmpty}>
79
+ <AuiIf condition={(s) => s.thread.isEmpty}>
75
80
  <ThreadWelcome />
76
81
  </AuiIf>
77
82
  ```
@@ -79,7 +84,7 @@ export default function Chat() {
79
84
  ### Viewport Spacer
80
85
 
81
86
  ```tsx
82
- <AuiIf condition={({ thread }) => !thread.isEmpty}>
87
+ <AuiIf condition={(s) => !s.thread.isEmpty}>
83
88
  <div className="min-h-8 grow" />
84
89
  </AuiIf>
85
90
  ```
@@ -87,13 +92,13 @@ export default function Chat() {
87
92
  ### Conditional Send/Cancel Button
88
93
 
89
94
  ```tsx
90
- <AuiIf condition={({ thread }) => !thread.isRunning}>
95
+ <AuiIf condition={(s) => !s.thread.isRunning}>
91
96
  <ComposerPrimitive.Send>
92
97
  Send
93
98
  </ComposerPrimitive.Send>
94
99
  </AuiIf>
95
100
 
96
- <AuiIf condition={({ thread }) => thread.isRunning}>
101
+ <AuiIf condition={(s) => s.thread.isRunning}>
97
102
  <ComposerPrimitive.Cancel>
98
103
  Cancel
99
104
  </ComposerPrimitive.Cancel>
@@ -349,15 +354,15 @@ Conditionally renders children based on assistant state. This is a generic compo
349
354
  ```tsx
350
355
  import { AuiIf } from "@assistant-ui/react";
351
356
 
352
- <AuiIf condition={({ thread }) => thread.isEmpty}>
357
+ <AuiIf condition={(s) => s.thread.isEmpty}>
353
358
  <WelcomeScreen />
354
359
  </AuiIf>
355
360
 
356
- <AuiIf condition={({ thread }) => thread.isRunning}>
361
+ <AuiIf condition={(s) => s.thread.isRunning}>
357
362
  <LoadingIndicator />
358
363
  </AuiIf>
359
364
 
360
- <AuiIf condition={({ message }) => message.role === "assistant"}>
365
+ <AuiIf condition={(s) => s.message.role === "assistant"}>
361
366
  <AssistantAvatar />
362
367
  </AuiIf>
363
368
  ```
@@ -382,3 +387,5 @@ The condition function receives an `AssistantState` object with access to `threa
382
387
  ## Related Components
383
388
 
384
389
  - [ThreadList](/docs/ui/thread-list) - List of threads, with or without sidebar
390
+ - [Quoting guide](/docs/guides/quoting) - Quote selected text from messages
391
+ - [SelectionToolbarPrimitive](/docs/reference/primitives/selection-toolbar) - Floating toolbar API reference
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1
+ import { McpServer } from "@modelcontextprotocol/sdk";
2
2
  export declare const server: McpServer;
3
3
  export declare function runServer(): Promise<void>;
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAcpE,eAAO,MAAM,MAAM,WAGjB,CAAC;AAeH,wBAAsB,SAAS,kBAW9B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,kCAAgD;AAcpE,eAAO,MAAM,MAAM,WAGjB,CAAC;AAeH,wBAAsB,SAAS,kBAW9B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/mcp-docs-server",
3
- "version": "0.1.22",
3
+ "version": "0.1.24",
4
4
  "description": "MCP server for assistant-ui documentation and examples",
5
5
  "keywords": [
6
6
  "mcp",
@@ -33,12 +33,12 @@
33
33
  ],
34
34
  "sideEffects": false,
35
35
  "dependencies": {
36
- "@modelcontextprotocol/sdk": "^1.26.0",
36
+ "@modelcontextprotocol/sdk": "^1.27.1",
37
37
  "gray-matter": "^4.0.3",
38
38
  "zod": "^4.3.6"
39
39
  },
40
40
  "devDependencies": {
41
- "@types/node": "^25.2.1",
41
+ "@types/node": "^25.3.3",
42
42
  "tsx": "^4.21.0",
43
43
  "vitest": "^4.0.18",
44
44
  "@assistant-ui/x-buildutils": "0.0.1"
@@ -36,11 +36,11 @@ describe("MCP Server Integration", () => {
36
36
  const docsResult = await docsTools.execute({ paths: ["/"] });
37
37
  expect(docsResult).toBeDefined();
38
38
  expect(docsResult.content).toBeDefined();
39
- expect(docsResult.content[0].type).toBe("text");
39
+ expect(docsResult.content[0]!.type).toBe("text");
40
40
 
41
41
  const examplesResult = await examplesTools.execute({});
42
42
  expect(examplesResult).toBeDefined();
43
43
  expect(examplesResult.content).toBeDefined();
44
- expect(examplesResult.content[0].type).toBe("text");
44
+ expect(examplesResult.content[0]!.type).toBe("text");
45
45
  });
46
46
  });
@@ -9,7 +9,7 @@ describe("JSON parsing error handling", () => {
9
9
 
10
10
  it("should provide helpful error message for invalid JSON", async () => {
11
11
  vi.spyOn(docsTools, "execute").mockResolvedValue({
12
- content: [{ text: "invalid json {not valid}" }],
12
+ content: [{ type: "text" as const, text: "invalid json {not valid}" }],
13
13
  });
14
14
 
15
15
  await expect(
@@ -17,9 +17,7 @@ describe("MCP Protocol Integration", () => {
17
17
  method: "initialize",
18
18
  params: {
19
19
  protocolVersion: "2024-11-05",
20
- capabilities: {
21
- tools: {},
22
- },
20
+ capabilities: {},
23
21
  clientInfo: {
24
22
  name: "test-client",
25
23
  version: "1.0.0",
@@ -1,108 +0,0 @@
1
- ---
2
- title: Chat History for AI SDK
3
- description: Integrate cloud persistence and thread management with Vercel AI SDK.
4
- ---
5
-
6
-
7
- ## Overview
8
-
9
- assistant-cloud provides thread management and persistent chat history for applications built with the [AI SDK by Vercel](https://sdk.vercel.ai/). This guide shows you how to integrate cloud persistence into your AI SDK application.
10
-
11
- ## Prerequisites
12
-
13
- <Callout type="info">
14
- You need an assistant-cloud account to follow this guide. [Sign up here](https://cloud.assistant-ui.com/) to get started.
15
- </Callout>
16
-
17
- ## Setup Guide
18
-
19
- <Steps>
20
-
21
- <Step>
22
-
23
- ### Create a Cloud Project
24
-
25
- Create a new project in the [assistant-cloud dashboard](https://cloud.assistant-ui.com/) and from the settings page, copy:
26
-
27
- - **Frontend API URL**: `https://proj-[ID].assistant-api.com`
28
- - **Assistant Cloud API Key**: `sk_aui_proj_*`
29
-
30
- </Step>
31
-
32
- <Step>
33
-
34
- ### Configure Environment Variables
35
-
36
- Add the following environment variables to your project:
37
-
38
- ```bash title=".env.local"
39
- # Frontend API URL from your cloud project settings
40
- NEXT_PUBLIC_ASSISTANT_BASE_URL=https://proj-[YOUR-ID].assistant-api.com
41
-
42
- # API key for server-side operations
43
- ASSISTANT_API_KEY=your-api-key-here
44
- ```
45
-
46
- </Step>
47
-
48
- <Step>
49
-
50
- ### Install Dependencies
51
-
52
- Install the required packages:
53
-
54
- <InstallCommand npm={["@assistant-ui/react", "@assistant-ui/react-ai-sdk"]} />
55
-
56
- </Step>
57
-
58
- <Step>
59
-
60
- ### Set Up the Cloud Runtime
61
-
62
- Create a client-side AssistantCloud instance and integrate it with your AI SDK runtime:
63
-
64
- ```tsx title="app/chat/page.tsx"
65
- "use client";
66
-
67
- import { AssistantCloud, AssistantRuntimeProvider } from "@assistant-ui/react";
68
- import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
69
- import { ThreadList } from "@/components/assistant-ui/thread-list";
70
- import { Thread } from "@/components/assistant-ui/thread";
71
-
72
- export default function ChatPage() {
73
- const cloud = new AssistantCloud({
74
- baseUrl: process.env.NEXT_PUBLIC_ASSISTANT_BASE_URL!,
75
- anonymous: true, // Creates browser-session based user ID
76
- });
77
-
78
- const runtime = useChatRuntime({
79
- api: "/api/chat", // Your AI SDK endpoint
80
- cloud,
81
- });
82
-
83
- return (
84
- <AssistantRuntimeProvider runtime={runtime}>
85
- <div className="grid h-dvh grid-cols-[200px_1fr] gap-x-2 px-4 py-4">
86
- <ThreadList />
87
- <Thread />
88
- </div>
89
- </AssistantRuntimeProvider>
90
- );
91
- }
92
- ```
93
-
94
- </Step>
95
-
96
- </Steps>
97
-
98
- ## Authentication
99
-
100
- The example above uses `anonymous: true` which creates a browser session-based user ID. This is suitable for public demos or prototypes.
101
-
102
- For production apps with user accounts, see the [Cloud Authorization](/docs/cloud/authorization) guide to persist threads per user or workspace.
103
-
104
- ## Next Steps
105
-
106
- - Learn about [user authentication](/docs/cloud/authorization) for multi-user applications
107
- - Explore [runtime hooks](/docs/api-reference/integrations/vercel-ai-sdk) and integration options
108
- - Check out the [complete example](https://github.com/assistant-ui/assistant-ui/tree/main/examples/with-cloud) on GitHub