@assistant-ui/mcp-docs-server 0.1.30 → 0.1.32

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 (341) hide show
  1. package/.docs/organized/code-examples/waterfall.md +8 -8
  2. package/.docs/organized/code-examples/with-a2a.md +10 -10
  3. package/.docs/organized/code-examples/with-ag-ui.md +12 -12
  4. package/.docs/organized/code-examples/with-ai-sdk-v6.md +14 -14
  5. package/.docs/organized/code-examples/with-artifacts.md +14 -14
  6. package/.docs/organized/code-examples/with-assistant-transport.md +11 -11
  7. package/.docs/organized/code-examples/with-browser-extension.md +345 -0
  8. package/.docs/organized/code-examples/with-chain-of-thought.md +129 -63
  9. package/.docs/organized/code-examples/with-cloud-standalone.md +13 -13
  10. package/.docs/organized/code-examples/with-cloud.md +13 -13
  11. package/.docs/organized/code-examples/with-custom-thread-list.md +65 -20
  12. package/.docs/organized/code-examples/with-elevenlabs-conversational.md +18 -17
  13. package/.docs/organized/code-examples/with-elevenlabs-scribe.md +18 -17
  14. package/.docs/organized/code-examples/with-expo.md +25 -25
  15. package/.docs/organized/code-examples/with-external-store.md +10 -10
  16. package/.docs/organized/code-examples/with-ffmpeg.md +14 -14
  17. package/.docs/organized/code-examples/with-generative-ui.md +211 -14
  18. package/.docs/organized/code-examples/with-google-adk.md +12 -12
  19. package/.docs/organized/code-examples/with-heat-graph.md +8 -8
  20. package/.docs/organized/code-examples/with-image-generation.md +454 -0
  21. package/.docs/organized/code-examples/with-interactables.md +14 -14
  22. package/.docs/organized/code-examples/with-langchain.md +12 -12
  23. package/.docs/organized/code-examples/with-langgraph.md +15 -12
  24. package/.docs/organized/code-examples/with-livekit.md +19 -18
  25. package/.docs/organized/code-examples/with-mcp.md +748 -0
  26. package/.docs/organized/code-examples/with-opencode.md +107 -62
  27. package/.docs/organized/code-examples/with-parent-id-grouping.md +12 -12
  28. package/.docs/organized/code-examples/with-react-hook-form.md +14 -14
  29. package/.docs/organized/code-examples/with-react-ink.md +4 -4
  30. package/.docs/organized/code-examples/with-react-router.md +16 -16
  31. package/.docs/organized/code-examples/with-resumable-stream.md +660 -0
  32. package/.docs/organized/code-examples/with-store.md +8 -8
  33. package/.docs/organized/code-examples/with-tanstack.md +14 -14
  34. package/.docs/organized/code-examples/with-tap-runtime.md +11 -10
  35. package/.docs/raw/docs/(docs)/cli.mdx +3 -1
  36. package/.docs/raw/docs/(docs)/copilots/assistant-frame.mdx +1 -0
  37. package/.docs/raw/docs/(docs)/copilots/make-assistant-tool-ui.mdx +10 -3
  38. package/.docs/raw/docs/(docs)/copilots/make-assistant-tool.mdx +8 -3
  39. package/.docs/raw/docs/(docs)/copilots/make-assistant-visible.mdx +1 -0
  40. package/.docs/raw/docs/(docs)/copilots/model-context.mdx +1 -0
  41. package/.docs/raw/docs/(docs)/copilots/motivation.mdx +1 -0
  42. package/.docs/raw/docs/(docs)/copilots/use-assistant-instructions.mdx +1 -0
  43. package/.docs/raw/docs/(docs)/devtools.mdx +1 -0
  44. package/.docs/raw/docs/(docs)/index.mdx +3 -2
  45. package/.docs/raw/docs/(docs)/installation.mdx +2 -1
  46. package/.docs/raw/docs/(docs)/rtl.mdx +1 -0
  47. package/.docs/raw/docs/(reference)/api-reference/adapters/attachments.mdx +36 -0
  48. package/.docs/raw/docs/(reference)/api-reference/adapters/feedback.mdx +20 -0
  49. package/.docs/raw/docs/(reference)/api-reference/adapters/index.mdx +34 -0
  50. package/.docs/raw/docs/(reference)/api-reference/adapters/model.mdx +44 -0
  51. package/.docs/raw/docs/(reference)/api-reference/adapters/persistence.mdx +55 -0
  52. package/.docs/raw/docs/(reference)/api-reference/adapters/runtime.mdx +20 -0
  53. package/.docs/raw/docs/(reference)/api-reference/adapters/suggestions.mdx +20 -0
  54. package/.docs/raw/docs/(reference)/api-reference/context-providers/assistant-runtime-provider.mdx +37 -8
  55. package/.docs/raw/docs/(reference)/api-reference/context-providers/index.mdx +22 -0
  56. package/.docs/raw/docs/(reference)/api-reference/context-providers/scoped-providers.mdx +64 -0
  57. package/.docs/raw/docs/(reference)/api-reference/external-store/index.mdx +22 -0
  58. package/.docs/raw/docs/(reference)/api-reference/external-store/message-conversion.mdx +52 -0
  59. package/.docs/raw/docs/(reference)/api-reference/external-store/runtime.mdx +36 -0
  60. package/.docs/raw/docs/(reference)/api-reference/hooks/composer-triggers.mdx +98 -0
  61. package/.docs/raw/docs/(reference)/api-reference/hooks/index.mdx +31 -0
  62. package/.docs/raw/docs/(reference)/api-reference/hooks/model-context.mdx +33 -0
  63. package/.docs/raw/docs/(reference)/api-reference/hooks/primitives.mdx +640 -0
  64. package/.docs/raw/docs/(reference)/api-reference/hooks/runtimes.mdx +28 -0
  65. package/.docs/raw/docs/(reference)/api-reference/hooks/state.mdx +94 -0
  66. package/.docs/raw/docs/(reference)/api-reference/hooks/utilities.mdx +464 -0
  67. package/.docs/raw/docs/(reference)/api-reference/integrations/cloud-ai-sdk.mdx +24 -0
  68. package/.docs/raw/docs/(reference)/api-reference/integrations/index.mdx +22 -0
  69. package/.docs/raw/docs/(reference)/api-reference/integrations/react-ai-sdk.mdx +79 -0
  70. package/.docs/raw/docs/(reference)/api-reference/model-context/context.mdx +52 -0
  71. package/.docs/raw/docs/(reference)/api-reference/model-context/index.mdx +22 -0
  72. package/.docs/raw/docs/(reference)/api-reference/model-context/registry.mdx +20 -0
  73. package/.docs/raw/docs/(reference)/api-reference/overview.mdx +125 -125
  74. package/.docs/raw/docs/(reference)/api-reference/primitives/action-bar-more.mdx +78 -221
  75. package/.docs/raw/docs/(reference)/api-reference/primitives/action-bar.mdx +127 -242
  76. package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-if.mdx +46 -20
  77. package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-modal.mdx +66 -87
  78. package/.docs/raw/docs/(reference)/api-reference/primitives/attachment.mdx +50 -58
  79. package/.docs/raw/docs/(reference)/api-reference/primitives/branch-picker.mdx +80 -48
  80. package/.docs/raw/docs/(reference)/api-reference/primitives/chain-of-thought.mdx +67 -0
  81. package/.docs/raw/docs/(reference)/api-reference/primitives/composer.mdx +323 -461
  82. package/.docs/raw/docs/(reference)/api-reference/primitives/error.mdx +36 -43
  83. package/.docs/raw/docs/(reference)/api-reference/primitives/index.mdx +70 -0
  84. package/.docs/raw/docs/(reference)/api-reference/primitives/message-part.mdx +63 -245
  85. package/.docs/raw/docs/(reference)/api-reference/primitives/message.mdx +182 -554
  86. package/.docs/raw/docs/(reference)/api-reference/primitives/queue-item.mdx +65 -0
  87. package/.docs/raw/docs/(reference)/api-reference/primitives/selection-toolbar.mdx +35 -22
  88. package/.docs/raw/docs/(reference)/api-reference/primitives/suggestion.mdx +57 -140
  89. package/.docs/raw/docs/(reference)/api-reference/primitives/thread-list-item-more.mdx +70 -161
  90. package/.docs/raw/docs/(reference)/api-reference/primitives/thread-list-item.mdx +84 -108
  91. package/.docs/raw/docs/(reference)/api-reference/primitives/thread-list.mdx +82 -86
  92. package/.docs/raw/docs/(reference)/api-reference/primitives/thread.mdx +173 -314
  93. package/.docs/raw/docs/(reference)/api-reference/runtimes/assistant-runtime.mdx +9 -21
  94. package/.docs/raw/docs/(reference)/api-reference/runtimes/attachment-runtime.mdx +10 -21
  95. package/.docs/raw/docs/(reference)/api-reference/runtimes/composer-runtime.mdx +15 -70
  96. package/.docs/raw/docs/(reference)/api-reference/runtimes/index.mdx +43 -0
  97. package/.docs/raw/docs/(reference)/api-reference/runtimes/message-part-runtime.mdx +25 -28
  98. package/.docs/raw/docs/(reference)/api-reference/runtimes/message-runtime.mdx +11 -63
  99. package/.docs/raw/docs/(reference)/api-reference/runtimes/queue-state.mdx +20 -0
  100. package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-list-item-runtime.mdx +11 -48
  101. package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-list-runtime.mdx +10 -42
  102. package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-runtime.mdx +18 -30
  103. package/.docs/raw/docs/(reference)/api-reference/tools/component-tools.mdx +68 -0
  104. package/.docs/raw/docs/(reference)/api-reference/tools/index.mdx +39 -0
  105. package/.docs/raw/docs/(reference)/api-reference/tools/rendering.mdx +79 -0
  106. package/.docs/raw/docs/(reference)/api-reference/tools/status.mdx +42 -0
  107. package/.docs/raw/docs/(reference)/api-reference/tools/toolkits.mdx +92 -0
  108. package/.docs/raw/docs/(reference)/api-reference/transport/assistant-transport.mdx +48 -0
  109. package/.docs/raw/docs/(reference)/api-reference/transport/frame.mdx +62 -0
  110. package/.docs/raw/docs/(reference)/api-reference/transport/index.mdx +22 -0
  111. package/.docs/raw/docs/(reference)/api-reference/utilities/index.mdx +19 -0
  112. package/.docs/raw/docs/(reference)/api-reference/utilities/miscellaneous.mdx +131 -0
  113. package/.docs/raw/docs/(reference)/api-reference/voice/index.mdx +22 -0
  114. package/.docs/raw/docs/(reference)/api-reference/voice/session.mdx +54 -0
  115. package/.docs/raw/docs/(reference)/api-reference/voice/speech-dictation.mdx +36 -0
  116. package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +230 -2
  117. package/.docs/raw/docs/cloud/ai-sdk.mdx +222 -4
  118. package/.docs/raw/docs/cloud/index.mdx +2 -2
  119. package/.docs/raw/docs/cloud/langgraph.mdx +274 -2
  120. package/.docs/raw/docs/{(docs)/guides → guides}/attachments.mdx +45 -40
  121. package/.docs/raw/docs/guides/branching.mdx +76 -0
  122. package/.docs/raw/docs/guides/chain-of-thought.mdx +166 -0
  123. package/.docs/raw/docs/{(docs)/guides → guides}/context-api.mdx +54 -26
  124. package/.docs/raw/docs/{(docs)/guides → guides}/dictation.mdx +3 -1
  125. package/.docs/raw/docs/guides/editing.mdx +102 -0
  126. package/.docs/raw/docs/guides/generative-ui.mdx +142 -0
  127. package/.docs/raw/docs/guides/image-generation.mdx +74 -0
  128. package/.docs/raw/docs/guides/index.mdx +103 -0
  129. package/.docs/raw/docs/{(docs)/guides → guides}/interactables.mdx +51 -2
  130. package/.docs/raw/docs/{(docs)/guides → guides}/latex.mdx +53 -10
  131. package/.docs/raw/docs/guides/mcp-apps.mdx +231 -0
  132. package/.docs/raw/docs/{(docs)/guides → guides}/mentions.mdx +63 -88
  133. package/.docs/raw/docs/{(docs)/guides → guides}/message-timing.mdx +45 -6
  134. package/.docs/raw/docs/{(docs)/guides → guides}/multi-agent.mdx +66 -6
  135. package/.docs/raw/docs/{(docs)/guides → guides}/quoting.mdx +11 -18
  136. package/.docs/raw/docs/guides/resumable-stream-deployment.mdx +212 -0
  137. package/.docs/raw/docs/guides/resumable-stream-stores.mdx +152 -0
  138. package/.docs/raw/docs/guides/resumable-streams.mdx +210 -0
  139. package/.docs/raw/docs/{(docs)/guides → guides}/slash-commands.mdx +104 -38
  140. package/.docs/raw/docs/guides/speech.mdx +156 -0
  141. package/.docs/raw/docs/{(docs)/guides → guides}/suggestions.mdx +91 -69
  142. package/.docs/raw/docs/{(docs)/guides → guides}/tool-ui.mdx +110 -38
  143. package/.docs/raw/docs/{(docs)/guides → guides}/tools.mdx +197 -40
  144. package/.docs/raw/docs/{(docs)/guides → guides}/voice.mdx +41 -2
  145. package/.docs/raw/docs/ink/adapters.mdx +37 -1
  146. package/.docs/raw/docs/ink/custom-backend.mdx +59 -8
  147. package/.docs/raw/docs/ink/index.mdx +11 -14
  148. package/.docs/raw/docs/ink/migration.mdx +1 -3
  149. package/.docs/raw/docs/ink/primitives.mdx +386 -9
  150. package/.docs/raw/docs/integrations/attachments/custom-adapter.mdx +520 -0
  151. package/.docs/raw/docs/integrations/auth/better-auth.mdx +191 -0
  152. package/.docs/raw/docs/integrations/auth/clerk.mdx +172 -0
  153. package/.docs/raw/docs/integrations/auth/next-auth.mdx +196 -0
  154. package/.docs/raw/docs/integrations/frameworks/ai-sdk.mdx +79 -0
  155. package/.docs/raw/docs/integrations/frameworks/cloudflare-agents/overview.mdx +282 -0
  156. package/.docs/raw/docs/integrations/frameworks/mastra/full-stack.mdx +188 -0
  157. package/.docs/raw/docs/integrations/frameworks/mastra/overview.mdx +57 -0
  158. package/.docs/raw/docs/integrations/frameworks/mastra/separate-server.mdx +201 -0
  159. package/.docs/raw/docs/integrations/gateways/index.mdx +162 -0
  160. package/.docs/raw/docs/integrations/index.mdx +185 -0
  161. package/.docs/raw/docs/integrations/observability/helicone.mdx +130 -0
  162. package/.docs/raw/docs/integrations/observability/langfuse.mdx +163 -0
  163. package/.docs/raw/docs/integrations/observability/langsmith.mdx +150 -0
  164. package/.docs/raw/docs/integrations/persistence/custom-adapter.mdx +712 -0
  165. package/.docs/raw/docs/integrations/tools/mcp.mdx +267 -0
  166. package/.docs/raw/docs/integrations/tools/react-mcp.mdx +337 -0
  167. package/.docs/raw/docs/migrations/v0-14.mdx +297 -0
  168. package/.docs/raw/docs/primitives/action-bar.mdx +1 -0
  169. package/.docs/raw/docs/primitives/assistant-modal.mdx +1 -0
  170. package/.docs/raw/docs/primitives/attachment.mdx +1 -0
  171. package/.docs/raw/docs/primitives/branch-picker.mdx +1 -0
  172. package/.docs/raw/docs/primitives/chain-of-thought.mdx +90 -85
  173. package/.docs/raw/docs/primitives/composer.mdx +55 -1
  174. package/.docs/raw/docs/primitives/error.mdx +1 -0
  175. package/.docs/raw/docs/primitives/index.mdx +4 -3
  176. package/.docs/raw/docs/primitives/message.mdx +68 -5
  177. package/.docs/raw/docs/primitives/selection-toolbar.mdx +1 -0
  178. package/.docs/raw/docs/primitives/suggestion.mdx +10 -0
  179. package/.docs/raw/docs/primitives/thread-list.mdx +39 -0
  180. package/.docs/raw/docs/primitives/thread.mdx +16 -13
  181. package/.docs/raw/docs/react-native/hooks.mdx +2 -2
  182. package/.docs/raw/docs/react-native/index.mdx +5 -7
  183. package/.docs/raw/docs/react-native/migration.mdx +1 -3
  184. package/.docs/raw/docs/runtimes/a2a/client-and-hooks.mdx +396 -0
  185. package/.docs/raw/docs/runtimes/a2a/overview.mdx +60 -0
  186. package/.docs/raw/docs/runtimes/a2a/quickstart.mdx +216 -0
  187. package/.docs/raw/docs/runtimes/ag-ui/overview.mdx +70 -0
  188. package/.docs/raw/docs/runtimes/ag-ui/quickstart.mdx +243 -0
  189. package/.docs/raw/docs/runtimes/ag-ui/runtime-options.mdx +154 -0
  190. package/.docs/raw/docs/runtimes/ai-sdk/overview.mdx +52 -0
  191. package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +73 -128
  192. package/.docs/raw/docs/runtimes/ai-sdk/v5-legacy.mdx +70 -64
  193. package/.docs/raw/docs/runtimes/ai-sdk/v6.mdx +337 -123
  194. package/.docs/raw/docs/runtimes/concepts/adapters.mdx +265 -0
  195. package/.docs/raw/docs/runtimes/concepts/architecture.mdx +125 -0
  196. package/.docs/raw/docs/runtimes/concepts/stability.mdx +67 -0
  197. package/.docs/raw/docs/runtimes/concepts/threads.mdx +428 -0
  198. package/.docs/raw/docs/runtimes/custom/assistant-transport.mdx +703 -0
  199. package/.docs/raw/docs/runtimes/custom/data-stream.mdx +348 -0
  200. package/.docs/raw/docs/runtimes/custom/external-store.mdx +261 -1236
  201. package/.docs/raw/docs/runtimes/custom/local-runtime.mdx +746 -0
  202. package/.docs/raw/docs/runtimes/custom/overview.mdx +71 -0
  203. package/.docs/raw/docs/runtimes/google-adk/api.mdx +256 -0
  204. package/.docs/raw/docs/runtimes/google-adk/hooks.mdx +717 -0
  205. package/.docs/raw/docs/runtimes/google-adk/overview.mdx +69 -0
  206. package/.docs/raw/docs/runtimes/google-adk/quickstart.mdx +229 -0
  207. package/.docs/raw/docs/runtimes/langchain.mdx +533 -0
  208. package/.docs/raw/docs/runtimes/langgraph/generative-ui.mdx +305 -0
  209. package/.docs/raw/docs/runtimes/langgraph/interrupts.mdx +104 -0
  210. package/.docs/raw/docs/runtimes/langgraph/overview.mdx +84 -0
  211. package/.docs/raw/docs/runtimes/langgraph/quickstart.mdx +496 -0
  212. package/.docs/raw/docs/runtimes/langgraph/streaming.mdx +127 -0
  213. package/.docs/raw/docs/runtimes/langgraph/threads.mdx +113 -0
  214. package/.docs/raw/docs/runtimes/langgraph/tutorial/introduction.mdx +3 -3
  215. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-1.mdx +0 -23
  216. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +1 -1
  217. package/.docs/raw/docs/runtimes/opencode/hooks.mdx +191 -0
  218. package/.docs/raw/docs/runtimes/opencode/overview.mdx +48 -0
  219. package/.docs/raw/docs/runtimes/opencode/quickstart.mdx +119 -0
  220. package/.docs/raw/docs/runtimes/pick-a-runtime.mdx +78 -203
  221. package/.docs/raw/docs/ui/accordion.mdx +1 -0
  222. package/.docs/raw/docs/ui/assistant-modal.mdx +1 -0
  223. package/.docs/raw/docs/ui/assistant-sidebar.mdx +1 -0
  224. package/.docs/raw/docs/ui/attachment.mdx +1 -0
  225. package/.docs/raw/docs/ui/badge.mdx +1 -0
  226. package/.docs/raw/docs/ui/composer-trigger-popover.mdx +12 -1
  227. package/.docs/raw/docs/ui/context-display.mdx +1 -0
  228. package/.docs/raw/docs/ui/diff-viewer.mdx +1 -0
  229. package/.docs/raw/docs/ui/directive-text.mdx +1 -0
  230. package/.docs/raw/docs/ui/file.mdx +1 -0
  231. package/.docs/raw/docs/ui/image.mdx +1 -0
  232. package/.docs/raw/docs/ui/markdown.mdx +2 -14
  233. package/.docs/raw/docs/ui/mcp-config.mdx +102 -0
  234. package/.docs/raw/docs/ui/mermaid.mdx +1 -0
  235. package/.docs/raw/docs/ui/message-timing.mdx +3 -2
  236. package/.docs/raw/docs/ui/model-selector.mdx +9 -8
  237. package/.docs/raw/docs/ui/part-grouping.mdx +325 -313
  238. package/.docs/raw/docs/ui/quote.mdx +1 -0
  239. package/.docs/raw/docs/ui/reasoning.mdx +66 -33
  240. package/.docs/raw/docs/ui/scrollbar.mdx +1 -0
  241. package/.docs/raw/docs/ui/select.mdx +1 -0
  242. package/.docs/raw/docs/ui/sources.mdx +18 -0
  243. package/.docs/raw/docs/ui/streamdown.mdx +35 -2
  244. package/.docs/raw/docs/ui/syntax-highlighting.mdx +1 -0
  245. package/.docs/raw/docs/ui/tabs.mdx +1 -0
  246. package/.docs/raw/docs/ui/thread-list.mdx +19 -2
  247. package/.docs/raw/docs/ui/thread.mdx +58 -3
  248. package/.docs/raw/docs/ui/tool-fallback.mdx +1 -0
  249. package/.docs/raw/docs/ui/tool-group.mdx +39 -11
  250. package/.docs/raw/docs/ui/voice.mdx +1 -0
  251. package/.docs/raw/docs/utilities/heat-graph.mdx +1 -0
  252. package/.docs/raw/docs/utilities/react-o11y.mdx +278 -0
  253. package/.docs/raw/docs/utilities/tw-shimmer.mdx +1 -0
  254. package/README.md +14 -72
  255. package/dist/constants.d.ts +12 -9
  256. package/dist/constants.d.ts.map +1 -1
  257. package/dist/constants.js +13 -9
  258. package/dist/constants.js.map +1 -1
  259. package/dist/index.d.ts +7 -3
  260. package/dist/index.d.ts.map +1 -1
  261. package/dist/index.js +25 -24
  262. package/dist/index.js.map +1 -1
  263. package/dist/prepare-docs/code-examples.d.ts +4 -1
  264. package/dist/prepare-docs/code-examples.d.ts.map +1 -1
  265. package/dist/prepare-docs/code-examples.js +109 -121
  266. package/dist/prepare-docs/code-examples.js.map +1 -1
  267. package/dist/prepare-docs/copy-raw.d.ts +4 -1
  268. package/dist/prepare-docs/copy-raw.d.ts.map +1 -1
  269. package/dist/prepare-docs/copy-raw.js +45 -42
  270. package/dist/prepare-docs/copy-raw.js.map +1 -1
  271. package/dist/prepare-docs/prepare.d.ts +1 -2
  272. package/dist/prepare-docs/prepare.js +17 -17
  273. package/dist/prepare-docs/prepare.js.map +1 -1
  274. package/dist/stdio.d.ts +1 -3
  275. package/dist/stdio.js +6 -3
  276. package/dist/stdio.js.map +1 -1
  277. package/dist/tools/docs.d.ts +20 -15
  278. package/dist/tools/docs.d.ts.map +1 -1
  279. package/dist/tools/docs.js +140 -161
  280. package/dist/tools/docs.js.map +1 -1
  281. package/dist/tools/examples.d.ts +20 -15
  282. package/dist/tools/examples.d.ts.map +1 -1
  283. package/dist/tools/examples.js +74 -86
  284. package/dist/tools/examples.js.map +1 -1
  285. package/dist/tools/tests/test-setup.d.ts +5 -2
  286. package/dist/tools/tests/test-setup.d.ts.map +1 -1
  287. package/dist/tools/tests/test-setup.js +21 -28
  288. package/dist/tools/tests/test-setup.js.map +1 -1
  289. package/dist/utils/logger.d.ts +8 -5
  290. package/dist/utils/logger.d.ts.map +1 -1
  291. package/dist/utils/logger.js +17 -17
  292. package/dist/utils/logger.js.map +1 -1
  293. package/dist/utils/mcp-format.d.ts +8 -5
  294. package/dist/utils/mcp-format.d.ts.map +1 -1
  295. package/dist/utils/mcp-format.js +9 -9
  296. package/dist/utils/mcp-format.js.map +1 -1
  297. package/dist/utils/mdx.d.ts +8 -6
  298. package/dist/utils/mdx.d.ts.map +1 -1
  299. package/dist/utils/mdx.js +22 -22
  300. package/dist/utils/mdx.js.map +1 -1
  301. package/dist/utils/paths.d.ts +9 -6
  302. package/dist/utils/paths.d.ts.map +1 -1
  303. package/dist/utils/paths.js +66 -76
  304. package/dist/utils/paths.js.map +1 -1
  305. package/dist/utils/security.d.ts +4 -1
  306. package/dist/utils/security.d.ts.map +1 -1
  307. package/dist/utils/security.js +19 -40
  308. package/dist/utils/security.js.map +1 -1
  309. package/package.json +6 -6
  310. package/src/tools/tests/path-traversal.test.ts +1 -1
  311. package/.docs/raw/docs/(docs)/guides/branching.mdx +0 -65
  312. package/.docs/raw/docs/(docs)/guides/chain-of-thought.mdx +0 -164
  313. package/.docs/raw/docs/(docs)/guides/editing.mdx +0 -66
  314. package/.docs/raw/docs/(docs)/guides/speech.mdx +0 -38
  315. package/.docs/raw/docs/(reference)/api-reference/context-providers/text-message-part-provider.mdx +0 -40
  316. package/.docs/raw/docs/(reference)/api-reference/integrations/react-data-stream.mdx +0 -260
  317. package/.docs/raw/docs/(reference)/api-reference/integrations/react-hook-form.mdx +0 -103
  318. package/.docs/raw/docs/(reference)/api-reference/integrations/vercel-ai-sdk.mdx +0 -254
  319. package/.docs/raw/docs/(reference)/migrations/v0-14.mdx +0 -159
  320. package/.docs/raw/docs/runtimes/a2a/index.mdx +0 -298
  321. package/.docs/raw/docs/runtimes/assistant-transport.mdx +0 -1033
  322. package/.docs/raw/docs/runtimes/custom/custom-thread-list.mdx +0 -314
  323. package/.docs/raw/docs/runtimes/custom/local.mdx +0 -1464
  324. package/.docs/raw/docs/runtimes/data-stream.mdx +0 -422
  325. package/.docs/raw/docs/runtimes/google-adk/index.mdx +0 -686
  326. package/.docs/raw/docs/runtimes/helicone.mdx +0 -61
  327. package/.docs/raw/docs/runtimes/langchain/comparison.mdx +0 -60
  328. package/.docs/raw/docs/runtimes/langchain/index.mdx +0 -210
  329. package/.docs/raw/docs/runtimes/langgraph/index.mdx +0 -699
  330. package/.docs/raw/docs/runtimes/langgraph/tutorial/index.mdx +0 -12
  331. package/.docs/raw/docs/runtimes/langserve.mdx +0 -116
  332. package/.docs/raw/docs/runtimes/mastra/full-stack-integration.mdx +0 -218
  333. package/.docs/raw/docs/runtimes/mastra/overview.mdx +0 -18
  334. package/.docs/raw/docs/runtimes/mastra/separate-server-integration.mdx +0 -217
  335. package/dist/prepare-docs/prepare.d.ts.map +0 -1
  336. package/dist/stdio.d.ts.map +0 -1
  337. /package/.docs/raw/docs/{(reference)/migrations → migrations}/deprecation-policy.mdx +0 -0
  338. /package/.docs/raw/docs/{(reference) → migrations}/react-compatibility.mdx +0 -0
  339. /package/.docs/raw/docs/{(reference)/migrations → migrations}/react-langgraph-v0-7.mdx +0 -0
  340. /package/.docs/raw/docs/{(reference)/migrations → migrations}/v0-11.mdx +0 -0
  341. /package/.docs/raw/docs/{(reference)/migrations → migrations}/v0-12.mdx +0 -0
@@ -0,0 +1,660 @@
1
+ # Example: with-resumable-stream
2
+
3
+ ## app/api/chat/resume/[streamId]/route.ts
4
+
5
+ ```typescript
6
+ import { UI_MESSAGE_STREAM_HEADERS } from "ai";
7
+ import { RESUMABLE_STREAM_ID_HEADER } from "assistant-stream/resumable";
8
+ import { getResumableStreamContext } from "@/lib/resumable-context";
9
+
10
+ export const maxDuration = 60;
11
+
12
+ export async function GET(
13
+ _req: Request,
14
+ context: { params: Promise<{ streamId: string }> },
15
+ ) {
16
+ const { streamId } = await context.params;
17
+ const ctx = await getResumableStreamContext();
18
+ const stream = await ctx.resume(streamId);
19
+
20
+ if (!stream) {
21
+ return new Response(JSON.stringify({ error: "stream not found" }), {
22
+ status: 404,
23
+ headers: { "Content-Type": "application/json" },
24
+ });
25
+ }
26
+
27
+ return new Response(stream, {
28
+ headers: {
29
+ ...UI_MESSAGE_STREAM_HEADERS,
30
+ [RESUMABLE_STREAM_ID_HEADER]: streamId,
31
+ },
32
+ });
33
+ }
34
+
35
+ ```
36
+
37
+ ## app/api/chat/route.ts
38
+
39
+ ```typescript
40
+ import { createOpenAI } from "@ai-sdk/openai";
41
+ import {
42
+ type JSONSchema7,
43
+ streamText,
44
+ convertToModelMessages,
45
+ createUIMessageStream,
46
+ JsonToSseTransformStream,
47
+ type UIMessage,
48
+ tool,
49
+ stepCountIs,
50
+ zodSchema,
51
+ } from "ai";
52
+ import { RESUMABLE_STREAM_ID_HEADER } from "assistant-stream/resumable";
53
+ import { z } from "zod";
54
+ import { getResumableStreamContext } from "@/lib/resumable-context";
55
+
56
+ export const maxDuration = 60;
57
+
58
+ export async function POST(req: Request) {
59
+ const {
60
+ messages,
61
+ system,
62
+ tools,
63
+ }: {
64
+ id?: string;
65
+ messages: UIMessage[];
66
+ system?: string;
67
+ tools?: Record<string, { description?: string; parameters: JSONSchema7 }>;
68
+ } = await req.json();
69
+
70
+ const streamId = crypto.randomUUID();
71
+
72
+ const sourceBody = process.env["OPENAI_API_KEY"]
73
+ ? await buildOpenAIBody({
74
+ messages,
75
+ ...(system && { system }),
76
+ ...(tools && { tools }),
77
+ })
78
+ : buildMockBody({ messages });
79
+
80
+ const context = await getResumableStreamContext();
81
+ const stream = await context.run(streamId, () => sourceBody);
82
+
83
+ return new Response(stream, {
84
+ headers: {
85
+ "Content-Type": "text/event-stream",
86
+ "Cache-Control": "no-cache",
87
+ Connection: "keep-alive",
88
+ [RESUMABLE_STREAM_ID_HEADER]: streamId,
89
+ },
90
+ });
91
+ }
92
+
93
+ function convertFrontendTools(
94
+ tools: Record<string, { description?: string; parameters: JSONSchema7 }>,
95
+ ): Record<string, ReturnType<typeof tool>> {
96
+ return Object.fromEntries(
97
+ Object.entries(tools).map(([name, t]) => [
98
+ name,
99
+ tool({
100
+ ...(t.description ? { description: t.description } : {}),
101
+ inputSchema: t.parameters as never,
102
+ }),
103
+ ]),
104
+ );
105
+ }
106
+
107
+ async function buildOpenAIBody({
108
+ messages,
109
+ system,
110
+ tools,
111
+ }: {
112
+ messages: UIMessage[];
113
+ system?: string;
114
+ tools?: Record<string, { description?: string; parameters: JSONSchema7 }>;
115
+ }): Promise<ReadableStream<Uint8Array>> {
116
+ const openai = createOpenAI({
117
+ apiKey: process.env["OPENAI_API_KEY"]!,
118
+ ...(process.env["OPENAI_BASE_URL"] && {
119
+ baseURL: process.env["OPENAI_BASE_URL"],
120
+ }),
121
+ });
122
+ const result = streamText({
123
+ model: openai("gpt-5.4-nano"),
124
+ messages: await convertToModelMessages(messages),
125
+ ...(system ? { system } : {}),
126
+ stopWhen: stepCountIs(10),
127
+ tools: {
128
+ ...convertFrontendTools(tools ?? {}),
129
+ get_current_weather: tool({
130
+ description: "Get the current weather",
131
+ inputSchema: zodSchema(z.object({ city: z.string() })),
132
+ execute: async ({ city }) => `The weather in ${city} is sunny`,
133
+ }),
134
+ slow_count: tool({
135
+ description: "Count slowly to N",
136
+ inputSchema: zodSchema(
137
+ z.object({ to: z.number().int().min(1).max(50) }),
138
+ ),
139
+ execute: async ({ to }) => {
140
+ await new Promise((r) => setTimeout(r, to * 200));
141
+ return `counted to ${to}`;
142
+ },
143
+ }),
144
+ },
145
+ });
146
+
147
+ const response = result.toUIMessageStreamResponse();
148
+ if (!response.body) throw new Error("expected response body");
149
+ return response.body;
150
+ }
151
+
152
+ function buildMockBody({
153
+ messages,
154
+ }: {
155
+ messages: UIMessage[];
156
+ }): ReadableStream<Uint8Array> {
157
+ const lastUserText =
158
+ messages
159
+ .filter((m) => m.role === "user")
160
+ .at(-1)
161
+ ?.parts.flatMap((p) =>
162
+ p.type === "text" ? [(p as { type: "text"; text: string }).text] : [],
163
+ )
164
+ .join(" ") ?? "your message";
165
+
166
+ const text =
167
+ `(mock response. set OPENAI_API_KEY for the real model)\n\n` +
168
+ `you said: ${lastUserText}\n\n` +
169
+ `here is a slow stream you can interrupt mid-flight by reloading the page. ` +
170
+ `the resumable layer keeps the producer running on the server, so when ` +
171
+ `the browser reconnects it continues right where it left off, with no ` +
172
+ `wasted tokens and no lost progress. ` +
173
+ `lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod ` +
174
+ `tempor incididunt ut labore et dolore magna aliqua. ut enim ad minim ` +
175
+ `veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea ` +
176
+ `commodo consequat. duis aute irure dolor in reprehenderit in voluptate ` +
177
+ `velit esse cillum dolore eu fugiat nulla pariatur. excepteur sint ` +
178
+ `occaecat cupidatat non proident, sunt in culpa qui officia deserunt ` +
179
+ `mollit anim id est laborum.\n\n` +
180
+ `done.`;
181
+
182
+ const messageId = `msg-${crypto.randomUUID()}`;
183
+ const textPartId = `text-${crypto.randomUUID()}`;
184
+ const tokens = text.match(/\S+\s*|\s+/g) ?? [text];
185
+
186
+ const uiStream = createUIMessageStream({
187
+ execute: async ({ writer }) => {
188
+ writer.write({ type: "start", messageId });
189
+ writer.write({ type: "start-step" });
190
+ writer.write({ type: "text-start", id: textPartId });
191
+ for (const tok of tokens) {
192
+ await new Promise((r) => setTimeout(r, 250));
193
+ writer.write({
194
+ type: "text-delta",
195
+ id: textPartId,
196
+ delta: tok,
197
+ });
198
+ }
199
+ writer.write({ type: "text-end", id: textPartId });
200
+ writer.write({ type: "finish-step" });
201
+ writer.write({ type: "finish" });
202
+ },
203
+ });
204
+
205
+ return uiStream
206
+ .pipeThrough(new JsonToSseTransformStream())
207
+ .pipeThrough(new TextEncoderStream());
208
+ }
209
+
210
+ ```
211
+
212
+ ## app/globals.css
213
+
214
+ ```css
215
+ @import "tailwindcss";
216
+ @import "tw-animate-css";
217
+
218
+ @source "../../../packages/ui/src";
219
+
220
+ @custom-variant dark (&:is(.dark *));
221
+
222
+ @theme inline {
223
+ --radius-sm: calc(var(--radius) - 4px);
224
+ --radius-md: calc(var(--radius) - 2px);
225
+ --radius-lg: var(--radius);
226
+ --radius-xl: calc(var(--radius) + 4px);
227
+ --color-background: var(--background);
228
+ --color-foreground: var(--foreground);
229
+ --color-card: var(--card);
230
+ --color-card-foreground: var(--card-foreground);
231
+ --color-popover: var(--popover);
232
+ --color-popover-foreground: var(--popover-foreground);
233
+ --color-primary: var(--primary);
234
+ --color-primary-foreground: var(--primary-foreground);
235
+ --color-secondary: var(--secondary);
236
+ --color-secondary-foreground: var(--secondary-foreground);
237
+ --color-muted: var(--muted);
238
+ --color-muted-foreground: var(--muted-foreground);
239
+ --color-accent: var(--accent);
240
+ --color-accent-foreground: var(--accent-foreground);
241
+ --color-destructive: var(--destructive);
242
+ --color-border: var(--border);
243
+ --color-input: var(--input);
244
+ --color-ring: var(--ring);
245
+ --color-chart-1: var(--chart-1);
246
+ --color-chart-2: var(--chart-2);
247
+ --color-chart-3: var(--chart-3);
248
+ --color-chart-4: var(--chart-4);
249
+ --color-chart-5: var(--chart-5);
250
+ --color-sidebar: var(--sidebar);
251
+ --color-sidebar-foreground: var(--sidebar-foreground);
252
+ --color-sidebar-primary: var(--sidebar-primary);
253
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
254
+ --color-sidebar-accent: var(--sidebar-accent);
255
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
256
+ --color-sidebar-border: var(--sidebar-border);
257
+ --color-sidebar-ring: var(--sidebar-ring);
258
+ }
259
+
260
+ :root {
261
+ --radius: 0.625rem;
262
+ --background: oklch(1 0 0);
263
+ --foreground: oklch(0.141 0.005 285.823);
264
+ --card: oklch(1 0 0);
265
+ --card-foreground: oklch(0.141 0.005 285.823);
266
+ --popover: oklch(1 0 0);
267
+ --popover-foreground: oklch(0.141 0.005 285.823);
268
+ --primary: oklch(0.21 0.006 285.885);
269
+ --primary-foreground: oklch(0.985 0 0);
270
+ --secondary: oklch(0.967 0.001 286.375);
271
+ --secondary-foreground: oklch(0.21 0.006 285.885);
272
+ --muted: oklch(0.967 0.001 286.375);
273
+ --muted-foreground: oklch(0.552 0.016 285.938);
274
+ --accent: oklch(0.967 0.001 286.375);
275
+ --accent-foreground: oklch(0.21 0.006 285.885);
276
+ --destructive: oklch(0.577 0.245 27.325);
277
+ --border: oklch(0.92 0.004 286.32);
278
+ --input: oklch(0.92 0.004 286.32);
279
+ --ring: oklch(0.705 0.015 286.067);
280
+ --chart-1: oklch(0.646 0.222 41.116);
281
+ --chart-2: oklch(0.6 0.118 184.704);
282
+ --chart-3: oklch(0.398 0.07 227.392);
283
+ --chart-4: oklch(0.828 0.189 84.429);
284
+ --chart-5: oklch(0.769 0.188 70.08);
285
+ --sidebar: oklch(0.985 0 0);
286
+ --sidebar-foreground: oklch(0.141 0.005 285.823);
287
+ --sidebar-primary: oklch(0.21 0.006 285.885);
288
+ --sidebar-primary-foreground: oklch(0.985 0 0);
289
+ --sidebar-accent: oklch(0.967 0.001 286.375);
290
+ --sidebar-accent-foreground: oklch(0.21 0.006 285.885);
291
+ --sidebar-border: oklch(0.92 0.004 286.32);
292
+ --sidebar-ring: oklch(0.705 0.015 286.067);
293
+ }
294
+
295
+ .dark {
296
+ --background: oklch(0.141 0.005 285.823);
297
+ --foreground: oklch(0.985 0 0);
298
+ --card: oklch(0.21 0.006 285.885);
299
+ --card-foreground: oklch(0.985 0 0);
300
+ --popover: oklch(0.21 0.006 285.885);
301
+ --popover-foreground: oklch(0.985 0 0);
302
+ --primary: oklch(0.92 0.004 286.32);
303
+ --primary-foreground: oklch(0.21 0.006 285.885);
304
+ --secondary: oklch(0.274 0.006 286.033);
305
+ --secondary-foreground: oklch(0.985 0 0);
306
+ --muted: oklch(0.274 0.006 286.033);
307
+ --muted-foreground: oklch(0.705 0.015 286.067);
308
+ --accent: oklch(0.274 0.006 286.033);
309
+ --accent-foreground: oklch(0.985 0 0);
310
+ --destructive: oklch(0.704 0.191 22.216);
311
+ --border: oklch(1 0 0 / 10%);
312
+ --input: oklch(1 0 0 / 15%);
313
+ --ring: oklch(0.552 0.016 285.938);
314
+ --chart-1: oklch(0.488 0.243 264.376);
315
+ --chart-2: oklch(0.696 0.17 162.48);
316
+ --chart-3: oklch(0.769 0.188 70.08);
317
+ --chart-4: oklch(0.627 0.265 303.9);
318
+ --chart-5: oklch(0.645 0.246 16.439);
319
+ --sidebar: oklch(0.21 0.006 285.885);
320
+ --sidebar-foreground: oklch(0.985 0 0);
321
+ --sidebar-primary: oklch(0.488 0.243 264.376);
322
+ --sidebar-primary-foreground: oklch(0.985 0 0);
323
+ --sidebar-accent: oklch(0.274 0.006 286.033);
324
+ --sidebar-accent-foreground: oklch(0.985 0 0);
325
+ --sidebar-border: oklch(1 0 0 / 10%);
326
+ --sidebar-ring: oklch(0.552 0.016 285.938);
327
+ }
328
+
329
+ @layer base {
330
+ * {
331
+ @apply border-border outline-ring/50;
332
+ }
333
+ body {
334
+ @apply bg-background text-foreground;
335
+ }
336
+ }
337
+
338
+ ```
339
+
340
+ ## app/layout.tsx
341
+
342
+ ```tsx
343
+ import type { Metadata } from "next";
344
+ import "./globals.css";
345
+
346
+ export const metadata: Metadata = {
347
+ title: "Resumable Stream Example",
348
+ description:
349
+ "Demonstrates assistant-stream/resumable: persist an in-flight LLM response so the client can reload mid-stream and pick up where it left off.",
350
+ };
351
+
352
+ export default function RootLayout({
353
+ children,
354
+ }: Readonly<{
355
+ children: React.ReactNode;
356
+ }>) {
357
+ return (
358
+ <html lang="en">
359
+ <body className="h-dvh">{children}</body>
360
+ </html>
361
+ );
362
+ }
363
+
364
+ ```
365
+
366
+ ## app/page.tsx
367
+
368
+ ```tsx
369
+ "use client";
370
+
371
+ import { useMemo } from "react";
372
+ import { AssistantRuntimeProvider } from "@assistant-ui/react";
373
+ import {
374
+ AssistantChatTransport,
375
+ createResumableSessionStorage,
376
+ useChatRuntime,
377
+ } from "@assistant-ui/react-ai-sdk";
378
+ import { Thread } from "@/components/assistant-ui/thread";
379
+
380
+ const storage = createResumableSessionStorage();
381
+
382
+ export default function Home() {
383
+ const transport = useMemo(
384
+ () =>
385
+ new AssistantChatTransport({
386
+ api: "/api/chat",
387
+ resumable: {
388
+ storage,
389
+ resumeApi: (streamId) => `/api/chat/resume/${streamId}`,
390
+ },
391
+ }),
392
+ [],
393
+ );
394
+
395
+ const runtime = useChatRuntime({ transport });
396
+
397
+ return (
398
+ <AssistantRuntimeProvider runtime={runtime}>
399
+ <div className="h-full">
400
+ <Thread />
401
+ </div>
402
+ </AssistantRuntimeProvider>
403
+ );
404
+ }
405
+
406
+ ```
407
+
408
+ ## components.json
409
+
410
+ ```json
411
+ {
412
+ "$schema": "https://ui.shadcn.com/schema.json",
413
+ "style": "new-york",
414
+ "rsc": true,
415
+ "tsx": true,
416
+ "tailwind": {
417
+ "config": "",
418
+ "css": "app/globals.css",
419
+ "baseColor": "zinc",
420
+ "cssVariables": true,
421
+ "prefix": ""
422
+ },
423
+ "aliases": {
424
+ "components": "@/components",
425
+ "utils": "@/lib/utils",
426
+ "ui": "@/components/ui",
427
+ "lib": "@/lib",
428
+ "hooks": "@/hooks"
429
+ },
430
+ "iconLibrary": "lucide",
431
+ "registries": {
432
+ "@assistant-ui": "https://r.assistant-ui.com/{name}.json"
433
+ }
434
+ }
435
+
436
+ ```
437
+
438
+ ## lib/resumable-context.ts
439
+
440
+ ```typescript
441
+ import {
442
+ createInMemoryResumableStreamStore,
443
+ createResumableStreamContext,
444
+ type ResumableStreamContext,
445
+ type ResumableStreamStore,
446
+ } from "assistant-stream/resumable";
447
+
448
+ const GLOBAL_KEY = Symbol.for("assistant-ui.example.resumable-context");
449
+
450
+ type GlobalSlot = typeof globalThis & {
451
+ [GLOBAL_KEY]?: Promise<ResumableStreamContext>;
452
+ };
453
+
454
+ const slot = globalThis as GlobalSlot;
455
+
456
+ export function getResumableStreamContext(): Promise<ResumableStreamContext> {
457
+ if (slot[GLOBAL_KEY]) return slot[GLOBAL_KEY];
458
+ const promise = (async () => {
459
+ const store = await createStore();
460
+ return createResumableStreamContext({ store });
461
+ })();
462
+ // clear the cache on rejection so the next request retries connecting.
463
+ promise.catch(() => {
464
+ if (slot[GLOBAL_KEY] === promise) {
465
+ delete slot[GLOBAL_KEY];
466
+ }
467
+ });
468
+ slot[GLOBAL_KEY] = promise;
469
+ return promise;
470
+ }
471
+
472
+ async function createStore(): Promise<ResumableStreamStore> {
473
+ const url = process.env["REDIS_URL"];
474
+ if (!url) {
475
+ return createInMemoryResumableStreamStore();
476
+ }
477
+
478
+ const { createClient } = await import("redis");
479
+ const { createRedisResumableStreamStore } = await import(
480
+ "assistant-stream/resumable/redis"
481
+ );
482
+
483
+ const client = createClient({ url });
484
+ client.on("error", (err) => {
485
+ console.error("[resumable-stream] redis client error:", err);
486
+ });
487
+ await client.connect();
488
+ return createRedisResumableStreamStore(client);
489
+ }
490
+
491
+ ```
492
+
493
+ ## next.config.js
494
+
495
+ ```javascript
496
+ /** @type {import('next').NextConfig} */
497
+ const nextConfig = {};
498
+
499
+ export default nextConfig;
500
+
501
+ ```
502
+
503
+ ## package.json
504
+
505
+ ```json
506
+ {
507
+ "name": "with-resumable-stream",
508
+ "version": "0.0.0",
509
+ "private": true,
510
+ "type": "module",
511
+ "scripts": {
512
+ "dev": "next dev --webpack",
513
+ "build": "next build",
514
+ "start": "next start"
515
+ },
516
+ "dependencies": {
517
+ "@ai-sdk/openai": "^3.0.64",
518
+ "@ai-sdk/react": "^3.0.190",
519
+ "@assistant-ui/react": "workspace:*",
520
+ "@assistant-ui/react-ai-sdk": "workspace:*",
521
+ "@assistant-ui/react-markdown": "workspace:*",
522
+ "@assistant-ui/store": "workspace:*",
523
+ "@assistant-ui/tap": "workspace:*",
524
+ "@assistant-ui/ui": "workspace:*",
525
+ "ai": "^6.0.188",
526
+ "assistant-stream": "workspace:*",
527
+ "class-variance-authority": "^0.7.1",
528
+ "clsx": "^2.1.1",
529
+ "lucide-react": "^1.16.0",
530
+ "next": "^16.2.6",
531
+ "react": "^19.2.6",
532
+ "react-dom": "^19.2.6",
533
+ "redis": "^5.12.1",
534
+ "tailwind-merge": "^3.6.0",
535
+ "zod": "^4.4.3"
536
+ },
537
+ "devDependencies": {
538
+ "@assistant-ui/x-buildutils": "workspace:*",
539
+ "@tailwindcss/postcss": "^4.3.0",
540
+ "@types/node": "^25.9.1",
541
+ "@types/react": "^19.2.15",
542
+ "@types/react-dom": "^19.2.3",
543
+ "postcss": "^8.5.15",
544
+ "tailwindcss": "^4.3.0",
545
+ "tw-animate-css": "^1.4.0",
546
+ "typescript": "^6.0.3"
547
+ }
548
+ }
549
+
550
+ ```
551
+
552
+ ## README.md
553
+
554
+ ```markdown
555
+ # with-resumable-stream
556
+
557
+ Demonstrates `assistant-stream/resumable`: persist an in-flight LLM response on the server so the client can reload or lose its connection mid-stream and pick up where it left off.
558
+
559
+ ## How it works
560
+
561
+ 1. Each `POST /api/chat` mints a new UUIDv4 `streamId` server-side and returns it in the `x-resumable-stream-id` header. `AssistantChatTransport` reads that header on the browser and stores the latest pending id in `sessionStorage`.
562
+ 2. The route runs `streamText`, then pipes the byte body through `context.run(streamId, () => uiMessageStreamBody)`. The bytes are persisted in the configured store while being streamed to the client.
563
+ 3. If the client disconnects mid-stream, the server-side producer task keeps running and continues to append bytes to the store.
564
+ 4. On page load, if `sessionStorage` still has a stream id, the client calls `chat.resumeStream()`. The transport's `resumable` adapter rewrites the AI SDK reconnect request to `GET /api/chat/resume/[streamId]`, which calls `context.resume(streamId)` and replays the persisted bytes (plus any new ones) to the reconnecting client.
565
+ 5. When the response stream closes naturally, the transport detects the AI SDK `finish` SSE event in the body and clears the stored id. Cancellation does not clear the id, so a reload mid-stream still finds it on next mount.
566
+
567
+ ## Quick start
568
+
569
+ ```sh
570
+ cp .env.example .env.local
571
+ # Optional: put your OPENAI_API_KEY in .env.local for the real model. Without
572
+ # it, the example falls back to a slow built-in mock so you can demo resume.
573
+ pnpm install
574
+ pnpm dev
575
+ ```
576
+
577
+ Open [http://localhost:3000](http://localhost:3000), send a prompt, then reload the page mid-response. The same answer keeps filling in.
578
+
579
+ ## Client integration
580
+
581
+ The browser side is wired through two helpers from `@assistant-ui/react-ai-sdk`:
582
+
583
+ - `createResumableSessionStorage()` returns a small `sessionStorage`-backed storage object for the pending stream id. Pass `{ key }` to namespace per route. Use `localStorage` instead if you want a stream that survives full browser restarts (and accept the cross-tab race that comes with it).
584
+ - `AssistantChatTransport` accepts a `resumable` option. When set, the transport captures the `x-resumable-stream-id` response header, watches the SSE body for the `finish` event so the stored id is cleared on natural completion (cancellation leaves it intact), and redirects `chat.resumeStream()` reconnects to the configured `resumeApi`.
585
+
586
+ The example fires `chat.resumeStream()` from a one-shot `useEffect` when storage already has an id at mount time. If you switch to `useChatRuntime`, that resume call is wired automatically.
587
+
588
+ ## Server methods
589
+
590
+ The `ResumableStreamContext` returned by `createResumableStreamContext` exposes:
591
+
592
+ - `run(streamId, makeStream)`: producer-or-consumer entrypoint. Auto-elects the role via the store, so concurrent callers with the same id share the persisted output.
593
+ - `resume(streamId)`: strict consumer; returns `null` when the stream does not exist.
594
+ - `requireResume(streamId)`: same as `resume`, but throws `ResumableStreamError("missing")` instead of returning `null`.
595
+ - `status(streamId)`: probe the lifecycle state without opening a reader.
596
+ - `delete(streamId)`: remove all state for a stream.
597
+
598
+ ## Storage
599
+
600
+ By default the example uses `createInMemoryResumableStreamStore` from `assistant-stream/resumable`. The store is memoized on `globalThis` via `Symbol.for`, so it survives Next.js hot reload but not full server restart. Default TTL is 24h; configure with `defaultTtlMs` if you want shorter eviction.
601
+
602
+ To use Redis instead, set `REDIS_URL` in `.env.local`:
603
+
604
+ ```sh
605
+ REDIS_URL=redis://localhost:6379
606
+ OPENAI_API_KEY=your-api-key-here
607
+ ```
608
+
609
+ The example will use the `assistant-stream/resumable/redis` adapter automatically. With Redis, resumable state survives server restarts (until the per-stream TTL expires; default 24h).
610
+
611
+ You can run a local Redis quickly with Docker:
612
+
613
+ ```sh
614
+ docker run -d --name redis -p 6379:6379 redis:7-alpine
615
+ ```
616
+
617
+ ## Production checklist
618
+
619
+ `GET /api/chat/resume/[streamId]` in this example serves any caller who knows the stream id. UUIDv4 is unguessable in practice, but the id leaks into response headers, `sessionStorage`, browser history, and access logs. Before deploying:
620
+
621
+ - Gate the resume endpoint with the same auth your chat endpoint uses.
622
+ - Bind `streamId` to the requesting user at creation time and reject mismatches before calling `context.resume`.
623
+ - On serverless platforms that kill the request handler when the response returns (Vercel, Cloudflare), pass `waitUntil` from `next/server` (`after`) when constructing the context. Otherwise the producer task is interrupted and resume cannot recover the rest of the stream.
624
+
625
+ ## Files of interest
626
+
627
+ - `lib/resumable-context.ts`: picks the store based on `REDIS_URL` and memoizes a single `ResumableStreamContext` across module reloads.
628
+ - `app/api/chat/route.ts`: POST endpoint that mints a fresh `streamId`, runs `streamText` (or a mock), and wraps the response body in `context.run`.
629
+ - `app/api/chat/resume/[streamId]/route.ts`: GET endpoint that calls `context.resume` and replays the persisted bytes.
630
+ - `app/page.tsx`: wires `useChat` with `AssistantChatTransport`'s `resumable` adapter and triggers `chat.resumeStream()` on mount when a pending id exists.
631
+
632
+ ## Related documentation
633
+
634
+ - [assistant-ui documentation](https://www.assistant-ui.com/docs)
635
+ - [AI SDK reconnect API](https://sdk.vercel.ai/docs)
636
+
637
+ ```
638
+
639
+ ## tsconfig.json
640
+
641
+ ```json
642
+ {
643
+ "extends": "@assistant-ui/x-buildutils/ts/next",
644
+ "compilerOptions": {
645
+ "paths": {
646
+ "@/*": ["./*"],
647
+ "@/components/assistant-ui/*": [
648
+ "../../packages/ui/src/components/assistant-ui/*"
649
+ ],
650
+ "@/components/ui/*": ["../../packages/ui/src/components/ui/*"],
651
+ "@/lib/utils": ["../../packages/ui/src/lib/utils"],
652
+ "@assistant-ui/ui/*": ["../../packages/ui/src/*"]
653
+ }
654
+ },
655
+ "include": ["**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
656
+ "exclude": ["node_modules"]
657
+ }
658
+
659
+ ```
660
+
@@ -491,18 +491,18 @@ export default nextConfig;
491
491
  "dependencies": {
492
492
  "@assistant-ui/store": "workspace:*",
493
493
  "@assistant-ui/tap": "workspace:*",
494
- "next": "^16.2.4",
495
- "react": "^19.2.5",
496
- "react-dom": "^19.2.5"
494
+ "next": "^16.2.6",
495
+ "react": "^19.2.6",
496
+ "react-dom": "^19.2.6"
497
497
  },
498
498
  "devDependencies": {
499
499
  "@assistant-ui/x-buildutils": "workspace:*",
500
- "@tailwindcss/postcss": "^4.2.4",
501
- "@types/node": "^25.6.0",
502
- "@types/react": "^19.2.14",
500
+ "@tailwindcss/postcss": "^4.3.0",
501
+ "@types/node": "^25.9.1",
502
+ "@types/react": "^19.2.15",
503
503
  "@types/react-dom": "^19.2.3",
504
- "postcss": "^8.5.10",
505
- "tailwindcss": "^4.2.4",
504
+ "postcss": "^8.5.15",
505
+ "tailwindcss": "^4.3.0",
506
506
  "tw-animate-css": "^1.4.0",
507
507
  "typescript": "^6.0.3"
508
508
  }