@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,5 @@
1
1
  import { describe, expect, it } from "vitest";
2
- import { auiV0Encode } from "../legacy-runtime/cloud/auiV0";
2
+ import { auiV0Decode, auiV0Encode } from "../legacy-runtime/cloud/auiV0";
3
3
 
4
4
  describe("auiV0Encode", () => {
5
5
  it("preserves document source parts in the legacy cloud encoder", () => {
@@ -52,4 +52,137 @@ describe("auiV0Encode", () => {
52
52
  },
53
53
  ]);
54
54
  });
55
+
56
+ it("preserves user attachments in the legacy cloud encoder", () => {
57
+ const encoded = auiV0Encode({
58
+ id: "m1",
59
+ createdAt: new Date("2026-03-15T00:00:00.000Z"),
60
+ role: "user",
61
+ metadata: { custom: {} },
62
+ content: [{ type: "text", text: "please review this" }],
63
+ attachments: [
64
+ {
65
+ id: "att-1",
66
+ type: "document",
67
+ name: "proposal.pdf",
68
+ contentType: "application/pdf",
69
+ status: { type: "complete" },
70
+ content: [
71
+ {
72
+ type: "file",
73
+ data: "data:application/pdf;base64,JVBERi0xLjQ=",
74
+ mimeType: "application/pdf",
75
+ filename: "proposal.pdf",
76
+ },
77
+ ],
78
+ },
79
+ ],
80
+ });
81
+
82
+ expect(encoded.attachments).toEqual([
83
+ {
84
+ id: "att-1",
85
+ type: "document",
86
+ name: "proposal.pdf",
87
+ contentType: "application/pdf",
88
+ status: { type: "complete" },
89
+ content: [
90
+ {
91
+ type: "file",
92
+ data: "data:application/pdf;base64,JVBERi0xLjQ=",
93
+ mimeType: "application/pdf",
94
+ filename: "proposal.pdf",
95
+ },
96
+ ],
97
+ },
98
+ ]);
99
+ });
100
+
101
+ it("omits missing attachment contentType in the legacy cloud encoder", () => {
102
+ const encoded = auiV0Encode({
103
+ id: "m1",
104
+ createdAt: new Date("2026-03-15T00:00:00.000Z"),
105
+ role: "user",
106
+ metadata: { custom: {} },
107
+ content: [{ type: "text", text: "please review this" }],
108
+ attachments: [
109
+ {
110
+ id: "att-1",
111
+ type: "document",
112
+ name: "notes.txt",
113
+ status: { type: "complete" },
114
+ content: [{ type: "text", text: "notes" }],
115
+ },
116
+ ],
117
+ });
118
+
119
+ expect(encoded.attachments).toEqual([
120
+ {
121
+ id: "att-1",
122
+ type: "document",
123
+ name: "notes.txt",
124
+ status: { type: "complete" },
125
+ content: [{ type: "text", text: "notes" }],
126
+ },
127
+ ]);
128
+ });
129
+ });
130
+
131
+ describe("auiV0Decode", () => {
132
+ it("restores user attachments from legacy cloud history", () => {
133
+ const content = auiV0Encode({
134
+ id: "local",
135
+ createdAt: new Date("2026-03-15T00:00:00.000Z"),
136
+ role: "user",
137
+ metadata: { custom: {} },
138
+ content: [{ type: "text", text: "please review this" }],
139
+ attachments: [
140
+ {
141
+ id: "att-1",
142
+ type: "document",
143
+ name: "proposal.pdf",
144
+ contentType: "application/pdf",
145
+ status: { type: "complete" },
146
+ content: [
147
+ {
148
+ type: "file",
149
+ data: "data:application/pdf;base64,JVBERi0xLjQ=",
150
+ mimeType: "application/pdf",
151
+ filename: "proposal.pdf",
152
+ },
153
+ ],
154
+ },
155
+ ],
156
+ });
157
+
158
+ const decoded = auiV0Decode({
159
+ id: "cloud",
160
+ parent_id: null,
161
+ height: 0,
162
+ created_at: new Date("2026-03-15T00:00:00.000Z"),
163
+ updated_at: new Date("2026-03-15T00:00:00.000Z"),
164
+ format: "aui/v0",
165
+ content: content as never,
166
+ });
167
+
168
+ expect(decoded.message.role).toBe("user");
169
+ if (decoded.message.role !== "user") throw new Error("expected user");
170
+ expect(decoded.message.attachments).toEqual([
171
+ {
172
+ id: "att-1",
173
+ type: "document",
174
+ name: "proposal.pdf",
175
+ contentType: "application/pdf",
176
+ status: { type: "complete" },
177
+ content: [
178
+ {
179
+ type: "file",
180
+ data: "data:application/pdf;base64,JVBERi0xLjQ=",
181
+ mimeType: "application/pdf",
182
+ filename: "proposal.pdf",
183
+ },
184
+ ],
185
+ },
186
+ ]);
187
+ });
55
188
  });
@@ -1,4 +1,4 @@
1
- import { describe, expect, it } from "vitest";
1
+ import { describe, expect, it, vi } from "vitest";
2
2
  import { renderToStaticMarkup } from "react-dom/server";
3
3
  import {
4
4
  GenerativeUIRender,
@@ -113,6 +113,26 @@ describe("MessagePrimitive.GenerativeUI (same-realm renderer)", () => {
113
113
  expect(out2).toContain("<h3>loading</h3>");
114
114
  });
115
115
 
116
+ it("skips malformed nodes with non-string component names", () => {
117
+ const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
118
+ const malformedNode = { component: 123, props: { title: "bad" } };
119
+ const spec = { root: malformedNode } as unknown as GenerativeUISpec;
120
+
121
+ try {
122
+ const out = renderToStaticMarkup(
123
+ <GenerativeUIRender spec={spec} components={{ Card }} />,
124
+ );
125
+
126
+ expect(out).toBe("");
127
+ expect(warn).toHaveBeenCalledWith(
128
+ "[generative-ui] Skipping malformed node at 0:",
129
+ malformedNode,
130
+ );
131
+ } finally {
132
+ warn.mockRestore();
133
+ }
134
+ });
135
+
116
136
  it("respects user-provided keys", () => {
117
137
  const spec: GenerativeUISpec = {
118
138
  root: [
@@ -0,0 +1,175 @@
1
+ /**
2
+ * @vitest-environment jsdom
3
+ */
4
+ import { afterEach, describe, expect, it } from "vitest";
5
+ import { getSelectionMessageId } from "./getSelectionMessageId";
6
+
7
+ const selectText = (start: Text, end = start) => {
8
+ const selection = window.getSelection();
9
+ expect(selection).not.toBeNull();
10
+ selection?.removeAllRanges();
11
+
12
+ const range = document.createRange();
13
+ range.setStart(start, 0);
14
+ range.setEnd(end, end.data.length);
15
+ selection?.addRange(range);
16
+
17
+ return selection as Selection;
18
+ };
19
+
20
+ const textNode = (selector: string) => {
21
+ const node = document.querySelector(selector)?.firstChild;
22
+ expect(node).toBeInstanceOf(Text);
23
+ return node as Text;
24
+ };
25
+
26
+ afterEach(() => {
27
+ window.getSelection()?.removeAllRanges();
28
+ document.body.replaceChildren();
29
+ });
30
+
31
+ describe("getSelectionMessageId", () => {
32
+ it("accepts selections anywhere in a message without quote regions", () => {
33
+ document.body.innerHTML = `
34
+ <div data-message-id="message-1">
35
+ <p id="text">message text</p>
36
+ <div id="tool">tool output</div>
37
+ </div>
38
+ `;
39
+
40
+ expect(getSelectionMessageId(selectText(textNode("#tool")))).toBe(
41
+ "message-1",
42
+ );
43
+ });
44
+
45
+ it("accepts selections inside a quote-selectable region", () => {
46
+ document.body.innerHTML = `
47
+ <div data-message-id="message-1">
48
+ <p id="text" data-aui-quote-selectable>message text</p>
49
+ <div id="tool">tool output</div>
50
+ </div>
51
+ `;
52
+
53
+ expect(getSelectionMessageId(selectText(textNode("#text")))).toBe(
54
+ "message-1",
55
+ );
56
+ });
57
+
58
+ it("treats the whole message as quotable when the root is the region", () => {
59
+ document.body.innerHTML = `
60
+ <div data-message-id="message-1" data-aui-quote-selectable>
61
+ <p id="text">message text</p>
62
+ <div id="tool">tool output</div>
63
+ </div>
64
+ `;
65
+
66
+ expect(getSelectionMessageId(selectText(textNode("#text")))).toBe(
67
+ "message-1",
68
+ );
69
+ expect(
70
+ getSelectionMessageId(selectText(textNode("#text"), textNode("#tool"))),
71
+ ).toBe("message-1");
72
+ });
73
+
74
+ it("disables quoting for the whole message when the root is marked false", () => {
75
+ document.body.innerHTML = `
76
+ <div data-message-id="message-1" data-aui-quote-selectable="false">
77
+ <p id="text">message text</p>
78
+ <div id="tool">tool output</div>
79
+ </div>
80
+ `;
81
+
82
+ expect(getSelectionMessageId(selectText(textNode("#text")))).toBeNull();
83
+ expect(getSelectionMessageId(selectText(textNode("#tool")))).toBeNull();
84
+ });
85
+
86
+ it("excludes a false subtree while the rest of the message stays quotable", () => {
87
+ document.body.innerHTML = `
88
+ <div data-message-id="message-1">
89
+ <p id="text">message text</p>
90
+ <div id="tool" data-aui-quote-selectable="false">tool output</div>
91
+ </div>
92
+ `;
93
+
94
+ expect(getSelectionMessageId(selectText(textNode("#text")))).toBe(
95
+ "message-1",
96
+ );
97
+ expect(getSelectionMessageId(selectText(textNode("#tool")))).toBeNull();
98
+ });
99
+
100
+ it("carves a false region out of a quote-selectable region", () => {
101
+ document.body.innerHTML = `
102
+ <div data-message-id="message-1">
103
+ <div data-aui-quote-selectable="">
104
+ <p id="text">message text</p>
105
+ <span id="chip" data-aui-quote-selectable="false">citation chip</span>
106
+ </div>
107
+ </div>
108
+ `;
109
+
110
+ expect(getSelectionMessageId(selectText(textNode("#text")))).toBe(
111
+ "message-1",
112
+ );
113
+ expect(getSelectionMessageId(selectText(textNode("#chip")))).toBeNull();
114
+ expect(
115
+ getSelectionMessageId(selectText(textNode("#text"), textNode("#chip"))),
116
+ ).toBeNull();
117
+ });
118
+
119
+ it("rejects selections outside quote-selectable regions when a message opts in", () => {
120
+ document.body.innerHTML = `
121
+ <div data-message-id="message-1">
122
+ <p id="text" data-aui-quote-selectable>message text</p>
123
+ <div id="tool">tool output</div>
124
+ </div>
125
+ `;
126
+
127
+ expect(getSelectionMessageId(selectText(textNode("#tool")))).toBeNull();
128
+ });
129
+
130
+ it("rejects selections crossing out of a quote-selectable region", () => {
131
+ document.body.innerHTML = `
132
+ <div data-message-id="message-1">
133
+ <p id="text" data-aui-quote-selectable>message text</p>
134
+ <div id="tool">tool output</div>
135
+ </div>
136
+ `;
137
+
138
+ expect(
139
+ getSelectionMessageId(selectText(textNode("#text"), textNode("#tool"))),
140
+ ).toBeNull();
141
+ });
142
+
143
+ it("rejects selections crossing separate quote-selectable regions", () => {
144
+ document.body.innerHTML = `
145
+ <div data-message-id="message-1">
146
+ <p id="first" data-aui-quote-selectable>first text</p>
147
+ <div id="tool">tool output</div>
148
+ <p id="second" data-aui-quote-selectable>second text</p>
149
+ </div>
150
+ `;
151
+
152
+ expect(
153
+ getSelectionMessageId(
154
+ selectText(textNode("#first"), textNode("#second")),
155
+ ),
156
+ ).toBeNull();
157
+ });
158
+
159
+ it("rejects selections across messages", () => {
160
+ document.body.innerHTML = `
161
+ <div data-message-id="message-1">
162
+ <p id="first">first text</p>
163
+ </div>
164
+ <div data-message-id="message-2">
165
+ <p id="second">second text</p>
166
+ </div>
167
+ `;
168
+
169
+ expect(
170
+ getSelectionMessageId(
171
+ selectText(textNode("#first"), textNode("#second")),
172
+ ),
173
+ ).toBeNull();
174
+ });
175
+ });
@@ -1,20 +1,71 @@
1
- const findMessageId = (node: Node | null): string | null => {
1
+ const QUOTE_SELECTABLE_SELECTOR = "[data-aui-quote-selectable]";
2
+
3
+ const getElement = (node: Node | null): HTMLElement | null => {
4
+ return node instanceof HTMLElement ? node : (node?.parentElement ?? null);
5
+ };
6
+
7
+ const findMessageElement = (node: Node | null): HTMLElement | null => {
2
8
  let el = node instanceof HTMLElement ? node : (node?.parentElement ?? null);
3
9
  while (el) {
4
10
  const id = el.getAttribute("data-message-id");
5
- if (id) return id;
11
+ if (id) return el;
6
12
  el = el.parentElement;
7
13
  }
8
14
  return null;
9
15
  };
10
16
 
17
+ const isExcluded = (marker: Element): boolean => {
18
+ return marker.getAttribute("data-aui-quote-selectable") === "false";
19
+ };
20
+
21
+ const hasQuoteSelectableRegion = (messageElement: HTMLElement) => {
22
+ if (
23
+ messageElement.matches(QUOTE_SELECTABLE_SELECTOR) &&
24
+ !isExcluded(messageElement)
25
+ ) {
26
+ return true;
27
+ }
28
+ for (const marker of messageElement.querySelectorAll(
29
+ QUOTE_SELECTABLE_SELECTOR,
30
+ )) {
31
+ if (!isExcluded(marker)) return true;
32
+ }
33
+ return false;
34
+ };
35
+
36
+ const findQuoteMarker = (
37
+ node: Node | null,
38
+ messageElement: HTMLElement,
39
+ ): HTMLElement | null => {
40
+ const marker = getElement(node)?.closest(QUOTE_SELECTABLE_SELECTOR);
41
+ if (!(marker instanceof HTMLElement)) return null;
42
+ if (!messageElement.contains(marker)) return null;
43
+ return marker;
44
+ };
45
+
11
46
  export const getSelectionMessageId = (selection: Selection): string | null => {
12
47
  const { anchorNode, focusNode } = selection;
13
48
  if (!anchorNode || !focusNode) return null;
14
49
 
15
- const anchorId = findMessageId(anchorNode);
16
- const focusId = findMessageId(focusNode);
50
+ const anchorMessageElement = findMessageElement(anchorNode);
51
+ const focusMessageElement = findMessageElement(focusNode);
52
+
53
+ if (!anchorMessageElement || anchorMessageElement !== focusMessageElement) {
54
+ return null;
55
+ }
56
+
57
+ const messageId = anchorMessageElement.getAttribute("data-message-id");
58
+ if (!messageId) return null;
59
+
60
+ const anchorMarker = findQuoteMarker(anchorNode, anchorMessageElement);
61
+ const focusMarker = findQuoteMarker(focusNode, anchorMessageElement);
62
+
63
+ if (anchorMarker && isExcluded(anchorMarker)) return null;
64
+ if (focusMarker && isExcluded(focusMarker)) return null;
65
+
66
+ if (!hasQuoteSelectableRegion(anchorMessageElement)) return messageId;
67
+
68
+ if (!anchorMarker || anchorMarker !== focusMarker) return null;
17
69
 
18
- if (!anchorId || anchorId !== focusId) return null;
19
- return anchorId;
70
+ return messageId;
20
71
  };
@@ -8,7 +8,7 @@ const noopUnsubscribe = () => {};
8
8
  export const useMediaQuery = (query: string | null): boolean => {
9
9
  const subscribe = useCallback(
10
10
  (callback: () => void) => {
11
- if (typeof window === "undefined" || query === null)
11
+ if (typeof window === "undefined" || query === null || !window.matchMedia)
12
12
  return noopUnsubscribe;
13
13
  const mql = window.matchMedia(query);
14
14
  mql.addEventListener("change", callback);
@@ -18,7 +18,8 @@ export const useMediaQuery = (query: string | null): boolean => {
18
18
  );
19
19
 
20
20
  const getSnapshot = useCallback(() => {
21
- if (typeof window === "undefined" || query === null) return false;
21
+ if (typeof window === "undefined" || query === null || !window.matchMedia)
22
+ return false;
22
23
  return window.matchMedia(query).matches;
23
24
  }, [query]);
24
25
 
@@ -39,6 +39,23 @@ const runningState = (text: string) =>
39
39
  status: { type: "running" },
40
40
  }) as MessagePartState & TextMessagePart;
41
41
 
42
+ const setReducedMotion = (matches: boolean) => {
43
+ Object.defineProperty(window, "matchMedia", {
44
+ writable: true,
45
+ configurable: true,
46
+ value: (query: string) => ({
47
+ matches,
48
+ media: query,
49
+ onchange: null,
50
+ addEventListener: () => {},
51
+ removeEventListener: () => {},
52
+ addListener: () => {},
53
+ removeListener: () => {},
54
+ dispatchEvent: () => false,
55
+ }),
56
+ });
57
+ };
58
+
42
59
  const driveAndCount = (minCommitMs: number) => {
43
60
  const raf: FrameRequestCallback[] = [];
44
61
  const rafSpy = vi
@@ -85,6 +102,7 @@ const driveAndCount = (minCommitMs: number) => {
85
102
  describe("useSmooth", () => {
86
103
  afterEach(() => {
87
104
  vi.restoreAllMocks();
105
+ Reflect.deleteProperty(window, "matchMedia");
88
106
  });
89
107
 
90
108
  it("returns the input state unchanged when disabled", () => {
@@ -115,6 +133,14 @@ describe("useSmooth", () => {
115
133
  expect(result.current).toBe(state);
116
134
  });
117
135
 
136
+ it("disables the reveal under prefers-reduced-motion", () => {
137
+ setReducedMotion(true);
138
+ const state = runningState("streaming");
139
+ const { result } = renderHook(() => useSmooth(state, true));
140
+ expect(result.current).toBe(state);
141
+ expect(result.current.text).toBe("streaming");
142
+ });
143
+
118
144
  it("starts from an empty reveal for running parts when enabled", () => {
119
145
  const state = {
120
146
  type: "text",
@@ -9,6 +9,7 @@ import type {
9
9
  MessagePartState,
10
10
  } from "@assistant-ui/core";
11
11
  import { useCallbackRef } from "@radix-ui/react-use-callback-ref";
12
+ import { useMediaQuery } from "../hooks/useMediaQuery";
12
13
  import { useSmoothStatusStore } from "./SmoothContext";
13
14
  import { writableStore } from "../../context/ReadonlyStore";
14
15
 
@@ -134,6 +135,10 @@ const positiveOr = (value: number | undefined, fallback: number): number =>
134
135
  * the reveal. Returns the part state with `text` replaced by the revealed
135
136
  * prefix and `status` reporting `running` until the reveal catches up.
136
137
  *
138
+ * The reveal auto-disables under `prefers-reduced-motion: reduce`,
139
+ * committing the full text immediately; this takes precedence over an
140
+ * explicit `smooth={true}`.
141
+ *
137
142
  * @example
138
143
  * ```tsx
139
144
  * const { text, status } = useSmooth(useMessagePartText(), {
@@ -147,9 +152,10 @@ export const useSmooth = (
147
152
  smooth: boolean | SmoothOptions = false,
148
153
  ): MessagePartState & (TextMessagePart | ReasoningMessagePart) => {
149
154
  const { text } = state;
155
+ const reduceMotion = useMediaQuery("(prefers-reduced-motion: reduce)");
150
156
  const options =
151
157
  typeof smooth === "object" && smooth !== null ? smooth : undefined;
152
- const enabled = smooth !== false && smooth !== null;
158
+ const enabled = smooth !== false && smooth !== null && !reduceMotion;
153
159
  const drainMs = positiveOr(options?.drainMs, DEFAULT_DRAIN_MS);
154
160
  const maxCharIntervalMs = positiveOr(
155
161
  options?.maxCharIntervalMs,
@@ -1,5 +0,0 @@
1
- //#region src/utils/json/is-json-equal.d.ts
2
- declare const isJSONValueEqual: (a: unknown, b: unknown) => boolean;
3
- //#endregion
4
- export { isJSONValueEqual };
5
- //# sourceMappingURL=is-json-equal.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"is-json-equal.d.ts","names":[],"sources":["../../../src/utils/json/is-json-equal.ts"],"mappings":";cA4Ca,gBAAA,GAAoB,CAAA,WAAY,CAAU"}
@@ -1,26 +0,0 @@
1
- import { isJSONValue, isRecord } from "./is-json.js";
2
- //#region src/utils/json/is-json-equal.ts
3
- const MAX_JSON_DEPTH = 100;
4
- const isJSONValueEqualAtDepth = (a, b, currentDepth) => {
5
- if (a === b) return true;
6
- if (currentDepth > MAX_JSON_DEPTH) return false;
7
- if (a == null || b == null) return false;
8
- if (Array.isArray(a)) {
9
- if (!Array.isArray(b) || a.length !== b.length) return false;
10
- return a.every((item, index) => isJSONValueEqualAtDepth(item, b[index], currentDepth + 1));
11
- }
12
- if (Array.isArray(b)) return false;
13
- if (!isRecord(a) || !isRecord(b)) return false;
14
- const aKeys = Object.keys(a);
15
- const bKeys = Object.keys(b);
16
- if (aKeys.length !== bKeys.length) return false;
17
- return aKeys.every((key) => Object.hasOwn(b, key) && isJSONValueEqualAtDepth(a[key], b[key], currentDepth + 1));
18
- };
19
- const isJSONValueEqual = (a, b) => {
20
- if (!isJSONValue(a) || !isJSONValue(b)) return false;
21
- return isJSONValueEqualAtDepth(a, b, 0);
22
- };
23
- //#endregion
24
- export { isJSONValueEqual };
25
-
26
- //# sourceMappingURL=is-json-equal.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"is-json-equal.js","names":["ReadonlyJSONValue","isJSONValue","isRecord","MAX_JSON_DEPTH","isJSONValueEqualAtDepth","a","b","currentDepth","Array","isArray","length","every","item","index","aKeys","Object","keys","bKeys","key","hasOwn","isJSONValueEqual"],"sources":["../../../src/utils/json/is-json-equal.ts"],"sourcesContent":["import type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport { isJSONValue, isRecord } from \"./is-json\";\n\nconst MAX_JSON_DEPTH = 100;\n\nconst isJSONValueEqualAtDepth = (\n a: ReadonlyJSONValue,\n b: ReadonlyJSONValue,\n currentDepth: number,\n): boolean => {\n if (a === b) return true;\n if (currentDepth > MAX_JSON_DEPTH) return false;\n\n if (a == null || b == null) return false;\n\n if (Array.isArray(a)) {\n if (!Array.isArray(b) || a.length !== b.length) return false;\n return a.every((item, index) =>\n isJSONValueEqualAtDepth(\n item,\n b[index] as ReadonlyJSONValue,\n currentDepth + 1,\n ),\n );\n }\n\n if (Array.isArray(b)) return false;\n if (!isRecord(a) || !isRecord(b)) return false;\n\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n if (aKeys.length !== bKeys.length) return false;\n\n return aKeys.every(\n (key) =>\n Object.hasOwn(b, key) &&\n isJSONValueEqualAtDepth(\n a[key] as ReadonlyJSONValue,\n b[key] as ReadonlyJSONValue,\n currentDepth + 1,\n ),\n );\n};\n\nexport const isJSONValueEqual = (a: unknown, b: unknown): boolean => {\n if (!isJSONValue(a) || !isJSONValue(b)) return false;\n return isJSONValueEqualAtDepth(a, b, 0);\n};\n"],"mappings":";;AAGA,MAAMG,iBAAiB;AAEvB,MAAMC,2BACJC,GACAC,GACAC,iBACY;CACZ,IAAIF,MAAMC,GAAG,OAAO;CACpB,IAAIC,eAAeJ,gBAAgB,OAAO;CAE1C,IAAIE,KAAK,QAAQC,KAAK,MAAM,OAAO;CAEnC,IAAIE,MAAMC,QAAQJ,CAAC,GAAG;EACpB,IAAI,CAACG,MAAMC,QAAQH,CAAC,KAAKD,EAAEK,WAAWJ,EAAEI,QAAQ,OAAO;EACvD,OAAOL,EAAEM,OAAOC,MAAMC,UACpBT,wBACEQ,MACAN,EAAEO,QACFN,eAAe,CACjB,CACF;CACF;CAEA,IAAIC,MAAMC,QAAQH,CAAC,GAAG,OAAO;CAC7B,IAAI,CAACJ,SAASG,CAAC,KAAK,CAACH,SAASI,CAAC,GAAG,OAAO;CAEzC,MAAMQ,QAAQC,OAAOC,KAAKX,CAAC;CAC3B,MAAMY,QAAQF,OAAOC,KAAKV,CAAC;CAC3B,IAAIQ,MAAMJ,WAAWO,MAAMP,QAAQ,OAAO;CAE1C,OAAOI,MAAMH,OACVO,QACCH,OAAOI,OAAOb,GAAGY,GAAG,KACpBd,wBACEC,EAAEa,MACFZ,EAAEY,MACFX,eAAe,CACjB,CACJ;AACF;AAEA,MAAaa,oBAAoBf,GAAYC,MAAwB;CACnE,IAAI,CAACL,YAAYI,CAAC,KAAK,CAACJ,YAAYK,CAAC,GAAG,OAAO;CAC/C,OAAOF,wBAAwBC,GAAGC,GAAG,CAAC;AACxC"}
@@ -1,10 +0,0 @@
1
- import { ReadonlyJSONArray, ReadonlyJSONObject, ReadonlyJSONValue } from "assistant-stream/utils";
2
-
3
- //#region src/utils/json/is-json.d.ts
4
- declare function isRecord(value: unknown): value is Record<string, unknown>;
5
- declare function isJSONValue(value: unknown, currentDepth?: number): value is ReadonlyJSONValue;
6
- declare function isJSONArray(value: unknown): value is ReadonlyJSONArray;
7
- declare function isJSONObject(value: unknown): value is ReadonlyJSONObject;
8
- //#endregion
9
- export { isJSONArray, isJSONObject, isJSONValue, isRecord };
10
- //# sourceMappingURL=is-json.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"is-json.d.ts","names":[],"sources":["../../../src/utils/json/is-json.ts"],"mappings":";;;iBAMgB,QAAA,CAAS,KAAA,YAAiB,KAAA,IAAS,MAAM;AAAA,iBAIzC,WAAA,CACd,KAAA,WACA,YAAA,YACC,KAAA,IAAS,iBAAiB;AAAA,iBAiCb,WAAA,CAAY,KAAA,YAAiB,KAAA,IAAS,iBAAiB;AAAA,iBAIvD,YAAA,CAAa,KAAA,YAAiB,KAAA,IAAS,kBAAkB"}
@@ -1,22 +0,0 @@
1
- //#region src/utils/json/is-json.ts
2
- function isRecord(value) {
3
- return value != null && typeof value === "object" && !Array.isArray(value);
4
- }
5
- function isJSONValue(value, currentDepth = 0) {
6
- if (currentDepth > 100) return false;
7
- if (value === null || typeof value === "string" || typeof value === "boolean") return true;
8
- if (typeof value === "number") return !Number.isNaN(value) && Number.isFinite(value);
9
- if (Array.isArray(value)) return value.every((item) => isJSONValue(item, currentDepth + 1));
10
- if (isRecord(value)) return Object.entries(value).every(([key, val]) => typeof key === "string" && isJSONValue(val, currentDepth + 1));
11
- return false;
12
- }
13
- function isJSONArray(value) {
14
- return Array.isArray(value) && value.every(isJSONValue);
15
- }
16
- function isJSONObject(value) {
17
- return isRecord(value) && Object.entries(value).every(([key, val]) => typeof key === "string" && isJSONValue(val));
18
- }
19
- //#endregion
20
- export { isJSONArray, isJSONObject, isJSONValue, isRecord };
21
-
22
- //# sourceMappingURL=is-json.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"is-json.js","names":["ReadonlyJSONArray","ReadonlyJSONObject","ReadonlyJSONValue","isRecord","value","Record","Array","isArray","isJSONValue","currentDepth","Number","isNaN","isFinite","every","item","Object","entries","key","val","isJSONArray","isJSONObject"],"sources":["../../../src/utils/json/is-json.ts"],"sourcesContent":["import type {\n ReadonlyJSONArray,\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from \"assistant-stream/utils\";\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return value != null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function isJSONValue(\n value: unknown,\n currentDepth: number = 0,\n): value is ReadonlyJSONValue {\n // Protect against too deep recursion\n if (currentDepth > 100) {\n return false;\n }\n\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"boolean\"\n ) {\n return true;\n }\n\n // Handle special number cases\n if (typeof value === \"number\") {\n return !Number.isNaN(value) && Number.isFinite(value);\n }\n\n if (Array.isArray(value)) {\n return value.every((item) => isJSONValue(item, currentDepth + 1));\n }\n\n if (isRecord(value)) {\n return Object.entries(value).every(\n ([key, val]) =>\n typeof key === \"string\" && isJSONValue(val, currentDepth + 1),\n );\n }\n\n return false;\n}\n\nexport function isJSONArray(value: unknown): value is ReadonlyJSONArray {\n return Array.isArray(value) && value.every(isJSONValue);\n}\n\nexport function isJSONObject(value: unknown): value is ReadonlyJSONObject {\n return (\n isRecord(value) &&\n Object.entries(value).every(\n ([key, val]) => typeof key === \"string\" && isJSONValue(val),\n )\n );\n}\n"],"mappings":";AAMA,SAAgBG,SAASC,OAAkD;CACzE,OAAOA,SAAS,QAAQ,OAAOA,UAAU,YAAY,CAACE,MAAMC,QAAQH,KAAK;AAC3E;AAEA,SAAgBI,YACdJ,OACAK,eAAuB,GACK;CAE5B,IAAIA,eAAe,KACjB,OAAO;CAGT,IACEL,UAAU,QACV,OAAOA,UAAU,YACjB,OAAOA,UAAU,WAEjB,OAAO;CAIT,IAAI,OAAOA,UAAU,UACnB,OAAO,CAACM,OAAOC,MAAMP,KAAK,KAAKM,OAAOE,SAASR,KAAK;CAGtD,IAAIE,MAAMC,QAAQH,KAAK,GACrB,OAAOA,MAAMS,OAAOC,SAASN,YAAYM,MAAML,eAAe,CAAC,CAAC;CAGlE,IAAIN,SAASC,KAAK,GAChB,OAAOW,OAAOC,QAAQZ,KAAK,CAAC,CAACS,OAC1B,CAACI,KAAKC,SACL,OAAOD,QAAQ,YAAYT,YAAYU,KAAKT,eAAe,CAAC,CAChE;CAGF,OAAO;AACT;AAEA,SAAgBU,YAAYf,OAA4C;CACtE,OAAOE,MAAMC,QAAQH,KAAK,KAAKA,MAAMS,MAAML,WAAW;AACxD;AAEA,SAAgBY,aAAahB,OAA6C;CACxE,OACED,SAASC,KAAK,KACdW,OAAOC,QAAQZ,KAAK,CAAC,CAACS,OACnB,CAACI,KAAKC,SAAS,OAAOD,QAAQ,YAAYT,YAAYU,GAAG,CAC5D;AAEJ"}
@@ -1,23 +0,0 @@
1
- "use client";
2
-
3
- import {
4
- type ActionButtonElement,
5
- type ActionButtonProps,
6
- createActionButton,
7
- } from "../../utils/createActionButton";
8
- import { useThreadListItemTrigger as useThreadListItemTriggerBehavior } from "@assistant-ui/core/react";
9
-
10
- const useThreadListItemTrigger = () => {
11
- const { switchTo } = useThreadListItemTriggerBehavior();
12
- return switchTo;
13
- };
14
-
15
- export namespace ThreadListItemPrimitiveTrigger {
16
- export type Element = ActionButtonElement;
17
- export type Props = ActionButtonProps<typeof useThreadListItemTrigger>;
18
- }
19
-
20
- export const ThreadListItemPrimitiveTrigger = createActionButton(
21
- "ThreadListItemPrimitive.Trigger",
22
- useThreadListItemTrigger,
23
- );