@assistant-ui/react 0.14.26 → 0.14.28

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 (496) 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 +4 -3
  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/AssistantRuntimeProvider.js.map +1 -1
  44. package/dist/legacy-runtime/cloud/auiV0.d.ts +11 -2
  45. package/dist/legacy-runtime/cloud/auiV0.d.ts.map +1 -1
  46. package/dist/legacy-runtime/cloud/auiV0.js +31 -2
  47. package/dist/legacy-runtime/cloud/auiV0.js.map +1 -1
  48. package/dist/legacy-runtime/cloud/useCloudThreadListRuntime.d.ts +1 -5
  49. package/dist/legacy-runtime/cloud/useCloudThreadListRuntime.d.ts.map +1 -1
  50. package/dist/legacy-runtime/hooks/AssistantContext.d.ts +0 -1
  51. package/dist/legacy-runtime/hooks/AssistantContext.d.ts.map +1 -1
  52. package/dist/legacy-runtime/hooks/AttachmentContext.d.ts +12 -13
  53. package/dist/legacy-runtime/hooks/AttachmentContext.d.ts.map +1 -1
  54. package/dist/legacy-runtime/hooks/ComposerContext.d.ts +0 -1
  55. package/dist/legacy-runtime/hooks/ComposerContext.d.ts.map +1 -1
  56. package/dist/legacy-runtime/hooks/MessageContext.d.ts +0 -1
  57. package/dist/legacy-runtime/hooks/MessageContext.d.ts.map +1 -1
  58. package/dist/legacy-runtime/hooks/MessagePartContext.d.ts +0 -1
  59. package/dist/legacy-runtime/hooks/MessagePartContext.d.ts.map +1 -1
  60. package/dist/legacy-runtime/hooks/ThreadContext.d.ts +0 -1
  61. package/dist/legacy-runtime/hooks/ThreadContext.d.ts.map +1 -1
  62. package/dist/legacy-runtime/hooks/ThreadListItemContext.d.ts +0 -1
  63. package/dist/legacy-runtime/hooks/ThreadListItemContext.d.ts.map +1 -1
  64. package/dist/legacy-runtime/runtime-cores/assistant-transport/commandQueue.d.ts +0 -1
  65. package/dist/legacy-runtime/runtime-cores/assistant-transport/commandQueue.d.ts.map +1 -1
  66. package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.d.ts +1 -4
  67. package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.d.ts.map +1 -1
  68. package/dist/legacy-runtime/runtime-cores/assistant-transport/runManager.d.ts.map +1 -1
  69. package/dist/legacy-runtime/runtime-cores/assistant-transport/types.d.ts +0 -1
  70. package/dist/legacy-runtime/runtime-cores/assistant-transport/types.d.ts.map +1 -1
  71. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.d.ts +0 -1
  72. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -1
  73. package/dist/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.d.ts +0 -1
  74. package/dist/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.d.ts.map +1 -1
  75. package/dist/legacy-runtime/runtime-cores/assistant-transport/useLatestRef.d.ts.map +1 -1
  76. package/dist/mcp-apps/McpAppRenderer.d.ts +12 -7
  77. package/dist/mcp-apps/McpAppRenderer.d.ts.map +1 -1
  78. package/dist/mcp-apps/McpAppRenderer.js +29 -7
  79. package/dist/mcp-apps/McpAppRenderer.js.map +1 -1
  80. package/dist/mcp-apps/McpAppsRemoteHost.d.ts +0 -1
  81. package/dist/mcp-apps/McpAppsRemoteHost.d.ts.map +1 -1
  82. package/dist/mcp-apps/McpAppsRemoteHost.js +32 -1
  83. package/dist/mcp-apps/McpAppsRemoteHost.js.map +1 -1
  84. package/dist/mcp-apps/app-frame.d.ts +1 -12
  85. package/dist/mcp-apps/app-frame.d.ts.map +1 -1
  86. package/dist/mcp-apps/app-frame.js +1 -1
  87. package/dist/mcp-apps/app-frame.js.map +1 -1
  88. package/dist/mcp-apps/bridge.d.ts +0 -1
  89. package/dist/mcp-apps/bridge.d.ts.map +1 -1
  90. package/dist/mcp-apps/bridge.js +4 -3
  91. package/dist/mcp-apps/bridge.js.map +1 -1
  92. package/dist/mcp-apps/types.d.ts +10 -7
  93. package/dist/mcp-apps/types.d.ts.map +1 -1
  94. package/dist/mcp-apps/types.js.map +1 -1
  95. package/dist/mcp-apps/utils.d.ts +0 -1
  96. package/dist/mcp-apps/utils.d.ts.map +1 -1
  97. package/dist/model-context/frame/useAssistantFrameHost.d.ts +1 -6
  98. package/dist/model-context/frame/useAssistantFrameHost.d.ts.map +1 -1
  99. package/dist/model-context/makeAssistantVisible.d.ts +0 -1
  100. package/dist/model-context/makeAssistantVisible.d.ts.map +1 -1
  101. package/dist/model-context/makeAssistantVisible.js +7 -1
  102. package/dist/model-context/makeAssistantVisible.js.map +1 -1
  103. package/dist/primitives/actionBar/ActionBarCopy.d.ts +1 -4
  104. package/dist/primitives/actionBar/ActionBarCopy.d.ts.map +1 -1
  105. package/dist/primitives/actionBar/ActionBarEdit.d.ts +0 -1
  106. package/dist/primitives/actionBar/ActionBarEdit.d.ts.map +1 -1
  107. package/dist/primitives/actionBar/ActionBarExportMarkdown.d.ts +1 -5
  108. package/dist/primitives/actionBar/ActionBarExportMarkdown.d.ts.map +1 -1
  109. package/dist/primitives/actionBar/ActionBarFeedbackNegative.d.ts +0 -1
  110. package/dist/primitives/actionBar/ActionBarFeedbackNegative.d.ts.map +1 -1
  111. package/dist/primitives/actionBar/ActionBarFeedbackPositive.d.ts +0 -1
  112. package/dist/primitives/actionBar/ActionBarFeedbackPositive.d.ts.map +1 -1
  113. package/dist/primitives/actionBar/ActionBarInteractionContext.d.ts.map +1 -1
  114. package/dist/primitives/actionBar/ActionBarReload.d.ts +0 -1
  115. package/dist/primitives/actionBar/ActionBarReload.d.ts.map +1 -1
  116. package/dist/primitives/actionBar/ActionBarRoot.d.ts +0 -1
  117. package/dist/primitives/actionBar/ActionBarRoot.d.ts.map +1 -1
  118. package/dist/primitives/actionBar/ActionBarRoot.js.map +1 -1
  119. package/dist/primitives/actionBar/ActionBarSpeak.d.ts +0 -1
  120. package/dist/primitives/actionBar/ActionBarSpeak.d.ts.map +1 -1
  121. package/dist/primitives/actionBar/ActionBarStopSpeaking.d.ts +0 -1
  122. package/dist/primitives/actionBar/ActionBarStopSpeaking.d.ts.map +1 -1
  123. package/dist/primitives/actionBar/useActionBarFloatStatus.d.ts +1 -6
  124. package/dist/primitives/actionBar/useActionBarFloatStatus.d.ts.map +1 -1
  125. package/dist/primitives/actionBar.d.ts +0 -2
  126. package/dist/primitives/actionBarMore/ActionBarMoreContent.d.ts +0 -1
  127. package/dist/primitives/actionBarMore/ActionBarMoreContent.d.ts.map +1 -1
  128. package/dist/primitives/actionBarMore/ActionBarMoreContent.js.map +1 -1
  129. package/dist/primitives/actionBarMore/ActionBarMoreItem.d.ts +0 -1
  130. package/dist/primitives/actionBarMore/ActionBarMoreItem.d.ts.map +1 -1
  131. package/dist/primitives/actionBarMore/ActionBarMoreRoot.d.ts +0 -1
  132. package/dist/primitives/actionBarMore/ActionBarMoreRoot.d.ts.map +1 -1
  133. package/dist/primitives/actionBarMore/ActionBarMoreSeparator.d.ts +0 -1
  134. package/dist/primitives/actionBarMore/ActionBarMoreSeparator.d.ts.map +1 -1
  135. package/dist/primitives/actionBarMore/ActionBarMoreTrigger.d.ts +0 -1
  136. package/dist/primitives/actionBarMore/ActionBarMoreTrigger.d.ts.map +1 -1
  137. package/dist/primitives/actionBarMore/scope.d.ts +0 -1
  138. package/dist/primitives/actionBarMore/scope.d.ts.map +1 -1
  139. package/dist/primitives/actionBarMore.d.ts +0 -2
  140. package/dist/primitives/assistantModal/AssistantModalAnchor.d.ts +6 -4
  141. package/dist/primitives/assistantModal/AssistantModalAnchor.d.ts.map +1 -1
  142. package/dist/primitives/assistantModal/AssistantModalAnchor.js +2 -2
  143. package/dist/primitives/assistantModal/AssistantModalAnchor.js.map +1 -1
  144. package/dist/primitives/assistantModal/AssistantModalContent.d.ts +4 -2
  145. package/dist/primitives/assistantModal/AssistantModalContent.d.ts.map +1 -1
  146. package/dist/primitives/assistantModal/AssistantModalContent.js +2 -1
  147. package/dist/primitives/assistantModal/AssistantModalContent.js.map +1 -1
  148. package/dist/primitives/assistantModal/AssistantModalRoot.d.ts +0 -1
  149. package/dist/primitives/assistantModal/AssistantModalRoot.d.ts.map +1 -1
  150. package/dist/primitives/assistantModal/AssistantModalTrigger.d.ts +6 -4
  151. package/dist/primitives/assistantModal/AssistantModalTrigger.d.ts.map +1 -1
  152. package/dist/primitives/assistantModal/AssistantModalTrigger.js +2 -2
  153. package/dist/primitives/assistantModal/AssistantModalTrigger.js.map +1 -1
  154. package/dist/primitives/assistantModal/popoverRenderPrimitives.d.ts +14 -0
  155. package/dist/primitives/assistantModal/popoverRenderPrimitives.d.ts.map +1 -0
  156. package/dist/primitives/assistantModal/popoverRenderPrimitives.js +10 -0
  157. package/dist/primitives/assistantModal/popoverRenderPrimitives.js.map +1 -0
  158. package/dist/primitives/assistantModal/scope.d.ts +0 -1
  159. package/dist/primitives/assistantModal/scope.d.ts.map +1 -1
  160. package/dist/primitives/assistantModal.d.ts +0 -2
  161. package/dist/primitives/attachment/AttachmentName.d.ts +0 -1
  162. package/dist/primitives/attachment/AttachmentName.d.ts.map +1 -1
  163. package/dist/primitives/attachment/AttachmentRemove.d.ts +0 -1
  164. package/dist/primitives/attachment/AttachmentRemove.d.ts.map +1 -1
  165. package/dist/primitives/attachment/AttachmentRoot.d.ts +0 -1
  166. package/dist/primitives/attachment/AttachmentRoot.d.ts.map +1 -1
  167. package/dist/primitives/attachment/AttachmentThumb.d.ts +0 -1
  168. package/dist/primitives/attachment/AttachmentThumb.d.ts.map +1 -1
  169. package/dist/primitives/attachment/AttachmentThumb.js.map +1 -1
  170. package/dist/primitives/attachment.d.ts +0 -2
  171. package/dist/primitives/branchPicker/BranchPickerCount.d.ts +0 -1
  172. package/dist/primitives/branchPicker/BranchPickerCount.d.ts.map +1 -1
  173. package/dist/primitives/branchPicker/BranchPickerNext.d.ts +0 -1
  174. package/dist/primitives/branchPicker/BranchPickerNext.d.ts.map +1 -1
  175. package/dist/primitives/branchPicker/BranchPickerNumber.d.ts +0 -1
  176. package/dist/primitives/branchPicker/BranchPickerNumber.d.ts.map +1 -1
  177. package/dist/primitives/branchPicker/BranchPickerPrevious.d.ts +0 -1
  178. package/dist/primitives/branchPicker/BranchPickerPrevious.d.ts.map +1 -1
  179. package/dist/primitives/branchPicker/BranchPickerRoot.d.ts +0 -1
  180. package/dist/primitives/branchPicker/BranchPickerRoot.d.ts.map +1 -1
  181. package/dist/primitives/branchPicker/BranchPickerRoot.js.map +1 -1
  182. package/dist/primitives/branchPicker.d.ts +0 -2
  183. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.d.ts +0 -1
  184. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.d.ts.map +1 -1
  185. package/dist/primitives/chainOfThought/ChainOfThoughtRoot.d.ts +0 -1
  186. package/dist/primitives/chainOfThought/ChainOfThoughtRoot.d.ts.map +1 -1
  187. package/dist/primitives/chainOfThought.d.ts +0 -2
  188. package/dist/primitives/composer/ComposerAddAttachment.d.ts +5 -6
  189. package/dist/primitives/composer/ComposerAddAttachment.d.ts.map +1 -1
  190. package/dist/primitives/composer/ComposerAttachmentDropzone.d.ts +0 -1
  191. package/dist/primitives/composer/ComposerAttachmentDropzone.d.ts.map +1 -1
  192. package/dist/primitives/composer/ComposerAttachmentDropzone.js.map +1 -1
  193. package/dist/primitives/composer/ComposerCancel.d.ts +0 -1
  194. package/dist/primitives/composer/ComposerCancel.d.ts.map +1 -1
  195. package/dist/primitives/composer/ComposerCompactContext.d.ts +9 -0
  196. package/dist/primitives/composer/ComposerCompactContext.d.ts.map +1 -0
  197. package/dist/primitives/composer/ComposerCompactContext.js +11 -0
  198. package/dist/primitives/composer/ComposerCompactContext.js.map +1 -0
  199. package/dist/primitives/composer/ComposerDictate.d.ts +0 -1
  200. package/dist/primitives/composer/ComposerDictate.d.ts.map +1 -1
  201. package/dist/primitives/composer/ComposerDictationTranscript.d.ts +0 -1
  202. package/dist/primitives/composer/ComposerDictationTranscript.d.ts.map +1 -1
  203. package/dist/primitives/composer/ComposerDictationTranscript.js.map +1 -1
  204. package/dist/primitives/composer/ComposerInput.d.ts +0 -1
  205. package/dist/primitives/composer/ComposerInput.d.ts.map +1 -1
  206. package/dist/primitives/composer/ComposerInput.js +17 -2
  207. package/dist/primitives/composer/ComposerInput.js.map +1 -1
  208. package/dist/primitives/composer/ComposerInputPluginContext.d.ts +4 -3
  209. package/dist/primitives/composer/ComposerInputPluginContext.d.ts.map +1 -1
  210. package/dist/primitives/composer/ComposerQuote.d.ts +0 -1
  211. package/dist/primitives/composer/ComposerQuote.d.ts.map +1 -1
  212. package/dist/primitives/composer/ComposerQuote.js.map +1 -1
  213. package/dist/primitives/composer/ComposerRoot.d.ts +27 -3
  214. package/dist/primitives/composer/ComposerRoot.d.ts.map +1 -1
  215. package/dist/primitives/composer/ComposerRoot.js +109 -30
  216. package/dist/primitives/composer/ComposerRoot.js.map +1 -1
  217. package/dist/primitives/composer/ComposerSend.d.ts +0 -1
  218. package/dist/primitives/composer/ComposerSend.d.ts.map +1 -1
  219. package/dist/primitives/composer/ComposerStopDictation.d.ts +0 -1
  220. package/dist/primitives/composer/ComposerStopDictation.d.ts.map +1 -1
  221. package/dist/primitives/composer/trigger/TriggerPopover.d.ts +10 -5
  222. package/dist/primitives/composer/trigger/TriggerPopover.d.ts.map +1 -1
  223. package/dist/primitives/composer/trigger/TriggerPopover.js.map +1 -1
  224. package/dist/primitives/composer/trigger/TriggerPopoverAction.d.ts +5 -3
  225. package/dist/primitives/composer/trigger/TriggerPopoverAction.d.ts.map +1 -1
  226. package/dist/primitives/composer/trigger/TriggerPopoverAction.js +3 -2
  227. package/dist/primitives/composer/trigger/TriggerPopoverAction.js.map +1 -1
  228. package/dist/primitives/composer/trigger/TriggerPopoverBack.d.ts +0 -1
  229. package/dist/primitives/composer/trigger/TriggerPopoverBack.d.ts.map +1 -1
  230. package/dist/primitives/composer/trigger/TriggerPopoverCategories.d.ts +0 -1
  231. package/dist/primitives/composer/trigger/TriggerPopoverCategories.d.ts.map +1 -1
  232. package/dist/primitives/composer/trigger/TriggerPopoverCategories.js.map +1 -1
  233. package/dist/primitives/composer/trigger/TriggerPopoverDirective.d.ts +3 -2
  234. package/dist/primitives/composer/trigger/TriggerPopoverDirective.d.ts.map +1 -1
  235. package/dist/primitives/composer/trigger/TriggerPopoverItems.d.ts +0 -1
  236. package/dist/primitives/composer/trigger/TriggerPopoverItems.d.ts.map +1 -1
  237. package/dist/primitives/composer/trigger/TriggerPopoverItems.js.map +1 -1
  238. package/dist/primitives/composer/trigger/TriggerPopoverResource.d.ts +10 -6
  239. package/dist/primitives/composer/trigger/TriggerPopoverResource.d.ts.map +1 -1
  240. package/dist/primitives/composer/trigger/TriggerPopoverRootContext.d.ts +8 -5
  241. package/dist/primitives/composer/trigger/TriggerPopoverRootContext.d.ts.map +1 -1
  242. package/dist/primitives/composer/trigger/TriggerPopoverRootContext.js.map +1 -1
  243. package/dist/primitives/composer/trigger/detectTrigger.d.ts +1 -1
  244. package/dist/primitives/composer/trigger/index.d.ts +0 -1
  245. package/dist/primitives/composer/trigger/index.d.ts.map +1 -1
  246. package/dist/primitives/composer/trigger/triggerDetectionResource.d.ts +5 -2
  247. package/dist/primitives/composer/trigger/triggerDetectionResource.d.ts.map +1 -1
  248. package/dist/primitives/composer/trigger/triggerKeyboardResource.d.ts +7 -4
  249. package/dist/primitives/composer/trigger/triggerKeyboardResource.d.ts.map +1 -1
  250. package/dist/primitives/composer/trigger/triggerNavigationResource.d.ts +13 -7
  251. package/dist/primitives/composer/trigger/triggerNavigationResource.d.ts.map +1 -1
  252. package/dist/primitives/composer/trigger/triggerSelectionResource.d.ts +7 -4
  253. package/dist/primitives/composer/trigger/triggerSelectionResource.d.ts.map +1 -1
  254. package/dist/primitives/composer/useComposerInputState.d.ts.map +1 -1
  255. package/dist/primitives/composer.d.ts +0 -2
  256. package/dist/primitives/dropdownMenuRenderPrimitives.d.ts +0 -1
  257. package/dist/primitives/dropdownMenuRenderPrimitives.d.ts.map +1 -1
  258. package/dist/primitives/error/ErrorMessage.d.ts +0 -1
  259. package/dist/primitives/error/ErrorMessage.d.ts.map +1 -1
  260. package/dist/primitives/error/ErrorMessage.js.map +1 -1
  261. package/dist/primitives/error/ErrorRoot.d.ts +0 -1
  262. package/dist/primitives/error/ErrorRoot.d.ts.map +1 -1
  263. package/dist/primitives/error.d.ts +0 -2
  264. package/dist/primitives/message/MessageError.d.ts +0 -1
  265. package/dist/primitives/message/MessageError.d.ts.map +1 -1
  266. package/dist/primitives/message/MessageIf.d.ts +0 -1
  267. package/dist/primitives/message/MessageIf.d.ts.map +1 -1
  268. package/dist/primitives/message/MessageParts.d.ts +0 -1
  269. package/dist/primitives/message/MessageParts.d.ts.map +1 -1
  270. package/dist/primitives/message/MessageParts.js.map +1 -1
  271. package/dist/primitives/message/MessagePartsGrouped.d.ts +25 -12
  272. package/dist/primitives/message/MessagePartsGrouped.d.ts.map +1 -1
  273. package/dist/primitives/message/MessagePartsGrouped.js.map +1 -1
  274. package/dist/primitives/message/MessageRoot.d.ts +0 -1
  275. package/dist/primitives/message/MessageRoot.d.ts.map +1 -1
  276. package/dist/primitives/message.d.ts +0 -2
  277. package/dist/primitives/messagePart/MessagePartImage.d.ts +0 -1
  278. package/dist/primitives/messagePart/MessagePartImage.d.ts.map +1 -1
  279. package/dist/primitives/messagePart/MessagePartText.d.ts +0 -1
  280. package/dist/primitives/messagePart/MessagePartText.d.ts.map +1 -1
  281. package/dist/primitives/messagePart/MessagePartText.js.map +1 -1
  282. package/dist/primitives/messagePart/useMessagePartData.d.ts +3 -3
  283. package/dist/primitives/messagePart/useMessagePartData.d.ts.map +1 -1
  284. package/dist/primitives/messagePart/useMessagePartData.js +3 -2
  285. package/dist/primitives/messagePart/useMessagePartData.js.map +1 -1
  286. package/dist/primitives/messagePart/useMessagePartFile.d.ts +5 -5
  287. package/dist/primitives/messagePart/useMessagePartFile.d.ts.map +1 -1
  288. package/dist/primitives/messagePart/useMessagePartFile.js +11 -3
  289. package/dist/primitives/messagePart/useMessagePartFile.js.map +1 -1
  290. package/dist/primitives/messagePart/useMessagePartImage.d.ts +5 -5
  291. package/dist/primitives/messagePart/useMessagePartImage.d.ts.map +1 -1
  292. package/dist/primitives/messagePart/useMessagePartImage.js +10 -3
  293. package/dist/primitives/messagePart/useMessagePartImage.js.map +1 -1
  294. package/dist/primitives/messagePart/useMessagePartReasoning.d.ts +5 -5
  295. package/dist/primitives/messagePart/useMessagePartReasoning.d.ts.map +1 -1
  296. package/dist/primitives/messagePart/useMessagePartReasoning.js +10 -3
  297. package/dist/primitives/messagePart/useMessagePartReasoning.js.map +1 -1
  298. package/dist/primitives/messagePart/useMessagePartSource.d.ts +6 -4
  299. package/dist/primitives/messagePart/useMessagePartSource.d.ts.map +1 -1
  300. package/dist/primitives/messagePart/useMessagePartSource.js +12 -3
  301. package/dist/primitives/messagePart/useMessagePartSource.js.map +1 -1
  302. package/dist/primitives/messagePart/useMessagePartText.d.ts +6 -6
  303. package/dist/primitives/messagePart/useMessagePartText.d.ts.map +1 -1
  304. package/dist/primitives/messagePart/useMessagePartText.js +10 -3
  305. package/dist/primitives/messagePart/useMessagePartText.js.map +1 -1
  306. package/dist/primitives/messagePart.d.ts +0 -2
  307. package/dist/primitives/queueItem/QueueItemRemove.d.ts +0 -1
  308. package/dist/primitives/queueItem/QueueItemRemove.d.ts.map +1 -1
  309. package/dist/primitives/queueItem/QueueItemSteer.d.ts +0 -1
  310. package/dist/primitives/queueItem/QueueItemSteer.d.ts.map +1 -1
  311. package/dist/primitives/queueItem/QueueItemText.d.ts +0 -1
  312. package/dist/primitives/queueItem/QueueItemText.d.ts.map +1 -1
  313. package/dist/primitives/queueItem/QueueItemText.js.map +1 -1
  314. package/dist/primitives/queueItem.d.ts +0 -2
  315. package/dist/primitives/reasoning/useScrollLock.d.ts +0 -1
  316. package/dist/primitives/reasoning/useScrollLock.d.ts.map +1 -1
  317. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.d.ts +0 -1
  318. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.d.ts.map +1 -1
  319. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.d.ts +0 -1
  320. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.d.ts.map +1 -1
  321. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js +2 -1
  322. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js.map +1 -1
  323. package/dist/primitives/selectionToolbar.d.ts +0 -2
  324. package/dist/primitives/suggestion/SuggestionDescription.d.ts +0 -1
  325. package/dist/primitives/suggestion/SuggestionDescription.d.ts.map +1 -1
  326. package/dist/primitives/suggestion/SuggestionDescription.js.map +1 -1
  327. package/dist/primitives/suggestion/SuggestionTitle.d.ts +0 -1
  328. package/dist/primitives/suggestion/SuggestionTitle.d.ts.map +1 -1
  329. package/dist/primitives/suggestion/SuggestionTitle.js.map +1 -1
  330. package/dist/primitives/suggestion/SuggestionTrigger.d.ts +1 -5
  331. package/dist/primitives/suggestion/SuggestionTrigger.d.ts.map +1 -1
  332. package/dist/primitives/suggestion.d.ts +0 -2
  333. package/dist/primitives/thread/ThreadEmpty.d.ts +0 -1
  334. package/dist/primitives/thread/ThreadEmpty.d.ts.map +1 -1
  335. package/dist/primitives/thread/ThreadIf.d.ts +0 -1
  336. package/dist/primitives/thread/ThreadIf.d.ts.map +1 -1
  337. package/dist/primitives/thread/ThreadRoot.d.ts +0 -1
  338. package/dist/primitives/thread/ThreadRoot.d.ts.map +1 -1
  339. package/dist/primitives/thread/ThreadScrollToBottom.d.ts +1 -4
  340. package/dist/primitives/thread/ThreadScrollToBottom.d.ts.map +1 -1
  341. package/dist/primitives/thread/ThreadSuggestion.d.ts +13 -14
  342. package/dist/primitives/thread/ThreadSuggestion.d.ts.map +1 -1
  343. package/dist/primitives/thread/ThreadViewport.d.ts +0 -1
  344. package/dist/primitives/thread/ThreadViewport.d.ts.map +1 -1
  345. package/dist/primitives/thread/ThreadViewport.js +53 -19
  346. package/dist/primitives/thread/ThreadViewport.js.map +1 -1
  347. package/dist/primitives/thread/ThreadViewportFooter.d.ts +0 -1
  348. package/dist/primitives/thread/ThreadViewportFooter.d.ts.map +1 -1
  349. package/dist/primitives/thread/topAnchor/computeTopAnchorSlack.d.ts +2 -11
  350. package/dist/primitives/thread/topAnchor/computeTopAnchorSlack.d.ts.map +1 -1
  351. package/dist/primitives/thread/topAnchor/createReserveObservers.d.ts.map +1 -1
  352. package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.d.ts +4 -0
  353. package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.d.ts.map +1 -1
  354. package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.js +14 -1
  355. package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.js.map +1 -1
  356. package/dist/primitives/thread/topAnchor/topAnchorTurn.d.ts +14 -5
  357. package/dist/primitives/thread/topAnchor/topAnchorTurn.d.ts.map +1 -1
  358. package/dist/primitives/thread/topAnchor/topAnchorTurn.js +14 -1
  359. package/dist/primitives/thread/topAnchor/topAnchorTurn.js.map +1 -1
  360. package/dist/primitives/thread/topAnchor/topAnchorUtils.d.ts.map +1 -1
  361. package/dist/primitives/thread/topAnchor/useTopAnchorReserve.d.ts.map +1 -1
  362. package/dist/primitives/thread/useThreadViewportAutoScroll.d.ts +1 -7
  363. package/dist/primitives/thread/useThreadViewportAutoScroll.d.ts.map +1 -1
  364. package/dist/primitives/thread/useThreadViewportAutoScroll.js +2 -1
  365. package/dist/primitives/thread/useThreadViewportAutoScroll.js.map +1 -1
  366. package/dist/primitives/thread.d.ts +0 -2
  367. package/dist/primitives/threadList/ThreadListLoadMore.d.ts +0 -1
  368. package/dist/primitives/threadList/ThreadListLoadMore.d.ts.map +1 -1
  369. package/dist/primitives/threadList/ThreadListNew.d.ts +0 -1
  370. package/dist/primitives/threadList/ThreadListNew.d.ts.map +1 -1
  371. package/dist/primitives/threadList/ThreadListRoot.d.ts +0 -1
  372. package/dist/primitives/threadList/ThreadListRoot.d.ts.map +1 -1
  373. package/dist/primitives/threadList/ThreadListRoot.js.map +1 -1
  374. package/dist/primitives/threadList.d.ts +0 -2
  375. package/dist/primitives/threadListFocusGroup.d.ts +0 -1
  376. package/dist/primitives/threadListFocusGroup.d.ts.map +1 -1
  377. package/dist/primitives/threadListItem/ThreadListItemArchive.d.ts +0 -1
  378. package/dist/primitives/threadListItem/ThreadListItemArchive.d.ts.map +1 -1
  379. package/dist/primitives/threadListItem/ThreadListItemDelete.d.ts +0 -1
  380. package/dist/primitives/threadListItem/ThreadListItemDelete.d.ts.map +1 -1
  381. package/dist/primitives/threadListItem/ThreadListItemRoot.d.ts +0 -1
  382. package/dist/primitives/threadListItem/ThreadListItemRoot.d.ts.map +1 -1
  383. package/dist/primitives/threadListItem/ThreadListItemRoot.js.map +1 -1
  384. package/dist/primitives/threadListItem/ThreadListItemTrigger.d.ts +0 -1
  385. package/dist/primitives/threadListItem/ThreadListItemTrigger.d.ts.map +1 -1
  386. package/dist/primitives/threadListItem/ThreadListItemTrigger.js.map +1 -1
  387. package/dist/primitives/threadListItem/ThreadListItemUnarchive.d.ts +0 -1
  388. package/dist/primitives/threadListItem/ThreadListItemUnarchive.d.ts.map +1 -1
  389. package/dist/primitives/threadListItem.d.ts +0 -2
  390. package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.d.ts +0 -1
  391. package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.d.ts.map +1 -1
  392. package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.js.map +1 -1
  393. package/dist/primitives/threadListItemMore/ThreadListItemMoreItem.d.ts +0 -1
  394. package/dist/primitives/threadListItemMore/ThreadListItemMoreItem.d.ts.map +1 -1
  395. package/dist/primitives/threadListItemMore/ThreadListItemMoreRoot.d.ts +0 -1
  396. package/dist/primitives/threadListItemMore/ThreadListItemMoreRoot.d.ts.map +1 -1
  397. package/dist/primitives/threadListItemMore/ThreadListItemMoreRoot.js.map +1 -1
  398. package/dist/primitives/threadListItemMore/ThreadListItemMoreSeparator.d.ts +0 -1
  399. package/dist/primitives/threadListItemMore/ThreadListItemMoreSeparator.d.ts.map +1 -1
  400. package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.d.ts +0 -1
  401. package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.d.ts.map +1 -1
  402. package/dist/primitives/threadListItemMore/scope.d.ts +0 -1
  403. package/dist/primitives/threadListItemMore/scope.d.ts.map +1 -1
  404. package/dist/primitives/threadListItemMore.d.ts +0 -2
  405. package/dist/sandbox-host/SandboxHost.d.ts +1 -10
  406. package/dist/sandbox-host/SandboxHost.d.ts.map +1 -1
  407. package/dist/tests/remote-thread-list-test-helpers.d.ts +0 -1
  408. package/dist/tests/remote-thread-list-test-helpers.d.ts.map +1 -1
  409. package/dist/tests/setup.d.ts +1 -1
  410. package/dist/unstable/useComposerInput.d.ts +2 -2
  411. package/dist/unstable/useComposerInput.d.ts.map +1 -1
  412. package/dist/unstable/useComposerInputHistory.d.ts +2 -2
  413. package/dist/unstable/useComposerInputHistory.d.ts.map +1 -1
  414. package/dist/unstable/useLiveCompletionAdapter.d.ts +4 -3
  415. package/dist/unstable/useLiveCompletionAdapter.d.ts.map +1 -1
  416. package/dist/unstable/useMentionAdapter.d.ts +19 -10
  417. package/dist/unstable/useMentionAdapter.d.ts.map +1 -1
  418. package/dist/unstable/useMessageStallDetection.d.ts +3 -1
  419. package/dist/unstable/useMessageStallDetection.d.ts.map +1 -1
  420. package/dist/unstable/useSlashCommandAdapter.d.ts +6 -4
  421. package/dist/unstable/useSlashCommandAdapter.d.ts.map +1 -1
  422. package/dist/utils/Primitive.d.ts +0 -1
  423. package/dist/utils/Primitive.d.ts.map +1 -1
  424. package/dist/utils/Primitive.js.map +1 -1
  425. package/dist/utils/RequireAtLeastOne.d.ts +1 -1
  426. package/dist/utils/RequireAtLeastOne.d.ts.map +1 -1
  427. package/dist/utils/createActionButton.d.ts +0 -1
  428. package/dist/utils/createActionButton.d.ts.map +1 -1
  429. package/dist/utils/getSelectionMessageId.d.ts.map +1 -1
  430. package/dist/utils/getSelectionMessageId.js +32 -7
  431. package/dist/utils/getSelectionMessageId.js.map +1 -1
  432. package/dist/utils/hooks/useManagedRef.d.ts.map +1 -1
  433. package/dist/utils/hooks/useMediaQuery.d.ts.map +1 -1
  434. package/dist/utils/hooks/useOnResizeContent.d.ts.map +1 -1
  435. package/dist/utils/hooks/useOnScrollToBottom.d.ts.map +1 -1
  436. package/dist/utils/hooks/useSizeHandle.d.ts +0 -1
  437. package/dist/utils/hooks/useSizeHandle.d.ts.map +1 -1
  438. package/dist/utils/smooth/SmoothContext.d.ts +71 -72
  439. package/dist/utils/smooth/SmoothContext.d.ts.map +1 -1
  440. package/dist/utils/smooth/useSmooth.d.ts +0 -1
  441. package/dist/utils/smooth/useSmooth.d.ts.map +1 -1
  442. package/dist/utils/useToolArgsFieldStatus.d.ts +2 -2
  443. package/dist/utils/useToolArgsFieldStatus.d.ts.map +1 -1
  444. package/package.json +23 -23
  445. package/src/client/ExternalThread.ts +2 -1
  446. package/src/index.ts +3 -0
  447. package/src/legacy-runtime/cloud/auiV0.ts +72 -3
  448. package/src/mcp-apps/McpAppRenderer.test.tsx +141 -0
  449. package/src/mcp-apps/McpAppRenderer.tsx +48 -10
  450. package/src/mcp-apps/McpAppsRemoteHost.test.ts +126 -0
  451. package/src/mcp-apps/McpAppsRemoteHost.ts +40 -1
  452. package/src/mcp-apps/app-frame.tsx +3 -1
  453. package/src/mcp-apps/bridge.ts +1 -1
  454. package/src/mcp-apps/types.ts +16 -8
  455. package/src/model-context/makeAssistantVisible.test.tsx +146 -0
  456. package/src/model-context/makeAssistantVisible.tsx +18 -1
  457. package/src/primitives/assistantModal/AssistantModalAnchor.tsx +6 -8
  458. package/src/primitives/assistantModal/AssistantModalContent.tsx +5 -5
  459. package/src/primitives/assistantModal/AssistantModalTrigger.test.tsx +80 -0
  460. package/src/primitives/assistantModal/AssistantModalTrigger.tsx +6 -8
  461. package/src/primitives/assistantModal/popoverRenderPrimitives.ts +6 -0
  462. package/src/primitives/composer/ComposerCompactContext.tsx +13 -0
  463. package/src/primitives/composer/ComposerInput.tsx +35 -0
  464. package/src/primitives/composer/ComposerRoot.test.tsx +382 -0
  465. package/src/primitives/composer/ComposerRoot.tsx +86 -7
  466. package/src/primitives/messagePart/useMessagePartData.ts +3 -2
  467. package/src/primitives/messagePart/useMessagePartFile.ts +19 -7
  468. package/src/primitives/messagePart/useMessagePartImage.ts +18 -7
  469. package/src/primitives/messagePart/useMessagePartReasoning.ts +15 -6
  470. package/src/primitives/messagePart/useMessagePartSource.ts +20 -7
  471. package/src/primitives/messagePart/useMessagePartText.ts +15 -5
  472. package/src/primitives/thread/ThreadViewport.tsx +15 -0
  473. package/src/primitives/thread/topAnchor/mountTopAnchorReserve.test.ts +243 -0
  474. package/src/primitives/thread/topAnchor/mountTopAnchorReserve.ts +28 -7
  475. package/src/primitives/thread/topAnchor/topAnchorTurn.test.ts +69 -0
  476. package/src/primitives/thread/topAnchor/topAnchorTurn.ts +29 -0
  477. package/src/primitives/thread/useThreadViewportAutoScroll.test.tsx +86 -1
  478. package/src/primitives/thread/useThreadViewportAutoScroll.ts +6 -1
  479. package/src/tests/BaseComposerRuntimeCore.test.ts +12 -3
  480. package/src/tests/LocalThreadRuntimeCore.test.ts +4 -1
  481. package/src/tests/auiV0Encode.test.ts +134 -1
  482. package/src/tests/external-thread-attachments.test.tsx +81 -0
  483. package/src/tests/messagePartSwitchRace.test.tsx +158 -0
  484. package/src/tests/messagePartTypeMismatch.test.tsx +146 -0
  485. package/src/utils/getSelectionMessageId.test.ts +175 -0
  486. package/src/utils/getSelectionMessageId.ts +57 -6
  487. package/dist/utils/json/is-json-equal.d.ts +0 -5
  488. package/dist/utils/json/is-json-equal.d.ts.map +0 -1
  489. package/dist/utils/json/is-json-equal.js +0 -26
  490. package/dist/utils/json/is-json-equal.js.map +0 -1
  491. package/dist/utils/json/is-json.d.ts +0 -10
  492. package/dist/utils/json/is-json.d.ts.map +0 -1
  493. package/dist/utils/json/is-json.js +0 -22
  494. package/dist/utils/json/is-json.js.map +0 -1
  495. package/src/utils/json/is-json-equal.ts +0 -48
  496. package/src/utils/json/is-json.ts +0 -58
@@ -0,0 +1,146 @@
1
+ // @vitest-environment jsdom
2
+
3
+ import { type FC, type PropsWithChildren, type ReactNode } from "react";
4
+ import { render, screen } from "@testing-library/react";
5
+ import { describe, expect, it } from "vitest";
6
+ import { AssistantRuntimeProvider } from "../context";
7
+ import * as MessagePartPrimitive from "../primitives/messagePart";
8
+ import * as MessagePrimitive from "../primitives/message";
9
+ import * as ThreadPrimitive from "../primitives/thread";
10
+ import { useLocalRuntime } from "../legacy-runtime/runtime-cores/local/useLocalRuntime";
11
+ import {
12
+ useMessagePartReasoning,
13
+ useMessagePartSource,
14
+ useMessagePartFile,
15
+ type ChatModelAdapter,
16
+ type ThreadMessageLike,
17
+ } from "../index";
18
+
19
+ const noOpAdapter: ChatModelAdapter = {
20
+ async *run() {},
21
+ };
22
+
23
+ // A thread whose only assistant message has a single tool-call part at index 0.
24
+ // During a thread switch, a still-mounted text/image/reasoning/source/file
25
+ // consumer at (0, 0) re-resolves its index-derived part scope against the new
26
+ // thread and reads this tool-call part, so its selector must not throw inside
27
+ // useSyncExternalStore's getSnapshot (#5118).
28
+ const toolCallOnly: ThreadMessageLike[] = [
29
+ {
30
+ role: "assistant",
31
+ content: [
32
+ {
33
+ type: "tool-call",
34
+ toolCallId: "tc-1",
35
+ toolName: "search",
36
+ args: {},
37
+ argsText: "{}",
38
+ },
39
+ ],
40
+ status: { type: "complete", reason: "stop" },
41
+ },
42
+ ];
43
+
44
+ const RuntimeProvider: FC<
45
+ PropsWithChildren<{ messages: ThreadMessageLike[] }>
46
+ > = ({ messages, children }) => {
47
+ const runtime = useLocalRuntime(noOpAdapter, { initialMessages: messages });
48
+ return (
49
+ <AssistantRuntimeProvider runtime={runtime}>
50
+ {children}
51
+ </AssistantRuntimeProvider>
52
+ );
53
+ };
54
+
55
+ // Renders a part consumer under a Message whose parts always render it,
56
+ // regardless of the part type. This mounts the consumer inside the part scope
57
+ // at index 0, where it reads the tool-call part — the transient state a
58
+ // thread switch produces for a still-mounted consumer.
59
+ const MessageWith: FC<{ renderPart: () => ReactNode }> = ({ renderPart }) => (
60
+ <MessagePrimitive.Parts>{() => renderPart()}</MessagePrimitive.Parts>
61
+ );
62
+
63
+ const renderToolCallMessage = (renderPart: () => ReactNode) => {
64
+ const Message: FC = () => <MessageWith renderPart={renderPart} />;
65
+ render(
66
+ <RuntimeProvider messages={toolCallOnly}>
67
+ <ThreadPrimitive.Messages components={{ Message }} />
68
+ </RuntimeProvider>,
69
+ );
70
+ };
71
+
72
+ describe("part hooks tolerate a transient part-type mismatch (#5118)", () => {
73
+ it("MessagePartPrimitive.Text renders empty when the part is a tool-call", async () => {
74
+ renderToolCallMessage(() => (
75
+ <MessagePartPrimitive.Text data-testid="text" />
76
+ ));
77
+
78
+ const text = await screen.findByTestId("text");
79
+ expect(text.textContent).toBe("");
80
+ });
81
+
82
+ it("MessagePartPrimitive.Image renders an empty image when the part is a tool-call", async () => {
83
+ renderToolCallMessage(() => (
84
+ <MessagePartPrimitive.Image data-testid="image" alt="" />
85
+ ));
86
+
87
+ const image = await screen.findByTestId("image");
88
+ expect(image.tagName).toBe("IMG");
89
+ });
90
+
91
+ it("useMessagePartReasoning returns an empty reasoning part when the part is a tool-call", async () => {
92
+ const Reader: FC = () => {
93
+ const part = useMessagePartReasoning();
94
+ return <span data-testid="reasoning">{part.text}</span>;
95
+ };
96
+ renderToolCallMessage(() => <Reader />);
97
+
98
+ const reasoning = await screen.findByTestId("reasoning");
99
+ expect(reasoning.textContent).toBe("");
100
+ });
101
+
102
+ it("useMessagePartSource returns an empty source part when the part is a tool-call", async () => {
103
+ const Reader: FC = () => {
104
+ const part = useMessagePartSource();
105
+ return <span data-testid="source">{part.sourceType}</span>;
106
+ };
107
+ renderToolCallMessage(() => <Reader />);
108
+
109
+ const source = await screen.findByTestId("source");
110
+ expect(source.textContent).toBe("url");
111
+ });
112
+
113
+ it("useMessagePartFile returns an empty file part when the part is a tool-call", async () => {
114
+ const Reader: FC = () => {
115
+ const part = useMessagePartFile();
116
+ return <span data-testid="file">{part.mimeType}</span>;
117
+ };
118
+ renderToolCallMessage(() => <Reader />);
119
+
120
+ const file = await screen.findByTestId("file");
121
+ expect(file.textContent).toBe("");
122
+ });
123
+
124
+ it("a real text part still renders its text (no regression in the happy path)", async () => {
125
+ const textMessage: ThreadMessageLike[] = [
126
+ {
127
+ role: "assistant",
128
+ content: [{ type: "text", text: "hello" }],
129
+ status: { type: "complete", reason: "stop" },
130
+ },
131
+ ];
132
+ const Message: FC = () => (
133
+ <MessageWith
134
+ renderPart={() => <MessagePartPrimitive.Text data-testid="text" />}
135
+ />
136
+ );
137
+ render(
138
+ <RuntimeProvider messages={textMessage}>
139
+ <ThreadPrimitive.Messages components={{ Message }} />
140
+ </RuntimeProvider>,
141
+ );
142
+
143
+ const text = await screen.findByTestId("text");
144
+ expect(text.textContent).toBe("hello");
145
+ });
146
+ });
@@ -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
  };
@@ -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,48 +0,0 @@
1
- import type { ReadonlyJSONValue } from "assistant-stream/utils";
2
- import { isJSONValue, isRecord } from "./is-json";
3
-
4
- const MAX_JSON_DEPTH = 100;
5
-
6
- const isJSONValueEqualAtDepth = (
7
- a: ReadonlyJSONValue,
8
- b: ReadonlyJSONValue,
9
- currentDepth: number,
10
- ): boolean => {
11
- if (a === b) return true;
12
- if (currentDepth > MAX_JSON_DEPTH) return false;
13
-
14
- if (a == null || b == null) return false;
15
-
16
- if (Array.isArray(a)) {
17
- if (!Array.isArray(b) || a.length !== b.length) return false;
18
- return a.every((item, index) =>
19
- isJSONValueEqualAtDepth(
20
- item,
21
- b[index] as ReadonlyJSONValue,
22
- currentDepth + 1,
23
- ),
24
- );
25
- }
26
-
27
- if (Array.isArray(b)) return false;
28
- if (!isRecord(a) || !isRecord(b)) return false;
29
-
30
- const aKeys = Object.keys(a);
31
- const bKeys = Object.keys(b);
32
- if (aKeys.length !== bKeys.length) return false;
33
-
34
- return aKeys.every(
35
- (key) =>
36
- Object.hasOwn(b, key) &&
37
- isJSONValueEqualAtDepth(
38
- a[key] as ReadonlyJSONValue,
39
- b[key] as ReadonlyJSONValue,
40
- currentDepth + 1,
41
- ),
42
- );
43
- };
44
-
45
- export const isJSONValueEqual = (a: unknown, b: unknown): boolean => {
46
- if (!isJSONValue(a) || !isJSONValue(b)) return false;
47
- return isJSONValueEqualAtDepth(a, b, 0);
48
- };
@@ -1,58 +0,0 @@
1
- import type {
2
- ReadonlyJSONArray,
3
- ReadonlyJSONObject,
4
- ReadonlyJSONValue,
5
- } from "assistant-stream/utils";
6
-
7
- export function isRecord(value: unknown): value is Record<string, unknown> {
8
- return value != null && typeof value === "object" && !Array.isArray(value);
9
- }
10
-
11
- export function isJSONValue(
12
- value: unknown,
13
- currentDepth: number = 0,
14
- ): value is ReadonlyJSONValue {
15
- // Protect against too deep recursion
16
- if (currentDepth > 100) {
17
- return false;
18
- }
19
-
20
- if (
21
- value === null ||
22
- typeof value === "string" ||
23
- typeof value === "boolean"
24
- ) {
25
- return true;
26
- }
27
-
28
- // Handle special number cases
29
- if (typeof value === "number") {
30
- return !Number.isNaN(value) && Number.isFinite(value);
31
- }
32
-
33
- if (Array.isArray(value)) {
34
- return value.every((item) => isJSONValue(item, currentDepth + 1));
35
- }
36
-
37
- if (isRecord(value)) {
38
- return Object.entries(value).every(
39
- ([key, val]) =>
40
- typeof key === "string" && isJSONValue(val, currentDepth + 1),
41
- );
42
- }
43
-
44
- return false;
45
- }
46
-
47
- export function isJSONArray(value: unknown): value is ReadonlyJSONArray {
48
- return Array.isArray(value) && value.every(isJSONValue);
49
- }
50
-
51
- export function isJSONObject(value: unknown): value is ReadonlyJSONObject {
52
- return (
53
- isRecord(value) &&
54
- Object.entries(value).every(
55
- ([key, val]) => typeof key === "string" && isJSONValue(val),
56
- )
57
- );
58
- }