@assistant-ui/react 0.15.29 → 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 (370) 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/context/stores/ThreadViewport.d.ts +8 -0
  12. package/dist/context/stores/ThreadViewport.d.ts.map +1 -1
  13. package/dist/context/stores/ThreadViewport.js +24 -8
  14. package/dist/context/stores/ThreadViewport.js.map +1 -1
  15. package/dist/index.d.ts +10 -9
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +2 -9
  18. package/dist/internal.d.ts +1 -1
  19. package/dist/internal.d.ts.map +1 -1
  20. package/dist/internal.js +1 -1
  21. package/dist/internal.js.map +1 -1
  22. package/dist/legacy-runtime/AssistantRuntimeProvider.d.ts +1 -1
  23. package/dist/legacy-runtime/AssistantRuntimeProvider.d.ts.map +1 -1
  24. package/dist/legacy-runtime/AssistantRuntimeProvider.js.map +1 -1
  25. package/dist/primitives/actionBar/ActionBarCopy.d.ts +1 -1
  26. package/dist/primitives/actionBar/ActionBarEdit.d.ts +1 -1
  27. package/dist/primitives/actionBar/ActionBarExportMarkdown.d.ts +1 -1
  28. package/dist/primitives/actionBar/ActionBarFeedbackNegative.d.ts +1 -1
  29. package/dist/primitives/actionBar/ActionBarFeedbackPositive.d.ts +1 -1
  30. package/dist/primitives/actionBar/ActionBarReload.d.ts +1 -1
  31. package/dist/primitives/actionBar/ActionBarRoot.d.ts +1 -1
  32. package/dist/primitives/actionBar/ActionBarSpeak.d.ts +1 -1
  33. package/dist/primitives/actionBar/ActionBarStopSpeaking.d.ts +1 -1
  34. package/dist/primitives/attachment/AttachmentRemove.d.ts +1 -1
  35. package/dist/primitives/attachment/AttachmentRoot.d.ts +1 -1
  36. package/dist/primitives/attachment/AttachmentThumb.d.ts +1 -1
  37. package/dist/primitives/branchPicker/BranchPickerNext.d.ts +1 -1
  38. package/dist/primitives/branchPicker/BranchPickerPrevious.d.ts +1 -1
  39. package/dist/primitives/branchPicker/BranchPickerRoot.d.ts +1 -1
  40. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.d.ts +1 -1
  41. package/dist/primitives/chainOfThought/ChainOfThoughtParts.js +1 -2
  42. package/dist/primitives/chainOfThought/ChainOfThoughtRoot.d.ts +1 -1
  43. package/dist/primitives/composer/ComposerAddAttachment.d.ts +1 -1
  44. package/dist/primitives/composer/ComposerAttachments.js +1 -2
  45. package/dist/primitives/composer/ComposerCancel.d.ts +1 -1
  46. package/dist/primitives/composer/ComposerDictate.d.ts +1 -1
  47. package/dist/primitives/composer/ComposerDictationTranscript.d.ts +1 -1
  48. package/dist/primitives/composer/ComposerIf.js +1 -2
  49. package/dist/primitives/composer/ComposerInput.d.ts.map +1 -1
  50. package/dist/primitives/composer/ComposerInput.js +3 -3
  51. package/dist/primitives/composer/ComposerInput.js.map +1 -1
  52. package/dist/primitives/composer/ComposerQueue.js +1 -2
  53. package/dist/primitives/composer/ComposerQuote.d.ts +3 -3
  54. package/dist/primitives/composer/ComposerResume.d.ts +23 -0
  55. package/dist/primitives/composer/ComposerResume.d.ts.map +1 -0
  56. package/dist/primitives/composer/ComposerResume.js +34 -0
  57. package/dist/primitives/composer/ComposerResume.js.map +1 -0
  58. package/dist/primitives/composer/ComposerRoot.d.ts +1 -1
  59. package/dist/primitives/composer/ComposerSend.d.ts +1 -1
  60. package/dist/primitives/composer/ComposerStopDictation.d.ts +1 -1
  61. package/dist/primitives/composer/trigger/TriggerPopover.d.ts +1 -1
  62. package/dist/primitives/composer/trigger/TriggerPopoverBack.d.ts +1 -1
  63. package/dist/primitives/composer/trigger/TriggerPopoverCategories.d.ts +2 -2
  64. package/dist/primitives/composer/trigger/TriggerPopoverItems.d.ts +2 -2
  65. package/dist/primitives/composer/trigger/index.d.ts +1 -1
  66. package/dist/primitives/composer/trigger/triggerSelectionResource.d.ts +6 -2
  67. package/dist/primitives/composer/trigger/triggerSelectionResource.d.ts.map +1 -1
  68. package/dist/primitives/composer/trigger/triggerSelectionResource.js +6 -3
  69. package/dist/primitives/composer/trigger/triggerSelectionResource.js.map +1 -1
  70. package/dist/primitives/composer.d.ts +1 -0
  71. package/dist/primitives/composer.d.ts.map +1 -1
  72. package/dist/primitives/composer.js +3 -1
  73. package/dist/primitives/composer.js.map +1 -1
  74. package/dist/primitives/error/ErrorMessage.d.ts +1 -1
  75. package/dist/primitives/error/ErrorRoot.d.ts +1 -1
  76. package/dist/primitives/message/MessageAttachments.js +1 -2
  77. package/dist/primitives/message/MessageRoot.d.ts +1 -1
  78. package/dist/primitives/messagePart/MessagePartImage.d.ts +1 -1
  79. package/dist/primitives/messagePart/MessagePartInProgress.js +1 -2
  80. package/dist/primitives/messagePart/MessagePartText.d.ts +1 -1
  81. package/dist/primitives/queueItem/QueueItemRemove.d.ts +1 -1
  82. package/dist/primitives/queueItem/QueueItemSteer.d.ts +1 -1
  83. package/dist/primitives/queueItem/QueueItemText.d.ts +1 -1
  84. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.d.ts +1 -1
  85. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.d.ts +1 -1
  86. package/dist/primitives/suggestion/SuggestionDescription.d.ts +1 -1
  87. package/dist/primitives/suggestion/SuggestionTitle.d.ts +1 -1
  88. package/dist/primitives/suggestion/SuggestionTrigger.d.ts +1 -1
  89. package/dist/primitives/thread/ThreadLoadEarlier.d.ts +1 -1
  90. package/dist/primitives/thread/ThreadMessages.js +1 -2
  91. package/dist/primitives/thread/ThreadRoot.d.ts +1 -1
  92. package/dist/primitives/thread/ThreadScrollToBottom.d.ts +1 -1
  93. package/dist/primitives/thread/ThreadSuggestion.d.ts +1 -1
  94. package/dist/primitives/thread/ThreadSuggestions.js +1 -2
  95. package/dist/primitives/thread/ThreadViewport.d.ts +1 -1
  96. package/dist/primitives/thread/ThreadViewportFooter.d.ts +1 -1
  97. package/dist/primitives/thread/useThreadViewportAutoScroll.d.ts.map +1 -1
  98. package/dist/primitives/thread/useThreadViewportAutoScroll.js +36 -293
  99. package/dist/primitives/thread/useThreadViewportAutoScroll.js.map +1 -1
  100. package/dist/primitives/threadList/ThreadListItems.js +1 -2
  101. package/dist/primitives/threadList/ThreadListLoadMore.d.ts +1 -1
  102. package/dist/primitives/threadList/ThreadListNew.d.ts +1 -1
  103. package/dist/primitives/threadList/ThreadListRoot.d.ts +1 -1
  104. package/dist/primitives/threadListFocusGroup.d.ts +1 -1
  105. package/dist/primitives/threadListFocusGroup.d.ts.map +1 -1
  106. package/dist/primitives/threadListItem/ThreadListItemArchive.d.ts +1 -1
  107. package/dist/primitives/threadListItem/ThreadListItemDelete.d.ts +1 -1
  108. package/dist/primitives/threadListItem/ThreadListItemRoot.d.ts +1 -1
  109. package/dist/primitives/threadListItem/ThreadListItemTitle.js +1 -2
  110. package/dist/primitives/threadListItem/ThreadListItemTrigger.d.ts +1 -1
  111. package/dist/primitives/threadListItem/ThreadListItemUnarchive.d.ts +2 -2
  112. package/dist/primitives/threadListItem/ThreadListItemUnarchive.d.ts.map +1 -1
  113. package/dist/primitives/threadListItem/ThreadListItemUnarchive.js +2 -2
  114. package/dist/primitives/threadListItem/ThreadListItemUnarchive.js.map +1 -1
  115. package/dist/unstable/useComposerInput.js +1 -1
  116. package/dist/unstable/useComposerInput.js.map +1 -1
  117. package/dist/unstable/useComposerInputHistory.d.ts.map +1 -1
  118. package/dist/unstable/useComposerInputHistory.js +2 -2
  119. package/dist/unstable/useComposerInputHistory.js.map +1 -1
  120. package/dist/unstable/useLiveCompletionAdapter.d.ts.map +1 -1
  121. package/dist/unstable/useLiveCompletionAdapter.js +3 -2
  122. package/dist/unstable/useLiveCompletionAdapter.js.map +1 -1
  123. package/dist/utils/Primitive.d.ts +17 -17
  124. package/dist/utils/createActionButton.d.ts +1 -1
  125. package/package.json +14 -14
  126. package/src/adapters/OpenAIRealtimeVoiceAdapter.test.ts +14 -1
  127. package/src/cloud-renderer/CloudRendererHost.tsx +4 -2
  128. package/src/context/stores/ThreadViewport.ts +36 -8
  129. package/src/index.ts +11 -8
  130. package/src/internal.ts +1 -1
  131. package/src/legacy-runtime/AssistantRuntimeProvider.tsx +1 -1
  132. package/src/model-context/makeAssistantVisible.test.tsx +25 -37
  133. package/src/primitives/actionBar/ActionBarCopy.test.tsx +57 -0
  134. package/src/primitives/actionBar/ActionBarExportMarkdown.test.tsx +24 -5
  135. package/src/primitives/assistantModal/AssistantModalRoot.test.tsx +1 -1
  136. package/src/primitives/composer/ComposerInput.focus-on-run-start.test.tsx +1 -1
  137. package/src/primitives/composer/ComposerInput.test.tsx +1 -0
  138. package/src/primitives/composer/ComposerInput.text-change.test.tsx +68 -0
  139. package/src/primitives/composer/ComposerInput.thread-scope.test.tsx +82 -0
  140. package/src/primitives/composer/ComposerInput.tsx +5 -4
  141. package/src/primitives/composer/ComposerResume.ts +36 -0
  142. package/src/primitives/composer/trigger/triggerSelectionResource.test.ts +30 -4
  143. package/src/primitives/composer/trigger/triggerSelectionResource.ts +16 -3
  144. package/src/primitives/composer/useAuiState.composer.test.tsx +84 -0
  145. package/src/primitives/composer.ts +1 -0
  146. package/src/primitives/thread/ThreadRoot.test.tsx +1 -1
  147. package/src/primitives/thread/ThreadViewport.thread-scope.test.tsx +51 -0
  148. package/src/primitives/thread/useThreadViewportAutoScroll.test.tsx +90 -0
  149. package/src/primitives/thread/useThreadViewportAutoScroll.ts +56 -488
  150. package/src/primitives/threadListItem/ThreadListItemUnarchive.test.tsx +52 -0
  151. package/src/primitives/threadListItem/ThreadListItemUnarchive.ts +2 -2
  152. package/src/tests/DataRenderers.test.tsx +1 -1
  153. package/src/tests/MessageParts.loading.test.tsx +1 -1
  154. package/src/tests/RemoteThreadListRuntime.adapterProvider.test.tsx +1 -1
  155. package/src/tests/RemoteThreadListRuntime.deferredProvider.test.tsx +4 -2
  156. package/src/tests/RemoteThreadListRuntime.reloadMainThread.test.tsx +4 -2
  157. package/src/tests/generative-ui.primitive.test.tsx +1 -1
  158. package/src/tests/local-runtime-queue.test.tsx +2 -2
  159. package/src/tests/messagePartSwitchRace.test.tsx +2 -2
  160. package/src/tests/messagePartTypeMismatch.test.tsx +1 -1
  161. package/src/tests/threadListItemIsRunning.test.tsx +5 -3
  162. package/src/tests/toolCallTiming.test.tsx +1 -1
  163. package/src/unstable/useComposerInput.test.tsx +1 -1
  164. package/src/unstable/useComposerInput.ts +1 -1
  165. package/src/unstable/useComposerInputHistory.test.tsx +10 -7
  166. package/src/unstable/useComposerInputHistory.thread-scope.test.tsx +123 -0
  167. package/src/unstable/useComposerInputHistory.ts +3 -2
  168. package/src/unstable/useLiveCompletionAdapter.test.tsx +44 -0
  169. package/src/unstable/useLiveCompletionAdapter.ts +3 -2
  170. package/src/unstable/webmcp/convertTools.test.ts +11 -1
  171. package/src/utils/hooks/useMediaQuery.test.tsx +35 -0
  172. package/src/utils/smooth/useSmooth.test.tsx +37 -10
  173. package/dist/context/providers/ChainOfThoughtPartByIndexProvider.d.ts +0 -2
  174. package/dist/context/providers/ChainOfThoughtPartByIndexProvider.d.ts.map +0 -1
  175. package/dist/context/providers/ChainOfThoughtPartByIndexProvider.js +0 -3
  176. package/dist/legacy-runtime/RuntimeAdapter.d.ts +0 -2
  177. package/dist/legacy-runtime/RuntimeAdapter.d.ts.map +0 -1
  178. package/dist/legacy-runtime/RuntimeAdapter.js +0 -2
  179. package/dist/legacy-runtime/cloud/AssistantCloudThreadHistoryAdapter.d.ts +0 -2
  180. package/dist/legacy-runtime/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +0 -1
  181. package/dist/legacy-runtime/cloud/AssistantCloudThreadHistoryAdapter.js +0 -3
  182. package/dist/legacy-runtime/runtime/AssistantRuntime.d.ts +0 -3
  183. package/dist/legacy-runtime/runtime/AssistantRuntime.d.ts.map +0 -1
  184. package/dist/legacy-runtime/runtime/AssistantRuntime.js +0 -2
  185. package/dist/legacy-runtime/runtime/AttachmentRuntime.d.ts +0 -3
  186. package/dist/legacy-runtime/runtime/AttachmentRuntime.d.ts.map +0 -1
  187. package/dist/legacy-runtime/runtime/AttachmentRuntime.js +0 -2
  188. package/dist/legacy-runtime/runtime/ComposerRuntime.d.ts +0 -4
  189. package/dist/legacy-runtime/runtime/ComposerRuntime.d.ts.map +0 -1
  190. package/dist/legacy-runtime/runtime/ComposerRuntime.js +0 -2
  191. package/dist/legacy-runtime/runtime/RuntimeBindings.d.ts +0 -3
  192. package/dist/legacy-runtime/runtime/RuntimeBindings.d.ts.map +0 -1
  193. package/dist/legacy-runtime/runtime/RuntimeBindings.js +0 -0
  194. package/dist/legacy-runtime/runtime/RuntimePathTypes.d.ts +0 -2
  195. package/dist/legacy-runtime/runtime/RuntimePathTypes.d.ts.map +0 -1
  196. package/dist/legacy-runtime/runtime/RuntimePathTypes.js +0 -0
  197. package/dist/legacy-runtime/runtime/ThreadListItemRuntime.d.ts +0 -5
  198. package/dist/legacy-runtime/runtime/ThreadListItemRuntime.d.ts.map +0 -1
  199. package/dist/legacy-runtime/runtime/ThreadListItemRuntime.js +0 -2
  200. package/dist/legacy-runtime/runtime/ThreadRuntime.d.ts +0 -4
  201. package/dist/legacy-runtime/runtime/ThreadRuntime.d.ts.map +0 -1
  202. package/dist/legacy-runtime/runtime/ThreadRuntime.js +0 -2
  203. package/dist/legacy-runtime/runtime-cores/adapters/RuntimeAdapterProvider.d.ts +0 -2
  204. package/dist/legacy-runtime/runtime-cores/adapters/RuntimeAdapterProvider.d.ts.map +0 -1
  205. package/dist/legacy-runtime/runtime-cores/adapters/RuntimeAdapterProvider.js +0 -3
  206. package/dist/legacy-runtime/runtime-cores/adapters/attachment/CloudFileAttachmentAdapter.d.ts +0 -2
  207. package/dist/legacy-runtime/runtime-cores/adapters/attachment/CloudFileAttachmentAdapter.d.ts.map +0 -1
  208. package/dist/legacy-runtime/runtime-cores/adapters/attachment/CloudFileAttachmentAdapter.js +0 -3
  209. package/dist/legacy-runtime/runtime-cores/composer/BaseComposerRuntimeCore.d.ts +0 -2
  210. package/dist/legacy-runtime/runtime-cores/composer/BaseComposerRuntimeCore.d.ts.map +0 -1
  211. package/dist/legacy-runtime/runtime-cores/composer/BaseComposerRuntimeCore.js +0 -2
  212. package/dist/legacy-runtime/runtime-cores/composer/DefaultEditComposerRuntimeCore.d.ts +0 -2
  213. package/dist/legacy-runtime/runtime-cores/composer/DefaultEditComposerRuntimeCore.d.ts.map +0 -1
  214. package/dist/legacy-runtime/runtime-cores/composer/DefaultEditComposerRuntimeCore.js +0 -2
  215. package/dist/legacy-runtime/runtime-cores/composer/DefaultThreadComposerRuntimeCore.d.ts +0 -2
  216. package/dist/legacy-runtime/runtime-cores/composer/DefaultThreadComposerRuntimeCore.d.ts.map +0 -1
  217. package/dist/legacy-runtime/runtime-cores/composer/DefaultThreadComposerRuntimeCore.js +0 -2
  218. package/dist/legacy-runtime/runtime-cores/core/AssistantRuntimeCore.d.ts +0 -2
  219. package/dist/legacy-runtime/runtime-cores/core/AssistantRuntimeCore.d.ts.map +0 -1
  220. package/dist/legacy-runtime/runtime-cores/core/AssistantRuntimeCore.js +0 -0
  221. package/dist/legacy-runtime/runtime-cores/core/BaseAssistantRuntimeCore.d.ts +0 -2
  222. package/dist/legacy-runtime/runtime-cores/core/BaseAssistantRuntimeCore.d.ts.map +0 -1
  223. package/dist/legacy-runtime/runtime-cores/core/BaseAssistantRuntimeCore.js +0 -2
  224. package/dist/legacy-runtime/runtime-cores/core/BaseThreadRuntimeCore.d.ts +0 -2
  225. package/dist/legacy-runtime/runtime-cores/core/BaseThreadRuntimeCore.d.ts.map +0 -1
  226. package/dist/legacy-runtime/runtime-cores/core/BaseThreadRuntimeCore.js +0 -2
  227. package/dist/legacy-runtime/runtime-cores/core/ComposerRuntimeCore.d.ts +0 -2
  228. package/dist/legacy-runtime/runtime-cores/core/ComposerRuntimeCore.d.ts.map +0 -1
  229. package/dist/legacy-runtime/runtime-cores/core/ComposerRuntimeCore.js +0 -0
  230. package/dist/legacy-runtime/runtime-cores/core/ThreadListRuntimeCore.d.ts +0 -2
  231. package/dist/legacy-runtime/runtime-cores/core/ThreadListRuntimeCore.d.ts.map +0 -1
  232. package/dist/legacy-runtime/runtime-cores/core/ThreadListRuntimeCore.js +0 -0
  233. package/dist/legacy-runtime/runtime-cores/core/ThreadRuntimeCore.d.ts +0 -2
  234. package/dist/legacy-runtime/runtime-cores/core/ThreadRuntimeCore.d.ts.map +0 -1
  235. package/dist/legacy-runtime/runtime-cores/core/ThreadRuntimeCore.js +0 -0
  236. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreAdapter.d.ts +0 -2
  237. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreAdapter.d.ts.map +0 -1
  238. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreAdapter.js +0 -0
  239. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreRuntimeCore.d.ts +0 -2
  240. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreRuntimeCore.d.ts.map +0 -1
  241. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreRuntimeCore.js +0 -2
  242. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadListRuntimeCore.d.ts +0 -3
  243. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadListRuntimeCore.d.ts.map +0 -1
  244. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadListRuntimeCore.js +0 -2
  245. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadRuntimeCore.d.ts +0 -2
  246. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadRuntimeCore.d.ts.map +0 -1
  247. package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadRuntimeCore.js +0 -2
  248. package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageConverter.d.ts +0 -3
  249. package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageConverter.d.ts.map +0 -1
  250. package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageConverter.js +0 -2
  251. package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageLike.d.ts +0 -3
  252. package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageLike.d.ts.map +0 -1
  253. package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageLike.js +0 -2
  254. package/dist/legacy-runtime/runtime-cores/external-store/auto-status.d.ts +0 -2
  255. package/dist/legacy-runtime/runtime-cores/external-store/auto-status.d.ts.map +0 -1
  256. package/dist/legacy-runtime/runtime-cores/external-store/auto-status.js +0 -2
  257. package/dist/legacy-runtime/runtime-cores/external-store/createMessageConverter.d.ts +0 -2
  258. package/dist/legacy-runtime/runtime-cores/external-store/createMessageConverter.d.ts.map +0 -1
  259. package/dist/legacy-runtime/runtime-cores/external-store/createMessageConverter.js +0 -3
  260. package/dist/legacy-runtime/runtime-cores/external-store/external-message-converter.d.ts +0 -2
  261. package/dist/legacy-runtime/runtime-cores/external-store/external-message-converter.d.ts.map +0 -1
  262. package/dist/legacy-runtime/runtime-cores/external-store/external-message-converter.js +0 -3
  263. package/dist/legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime.d.ts +0 -2
  264. package/dist/legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime.d.ts.map +0 -1
  265. package/dist/legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime.js +0 -3
  266. package/dist/legacy-runtime/runtime-cores/local/ChatModelAdapter.d.ts +0 -2
  267. package/dist/legacy-runtime/runtime-cores/local/ChatModelAdapter.d.ts.map +0 -1
  268. package/dist/legacy-runtime/runtime-cores/local/ChatModelAdapter.js +0 -0
  269. package/dist/legacy-runtime/runtime-cores/local/LocalRuntimeCore.d.ts +0 -2
  270. package/dist/legacy-runtime/runtime-cores/local/LocalRuntimeCore.d.ts.map +0 -1
  271. package/dist/legacy-runtime/runtime-cores/local/LocalRuntimeCore.js +0 -2
  272. package/dist/legacy-runtime/runtime-cores/local/LocalRuntimeOptions.d.ts +0 -4
  273. package/dist/legacy-runtime/runtime-cores/local/LocalRuntimeOptions.d.ts.map +0 -1
  274. package/dist/legacy-runtime/runtime-cores/local/LocalRuntimeOptions.js +0 -2
  275. package/dist/legacy-runtime/runtime-cores/local/LocalThreadListRuntimeCore.d.ts +0 -3
  276. package/dist/legacy-runtime/runtime-cores/local/LocalThreadListRuntimeCore.d.ts.map +0 -1
  277. package/dist/legacy-runtime/runtime-cores/local/LocalThreadListRuntimeCore.js +0 -2
  278. package/dist/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.d.ts +0 -2
  279. package/dist/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.d.ts.map +0 -1
  280. package/dist/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.js +0 -2
  281. package/dist/legacy-runtime/runtime-cores/local/shouldContinue.d.ts +0 -2
  282. package/dist/legacy-runtime/runtime-cores/local/shouldContinue.d.ts.map +0 -1
  283. package/dist/legacy-runtime/runtime-cores/local/shouldContinue.js +0 -2
  284. package/dist/legacy-runtime/runtime-cores/local/useLocalRuntime.d.ts +0 -2
  285. package/dist/legacy-runtime/runtime-cores/local/useLocalRuntime.d.ts.map +0 -1
  286. package/dist/legacy-runtime/runtime-cores/local/useLocalRuntime.js +0 -3
  287. package/dist/legacy-runtime/runtime-cores/remote-thread-list/BaseSubscribable.d.ts +0 -2
  288. package/dist/legacy-runtime/runtime-cores/remote-thread-list/BaseSubscribable.d.ts.map +0 -1
  289. package/dist/legacy-runtime/runtime-cores/remote-thread-list/BaseSubscribable.js +0 -2
  290. package/dist/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.d.ts +0 -2
  291. package/dist/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.d.ts.map +0 -1
  292. package/dist/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.js +0 -2
  293. package/dist/legacy-runtime/runtime-cores/remote-thread-list/OptimisticState.d.ts +0 -2
  294. package/dist/legacy-runtime/runtime-cores/remote-thread-list/OptimisticState.d.ts.map +0 -1
  295. package/dist/legacy-runtime/runtime-cores/remote-thread-list/OptimisticState.js +0 -2
  296. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.d.ts +0 -2
  297. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.d.ts.map +0 -1
  298. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.js +0 -3
  299. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.d.ts +0 -2
  300. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.d.ts.map +0 -1
  301. package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.js +0 -3
  302. package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud.d.ts +0 -2
  303. package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud.d.ts.map +0 -1
  304. package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud.js +0 -3
  305. package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/in-memory.d.ts +0 -2
  306. package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/in-memory.d.ts.map +0 -1
  307. package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/in-memory.js +0 -2
  308. package/dist/legacy-runtime/runtime-cores/remote-thread-list/types.d.ts +0 -2
  309. package/dist/legacy-runtime/runtime-cores/remote-thread-list/types.d.ts.map +0 -1
  310. package/dist/legacy-runtime/runtime-cores/remote-thread-list/types.js +0 -0
  311. package/dist/legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime.d.ts +0 -2
  312. package/dist/legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime.d.ts.map +0 -1
  313. package/dist/legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime.js +0 -3
  314. package/dist/legacy-runtime/runtime-cores/utils/MessageRepository.d.ts +0 -4
  315. package/dist/legacy-runtime/runtime-cores/utils/MessageRepository.d.ts.map +0 -1
  316. package/dist/legacy-runtime/runtime-cores/utils/MessageRepository.js +0 -3
  317. package/dist/utils/hooks/useOnResizeContent.d.ts +0 -2
  318. package/dist/utils/hooks/useOnResizeContent.d.ts.map +0 -1
  319. package/dist/utils/hooks/useOnResizeContent.js +0 -21
  320. package/dist/utils/hooks/useOnResizeContent.js.map +0 -1
  321. package/src/context/providers/ChainOfThoughtPartByIndexProvider.tsx +0 -3
  322. package/src/legacy-runtime/RuntimeAdapter.ts +0 -1
  323. package/src/legacy-runtime/cloud/AssistantCloudThreadHistoryAdapter.ts +0 -3
  324. package/src/legacy-runtime/runtime/AssistantRuntime.ts +0 -2
  325. package/src/legacy-runtime/runtime/AttachmentRuntime.ts +0 -7
  326. package/src/legacy-runtime/runtime/ComposerRuntime.ts +0 -20
  327. package/src/legacy-runtime/runtime/RuntimeBindings.ts +0 -12
  328. package/src/legacy-runtime/runtime/RuntimePathTypes.ts +0 -8
  329. package/src/legacy-runtime/runtime/ThreadListItemRuntime.ts +0 -10
  330. package/src/legacy-runtime/runtime/ThreadRuntime.ts +0 -14
  331. package/src/legacy-runtime/runtime-cores/adapters/RuntimeAdapterProvider.tsx +0 -7
  332. package/src/legacy-runtime/runtime-cores/adapters/attachment/CloudFileAttachmentAdapter.ts +0 -3
  333. package/src/legacy-runtime/runtime-cores/composer/BaseComposerRuntimeCore.ts +0 -1
  334. package/src/legacy-runtime/runtime-cores/composer/DefaultEditComposerRuntimeCore.ts +0 -1
  335. package/src/legacy-runtime/runtime-cores/composer/DefaultThreadComposerRuntimeCore.ts +0 -1
  336. package/src/legacy-runtime/runtime-cores/core/AssistantRuntimeCore.ts +0 -1
  337. package/src/legacy-runtime/runtime-cores/core/BaseAssistantRuntimeCore.ts +0 -1
  338. package/src/legacy-runtime/runtime-cores/core/BaseThreadRuntimeCore.ts +0 -1
  339. package/src/legacy-runtime/runtime-cores/core/ComposerRuntimeCore.ts +0 -6
  340. package/src/legacy-runtime/runtime-cores/core/ThreadListRuntimeCore.ts +0 -4
  341. package/src/legacy-runtime/runtime-cores/core/ThreadRuntimeCore.ts +0 -13
  342. package/src/legacy-runtime/runtime-cores/external-store/ExternalStoreAdapter.ts +0 -6
  343. package/src/legacy-runtime/runtime-cores/external-store/ExternalStoreRuntimeCore.ts +0 -1
  344. package/src/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadListRuntimeCore.ts +0 -2
  345. package/src/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadRuntimeCore.ts +0 -4
  346. package/src/legacy-runtime/runtime-cores/external-store/ThreadMessageConverter.ts +0 -2
  347. package/src/legacy-runtime/runtime-cores/external-store/ThreadMessageLike.ts +0 -2
  348. package/src/legacy-runtime/runtime-cores/external-store/auto-status.ts +0 -1
  349. package/src/legacy-runtime/runtime-cores/external-store/createMessageConverter.ts +0 -2
  350. package/src/legacy-runtime/runtime-cores/external-store/external-message-converter.ts +0 -7
  351. package/src/legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime.ts +0 -3
  352. package/src/legacy-runtime/runtime-cores/local/ChatModelAdapter.ts +0 -7
  353. package/src/legacy-runtime/runtime-cores/local/LocalRuntimeCore.ts +0 -1
  354. package/src/legacy-runtime/runtime-cores/local/LocalRuntimeOptions.ts +0 -3
  355. package/src/legacy-runtime/runtime-cores/local/LocalThreadListRuntimeCore.ts +0 -2
  356. package/src/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.ts +0 -1
  357. package/src/legacy-runtime/runtime-cores/local/shouldContinue.ts +0 -1
  358. package/src/legacy-runtime/runtime-cores/local/useLocalRuntime.ts +0 -3
  359. package/src/legacy-runtime/runtime-cores/remote-thread-list/BaseSubscribable.ts +0 -1
  360. package/src/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.ts +0 -1
  361. package/src/legacy-runtime/runtime-cores/remote-thread-list/OptimisticState.ts +0 -1
  362. package/src/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.tsx +0 -3
  363. package/src/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.tsx +0 -3
  364. package/src/legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud.tsx +0 -3
  365. package/src/legacy-runtime/runtime-cores/remote-thread-list/adapter/in-memory.ts +0 -1
  366. package/src/legacy-runtime/runtime-cores/remote-thread-list/types.ts +0 -7
  367. package/src/legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime.ts +0 -3
  368. package/src/legacy-runtime/runtime-cores/utils/MessageRepository.ts +0 -3
  369. package/src/model-context/frame/AssistantFrame.test.ts +0 -400
  370. package/src/utils/hooks/useOnResizeContent.ts +0 -15
@@ -136,6 +136,21 @@ const runEditTool = async (
136
136
  await task;
137
137
  };
138
138
 
139
+ const expectDefaultSettleDelay = async (start: () => Promise<unknown>) => {
140
+ await act(async () => {
141
+ const settled = vi.fn();
142
+ const task = start();
143
+ void task.then(settled);
144
+
145
+ await vi.advanceTimersByTimeAsync(1999);
146
+ expect(settled).not.toHaveBeenCalled();
147
+
148
+ await vi.advanceTimersByTimeAsync(1);
149
+ expect(settled).toHaveBeenCalledOnce();
150
+ await task;
151
+ });
152
+ };
153
+
139
154
  describe("makeAssistantVisible", () => {
140
155
  beforeEach(() => {
141
156
  registerMock.mockClear();
@@ -191,21 +206,14 @@ describe("makeAssistantVisible", () => {
191
206
  });
192
207
  const input = render(<EditableInput />).getByRole("textbox");
193
208
  const editId = (input as HTMLInputElement).dataset.editId!;
194
- const setTimeoutSpy = vi.spyOn(globalThis, "setTimeout");
195
209
 
196
210
  expect(
197
211
  (input as HTMLInputElement).dataset.actionSettleDelay,
198
212
  ).toBeUndefined();
199
213
 
200
- const task = getRegisteredTools().edit!.execute({
201
- editId,
202
- value: "updated",
203
- });
204
-
205
- expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), 2000);
206
- await vi.runAllTimersAsync();
207
- await task;
208
- setTimeoutSpy.mockRestore();
214
+ await expectDefaultSettleDelay(() =>
215
+ getRegisteredTools().edit!.execute({ editId, value: "updated" }),
216
+ );
209
217
  });
210
218
 
211
219
  it("uses the default when the rendered settle delay is invalid", async () => {
@@ -218,14 +226,9 @@ describe("makeAssistantVisible", () => {
218
226
  );
219
227
  const clickId = (button as HTMLButtonElement).dataset.clickId!;
220
228
  (button as HTMLButtonElement).dataset.actionSettleDelay = "invalid";
221
- const setTimeoutSpy = vi.spyOn(globalThis, "setTimeout");
222
-
223
- const task = getRegisteredTools().click!.execute({ clickId });
224
-
225
- expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), 2000);
226
- await vi.runAllTimersAsync();
227
- await task;
228
- setTimeoutSpy.mockRestore();
229
+ await expectDefaultSettleDelay(() =>
230
+ getRegisteredTools().click!.execute({ clickId }),
231
+ );
229
232
  });
230
233
 
231
234
  it.each(["", " "])(
@@ -239,29 +242,14 @@ describe("makeAssistantVisible", () => {
239
242
  const input = render(<VisibleInput />).getByRole("textbox");
240
243
  const clickId = (input as HTMLInputElement).dataset.clickId!;
241
244
  const editId = (input as HTMLInputElement).dataset.editId!;
242
- const setTimeoutSpy = vi.spyOn(globalThis, "setTimeout");
243
245
  input.dataset.actionSettleDelay = renderedDelay;
244
246
 
245
- const clickTask = getRegisteredTools().click!.execute({ clickId });
246
- expect(setTimeoutSpy).toHaveBeenLastCalledWith(
247
- expect.any(Function),
248
- 2000,
247
+ await expectDefaultSettleDelay(() =>
248
+ getRegisteredTools().click!.execute({ clickId }),
249
249
  );
250
- await vi.runAllTimersAsync();
251
- await clickTask;
252
-
253
- setTimeoutSpy.mockClear();
254
- const editTask = getRegisteredTools().edit!.execute({
255
- editId,
256
- value: "updated",
257
- });
258
- expect(setTimeoutSpy).toHaveBeenLastCalledWith(
259
- expect.any(Function),
260
- 2000,
250
+ await expectDefaultSettleDelay(() =>
251
+ getRegisteredTools().edit!.execute({ editId, value: "updated" }),
261
252
  );
262
- await vi.runAllTimersAsync();
263
- await editTask;
264
- setTimeoutSpy.mockRestore();
265
253
  },
266
254
  );
267
255
 
@@ -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
 
@@ -424,9 +425,9 @@ export const ComposerPrimitiveInput = forwardRef<
424
425
  compositionRef.current = false;
425
426
  }
426
427
  const isComposing = nativeIsComposing || compositionRef.current;
427
- // keep controlled value in sync mid-IME so react does not reset the textarea to a stale value
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) {
@@ -0,0 +1,36 @@
1
+ "use client";
2
+
3
+ import { useCallback } from "react";
4
+ import { useComposerResume as useComposerResumeBehavior } from "@assistant-ui/core/react";
5
+ import {
6
+ createActionButton,
7
+ type ActionButtonElement,
8
+ type ActionButtonProps,
9
+ } from "../../utils/createActionButton";
10
+
11
+ const useComposerResume = () => {
12
+ const { disabled, resume } = useComposerResumeBehavior();
13
+ const callback = useCallback(() => resume(), [resume]);
14
+ if (disabled) return null;
15
+ return callback;
16
+ };
17
+
18
+ export namespace ComposerPrimitiveResume {
19
+ export type Element = ActionButtonElement;
20
+ export type Props = ActionButtonProps<typeof useComposerResume>;
21
+ }
22
+
23
+ /**
24
+ * Resumes an interrupted run when its adapter explicitly reports a checkpoint.
25
+ *
26
+ * @example
27
+ * ```tsx
28
+ * <ComposerPrimitive.Resume>
29
+ * Resume
30
+ * </ComposerPrimitive.Resume>
31
+ * ```
32
+ */
33
+ export const ComposerPrimitiveResume = createActionButton(
34
+ "ComposerPrimitive.Resume",
35
+ useComposerResume,
36
+ );
@@ -77,11 +77,35 @@ 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
  });
84
84
 
85
+ it("reports an inserted directive once a select override finishes the insertion", () => {
86
+ const onInserted = vi.fn();
87
+ const { root, setText, onSelected } = render({
88
+ behavior: { kind: "directive", formatter, onInserted },
89
+ text: "@file tail",
90
+ trigger: { offset: 0, query: "file", endOffset: 5 },
91
+ });
92
+ let finishInsertion: (() => void) | undefined;
93
+ root.getValue().registerSelectItemOverride((_, onOverrideInserted) => {
94
+ finishInsertion = onOverrideInserted;
95
+ return true;
96
+ });
97
+
98
+ root.getValue().selectItem(item);
99
+
100
+ expect(onInserted).not.toHaveBeenCalled();
101
+ expect(setText).not.toHaveBeenCalled();
102
+ expect(onSelected).toHaveBeenCalledOnce();
103
+
104
+ finishInsertion?.();
105
+
106
+ expect(onInserted).toHaveBeenCalledExactlyOnceWith(item);
107
+ });
108
+
85
109
  it("resynchronizes the cursor after removing an action", () => {
86
110
  const { root, setText, setCursorPosition } = render({
87
111
  behavior: {
@@ -96,7 +120,7 @@ describe("TriggerSelectionResource", () => {
96
120
 
97
121
  root.getValue().selectItem(item);
98
122
 
99
- expect(setText).toHaveBeenCalledWith("before tail");
123
+ expect(setText).toHaveBeenCalledWith("before tail", { origin: "user" });
100
124
  expect(setCursorPosition).toHaveBeenCalledWith(7);
101
125
  });
102
126
 
@@ -129,7 +153,7 @@ describe("TriggerSelectionResource", () => {
129
153
  root.getValue().selectItem(item);
130
154
 
131
155
  expect(setText).toHaveBeenCalledOnce();
132
- expect(setText).toHaveBeenCalledWith("@file.txt ");
156
+ expect(setText).toHaveBeenCalledWith("@file.txt ", { origin: "user" });
133
157
  expect(textRef.value).toBe("@file.txt ");
134
158
  });
135
159
 
@@ -142,6 +166,8 @@ describe("TriggerSelectionResource", () => {
142
166
 
143
167
  root.getValue().selectItem(item);
144
168
 
145
- expect(setText).toHaveBeenCalledWith("hello @file.txt tail");
169
+ expect(setText).toHaveBeenCalledWith("hello @file.txt tail", {
170
+ origin: "user",
171
+ });
146
172
  });
147
173
  });
@@ -7,8 +7,15 @@ import type {
7
7
  import type { AssistantClient } from "@assistant-ui/store";
8
8
  import type { DetectedTrigger } from "./triggerDetectionResource";
9
9
 
10
- /** External override for selection (used by Lexical's DirectivePlugin). */
11
- export type SelectItemOverride = (item: Unstable_TriggerItem) => boolean;
10
+ /**
11
+ * External override for selection (used by Lexical's DirectivePlugin).
12
+ * Returns whether it handled the item, and calls `onInserted` once the
13
+ * insertion has reached the composer.
14
+ */
15
+ export type SelectItemOverride = (
16
+ item: Unstable_TriggerItem,
17
+ onInserted: () => void,
18
+ ) => boolean;
12
19
 
13
20
  export type TriggerBehavior =
14
21
  | {
@@ -66,7 +73,11 @@ const useTriggerSelectionResource = ({
66
73
  const selectItem = useEffectEvent((item: Unstable_TriggerItem) => {
67
74
  if (!trigger || !behavior) return;
68
75
 
69
- if (selectItemOverrideRef.current?.(item)) {
76
+ const reportInserted = () => {
77
+ if (behavior.kind === "directive") behavior.onInserted?.(item);
78
+ };
79
+
80
+ if (selectItemOverrideRef.current?.(item, reportInserted)) {
70
81
  onSelected();
71
82
  return;
72
83
  }
@@ -79,6 +90,7 @@ const useTriggerSelectionResource = ({
79
90
  const directive = behavior.formatter.serialize(item);
80
91
  aui.composer.setText(
81
92
  before + directive + (after.startsWith(" ") ? after : ` ${after}`),
93
+ { origin: "user" },
82
94
  );
83
95
  setCursorPosition(before.length + directive.length + 1);
84
96
  };
@@ -90,6 +102,7 @@ const useTriggerSelectionResource = ({
90
102
  if (behavior.removeOnExecute) {
91
103
  aui.composer.setText(
92
104
  before + (after.startsWith(" ") ? after.slice(1) : after),
105
+ { origin: "user" },
93
106
  );
94
107
  setCursorPosition(before.length);
95
108
  } else {
@@ -0,0 +1,84 @@
1
+ /** @vitest-environment jsdom */
2
+ import { fireEvent, render, screen, waitFor } from "@testing-library/react";
3
+ import { useState } from "react";
4
+ import { describe, expect, it } from "vitest";
5
+ import {
6
+ AssistantRuntimeProvider,
7
+ useExternalStoreRuntime,
8
+ } from "@assistant-ui/core/react";
9
+ import type { ThreadMessage } from "@assistant-ui/core";
10
+ import { useAui, useAuiState } from "@assistant-ui/store";
11
+
12
+ function Input({
13
+ value,
14
+ onChange,
15
+ withOwnState,
16
+ }: {
17
+ value: string;
18
+ onChange: (value: string) => void;
19
+ withOwnState: boolean;
20
+ }) {
21
+ const [, setChangeCount] = useState(0);
22
+ return (
23
+ <textarea
24
+ aria-label="composer"
25
+ value={value}
26
+ onChange={(event) => {
27
+ if (withOwnState) setChangeCount((count) => count + 1);
28
+ onChange(event.target.value);
29
+ }}
30
+ />
31
+ );
32
+ }
33
+
34
+ function BoundInput({ withOwnState }: { withOwnState: boolean }) {
35
+ const aui = useAui();
36
+ const text = useAuiState((s) => s.composer.text);
37
+ return (
38
+ <>
39
+ <button onClick={() => aui.composer.setText("hello world")}>seed</button>
40
+ <Input
41
+ value={text}
42
+ onChange={(value) => aui.composer.setText(value)}
43
+ withOwnState={withOwnState}
44
+ />
45
+ </>
46
+ );
47
+ }
48
+
49
+ function App({ withOwnState }: { withOwnState: boolean }) {
50
+ const runtime = useExternalStoreRuntime<ThreadMessage>({
51
+ messages: [],
52
+ convertMessage: (message) => message,
53
+ onNew: async () => {},
54
+ });
55
+ return (
56
+ <AssistantRuntimeProvider runtime={runtime}>
57
+ <BoundInput withOwnState={withOwnState} />
58
+ </AssistantRuntimeProvider>
59
+ );
60
+ }
61
+
62
+ describe("composer state in controlled inputs", () => {
63
+ it.each([
64
+ ["mentions-like", true],
65
+ ["plain textarea", false],
66
+ ])(
67
+ "keeps the caret after typing in the middle: %s",
68
+ async (_, withOwnState) => {
69
+ render(<App withOwnState={withOwnState} />);
70
+ fireEvent.click(screen.getByRole("button", { name: "seed" }));
71
+ const input = screen.getByRole("textbox", {
72
+ name: "composer",
73
+ }) as HTMLTextAreaElement;
74
+ await waitFor(() => expect(input.value).toBe("hello world"));
75
+
76
+ input.setSelectionRange(5, 5);
77
+ fireEvent.change(input, {
78
+ target: { value: "helloX world", selectionStart: 6, selectionEnd: 6 },
79
+ });
80
+ await waitFor(() => expect(input.value).toBe("helloX world"));
81
+ expect(input.selectionStart).toBe(6);
82
+ },
83
+ );
84
+ });
@@ -3,6 +3,7 @@ import type { TriggerMatch, TriggerMatcher } from "./composer/trigger";
3
3
  export { ComposerPrimitiveRoot as Root } from "./composer/ComposerRoot";
4
4
  export { ComposerPrimitiveInput as Input } from "./composer/ComposerInput";
5
5
  export { ComposerPrimitiveSend as Send } from "./composer/ComposerSend";
6
+ export { ComposerPrimitiveResume as Resume } from "./composer/ComposerResume";
6
7
  export { ComposerPrimitiveCancel as Cancel } from "./composer/ComposerCancel";
7
8
  export { ComposerPrimitiveAddAttachment as AddAttachment } from "./composer/ComposerAddAttachment";
8
9
  export { ComposerPrimitiveAttachments as Attachments } from "./composer/ComposerAttachments";
@@ -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,