@assistant-ui/core 0.3.13 → 0.3.15

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 (463) hide show
  1. package/dist/adapters/speech.d.ts.map +1 -1
  2. package/dist/adapters/speech.js +9 -15
  3. package/dist/adapters/speech.js.map +1 -1
  4. package/dist/adapters/thread-history.d.ts +2 -0
  5. package/dist/adapters/thread-history.d.ts.map +1 -1
  6. package/dist/adapters/voice.d.ts.map +1 -1
  7. package/dist/adapters/voice.js +38 -15
  8. package/dist/adapters/voice.js.map +1 -1
  9. package/dist/index.d.ts +2 -2
  10. package/dist/index.js +1 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/internal.d.ts +3 -2
  13. package/dist/internal.js +8 -7
  14. package/dist/model-context/frame/host.d.ts +1 -1
  15. package/dist/model-context/frame/host.d.ts.map +1 -1
  16. package/dist/model-context/frame/host.js +19 -4
  17. package/dist/model-context/frame/host.js.map +1 -1
  18. package/dist/model-context/frame/provider.d.ts +4 -0
  19. package/dist/model-context/frame/provider.d.ts.map +1 -1
  20. package/dist/model-context/frame/provider.js +50 -3
  21. package/dist/model-context/frame/provider.js.map +1 -1
  22. package/dist/model-context/frame/types.d.ts +4 -1
  23. package/dist/model-context/frame/types.d.ts.map +1 -1
  24. package/dist/model-context/frame/types.js.map +1 -1
  25. package/dist/model-context/registry.d.ts.map +1 -1
  26. package/dist/model-context/registry.js +16 -4
  27. package/dist/model-context/registry.js.map +1 -1
  28. package/dist/react/RuntimeAdapter.d.ts +8 -1
  29. package/dist/react/RuntimeAdapter.d.ts.map +1 -1
  30. package/dist/react/RuntimeAdapter.js +23 -18
  31. package/dist/react/RuntimeAdapter.js.map +1 -1
  32. package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
  33. package/dist/react/adapters/LocalStorageThreadListAdapter.js +28 -12
  34. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  35. package/dist/react/client/AdaptedRemoteThread.d.ts +11 -0
  36. package/dist/react/client/AdaptedRemoteThread.d.ts.map +1 -0
  37. package/dist/react/client/AdaptedRemoteThread.js +27 -0
  38. package/dist/react/client/AdaptedRemoteThread.js.map +1 -0
  39. package/dist/react/client/InMemoryThreadList.d.ts +19 -0
  40. package/dist/react/client/InMemoryThreadList.d.ts.map +1 -0
  41. package/dist/react/client/InMemoryThreadList.js +418 -0
  42. package/dist/react/client/InMemoryThreadList.js.map +1 -0
  43. package/dist/react/client/Interactables.d.ts.map +1 -1
  44. package/dist/react/client/Interactables.js +159 -102
  45. package/dist/react/client/Interactables.js.map +1 -1
  46. package/dist/react/client/RemoteThreadList.d.ts +34 -0
  47. package/dist/react/client/RemoteThreadList.d.ts.map +1 -0
  48. package/dist/react/client/RemoteThreadList.js +898 -0
  49. package/dist/react/client/RemoteThreadList.js.map +1 -0
  50. package/dist/react/client/Tools.d.ts.map +1 -1
  51. package/dist/react/client/Tools.js +38 -27
  52. package/dist/react/client/Tools.js.map +1 -1
  53. package/dist/react/index.d.ts +7 -2
  54. package/dist/react/index.js +5 -2
  55. package/dist/react/interactables-legacy/Interactables.d.ts.map +1 -1
  56. package/dist/react/interactables-legacy/Interactables.js +145 -110
  57. package/dist/react/interactables-legacy/Interactables.js.map +1 -1
  58. package/dist/react/primitive-hooks/useActionBarCopy.d.ts.map +1 -1
  59. package/dist/react/primitive-hooks/useActionBarCopy.js +20 -19
  60. package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
  61. package/dist/react/primitive-hooks/useActionBarEdit.d.ts.map +1 -1
  62. package/dist/react/primitive-hooks/useActionBarEdit.js +2 -4
  63. package/dist/react/primitive-hooks/useActionBarEdit.js.map +1 -1
  64. package/dist/react/primitive-hooks/useActionBarReload.d.ts.map +1 -1
  65. package/dist/react/primitive-hooks/useActionBarReload.js +2 -4
  66. package/dist/react/primitive-hooks/useActionBarReload.js.map +1 -1
  67. package/dist/react/primitive-hooks/useBranchPickerNext.d.ts.map +1 -1
  68. package/dist/react/primitive-hooks/useBranchPickerNext.js +2 -6
  69. package/dist/react/primitive-hooks/useBranchPickerNext.js.map +1 -1
  70. package/dist/react/primitive-hooks/useBranchPickerPrevious.d.ts.map +1 -1
  71. package/dist/react/primitive-hooks/useBranchPickerPrevious.js +2 -6
  72. package/dist/react/primitive-hooks/useBranchPickerPrevious.js.map +1 -1
  73. package/dist/react/primitive-hooks/useComposerCancel.d.ts.map +1 -1
  74. package/dist/react/primitive-hooks/useComposerCancel.js +2 -4
  75. package/dist/react/primitive-hooks/useComposerCancel.js.map +1 -1
  76. package/dist/react/primitive-hooks/useComposerSend.d.ts.map +1 -1
  77. package/dist/react/primitive-hooks/useComposerSend.js +2 -4
  78. package/dist/react/primitive-hooks/useComposerSend.js.map +1 -1
  79. package/dist/react/primitive-hooks/useSuggestionTrigger.d.ts.map +1 -1
  80. package/dist/react/primitive-hooks/useSuggestionTrigger.js +6 -2
  81. package/dist/react/primitive-hooks/useSuggestionTrigger.js.map +1 -1
  82. package/dist/react/primitive-hooks/useThreadIsEmpty.d.ts +3 -0
  83. package/dist/react/primitive-hooks/useThreadIsEmpty.d.ts.map +1 -1
  84. package/dist/react/primitive-hooks/useThreadIsEmpty.js +3 -0
  85. package/dist/react/primitive-hooks/useThreadIsEmpty.js.map +1 -1
  86. package/dist/react/primitive-hooks/useThreadIsRunning.d.ts +3 -0
  87. package/dist/react/primitive-hooks/useThreadIsRunning.d.ts.map +1 -1
  88. package/dist/react/primitive-hooks/useThreadIsRunning.js +3 -0
  89. package/dist/react/primitive-hooks/useThreadIsRunning.js.map +1 -1
  90. package/dist/react/primitives/message/MessageParts.d.ts +13 -0
  91. package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
  92. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  93. package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
  94. package/dist/react/primitives/thread/ThreadMessages.js +1 -1
  95. package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
  96. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +24 -10
  97. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  98. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +115 -71
  99. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  100. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +14 -2
  101. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  102. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +232 -63
  103. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  104. package/dist/react/runtimes/RemoteThreadResource.d.ts +30 -0
  105. package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -0
  106. package/dist/react/runtimes/RemoteThreadResource.js +136 -0
  107. package/dist/react/runtimes/RemoteThreadResource.js.map +1 -0
  108. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts +3 -10
  109. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts.map +1 -1
  110. package/dist/react/runtimes/RuntimeAdapterProvider.js +3 -6
  111. package/dist/react/runtimes/RuntimeAdapterProvider.js.map +1 -1
  112. package/dist/react/runtimes/assistant-transport/commandQueue.d.ts +17 -0
  113. package/dist/react/runtimes/assistant-transport/commandQueue.d.ts.map +1 -0
  114. package/dist/react/runtimes/assistant-transport/commandQueue.js +55 -0
  115. package/dist/react/runtimes/assistant-transport/commandQueue.js.map +1 -0
  116. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.d.ts +11 -0
  117. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.d.ts.map +1 -0
  118. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.js +165 -0
  119. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.js.map +1 -0
  120. package/dist/react/runtimes/assistant-transport/runManager.d.ts +15 -0
  121. package/dist/react/runtimes/assistant-transport/runManager.d.ts.map +1 -0
  122. package/dist/react/runtimes/assistant-transport/runManager.js +86 -0
  123. package/dist/react/runtimes/assistant-transport/runManager.js.map +1 -0
  124. package/dist/react/runtimes/assistant-transport/types.d.ts +130 -0
  125. package/dist/react/runtimes/assistant-transport/types.d.ts.map +1 -0
  126. package/dist/react/runtimes/assistant-transport/types.js +0 -0
  127. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts +14 -0
  128. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -0
  129. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js +296 -0
  130. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js.map +1 -0
  131. package/dist/react/runtimes/assistant-transport/useConvertedState.d.ts +7 -0
  132. package/dist/react/runtimes/assistant-transport/useConvertedState.d.ts.map +1 -0
  133. package/dist/react/runtimes/assistant-transport/useConvertedState.js +25 -0
  134. package/dist/react/runtimes/assistant-transport/useConvertedState.js.map +1 -0
  135. package/dist/react/runtimes/assistant-transport/useLatestRef.d.ts +7 -0
  136. package/dist/react/runtimes/assistant-transport/useLatestRef.d.ts.map +1 -0
  137. package/dist/react/runtimes/assistant-transport/useLatestRef.js +27 -0
  138. package/dist/react/runtimes/assistant-transport/useLatestRef.js.map +1 -0
  139. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  140. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +39 -13
  141. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  142. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +2 -1
  143. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
  144. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +3 -3
  145. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
  146. package/dist/react/runtimes/cloud/auiV0.d.ts +4 -0
  147. package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
  148. package/dist/react/runtimes/cloud/auiV0.js +7 -0
  149. package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
  150. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  151. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +60 -17
  152. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  153. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.d.ts +16 -0
  154. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.d.ts.map +1 -0
  155. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js +36 -0
  156. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js.map +1 -0
  157. package/dist/react/runtimes/external-message-converter.js +14 -14
  158. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  159. package/dist/react/runtimes/useExternalStoreRuntime.d.ts.map +1 -1
  160. package/dist/react/runtimes/useExternalStoreRuntime.js +44 -28
  161. package/dist/react/runtimes/useExternalStoreRuntime.js.map +1 -1
  162. package/dist/react/runtimes/useExternalStoreSharedOptions.js.map +1 -1
  163. package/dist/react/runtimes/useLocalRuntime.js +1 -1
  164. package/dist/react/runtimes/useRuntimeAdapters.d.ts +9 -0
  165. package/dist/react/runtimes/useRuntimeAdapters.d.ts.map +1 -0
  166. package/dist/react/runtimes/useRuntimeAdapters.js +20 -0
  167. package/dist/react/runtimes/useRuntimeAdapters.js.map +1 -0
  168. package/dist/runtime/api/composer-runtime.d.ts +5 -0
  169. package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
  170. package/dist/runtime/api/composer-runtime.js.map +1 -1
  171. package/dist/runtime/api/message-runtime.js +1 -1
  172. package/dist/runtime/api/thread-list-runtime.d.ts +1 -0
  173. package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
  174. package/dist/runtime/api/thread-list-runtime.js +4 -2
  175. package/dist/runtime/api/thread-list-runtime.js.map +1 -1
  176. package/dist/runtime/api/thread-runtime.d.ts +12 -2
  177. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  178. package/dist/runtime/api/thread-runtime.js +8 -2
  179. package/dist/runtime/api/thread-runtime.js.map +1 -1
  180. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  181. package/dist/runtime/base/base-composer-runtime-core.js +8 -7
  182. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  183. package/dist/runtime/base/base-thread-runtime-core.d.ts +1 -0
  184. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  185. package/dist/runtime/base/base-thread-runtime-core.js +3 -3
  186. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  187. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +0 -1
  188. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
  189. package/dist/runtime/base/default-thread-composer-runtime-core.js +10 -4
  190. package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
  191. package/dist/runtime/interfaces/thread-runtime-core.d.ts +6 -0
  192. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  193. package/dist/runtime/internal.js +5 -5
  194. package/dist/runtime/queue/message-queue.d.ts.map +1 -1
  195. package/dist/runtime/queue/message-queue.js +2 -1
  196. package/dist/runtime/queue/message-queue.js.map +1 -1
  197. package/dist/runtime/utils/message-repository.d.ts.map +1 -1
  198. package/dist/runtime/utils/message-repository.js +27 -18
  199. package/dist/runtime/utils/message-repository.js.map +1 -1
  200. package/dist/runtime/utils/thread-runtime-lifecycle.d.ts +8 -0
  201. package/dist/runtime/utils/thread-runtime-lifecycle.d.ts.map +1 -0
  202. package/dist/runtime/utils/thread-runtime-lifecycle.js +11 -0
  203. package/dist/runtime/utils/thread-runtime-lifecycle.js.map +1 -0
  204. package/dist/runtimes/external-store/external-store-shared-options.js.map +1 -1
  205. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  206. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +4 -1
  207. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  208. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +8 -0
  209. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  210. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +37 -13
  211. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  212. package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts +102 -0
  213. package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts.map +1 -0
  214. package/dist/runtimes/inert/InertThreadRuntimeCore.js +156 -0
  215. package/dist/runtimes/inert/InertThreadRuntimeCore.js.map +1 -0
  216. package/dist/runtimes/internal.d.ts +1 -1
  217. package/dist/runtimes/local/local-thread-runtime-core.d.ts +3 -0
  218. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  219. package/dist/runtimes/local/local-thread-runtime-core.js +78 -19
  220. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  221. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +12 -59
  222. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
  223. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +10 -142
  224. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
  225. package/dist/runtimes/remote-thread-list/adapter-changed.d.ts +9 -0
  226. package/dist/runtimes/remote-thread-list/adapter-changed.d.ts.map +1 -0
  227. package/dist/runtimes/remote-thread-list/adapter-changed.js +13 -0
  228. package/dist/runtimes/remote-thread-list/adapter-changed.js.map +1 -0
  229. package/dist/runtimes/remote-thread-list/empty-thread-core.d.ts.map +1 -1
  230. package/dist/runtimes/remote-thread-list/empty-thread-core.js +16 -152
  231. package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
  232. package/dist/runtimes/remote-thread-list/optimistic-state.d.ts +2 -0
  233. package/dist/runtimes/remote-thread-list/optimistic-state.d.ts.map +1 -1
  234. package/dist/runtimes/remote-thread-list/optimistic-state.js +11 -0
  235. package/dist/runtimes/remote-thread-list/optimistic-state.js.map +1 -1
  236. package/dist/runtimes/remote-thread-list/types.d.ts +32 -1
  237. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  238. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +1 -12
  239. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
  240. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +67 -38
  241. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
  242. package/dist/store/clients/external-thread.js +1 -1
  243. package/dist/store/clients/external-thread.js.map +1 -1
  244. package/dist/store/clients/suggestions.js +2 -2
  245. package/dist/store/clients/suggestions.js.map +1 -1
  246. package/dist/store/clients/thread-selection-events.d.ts +10 -0
  247. package/dist/store/clients/thread-selection-events.d.ts.map +1 -0
  248. package/dist/store/clients/thread-selection-events.js +40 -0
  249. package/dist/store/clients/thread-selection-events.js.map +1 -0
  250. package/dist/store/env.d.ts +5 -0
  251. package/dist/store/env.d.ts.map +1 -0
  252. package/dist/store/env.js +12 -0
  253. package/dist/store/env.js.map +1 -0
  254. package/dist/store/index.d.ts +5 -3
  255. package/dist/store/index.js +4 -2
  256. package/dist/store/internal.d.ts +4 -1
  257. package/dist/store/internal.js +4 -1
  258. package/dist/store/primitive-predicates.d.ts +19 -0
  259. package/dist/store/primitive-predicates.d.ts.map +1 -0
  260. package/dist/store/primitive-predicates.js +19 -0
  261. package/dist/store/primitive-predicates.js.map +1 -0
  262. package/dist/store/runtime-clients/attachment-runtime-client.d.ts.map +1 -1
  263. package/dist/store/runtime-clients/attachment-runtime-client.js +18 -11
  264. package/dist/store/runtime-clients/attachment-runtime-client.js.map +1 -1
  265. package/dist/store/runtime-clients/handle-runtime-action.d.ts +5 -0
  266. package/dist/store/runtime-clients/handle-runtime-action.d.ts.map +1 -0
  267. package/dist/store/runtime-clients/handle-runtime-action.js +14 -0
  268. package/dist/store/runtime-clients/handle-runtime-action.js.map +1 -0
  269. package/dist/store/runtime-clients/handle-thread-list-action.d.ts +5 -0
  270. package/dist/store/runtime-clients/handle-thread-list-action.d.ts.map +1 -0
  271. package/dist/store/runtime-clients/handle-thread-list-action.js +7 -0
  272. package/dist/store/runtime-clients/handle-thread-list-action.js.map +1 -0
  273. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  274. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +62 -29
  275. package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
  276. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
  277. package/dist/store/runtime-clients/thread-list-runtime-client.js +5 -6
  278. package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
  279. package/dist/store/scopes/composer.d.ts +9 -4
  280. package/dist/store/scopes/composer.d.ts.map +1 -1
  281. package/dist/store/scopes/thread-list-item.d.ts +7 -6
  282. package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
  283. package/dist/store/scopes/thread.d.ts +8 -7
  284. package/dist/store/scopes/thread.d.ts.map +1 -1
  285. package/dist/store/scopes/threads.d.ts +17 -1
  286. package/dist/store/scopes/threads.d.ts.map +1 -1
  287. package/dist/subscribable/subscribable.d.ts +2 -1
  288. package/dist/subscribable/subscribable.d.ts.map +1 -1
  289. package/dist/subscribable/subscribable.js +23 -18
  290. package/dist/subscribable/subscribable.js.map +1 -1
  291. package/dist/types/message.d.ts +1 -1
  292. package/dist/types/message.js.map +1 -1
  293. package/dist/utils/composite-context-provider.d.ts +1 -0
  294. package/dist/utils/composite-context-provider.d.ts.map +1 -1
  295. package/dist/utils/composite-context-provider.js +25 -9
  296. package/dist/utils/composite-context-provider.js.map +1 -1
  297. package/dist/utils/notify-event-listeners.d.ts +2 -2
  298. package/dist/utils/notify-event-listeners.d.ts.map +1 -1
  299. package/dist/utils/notify-event-listeners.js +2 -2
  300. package/dist/utils/notify-event-listeners.js.map +1 -1
  301. package/dist/utils/silent-runtime-action.d.ts +6 -0
  302. package/dist/utils/silent-runtime-action.d.ts.map +1 -0
  303. package/dist/utils/silent-runtime-action.js +7 -0
  304. package/dist/utils/silent-runtime-action.js.map +1 -0
  305. package/package.json +8 -8
  306. package/src/adapters/speech.test.ts +118 -1
  307. package/src/adapters/speech.ts +21 -22
  308. package/src/adapters/thread-history.ts +2 -0
  309. package/src/adapters/voice.test.ts +134 -0
  310. package/src/adapters/voice.ts +35 -27
  311. package/src/index.ts +1 -0
  312. package/src/internal.ts +1 -0
  313. package/src/model-context/frame/host.test.ts +87 -5
  314. package/src/model-context/frame/host.ts +18 -4
  315. package/src/model-context/frame/provider.test.ts +347 -20
  316. package/src/model-context/frame/provider.ts +58 -2
  317. package/src/model-context/frame/types.ts +5 -0
  318. package/src/model-context/registry.test.ts +131 -0
  319. package/src/model-context/registry.ts +16 -6
  320. package/src/react/RuntimeAdapter.test.ts +2 -0
  321. package/src/react/RuntimeAdapter.ts +20 -8
  322. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +34 -17
  323. package/src/react/client/AdaptedRemoteThread.ts +41 -0
  324. package/src/react/client/InMemoryThreadList.test.tsx +148 -0
  325. package/src/react/client/InMemoryThreadList.ts +290 -0
  326. package/src/react/client/Interactables.test.ts +326 -2
  327. package/src/react/client/Interactables.ts +227 -110
  328. package/src/react/client/RemoteThreadList.test.ts +1222 -0
  329. package/src/react/client/RemoteThreadList.ts +1136 -0
  330. package/src/react/client/Tools.ts +36 -29
  331. package/src/react/index.ts +13 -0
  332. package/src/react/interactables-legacy/Interactables.test.ts +317 -0
  333. package/src/react/interactables-legacy/Interactables.ts +204 -128
  334. package/src/react/primitive-hooks/useActionBarCopy.test.ts +15 -0
  335. package/src/react/primitive-hooks/useActionBarCopy.ts +15 -10
  336. package/src/react/primitive-hooks/useActionBarEdit.ts +2 -1
  337. package/src/react/primitive-hooks/useActionBarReload.ts +2 -6
  338. package/src/react/primitive-hooks/useBranchPickerNext.ts +2 -7
  339. package/src/react/primitive-hooks/useBranchPickerPrevious.ts +2 -7
  340. package/src/react/primitive-hooks/useComposerCancel.ts +2 -1
  341. package/src/react/primitive-hooks/useComposerSend.ts +2 -5
  342. package/src/react/primitive-hooks/useSuggestionTrigger.test.ts +11 -0
  343. package/src/react/primitive-hooks/useSuggestionTrigger.ts +4 -5
  344. package/src/react/primitive-hooks/useThreadIsEmpty.ts +3 -0
  345. package/src/react/primitive-hooks/useThreadIsRunning.ts +3 -0
  346. package/src/react/primitives/message/MessageParts.tsx +0 -1
  347. package/src/react/primitives/thread/ThreadMessages.tsx +2 -1
  348. package/src/react/runtimes/RemoteThreadListHookInstanceManager.retry.test.tsx +116 -0
  349. package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +1 -1
  350. package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +57 -6
  351. package/src/react/runtimes/RemoteThreadListHookInstanceManager.title.test.tsx +272 -0
  352. package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +171 -124
  353. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.republish.test.ts +87 -0
  354. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +327 -83
  355. package/src/react/runtimes/RemoteThreadResource.test.ts +141 -0
  356. package/src/react/runtimes/RemoteThreadResource.ts +233 -0
  357. package/src/react/runtimes/RuntimeAdapterProvider.tsx +8 -20
  358. package/src/react/runtimes/assistant-transport/commandQueue.ts +68 -0
  359. package/src/react/runtimes/assistant-transport/replayBoundaryStream.test.ts +455 -0
  360. package/src/react/runtimes/assistant-transport/replayBoundaryStream.ts +172 -0
  361. package/src/react/runtimes/assistant-transport/runManager.ts +124 -0
  362. package/src/react/runtimes/assistant-transport/transport-delivery.test.tsx +79 -0
  363. package/src/react/runtimes/assistant-transport/transport-parentid.test.tsx +97 -0
  364. package/src/react/runtimes/assistant-transport/transport-scheduling.test.ts +414 -0
  365. package/src/react/runtimes/assistant-transport/types.ts +170 -0
  366. package/src/react/runtimes/assistant-transport/useAssistantTransport.spec.md +141 -0
  367. package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.test.tsx +683 -0
  368. package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.ts +483 -0
  369. package/src/react/runtimes/assistant-transport/useConvertedState.ts +20 -0
  370. package/src/react/runtimes/assistant-transport/useLatestRef.ts +9 -0
  371. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +131 -6
  372. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +61 -15
  373. package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +6 -4
  374. package/src/react/runtimes/cloud/auiV0.ts +17 -1
  375. package/src/react/runtimes/cloud/useCloudThreadListAdapter.test.tsx +98 -3
  376. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +104 -27
  377. package/src/react/runtimes/cloud/useCloudThreadListRuntime.test.tsx +56 -0
  378. package/src/react/runtimes/cloud/useCloudThreadListRuntime.ts +31 -0
  379. package/src/react/runtimes/external-message-converter.test.ts +143 -0
  380. package/src/react/runtimes/external-message-converter.ts +41 -41
  381. package/src/react/runtimes/remote-thread-hook-on-tap.test.ts +58 -0
  382. package/src/react/runtimes/useExternalStoreRuntime.lifecycle.test.tsx +83 -0
  383. package/src/react/runtimes/useExternalStoreRuntime.suggestions.test.tsx +13 -3
  384. package/src/react/runtimes/useExternalStoreRuntime.ts +7 -0
  385. package/src/react/runtimes/useExternalStoreSharedOptions.ts +3 -1
  386. package/src/react/runtimes/useLocalRuntime.test.tsx +134 -8
  387. package/src/react/runtimes/useRuntimeAdapters.test.tsx +62 -0
  388. package/src/react/runtimes/useRuntimeAdapters.ts +28 -0
  389. package/src/runtime/api/composer-runtime.ts +5 -0
  390. package/src/runtime/api/thread-list-runtime.ts +3 -1
  391. package/src/runtime/api/thread-runtime.ts +20 -2
  392. package/src/runtime/base/base-composer-runtime-core.ts +6 -5
  393. package/src/runtime/base/base-thread-runtime-core.test.ts +191 -0
  394. package/src/runtime/base/base-thread-runtime-core.ts +11 -2
  395. package/src/runtime/base/default-thread-composer-runtime-core.ts +12 -4
  396. package/src/runtime/interfaces/thread-runtime-core.ts +6 -0
  397. package/src/runtime/queue/message-queue.ts +2 -1
  398. package/src/runtime/utils/message-repository.ts +26 -18
  399. package/src/runtime/utils/thread-runtime-lifecycle.ts +18 -0
  400. package/src/runtimes/external-store/external-store-shared-options.ts +3 -1
  401. package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +4 -1
  402. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +103 -34
  403. package/src/runtimes/inert/InertThreadRuntimeCore.test.ts +253 -0
  404. package/src/runtimes/inert/InertThreadRuntimeCore.ts +232 -0
  405. package/src/runtimes/local/local-thread-runtime-core.test.ts +692 -4
  406. package/src/runtimes/local/local-thread-runtime-core.ts +117 -22
  407. package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +17 -205
  408. package/src/runtimes/remote-thread-list/adapter-changed.ts +10 -0
  409. package/src/runtimes/remote-thread-list/empty-thread-core.ts +28 -217
  410. package/src/runtimes/remote-thread-list/optimistic-state.test.ts +18 -0
  411. package/src/runtimes/remote-thread-list/optimistic-state.ts +13 -0
  412. package/src/runtimes/remote-thread-list/types.ts +34 -0
  413. package/src/runtimes/tool-invocations/EDGE_CASES.md +17 -6
  414. package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +243 -0
  415. package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +127 -61
  416. package/src/store/clients/external-thread.ts +1 -1
  417. package/src/store/clients/model-context-client.test.ts +16 -8
  418. package/src/store/clients/suggestions.ts +2 -2
  419. package/src/store/clients/thread-selection-events.ts +21 -0
  420. package/src/store/env.ts +11 -0
  421. package/src/store/index.ts +14 -1
  422. package/src/store/internal.ts +13 -0
  423. package/src/store/primitive-predicates.test.ts +184 -0
  424. package/src/store/primitive-predicates.ts +43 -0
  425. package/src/store/runtime-clients/attachment-runtime-client.test.ts +41 -0
  426. package/src/store/runtime-clients/attachment-runtime-client.ts +2 -1
  427. package/src/store/runtime-clients/handle-runtime-action.test.ts +40 -0
  428. package/src/store/runtime-clients/handle-runtime-action.ts +14 -0
  429. package/src/store/runtime-clients/handle-thread-list-action.test.ts +69 -0
  430. package/src/store/runtime-clients/handle-thread-list-action.ts +6 -0
  431. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +15 -7
  432. package/src/store/runtime-clients/thread-list-runtime-client.ts +9 -6
  433. package/src/store/scopes/composer.ts +9 -4
  434. package/src/store/scopes/thread-list-item.ts +7 -6
  435. package/src/store/scopes/thread.ts +8 -7
  436. package/src/store/scopes/threads.ts +14 -0
  437. package/src/subscribable/subscribable.test.ts +77 -1
  438. package/src/subscribable/subscribable.ts +38 -23
  439. package/src/tests/MessageRepository.test.ts +48 -0
  440. package/src/tests/RemoteThreadListThreadListRuntimeCore-errors.test.ts +2 -2
  441. package/src/tests/RemoteThreadListThreadListRuntimeCore-loadMore.test.ts +8 -6
  442. package/src/tests/RemoteThreadListThreadListRuntimeCore-switchToThread-unarchive.test.ts +25 -0
  443. package/src/tests/auiV0Encode.test.ts +66 -0
  444. package/src/tests/base-composer-runtime-core-send.test.ts +30 -0
  445. package/src/tests/base-composer-runtime-core.test.ts +28 -0
  446. package/src/tests/composer-can-cancel.test.ts +101 -0
  447. package/src/tests/empty-thread-core.test.ts +6 -0
  448. package/src/tests/external-store-thread-list-runtime-core.test.ts +101 -0
  449. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +211 -1
  450. package/src/tests/external-store-thread-runtime-core.test.ts +124 -0
  451. package/src/tests/external-thread-isEmpty.test.tsx +100 -0
  452. package/src/tests/interactables-toolui-migration.test.tsx +66 -0
  453. package/src/tests/message-queue.test.ts +28 -0
  454. package/src/tests/remote-thread-list-adapter-switch.test.ts +383 -0
  455. package/src/tests/session-reset-notification.test.ts +145 -0
  456. package/src/tests/thread-switch-events.test.tsx +99 -1
  457. package/src/tests/tools-scope-migration.test.tsx +58 -0
  458. package/src/tests/useRemoteThreadListRuntime-controlled.test.tsx +67 -0
  459. package/src/types/message.ts +1 -1
  460. package/src/utils/composite-context-provider.test.ts +139 -0
  461. package/src/utils/composite-context-provider.ts +26 -8
  462. package/src/utils/notify-event-listeners.ts +10 -5
  463. package/src/utils/silent-runtime-action.ts +6 -0
@@ -180,6 +180,24 @@ describe("MessageRepository", () => {
180
180
  });
181
181
 
182
182
  describe("Branch management", () => {
183
+ const createLongBranchMessages = (
184
+ messageCount: number,
185
+ ): Array<{ message: ThreadMessage; parentId: string | null }> => {
186
+ const messages: Array<{
187
+ message: ThreadMessage;
188
+ parentId: string | null;
189
+ }> = [{ message: createTestMessage({ id: "root" }), parentId: null }];
190
+
191
+ for (let index = 0; index < messageCount; index++) {
192
+ messages.push({
193
+ message: createTestMessage({ id: `branch-${index}` }),
194
+ parentId: index === 0 ? "root" : `branch-${index - 1}`,
195
+ });
196
+ }
197
+
198
+ return messages;
199
+ };
200
+
183
201
  it("should create multiple branches from a parent message", () => {
184
202
  const parent = createTestMessage({ id: "parent-id" });
185
203
  const branch1 = createTestMessage({ id: "branch1-id" });
@@ -222,6 +240,36 @@ describe("MessageRepository", () => {
222
240
  expect(messages2.map((m) => m.id)).toEqual(["parent-id", "branch2-id"]);
223
241
  });
224
242
 
243
+ it("should operate on a long message history without overflowing the stack", () => {
244
+ const messageCount = 30_000;
245
+ const messages = createLongBranchMessages(messageCount);
246
+
247
+ messages.push({
248
+ message: createTestMessage({ id: "alternate" }),
249
+ parentId: "root",
250
+ });
251
+
252
+ repository.import({ headId: "alternate", messages });
253
+ repository.switchToBranch("branch-0");
254
+
255
+ expect(repository.headId).toBe(`branch-${messageCount - 1}`);
256
+
257
+ repository.deleteMessage("branch-0", "root");
258
+
259
+ expect(repository.getMessage("branch-1")).toMatchObject({
260
+ parentId: "root",
261
+ index: 1,
262
+ });
263
+ expect(repository.headId).toBe(`branch-${messageCount - 1}`);
264
+
265
+ repository.resetHead("root");
266
+
267
+ expect(repository.getMessages().map((message) => message.id)).toEqual([
268
+ "root",
269
+ ]);
270
+ expect(() => repository.getMessage("branch-1")).toThrow();
271
+ }, 20_000);
272
+
225
273
  it("should throw error when switching to a non-existent branch", () => {
226
274
  expect(() => {
227
275
  repository.switchToBranch("non-existent-id");
@@ -3,10 +3,10 @@ import { createCore, makeAdapter } from "./remote-thread-list-test-helpers";
3
3
  import { InMemoryThreadListAdapter } from "../runtimes/remote-thread-list/adapter/in-memory";
4
4
 
5
5
  describe("RemoteThreadListThreadListRuntimeCore errors", () => {
6
- it("includes the requested thread id when a thread is missing", () => {
6
+ it("includes the requested thread id when a thread is missing", async () => {
7
7
  const core = createCore(makeAdapter());
8
8
 
9
- expect(() => core.rename("missing-thread", "New title")).toThrow(
9
+ await expect(core.rename("missing-thread", "New title")).rejects.toThrow(
10
10
  'Thread "missing-thread" not found while renaming it.',
11
11
  );
12
12
  });
@@ -268,6 +268,7 @@ describe("RemoteThreadListThreadListRuntimeCore.loadMore", () => {
268
268
  await core.getLoadThreadsPromise();
269
269
  expect(secondList).toHaveBeenCalledTimes(1);
270
270
  expect(core.threadIds).toEqual(["new"]);
271
+ expect(core.getItemById("old")).toBeUndefined();
271
272
  });
272
273
 
273
274
  it("ignores an in-flight loadMore response when the adapter swaps mid-flight", async () => {
@@ -289,23 +290,24 @@ describe("RemoteThreadListThreadListRuntimeCore.loadMore", () => {
289
290
  await core.getLoadThreadsPromise();
290
291
  const stale = core.loadMore();
291
292
 
292
- const secondAdapter = makeAdapter({
293
- list: vi.fn<ListFn>(async () => ({
294
- threads: [{ status: "regular", remoteId: "ignored", externalId: "x" }],
295
- })),
296
- });
293
+ const secondList = vi.fn<ListFn>(async () => ({
294
+ threads: [{ status: "regular", remoteId: "fresh", externalId: "fresh" }],
295
+ }));
296
+ const secondAdapter = makeAdapter({ list: secondList });
297
297
  core.__internal_setOptions({
298
298
  adapter: secondAdapter,
299
299
  runtimeHook: () => ({}) as never,
300
300
  });
301
+ const replacementLoad = core.getLoadThreadsPromise();
301
302
 
302
303
  slow.resolve({
303
304
  threads: [{ status: "regular", remoteId: "stale", externalId: "stale" }],
304
305
  nextCursor: "stale-cursor",
305
306
  });
306
307
  await stale;
308
+ await replacementLoad;
307
309
 
308
- expect(core.threadIds).toEqual(["p1"]);
310
+ expect(core.threadIds).toEqual(["fresh"]);
309
311
  expect(core.hasMore).toBe(false);
310
312
  expect(core.isLoadingMore).toBe(false);
311
313
  });
@@ -63,6 +63,31 @@ describe("RemoteThreadListThreadListRuntimeCore.switchToThread unarchive option"
63
63
  expect(core.mainThreadId).toBe(core.getItemById(THREAD_ID)?.id);
64
64
  });
65
65
 
66
+ it("restores an initialized draft's archived thread when unarchive fails", async () => {
67
+ const THREAD_ID = "archived-initialized-draft";
68
+ const error = new Error("unarchive failed");
69
+ const adapter = makeAdapter({
70
+ list: vi.fn(async () => ({ threads: [archivedThread(THREAD_ID)] })),
71
+ unarchive: vi.fn(async () => {
72
+ throw error;
73
+ }),
74
+ });
75
+
76
+ const core = createCore(adapter);
77
+ await core.getLoadThreadsPromise();
78
+ const draftId = core.newThreadId;
79
+ if (draftId === undefined) throw new Error("Expected seeded draft");
80
+ await core.initialize(draftId);
81
+ expect(core.newThreadId).toBeUndefined();
82
+ await core.switchToThread(THREAD_ID, { unarchive: false });
83
+
84
+ await expect(core.unarchive(THREAD_ID)).rejects.toBe(error);
85
+ expect(core.mainThreadId).not.toBe(THREAD_ID);
86
+ expect(core.getItemById(THREAD_ID)?.status).toBe("archived");
87
+ expect(core.archivedThreadIds).toContain(THREAD_ID);
88
+ expect(core.threadIds).not.toContain(THREAD_ID);
89
+ });
90
+
66
91
  it("does not call unarchive when the target is already regular, regardless of option", async () => {
67
92
  const THREAD_ID = "regular-target";
68
93
  const adapter = makeAdapter({
@@ -330,6 +330,33 @@ describe("auiV0Encode", () => {
330
330
  { type: "data", name: "telemetry", data: { runs: 3 } },
331
331
  ]);
332
332
  });
333
+
334
+ it("preserves data message parts verbatim in the core cloud encoder", () => {
335
+ const encoded = auiV0Encode({
336
+ id: "m1",
337
+ createdAt: new Date("2026-03-15T00:00:00.000Z"),
338
+ role: "assistant",
339
+ status: { type: "complete", reason: "stop" },
340
+ metadata: {
341
+ unstable_state: null,
342
+ unstable_annotations: [],
343
+ unstable_data: [],
344
+ steps: [],
345
+ custom: {},
346
+ },
347
+ content: [
348
+ { type: "text", text: "planned" },
349
+ { type: "data", name: "PredictState", data: { steps: ["a"] } },
350
+ { type: "data", name: "PredictState", data: '{"steps":["a","b"]}' },
351
+ ],
352
+ });
353
+
354
+ expect(encoded.content).toEqual([
355
+ { type: "text", text: "planned" },
356
+ { type: "data", name: "PredictState", data: { steps: ["a"] } },
357
+ { type: "data", name: "PredictState", data: '{"steps":["a","b"]}' },
358
+ ]);
359
+ });
333
360
  });
334
361
 
335
362
  describe("auiV0Decode", () => {
@@ -573,4 +600,43 @@ describe("auiV0Decode", () => {
573
600
  const toolCall = message.content.find((p) => p.type === "tool-call");
574
601
  expect(toolCall).toHaveProperty("result", false);
575
602
  });
603
+
604
+ it("round-trips data message parts, keeping repeated names in order", () => {
605
+ const content = auiV0Encode({
606
+ id: "local",
607
+ createdAt: new Date("2026-03-15T00:00:00.000Z"),
608
+ role: "assistant",
609
+ status: { type: "complete", reason: "stop" },
610
+ metadata: {
611
+ unstable_state: null,
612
+ unstable_annotations: [],
613
+ unstable_data: [],
614
+ steps: [],
615
+ custom: {},
616
+ },
617
+ content: [
618
+ { type: "text", text: "planned" },
619
+ { type: "data", name: "PredictState", data: { steps: ["a"] } },
620
+ { type: "data", name: "PredictState", data: '{"steps":["a","b"]}' },
621
+ ],
622
+ });
623
+
624
+ const decoded = auiV0Decode({
625
+ id: "cloud",
626
+ parent_id: null,
627
+ height: 0,
628
+ created_at: new Date("2026-03-15T00:00:00.000Z"),
629
+ updated_at: new Date("2026-03-15T00:00:00.000Z"),
630
+ format: "aui/v0",
631
+ content: content as never,
632
+ });
633
+
634
+ if (decoded.message.role !== "assistant")
635
+ throw new Error("expected assistant");
636
+ expect(decoded.message.content).toEqual([
637
+ { type: "text", text: "planned" },
638
+ { type: "data", name: "PredictState", data: { steps: ["a"] } },
639
+ { type: "data", name: "PredictState", data: '{"steps":["a","b"]}' },
640
+ ]);
641
+ });
576
642
  });
@@ -158,6 +158,36 @@ describe("BaseComposerRuntimeCore.send restore-on-failure", () => {
158
158
  expect(append).toHaveBeenCalledTimes(1);
159
159
  });
160
160
 
161
+ it("snapshots role and run config before uploading attachments", async () => {
162
+ let resolveSend!: () => void;
163
+ const adapter = makeAdapter({
164
+ send: (a) =>
165
+ new Promise((resolve) => {
166
+ resolveSend = () =>
167
+ resolve({ ...a, status: { type: "complete" }, content: [] });
168
+ }),
169
+ });
170
+ const { composer, append } = makeComposer(adapter);
171
+
172
+ composer.setText("hello");
173
+ composer.setRole("assistant");
174
+ composer.setRunConfig({ custom: { modelName: "model-a" } });
175
+ await composer.addAttachment(textFile());
176
+
177
+ const sendPromise = composer.send();
178
+ composer.setRole("system");
179
+ composer.setRunConfig({ custom: { modelName: "model-b" } });
180
+ resolveSend();
181
+ await sendPromise;
182
+
183
+ expect(append).toHaveBeenCalledWith(
184
+ expect.objectContaining({
185
+ role: "assistant",
186
+ runConfig: { custom: { modelName: "model-a" } },
187
+ }),
188
+ );
189
+ });
190
+
161
191
  it("keeps an attachment added while the upload was in flight", async () => {
162
192
  let resolveSend!: () => void;
163
193
  const adapter = makeAdapter({
@@ -186,6 +186,34 @@ describe("BaseComposerRuntimeCore", () => {
186
186
  expect(composer.attachmentAccept).toBe("image/*");
187
187
  });
188
188
 
189
+ it("handles rejected dictation shutdowns", async () => {
190
+ const session: DictationAdapter.Session = {
191
+ status: { type: "running" },
192
+ stop: vi.fn().mockRejectedValue(new Error("shutdown failed")),
193
+ cancel: vi.fn(),
194
+ onSpeechStart: vi.fn(() => () => {}),
195
+ onSpeechEnd: vi.fn(() => () => {}),
196
+ onSpeech: vi.fn(() => () => {}),
197
+ };
198
+ const unhandledRejection = vi.fn();
199
+ composer.setDictationAdapter({ listen: () => session });
200
+ process.on("unhandledRejection", unhandledRejection);
201
+
202
+ try {
203
+ composer.startDictation();
204
+ expect(composer.dictation).toBeDefined();
205
+
206
+ composer.stopDictation();
207
+ await new Promise((resolve) => setTimeout(resolve, 0));
208
+
209
+ expect(session.stop).toHaveBeenCalledOnce();
210
+ expect(composer.dictation).toBeUndefined();
211
+ expect(unhandledRejection).not.toHaveBeenCalled();
212
+ } finally {
213
+ process.off("unhandledRejection", unhandledRejection);
214
+ }
215
+ });
216
+
189
217
  describe("CreateAttachment (external source)", () => {
190
218
  const makeCreateAttachment = (
191
219
  overrides?: Partial<CreateAttachment>,
@@ -0,0 +1,101 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { DefaultThreadComposerRuntimeCore } from "../runtime/base/default-thread-composer-runtime-core";
3
+ import type { ThreadRuntimeCore } from "../runtime/interfaces/thread-runtime-core";
4
+ import type { ThreadMessage } from "../types/message";
5
+
6
+ type ThreadRuntimeStub = Omit<ThreadRuntimeCore, "composer"> & {
7
+ notify: () => void;
8
+ };
9
+
10
+ const makeRuntimeStub = (
11
+ overrides: Partial<ThreadRuntimeCore> = {},
12
+ ): ThreadRuntimeStub => {
13
+ const subscribers = new Set<() => void>();
14
+ return {
15
+ append: vi.fn(),
16
+ cancelRun: vi.fn(),
17
+ getModelContext: () => ({}),
18
+ subscribe: (cb: () => void) => {
19
+ subscribers.add(cb);
20
+ return () => subscribers.delete(cb);
21
+ },
22
+ capabilities: { cancel: true },
23
+ messages: [],
24
+ isDisabled: false,
25
+ isSendDisabled: false,
26
+ isLoading: false,
27
+ composer: { runConfig: {} },
28
+ notify: () => {
29
+ for (const cb of subscribers) cb();
30
+ },
31
+ ...overrides,
32
+ } as unknown as ThreadRuntimeStub;
33
+ };
34
+
35
+ const runningAssistant = {
36
+ id: "a1",
37
+ role: "assistant",
38
+ status: { type: "running" },
39
+ } as ThreadMessage;
40
+
41
+ describe("DefaultThreadComposerRuntimeCore.canCancel", () => {
42
+ it("is false when the runtime is idle even if cancel is supported", () => {
43
+ const composer = new DefaultThreadComposerRuntimeCore(makeRuntimeStub());
44
+ expect(composer.canCancel).toBe(false);
45
+ });
46
+
47
+ it("is false when cancel is not a capability", () => {
48
+ const composer = new DefaultThreadComposerRuntimeCore(
49
+ makeRuntimeStub({
50
+ capabilities: { cancel: false },
51
+ isRunning: true,
52
+ }),
53
+ );
54
+ expect(composer.canCancel).toBe(false);
55
+ });
56
+
57
+ it("is true while the runtime reports isRunning", () => {
58
+ const composer = new DefaultThreadComposerRuntimeCore(
59
+ makeRuntimeStub({ isRunning: true }),
60
+ );
61
+ expect(composer.canCancel).toBe(true);
62
+ });
63
+
64
+ it("is true while the trailing assistant message is running", () => {
65
+ const composer = new DefaultThreadComposerRuntimeCore(
66
+ makeRuntimeStub({ messages: [runningAssistant] }),
67
+ );
68
+ expect(composer.canCancel).toBe(true);
69
+ });
70
+
71
+ it("stays false after a runtime notify while idle", () => {
72
+ const stub = makeRuntimeStub();
73
+ const composer = new DefaultThreadComposerRuntimeCore(stub);
74
+ stub.notify();
75
+ expect(composer.canCancel).toBe(false);
76
+ });
77
+
78
+ it("notifies subscribers when a run starts", () => {
79
+ const stub = makeRuntimeStub();
80
+ const composer = new DefaultThreadComposerRuntimeCore(stub);
81
+ const onChange = vi.fn();
82
+ composer.subscribe(onChange);
83
+
84
+ (stub as { isRunning?: boolean }).isRunning = true;
85
+ stub.notify();
86
+
87
+ expect(onChange).toHaveBeenCalled();
88
+ expect(composer.canCancel).toBe(true);
89
+ });
90
+
91
+ it("returns to false when the run ends", () => {
92
+ const stub = makeRuntimeStub({ isRunning: true });
93
+ const composer = new DefaultThreadComposerRuntimeCore(stub);
94
+ expect(composer.canCancel).toBe(true);
95
+
96
+ (stub as { isRunning?: boolean }).isRunning = false;
97
+ stub.notify();
98
+
99
+ expect(composer.canCancel).toBe(false);
100
+ });
101
+ });
@@ -2,6 +2,12 @@ import { describe, it, expect } from "vitest";
2
2
  import { EMPTY_THREAD_CORE } from "../runtimes/remote-thread-list/empty-thread-core";
3
3
 
4
4
  describe("EMPTY_THREAD_CORE", () => {
5
+ it("reads no messages, branches, or exported repository", () => {
6
+ expect(EMPTY_THREAD_CORE.getMessageById("a")).toBeUndefined();
7
+ expect(EMPTY_THREAD_CORE.getBranches("a")).toEqual([]);
8
+ expect(EMPTY_THREAD_CORE.export()).toEqual({ messages: [] });
9
+ });
10
+
5
11
  it("has isLoading=true so it is not mistaken for an empty conversation", () => {
6
12
  expect(EMPTY_THREAD_CORE.isLoading).toBe(true);
7
13
  });
@@ -1,7 +1,10 @@
1
1
  import { describe, expect, it, vi } from "vitest";
2
2
  import { ExternalStoreThreadListRuntimeCore } from "../runtimes/external-store/external-store-thread-list-runtime-core";
3
3
  import type { ExternalStoreThreadRuntimeCore } from "../runtimes/external-store/external-store-thread-runtime-core";
4
+ import { ExternalStoreThreadRuntimeCore as ExternalStoreThreadRuntimeCoreImpl } from "../runtimes/external-store/external-store-thread-runtime-core";
4
5
  import type { ExternalStoreThreadListAdapter } from "../runtimes/external-store/external-store-adapter";
6
+ import type { ExternalStoreAdapter } from "../runtimes/external-store/external-store-adapter";
7
+ import type { ModelContextProvider } from "../model-context/types";
5
8
  import { ThreadListRuntimeImpl } from "../runtime/api/thread-list-runtime";
6
9
 
7
10
  const makeFactory = (overrides: Record<string, unknown> = {}) =>
@@ -18,6 +21,21 @@ const makeAdapter = (
18
21
  overrides: Partial<ExternalStoreThreadListAdapter> = {},
19
22
  ): ExternalStoreThreadListAdapter => ({ ...overrides });
20
23
 
24
+ const mockContextProvider: ModelContextProvider = {
25
+ getModelContext: () => ({}),
26
+ };
27
+
28
+ const appendMessage = () => ({
29
+ parentId: null,
30
+ sourceId: null,
31
+ runConfig: {},
32
+ role: "user" as const,
33
+ content: [{ type: "text" as const, text: "hello" }],
34
+ attachments: [],
35
+ metadata: { custom: {} },
36
+ createdAt: new Date(0),
37
+ });
38
+
21
39
  describe("ExternalStoreThreadListRuntimeCore - construction", () => {
22
40
  it("assigns a resolvable fallback mainThreadId when adapter has no threadId", () => {
23
41
  const core = new ExternalStoreThreadListRuntimeCore(
@@ -149,6 +167,26 @@ describe("ExternalStoreThreadListRuntimeCore - __internal_setAdapter", () => {
149
167
  expect(callback).toHaveBeenCalled();
150
168
  });
151
169
 
170
+ it("notifies later subscribers when an earlier subscriber throws", () => {
171
+ const core = new ExternalStoreThreadListRuntimeCore(
172
+ makeAdapter({ threadId: "thread-alpha" }),
173
+ makeFactory(),
174
+ );
175
+ const error = new Error("subscriber failed");
176
+ const laterSubscriber = vi.fn();
177
+
178
+ core.subscribe(() => {
179
+ throw error;
180
+ });
181
+ core.subscribe(laterSubscriber);
182
+
183
+ expect(() =>
184
+ core.__internal_setAdapter(makeAdapter({ threadId: "thread-beta" })),
185
+ ).toThrow(error);
186
+ expect(core.mainThreadId).toBe("thread-beta");
187
+ expect(laterSubscriber).toHaveBeenCalledOnce();
188
+ });
189
+
152
190
  it("synthesizes mainThreadId entry after a switch to a threadId not in the threads list", () => {
153
191
  const core = new ExternalStoreThreadListRuntimeCore(
154
192
  makeAdapter({ threadId: "thread-alpha" }),
@@ -175,6 +213,69 @@ describe("ExternalStoreThreadListRuntimeCore - __internal_setAdapter", () => {
175
213
  "thread-gamma",
176
214
  ]);
177
215
  });
216
+
217
+ it("dispatches an append before a thread switch", async () => {
218
+ let resolveInitialization!: () => void;
219
+ const initialization = new Promise<void>((resolve) => {
220
+ resolveInitialization = resolve;
221
+ });
222
+ const onNew = vi.fn(async () => {});
223
+ const firstRuntime = new ExternalStoreThreadRuntimeCoreImpl(
224
+ mockContextProvider,
225
+ { messages: [], onNew } as ExternalStoreAdapter,
226
+ );
227
+ firstRuntime.__internal_setGetInitializePromise(() => initialization);
228
+ const secondRuntime = new ExternalStoreThreadRuntimeCoreImpl(
229
+ mockContextProvider,
230
+ { messages: [], onNew: vi.fn() } as ExternalStoreAdapter,
231
+ );
232
+ const factory = vi
233
+ .fn()
234
+ .mockReturnValueOnce(firstRuntime)
235
+ .mockReturnValueOnce(secondRuntime);
236
+ const core = new ExternalStoreThreadListRuntimeCore(
237
+ makeAdapter({ threadId: "thread-alpha" }),
238
+ factory,
239
+ );
240
+
241
+ const appendPromise = firstRuntime.append(appendMessage());
242
+ await Promise.resolve();
243
+
244
+ expect(onNew).toHaveBeenCalledTimes(1);
245
+
246
+ core.__internal_setAdapter(makeAdapter({ threadId: "thread-beta" }));
247
+ resolveInitialization();
248
+
249
+ await appendPromise;
250
+ expect(onNew).toHaveBeenCalledTimes(1);
251
+ });
252
+ });
253
+
254
+ describe("ExternalStoreThreadListRuntimeCore - detach", () => {
255
+ it("leaves the main thread's pending append alone when an item detaches", async () => {
256
+ let resolveInitialization!: () => void;
257
+ const initialization = new Promise<void>((resolve) => {
258
+ resolveInitialization = resolve;
259
+ });
260
+ const onNew = vi.fn(async () => {});
261
+ const runtime = new ExternalStoreThreadRuntimeCoreImpl(
262
+ mockContextProvider,
263
+ { messages: [], onNew } as ExternalStoreAdapter,
264
+ );
265
+ runtime.__internal_setGetInitializePromise(() => initialization);
266
+ const core = new ExternalStoreThreadListRuntimeCore(
267
+ makeAdapter(),
268
+ vi.fn(() => runtime),
269
+ );
270
+
271
+ const appendPromise = runtime.append(appendMessage());
272
+ await Promise.resolve();
273
+ await core.detach();
274
+ resolveInitialization();
275
+
276
+ await appendPromise;
277
+ expect(onNew).toHaveBeenCalledTimes(1);
278
+ });
178
279
  });
179
280
 
180
281
  describe("ExternalStoreThreadListRuntimeCore - isMain via ThreadListRuntimeImpl", () => {