@assistant-ui/react 0.15.30 → 0.15.31

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 (351) hide show
  1. package/dist/cloud-renderer/CloudRendererHost.d.ts.map +1 -1
  2. package/dist/cloud-renderer/CloudRendererHost.js +1 -2
  3. package/dist/cloud-renderer/CloudRendererHost.js.map +1 -1
  4. package/dist/context/providers/AttachmentByIndexProvider.js +1 -2
  5. package/dist/context/providers/ChainOfThoughtByIndicesProvider.js +1 -2
  6. package/dist/context/providers/MessageByIndexProvider.js +1 -2
  7. package/dist/context/providers/PartByIndexProvider.js +1 -2
  8. package/dist/context/providers/SuggestionByIndexProvider.js +1 -2
  9. package/dist/context/providers/TextMessagePartProvider.js +1 -2
  10. package/dist/context/providers/ThreadListItemProvider.js +1 -2
  11. package/dist/index.d.ts +9 -8
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +2 -9
  14. package/dist/internal.d.ts +1 -1
  15. package/dist/internal.d.ts.map +1 -1
  16. package/dist/internal.js +1 -1
  17. package/dist/internal.js.map +1 -1
  18. package/dist/legacy-runtime/AssistantRuntimeProvider.d.ts +1 -1
  19. package/dist/legacy-runtime/AssistantRuntimeProvider.d.ts.map +1 -1
  20. package/dist/legacy-runtime/AssistantRuntimeProvider.js.map +1 -1
  21. package/dist/primitives/actionBar/ActionBarCopy.d.ts +1 -1
  22. package/dist/primitives/actionBar/ActionBarEdit.d.ts +1 -1
  23. package/dist/primitives/actionBar/ActionBarExportMarkdown.d.ts +1 -1
  24. package/dist/primitives/actionBar/ActionBarFeedbackNegative.d.ts +1 -1
  25. package/dist/primitives/actionBar/ActionBarFeedbackPositive.d.ts +1 -1
  26. package/dist/primitives/actionBar/ActionBarReload.d.ts +1 -1
  27. package/dist/primitives/actionBar/ActionBarRoot.d.ts +1 -1
  28. package/dist/primitives/actionBar/ActionBarSpeak.d.ts +1 -1
  29. package/dist/primitives/actionBar/ActionBarStopSpeaking.d.ts +1 -1
  30. package/dist/primitives/attachment/AttachmentRemove.d.ts +1 -1
  31. package/dist/primitives/attachment/AttachmentRoot.d.ts +1 -1
  32. package/dist/primitives/attachment/AttachmentThumb.d.ts +1 -1
  33. package/dist/primitives/branchPicker/BranchPickerNext.d.ts +1 -1
  34. package/dist/primitives/branchPicker/BranchPickerPrevious.d.ts +1 -1
  35. package/dist/primitives/branchPicker/BranchPickerRoot.d.ts +1 -1
  36. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.d.ts +1 -1
  37. package/dist/primitives/chainOfThought/ChainOfThoughtParts.js +1 -2
  38. package/dist/primitives/chainOfThought/ChainOfThoughtRoot.d.ts +1 -1
  39. package/dist/primitives/composer/ComposerAddAttachment.d.ts +1 -1
  40. package/dist/primitives/composer/ComposerAttachments.js +1 -2
  41. package/dist/primitives/composer/ComposerCancel.d.ts +1 -1
  42. package/dist/primitives/composer/ComposerDictate.d.ts +1 -1
  43. package/dist/primitives/composer/ComposerDictationTranscript.d.ts +1 -1
  44. package/dist/primitives/composer/ComposerIf.js +1 -2
  45. package/dist/primitives/composer/ComposerInput.d.ts.map +1 -1
  46. package/dist/primitives/composer/ComposerInput.js +3 -3
  47. package/dist/primitives/composer/ComposerInput.js.map +1 -1
  48. package/dist/primitives/composer/ComposerQueue.js +1 -2
  49. package/dist/primitives/composer/ComposerQuote.d.ts +3 -3
  50. package/dist/primitives/composer/ComposerResume.d.ts +1 -1
  51. package/dist/primitives/composer/ComposerRoot.d.ts +1 -1
  52. package/dist/primitives/composer/ComposerSend.d.ts +1 -1
  53. package/dist/primitives/composer/ComposerStopDictation.d.ts +1 -1
  54. package/dist/primitives/composer/trigger/TriggerPopover.d.ts +1 -1
  55. package/dist/primitives/composer/trigger/TriggerPopoverBack.d.ts +1 -1
  56. package/dist/primitives/composer/trigger/TriggerPopoverCategories.d.ts +2 -2
  57. package/dist/primitives/composer/trigger/TriggerPopoverItems.d.ts +2 -2
  58. package/dist/primitives/composer/trigger/index.d.ts +1 -1
  59. package/dist/primitives/composer/trigger/triggerSelectionResource.d.ts.map +1 -1
  60. package/dist/primitives/composer/trigger/triggerSelectionResource.js +2 -2
  61. package/dist/primitives/composer/trigger/triggerSelectionResource.js.map +1 -1
  62. package/dist/primitives/error/ErrorMessage.d.ts +1 -1
  63. package/dist/primitives/error/ErrorRoot.d.ts +1 -1
  64. package/dist/primitives/message/MessageAttachments.js +1 -2
  65. package/dist/primitives/message/MessageRoot.d.ts +1 -1
  66. package/dist/primitives/messagePart/MessagePartImage.d.ts +1 -1
  67. package/dist/primitives/messagePart/MessagePartInProgress.js +1 -2
  68. package/dist/primitives/messagePart/MessagePartText.d.ts +1 -1
  69. package/dist/primitives/queueItem/QueueItemRemove.d.ts +1 -1
  70. package/dist/primitives/queueItem/QueueItemSteer.d.ts +1 -1
  71. package/dist/primitives/queueItem/QueueItemText.d.ts +1 -1
  72. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.d.ts +1 -1
  73. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.d.ts +1 -1
  74. package/dist/primitives/suggestion/SuggestionDescription.d.ts +1 -1
  75. package/dist/primitives/suggestion/SuggestionTitle.d.ts +1 -1
  76. package/dist/primitives/suggestion/SuggestionTrigger.d.ts +1 -1
  77. package/dist/primitives/thread/ThreadLoadEarlier.d.ts +1 -1
  78. package/dist/primitives/thread/ThreadMessages.js +1 -2
  79. package/dist/primitives/thread/ThreadRoot.d.ts +1 -1
  80. package/dist/primitives/thread/ThreadScrollToBottom.d.ts +1 -1
  81. package/dist/primitives/thread/ThreadSuggestion.d.ts +1 -1
  82. package/dist/primitives/thread/ThreadSuggestions.js +1 -2
  83. package/dist/primitives/thread/ThreadViewport.d.ts +1 -1
  84. package/dist/primitives/thread/ThreadViewportFooter.d.ts +1 -1
  85. package/dist/primitives/thread/useThreadViewportAutoScroll.d.ts.map +1 -1
  86. package/dist/primitives/thread/useThreadViewportAutoScroll.js +6 -3
  87. package/dist/primitives/thread/useThreadViewportAutoScroll.js.map +1 -1
  88. package/dist/primitives/threadList/ThreadListItems.js +1 -2
  89. package/dist/primitives/threadList/ThreadListLoadMore.d.ts +1 -1
  90. package/dist/primitives/threadList/ThreadListNew.d.ts +1 -1
  91. package/dist/primitives/threadList/ThreadListRoot.d.ts +1 -1
  92. package/dist/primitives/threadListFocusGroup.d.ts +1 -1
  93. package/dist/primitives/threadListFocusGroup.d.ts.map +1 -1
  94. package/dist/primitives/threadListItem/ThreadListItemArchive.d.ts +1 -1
  95. package/dist/primitives/threadListItem/ThreadListItemDelete.d.ts +1 -1
  96. package/dist/primitives/threadListItem/ThreadListItemRoot.d.ts +1 -1
  97. package/dist/primitives/threadListItem/ThreadListItemTitle.js +1 -2
  98. package/dist/primitives/threadListItem/ThreadListItemTrigger.d.ts +1 -1
  99. package/dist/primitives/threadListItem/ThreadListItemUnarchive.d.ts +2 -2
  100. package/dist/primitives/threadListItem/ThreadListItemUnarchive.d.ts.map +1 -1
  101. package/dist/primitives/threadListItem/ThreadListItemUnarchive.js +2 -2
  102. package/dist/primitives/threadListItem/ThreadListItemUnarchive.js.map +1 -1
  103. package/dist/unstable/useComposerInput.js +1 -1
  104. package/dist/unstable/useComposerInput.js.map +1 -1
  105. package/dist/unstable/useComposerInputHistory.d.ts.map +1 -1
  106. package/dist/unstable/useComposerInputHistory.js +2 -2
  107. package/dist/unstable/useComposerInputHistory.js.map +1 -1
  108. package/dist/unstable/useLiveCompletionAdapter.d.ts.map +1 -1
  109. package/dist/unstable/useLiveCompletionAdapter.js +3 -2
  110. package/dist/unstable/useLiveCompletionAdapter.js.map +1 -1
  111. package/dist/utils/Primitive.d.ts +17 -17
  112. package/dist/utils/createActionButton.d.ts +1 -1
  113. package/package.json +12 -12
  114. package/src/adapters/OpenAIRealtimeVoiceAdapter.test.ts +14 -1
  115. package/src/cloud-renderer/CloudRendererHost.tsx +4 -2
  116. package/src/index.ts +9 -8
  117. package/src/internal.ts +1 -1
  118. package/src/legacy-runtime/AssistantRuntimeProvider.tsx +1 -1
  119. package/src/primitives/actionBar/ActionBarCopy.test.tsx +57 -0
  120. package/src/primitives/actionBar/ActionBarExportMarkdown.test.tsx +24 -5
  121. package/src/primitives/assistantModal/AssistantModalRoot.test.tsx +1 -1
  122. package/src/primitives/composer/ComposerInput.focus-on-run-start.test.tsx +1 -1
  123. package/src/primitives/composer/ComposerInput.test.tsx +1 -0
  124. package/src/primitives/composer/ComposerInput.text-change.test.tsx +68 -0
  125. package/src/primitives/composer/ComposerInput.thread-scope.test.tsx +82 -0
  126. package/src/primitives/composer/ComposerInput.tsx +4 -3
  127. package/src/primitives/composer/trigger/triggerSelectionResource.test.ts +6 -4
  128. package/src/primitives/composer/trigger/triggerSelectionResource.ts +2 -0
  129. package/src/primitives/thread/ThreadRoot.test.tsx +1 -1
  130. package/src/primitives/thread/ThreadViewport.thread-scope.test.tsx +51 -0
  131. package/src/primitives/thread/useThreadViewportAutoScroll.ts +8 -2
  132. package/src/primitives/threadListItem/ThreadListItemUnarchive.test.tsx +52 -0
  133. package/src/primitives/threadListItem/ThreadListItemUnarchive.ts +2 -2
  134. package/src/tests/DataRenderers.test.tsx +1 -1
  135. package/src/tests/MessageParts.loading.test.tsx +1 -1
  136. package/src/tests/RemoteThreadListRuntime.adapterProvider.test.tsx +1 -1
  137. package/src/tests/RemoteThreadListRuntime.deferredProvider.test.tsx +4 -2
  138. package/src/tests/RemoteThreadListRuntime.reloadMainThread.test.tsx +4 -2
  139. package/src/tests/generative-ui.primitive.test.tsx +1 -1
  140. package/src/tests/local-runtime-queue.test.tsx +2 -2
  141. package/src/tests/messagePartSwitchRace.test.tsx +2 -2
  142. package/src/tests/messagePartTypeMismatch.test.tsx +1 -1
  143. package/src/tests/threadListItemIsRunning.test.tsx +5 -3
  144. package/src/tests/toolCallTiming.test.tsx +1 -1
  145. package/src/unstable/useComposerInput.test.tsx +1 -1
  146. package/src/unstable/useComposerInput.ts +1 -1
  147. package/src/unstable/useComposerInputHistory.test.tsx +10 -7
  148. package/src/unstable/useComposerInputHistory.thread-scope.test.tsx +123 -0
  149. package/src/unstable/useComposerInputHistory.ts +3 -2
  150. package/src/unstable/useLiveCompletionAdapter.test.tsx +44 -0
  151. package/src/unstable/useLiveCompletionAdapter.ts +3 -2
  152. package/src/unstable/webmcp/convertTools.test.ts +11 -1
  153. package/src/utils/hooks/useMediaQuery.test.tsx +35 -0
  154. package/src/utils/smooth/useSmooth.test.tsx +37 -10
  155. package/dist/context/providers/ChainOfThoughtPartByIndexProvider.d.ts +0 -2
  156. package/dist/context/providers/ChainOfThoughtPartByIndexProvider.d.ts.map +0 -1
  157. package/dist/context/providers/ChainOfThoughtPartByIndexProvider.js +0 -3
  158. package/dist/legacy-runtime/RuntimeAdapter.d.ts +0 -2
  159. package/dist/legacy-runtime/RuntimeAdapter.d.ts.map +0 -1
  160. package/dist/legacy-runtime/RuntimeAdapter.js +0 -2
  161. package/dist/legacy-runtime/cloud/AssistantCloudThreadHistoryAdapter.d.ts +0 -2
  162. package/dist/legacy-runtime/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +0 -1
  163. package/dist/legacy-runtime/cloud/AssistantCloudThreadHistoryAdapter.js +0 -3
  164. package/dist/legacy-runtime/runtime/AssistantRuntime.d.ts +0 -3
  165. package/dist/legacy-runtime/runtime/AssistantRuntime.d.ts.map +0 -1
  166. package/dist/legacy-runtime/runtime/AssistantRuntime.js +0 -2
  167. package/dist/legacy-runtime/runtime/AttachmentRuntime.d.ts +0 -3
  168. package/dist/legacy-runtime/runtime/AttachmentRuntime.d.ts.map +0 -1
  169. package/dist/legacy-runtime/runtime/AttachmentRuntime.js +0 -2
  170. package/dist/legacy-runtime/runtime/ComposerRuntime.d.ts +0 -4
  171. package/dist/legacy-runtime/runtime/ComposerRuntime.d.ts.map +0 -1
  172. package/dist/legacy-runtime/runtime/ComposerRuntime.js +0 -2
  173. package/dist/legacy-runtime/runtime/RuntimeBindings.d.ts +0 -3
  174. package/dist/legacy-runtime/runtime/RuntimeBindings.d.ts.map +0 -1
  175. package/dist/legacy-runtime/runtime/RuntimeBindings.js +0 -0
  176. package/dist/legacy-runtime/runtime/RuntimePathTypes.d.ts +0 -2
  177. package/dist/legacy-runtime/runtime/RuntimePathTypes.d.ts.map +0 -1
  178. package/dist/legacy-runtime/runtime/RuntimePathTypes.js +0 -0
  179. package/dist/legacy-runtime/runtime/ThreadListItemRuntime.d.ts +0 -5
  180. package/dist/legacy-runtime/runtime/ThreadListItemRuntime.d.ts.map +0 -1
  181. package/dist/legacy-runtime/runtime/ThreadListItemRuntime.js +0 -2
  182. package/dist/legacy-runtime/runtime/ThreadRuntime.d.ts +0 -4
  183. package/dist/legacy-runtime/runtime/ThreadRuntime.d.ts.map +0 -1
  184. package/dist/legacy-runtime/runtime/ThreadRuntime.js +0 -2
  185. package/dist/legacy-runtime/runtime-cores/adapters/RuntimeAdapterProvider.d.ts +0 -2
  186. package/dist/legacy-runtime/runtime-cores/adapters/RuntimeAdapterProvider.d.ts.map +0 -1
  187. package/dist/legacy-runtime/runtime-cores/adapters/RuntimeAdapterProvider.js +0 -3
  188. package/dist/legacy-runtime/runtime-cores/adapters/attachment/CloudFileAttachmentAdapter.d.ts +0 -2
  189. package/dist/legacy-runtime/runtime-cores/adapters/attachment/CloudFileAttachmentAdapter.d.ts.map +0 -1
  190. package/dist/legacy-runtime/runtime-cores/adapters/attachment/CloudFileAttachmentAdapter.js +0 -3
  191. package/dist/legacy-runtime/runtime-cores/composer/BaseComposerRuntimeCore.d.ts +0 -2
  192. package/dist/legacy-runtime/runtime-cores/composer/BaseComposerRuntimeCore.d.ts.map +0 -1
  193. package/dist/legacy-runtime/runtime-cores/composer/BaseComposerRuntimeCore.js +0 -2
  194. package/dist/legacy-runtime/runtime-cores/composer/DefaultEditComposerRuntimeCore.d.ts +0 -2
  195. package/dist/legacy-runtime/runtime-cores/composer/DefaultEditComposerRuntimeCore.d.ts.map +0 -1
  196. package/dist/legacy-runtime/runtime-cores/composer/DefaultEditComposerRuntimeCore.js +0 -2
  197. package/dist/legacy-runtime/runtime-cores/composer/DefaultThreadComposerRuntimeCore.d.ts +0 -2
  198. package/dist/legacy-runtime/runtime-cores/composer/DefaultThreadComposerRuntimeCore.d.ts.map +0 -1
  199. package/dist/legacy-runtime/runtime-cores/composer/DefaultThreadComposerRuntimeCore.js +0 -2
  200. package/dist/legacy-runtime/runtime-cores/core/AssistantRuntimeCore.d.ts +0 -2
  201. package/dist/legacy-runtime/runtime-cores/core/AssistantRuntimeCore.d.ts.map +0 -1
  202. package/dist/legacy-runtime/runtime-cores/core/AssistantRuntimeCore.js +0 -0
  203. package/dist/legacy-runtime/runtime-cores/core/BaseAssistantRuntimeCore.d.ts +0 -2
  204. package/dist/legacy-runtime/runtime-cores/core/BaseAssistantRuntimeCore.d.ts.map +0 -1
  205. package/dist/legacy-runtime/runtime-cores/core/BaseAssistantRuntimeCore.js +0 -2
  206. package/dist/legacy-runtime/runtime-cores/core/BaseThreadRuntimeCore.d.ts +0 -2
  207. package/dist/legacy-runtime/runtime-cores/core/BaseThreadRuntimeCore.d.ts.map +0 -1
  208. package/dist/legacy-runtime/runtime-cores/core/BaseThreadRuntimeCore.js +0 -2
  209. package/dist/legacy-runtime/runtime-cores/core/ComposerRuntimeCore.d.ts +0 -2
  210. package/dist/legacy-runtime/runtime-cores/core/ComposerRuntimeCore.d.ts.map +0 -1
  211. package/dist/legacy-runtime/runtime-cores/core/ComposerRuntimeCore.js +0 -0
  212. package/dist/legacy-runtime/runtime-cores/core/ThreadListRuntimeCore.d.ts +0 -2
  213. package/dist/legacy-runtime/runtime-cores/core/ThreadListRuntimeCore.d.ts.map +0 -1
  214. package/dist/legacy-runtime/runtime-cores/core/ThreadListRuntimeCore.js +0 -0
  215. package/dist/legacy-runtime/runtime-cores/core/ThreadRuntimeCore.d.ts +0 -2
  216. package/dist/legacy-runtime/runtime-cores/core/ThreadRuntimeCore.d.ts.map +0 -1
  217. package/dist/legacy-runtime/runtime-cores/core/ThreadRuntimeCore.js +0 -0
  218. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreAdapter.d.ts +0 -2
  219. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreAdapter.d.ts.map +0 -1
  220. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreAdapter.js +0 -0
  221. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreRuntimeCore.d.ts +0 -2
  222. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreRuntimeCore.d.ts.map +0 -1
  223. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreRuntimeCore.js +0 -2
  224. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadListRuntimeCore.d.ts +0 -3
  225. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadListRuntimeCore.d.ts.map +0 -1
  226. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadListRuntimeCore.js +0 -2
  227. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadRuntimeCore.d.ts +0 -2
  228. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadRuntimeCore.d.ts.map +0 -1
  229. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadRuntimeCore.js +0 -2
  230. package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageConverter.d.ts +0 -3
  231. package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageConverter.d.ts.map +0 -1
  232. package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageConverter.js +0 -2
  233. package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageLike.d.ts +0 -3
  234. package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageLike.d.ts.map +0 -1
  235. package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageLike.js +0 -2
  236. package/dist/legacy-runtime/runtime-cores/external-store/auto-status.d.ts +0 -2
  237. package/dist/legacy-runtime/runtime-cores/external-store/auto-status.d.ts.map +0 -1
  238. package/dist/legacy-runtime/runtime-cores/external-store/auto-status.js +0 -2
  239. package/dist/legacy-runtime/runtime-cores/external-store/createMessageConverter.d.ts +0 -2
  240. package/dist/legacy-runtime/runtime-cores/external-store/createMessageConverter.d.ts.map +0 -1
  241. package/dist/legacy-runtime/runtime-cores/external-store/createMessageConverter.js +0 -3
  242. package/dist/legacy-runtime/runtime-cores/external-store/external-message-converter.d.ts +0 -2
  243. package/dist/legacy-runtime/runtime-cores/external-store/external-message-converter.d.ts.map +0 -1
  244. package/dist/legacy-runtime/runtime-cores/external-store/external-message-converter.js +0 -3
  245. package/dist/legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime.d.ts +0 -2
  246. package/dist/legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime.d.ts.map +0 -1
  247. package/dist/legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime.js +0 -3
  248. package/dist/legacy-runtime/runtime-cores/local/ChatModelAdapter.d.ts +0 -2
  249. package/dist/legacy-runtime/runtime-cores/local/ChatModelAdapter.d.ts.map +0 -1
  250. package/dist/legacy-runtime/runtime-cores/local/ChatModelAdapter.js +0 -0
  251. package/dist/legacy-runtime/runtime-cores/local/LocalRuntimeCore.d.ts +0 -2
  252. package/dist/legacy-runtime/runtime-cores/local/LocalRuntimeCore.d.ts.map +0 -1
  253. package/dist/legacy-runtime/runtime-cores/local/LocalRuntimeCore.js +0 -2
  254. package/dist/legacy-runtime/runtime-cores/local/LocalRuntimeOptions.d.ts +0 -4
  255. package/dist/legacy-runtime/runtime-cores/local/LocalRuntimeOptions.d.ts.map +0 -1
  256. package/dist/legacy-runtime/runtime-cores/local/LocalRuntimeOptions.js +0 -2
  257. package/dist/legacy-runtime/runtime-cores/local/LocalThreadListRuntimeCore.d.ts +0 -3
  258. package/dist/legacy-runtime/runtime-cores/local/LocalThreadListRuntimeCore.d.ts.map +0 -1
  259. package/dist/legacy-runtime/runtime-cores/local/LocalThreadListRuntimeCore.js +0 -2
  260. package/dist/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.d.ts +0 -2
  261. package/dist/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.d.ts.map +0 -1
  262. package/dist/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.js +0 -2
  263. package/dist/legacy-runtime/runtime-cores/local/shouldContinue.d.ts +0 -2
  264. package/dist/legacy-runtime/runtime-cores/local/shouldContinue.d.ts.map +0 -1
  265. package/dist/legacy-runtime/runtime-cores/local/shouldContinue.js +0 -2
  266. package/dist/legacy-runtime/runtime-cores/local/useLocalRuntime.d.ts +0 -2
  267. package/dist/legacy-runtime/runtime-cores/local/useLocalRuntime.d.ts.map +0 -1
  268. package/dist/legacy-runtime/runtime-cores/local/useLocalRuntime.js +0 -3
  269. package/dist/legacy-runtime/runtime-cores/remote-thread-list/BaseSubscribable.d.ts +0 -2
  270. package/dist/legacy-runtime/runtime-cores/remote-thread-list/BaseSubscribable.d.ts.map +0 -1
  271. package/dist/legacy-runtime/runtime-cores/remote-thread-list/BaseSubscribable.js +0 -2
  272. package/dist/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.d.ts +0 -2
  273. package/dist/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.d.ts.map +0 -1
  274. package/dist/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.js +0 -2
  275. package/dist/legacy-runtime/runtime-cores/remote-thread-list/OptimisticState.d.ts +0 -2
  276. package/dist/legacy-runtime/runtime-cores/remote-thread-list/OptimisticState.d.ts.map +0 -1
  277. package/dist/legacy-runtime/runtime-cores/remote-thread-list/OptimisticState.js +0 -2
  278. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.d.ts +0 -2
  279. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.d.ts.map +0 -1
  280. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.js +0 -3
  281. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.d.ts +0 -2
  282. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.d.ts.map +0 -1
  283. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.js +0 -3
  284. package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud.d.ts +0 -2
  285. package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud.d.ts.map +0 -1
  286. package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud.js +0 -3
  287. package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/in-memory.d.ts +0 -2
  288. package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/in-memory.d.ts.map +0 -1
  289. package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/in-memory.js +0 -2
  290. package/dist/legacy-runtime/runtime-cores/remote-thread-list/types.d.ts +0 -2
  291. package/dist/legacy-runtime/runtime-cores/remote-thread-list/types.d.ts.map +0 -1
  292. package/dist/legacy-runtime/runtime-cores/remote-thread-list/types.js +0 -0
  293. package/dist/legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime.d.ts +0 -2
  294. package/dist/legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime.d.ts.map +0 -1
  295. package/dist/legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime.js +0 -3
  296. package/dist/legacy-runtime/runtime-cores/utils/MessageRepository.d.ts +0 -4
  297. package/dist/legacy-runtime/runtime-cores/utils/MessageRepository.d.ts.map +0 -1
  298. package/dist/legacy-runtime/runtime-cores/utils/MessageRepository.js +0 -3
  299. package/dist/utils/hooks/useOnResizeContent.d.ts +0 -2
  300. package/dist/utils/hooks/useOnResizeContent.d.ts.map +0 -1
  301. package/dist/utils/hooks/useOnResizeContent.js +0 -21
  302. package/dist/utils/hooks/useOnResizeContent.js.map +0 -1
  303. package/src/context/providers/ChainOfThoughtPartByIndexProvider.tsx +0 -3
  304. package/src/legacy-runtime/RuntimeAdapter.ts +0 -1
  305. package/src/legacy-runtime/cloud/AssistantCloudThreadHistoryAdapter.ts +0 -3
  306. package/src/legacy-runtime/runtime/AssistantRuntime.ts +0 -2
  307. package/src/legacy-runtime/runtime/AttachmentRuntime.ts +0 -7
  308. package/src/legacy-runtime/runtime/ComposerRuntime.ts +0 -20
  309. package/src/legacy-runtime/runtime/RuntimeBindings.ts +0 -12
  310. package/src/legacy-runtime/runtime/RuntimePathTypes.ts +0 -8
  311. package/src/legacy-runtime/runtime/ThreadListItemRuntime.ts +0 -10
  312. package/src/legacy-runtime/runtime/ThreadRuntime.ts +0 -14
  313. package/src/legacy-runtime/runtime-cores/adapters/RuntimeAdapterProvider.tsx +0 -7
  314. package/src/legacy-runtime/runtime-cores/adapters/attachment/CloudFileAttachmentAdapter.ts +0 -3
  315. package/src/legacy-runtime/runtime-cores/composer/BaseComposerRuntimeCore.ts +0 -1
  316. package/src/legacy-runtime/runtime-cores/composer/DefaultEditComposerRuntimeCore.ts +0 -1
  317. package/src/legacy-runtime/runtime-cores/composer/DefaultThreadComposerRuntimeCore.ts +0 -1
  318. package/src/legacy-runtime/runtime-cores/core/AssistantRuntimeCore.ts +0 -1
  319. package/src/legacy-runtime/runtime-cores/core/BaseAssistantRuntimeCore.ts +0 -1
  320. package/src/legacy-runtime/runtime-cores/core/BaseThreadRuntimeCore.ts +0 -1
  321. package/src/legacy-runtime/runtime-cores/core/ComposerRuntimeCore.ts +0 -6
  322. package/src/legacy-runtime/runtime-cores/core/ThreadListRuntimeCore.ts +0 -4
  323. package/src/legacy-runtime/runtime-cores/core/ThreadRuntimeCore.ts +0 -13
  324. package/src/legacy-runtime/runtime-cores/external-store/ExternalStoreAdapter.ts +0 -6
  325. package/src/legacy-runtime/runtime-cores/external-store/ExternalStoreRuntimeCore.ts +0 -1
  326. package/src/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadListRuntimeCore.ts +0 -2
  327. package/src/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadRuntimeCore.ts +0 -4
  328. package/src/legacy-runtime/runtime-cores/external-store/ThreadMessageConverter.ts +0 -2
  329. package/src/legacy-runtime/runtime-cores/external-store/ThreadMessageLike.ts +0 -2
  330. package/src/legacy-runtime/runtime-cores/external-store/auto-status.ts +0 -1
  331. package/src/legacy-runtime/runtime-cores/external-store/createMessageConverter.ts +0 -2
  332. package/src/legacy-runtime/runtime-cores/external-store/external-message-converter.ts +0 -7
  333. package/src/legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime.ts +0 -3
  334. package/src/legacy-runtime/runtime-cores/local/ChatModelAdapter.ts +0 -7
  335. package/src/legacy-runtime/runtime-cores/local/LocalRuntimeCore.ts +0 -1
  336. package/src/legacy-runtime/runtime-cores/local/LocalRuntimeOptions.ts +0 -3
  337. package/src/legacy-runtime/runtime-cores/local/LocalThreadListRuntimeCore.ts +0 -2
  338. package/src/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.ts +0 -1
  339. package/src/legacy-runtime/runtime-cores/local/shouldContinue.ts +0 -1
  340. package/src/legacy-runtime/runtime-cores/local/useLocalRuntime.ts +0 -3
  341. package/src/legacy-runtime/runtime-cores/remote-thread-list/BaseSubscribable.ts +0 -1
  342. package/src/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.ts +0 -1
  343. package/src/legacy-runtime/runtime-cores/remote-thread-list/OptimisticState.ts +0 -1
  344. package/src/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.tsx +0 -3
  345. package/src/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.tsx +0 -3
  346. package/src/legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud.tsx +0 -3
  347. package/src/legacy-runtime/runtime-cores/remote-thread-list/adapter/in-memory.ts +0 -1
  348. package/src/legacy-runtime/runtime-cores/remote-thread-list/types.ts +0 -7
  349. package/src/legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime.ts +0 -3
  350. package/src/legacy-runtime/runtime-cores/utils/MessageRepository.ts +0 -3
  351. package/src/utils/hooks/useOnResizeContent.ts +0 -15
@@ -5,7 +5,7 @@ type PrimitiveButtonProps = ComponentPropsWithoutRef<typeof Primitive.button>;
5
5
  export type ActionButtonProps<THook> = PrimitiveButtonProps & (THook extends (props: infer TProps) => unknown ? TProps : never);
6
6
  export type ActionButtonElement = ComponentRef<typeof Primitive.button>;
7
7
  export declare const createActionButton: <TProps>(displayName: string, useActionButton: ActionButtonCallback<TProps>, forwardProps?: (keyof NonNullable<TProps>)[]) => import("react").ForwardRefExoticComponent<import("react").PropsWithoutRef<Omit<Omit<import("react").ClassAttributes<HTMLButtonElement> & import("react").ButtonHTMLAttributes<HTMLButtonElement> & {
8
- asChild?: boolean;
8
+ asChild?: boolean | undefined;
9
9
  }, "ref"> & {
10
10
  render?: import("react").ReactElement | undefined;
11
11
  } & import("react").RefAttributes<HTMLButtonElement>, "ref"> & TProps> & import("react").RefAttributes<HTMLButtonElement>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/react",
3
- "version": "0.15.30",
3
+ "version": "0.15.31",
4
4
  "description": "Open-source TypeScript/React library for building production-grade AI chat experiences",
5
5
  "keywords": [
6
6
  "ai",
@@ -55,15 +55,15 @@
55
55
  ],
56
56
  "sideEffects": false,
57
57
  "dependencies": {
58
- "@assistant-ui/core": "^0.3.30",
58
+ "@assistant-ui/core": "^0.3.31",
59
59
  "@assistant-ui/store": "^0.3.22",
60
60
  "@assistant-ui/tap": "^0.9.24",
61
- "assistant-cloud": "^0.2.7",
62
- "assistant-stream": "^0.3.53",
63
- "radix-ui": "^1.7.0",
61
+ "assistant-cloud": "^0.2.8",
62
+ "assistant-stream": "^0.3.54",
63
+ "radix-ui": "^1.8.1",
64
64
  "react-textarea-autosize": "^8.5.9",
65
65
  "safe-content-frame": "^0.0.34",
66
- "zod": "^4.6.5",
66
+ "zod": "^4.6.7",
67
67
  "zustand": "^5.0.15"
68
68
  },
69
69
  "peerDependencies": {
@@ -82,17 +82,17 @@
82
82
  },
83
83
  "devDependencies": {
84
84
  "@assistant-ui/vite": "0.0.21",
85
- "@assistant-ui/x-buildutils": "0.0.30",
85
+ "@assistant-ui/x-buildutils": "0.0.31",
86
86
  "@assistant-ui/x-react18": "0.0.0",
87
87
  "@testing-library/react": "^16.3.3",
88
88
  "@types/json-schema": "^7.0.15",
89
- "@types/node": "^26.6.4",
89
+ "@types/node": "^26.6.5",
90
90
  "@types/react": "^19.3.0",
91
91
  "@types/react-dom": "^19.3.0",
92
- "jsdom": "^30.1.2",
93
- "react": "^19.3.0",
94
- "react-dom": "^19.3.0",
95
- "vitest": "^5.0.3"
92
+ "jsdom": "^30.1.3",
93
+ "react": "^19.3.1",
94
+ "react-dom": "^19.3.1",
95
+ "vitest": "^5.0.5"
96
96
  },
97
97
  "publishConfig": {
98
98
  "access": "public",
@@ -435,6 +435,11 @@ describe("OpenAIRealtimeVoiceAdapter", () => {
435
435
  const accepted = vi.fn();
436
436
  session.onTranscript(onTranscript);
437
437
  channel.emit({ type: "response.created" });
438
+ channel.emit({
439
+ type: "response.output_audio_transcript.delta",
440
+ item_id: "old-reply",
441
+ delta: "Previous reply",
442
+ });
438
443
  channel.emit({ type: "output_audio_buffer.started" });
439
444
  const sent = Promise.resolve(session.sendText!("Change the topic"));
440
445
  void sent.then(accepted);
@@ -448,6 +453,11 @@ describe("OpenAIRealtimeVoiceAdapter", () => {
448
453
  role: "user",
449
454
  content: [{ type: "input_text", text: "Change the topic" }],
450
455
  });
456
+ channel.emit({ type: "response.done", response: { status: "cancelled" } });
457
+ expect(onTranscript.mock.calls.map(([item]) => item)).toEqual([
458
+ { role: "assistant", text: "Previous reply", isFinal: false },
459
+ { role: "assistant", text: "Previous reply", isFinal: true },
460
+ ]);
451
461
  expect(accepted).not.toHaveBeenCalled();
452
462
  channel.emit({
453
463
  type: "conversation.item.added",
@@ -475,7 +485,10 @@ describe("OpenAIRealtimeVoiceAdapter", () => {
475
485
  response: { metadata: response.response.metadata },
476
486
  });
477
487
  await sent;
478
- expect(onTranscript).not.toHaveBeenCalled();
488
+ expect(onTranscript.mock.calls.map(([item]) => item)).toEqual([
489
+ { role: "assistant", text: "Previous reply", isFinal: false },
490
+ { role: "assistant", text: "Previous reply", isFinal: true },
491
+ ]);
479
492
  });
480
493
 
481
494
  it("rejects a typed send whose response request fails after the item was accepted", async () => {
@@ -17,10 +17,12 @@ import {
17
17
  type AssistantClient,
18
18
  } from "@assistant-ui/store";
19
19
  import { resource } from "@assistant-ui/tap";
20
- import { ReadonlyThreadProvider } from "@assistant-ui/core/react";
20
+ import {
21
+ ReadonlyThreadProvider,
22
+ useExternalStoreRuntime,
23
+ } from "@assistant-ui/core/react";
21
24
  import type { ThreadMessage } from "@assistant-ui/core";
22
25
  import { AssistantRuntimeProvider } from "../legacy-runtime/AssistantRuntimeProvider";
23
- import { useExternalStoreRuntime } from "../legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime";
24
26
 
25
27
  const CHANNEL = "assistant-ui/cloud-renderer";
26
28
 
package/src/index.ts CHANGED
@@ -60,7 +60,7 @@ export {
60
60
  SimpleTextAttachmentAdapter,
61
61
  CompositeAttachmentAdapter,
62
62
  } from "@assistant-ui/core";
63
- export { CloudFileAttachmentAdapter } from "./legacy-runtime/runtime-cores/adapters/attachment/CloudFileAttachmentAdapter";
63
+ export { CloudFileAttachmentAdapter } from "@assistant-ui/core/react";
64
64
 
65
65
  // --- adapters/voice ---
66
66
  export type { RealtimeVoiceAdapter } from "@assistant-ui/core";
@@ -164,7 +164,7 @@ export {
164
164
  type ExternalThreadQueueAdapter,
165
165
  type ExternalThreadBranchAdapter,
166
166
  } from "@assistant-ui/core";
167
- export { useExternalStoreRuntime } from "./legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime";
167
+ export { useExternalStoreRuntime } from "@assistant-ui/core/react";
168
168
  export { useExternalStoreSharedOptions } from "@assistant-ui/core/react";
169
169
  export {
170
170
  useExternalMessageConverter,
@@ -174,11 +174,11 @@ export {
174
174
  createExternalMessageConversionCache as unstable_createExternalMessageConversionCache,
175
175
  /** @deprecated Experimental since 2026-09-15. Not scheduled for removal; the API may change in any release. */
176
176
  type ExternalMessageConversionCache as Unstable_ExternalMessageConversionCache,
177
- } from "./legacy-runtime/runtime-cores/external-store/external-message-converter";
177
+ } from "@assistant-ui/core/react";
178
178
  export {
179
179
  /** @deprecated Experimental since 2025-02-02. Not scheduled for removal; the API may change in any release. */
180
180
  createMessageConverter as unstable_createMessageConverter,
181
- } from "./legacy-runtime/runtime-cores/external-store/createMessageConverter";
181
+ } from "@assistant-ui/core/react";
182
182
 
183
183
  // --- local ---
184
184
  export type {
@@ -188,12 +188,12 @@ export type {
188
188
  ChatModelRunUpdate,
189
189
  LocalRuntimeOptionsBase,
190
190
  } from "@assistant-ui/core";
191
- export { useLocalRuntime } from "./legacy-runtime/runtime-cores/local/useLocalRuntime";
192
- export type { LocalRuntimeOptions } from "./legacy-runtime/runtime-cores/local/LocalRuntimeOptions";
191
+ export { useLocalRuntime } from "@assistant-ui/core/react";
192
+ export type { LocalRuntimeOptions } from "@assistant-ui/core/react";
193
193
 
194
194
  // --- remote-thread-list ---
195
- export { useRemoteThreadListRuntime } from "./legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime";
196
- export { useCloudThreadListAdapter } from "./legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud";
195
+ export { useRemoteThreadListRuntime } from "@assistant-ui/core/react";
196
+ export { useCloudThreadListAdapter } from "@assistant-ui/core/react";
197
197
  export type {
198
198
  RemoteThreadListAdapter,
199
199
  RemoteThreadListProviderComponent,
@@ -303,6 +303,7 @@ export type {
303
303
  QueueItemMethods,
304
304
  } from "@assistant-ui/core/store";
305
305
  export type { ComposerSendOptions } from "@assistant-ui/core/store";
306
+ export type { ComposerTextOrigin } from "@assistant-ui/core";
306
307
 
307
308
  export { makeAssistantVisible } from "./model-context/makeAssistantVisible";
308
309
 
package/src/internal.ts CHANGED
@@ -20,7 +20,7 @@ export type {
20
20
  } from "@assistant-ui/core/internal";
21
21
 
22
22
  // React-specific (stay in react)
23
- export { splitLocalRuntimeOptions } from "./legacy-runtime/runtime-cores/local/LocalRuntimeOptions";
23
+ export { splitLocalRuntimeOptions } from "@assistant-ui/core/react";
24
24
  export type { ToolExecutionStatus } from "@assistant-ui/core";
25
25
 
26
26
  export { useSmooth } from "./utils/smooth/useSmooth";
@@ -6,7 +6,7 @@ import {
6
6
  type AuiConfig,
7
7
  useAui,
8
8
  } from "@assistant-ui/store";
9
- import type { AssistantRuntime } from "./runtime/AssistantRuntime";
9
+ import type { AssistantRuntime } from "@assistant-ui/core";
10
10
  import { AssistantProviderBase } from "@assistant-ui/core/react";
11
11
  import { ThreadPrimitiveViewportProvider } from "../context/providers/ThreadViewportProvider";
12
12
  import { DevToolsProviderApi } from "../devtools/DevToolsHooks";
@@ -0,0 +1,57 @@
1
+ // @vitest-environment jsdom
2
+
3
+ import {
4
+ act,
5
+ cleanup,
6
+ fireEvent,
7
+ render,
8
+ screen,
9
+ waitFor,
10
+ } from "@testing-library/react";
11
+ import { afterEach, expect, it, vi } from "vitest";
12
+ import type { ChatModelAdapter, ThreadMessageLike } from "@assistant-ui/core";
13
+ import {
14
+ AssistantRuntimeProvider,
15
+ useLocalRuntime,
16
+ } from "@assistant-ui/core/react";
17
+ import { ThreadPrimitiveMessages } from "../thread/ThreadMessages";
18
+ import { ActionBarPrimitiveCopy } from "./ActionBarCopy";
19
+
20
+ const model: ChatModelAdapter = { async *run() {} };
21
+ const initialMessages: ThreadMessageLike[] = [
22
+ {
23
+ role: "assistant",
24
+ content: [{ type: "text", text: "Message to copy." }],
25
+ status: { type: "complete", reason: "stop" },
26
+ },
27
+ ];
28
+ const Message = () => (
29
+ <ActionBarPrimitiveCopy>Copy message</ActionBarPrimitiveCopy>
30
+ );
31
+ const Example = () => {
32
+ const runtime = useLocalRuntime(model, { initialMessages });
33
+ return (
34
+ <AssistantRuntimeProvider runtime={runtime}>
35
+ <ThreadPrimitiveMessages components={{ Message }} />
36
+ </AssistantRuntimeProvider>
37
+ );
38
+ };
39
+
40
+ afterEach(() => {
41
+ cleanup();
42
+ vi.unstubAllGlobals();
43
+ });
44
+
45
+ it("copies the scoped message through the browser clipboard", async () => {
46
+ const writeText = vi.fn().mockResolvedValue(undefined);
47
+ vi.stubGlobal("navigator", { ...navigator, clipboard: { writeText } });
48
+ render(<Example />);
49
+ const button = screen.getByRole("button", { name: "Copy message" });
50
+
51
+ await act(async () => {
52
+ fireEvent.click(button);
53
+ });
54
+
55
+ expect(writeText).toHaveBeenCalledExactlyOnceWith("Message to copy.");
56
+ await waitFor(() => expect(button.getAttribute("data-copied")).toBe("true"));
57
+ });
@@ -41,16 +41,24 @@ describe("ActionBarPrimitiveExportMarkdown", () => {
41
41
  vi.restoreAllMocks();
42
42
  });
43
43
 
44
- it("clicks a download anchor that is attached to the document", async () => {
44
+ it("downloads the message as Markdown through an attached anchor", async () => {
45
45
  const createObjectURL = vi
46
46
  .spyOn(URL, "createObjectURL")
47
47
  .mockReturnValue("blob:export");
48
48
  vi.spyOn(URL, "revokeObjectURL").mockImplementation(() => {});
49
- const connectedAtClick: boolean[] = [];
49
+ const downloads: {
50
+ isConnected: boolean;
51
+ href: string;
52
+ download: string;
53
+ }[] = [];
50
54
  vi.spyOn(HTMLAnchorElement.prototype, "click").mockImplementation(function (
51
55
  this: HTMLAnchorElement,
52
56
  ) {
53
- connectedAtClick.push(this.isConnected);
57
+ downloads.push({
58
+ isConnected: this.isConnected,
59
+ href: this.href,
60
+ download: this.download,
61
+ });
54
62
  });
55
63
 
56
64
  await act(async () => {
@@ -65,9 +73,20 @@ describe("ActionBarPrimitiveExportMarkdown", () => {
65
73
  container.querySelector("button")!.click();
66
74
  });
67
75
 
68
- expect(createObjectURL).toHaveBeenCalled();
76
+ expect(createObjectURL).toHaveBeenCalledOnce();
77
+ const blob = createObjectURL.mock.calls[0]![0] as Blob;
78
+ expect(blob.type).toBe("text/markdown");
79
+ const content = await new Promise<string>((resolve, reject) => {
80
+ const reader = new FileReader();
81
+ reader.onload = () => resolve(reader.result as string);
82
+ reader.onerror = () => reject(reader.error);
83
+ reader.readAsText(blob);
84
+ });
85
+ expect(content).toBe("# Exported message");
69
86
  // Firefox ignores a programmatic click on a detached anchor.
70
- expect(connectedAtClick).toEqual([true]);
87
+ expect(downloads).toEqual([
88
+ { isConnected: true, href: "blob:export", download: "message.md" },
89
+ ]);
71
90
  expect(document.querySelector('a[download="message.md"]')).toBeNull();
72
91
  });
73
92
 
@@ -10,7 +10,7 @@ import {
10
10
  import { useState } from "react";
11
11
  import { afterEach, describe, expect, it, vi } from "vitest";
12
12
  import { AssistantRuntimeProvider } from "../../context";
13
- import { useLocalRuntime } from "../../legacy-runtime/runtime-cores/local/useLocalRuntime";
13
+ import { useLocalRuntime } from "@assistant-ui/core/react";
14
14
  import { AssistantModalPrimitiveContent } from "./AssistantModalContent";
15
15
  import { AssistantModalPrimitiveRoot } from "./AssistantModalRoot";
16
16
  import { AssistantModalPrimitiveTrigger } from "./AssistantModalTrigger";
@@ -3,7 +3,7 @@
3
3
  import { act, fireEvent, render, screen } from "@testing-library/react";
4
4
  import { describe, expect, it } from "vitest";
5
5
  import { AssistantRuntimeProvider } from "../../context";
6
- import { useLocalRuntime } from "../../legacy-runtime/runtime-cores/local/useLocalRuntime";
6
+ import { useLocalRuntime } from "@assistant-ui/core/react";
7
7
  import { ThreadPrimitiveRoot } from "../thread/ThreadRoot";
8
8
  import { ComposerPrimitiveInput } from "./ComposerInput";
9
9
  import { ComposerPrimitiveRoot } from "./ComposerRoot";
@@ -40,6 +40,7 @@ let pluginRegistry: { getPlugins: () => (typeof plugin)[] } | null = null;
40
40
 
41
41
  vi.mock("@assistant-ui/store", () => {
42
42
  const aui = {
43
+ optional: { threads: {} },
43
44
  composer: {
44
45
  setText: (text: string) => setText(text),
45
46
  getState: () => composerState,
@@ -0,0 +1,68 @@
1
+ // @vitest-environment jsdom
2
+
3
+ import {
4
+ act,
5
+ cleanup,
6
+ fireEvent,
7
+ render,
8
+ screen,
9
+ } from "@testing-library/react";
10
+ import type { FC } from "react";
11
+ import { afterEach, expect, it } from "vitest";
12
+ import { useAui } from "@assistant-ui/store";
13
+ import { useLocalRuntime } from "@assistant-ui/core/react";
14
+ import type { ChatModelAdapter } from "@assistant-ui/core";
15
+ import { AssistantRuntimeProvider } from "../../context";
16
+ import { ThreadPrimitiveViewportProvider } from "../../context/providers/ThreadViewportProvider";
17
+ import { ComposerPrimitiveInput } from "./ComposerInput";
18
+
19
+ const adapter: ChatModelAdapter = {
20
+ async *run() {
21
+ yield { content: [{ type: "text", text: "done" }] };
22
+ },
23
+ };
24
+
25
+ afterEach(cleanup);
26
+
27
+ it("emits composer.textChange with the user origin for typing and the send origin for the clear", async () => {
28
+ let aui!: ReturnType<typeof useAui>;
29
+ const Capture: FC = () => {
30
+ aui = useAui();
31
+ return null;
32
+ };
33
+ const App: FC = () => (
34
+ <AssistantRuntimeProvider runtime={useLocalRuntime(adapter)}>
35
+ <Capture />
36
+ <ThreadPrimitiveViewportProvider>
37
+ <ComposerPrimitiveInput aria-label="Composer" />
38
+ </ThreadPrimitiveViewportProvider>
39
+ </AssistantRuntimeProvider>
40
+ );
41
+ render(<App />);
42
+ const changes: unknown[] = [];
43
+ aui.on({ scope: "*", event: "composer.textChange" }, (change) =>
44
+ changes.push(change),
45
+ );
46
+ const input = screen.getByRole("textbox", { name: "Composer" });
47
+
48
+ await act(async () => {
49
+ fireEvent.change(input, { target: { value: "hi" } });
50
+ });
51
+ await act(async () => {
52
+ fireEvent.change(input, { target: { value: "" } });
53
+ });
54
+ await act(async () => {
55
+ fireEvent.change(input, { target: { value: "hello" } });
56
+ });
57
+ await act(async () => {
58
+ aui.composer().send();
59
+ });
60
+
61
+ const threadId = aui.threads().getState().mainThreadId;
62
+ expect(changes).toEqual([
63
+ { threadId, text: "hi", origin: "user" },
64
+ { threadId, text: "", origin: "user" },
65
+ { threadId, text: "hello", origin: "user" },
66
+ { threadId, text: "", origin: "send" },
67
+ ]);
68
+ });
@@ -0,0 +1,82 @@
1
+ // @vitest-environment jsdom
2
+
3
+ import {
4
+ act,
5
+ cleanup,
6
+ fireEvent,
7
+ render,
8
+ screen,
9
+ waitFor,
10
+ } from "@testing-library/react";
11
+ import { afterEach, expect, it } from "vitest";
12
+ import { AuiConfig, AuiProvider, Derived, useAui } from "@assistant-ui/store";
13
+ import { ExternalThread, InMemoryThreadList } from "@assistant-ui/core/store";
14
+ import { resource, useResource } from "@assistant-ui/tap";
15
+ import { ThreadPrimitiveViewportProvider } from "../../context/providers/ThreadViewportProvider";
16
+ import { ComposerPrimitiveInput } from "./ComposerInput";
17
+
18
+ const StandaloneThread = resource(function useStandaloneThread() {
19
+ return useResource(ExternalThread({ messages: [] }));
20
+ });
21
+ const StandaloneApp = () => {
22
+ const config = AuiConfig({
23
+ thread: StandaloneThread(),
24
+ composer: Derived({
25
+ source: "thread",
26
+ query: {},
27
+ get: (aui) => aui.thread.composer(),
28
+ }),
29
+ });
30
+ return (
31
+ <AuiProvider config={config}>
32
+ <ThreadPrimitiveViewportProvider>
33
+ <ComposerPrimitiveInput aria-label="Composer" />
34
+ </ThreadPrimitiveViewportProvider>
35
+ </AuiProvider>
36
+ );
37
+ };
38
+
39
+ afterEach(cleanup);
40
+
41
+ it("edits a draft without a thread-list scope", async () => {
42
+ render(<StandaloneApp />);
43
+ const input = screen.getByRole("textbox", {
44
+ name: "Composer",
45
+ }) as HTMLTextAreaElement;
46
+ await act(async () => {
47
+ fireEvent.change(input, { target: { value: "New question" } });
48
+ });
49
+ expect(input.value).toBe("New question");
50
+ });
51
+
52
+ it("restores composer focus when the thread switches", async () => {
53
+ let captured!: ReturnType<typeof useAui>;
54
+ const App = () => {
55
+ const aui = useAui({
56
+ threads: InMemoryThreadList({
57
+ thread: () => ExternalThread({ messages: [] }),
58
+ }),
59
+ });
60
+ captured = aui;
61
+ return (
62
+ <AuiProvider value={aui}>
63
+ <ThreadPrimitiveViewportProvider>
64
+ <button>Outside</button>
65
+ <ComposerPrimitiveInput aria-label="Composer" autoFocus />
66
+ </ThreadPrimitiveViewportProvider>
67
+ </AuiProvider>
68
+ );
69
+ };
70
+ render(<App />);
71
+ const input = screen.getByRole("textbox", { name: "Composer" });
72
+ expect(document.activeElement).toBe(input);
73
+ act(() => screen.getByRole("button", { name: "Outside" }).focus());
74
+ const oldId = captured.threads.getState().mainThreadId;
75
+ await act(async () => {
76
+ captured.threads.switchToNewThread();
77
+ });
78
+ await waitFor(() =>
79
+ expect(captured.threads.getState().mainThreadId).not.toBe(oldId),
80
+ );
81
+ expect(document.activeElement).toBe(input);
82
+ });
@@ -393,7 +393,8 @@ export const ComposerPrimitiveInput = forwardRef<
393
393
  useEffect(() => {
394
394
  if (
395
395
  aui.composer.getState().type !== "thread" ||
396
- !unstable_focusOnThreadSwitched
396
+ !unstable_focusOnThreadSwitched ||
397
+ !aui.optional.threads
397
398
  )
398
399
  return undefined;
399
400
 
@@ -426,7 +427,7 @@ export const ComposerPrimitiveInput = forwardRef<
426
427
  const isComposing = nativeIsComposing || compositionRef.current;
427
428
  // Standalone tap roots need a synchronous flush while the input is composing.
428
429
  flushTapSync(() => {
429
- aui.composer.setText(e.target.value);
430
+ aui.composer.setText(e.target.value, { origin: "user" });
430
431
  });
431
432
  if (isComposing) return;
432
433
  const pos = e.target.selectionStart ?? e.target.value.length;
@@ -453,7 +454,7 @@ export const ComposerPrimitiveInput = forwardRef<
453
454
  if (!aui.composer.getState().isEditing) return;
454
455
  const target = e.target as HTMLTextAreaElement;
455
456
  flushTapSync(() => {
456
- aui.composer.setText(target.value);
457
+ aui.composer.setText(target.value, { origin: "user" });
457
458
  });
458
459
  const pos = target.selectionStart ?? target.value.length;
459
460
  if (pluginRegistry) {
@@ -77,7 +77,7 @@ describe("TriggerSelectionResource", () => {
77
77
 
78
78
  root.getValue().selectItem(item);
79
79
 
80
- expect(setText).toHaveBeenCalledWith("@file.txt tail");
80
+ expect(setText).toHaveBeenCalledWith("@file.txt tail", { origin: "user" });
81
81
  expect(setCursorPosition).toHaveBeenCalledWith("@file.txt".length + 1);
82
82
  expect(onSelected).toHaveBeenCalledOnce();
83
83
  });
@@ -120,7 +120,7 @@ describe("TriggerSelectionResource", () => {
120
120
 
121
121
  root.getValue().selectItem(item);
122
122
 
123
- expect(setText).toHaveBeenCalledWith("before tail");
123
+ expect(setText).toHaveBeenCalledWith("before tail", { origin: "user" });
124
124
  expect(setCursorPosition).toHaveBeenCalledWith(7);
125
125
  });
126
126
 
@@ -153,7 +153,7 @@ describe("TriggerSelectionResource", () => {
153
153
  root.getValue().selectItem(item);
154
154
 
155
155
  expect(setText).toHaveBeenCalledOnce();
156
- expect(setText).toHaveBeenCalledWith("@file.txt ");
156
+ expect(setText).toHaveBeenCalledWith("@file.txt ", { origin: "user" });
157
157
  expect(textRef.value).toBe("@file.txt ");
158
158
  });
159
159
 
@@ -166,6 +166,8 @@ describe("TriggerSelectionResource", () => {
166
166
 
167
167
  root.getValue().selectItem(item);
168
168
 
169
- expect(setText).toHaveBeenCalledWith("hello @file.txt tail");
169
+ expect(setText).toHaveBeenCalledWith("hello @file.txt tail", {
170
+ origin: "user",
171
+ });
170
172
  });
171
173
  });
@@ -90,6 +90,7 @@ const useTriggerSelectionResource = ({
90
90
  const directive = behavior.formatter.serialize(item);
91
91
  aui.composer.setText(
92
92
  before + directive + (after.startsWith(" ") ? after : ` ${after}`),
93
+ { origin: "user" },
93
94
  );
94
95
  setCursorPosition(before.length + directive.length + 1);
95
96
  };
@@ -101,6 +102,7 @@ const useTriggerSelectionResource = ({
101
102
  if (behavior.removeOnExecute) {
102
103
  aui.composer.setText(
103
104
  before + (after.startsWith(" ") ? after.slice(1) : after),
105
+ { origin: "user" },
104
106
  );
105
107
  setCursorPosition(before.length);
106
108
  } else {
@@ -4,7 +4,7 @@ import { act, render, screen, waitFor } from "@testing-library/react";
4
4
  import type { FC, PropsWithChildren } from "react";
5
5
  import { describe, expect, it, vi } from "vitest";
6
6
  import { AssistantRuntimeProvider } from "../../context";
7
- import { useLocalRuntime } from "../../legacy-runtime/runtime-cores/local/useLocalRuntime";
7
+ import { useLocalRuntime } from "@assistant-ui/core/react";
8
8
  import type {
9
9
  ChatModelAdapter,
10
10
  SpeechSynthesisAdapter,
@@ -0,0 +1,51 @@
1
+ // @vitest-environment jsdom
2
+
3
+ import { cleanup, render } from "@testing-library/react";
4
+ import { afterEach, beforeEach, expect, it, vi } from "vitest";
5
+ import { AuiConfig, AuiProvider } from "@assistant-ui/store";
6
+ import { resource, useResource } from "@assistant-ui/tap";
7
+ import { ExternalThread } from "@assistant-ui/core/store";
8
+ import { ThreadPrimitiveViewport } from "./ThreadViewport";
9
+
10
+ const StandaloneThread = resource(function useStandaloneThread() {
11
+ return useResource(ExternalThread({ messages: [] }));
12
+ });
13
+
14
+ const Harness = ({ standalone }: { standalone: boolean }) => {
15
+ const config = AuiConfig({
16
+ thread: standalone ? StandaloneThread() : ExternalThread({ messages: [] }),
17
+ });
18
+ return (
19
+ <AuiProvider config={config}>
20
+ <ThreadPrimitiveViewport role="region" aria-label="Conversation">
21
+ Conversation content
22
+ </ThreadPrimitiveViewport>
23
+ </AuiProvider>
24
+ );
25
+ };
26
+
27
+ beforeEach(() => {
28
+ vi.stubGlobal(
29
+ "ResizeObserver",
30
+ class {
31
+ observe() {}
32
+ unobserve() {}
33
+ disconnect() {}
34
+ },
35
+ );
36
+ });
37
+
38
+ afterEach(() => {
39
+ cleanup();
40
+ vi.unstubAllGlobals();
41
+ });
42
+
43
+ it.each([true, false])(
44
+ "renders a thread viewport with standalone=%s",
45
+ (standalone) => {
46
+ const view = render(<Harness standalone={standalone} />);
47
+ expect(view.getByRole("region", { name: "Conversation" }).textContent).toBe(
48
+ "Conversation content",
49
+ );
50
+ },
51
+ );
@@ -2,6 +2,7 @@
2
2
 
3
3
  import {
4
4
  useCallback,
5
+ useEffect,
5
6
  useInsertionEffect,
6
7
  useRef,
7
8
  type RefCallback,
@@ -56,7 +57,7 @@ export const useThreadViewportAutoScroll = <TElement extends HTMLElement>({
56
57
  const divRef = useRef<TElement>(null);
57
58
  const hasMessages = useAuiState((s) => s.thread.messages.length > 0);
58
59
  const firstMessageId = useAuiState((s) => s.thread.messages[0]?.id);
59
- const threadId = useAuiState((s) => s.threadListItem.id);
60
+ const threadId = useAuiState((s) => s.optional.threadListItem?.id);
60
61
  const isRunning = useAuiState((s) => s.thread.isRunning);
61
62
  const threadViewportStore = useThreadViewportStore();
62
63
  const binding = getThreadViewportAutoScroll(threadViewportStore);
@@ -105,7 +106,12 @@ export const useThreadViewportAutoScroll = <TElement extends HTMLElement>({
105
106
 
106
107
  useOnScrollToBottom(({ behavior }) => controller.scrollToBottom(behavior));
107
108
  useAuiEvent("thread.runStart", () => controller.runStarted());
108
- useAuiEvent("threads.selectionChanged", () => controller.threadSwitched());
109
+ useEffect(() => {
110
+ if (!aui.optional.threads) return;
111
+ return aui.on("threads.selectionChanged", () =>
112
+ controller.threadSwitched(),
113
+ );
114
+ }, [aui, controller]);
109
115
 
110
116
  return useManagedRef(
111
117
  useCallback(