@assistant-ui/mcp-docs-server 0.1.9 → 0.1.11

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 (35) hide show
  1. package/.docs/organized/code-examples/with-ai-sdk-v5.md +26 -26
  2. package/.docs/organized/code-examples/with-assistant-transport.md +29 -29
  3. package/.docs/organized/code-examples/with-cloud.md +21 -21
  4. package/.docs/organized/code-examples/with-external-store.md +18 -18
  5. package/.docs/organized/code-examples/with-ffmpeg.md +22 -22
  6. package/.docs/organized/code-examples/with-langgraph.md +35 -120
  7. package/.docs/organized/code-examples/with-parent-id-grouping.md +18 -18
  8. package/.docs/organized/code-examples/with-react-hook-form.md +27 -27
  9. package/.docs/raw/docs/api-reference/primitives/Thread.mdx +40 -8
  10. package/.docs/raw/docs/cloud/persistence/langgraph.mdx +64 -68
  11. package/.docs/raw/docs/getting-started.mdx +541 -152
  12. package/.docs/raw/docs/guides/Attachments.mdx +21 -0
  13. package/.docs/raw/docs/guides/ToolUI.mdx +112 -37
  14. package/.docs/raw/docs/guides/Tools.mdx +170 -6
  15. package/.docs/raw/docs/migrations/react-langgraph-v0-7.mdx +324 -0
  16. package/.docs/raw/docs/runtimes/ai-sdk/use-chat.mdx +2 -2
  17. package/.docs/raw/docs/runtimes/custom/custom-thread-list.mdx +218 -0
  18. package/.docs/raw/docs/runtimes/custom/external-store.mdx +31 -24
  19. package/.docs/raw/docs/runtimes/langgraph/index.mdx +55 -20
  20. package/.docs/raw/docs/runtimes/mastra/separate-server-integration.mdx +8 -3
  21. package/.docs/raw/docs/runtimes/pick-a-runtime.mdx +1 -1
  22. package/.docs/raw/docs/ui/AssistantModal.mdx +21 -0
  23. package/.docs/raw/docs/ui/AssistantSidebar.mdx +21 -0
  24. package/.docs/raw/docs/ui/Attachment.mdx +21 -0
  25. package/.docs/raw/docs/ui/Markdown.mdx +22 -1
  26. package/.docs/raw/docs/ui/Mermaid.mdx +22 -1
  27. package/.docs/raw/docs/ui/SyntaxHighlighting.mdx +43 -2
  28. package/.docs/raw/docs/ui/Thread.mdx +374 -5
  29. package/.docs/raw/docs/ui/ThreadList.mdx +48 -2
  30. package/.docs/raw/docs/ui/ToolFallback.mdx +21 -0
  31. package/package.json +7 -7
  32. package/.docs/raw/docs/migrations/v0-7.mdx +0 -188
  33. package/.docs/raw/docs/migrations/v0-8.mdx +0 -160
  34. package/.docs/raw/docs/migrations/v0-9.mdx +0 -75
  35. package/.docs/raw/docs/ui/primitives/Thread.mdx +0 -197
@@ -444,7 +444,7 @@ const defaultComponents = memoizeMarkdownComponents({
444
444
  h2: ({ className, ...props }) => (
445
445
  <h2
446
446
  className={cn(
447
- "mb-4 mt-8 scroll-m-20 text-3xl font-semibold tracking-tight first:mt-0 last:mb-0",
447
+ "mt-8 mb-4 scroll-m-20 text-3xl font-semibold tracking-tight first:mt-0 last:mb-0",
448
448
  className,
449
449
  )}
450
450
  {...props}
@@ -453,7 +453,7 @@ const defaultComponents = memoizeMarkdownComponents({
453
453
  h3: ({ className, ...props }) => (
454
454
  <h3
455
455
  className={cn(
456
- "mb-4 mt-6 scroll-m-20 text-2xl font-semibold tracking-tight first:mt-0 last:mb-0",
456
+ "mt-6 mb-4 scroll-m-20 text-2xl font-semibold tracking-tight first:mt-0 last:mb-0",
457
457
  className,
458
458
  )}
459
459
  {...props}
@@ -462,7 +462,7 @@ const defaultComponents = memoizeMarkdownComponents({
462
462
  h4: ({ className, ...props }) => (
463
463
  <h4
464
464
  className={cn(
465
- "mb-4 mt-6 scroll-m-20 text-xl font-semibold tracking-tight first:mt-0 last:mb-0",
465
+ "mt-6 mb-4 scroll-m-20 text-xl font-semibold tracking-tight first:mt-0 last:mb-0",
466
466
  className,
467
467
  )}
468
468
  {...props}
@@ -485,7 +485,7 @@ const defaultComponents = memoizeMarkdownComponents({
485
485
  ),
486
486
  p: ({ className, ...props }) => (
487
487
  <p
488
- className={cn("mb-5 mt-5 leading-7 first:mt-0 last:mb-0", className)}
488
+ className={cn("mt-5 mb-5 leading-7 first:mt-0 last:mb-0", className)}
489
489
  {...props}
490
490
  />
491
491
  ),
@@ -682,7 +682,7 @@ const ThreadWelcomeSuggestions: FC = () => {
682
682
  method="replace"
683
683
  autoSend
684
684
  >
685
- <span className="line-clamp-2 text-ellipsis text-sm font-semibold">
685
+ <span className="line-clamp-2 text-sm font-semibold text-ellipsis">
686
686
  What is the weather in Tokyo?
687
687
  </span>
688
688
  </ThreadPrimitive.Suggestion>
@@ -692,7 +692,7 @@ const ThreadWelcomeSuggestions: FC = () => {
692
692
  method="replace"
693
693
  autoSend
694
694
  >
695
- <span className="line-clamp-2 text-ellipsis text-sm font-semibold">
695
+ <span className="line-clamp-2 text-sm font-semibold text-ellipsis">
696
696
  What is assistant-ui?
697
697
  </span>
698
698
  </ThreadPrimitive.Suggestion>
@@ -748,7 +748,7 @@ const UserMessage: FC = () => {
748
748
  <MessagePrimitive.Root className="grid w-full max-w-[var(--thread-max-width)] auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] gap-y-2 py-4 [&:where(>*)]:col-start-2">
749
749
  <UserActionBar />
750
750
 
751
- <div className="bg-muted text-foreground col-start-2 row-start-2 max-w-[calc(var(--thread-max-width)*0.8)] break-words rounded-3xl px-5 py-2.5">
751
+ <div className="bg-muted text-foreground col-start-2 row-start-2 max-w-[calc(var(--thread-max-width)*0.8)] rounded-3xl px-5 py-2.5 break-words">
752
752
  <MessagePrimitive.Parts />
753
753
  </div>
754
754
 
@@ -762,7 +762,7 @@ const UserActionBar: FC = () => {
762
762
  <ActionBarPrimitive.Root
763
763
  hideWhenRunning
764
764
  autohide="not-last"
765
- className="col-start-1 row-start-2 mr-3 mt-2.5 flex flex-col items-end"
765
+ className="col-start-1 row-start-2 mt-2.5 mr-3 flex flex-col items-end"
766
766
  >
767
767
  <ActionBarPrimitive.Edit asChild>
768
768
  <TooltipIconButton tooltip="Edit">
@@ -793,13 +793,13 @@ const EditComposer: FC = () => {
793
793
  const AssistantMessage: FC = () => {
794
794
  return (
795
795
  <MessagePrimitive.Root className="relative grid w-full max-w-[var(--thread-max-width)] grid-cols-[auto_auto_1fr] grid-rows-[auto_1fr] py-4">
796
- <div className="text-foreground col-span-2 col-start-2 row-start-1 my-1.5 max-w-[calc(var(--thread-max-width)*0.8)] break-words leading-7">
796
+ <div className="text-foreground col-span-2 col-start-2 row-start-1 my-1.5 max-w-[calc(var(--thread-max-width)*0.8)] leading-7 break-words">
797
797
  <MessagePrimitive.Parts components={{ Text: MarkdownText }} />
798
798
  </div>
799
799
 
800
800
  <AssistantActionBar />
801
801
 
802
- <BranchPicker className="col-start-2 row-start-2 -ml-2 mr-2" />
802
+ <BranchPicker className="col-start-2 row-start-2 mr-2 -ml-2" />
803
803
  </MessagePrimitive.Root>
804
804
  );
805
805
  };
@@ -1326,7 +1326,7 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
1326
1326
  type={type}
1327
1327
  data-slot="input"
1328
1328
  className={cn(
1329
- "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input shadow-xs flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base outline-none transition-[color,box-shadow] file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1329
+ "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1330
1330
  "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
1331
1331
  "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
1332
1332
  className,
@@ -1358,7 +1358,7 @@ function Label({
1358
1358
  <LabelPrimitive.Root
1359
1359
  data-slot="label"
1360
1360
  className={cn(
1361
- "flex select-none items-center gap-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50 group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50",
1361
+ "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
1362
1362
  className,
1363
1363
  )}
1364
1364
  {...props}
@@ -1414,13 +1414,13 @@ function ResizableHandle({
1414
1414
  <ResizablePrimitive.PanelResizeHandle
1415
1415
  data-slot="resizable-handle"
1416
1416
  className={cn(
1417
- "bg-border focus-visible:ring-ring focus-visible:outline-hidden relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90",
1417
+ "bg-border focus-visible:ring-ring relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:translate-x-0 data-[panel-group-direction=vertical]:after:-translate-y-1/2 [&[data-panel-group-direction=vertical]>div]:rotate-90",
1418
1418
  className,
1419
1419
  )}
1420
1420
  {...props}
1421
1421
  >
1422
1422
  {withHandle && (
1423
- <div className="bg-border rounded-xs z-10 flex h-4 w-3 items-center justify-center border">
1423
+ <div className="bg-border z-10 flex h-4 w-3 items-center justify-center rounded-xs border">
1424
1424
  <GripVerticalIcon className="size-2.5" />
1425
1425
  </div>
1426
1426
  )}
@@ -1479,7 +1479,7 @@ function TabsTrigger({
1479
1479
  <TabsPrimitive.Trigger
1480
1480
  data-slot="tabs-trigger"
1481
1481
  className={cn(
1482
- "data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 whitespace-nowrap rounded-md border border-transparent px-2 py-1 text-sm font-medium transition-[color,box-shadow] focus-visible:outline-1 focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
1482
+ "data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
1483
1483
  className,
1484
1484
  )}
1485
1485
  {...props}
@@ -1555,7 +1555,7 @@ function TooltipContent({
1555
1555
  data-slot="tooltip-content"
1556
1556
  sideOffset={sideOffset}
1557
1557
  className={cn(
1558
- "bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-[--radix-tooltip-content-transform-origin] text-balance rounded-md px-3 py-1.5 text-xs",
1558
+ "bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-[--radix-tooltip-content-transform-origin] rounded-md px-3 py-1.5 text-xs text-balance",
1559
1559
  className,
1560
1560
  )}
1561
1561
  {...props}
@@ -1647,7 +1647,7 @@ export default nextConfig;
1647
1647
  "lint": "eslint ."
1648
1648
  },
1649
1649
  "dependencies": {
1650
- "@ai-sdk/openai": "^2.0.38",
1650
+ "@ai-sdk/openai": "^2.0.52",
1651
1651
  "@assistant-ui/react": "workspace:*",
1652
1652
  "@assistant-ui/react-ai-sdk": "workspace:*",
1653
1653
  "@assistant-ui/react-hook-form": "workspace:*",
@@ -1660,20 +1660,20 @@ export default nextConfig;
1660
1660
  "@radix-ui/react-tabs": "^1.1.13",
1661
1661
  "@radix-ui/react-tooltip": "^1.2.8",
1662
1662
  "@react-hook/media-query": "^1.1.1",
1663
- "ai": "^5.0.56",
1663
+ "ai": "^5.0.76",
1664
1664
  "class-variance-authority": "^0.7.1",
1665
1665
  "clsx": "^2.1.1",
1666
1666
  "json-schema-to-zod": "^2.6.1",
1667
- "lucide-react": "^0.544.0",
1668
- "next": "15.5.4",
1669
- "react": "19.1.1",
1670
- "react-dom": "19.1.1",
1671
- "react-hook-form": "^7.63.0",
1667
+ "lucide-react": "^0.546.0",
1668
+ "next": "15.5.6",
1669
+ "react": "19.2.0",
1670
+ "react-dom": "19.2.0",
1671
+ "react-hook-form": "^7.65.0",
1672
1672
  "react-resizable-panels": "^3.0.6",
1673
1673
  "remark-gfm": "^4.0.1",
1674
1674
  "tailwind-merge": "^3.3.1",
1675
1675
  "tw-animate-css": "^1.4.0",
1676
- "zod": "^4.1.11",
1676
+ "zod": "^4.1.12",
1677
1677
  "zustand": "^5.0.8"
1678
1678
  },
1679
1679
  "devDependencies": {
@@ -1682,10 +1682,10 @@ export default nextConfig;
1682
1682
  "@types/react": "^19",
1683
1683
  "@types/react-dom": "^19",
1684
1684
  "eslint": "^9",
1685
- "eslint-config-next": "15.5.4",
1685
+ "eslint-config-next": "15.5.6",
1686
1686
  "postcss": "^8",
1687
- "tailwindcss": "^4.1.13",
1688
- "typescript": "^5.9.2"
1687
+ "tailwindcss": "^4.1.14",
1688
+ "typescript": "^5.9.3"
1689
1689
  }
1690
1690
  }
1691
1691
 
@@ -195,8 +195,7 @@ const Suggestion = () => {
195
195
  return (
196
196
  <ThreadPrimitive.Suggestion
197
197
  prompt="I need help with product search"
198
- method="replace"
199
- autoSend
198
+ send
200
199
  />
201
200
  );
202
201
  };
@@ -211,17 +210,29 @@ const Suggestion = () => {
211
210
  description: "The suggestion's prompt.",
212
211
  },
213
212
  {
214
- name: "method",
215
- type: "'replace'",
213
+ name: "send",
214
+ type: "boolean",
216
215
  description:
217
- "How does the suggestion interact with the composer's existing value.",
216
+ "When true, automatically sends the message. When false, replaces or appends the composer text with the suggestion - depending on the value of `clearComposer`",
218
217
  },
219
218
  {
220
- name: "autoSend",
219
+ name: "clearComposer",
221
220
  type: "boolean",
221
+ default: "true",
222
222
  description:
223
- "Whether to automatically send the suggestion when the user clicks on it.",
224
- default: "false",
223
+ "Whether to clear the composer after sending. When send is set to false, determines if composer text is replaced with suggestion (true, default), or if the suggestion's prompt is appended to the composer text (false).",
224
+ },
225
+ {
226
+ name: "autoSend",
227
+ type: "boolean",
228
+ deprecated: true,
229
+ description: "Deprecated. Use 'send' instead.",
230
+ },
231
+ {
232
+ name: "method",
233
+ type: "'replace'",
234
+ deprecated: true,
235
+ description: "Deprecated. This parameter is no longer used.",
225
236
  },
226
237
  ]}
227
238
  />
@@ -243,6 +254,21 @@ Renders children if a condition is met.
243
254
  type: "boolean | undefined",
244
255
  description: "Render children if the thread is running.",
245
256
  },
257
+ {
258
+ name: "disabled",
259
+ type: "boolean | undefined",
260
+ description: "Render children if the thread is disabled.",
261
+ },
262
+ {
263
+ name: "loading",
264
+ type: "boolean | undefined",
265
+ description: "Render children if the thread is loading.",
266
+ },
267
+ {
268
+ name: "new",
269
+ type: "boolean | undefined",
270
+ description: "Render children if the thread is new.",
271
+ },
246
272
  ]}
247
273
  />
248
274
 
@@ -253,4 +279,10 @@ Renders children if a condition is met.
253
279
  <Thread.If empty={false}>
254
280
  {/* rendered if thread is not empty */}
255
281
  </Thread.If>
282
+ <Thread.If loading>
283
+ {/* rendered if thread is loading */}
284
+ </Thread.If>
285
+ <Thread.If new>
286
+ {/* rendered if thread is new */}
287
+ </Thread.If>
256
288
  ```
@@ -2,9 +2,9 @@
2
2
  title: Chat History for LangGraph Cloud
3
3
  ---
4
4
 
5
- import { Steps, Step } from 'fumadocs-ui/components/steps';
6
- import { Callout } from 'fumadocs-ui/components/callout';
7
- import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
5
+ import { Steps, Step } from "fumadocs-ui/components/steps";
6
+ import { Callout } from "fumadocs-ui/components/callout";
7
+ import { Tab, Tabs } from "fumadocs-ui/components/tabs";
8
8
 
9
9
  ## Overview
10
10
 
@@ -13,7 +13,8 @@ assistant-cloud provides thread management and persistent chat history for appli
13
13
  ## Prerequisites
14
14
 
15
15
  <Callout type="info">
16
- You need an assistant-cloud account to follow this guide. [Sign up here](https://cloud.assistant-ui.com/) to get started.
16
+ You need an assistant-cloud account to follow this guide. [Sign up
17
+ here](https://cloud.assistant-ui.com/) to get started.
17
18
  </Callout>
18
19
 
19
20
  ## Setup Guide
@@ -75,40 +76,12 @@ Create a runtime provider that integrates LangGraph with assistant-cloud. Choose
75
76
  import {
76
77
  AssistantCloud,
77
78
  AssistantRuntimeProvider,
78
- useCloudThreadListRuntime,
79
- useThreadListItemRuntime,
80
79
  } from "@assistant-ui/react";
81
80
  import { useLangGraphRuntime } from "@assistant-ui/react-langgraph";
82
81
  import { createThread, getThreadState, sendMessage } from "@/lib/chatApi";
83
82
  import { LangChainMessage } from "@assistant-ui/react-langgraph";
84
83
  import { useMemo } from "react";
85
84
 
86
- const useMyLangGraphRuntime = () => {
87
- const threadListItemRuntime = useThreadListItemRuntime();
88
-
89
- const runtime = useLangGraphRuntime({
90
- stream: async function* (messages) {
91
- const { externalId } = await threadListItemRuntime.initialize();
92
- if (!externalId) throw new Error("Thread not found");
93
-
94
- return sendMessage({
95
- threadId: externalId,
96
- messages,
97
- });
98
- },
99
-
100
- onSwitchToThread: async (externalId) => {
101
- const state = await getThreadState(externalId);
102
- return {
103
- messages:
104
- (state.values as { messages?: LangChainMessage[] }).messages ?? [],
105
- };
106
- },
107
- });
108
-
109
- return runtime;
110
- };
111
-
112
85
  export function MyRuntimeProvider({
113
86
  children,
114
87
  }: Readonly<{
@@ -123,13 +96,28 @@ export function MyRuntimeProvider({
123
96
  [],
124
97
  );
125
98
 
126
- const runtime = useCloudThreadListRuntime({
99
+ const runtime = useLangGraphRuntime({
127
100
  cloud,
128
- runtimeHook: useMyLangGraphRuntime,
101
+ stream: async function* (messages, { initialize }) {
102
+ const { externalId } = await initialize();
103
+ if (!externalId) throw new Error("Thread not found");
104
+
105
+ return sendMessage({
106
+ threadId: externalId,
107
+ messages,
108
+ });
109
+ },
129
110
  create: async () => {
130
111
  const { thread_id } = await createThread();
131
112
  return { externalId: thread_id };
132
113
  },
114
+ load: async (externalId) => {
115
+ const state = await getThreadState(externalId);
116
+ return {
117
+ messages:
118
+ (state.values as { messages?: LangChainMessage[] }).messages ?? [],
119
+ };
120
+ },
133
121
  });
134
122
 
135
123
  return (
@@ -150,8 +138,6 @@ export function MyRuntimeProvider({
150
138
  import {
151
139
  AssistantCloud,
152
140
  AssistantRuntimeProvider,
153
- useCloudThreadListRuntime,
154
- useThreadListItemRuntime,
155
141
  } from "@assistant-ui/react";
156
142
  import { useLangGraphRuntime } from "@assistant-ui/react-langgraph";
157
143
  import { createThread, getThreadState, sendMessage } from "@/lib/chatApi";
@@ -159,32 +145,6 @@ import { LangChainMessage } from "@assistant-ui/react-langgraph";
159
145
  import { useAuth } from "@clerk/nextjs";
160
146
  import { useMemo } from "react";
161
147
 
162
- const useMyLangGraphRuntime = () => {
163
- const threadListItemRuntime = useThreadListItemRuntime();
164
-
165
- const runtime = useLangGraphRuntime({
166
- stream: async function* (messages) {
167
- const { externalId } = await threadListItemRuntime.initialize();
168
- if (!externalId) throw new Error("Thread not found");
169
-
170
- return sendMessage({
171
- threadId: externalId,
172
- messages,
173
- });
174
- },
175
-
176
- onSwitchToThread: async (externalId) => {
177
- const state = await getThreadState(externalId);
178
- return {
179
- messages:
180
- (state.values as { messages?: LangChainMessage[] }).messages ?? []
181
- };
182
- },
183
- });
184
-
185
- return runtime;
186
- };
187
-
188
148
  export function MyRuntimeProvider({
189
149
  children,
190
150
  }: Readonly<{
@@ -201,13 +161,28 @@ export function MyRuntimeProvider({
201
161
  [getToken],
202
162
  );
203
163
 
204
- const runtime = useCloudThreadListRuntime({
164
+ const runtime = useLangGraphRuntime({
205
165
  cloud,
206
- runtimeHook: useMyLangGraphRuntime,
166
+ stream: async function* (messages, { initialize }) {
167
+ const { externalId } = await initialize();
168
+ if (!externalId) throw new Error("Thread not found");
169
+
170
+ return sendMessage({
171
+ threadId: externalId,
172
+ messages,
173
+ });
174
+ },
207
175
  create: async () => {
208
176
  const { thread_id } = await createThread();
209
177
  return { externalId: thread_id };
210
178
  },
179
+ load: async (externalId) => {
180
+ const state = await getThreadState(externalId);
181
+ return {
182
+ messages:
183
+ (state.values as { messages?: LangChainMessage[] }).messages ?? [],
184
+ };
185
+ },
211
186
  });
212
187
 
213
188
  return (
@@ -219,7 +194,8 @@ export function MyRuntimeProvider({
219
194
  ```
220
195
 
221
196
  <Callout type="info">
222
- For Clerk authentication, configure the `"assistant-ui"` token template in your Clerk dashboard.
197
+ For Clerk authentication, configure the `"assistant-ui"` token template in
198
+ your Clerk dashboard.
223
199
  </Callout>
224
200
 
225
201
  </Tab>
@@ -227,7 +203,7 @@ export function MyRuntimeProvider({
227
203
  </Tabs>
228
204
 
229
205
  <Callout type="info">
230
- The `useMyLangGraphRuntime` hook is extracted into a separate function because it will be mounted multiple times, once per active thread.
206
+ The `useLangGraphRuntime` hook now directly accepts `cloud`, `create`, and `load` parameters for simplified thread management. The runtime handles thread lifecycle internally.
231
207
  </Callout>
232
208
 
233
209
  </Step>
@@ -238,10 +214,30 @@ export function MyRuntimeProvider({
238
214
 
239
215
  Install the thread list component:
240
216
 
241
- ```bash
242
- npx assistant-ui add thread-list
217
+ <Tabs items={["assistant-ui", "shadcn (namespace)", "shadcn"]}>
218
+ <Tab>
219
+
220
+ ```sh
221
+ npx assistant-ui@latest add thread-list
243
222
  ```
244
223
 
224
+ </Tab>
225
+ <Tab>
226
+
227
+ ```sh
228
+ npx shadcn@latest add @assistant-ui/thread-list
229
+ ```
230
+
231
+ </Tab>
232
+ <Tab>
233
+
234
+ ```sh
235
+ npx shadcn@latest add "https://r.assistant-ui.com/thread-list"
236
+ ```
237
+
238
+ </Tab>
239
+ </Tabs>
240
+
245
241
  Then add it to your application layout:
246
242
 
247
243
  ```tsx title="app/chat/page.tsx"