@assistant-ui/react 0.14.24 → 0.14.27

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 (457) hide show
  1. package/README.md +1 -1
  2. package/dist/augmentations.d.ts.map +1 -1
  3. package/dist/client/ExternalThread.d.ts +6 -4
  4. package/dist/client/ExternalThread.d.ts.map +1 -1
  5. package/dist/client/ExternalThread.js +2 -1
  6. package/dist/client/ExternalThread.js.map +1 -1
  7. package/dist/client/InMemoryThreadList.d.ts +0 -1
  8. package/dist/client/InMemoryThreadList.d.ts.map +1 -1
  9. package/dist/client/InMemoryThreadList.js +4 -1
  10. package/dist/client/InMemoryThreadList.js.map +1 -1
  11. package/dist/client/SingleThreadList.d.ts +0 -1
  12. package/dist/client/SingleThreadList.d.ts.map +1 -1
  13. package/dist/context/ReadonlyStore.d.ts +0 -1
  14. package/dist/context/ReadonlyStore.d.ts.map +1 -1
  15. package/dist/context/providers/MessageProvider.d.ts +0 -1
  16. package/dist/context/providers/MessageProvider.d.ts.map +1 -1
  17. package/dist/context/providers/ThreadViewportProvider.d.ts +0 -1
  18. package/dist/context/providers/ThreadViewportProvider.d.ts.map +1 -1
  19. package/dist/context/react/ThreadViewportContext.d.ts +15 -16
  20. package/dist/context/react/ThreadViewportContext.d.ts.map +1 -1
  21. package/dist/context/react/utils/createContextHook.d.ts +0 -1
  22. package/dist/context/react/utils/createContextHook.d.ts.map +1 -1
  23. package/dist/context/react/utils/createContextStoreHook.d.ts +2 -3
  24. package/dist/context/react/utils/createContextStoreHook.d.ts.map +1 -1
  25. package/dist/context/react/utils/createStateHookForRuntime.d.ts +0 -1
  26. package/dist/context/react/utils/createStateHookForRuntime.d.ts.map +1 -1
  27. package/dist/context/react/utils/ensureBinding.d.ts.map +1 -1
  28. package/dist/context/react/utils/useRuntimeState.d.ts +0 -1
  29. package/dist/context/react/utils/useRuntimeState.d.ts.map +1 -1
  30. package/dist/context/stores/ThreadViewport.d.ts +25 -15
  31. package/dist/context/stores/ThreadViewport.d.ts.map +1 -1
  32. package/dist/devtools/DevToolsHooks.d.ts +0 -1
  33. package/dist/devtools/DevToolsHooks.d.ts.map +1 -1
  34. package/dist/hooks/useMessageQuote.d.ts +0 -1
  35. package/dist/hooks/useMessageQuote.d.ts.map +1 -1
  36. package/dist/hooks/useMessageTiming.d.ts +0 -1
  37. package/dist/hooks/useMessageTiming.d.ts.map +1 -1
  38. package/dist/hooks/useToolCallElapsed.d.ts.map +1 -1
  39. package/dist/index.d.ts +5 -3
  40. package/dist/internal.d.ts +0 -2
  41. package/dist/legacy-runtime/AssistantRuntimeProvider.d.ts +0 -1
  42. package/dist/legacy-runtime/AssistantRuntimeProvider.d.ts.map +1 -1
  43. package/dist/legacy-runtime/cloud/auiV0.d.ts +11 -2
  44. package/dist/legacy-runtime/cloud/auiV0.d.ts.map +1 -1
  45. package/dist/legacy-runtime/cloud/auiV0.js +31 -2
  46. package/dist/legacy-runtime/cloud/auiV0.js.map +1 -1
  47. package/dist/legacy-runtime/cloud/useCloudThreadListRuntime.d.ts +1 -5
  48. package/dist/legacy-runtime/cloud/useCloudThreadListRuntime.d.ts.map +1 -1
  49. package/dist/legacy-runtime/hooks/AssistantContext.d.ts +0 -1
  50. package/dist/legacy-runtime/hooks/AssistantContext.d.ts.map +1 -1
  51. package/dist/legacy-runtime/hooks/AttachmentContext.d.ts +0 -1
  52. package/dist/legacy-runtime/hooks/AttachmentContext.d.ts.map +1 -1
  53. package/dist/legacy-runtime/hooks/ComposerContext.d.ts +0 -1
  54. package/dist/legacy-runtime/hooks/ComposerContext.d.ts.map +1 -1
  55. package/dist/legacy-runtime/hooks/MessageContext.d.ts +0 -1
  56. package/dist/legacy-runtime/hooks/MessageContext.d.ts.map +1 -1
  57. package/dist/legacy-runtime/hooks/MessagePartContext.d.ts +0 -1
  58. package/dist/legacy-runtime/hooks/MessagePartContext.d.ts.map +1 -1
  59. package/dist/legacy-runtime/hooks/ThreadContext.d.ts +0 -1
  60. package/dist/legacy-runtime/hooks/ThreadContext.d.ts.map +1 -1
  61. package/dist/legacy-runtime/hooks/ThreadListItemContext.d.ts +0 -1
  62. package/dist/legacy-runtime/hooks/ThreadListItemContext.d.ts.map +1 -1
  63. package/dist/legacy-runtime/runtime-cores/assistant-transport/commandQueue.d.ts +0 -1
  64. package/dist/legacy-runtime/runtime-cores/assistant-transport/commandQueue.d.ts.map +1 -1
  65. package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.d.ts +1 -4
  66. package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.d.ts.map +1 -1
  67. package/dist/legacy-runtime/runtime-cores/assistant-transport/runManager.d.ts.map +1 -1
  68. package/dist/legacy-runtime/runtime-cores/assistant-transport/types.d.ts +0 -1
  69. package/dist/legacy-runtime/runtime-cores/assistant-transport/types.d.ts.map +1 -1
  70. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.d.ts +0 -1
  71. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -1
  72. package/dist/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.d.ts +0 -1
  73. package/dist/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.d.ts.map +1 -1
  74. package/dist/legacy-runtime/runtime-cores/assistant-transport/useLatestRef.d.ts.map +1 -1
  75. package/dist/mcp-apps/McpAppRenderer.d.ts +12 -7
  76. package/dist/mcp-apps/McpAppRenderer.d.ts.map +1 -1
  77. package/dist/mcp-apps/McpAppRenderer.js +29 -7
  78. package/dist/mcp-apps/McpAppRenderer.js.map +1 -1
  79. package/dist/mcp-apps/McpAppsRemoteHost.d.ts +0 -1
  80. package/dist/mcp-apps/McpAppsRemoteHost.d.ts.map +1 -1
  81. package/dist/mcp-apps/McpAppsRemoteHost.js +32 -1
  82. package/dist/mcp-apps/McpAppsRemoteHost.js.map +1 -1
  83. package/dist/mcp-apps/app-frame.d.ts +1 -12
  84. package/dist/mcp-apps/app-frame.d.ts.map +1 -1
  85. package/dist/mcp-apps/app-frame.js +1 -1
  86. package/dist/mcp-apps/app-frame.js.map +1 -1
  87. package/dist/mcp-apps/bridge.d.ts +0 -1
  88. package/dist/mcp-apps/bridge.d.ts.map +1 -1
  89. package/dist/mcp-apps/bridge.js +4 -3
  90. package/dist/mcp-apps/bridge.js.map +1 -1
  91. package/dist/mcp-apps/types.d.ts +10 -7
  92. package/dist/mcp-apps/types.d.ts.map +1 -1
  93. package/dist/mcp-apps/types.js.map +1 -1
  94. package/dist/mcp-apps/utils.d.ts +0 -1
  95. package/dist/mcp-apps/utils.d.ts.map +1 -1
  96. package/dist/model-context/frame/useAssistantFrameHost.d.ts +1 -6
  97. package/dist/model-context/frame/useAssistantFrameHost.d.ts.map +1 -1
  98. package/dist/model-context/makeAssistantVisible.d.ts +0 -1
  99. package/dist/model-context/makeAssistantVisible.d.ts.map +1 -1
  100. package/dist/primitives/actionBar/ActionBarCopy.d.ts +1 -4
  101. package/dist/primitives/actionBar/ActionBarCopy.d.ts.map +1 -1
  102. package/dist/primitives/actionBar/ActionBarEdit.d.ts +0 -1
  103. package/dist/primitives/actionBar/ActionBarEdit.d.ts.map +1 -1
  104. package/dist/primitives/actionBar/ActionBarExportMarkdown.d.ts +1 -5
  105. package/dist/primitives/actionBar/ActionBarExportMarkdown.d.ts.map +1 -1
  106. package/dist/primitives/actionBar/ActionBarFeedbackNegative.d.ts +0 -1
  107. package/dist/primitives/actionBar/ActionBarFeedbackNegative.d.ts.map +1 -1
  108. package/dist/primitives/actionBar/ActionBarFeedbackPositive.d.ts +0 -1
  109. package/dist/primitives/actionBar/ActionBarFeedbackPositive.d.ts.map +1 -1
  110. package/dist/primitives/actionBar/ActionBarInteractionContext.d.ts.map +1 -1
  111. package/dist/primitives/actionBar/ActionBarReload.d.ts +0 -1
  112. package/dist/primitives/actionBar/ActionBarReload.d.ts.map +1 -1
  113. package/dist/primitives/actionBar/ActionBarRoot.d.ts +0 -1
  114. package/dist/primitives/actionBar/ActionBarRoot.d.ts.map +1 -1
  115. package/dist/primitives/actionBar/ActionBarSpeak.d.ts +0 -1
  116. package/dist/primitives/actionBar/ActionBarSpeak.d.ts.map +1 -1
  117. package/dist/primitives/actionBar/ActionBarStopSpeaking.d.ts +0 -1
  118. package/dist/primitives/actionBar/ActionBarStopSpeaking.d.ts.map +1 -1
  119. package/dist/primitives/actionBar/useActionBarFloatStatus.d.ts +1 -6
  120. package/dist/primitives/actionBar/useActionBarFloatStatus.d.ts.map +1 -1
  121. package/dist/primitives/actionBar.d.ts +0 -2
  122. package/dist/primitives/actionBarMore/ActionBarMoreContent.d.ts +0 -1
  123. package/dist/primitives/actionBarMore/ActionBarMoreContent.d.ts.map +1 -1
  124. package/dist/primitives/actionBarMore/ActionBarMoreItem.d.ts +0 -1
  125. package/dist/primitives/actionBarMore/ActionBarMoreItem.d.ts.map +1 -1
  126. package/dist/primitives/actionBarMore/ActionBarMoreRoot.d.ts +0 -1
  127. package/dist/primitives/actionBarMore/ActionBarMoreRoot.d.ts.map +1 -1
  128. package/dist/primitives/actionBarMore/ActionBarMoreSeparator.d.ts +0 -1
  129. package/dist/primitives/actionBarMore/ActionBarMoreSeparator.d.ts.map +1 -1
  130. package/dist/primitives/actionBarMore/ActionBarMoreTrigger.d.ts +0 -1
  131. package/dist/primitives/actionBarMore/ActionBarMoreTrigger.d.ts.map +1 -1
  132. package/dist/primitives/actionBarMore/scope.d.ts +0 -1
  133. package/dist/primitives/actionBarMore/scope.d.ts.map +1 -1
  134. package/dist/primitives/actionBarMore.d.ts +0 -2
  135. package/dist/primitives/assistantModal/AssistantModalAnchor.d.ts +6 -4
  136. package/dist/primitives/assistantModal/AssistantModalAnchor.d.ts.map +1 -1
  137. package/dist/primitives/assistantModal/AssistantModalAnchor.js +2 -2
  138. package/dist/primitives/assistantModal/AssistantModalAnchor.js.map +1 -1
  139. package/dist/primitives/assistantModal/AssistantModalContent.d.ts +4 -2
  140. package/dist/primitives/assistantModal/AssistantModalContent.d.ts.map +1 -1
  141. package/dist/primitives/assistantModal/AssistantModalContent.js +2 -1
  142. package/dist/primitives/assistantModal/AssistantModalContent.js.map +1 -1
  143. package/dist/primitives/assistantModal/AssistantModalRoot.d.ts +0 -1
  144. package/dist/primitives/assistantModal/AssistantModalRoot.d.ts.map +1 -1
  145. package/dist/primitives/assistantModal/AssistantModalTrigger.d.ts +6 -4
  146. package/dist/primitives/assistantModal/AssistantModalTrigger.d.ts.map +1 -1
  147. package/dist/primitives/assistantModal/AssistantModalTrigger.js +2 -2
  148. package/dist/primitives/assistantModal/AssistantModalTrigger.js.map +1 -1
  149. package/dist/primitives/assistantModal/popoverRenderPrimitives.d.ts +14 -0
  150. package/dist/primitives/assistantModal/popoverRenderPrimitives.d.ts.map +1 -0
  151. package/dist/primitives/assistantModal/popoverRenderPrimitives.js +10 -0
  152. package/dist/primitives/assistantModal/popoverRenderPrimitives.js.map +1 -0
  153. package/dist/primitives/assistantModal/scope.d.ts +0 -1
  154. package/dist/primitives/assistantModal/scope.d.ts.map +1 -1
  155. package/dist/primitives/assistantModal.d.ts +0 -2
  156. package/dist/primitives/attachment/AttachmentName.d.ts +0 -1
  157. package/dist/primitives/attachment/AttachmentName.d.ts.map +1 -1
  158. package/dist/primitives/attachment/AttachmentRemove.d.ts +0 -1
  159. package/dist/primitives/attachment/AttachmentRemove.d.ts.map +1 -1
  160. package/dist/primitives/attachment/AttachmentRoot.d.ts +0 -1
  161. package/dist/primitives/attachment/AttachmentRoot.d.ts.map +1 -1
  162. package/dist/primitives/attachment/AttachmentThumb.d.ts +0 -1
  163. package/dist/primitives/attachment/AttachmentThumb.d.ts.map +1 -1
  164. package/dist/primitives/attachment.d.ts +0 -2
  165. package/dist/primitives/branchPicker/BranchPickerCount.d.ts +0 -1
  166. package/dist/primitives/branchPicker/BranchPickerCount.d.ts.map +1 -1
  167. package/dist/primitives/branchPicker/BranchPickerNext.d.ts +0 -1
  168. package/dist/primitives/branchPicker/BranchPickerNext.d.ts.map +1 -1
  169. package/dist/primitives/branchPicker/BranchPickerNumber.d.ts +0 -1
  170. package/dist/primitives/branchPicker/BranchPickerNumber.d.ts.map +1 -1
  171. package/dist/primitives/branchPicker/BranchPickerPrevious.d.ts +0 -1
  172. package/dist/primitives/branchPicker/BranchPickerPrevious.d.ts.map +1 -1
  173. package/dist/primitives/branchPicker/BranchPickerRoot.d.ts +0 -1
  174. package/dist/primitives/branchPicker/BranchPickerRoot.d.ts.map +1 -1
  175. package/dist/primitives/branchPicker.d.ts +0 -2
  176. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.d.ts +0 -1
  177. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.d.ts.map +1 -1
  178. package/dist/primitives/chainOfThought/ChainOfThoughtRoot.d.ts +0 -1
  179. package/dist/primitives/chainOfThought/ChainOfThoughtRoot.d.ts.map +1 -1
  180. package/dist/primitives/chainOfThought.d.ts +0 -2
  181. package/dist/primitives/composer/ComposerAddAttachment.d.ts +5 -6
  182. package/dist/primitives/composer/ComposerAddAttachment.d.ts.map +1 -1
  183. package/dist/primitives/composer/ComposerAttachmentDropzone.d.ts +0 -1
  184. package/dist/primitives/composer/ComposerAttachmentDropzone.d.ts.map +1 -1
  185. package/dist/primitives/composer/ComposerCancel.d.ts +0 -1
  186. package/dist/primitives/composer/ComposerCancel.d.ts.map +1 -1
  187. package/dist/primitives/composer/ComposerCompactContext.d.ts +9 -0
  188. package/dist/primitives/composer/ComposerCompactContext.d.ts.map +1 -0
  189. package/dist/primitives/composer/ComposerCompactContext.js +11 -0
  190. package/dist/primitives/composer/ComposerCompactContext.js.map +1 -0
  191. package/dist/primitives/composer/ComposerDictate.d.ts +0 -1
  192. package/dist/primitives/composer/ComposerDictate.d.ts.map +1 -1
  193. package/dist/primitives/composer/ComposerDictationTranscript.d.ts +0 -1
  194. package/dist/primitives/composer/ComposerDictationTranscript.d.ts.map +1 -1
  195. package/dist/primitives/composer/ComposerInput.d.ts +0 -1
  196. package/dist/primitives/composer/ComposerInput.d.ts.map +1 -1
  197. package/dist/primitives/composer/ComposerInput.js +17 -2
  198. package/dist/primitives/composer/ComposerInput.js.map +1 -1
  199. package/dist/primitives/composer/ComposerInputPluginContext.d.ts +4 -3
  200. package/dist/primitives/composer/ComposerInputPluginContext.d.ts.map +1 -1
  201. package/dist/primitives/composer/ComposerQuote.d.ts +0 -1
  202. package/dist/primitives/composer/ComposerQuote.d.ts.map +1 -1
  203. package/dist/primitives/composer/ComposerRoot.d.ts +22 -3
  204. package/dist/primitives/composer/ComposerRoot.d.ts.map +1 -1
  205. package/dist/primitives/composer/ComposerRoot.js +63 -30
  206. package/dist/primitives/composer/ComposerRoot.js.map +1 -1
  207. package/dist/primitives/composer/ComposerSend.d.ts +0 -1
  208. package/dist/primitives/composer/ComposerSend.d.ts.map +1 -1
  209. package/dist/primitives/composer/ComposerStopDictation.d.ts +0 -1
  210. package/dist/primitives/composer/ComposerStopDictation.d.ts.map +1 -1
  211. package/dist/primitives/composer/trigger/TriggerPopover.d.ts +10 -5
  212. package/dist/primitives/composer/trigger/TriggerPopover.d.ts.map +1 -1
  213. package/dist/primitives/composer/trigger/TriggerPopoverAction.d.ts +5 -3
  214. package/dist/primitives/composer/trigger/TriggerPopoverAction.d.ts.map +1 -1
  215. package/dist/primitives/composer/trigger/TriggerPopoverAction.js +3 -2
  216. package/dist/primitives/composer/trigger/TriggerPopoverAction.js.map +1 -1
  217. package/dist/primitives/composer/trigger/TriggerPopoverBack.d.ts +0 -1
  218. package/dist/primitives/composer/trigger/TriggerPopoverBack.d.ts.map +1 -1
  219. package/dist/primitives/composer/trigger/TriggerPopoverCategories.d.ts +0 -1
  220. package/dist/primitives/composer/trigger/TriggerPopoverCategories.d.ts.map +1 -1
  221. package/dist/primitives/composer/trigger/TriggerPopoverDirective.d.ts +3 -2
  222. package/dist/primitives/composer/trigger/TriggerPopoverDirective.d.ts.map +1 -1
  223. package/dist/primitives/composer/trigger/TriggerPopoverItems.d.ts +0 -1
  224. package/dist/primitives/composer/trigger/TriggerPopoverItems.d.ts.map +1 -1
  225. package/dist/primitives/composer/trigger/TriggerPopoverResource.d.ts +10 -6
  226. package/dist/primitives/composer/trigger/TriggerPopoverResource.d.ts.map +1 -1
  227. package/dist/primitives/composer/trigger/TriggerPopoverRootContext.d.ts +8 -5
  228. package/dist/primitives/composer/trigger/TriggerPopoverRootContext.d.ts.map +1 -1
  229. package/dist/primitives/composer/trigger/index.d.ts +0 -1
  230. package/dist/primitives/composer/trigger/index.d.ts.map +1 -1
  231. package/dist/primitives/composer/trigger/triggerDetectionResource.d.ts +5 -2
  232. package/dist/primitives/composer/trigger/triggerDetectionResource.d.ts.map +1 -1
  233. package/dist/primitives/composer/trigger/triggerKeyboardResource.d.ts +7 -4
  234. package/dist/primitives/composer/trigger/triggerKeyboardResource.d.ts.map +1 -1
  235. package/dist/primitives/composer/trigger/triggerNavigationResource.d.ts +13 -7
  236. package/dist/primitives/composer/trigger/triggerNavigationResource.d.ts.map +1 -1
  237. package/dist/primitives/composer/trigger/triggerSelectionResource.d.ts +7 -4
  238. package/dist/primitives/composer/trigger/triggerSelectionResource.d.ts.map +1 -1
  239. package/dist/primitives/composer/useComposerInputState.d.ts.map +1 -1
  240. package/dist/primitives/composer.d.ts +0 -2
  241. package/dist/primitives/dropdownMenuRenderPrimitives.d.ts +0 -1
  242. package/dist/primitives/dropdownMenuRenderPrimitives.d.ts.map +1 -1
  243. package/dist/primitives/error/ErrorMessage.d.ts +0 -1
  244. package/dist/primitives/error/ErrorMessage.d.ts.map +1 -1
  245. package/dist/primitives/error/ErrorRoot.d.ts +0 -1
  246. package/dist/primitives/error/ErrorRoot.d.ts.map +1 -1
  247. package/dist/primitives/error.d.ts +0 -2
  248. package/dist/primitives/message/MessageError.d.ts +0 -1
  249. package/dist/primitives/message/MessageError.d.ts.map +1 -1
  250. package/dist/primitives/message/MessageIf.d.ts +0 -1
  251. package/dist/primitives/message/MessageIf.d.ts.map +1 -1
  252. package/dist/primitives/message/MessageParts.d.ts +0 -1
  253. package/dist/primitives/message/MessageParts.d.ts.map +1 -1
  254. package/dist/primitives/message/MessagePartsGrouped.d.ts +25 -12
  255. package/dist/primitives/message/MessagePartsGrouped.d.ts.map +1 -1
  256. package/dist/primitives/message/MessageRoot.d.ts +0 -1
  257. package/dist/primitives/message/MessageRoot.d.ts.map +1 -1
  258. package/dist/primitives/message.d.ts +0 -2
  259. package/dist/primitives/messagePart/MessagePartImage.d.ts +0 -1
  260. package/dist/primitives/messagePart/MessagePartImage.d.ts.map +1 -1
  261. package/dist/primitives/messagePart/MessagePartText.d.ts +2 -1
  262. package/dist/primitives/messagePart/MessagePartText.d.ts.map +1 -1
  263. package/dist/primitives/messagePart/MessagePartText.js.map +1 -1
  264. package/dist/primitives/messagePart/useMessagePartData.d.ts +0 -1
  265. package/dist/primitives/messagePart/useMessagePartData.d.ts.map +1 -1
  266. package/dist/primitives/messagePart/useMessagePartFile.d.ts +0 -1
  267. package/dist/primitives/messagePart/useMessagePartFile.d.ts.map +1 -1
  268. package/dist/primitives/messagePart/useMessagePartImage.d.ts +0 -1
  269. package/dist/primitives/messagePart/useMessagePartImage.d.ts.map +1 -1
  270. package/dist/primitives/messagePart/useMessagePartReasoning.d.ts +0 -1
  271. package/dist/primitives/messagePart/useMessagePartReasoning.d.ts.map +1 -1
  272. package/dist/primitives/messagePart/useMessagePartSource.d.ts.map +1 -1
  273. package/dist/primitives/messagePart/useMessagePartText.d.ts +0 -1
  274. package/dist/primitives/messagePart/useMessagePartText.d.ts.map +1 -1
  275. package/dist/primitives/messagePart.d.ts +0 -2
  276. package/dist/primitives/queueItem/QueueItemRemove.d.ts +0 -1
  277. package/dist/primitives/queueItem/QueueItemRemove.d.ts.map +1 -1
  278. package/dist/primitives/queueItem/QueueItemSteer.d.ts +0 -1
  279. package/dist/primitives/queueItem/QueueItemSteer.d.ts.map +1 -1
  280. package/dist/primitives/queueItem/QueueItemText.d.ts +0 -1
  281. package/dist/primitives/queueItem/QueueItemText.d.ts.map +1 -1
  282. package/dist/primitives/queueItem.d.ts +0 -2
  283. package/dist/primitives/reasoning/useScrollLock.d.ts +0 -1
  284. package/dist/primitives/reasoning/useScrollLock.d.ts.map +1 -1
  285. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.d.ts +0 -1
  286. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.d.ts.map +1 -1
  287. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.d.ts +0 -1
  288. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.d.ts.map +1 -1
  289. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js +2 -1
  290. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js.map +1 -1
  291. package/dist/primitives/selectionToolbar.d.ts +0 -2
  292. package/dist/primitives/suggestion/SuggestionDescription.d.ts +0 -1
  293. package/dist/primitives/suggestion/SuggestionDescription.d.ts.map +1 -1
  294. package/dist/primitives/suggestion/SuggestionTitle.d.ts +0 -1
  295. package/dist/primitives/suggestion/SuggestionTitle.d.ts.map +1 -1
  296. package/dist/primitives/suggestion/SuggestionTrigger.d.ts +1 -5
  297. package/dist/primitives/suggestion/SuggestionTrigger.d.ts.map +1 -1
  298. package/dist/primitives/suggestion.d.ts +0 -2
  299. package/dist/primitives/thread/ThreadEmpty.d.ts +0 -1
  300. package/dist/primitives/thread/ThreadEmpty.d.ts.map +1 -1
  301. package/dist/primitives/thread/ThreadIf.d.ts +0 -1
  302. package/dist/primitives/thread/ThreadIf.d.ts.map +1 -1
  303. package/dist/primitives/thread/ThreadRoot.d.ts +0 -1
  304. package/dist/primitives/thread/ThreadRoot.d.ts.map +1 -1
  305. package/dist/primitives/thread/ThreadScrollToBottom.d.ts +1 -4
  306. package/dist/primitives/thread/ThreadScrollToBottom.d.ts.map +1 -1
  307. package/dist/primitives/thread/ThreadSuggestion.d.ts +13 -14
  308. package/dist/primitives/thread/ThreadSuggestion.d.ts.map +1 -1
  309. package/dist/primitives/thread/ThreadViewport.d.ts +0 -1
  310. package/dist/primitives/thread/ThreadViewport.d.ts.map +1 -1
  311. package/dist/primitives/thread/ThreadViewportFooter.d.ts +0 -1
  312. package/dist/primitives/thread/ThreadViewportFooter.d.ts.map +1 -1
  313. package/dist/primitives/thread/topAnchor/computeTopAnchorSlack.d.ts +2 -11
  314. package/dist/primitives/thread/topAnchor/computeTopAnchorSlack.d.ts.map +1 -1
  315. package/dist/primitives/thread/topAnchor/createReserveObservers.d.ts.map +1 -1
  316. package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.d.ts.map +1 -1
  317. package/dist/primitives/thread/topAnchor/topAnchorTurn.d.ts +1 -4
  318. package/dist/primitives/thread/topAnchor/topAnchorTurn.d.ts.map +1 -1
  319. package/dist/primitives/thread/topAnchor/topAnchorUtils.d.ts.map +1 -1
  320. package/dist/primitives/thread/topAnchor/useTopAnchorReserve.d.ts.map +1 -1
  321. package/dist/primitives/thread/useThreadViewportAutoScroll.d.ts +1 -7
  322. package/dist/primitives/thread/useThreadViewportAutoScroll.d.ts.map +1 -1
  323. package/dist/primitives/thread.d.ts +0 -2
  324. package/dist/primitives/threadList/ThreadListLoadMore.d.ts +0 -1
  325. package/dist/primitives/threadList/ThreadListLoadMore.d.ts.map +1 -1
  326. package/dist/primitives/threadList/ThreadListNew.d.ts +0 -1
  327. package/dist/primitives/threadList/ThreadListNew.d.ts.map +1 -1
  328. package/dist/primitives/threadList/ThreadListRoot.d.ts +0 -1
  329. package/dist/primitives/threadList/ThreadListRoot.d.ts.map +1 -1
  330. package/dist/primitives/threadList/ThreadListRoot.js +10 -3
  331. package/dist/primitives/threadList/ThreadListRoot.js.map +1 -1
  332. package/dist/primitives/threadList.d.ts +0 -2
  333. package/dist/primitives/threadListFocusGroup.d.ts +25 -0
  334. package/dist/primitives/threadListFocusGroup.d.ts.map +1 -0
  335. package/dist/primitives/threadListFocusGroup.js +15 -0
  336. package/dist/primitives/threadListFocusGroup.js.map +1 -0
  337. package/dist/primitives/threadListItem/ThreadListItemArchive.d.ts +0 -1
  338. package/dist/primitives/threadListItem/ThreadListItemArchive.d.ts.map +1 -1
  339. package/dist/primitives/threadListItem/ThreadListItemDelete.d.ts +0 -1
  340. package/dist/primitives/threadListItem/ThreadListItemDelete.d.ts.map +1 -1
  341. package/dist/primitives/threadListItem/ThreadListItemRoot.d.ts +0 -1
  342. package/dist/primitives/threadListItem/ThreadListItemRoot.d.ts.map +1 -1
  343. package/dist/primitives/threadListItem/ThreadListItemRoot.js +45 -27
  344. package/dist/primitives/threadListItem/ThreadListItemRoot.js.map +1 -1
  345. package/dist/primitives/threadListItem/ThreadListItemTrigger.d.ts +0 -1
  346. package/dist/primitives/threadListItem/ThreadListItemTrigger.d.ts.map +1 -1
  347. package/dist/primitives/threadListItem/ThreadListItemTrigger.js +26 -2
  348. package/dist/primitives/threadListItem/ThreadListItemTrigger.js.map +1 -1
  349. package/dist/primitives/threadListItem/ThreadListItemUnarchive.d.ts +0 -1
  350. package/dist/primitives/threadListItem/ThreadListItemUnarchive.d.ts.map +1 -1
  351. package/dist/primitives/threadListItem.d.ts +0 -2
  352. package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.d.ts +0 -1
  353. package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.d.ts.map +1 -1
  354. package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.js +63 -38
  355. package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.js.map +1 -1
  356. package/dist/primitives/threadListItemMore/ThreadListItemMoreItem.d.ts +0 -1
  357. package/dist/primitives/threadListItemMore/ThreadListItemMoreItem.d.ts.map +1 -1
  358. package/dist/primitives/threadListItemMore/ThreadListItemMoreRoot.d.ts +20 -4
  359. package/dist/primitives/threadListItemMore/ThreadListItemMoreRoot.d.ts.map +1 -1
  360. package/dist/primitives/threadListItemMore/ThreadListItemMoreRoot.js +95 -14
  361. package/dist/primitives/threadListItemMore/ThreadListItemMoreRoot.js.map +1 -1
  362. package/dist/primitives/threadListItemMore/ThreadListItemMoreSeparator.d.ts +0 -1
  363. package/dist/primitives/threadListItemMore/ThreadListItemMoreSeparator.d.ts.map +1 -1
  364. package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.d.ts +0 -1
  365. package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.d.ts.map +1 -1
  366. package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.js +38 -21
  367. package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.js.map +1 -1
  368. package/dist/primitives/threadListItemMore/scope.d.ts +0 -1
  369. package/dist/primitives/threadListItemMore/scope.d.ts.map +1 -1
  370. package/dist/primitives/threadListItemMore.d.ts +0 -2
  371. package/dist/sandbox-host/SandboxHost.d.ts +1 -10
  372. package/dist/sandbox-host/SandboxHost.d.ts.map +1 -1
  373. package/dist/tests/remote-thread-list-test-helpers.d.ts +0 -1
  374. package/dist/tests/remote-thread-list-test-helpers.d.ts.map +1 -1
  375. package/dist/unstable/useComposerInput.d.ts +2 -2
  376. package/dist/unstable/useComposerInput.d.ts.map +1 -1
  377. package/dist/unstable/useComposerInputHistory.d.ts +2 -2
  378. package/dist/unstable/useComposerInputHistory.d.ts.map +1 -1
  379. package/dist/unstable/useLiveCompletionAdapter.d.ts +4 -3
  380. package/dist/unstable/useLiveCompletionAdapter.d.ts.map +1 -1
  381. package/dist/unstable/useMentionAdapter.d.ts +19 -10
  382. package/dist/unstable/useMentionAdapter.d.ts.map +1 -1
  383. package/dist/unstable/useMessageStallDetection.d.ts +3 -1
  384. package/dist/unstable/useMessageStallDetection.d.ts.map +1 -1
  385. package/dist/unstable/useSlashCommandAdapter.d.ts +6 -4
  386. package/dist/unstable/useSlashCommandAdapter.d.ts.map +1 -1
  387. package/dist/utils/Primitive.d.ts +0 -1
  388. package/dist/utils/Primitive.d.ts.map +1 -1
  389. package/dist/utils/RequireAtLeastOne.d.ts +1 -1
  390. package/dist/utils/RequireAtLeastOne.d.ts.map +1 -1
  391. package/dist/utils/createActionButton.d.ts +0 -1
  392. package/dist/utils/createActionButton.d.ts.map +1 -1
  393. package/dist/utils/getSelectionMessageId.d.ts.map +1 -1
  394. package/dist/utils/getSelectionMessageId.js +32 -7
  395. package/dist/utils/getSelectionMessageId.js.map +1 -1
  396. package/dist/utils/hooks/useManagedRef.d.ts.map +1 -1
  397. package/dist/utils/hooks/useMediaQuery.d.ts.map +1 -1
  398. package/dist/utils/hooks/useMediaQuery.js +2 -2
  399. package/dist/utils/hooks/useMediaQuery.js.map +1 -1
  400. package/dist/utils/hooks/useOnResizeContent.d.ts.map +1 -1
  401. package/dist/utils/hooks/useOnScrollToBottom.d.ts.map +1 -1
  402. package/dist/utils/hooks/useSizeHandle.d.ts +0 -1
  403. package/dist/utils/hooks/useSizeHandle.d.ts.map +1 -1
  404. package/dist/utils/smooth/SmoothContext.d.ts +71 -72
  405. package/dist/utils/smooth/SmoothContext.d.ts.map +1 -1
  406. package/dist/utils/smooth/useSmooth.d.ts +4 -1
  407. package/dist/utils/smooth/useSmooth.d.ts.map +1 -1
  408. package/dist/utils/smooth/useSmooth.js +7 -1
  409. package/dist/utils/smooth/useSmooth.js.map +1 -1
  410. package/dist/utils/useToolArgsFieldStatus.d.ts.map +1 -1
  411. package/package.json +19 -17
  412. package/src/index.ts +3 -0
  413. package/src/legacy-runtime/cloud/auiV0.ts +72 -3
  414. package/src/mcp-apps/McpAppRenderer.test.tsx +141 -0
  415. package/src/mcp-apps/McpAppRenderer.tsx +48 -10
  416. package/src/mcp-apps/McpAppsRemoteHost.test.ts +126 -0
  417. package/src/mcp-apps/McpAppsRemoteHost.ts +40 -1
  418. package/src/mcp-apps/app-frame.tsx +3 -1
  419. package/src/mcp-apps/bridge.ts +1 -1
  420. package/src/mcp-apps/types.ts +16 -8
  421. package/src/primitives/assistantModal/AssistantModalAnchor.tsx +6 -8
  422. package/src/primitives/assistantModal/AssistantModalContent.tsx +5 -5
  423. package/src/primitives/assistantModal/AssistantModalTrigger.test.tsx +80 -0
  424. package/src/primitives/assistantModal/AssistantModalTrigger.tsx +6 -8
  425. package/src/primitives/assistantModal/popoverRenderPrimitives.ts +6 -0
  426. package/src/primitives/composer/ComposerCompactContext.tsx +13 -0
  427. package/src/primitives/composer/ComposerInput.tsx +35 -0
  428. package/src/primitives/composer/ComposerRoot.test.tsx +161 -0
  429. package/src/primitives/composer/ComposerRoot.tsx +37 -7
  430. package/src/primitives/messagePart/MessagePartText.tsx +1 -0
  431. package/src/primitives/threadList/ThreadListRoot.tsx +8 -1
  432. package/src/primitives/threadListFocusGroup.ts +24 -0
  433. package/src/primitives/threadListItem/ThreadListItemRoot.tsx +53 -5
  434. package/src/primitives/threadListItem/ThreadListItemTrigger.tsx +45 -0
  435. package/src/primitives/threadListItem/ThreadListKeyboardNav.test.tsx +141 -0
  436. package/src/primitives/threadListItemMore/ThreadListItemMoreContent.tsx +22 -1
  437. package/src/primitives/threadListItemMore/ThreadListItemMoreRoot.tsx +64 -3
  438. package/src/primitives/threadListItemMore/ThreadListItemMoreTrigger.tsx +29 -2
  439. package/src/tests/LocalThreadRuntimeCore.test.ts +4 -1
  440. package/src/tests/auiV0Encode.test.ts +134 -1
  441. package/src/tests/generative-ui.test.tsx +21 -1
  442. package/src/utils/getSelectionMessageId.test.ts +175 -0
  443. package/src/utils/getSelectionMessageId.ts +57 -6
  444. package/src/utils/hooks/useMediaQuery.ts +3 -2
  445. package/src/utils/smooth/useSmooth.test.tsx +26 -0
  446. package/src/utils/smooth/useSmooth.ts +7 -1
  447. package/dist/utils/json/is-json-equal.d.ts +0 -5
  448. package/dist/utils/json/is-json-equal.d.ts.map +0 -1
  449. package/dist/utils/json/is-json-equal.js +0 -26
  450. package/dist/utils/json/is-json-equal.js.map +0 -1
  451. package/dist/utils/json/is-json.d.ts +0 -10
  452. package/dist/utils/json/is-json.d.ts.map +0 -1
  453. package/dist/utils/json/is-json.js +0 -22
  454. package/dist/utils/json/is-json.js.map +0 -1
  455. package/src/primitives/threadListItem/ThreadListItemTrigger.ts +0 -23
  456. package/src/utils/json/is-json-equal.ts +0 -48
  457. package/src/utils/json/is-json.ts +0 -58
@@ -1,5 +1,4 @@
1
1
  import { MessagePartState, ReasoningMessagePart, TextMessagePart } from "@assistant-ui/core";
2
-
3
2
  //#region src/utils/smooth/useSmooth.d.ts
4
3
  /**
5
4
  * Tuning options for the smooth text streaming animation.
@@ -39,6 +38,10 @@ type SmoothOptions = {
39
38
  * the reveal. Returns the part state with `text` replaced by the revealed
40
39
  * prefix and `status` reporting `running` until the reveal catches up.
41
40
  *
41
+ * The reveal auto-disables under `prefers-reduced-motion: reduce`,
42
+ * committing the full text immediately; this takes precedence over an
43
+ * explicit `smooth={true}`.
44
+ *
42
45
  * @example
43
46
  * ```tsx
44
47
  * const { text, status } = useSmooth(useMessagePartText(), {
@@ -1 +1 @@
1
- {"version":3,"file":"useSmooth.d.ts","names":[],"sources":["../../../src/utils/smooth/useSmooth.ts"],"mappings":";;;;;AAiBA;KAAY,aAAA;;;;;;EAMV,OAAA;EAmBW;AAAA;AAsGb;;;EAnHE,iBAAA;EAoH2B;;;;EA/G3B,gBAAA;EAiHuC;;;;;;;EAzGvC,WAAA;AAAA;;;;;AAyG2D;;;;;;;;;;;;cAHhD,SAAA,GACX,KAAA,EAAO,gBAAA,IAAoB,eAAA,GAAkB,oBAAA,GAC7C,MAAA,aAAkB,aAAA,KACjB,gBAAA,IAAoB,eAAA,GAAkB,oBAAA"}
1
+ {"version":3,"file":"useSmooth.d.ts","names":[],"sources":["../../../src/utils/smooth/useSmooth.ts"],"mappings":";;;;;KAkBY;;;;;;EAMV;;;;;;EAMA;;;;;EAKA;;;;;;;;EAQA;;;;;;;;;;;;;;;;;;;;;;cA0GW,YACX,OAAO,oBAAoB,kBAAkB,uBAC7C,mBAAkB,kBACjB,oBAAoB,kBAAkB"}
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { writableStore } from "../../context/ReadonlyStore.js";
3
+ import { useMediaQuery } from "../hooks/useMediaQuery.js";
3
4
  import { useSmoothStatusStore } from "./SmoothContext.js";
4
5
  import { useAui, useAuiState } from "@assistant-ui/store";
5
6
  import { useEffect, useMemo, useRef, useState } from "@assistant-ui/tap/react-shim";
@@ -66,6 +67,10 @@ const positiveOr = (value, fallback) => value !== void 0 && value > 0 ? value :
66
67
  * the reveal. Returns the part state with `text` replaced by the revealed
67
68
  * prefix and `status` reporting `running` until the reveal catches up.
68
69
  *
70
+ * The reveal auto-disables under `prefers-reduced-motion: reduce`,
71
+ * committing the full text immediately; this takes precedence over an
72
+ * explicit `smooth={true}`.
73
+ *
69
74
  * @example
70
75
  * ```tsx
71
76
  * const { text, status } = useSmooth(useMessagePartText(), {
@@ -76,8 +81,9 @@ const positiveOr = (value, fallback) => value !== void 0 && value > 0 ? value :
76
81
  */
77
82
  const useSmooth = (state, smooth = false) => {
78
83
  const { text } = state;
84
+ const reduceMotion = useMediaQuery("(prefers-reduced-motion: reduce)");
79
85
  const options = typeof smooth === "object" && smooth !== null ? smooth : void 0;
80
- const enabled = smooth !== false && smooth !== null;
86
+ const enabled = smooth !== false && smooth !== null && !reduceMotion;
81
87
  const drainMs = positiveOr(options?.drainMs, DEFAULT_DRAIN_MS);
82
88
  const maxCharIntervalMs = positiveOr(options?.maxCharIntervalMs, DEFAULT_MAX_CHAR_INTERVAL_MS);
83
89
  const maxCharsPerFrame = positiveOr(options?.maxCharsPerFrame, Infinity);
@@ -1 +1 @@
1
- {"version":3,"file":"useSmooth.js","names":["useEffect","useMemo","useRef","useState","useAui","useAuiState","MessagePartStatus","ReasoningMessagePart","TextMessagePart","MessagePartState","useCallbackRef","useSmoothStatusStore","writableStore","SmoothOptions","drainMs","maxCharIntervalMs","maxCharsPerFrame","minCommitMs","DEFAULT_DRAIN_MS","DEFAULT_MAX_CHAR_INTERVAL_MS","TextStreamAnimator","animationFrameId","lastUpdateTime","Date","now","lastCommitTime","targetText","Infinity","constructor","currentText","setText","newText","start","animate","stop","cancelAnimationFrame","currentTime","deltaTime","timeToConsume","remainingChars","length","baseTimePerChar","Math","min","frameLimit","charsToAdd","requestAnimationFrame","slice","isComplete","SMOOTH_STATUS","Object","freeze","type","positiveOr","value","fallback","undefined","useSmooth","state","smooth","text","options","enabled","displayedText","setDisplayedText","status","aui","part","prevPart","setPrevPart","startsWith","smoothStatusStore","optional","target","setState","animatorRef","animatorPartRef","partChanged","current"],"sources":["../../../src/utils/smooth/useSmooth.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\nimport type {\n MessagePartStatus,\n ReasoningMessagePart,\n TextMessagePart,\n MessagePartState,\n} from \"@assistant-ui/core\";\nimport { useCallbackRef } from \"@radix-ui/react-use-callback-ref\";\nimport { useSmoothStatusStore } from \"./SmoothContext\";\nimport { writableStore } from \"../../context/ReadonlyStore\";\n\n/**\n * Tuning options for the smooth text streaming animation.\n */\nexport type SmoothOptions = {\n /**\n * Target time in milliseconds to drain the backlog of unrevealed\n * characters. Larger values reveal long backlogs more gradually.\n * @default 250\n */\n drainMs?: number | undefined;\n /**\n * Maximum time in milliseconds between revealed characters, i.e. the\n * slowest reveal rate when the backlog is short.\n * @default 5\n */\n maxCharIntervalMs?: number | undefined;\n /**\n * Maximum number of characters revealed per animation frame.\n * @default Infinity\n */\n maxCharsPerFrame?: number | undefined;\n /**\n * Minimum time in milliseconds between committed updates. The reveal keeps\n * advancing every frame, but the visible text (and the downstream re-render\n * and markdown re-parse it triggers) is committed at most once per interval.\n * The final frame always commits. `0` commits every frame.\n * @default 0\n */\n minCommitMs?: number | undefined;\n};\n\nconst DEFAULT_DRAIN_MS = 250;\nconst DEFAULT_MAX_CHAR_INTERVAL_MS = 5;\n\nclass TextStreamAnimator {\n private animationFrameId: number | null = null;\n private lastUpdateTime: number = Date.now();\n public lastCommitTime: number = 0;\n\n public targetText: string = \"\";\n public drainMs: number = DEFAULT_DRAIN_MS;\n public maxCharIntervalMs: number = DEFAULT_MAX_CHAR_INTERVAL_MS;\n public maxCharsPerFrame: number = Infinity;\n public minCommitMs: number = 0;\n\n constructor(\n public currentText: string,\n private setText: (newText: string) => void,\n ) {}\n\n start() {\n if (this.animationFrameId !== null) return;\n this.lastUpdateTime = Date.now();\n this.animate();\n }\n\n stop() {\n if (this.animationFrameId !== null) {\n cancelAnimationFrame(this.animationFrameId);\n this.animationFrameId = null;\n }\n }\n\n private animate = () => {\n const currentTime = Date.now();\n const deltaTime = currentTime - this.lastUpdateTime;\n let timeToConsume = deltaTime;\n\n const remainingChars = this.targetText.length - this.currentText.length;\n const baseTimePerChar = Math.min(\n this.maxCharIntervalMs,\n this.drainMs / remainingChars,\n );\n\n const frameLimit = Math.min(remainingChars, this.maxCharsPerFrame);\n let charsToAdd = 0;\n while (timeToConsume >= baseTimePerChar && charsToAdd < frameLimit) {\n charsToAdd++;\n timeToConsume -= baseTimePerChar;\n }\n // A cap-limited frame must not bank its surplus time, or the next\n // frame would burst past the cap.\n if (charsToAdd === frameLimit && frameLimit === this.maxCharsPerFrame) {\n timeToConsume = 0;\n }\n\n if (charsToAdd !== remainingChars) {\n this.animationFrameId = requestAnimationFrame(this.animate);\n } else {\n this.animationFrameId = null;\n }\n if (charsToAdd === 0) return;\n\n this.currentText = this.targetText.slice(\n 0,\n this.currentText.length + charsToAdd,\n );\n this.lastUpdateTime = currentTime - timeToConsume;\n\n const isComplete = charsToAdd === remainingChars;\n if (isComplete || currentTime - this.lastCommitTime >= this.minCommitMs) {\n this.lastCommitTime = currentTime;\n this.setText(this.currentText);\n }\n };\n}\n\nconst SMOOTH_STATUS: MessagePartStatus = Object.freeze({\n type: \"running\",\n});\n\nconst positiveOr = (value: number | undefined, fallback: number): number =>\n value !== undefined && value > 0 ? value : fallback;\n\n/**\n * Animates streamed message part text with a typewriter-style reveal.\n *\n * Takes the current part state and a `smooth` argument: `false` disables,\n * `true` uses the default rate, and a {@link SmoothOptions} object tunes\n * the reveal. Returns the part state with `text` replaced by the revealed\n * prefix and `status` reporting `running` until the reveal catches up.\n *\n * @example\n * ```tsx\n * const { text, status } = useSmooth(useMessagePartText(), {\n * drainMs: 500,\n * maxCharsPerFrame: 30,\n * });\n * ```\n */\nexport const useSmooth = (\n state: MessagePartState & (TextMessagePart | ReasoningMessagePart),\n smooth: boolean | SmoothOptions = false,\n): MessagePartState & (TextMessagePart | ReasoningMessagePart) => {\n const { text } = state;\n const options =\n typeof smooth === \"object\" && smooth !== null ? smooth : undefined;\n const enabled = smooth !== false && smooth !== null;\n const drainMs = positiveOr(options?.drainMs, DEFAULT_DRAIN_MS);\n const maxCharIntervalMs = positiveOr(\n options?.maxCharIntervalMs,\n DEFAULT_MAX_CHAR_INTERVAL_MS,\n );\n const maxCharsPerFrame = positiveOr(options?.maxCharsPerFrame, Infinity);\n const minCommitMs = positiveOr(options?.minCommitMs, 0);\n\n const [displayedText, setDisplayedText] = useState(\n state.status.type === \"running\" ? \"\" : text,\n );\n\n // Render-phase resync on part flip or text discontinuity, so the\n // first paint after a thread switch never shows the previous\n // part's text (#4051). `displayedText` is already a prefix of\n // `text` during normal streaming, so use it as the previous-text\n // reference instead of carrying separate state — avoids the\n // double render per streaming token. Read part identity through\n // `useAuiState` so we actually subscribe to its changes instead\n // of relying on a render-time proxy reference that may be stable\n // across thread swaps.\n const aui = useAui();\n const part = useAuiState(() => aui.part());\n const [prevPart, setPrevPart] = useState(part);\n if (part !== prevPart || !text.startsWith(displayedText)) {\n setPrevPart(part);\n setDisplayedText(state.status.type === \"running\" ? \"\" : text);\n }\n\n const smoothStatusStore = useSmoothStatusStore({ optional: true });\n const setText = useCallbackRef((text: string) => {\n setDisplayedText(text);\n if (smoothStatusStore) {\n const target =\n displayedText !== text || state.status.type === \"running\"\n ? SMOOTH_STATUS\n : state.status;\n writableStore(smoothStatusStore).setState(target, true);\n }\n });\n\n // TODO this is hacky\n useEffect(() => {\n if (smoothStatusStore) {\n const target =\n enabled && (displayedText !== text || state.status.type === \"running\")\n ? SMOOTH_STATUS\n : state.status;\n writableStore(smoothStatusStore).setState(target, true);\n }\n }, [smoothStatusStore, enabled, text, displayedText, state.status]);\n\n const [animatorRef] = useState<TextStreamAnimator>(\n new TextStreamAnimator(displayedText, setText),\n );\n\n useEffect(() => {\n animatorRef.drainMs = drainMs;\n animatorRef.maxCharIntervalMs = maxCharIntervalMs;\n animatorRef.maxCharsPerFrame = maxCharsPerFrame;\n animatorRef.minCommitMs = minCommitMs;\n }, [animatorRef, drainMs, maxCharIntervalMs, maxCharsPerFrame, minCommitMs]);\n\n const animatorPartRef = useRef(part);\n useEffect(() => {\n if (!enabled) {\n animatorRef.stop();\n return;\n }\n\n // Discontinuity: part flipped, or new text breaks continuation\n // of the animator's current target. Either case requires\n // resetting the cursor — without the part check, a new part\n // whose text happens to share a prefix with the previous target\n // would keep the stale cursor and flicker.\n const partChanged = animatorPartRef.current !== part;\n animatorPartRef.current = part;\n if (partChanged || !text.startsWith(animatorRef.targetText)) {\n if (state.status.type === \"running\") {\n animatorRef.currentText = \"\";\n animatorRef.targetText = text;\n animatorRef.lastCommitTime = 0;\n animatorRef.start();\n } else {\n animatorRef.currentText = text;\n animatorRef.targetText = text;\n animatorRef.stop();\n }\n return;\n }\n\n animatorRef.targetText = text;\n animatorRef.start();\n }, [animatorRef, enabled, text, state.status.type, part]);\n\n useEffect(() => {\n return () => {\n animatorRef.stop();\n };\n }, [animatorRef]);\n\n return useMemo(\n () =>\n enabled\n ? {\n ...state,\n text: displayedText,\n status: text === displayedText ? state.status : SMOOTH_STATUS,\n }\n : state,\n [enabled, displayedText, state, text],\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"useSmooth.js","names":["useEffect","useMemo","useRef","useState","useAui","useAuiState","MessagePartStatus","ReasoningMessagePart","TextMessagePart","MessagePartState","useCallbackRef","useMediaQuery","useSmoothStatusStore","writableStore","SmoothOptions","drainMs","maxCharIntervalMs","maxCharsPerFrame","minCommitMs","DEFAULT_DRAIN_MS","DEFAULT_MAX_CHAR_INTERVAL_MS","TextStreamAnimator","animationFrameId","lastUpdateTime","Date","now","lastCommitTime","targetText","Infinity","constructor","currentText","setText","newText","start","animate","stop","cancelAnimationFrame","currentTime","deltaTime","timeToConsume","remainingChars","length","baseTimePerChar","Math","min","frameLimit","charsToAdd","requestAnimationFrame","slice","isComplete","SMOOTH_STATUS","Object","freeze","type","positiveOr","value","fallback","undefined","useSmooth","state","smooth","text","reduceMotion","options","enabled","displayedText","setDisplayedText","status","aui","part","prevPart","setPrevPart","startsWith","smoothStatusStore","optional","target","setState","animatorRef","animatorPartRef","partChanged","current"],"sources":["../../../src/utils/smooth/useSmooth.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\nimport type {\n MessagePartStatus,\n ReasoningMessagePart,\n TextMessagePart,\n MessagePartState,\n} from \"@assistant-ui/core\";\nimport { useCallbackRef } from \"@radix-ui/react-use-callback-ref\";\nimport { useMediaQuery } from \"../hooks/useMediaQuery\";\nimport { useSmoothStatusStore } from \"./SmoothContext\";\nimport { writableStore } from \"../../context/ReadonlyStore\";\n\n/**\n * Tuning options for the smooth text streaming animation.\n */\nexport type SmoothOptions = {\n /**\n * Target time in milliseconds to drain the backlog of unrevealed\n * characters. Larger values reveal long backlogs more gradually.\n * @default 250\n */\n drainMs?: number | undefined;\n /**\n * Maximum time in milliseconds between revealed characters, i.e. the\n * slowest reveal rate when the backlog is short.\n * @default 5\n */\n maxCharIntervalMs?: number | undefined;\n /**\n * Maximum number of characters revealed per animation frame.\n * @default Infinity\n */\n maxCharsPerFrame?: number | undefined;\n /**\n * Minimum time in milliseconds between committed updates. The reveal keeps\n * advancing every frame, but the visible text (and the downstream re-render\n * and markdown re-parse it triggers) is committed at most once per interval.\n * The final frame always commits. `0` commits every frame.\n * @default 0\n */\n minCommitMs?: number | undefined;\n};\n\nconst DEFAULT_DRAIN_MS = 250;\nconst DEFAULT_MAX_CHAR_INTERVAL_MS = 5;\n\nclass TextStreamAnimator {\n private animationFrameId: number | null = null;\n private lastUpdateTime: number = Date.now();\n public lastCommitTime: number = 0;\n\n public targetText: string = \"\";\n public drainMs: number = DEFAULT_DRAIN_MS;\n public maxCharIntervalMs: number = DEFAULT_MAX_CHAR_INTERVAL_MS;\n public maxCharsPerFrame: number = Infinity;\n public minCommitMs: number = 0;\n\n constructor(\n public currentText: string,\n private setText: (newText: string) => void,\n ) {}\n\n start() {\n if (this.animationFrameId !== null) return;\n this.lastUpdateTime = Date.now();\n this.animate();\n }\n\n stop() {\n if (this.animationFrameId !== null) {\n cancelAnimationFrame(this.animationFrameId);\n this.animationFrameId = null;\n }\n }\n\n private animate = () => {\n const currentTime = Date.now();\n const deltaTime = currentTime - this.lastUpdateTime;\n let timeToConsume = deltaTime;\n\n const remainingChars = this.targetText.length - this.currentText.length;\n const baseTimePerChar = Math.min(\n this.maxCharIntervalMs,\n this.drainMs / remainingChars,\n );\n\n const frameLimit = Math.min(remainingChars, this.maxCharsPerFrame);\n let charsToAdd = 0;\n while (timeToConsume >= baseTimePerChar && charsToAdd < frameLimit) {\n charsToAdd++;\n timeToConsume -= baseTimePerChar;\n }\n // A cap-limited frame must not bank its surplus time, or the next\n // frame would burst past the cap.\n if (charsToAdd === frameLimit && frameLimit === this.maxCharsPerFrame) {\n timeToConsume = 0;\n }\n\n if (charsToAdd !== remainingChars) {\n this.animationFrameId = requestAnimationFrame(this.animate);\n } else {\n this.animationFrameId = null;\n }\n if (charsToAdd === 0) return;\n\n this.currentText = this.targetText.slice(\n 0,\n this.currentText.length + charsToAdd,\n );\n this.lastUpdateTime = currentTime - timeToConsume;\n\n const isComplete = charsToAdd === remainingChars;\n if (isComplete || currentTime - this.lastCommitTime >= this.minCommitMs) {\n this.lastCommitTime = currentTime;\n this.setText(this.currentText);\n }\n };\n}\n\nconst SMOOTH_STATUS: MessagePartStatus = Object.freeze({\n type: \"running\",\n});\n\nconst positiveOr = (value: number | undefined, fallback: number): number =>\n value !== undefined && value > 0 ? value : fallback;\n\n/**\n * Animates streamed message part text with a typewriter-style reveal.\n *\n * Takes the current part state and a `smooth` argument: `false` disables,\n * `true` uses the default rate, and a {@link SmoothOptions} object tunes\n * the reveal. Returns the part state with `text` replaced by the revealed\n * prefix and `status` reporting `running` until the reveal catches up.\n *\n * The reveal auto-disables under `prefers-reduced-motion: reduce`,\n * committing the full text immediately; this takes precedence over an\n * explicit `smooth={true}`.\n *\n * @example\n * ```tsx\n * const { text, status } = useSmooth(useMessagePartText(), {\n * drainMs: 500,\n * maxCharsPerFrame: 30,\n * });\n * ```\n */\nexport const useSmooth = (\n state: MessagePartState & (TextMessagePart | ReasoningMessagePart),\n smooth: boolean | SmoothOptions = false,\n): MessagePartState & (TextMessagePart | ReasoningMessagePart) => {\n const { text } = state;\n const reduceMotion = useMediaQuery(\"(prefers-reduced-motion: reduce)\");\n const options =\n typeof smooth === \"object\" && smooth !== null ? smooth : undefined;\n const enabled = smooth !== false && smooth !== null && !reduceMotion;\n const drainMs = positiveOr(options?.drainMs, DEFAULT_DRAIN_MS);\n const maxCharIntervalMs = positiveOr(\n options?.maxCharIntervalMs,\n DEFAULT_MAX_CHAR_INTERVAL_MS,\n );\n const maxCharsPerFrame = positiveOr(options?.maxCharsPerFrame, Infinity);\n const minCommitMs = positiveOr(options?.minCommitMs, 0);\n\n const [displayedText, setDisplayedText] = useState(\n state.status.type === \"running\" ? \"\" : text,\n );\n\n // Render-phase resync on part flip or text discontinuity, so the\n // first paint after a thread switch never shows the previous\n // part's text (#4051). `displayedText` is already a prefix of\n // `text` during normal streaming, so use it as the previous-text\n // reference instead of carrying separate state — avoids the\n // double render per streaming token. Read part identity through\n // `useAuiState` so we actually subscribe to its changes instead\n // of relying on a render-time proxy reference that may be stable\n // across thread swaps.\n const aui = useAui();\n const part = useAuiState(() => aui.part());\n const [prevPart, setPrevPart] = useState(part);\n if (part !== prevPart || !text.startsWith(displayedText)) {\n setPrevPart(part);\n setDisplayedText(state.status.type === \"running\" ? \"\" : text);\n }\n\n const smoothStatusStore = useSmoothStatusStore({ optional: true });\n const setText = useCallbackRef((text: string) => {\n setDisplayedText(text);\n if (smoothStatusStore) {\n const target =\n displayedText !== text || state.status.type === \"running\"\n ? SMOOTH_STATUS\n : state.status;\n writableStore(smoothStatusStore).setState(target, true);\n }\n });\n\n // TODO this is hacky\n useEffect(() => {\n if (smoothStatusStore) {\n const target =\n enabled && (displayedText !== text || state.status.type === \"running\")\n ? SMOOTH_STATUS\n : state.status;\n writableStore(smoothStatusStore).setState(target, true);\n }\n }, [smoothStatusStore, enabled, text, displayedText, state.status]);\n\n const [animatorRef] = useState<TextStreamAnimator>(\n new TextStreamAnimator(displayedText, setText),\n );\n\n useEffect(() => {\n animatorRef.drainMs = drainMs;\n animatorRef.maxCharIntervalMs = maxCharIntervalMs;\n animatorRef.maxCharsPerFrame = maxCharsPerFrame;\n animatorRef.minCommitMs = minCommitMs;\n }, [animatorRef, drainMs, maxCharIntervalMs, maxCharsPerFrame, minCommitMs]);\n\n const animatorPartRef = useRef(part);\n useEffect(() => {\n if (!enabled) {\n animatorRef.stop();\n return;\n }\n\n // Discontinuity: part flipped, or new text breaks continuation\n // of the animator's current target. Either case requires\n // resetting the cursor — without the part check, a new part\n // whose text happens to share a prefix with the previous target\n // would keep the stale cursor and flicker.\n const partChanged = animatorPartRef.current !== part;\n animatorPartRef.current = part;\n if (partChanged || !text.startsWith(animatorRef.targetText)) {\n if (state.status.type === \"running\") {\n animatorRef.currentText = \"\";\n animatorRef.targetText = text;\n animatorRef.lastCommitTime = 0;\n animatorRef.start();\n } else {\n animatorRef.currentText = text;\n animatorRef.targetText = text;\n animatorRef.stop();\n }\n return;\n }\n\n animatorRef.targetText = text;\n animatorRef.start();\n }, [animatorRef, enabled, text, state.status.type, part]);\n\n useEffect(() => {\n return () => {\n animatorRef.stop();\n };\n }, [animatorRef]);\n\n return useMemo(\n () =>\n enabled\n ? {\n ...state,\n text: displayedText,\n status: text === displayedText ? state.status : SMOOTH_STATUS,\n }\n : state,\n [enabled, displayedText, state, text],\n );\n};\n"],"mappings":";;;;;;;;AA8CA,MAAMmB,mBAAmB;AACzB,MAAMC,+BAA+B;AAErC,IAAMC,qBAAN,MAAyB;CAYdS;CACCC;CAZV,mBAA0C;CAC1C,iBAAiCP,KAAKC,IAAI;CAC1C,iBAAgC;CAEhC,aAA4B;CAC5B,UAAyBN;CACzB,oBAAmCC;CACnC,mBAAkCQ;CAClC,cAA6B;CAE7BC,YACE,aACA,SACA;EAFOC,KAAAA,cAAAA;EACCC,KAAAA,UAAAA;CACP;CAEHE,QAAQ;EACN,IAAI,KAAKX,qBAAqB,MAAM;EACpC,KAAKC,iBAAiBC,KAAKC,IAAI;EAC/B,KAAKS,QAAQ;CACf;CAEAC,OAAO;EACL,IAAI,KAAKb,qBAAqB,MAAM;GAClCc,qBAAqB,KAAKd,gBAAgB;GAC1C,KAAKA,mBAAmB;EAC1B;CACF;CAEA,gBAAwB;EACtB,MAAMe,cAAcb,KAAKC,IAAI;EAE7B,IAAIc,gBADcF,cAAc,KAAKd;EAGrC,MAAMiB,iBAAiB,KAAKb,WAAWc,SAAS,KAAKX,YAAYW;EACjE,MAAMC,kBAAkBC,KAAKC,IAC3B,KAAK5B,mBACL,KAAKD,UAAUyB,cACjB;EAEA,MAAMK,aAAaF,KAAKC,IAAIJ,gBAAgB,KAAKvB,gBAAgB;EACjE,IAAI6B,aAAa;EACjB,OAAOP,iBAAiBG,mBAAmBI,aAAaD,YAAY;GAClEC;GACAP,iBAAiBG;EACnB;EAGA,IAAII,eAAeD,cAAcA,eAAe,KAAK5B,kBACnDsB,gBAAgB;EAGlB,IAAIO,eAAeN,gBACjB,KAAKlB,mBAAmByB,sBAAsB,KAAKb,OAAO;OAE1D,KAAKZ,mBAAmB;EAE1B,IAAIwB,eAAe,GAAG;EAEtB,KAAKhB,cAAc,KAAKH,WAAWqB,MACjC,GACA,KAAKlB,YAAYW,SAASK,UAC5B;EACA,KAAKvB,iBAAiBc,cAAcE;EAGpC,IADmBO,eAAeN,kBAChBH,cAAc,KAAKX,kBAAkB,KAAKR,aAAa;GACvE,KAAKQ,iBAAiBW;GACtB,KAAKN,QAAQ,KAAKD,WAAW;EAC/B;CACF;AACF;AAEA,MAAMoB,gBAAmCC,OAAOC,OAAO,EACrDC,MAAM,UACR,CAAC;AAED,MAAMC,cAAcC,OAA2BC,aAC7CD,UAAUE,KAAAA,KAAaF,QAAQ,IAAIA,QAAQC;;;;;;;;;;;;;;;;;;;;;AAsB7C,MAAaE,aACXC,OACAC,SAAkC,UAC8B;CAChE,MAAM,EAAEC,SAASF;CACjB,MAAMG,eAAenD,cAAc,kCAAkC;CACrE,MAAMoD,UACJ,OAAOH,WAAW,YAAYA,WAAW,OAAOA,SAASH,KAAAA;CAC3D,MAAMO,UAAUJ,WAAW,SAASA,WAAW,QAAQ,CAACE;CACxD,MAAM/C,UAAUuC,WAAWS,SAAShD,SAASI,gBAAgB;CAC7D,MAAMH,oBAAoBsC,WACxBS,SAAS/C,mBACTI,4BACF;CACA,MAAMH,mBAAmBqC,WAAWS,SAAS9C,kBAAkBW,QAAQ;CACvE,MAAMV,cAAcoC,WAAWS,SAAS7C,aAAa,CAAC;CAEtD,MAAM,CAAC+C,eAAeC,oBAAoB/D,SACxCwD,MAAMQ,OAAOd,SAAS,YAAY,KAAKQ,IACzC;CAWA,MAAMO,MAAMhE,OAAO;CACnB,MAAMiE,OAAOhE,kBAAkB+D,IAAIC,KAAK,CAAC;CACzC,MAAM,CAACC,UAAUC,eAAepE,SAASkE,IAAI;CAC7C,IAAIA,SAASC,YAAY,CAACT,KAAKW,WAAWP,aAAa,GAAG;EACxDM,YAAYF,IAAI;EAChBH,iBAAiBP,MAAMQ,OAAOd,SAAS,YAAY,KAAKQ,IAAI;CAC9D;CAEA,MAAMY,oBAAoB7D,qBAAqB,EAAE8D,UAAU,KAAK,CAAC;CACjE,MAAM3C,UAAUrB,gBAAgBmD,WAAiB;EAC/CK,iBAAiBL,MAAI;EACrB,IAAIY,mBAAmB;GACrB,MAAME,SACJV,kBAAkBJ,UAAQF,MAAMQ,OAAOd,SAAS,YAC5CH,gBACAS,MAAMQ;GACZtD,cAAc4D,iBAAiB,CAAC,CAACG,SAASD,QAAQ,IAAI;EACxD;CACF,CAAC;CAGD3E,gBAAgB;EACd,IAAIyE,mBAAmB;GACrB,MAAME,WACJX,YAAYC,kBAAkBJ,QAAQF,MAAMQ,OAAOd,SAAS,aACxDH,gBACAS,MAAMQ;GACZtD,cAAc4D,iBAAiB,CAAC,CAACG,SAASD,UAAQ,IAAI;EACxD;CACF,GAAG;EAACF;EAAmBT;EAASH;EAAMI;EAAeN,MAAMQ;CAAM,CAAC;CAElE,MAAM,CAACU,eAAe1E,SACpB,IAAIkB,mBAAmB4C,eAAelC,OAAO,CAC/C;CAEA/B,gBAAgB;EACd6E,YAAY9D,UAAUA;EACtB8D,YAAY7D,oBAAoBA;EAChC6D,YAAY5D,mBAAmBA;EAC/B4D,YAAY3D,cAAcA;CAC5B,GAAG;EAAC2D;EAAa9D;EAASC;EAAmBC;EAAkBC;CAAW,CAAC;CAE3E,MAAM4D,kBAAkB5E,OAAOmE,IAAI;CACnCrE,gBAAgB;EACd,IAAI,CAACgE,SAAS;GACZa,YAAY1C,KAAK;GACjB;EACF;EAOA,MAAM4C,cAAcD,gBAAgBE,YAAYX;EAChDS,gBAAgBE,UAAUX;EAC1B,IAAIU,eAAe,CAAClB,KAAKW,WAAWK,YAAYlD,UAAU,GAAG;GAC3D,IAAIgC,MAAMQ,OAAOd,SAAS,WAAW;IACnCwB,YAAY/C,cAAc;IAC1B+C,YAAYlD,aAAakC;IACzBgB,YAAYnD,iBAAiB;IAC7BmD,YAAY5C,MAAM;GACpB,OAAO;IACL4C,YAAY/C,cAAc+B;IAC1BgB,YAAYlD,aAAakC;IACzBgB,YAAY1C,KAAK;GACnB;GACA;EACF;EAEA0C,YAAYlD,aAAakC;EACzBgB,YAAY5C,MAAM;CACpB,GAAG;EAAC4C;EAAab;EAASH;EAAMF,MAAMQ,OAAOd;EAAMgB;CAAI,CAAC;CAExDrE,gBAAgB;EACd,aAAa;GACX6E,YAAY1C,KAAK;EACnB;CACF,GAAG,CAAC0C,WAAW,CAAC;CAEhB,OAAO5E,cAEH+D,UACI;EACE,GAAGL;EACHE,MAAMI;EACNE,QAAQN,SAASI,gBAAgBN,MAAMQ,SAASjB;CAClD,IACAS,OACN;EAACK;EAASC;EAAeN;EAAOE;CAAI,CACtC;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"useToolArgsFieldStatus.d.ts","names":[],"sources":["../../src/utils/useToolArgsFieldStatus.ts"],"mappings":";cAKa,sBAAA,GAA0B,SAAA;EAAA"}
1
+ {"version":3,"file":"useToolArgsFieldStatus.d.ts","names":[],"sources":["../../src/utils/useToolArgsFieldStatus.ts"],"mappings":";cAKa,yBAA0B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/react",
3
- "version": "0.14.24",
3
+ "version": "0.14.27",
4
4
  "description": "Open-source TypeScript/React library for building production-grade AI chat experiences",
5
5
  "keywords": [
6
6
  "ai",
@@ -55,21 +55,23 @@
55
55
  ],
56
56
  "sideEffects": false,
57
57
  "dependencies": {
58
- "@assistant-ui/core": "^0.2.19",
59
- "@assistant-ui/store": "^0.2.19",
60
- "@assistant-ui/tap": "^0.9.3",
61
- "@radix-ui/primitive": "^1.1.4",
58
+ "@assistant-ui/core": "^0.2.21",
59
+ "@assistant-ui/store": "^0.2.20",
60
+ "@assistant-ui/tap": "^0.9.4",
61
+ "@radix-ui/primitive": "^1.1.5",
62
+ "@radix-ui/react-collection": "^1.1.12",
62
63
  "@radix-ui/react-compose-refs": "^1.1.3",
63
- "@radix-ui/react-context": "^1.1.4",
64
- "@radix-ui/react-primitive": "^2.1.6",
64
+ "@radix-ui/react-context": "^1.2.0",
65
+ "@radix-ui/react-primitive": "^2.1.7",
65
66
  "@radix-ui/react-use-callback-ref": "^1.1.2",
66
- "@radix-ui/react-use-escape-keydown": "^1.1.2",
67
- "assistant-cloud": "^0.1.34",
68
- "assistant-stream": "^0.3.24",
69
- "nanoid": "^5.1.15",
70
- "radix-ui": "^1.6.0",
67
+ "@radix-ui/react-use-controllable-state": "^1.2.3",
68
+ "@radix-ui/react-use-escape-keydown": "^1.1.3",
69
+ "assistant-cloud": "^0.1.35",
70
+ "assistant-stream": "^0.3.26",
71
+ "nanoid": "^6.0.0",
72
+ "radix-ui": "^1.6.2",
71
73
  "react-textarea-autosize": "^8.5.9",
72
- "safe-content-frame": "^0.0.21",
74
+ "safe-content-frame": "^0.0.23",
73
75
  "zod": "^4.4.3",
74
76
  "zustand": "^5.0.14"
75
77
  },
@@ -90,15 +92,15 @@
90
92
  "devDependencies": {
91
93
  "@testing-library/react": "^16.3.2",
92
94
  "@types/json-schema": "^7.0.15",
93
- "@types/node": "^26.0.0",
95
+ "@types/node": "^26.1.1",
94
96
  "@types/react": "^19.2.17",
95
97
  "@types/react-dom": "^19.2.3",
96
98
  "jsdom": "^29.1.1",
97
99
  "react": "^19.2.7",
98
100
  "react-dom": "^19.2.7",
99
- "vitest": "^4.1.9",
100
- "@assistant-ui/vite": "0.0.6",
101
- "@assistant-ui/x-buildutils": "0.0.16"
101
+ "vitest": "^4.1.10",
102
+ "@assistant-ui/vite": "0.0.9",
103
+ "@assistant-ui/x-buildutils": "0.0.18"
102
104
  },
103
105
  "publishConfig": {
104
106
  "access": "public",
package/src/index.ts CHANGED
@@ -209,7 +209,9 @@ export {
209
209
  providerTool,
210
210
  type ProviderToolConfig,
211
211
  defineMcpToolkit,
212
+ type McpToolkitEntry,
212
213
  type McpToolkitDefinition,
214
+ type McpToolkitToolConfig,
213
215
  Tools,
214
216
  DataRenderers,
215
217
  Interactables,
@@ -337,6 +339,7 @@ export type {
337
339
  AppendMessage,
338
340
  TextMessagePart,
339
341
  ReasoningMessagePart,
342
+ PartProviderMetadata,
340
343
  SourceProviderMetadata,
341
344
  SourceMessagePart,
342
345
  ImageMessagePart,
@@ -1,11 +1,17 @@
1
1
  import type {
2
+ CompleteAttachment,
3
+ DataMessagePart,
4
+ FileMessagePart,
5
+ ImageMessagePart,
2
6
  MessageStatus,
3
7
  SourceProviderMetadata,
4
8
  ThreadMessage,
9
+ TextMessagePart,
10
+ Unstable_AudioMessagePart,
5
11
  } from "@assistant-ui/core";
6
12
  import { fromThreadMessageLike } from "../runtime-cores/external-store/ThreadMessageLike";
7
13
  import type { CloudMessage } from "assistant-cloud";
8
- import { isJSONValue } from "../../utils/json/is-json";
14
+ import { isJSONValue } from "@assistant-ui/core/internal";
9
15
  import type {
10
16
  ReadonlyJSONObject,
11
17
  ReadonlyJSONValue,
@@ -65,10 +71,27 @@ type AuiV0MessagePart =
65
71
  readonly filename?: string;
66
72
  };
67
73
 
74
+ type AuiV0AttachmentPart =
75
+ | TextMessagePart
76
+ | ImageMessagePart
77
+ | FileMessagePart
78
+ | Unstable_AudioMessagePart
79
+ | DataMessagePart<ReadonlyJSONValue>;
80
+
81
+ type AuiV0Attachment = {
82
+ readonly id: string;
83
+ readonly type: CompleteAttachment["type"];
84
+ readonly name: string;
85
+ readonly contentType?: string;
86
+ readonly status: CompleteAttachment["status"];
87
+ readonly content: readonly AuiV0AttachmentPart[];
88
+ };
89
+
68
90
  type AuiV0Message = {
69
91
  readonly role: "assistant" | "user" | "system";
70
92
  readonly status?: MessageStatus;
71
93
  readonly content: readonly AuiV0MessagePart[];
94
+ readonly attachments?: readonly AuiV0Attachment[];
72
95
  readonly metadata: {
73
96
  readonly unstable_state?: ReadonlyJSONValue;
74
97
  readonly unstable_annotations: readonly ReadonlyJSONValue[];
@@ -83,14 +106,59 @@ type AuiV0Message = {
83
106
  };
84
107
  };
85
108
 
109
+ const encodeAttachmentPart = (
110
+ part: CompleteAttachment["content"][number],
111
+ ): AuiV0AttachmentPart => {
112
+ const type = part.type;
113
+ switch (type) {
114
+ case "text":
115
+ case "image":
116
+ case "file":
117
+ case "audio":
118
+ return part;
119
+
120
+ case "data": {
121
+ if (!isJSONValue(part.data)) {
122
+ console.warn(`attachment data is not JSON! ${JSON.stringify(part)}`);
123
+ }
124
+ return { ...part, data: part.data as ReadonlyJSONValue };
125
+ }
126
+
127
+ default: {
128
+ const unhandledType: never = type;
129
+ throw new Error(
130
+ `Attachment part type not supported by aui/v0: ${unhandledType}`,
131
+ );
132
+ }
133
+ }
134
+ };
135
+
136
+ const encodeAttachments = (
137
+ message: ThreadMessage,
138
+ ): readonly AuiV0Attachment[] | undefined => {
139
+ if (message.role !== "user" || message.attachments.length === 0) {
140
+ return undefined;
141
+ }
142
+
143
+ return message.attachments.map(
144
+ ({ id, type, name, contentType, status, content }) => ({
145
+ id,
146
+ type,
147
+ name,
148
+ status,
149
+ ...(contentType != null ? { contentType } : undefined),
150
+ content: content.map(encodeAttachmentPart),
151
+ }),
152
+ );
153
+ };
154
+
86
155
  export function auiV0Encode(message: ThreadMessage): AuiV0Message {
87
- // TODO attachments are currently intentionally ignored
88
156
  // info: ID and createdAt are ignored (we use the server value instead)
89
-
90
157
  const status: MessageStatus | undefined =
91
158
  message.status?.type === "running"
92
159
  ? { type: "incomplete", reason: "cancelled" }
93
160
  : message.status;
161
+ const attachments = encodeAttachments(message);
94
162
 
95
163
  return {
96
164
  role: message.role,
@@ -172,6 +240,7 @@ export function auiV0Encode(message: ThreadMessage): AuiV0Message {
172
240
  }),
173
241
  metadata: message.metadata as AuiV0Message["metadata"],
174
242
  ...(status ? { status } : undefined),
243
+ ...(attachments ? { attachments } : undefined),
175
244
  };
176
245
  }
177
246
 
@@ -0,0 +1,141 @@
1
+ // @vitest-environment jsdom
2
+ import { render, waitFor } from "@testing-library/react";
3
+ import { resource, useResource } from "@assistant-ui/tap";
4
+ import type { ToolCallMessagePartProps } from "@assistant-ui/core/react";
5
+ import { beforeEach, describe, expect, it, vi } from "vitest";
6
+ import type { McpAppBridgeHandlers, McpAppsHost } from "./types";
7
+
8
+ const { framePropsMock } = vi.hoisted(() => ({ framePropsMock: vi.fn() }));
9
+
10
+ vi.mock("@assistant-ui/store", async (importOriginal) => ({
11
+ ...(await importOriginal()),
12
+ useAui: () => ({
13
+ thread: () => ({ append: vi.fn() }),
14
+ }),
15
+ }));
16
+
17
+ vi.mock("./app-frame", () => ({
18
+ McpAppFrame: (props: unknown) => {
19
+ framePropsMock(props);
20
+ return null;
21
+ },
22
+ }));
23
+
24
+ import { McpAppRenderer } from "./McpAppRenderer";
25
+
26
+ const useHost = ({ host }: { host: McpAppsHost }) => host;
27
+ const Host = resource(useHost);
28
+
29
+ const createPart = (serverId?: string): ToolCallMessagePartProps => ({
30
+ type: "tool-call",
31
+ toolCallId: "call-1",
32
+ toolName: "search",
33
+ args: {},
34
+ argsText: "{}",
35
+ status: { type: "complete" },
36
+ mcp: {
37
+ app: {
38
+ resourceUri: "ui://example/search",
39
+ ...(serverId !== undefined ? { serverId } : {}),
40
+ },
41
+ },
42
+ addResult: vi.fn(),
43
+ resume: vi.fn(),
44
+ respondToApproval: vi.fn(),
45
+ });
46
+
47
+ function Harness({ host, serverId }: { host: McpAppsHost; serverId?: string }) {
48
+ const renderer = useResource(
49
+ McpAppRenderer({
50
+ host: Host({ host }),
51
+ }),
52
+ );
53
+ const Renderer = renderer.render;
54
+ return <Renderer {...createPart(serverId)} />;
55
+ }
56
+
57
+ describe("McpAppRenderer", () => {
58
+ beforeEach(() => {
59
+ framePropsMock.mockReset();
60
+ });
61
+
62
+ it("injects serverId into loadResource and reloads when it changes", async () => {
63
+ const loadResource = vi.fn(async ({ uri }: { uri: string }) => ({
64
+ uri,
65
+ mimeType: "text/html;profile=mcp-app" as const,
66
+ html: "",
67
+ }));
68
+ const host: McpAppsHost = {
69
+ loadResource,
70
+ callTool: vi.fn(),
71
+ readResource: vi.fn(),
72
+ listResources: vi.fn(),
73
+ };
74
+
75
+ const view = render(<Harness host={host} serverId="server-a" />);
76
+ await waitFor(() =>
77
+ expect(loadResource).toHaveBeenCalledWith({
78
+ uri: "ui://example/search",
79
+ serverId: "server-a",
80
+ }),
81
+ );
82
+
83
+ view.rerender(<Harness host={host} serverId="server-b" />);
84
+ await waitFor(() => expect(loadResource).toHaveBeenCalledTimes(2));
85
+ expect(loadResource).toHaveBeenLastCalledWith({
86
+ uri: "ui://example/search",
87
+ serverId: "server-b",
88
+ });
89
+ });
90
+
91
+ it("gives the renderer serverId precedence in listResources", async () => {
92
+ const listResources = vi.fn();
93
+ const host: McpAppsHost = {
94
+ loadResource: vi.fn(async ({ uri }) => ({
95
+ uri,
96
+ mimeType: "text/html;profile=mcp-app" as const,
97
+ html: "",
98
+ })),
99
+ callTool: vi.fn(),
100
+ readResource: vi.fn(),
101
+ listResources,
102
+ };
103
+
104
+ render(<Harness host={host} serverId="host-server" />);
105
+ await waitFor(() => expect(framePropsMock).toHaveBeenCalled());
106
+ const handlers = framePropsMock.mock.lastCall?.[0]
107
+ .handlers as McpAppBridgeHandlers;
108
+
109
+ await handlers.listResources?.({
110
+ cursor: "next",
111
+ serverId: "widget-server",
112
+ });
113
+ expect(listResources).toHaveBeenCalledWith({
114
+ cursor: "next",
115
+ serverId: "host-server",
116
+ });
117
+ });
118
+
119
+ it("passes listResources params through unchanged without serverId", async () => {
120
+ const listResources = vi.fn();
121
+ const host: McpAppsHost = {
122
+ loadResource: vi.fn(async ({ uri }) => ({
123
+ uri,
124
+ mimeType: "text/html;profile=mcp-app" as const,
125
+ html: "",
126
+ })),
127
+ callTool: vi.fn(),
128
+ readResource: vi.fn(),
129
+ listResources,
130
+ };
131
+ const params = { cursor: "next" };
132
+
133
+ render(<Harness host={host} />);
134
+ await waitFor(() => expect(framePropsMock).toHaveBeenCalled());
135
+ const handlers = framePropsMock.mock.lastCall?.[0]
136
+ .handlers as McpAppBridgeHandlers;
137
+
138
+ await handlers.listResources?.(params);
139
+ expect(listResources).toHaveBeenCalledWith(params);
140
+ });
141
+ });
@@ -26,6 +26,7 @@ import type {
26
26
  McpAppsHost,
27
27
  } from "./types";
28
28
  import { getMcpAppFromToolPart } from "./utils";
29
+ import { isRecord } from "@assistant-ui/core/internal";
29
30
 
30
31
  export type McpAppRendererOptions = {
31
32
  /**
@@ -55,6 +56,7 @@ export type McpAppRendererOptions = {
55
56
 
56
57
  type LoadedResourceState = {
57
58
  resourceUri: string;
59
+ serverId?: string;
58
60
  resource?: McpAppResource;
59
61
  error?: Error;
60
62
  };
@@ -100,7 +102,11 @@ function InlineRenderer({
100
102
  const aui = useAui();
101
103
  const app = getMcpAppFromToolPart(part);
102
104
  const cachedAppRef = useRef<McpAppMetadata | undefined>(undefined);
103
- if (app != null && cachedAppRef.current?.resourceUri !== app.resourceUri) {
105
+ if (
106
+ app != null &&
107
+ (cachedAppRef.current?.resourceUri !== app.resourceUri ||
108
+ cachedAppRef.current?.serverId !== app.serverId)
109
+ ) {
104
110
  cachedAppRef.current = app;
105
111
  }
106
112
  const appForRender = app ?? cachedAppRef.current;
@@ -108,21 +114,37 @@ function InlineRenderer({
108
114
  const [loadedResource, setLoadedResource] = useState<LoadedResourceState>();
109
115
 
110
116
  const resourceUri = appForRender?.resourceUri;
117
+ const serverId = appForRender?.serverId;
118
+ const serverIdRef = useRef<string | undefined>(undefined);
119
+ serverIdRef.current = serverId;
111
120
  useEffect(() => {
112
121
  if (appForRender == null || resourceUri == null) return;
113
122
  let cancelled = false;
114
123
  const targetUri = resourceUri;
124
+ const targetServerId = serverId;
115
125
 
116
126
  internalsRef.current.host
117
- .loadResource({ uri: targetUri })
127
+ .loadResource({
128
+ uri: targetUri,
129
+ ...(targetServerId ? { serverId: targetServerId } : {}),
130
+ })
118
131
  .then((res) => {
119
132
  if (!cancelled)
120
- setLoadedResource({ resourceUri: targetUri, resource: res });
133
+ setLoadedResource({
134
+ resourceUri: targetUri,
135
+ ...(targetServerId !== undefined
136
+ ? { serverId: targetServerId }
137
+ : {}),
138
+ resource: res,
139
+ });
121
140
  })
122
141
  .catch((error: unknown) => {
123
142
  if (!cancelled) {
124
143
  setLoadedResource({
125
144
  resourceUri: targetUri,
145
+ ...(targetServerId !== undefined
146
+ ? { serverId: targetServerId }
147
+ : {}),
126
148
  error: error instanceof Error ? error : new Error(String(error)),
127
149
  });
128
150
  }
@@ -131,8 +153,8 @@ function InlineRenderer({
131
153
  return () => {
132
154
  cancelled = true;
133
155
  };
134
- // oxlint-disable-next-line react/exhaustive-deps -- re-fetch only when URI changes; appForRender identity is unstable and internalsRef is a stable ref
135
- }, [resourceUri]);
156
+ // oxlint-disable-next-line react/exhaustive-deps -- re-fetch only when URI or server identity changes; appForRender identity is unstable and internalsRef is a stable ref
157
+ }, [resourceUri, serverId]);
136
158
 
137
159
  const bridgeHandlers = useMemo<McpAppBridgeHandlers>(
138
160
  () => ({
@@ -143,16 +165,32 @@ function InlineRenderer({
143
165
  aui.thread().append({ content: [{ type: "text", text }] });
144
166
  return { ok: true };
145
167
  },
146
- callTool: (params) => internalsRef.current.host.callTool(params),
147
- readResource: (params) => internalsRef.current.host.readResource(params),
148
- listResources: (params) =>
149
- internalsRef.current.host.listResources(params),
168
+ callTool: (params) =>
169
+ internalsRef.current.host.callTool({
170
+ ...params,
171
+ ...(serverIdRef.current ? { serverId: serverIdRef.current } : {}),
172
+ }),
173
+ readResource: (params) =>
174
+ internalsRef.current.host.readResource({
175
+ ...params,
176
+ ...(serverIdRef.current ? { serverId: serverIdRef.current } : {}),
177
+ }),
178
+ listResources: (params) => {
179
+ if (!serverIdRef.current) {
180
+ return internalsRef.current.host.listResources(params);
181
+ }
182
+ return internalsRef.current.host.listResources({
183
+ ...(isRecord(params) ? params : {}),
184
+ serverId: serverIdRef.current,
185
+ });
186
+ },
150
187
  }),
151
188
  [aui, internalsRef],
152
189
  );
153
190
 
154
191
  const loadedResourceForApp =
155
- loadedResource?.resourceUri === appForRender?.resourceUri
192
+ loadedResource?.resourceUri === appForRender?.resourceUri &&
193
+ loadedResource?.serverId === appForRender?.serverId
156
194
  ? loadedResource
157
195
  : undefined;
158
196
  const appResource = loadedResourceForApp?.resource;