@assistant-ui/core 0.3.13 → 0.3.14

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 (396) 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 +27 -15
  8. package/dist/adapters/voice.js.map +1 -1
  9. package/dist/index.d.ts +2 -2
  10. package/dist/index.js.map +1 -1
  11. package/dist/internal.d.ts +1 -1
  12. package/dist/internal.js +6 -6
  13. package/dist/model-context/frame/host.d.ts.map +1 -1
  14. package/dist/model-context/frame/host.js +2 -1
  15. package/dist/model-context/frame/host.js.map +1 -1
  16. package/dist/model-context/registry.d.ts.map +1 -1
  17. package/dist/model-context/registry.js +16 -4
  18. package/dist/model-context/registry.js.map +1 -1
  19. package/dist/react/RuntimeAdapter.d.ts +8 -1
  20. package/dist/react/RuntimeAdapter.d.ts.map +1 -1
  21. package/dist/react/RuntimeAdapter.js +23 -18
  22. package/dist/react/RuntimeAdapter.js.map +1 -1
  23. package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
  24. package/dist/react/adapters/LocalStorageThreadListAdapter.js +28 -12
  25. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  26. package/dist/react/client/AdaptedRemoteThread.d.ts +11 -0
  27. package/dist/react/client/AdaptedRemoteThread.d.ts.map +1 -0
  28. package/dist/react/client/AdaptedRemoteThread.js +27 -0
  29. package/dist/react/client/AdaptedRemoteThread.js.map +1 -0
  30. package/dist/react/client/InMemoryThreadList.d.ts +19 -0
  31. package/dist/react/client/InMemoryThreadList.d.ts.map +1 -0
  32. package/dist/react/client/InMemoryThreadList.js +418 -0
  33. package/dist/react/client/InMemoryThreadList.js.map +1 -0
  34. package/dist/react/client/Interactables.d.ts.map +1 -1
  35. package/dist/react/client/Interactables.js +159 -102
  36. package/dist/react/client/Interactables.js.map +1 -1
  37. package/dist/react/client/RemoteThreadList.d.ts +34 -0
  38. package/dist/react/client/RemoteThreadList.d.ts.map +1 -0
  39. package/dist/react/client/RemoteThreadList.js +826 -0
  40. package/dist/react/client/RemoteThreadList.js.map +1 -0
  41. package/dist/react/client/Tools.d.ts.map +1 -1
  42. package/dist/react/client/Tools.js +38 -27
  43. package/dist/react/client/Tools.js.map +1 -1
  44. package/dist/react/index.d.ts +7 -2
  45. package/dist/react/index.js +5 -2
  46. package/dist/react/interactables-legacy/Interactables.d.ts.map +1 -1
  47. package/dist/react/interactables-legacy/Interactables.js +145 -110
  48. package/dist/react/interactables-legacy/Interactables.js.map +1 -1
  49. package/dist/react/primitive-hooks/useActionBarCopy.d.ts.map +1 -1
  50. package/dist/react/primitive-hooks/useActionBarCopy.js +13 -18
  51. package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
  52. package/dist/react/primitive-hooks/useActionBarEdit.d.ts.map +1 -1
  53. package/dist/react/primitive-hooks/useActionBarEdit.js +2 -4
  54. package/dist/react/primitive-hooks/useActionBarEdit.js.map +1 -1
  55. package/dist/react/primitive-hooks/useActionBarReload.d.ts.map +1 -1
  56. package/dist/react/primitive-hooks/useActionBarReload.js +2 -4
  57. package/dist/react/primitive-hooks/useActionBarReload.js.map +1 -1
  58. package/dist/react/primitive-hooks/useBranchPickerNext.d.ts.map +1 -1
  59. package/dist/react/primitive-hooks/useBranchPickerNext.js +2 -6
  60. package/dist/react/primitive-hooks/useBranchPickerNext.js.map +1 -1
  61. package/dist/react/primitive-hooks/useBranchPickerPrevious.d.ts.map +1 -1
  62. package/dist/react/primitive-hooks/useBranchPickerPrevious.js +2 -6
  63. package/dist/react/primitive-hooks/useBranchPickerPrevious.js.map +1 -1
  64. package/dist/react/primitive-hooks/useComposerCancel.d.ts.map +1 -1
  65. package/dist/react/primitive-hooks/useComposerCancel.js +2 -4
  66. package/dist/react/primitive-hooks/useComposerCancel.js.map +1 -1
  67. package/dist/react/primitive-hooks/useComposerSend.d.ts.map +1 -1
  68. package/dist/react/primitive-hooks/useComposerSend.js +2 -4
  69. package/dist/react/primitive-hooks/useComposerSend.js.map +1 -1
  70. package/dist/react/primitive-hooks/useSuggestionTrigger.d.ts.map +1 -1
  71. package/dist/react/primitive-hooks/useSuggestionTrigger.js +6 -2
  72. package/dist/react/primitive-hooks/useSuggestionTrigger.js.map +1 -1
  73. package/dist/react/primitives/message/MessageParts.d.ts +13 -0
  74. package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
  75. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  76. package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
  77. package/dist/react/primitives/thread/ThreadMessages.js +1 -1
  78. package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
  79. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +22 -10
  80. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  81. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +109 -71
  82. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  83. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +8 -2
  84. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  85. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +40 -13
  86. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  87. package/dist/react/runtimes/RemoteThreadResource.d.ts +30 -0
  88. package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -0
  89. package/dist/react/runtimes/RemoteThreadResource.js +134 -0
  90. package/dist/react/runtimes/RemoteThreadResource.js.map +1 -0
  91. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts +3 -10
  92. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts.map +1 -1
  93. package/dist/react/runtimes/RuntimeAdapterProvider.js +3 -6
  94. package/dist/react/runtimes/RuntimeAdapterProvider.js.map +1 -1
  95. package/dist/react/runtimes/assistant-transport/commandQueue.d.ts +17 -0
  96. package/dist/react/runtimes/assistant-transport/commandQueue.d.ts.map +1 -0
  97. package/dist/react/runtimes/assistant-transport/commandQueue.js +55 -0
  98. package/dist/react/runtimes/assistant-transport/commandQueue.js.map +1 -0
  99. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.d.ts +11 -0
  100. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.d.ts.map +1 -0
  101. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.js +165 -0
  102. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.js.map +1 -0
  103. package/dist/react/runtimes/assistant-transport/runManager.d.ts +15 -0
  104. package/dist/react/runtimes/assistant-transport/runManager.d.ts.map +1 -0
  105. package/dist/react/runtimes/assistant-transport/runManager.js +86 -0
  106. package/dist/react/runtimes/assistant-transport/runManager.js.map +1 -0
  107. package/dist/react/runtimes/assistant-transport/types.d.ts +130 -0
  108. package/dist/react/runtimes/assistant-transport/types.d.ts.map +1 -0
  109. package/dist/react/runtimes/assistant-transport/types.js +0 -0
  110. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts +14 -0
  111. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -0
  112. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js +296 -0
  113. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js.map +1 -0
  114. package/dist/react/runtimes/assistant-transport/useConvertedState.d.ts +7 -0
  115. package/dist/react/runtimes/assistant-transport/useConvertedState.d.ts.map +1 -0
  116. package/dist/react/runtimes/assistant-transport/useConvertedState.js +25 -0
  117. package/dist/react/runtimes/assistant-transport/useConvertedState.js.map +1 -0
  118. package/dist/react/runtimes/assistant-transport/useLatestRef.d.ts +7 -0
  119. package/dist/react/runtimes/assistant-transport/useLatestRef.d.ts.map +1 -0
  120. package/dist/react/runtimes/assistant-transport/useLatestRef.js +27 -0
  121. package/dist/react/runtimes/assistant-transport/useLatestRef.js.map +1 -0
  122. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  123. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +39 -13
  124. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  125. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +2 -1
  126. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
  127. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +3 -3
  128. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
  129. package/dist/react/runtimes/cloud/auiV0.d.ts +4 -0
  130. package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
  131. package/dist/react/runtimes/cloud/auiV0.js +7 -0
  132. package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
  133. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  134. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +22 -12
  135. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  136. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.d.ts +16 -0
  137. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.d.ts.map +1 -0
  138. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js +36 -0
  139. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js.map +1 -0
  140. package/dist/react/runtimes/external-message-converter.js +14 -14
  141. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  142. package/dist/react/runtimes/useExternalStoreRuntime.d.ts.map +1 -1
  143. package/dist/react/runtimes/useExternalStoreRuntime.js +44 -28
  144. package/dist/react/runtimes/useExternalStoreRuntime.js.map +1 -1
  145. package/dist/react/runtimes/useExternalStoreSharedOptions.js.map +1 -1
  146. package/dist/react/runtimes/useLocalRuntime.js +1 -1
  147. package/dist/react/runtimes/useRuntimeAdapters.d.ts +9 -0
  148. package/dist/react/runtimes/useRuntimeAdapters.d.ts.map +1 -0
  149. package/dist/react/runtimes/useRuntimeAdapters.js +20 -0
  150. package/dist/react/runtimes/useRuntimeAdapters.js.map +1 -0
  151. package/dist/runtime/api/composer-runtime.d.ts +5 -0
  152. package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
  153. package/dist/runtime/api/composer-runtime.js.map +1 -1
  154. package/dist/runtime/api/message-runtime.js +1 -1
  155. package/dist/runtime/api/thread-list-runtime.d.ts +1 -0
  156. package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
  157. package/dist/runtime/api/thread-list-runtime.js +4 -2
  158. package/dist/runtime/api/thread-list-runtime.js.map +1 -1
  159. package/dist/runtime/api/thread-runtime.d.ts +12 -2
  160. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  161. package/dist/runtime/api/thread-runtime.js +8 -2
  162. package/dist/runtime/api/thread-runtime.js.map +1 -1
  163. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  164. package/dist/runtime/base/base-composer-runtime-core.js +8 -7
  165. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  166. package/dist/runtime/base/base-thread-runtime-core.d.ts +1 -0
  167. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  168. package/dist/runtime/base/base-thread-runtime-core.js +3 -3
  169. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  170. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +0 -1
  171. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
  172. package/dist/runtime/base/default-thread-composer-runtime-core.js +10 -4
  173. package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
  174. package/dist/runtime/interfaces/thread-runtime-core.d.ts +6 -0
  175. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  176. package/dist/runtime/internal.js +5 -5
  177. package/dist/runtime/queue/message-queue.d.ts.map +1 -1
  178. package/dist/runtime/queue/message-queue.js +2 -1
  179. package/dist/runtime/queue/message-queue.js.map +1 -1
  180. package/dist/runtime/utils/thread-runtime-lifecycle.d.ts +8 -0
  181. package/dist/runtime/utils/thread-runtime-lifecycle.d.ts.map +1 -0
  182. package/dist/runtime/utils/thread-runtime-lifecycle.js +11 -0
  183. package/dist/runtime/utils/thread-runtime-lifecycle.js.map +1 -0
  184. package/dist/runtimes/external-store/external-store-shared-options.js.map +1 -1
  185. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  186. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +4 -1
  187. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  188. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +8 -0
  189. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  190. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +35 -13
  191. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  192. package/dist/runtimes/internal.d.ts +1 -1
  193. package/dist/runtimes/local/local-thread-runtime-core.d.ts +3 -0
  194. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  195. package/dist/runtimes/local/local-thread-runtime-core.js +53 -13
  196. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  197. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +1 -0
  198. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
  199. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +3 -0
  200. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
  201. package/dist/runtimes/remote-thread-list/empty-thread-core.js +3 -0
  202. package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
  203. package/dist/runtimes/remote-thread-list/types.d.ts +29 -1
  204. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  205. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +1 -12
  206. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
  207. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +67 -38
  208. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
  209. package/dist/store/clients/suggestions.js +2 -2
  210. package/dist/store/clients/suggestions.js.map +1 -1
  211. package/dist/store/clients/thread-selection-events.d.ts +10 -0
  212. package/dist/store/clients/thread-selection-events.d.ts.map +1 -0
  213. package/dist/store/clients/thread-selection-events.js +40 -0
  214. package/dist/store/clients/thread-selection-events.js.map +1 -0
  215. package/dist/store/env.d.ts +5 -0
  216. package/dist/store/env.d.ts.map +1 -0
  217. package/dist/store/env.js +12 -0
  218. package/dist/store/env.js.map +1 -0
  219. package/dist/store/index.d.ts +5 -3
  220. package/dist/store/index.js +4 -2
  221. package/dist/store/internal.d.ts +4 -1
  222. package/dist/store/internal.js +4 -1
  223. package/dist/store/primitive-predicates.d.ts +19 -0
  224. package/dist/store/primitive-predicates.d.ts.map +1 -0
  225. package/dist/store/primitive-predicates.js +19 -0
  226. package/dist/store/primitive-predicates.js.map +1 -0
  227. package/dist/store/runtime-clients/attachment-runtime-client.d.ts.map +1 -1
  228. package/dist/store/runtime-clients/attachment-runtime-client.js +18 -11
  229. package/dist/store/runtime-clients/attachment-runtime-client.js.map +1 -1
  230. package/dist/store/runtime-clients/handle-runtime-action.d.ts +5 -0
  231. package/dist/store/runtime-clients/handle-runtime-action.d.ts.map +1 -0
  232. package/dist/store/runtime-clients/handle-runtime-action.js +12 -0
  233. package/dist/store/runtime-clients/handle-runtime-action.js.map +1 -0
  234. package/dist/store/runtime-clients/handle-thread-list-action.d.ts +5 -0
  235. package/dist/store/runtime-clients/handle-thread-list-action.d.ts.map +1 -0
  236. package/dist/store/runtime-clients/handle-thread-list-action.js +7 -0
  237. package/dist/store/runtime-clients/handle-thread-list-action.js.map +1 -0
  238. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  239. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +62 -29
  240. package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
  241. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
  242. package/dist/store/runtime-clients/thread-list-runtime-client.js +5 -6
  243. package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
  244. package/dist/store/scopes/composer.d.ts +9 -4
  245. package/dist/store/scopes/composer.d.ts.map +1 -1
  246. package/dist/store/scopes/thread-list-item.d.ts +7 -6
  247. package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
  248. package/dist/store/scopes/thread.d.ts +8 -7
  249. package/dist/store/scopes/thread.d.ts.map +1 -1
  250. package/dist/store/scopes/threads.d.ts +17 -1
  251. package/dist/store/scopes/threads.d.ts.map +1 -1
  252. package/dist/subscribable/subscribable.d.ts +2 -1
  253. package/dist/subscribable/subscribable.d.ts.map +1 -1
  254. package/dist/subscribable/subscribable.js +23 -18
  255. package/dist/subscribable/subscribable.js.map +1 -1
  256. package/dist/utils/composite-context-provider.d.ts +1 -0
  257. package/dist/utils/composite-context-provider.d.ts.map +1 -1
  258. package/dist/utils/composite-context-provider.js +25 -9
  259. package/dist/utils/composite-context-provider.js.map +1 -1
  260. package/dist/utils/notify-event-listeners.d.ts +2 -2
  261. package/dist/utils/notify-event-listeners.d.ts.map +1 -1
  262. package/dist/utils/notify-event-listeners.js +2 -2
  263. package/dist/utils/notify-event-listeners.js.map +1 -1
  264. package/package.json +7 -7
  265. package/src/adapters/speech.test.ts +118 -1
  266. package/src/adapters/speech.ts +21 -22
  267. package/src/adapters/thread-history.ts +2 -0
  268. package/src/adapters/voice.test.ts +69 -0
  269. package/src/adapters/voice.ts +27 -27
  270. package/src/index.ts +1 -0
  271. package/src/model-context/frame/host.test.ts +23 -0
  272. package/src/model-context/frame/host.ts +2 -1
  273. package/src/model-context/registry.test.ts +131 -0
  274. package/src/model-context/registry.ts +16 -6
  275. package/src/react/RuntimeAdapter.test.ts +2 -0
  276. package/src/react/RuntimeAdapter.ts +20 -8
  277. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +34 -17
  278. package/src/react/client/AdaptedRemoteThread.ts +41 -0
  279. package/src/react/client/InMemoryThreadList.test.tsx +148 -0
  280. package/src/react/client/InMemoryThreadList.ts +290 -0
  281. package/src/react/client/Interactables.test.ts +326 -2
  282. package/src/react/client/Interactables.ts +227 -110
  283. package/src/react/client/RemoteThreadList.test.ts +1026 -0
  284. package/src/react/client/RemoteThreadList.ts +1067 -0
  285. package/src/react/client/Tools.ts +36 -29
  286. package/src/react/index.ts +13 -0
  287. package/src/react/interactables-legacy/Interactables.test.ts +317 -0
  288. package/src/react/interactables-legacy/Interactables.ts +204 -128
  289. package/src/react/primitive-hooks/useActionBarCopy.ts +2 -7
  290. package/src/react/primitive-hooks/useActionBarEdit.ts +2 -1
  291. package/src/react/primitive-hooks/useActionBarReload.ts +2 -6
  292. package/src/react/primitive-hooks/useBranchPickerNext.ts +2 -7
  293. package/src/react/primitive-hooks/useBranchPickerPrevious.ts +2 -7
  294. package/src/react/primitive-hooks/useComposerCancel.ts +2 -1
  295. package/src/react/primitive-hooks/useComposerSend.ts +2 -5
  296. package/src/react/primitive-hooks/useSuggestionTrigger.test.ts +11 -0
  297. package/src/react/primitive-hooks/useSuggestionTrigger.ts +4 -5
  298. package/src/react/primitives/message/MessageParts.tsx +0 -1
  299. package/src/react/primitives/thread/ThreadMessages.tsx +2 -1
  300. package/src/react/runtimes/RemoteThreadListHookInstanceManager.retry.test.tsx +116 -0
  301. package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +1 -1
  302. package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +57 -6
  303. package/src/react/runtimes/RemoteThreadListHookInstanceManager.title.test.tsx +272 -0
  304. package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +159 -124
  305. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +59 -20
  306. package/src/react/runtimes/RemoteThreadResource.test.ts +141 -0
  307. package/src/react/runtimes/RemoteThreadResource.ts +231 -0
  308. package/src/react/runtimes/RuntimeAdapterProvider.tsx +8 -20
  309. package/src/react/runtimes/assistant-transport/commandQueue.ts +68 -0
  310. package/src/react/runtimes/assistant-transport/replayBoundaryStream.test.ts +455 -0
  311. package/src/react/runtimes/assistant-transport/replayBoundaryStream.ts +172 -0
  312. package/src/react/runtimes/assistant-transport/runManager.ts +124 -0
  313. package/src/react/runtimes/assistant-transport/transport-delivery.test.tsx +79 -0
  314. package/src/react/runtimes/assistant-transport/transport-parentid.test.tsx +97 -0
  315. package/src/react/runtimes/assistant-transport/transport-scheduling.test.ts +414 -0
  316. package/src/react/runtimes/assistant-transport/types.ts +170 -0
  317. package/src/react/runtimes/assistant-transport/useAssistantTransport.spec.md +141 -0
  318. package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.test.tsx +625 -0
  319. package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.ts +481 -0
  320. package/src/react/runtimes/assistant-transport/useConvertedState.ts +20 -0
  321. package/src/react/runtimes/assistant-transport/useLatestRef.ts +9 -0
  322. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +131 -6
  323. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +61 -15
  324. package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +6 -4
  325. package/src/react/runtimes/cloud/auiV0.ts +17 -1
  326. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +36 -21
  327. package/src/react/runtimes/cloud/useCloudThreadListRuntime.test.tsx +56 -0
  328. package/src/react/runtimes/cloud/useCloudThreadListRuntime.ts +31 -0
  329. package/src/react/runtimes/external-message-converter.test.ts +143 -0
  330. package/src/react/runtimes/external-message-converter.ts +41 -41
  331. package/src/react/runtimes/remote-thread-hook-on-tap.test.ts +58 -0
  332. package/src/react/runtimes/useExternalStoreRuntime.lifecycle.test.tsx +83 -0
  333. package/src/react/runtimes/useExternalStoreRuntime.suggestions.test.tsx +13 -3
  334. package/src/react/runtimes/useExternalStoreRuntime.ts +7 -0
  335. package/src/react/runtimes/useExternalStoreSharedOptions.ts +3 -1
  336. package/src/react/runtimes/useLocalRuntime.test.tsx +130 -4
  337. package/src/react/runtimes/useRuntimeAdapters.test.tsx +62 -0
  338. package/src/react/runtimes/useRuntimeAdapters.ts +28 -0
  339. package/src/runtime/api/composer-runtime.ts +5 -0
  340. package/src/runtime/api/thread-list-runtime.ts +3 -1
  341. package/src/runtime/api/thread-runtime.ts +20 -2
  342. package/src/runtime/base/base-composer-runtime-core.ts +6 -5
  343. package/src/runtime/base/base-thread-runtime-core.test.ts +191 -0
  344. package/src/runtime/base/base-thread-runtime-core.ts +11 -2
  345. package/src/runtime/base/default-thread-composer-runtime-core.ts +12 -4
  346. package/src/runtime/interfaces/thread-runtime-core.ts +6 -0
  347. package/src/runtime/queue/message-queue.ts +2 -1
  348. package/src/runtime/utils/thread-runtime-lifecycle.ts +18 -0
  349. package/src/runtimes/external-store/external-store-shared-options.ts +3 -1
  350. package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +4 -1
  351. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +99 -34
  352. package/src/runtimes/local/local-thread-runtime-core.test.ts +373 -4
  353. package/src/runtimes/local/local-thread-runtime-core.ts +79 -14
  354. package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +4 -0
  355. package/src/runtimes/remote-thread-list/empty-thread-core.ts +4 -0
  356. package/src/runtimes/remote-thread-list/types.ts +30 -0
  357. package/src/runtimes/tool-invocations/EDGE_CASES.md +17 -6
  358. package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +243 -0
  359. package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +127 -61
  360. package/src/store/clients/model-context-client.test.ts +16 -8
  361. package/src/store/clients/suggestions.ts +2 -2
  362. package/src/store/clients/thread-selection-events.ts +21 -0
  363. package/src/store/env.ts +11 -0
  364. package/src/store/index.ts +14 -1
  365. package/src/store/internal.ts +13 -0
  366. package/src/store/primitive-predicates.test.ts +184 -0
  367. package/src/store/primitive-predicates.ts +43 -0
  368. package/src/store/runtime-clients/attachment-runtime-client.test.ts +41 -0
  369. package/src/store/runtime-clients/attachment-runtime-client.ts +2 -1
  370. package/src/store/runtime-clients/handle-runtime-action.ts +11 -0
  371. package/src/store/runtime-clients/handle-thread-list-action.test.ts +69 -0
  372. package/src/store/runtime-clients/handle-thread-list-action.ts +6 -0
  373. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +15 -7
  374. package/src/store/runtime-clients/thread-list-runtime-client.ts +9 -6
  375. package/src/store/scopes/composer.ts +9 -4
  376. package/src/store/scopes/thread-list-item.ts +7 -6
  377. package/src/store/scopes/thread.ts +8 -7
  378. package/src/store/scopes/threads.ts +14 -0
  379. package/src/subscribable/subscribable.test.ts +77 -1
  380. package/src/subscribable/subscribable.ts +38 -23
  381. package/src/tests/RemoteThreadListThreadListRuntimeCore-switchToThread-unarchive.test.ts +25 -0
  382. package/src/tests/auiV0Encode.test.ts +66 -0
  383. package/src/tests/base-composer-runtime-core-send.test.ts +30 -0
  384. package/src/tests/base-composer-runtime-core.test.ts +28 -0
  385. package/src/tests/composer-can-cancel.test.ts +101 -0
  386. package/src/tests/external-store-thread-list-runtime-core.test.ts +101 -0
  387. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +191 -1
  388. package/src/tests/external-store-thread-runtime-core.test.ts +124 -0
  389. package/src/tests/interactables-toolui-migration.test.tsx +66 -0
  390. package/src/tests/message-queue.test.ts +28 -0
  391. package/src/tests/session-reset-notification.test.ts +145 -0
  392. package/src/tests/thread-switch-events.test.tsx +99 -1
  393. package/src/tests/tools-scope-migration.test.tsx +58 -0
  394. package/src/utils/composite-context-provider.test.ts +139 -0
  395. package/src/utils/composite-context-provider.ts +26 -8
  396. package/src/utils/notify-event-listeners.ts +10 -5
@@ -0,0 +1,83 @@
1
+ // @vitest-environment jsdom
2
+
3
+ import { StrictMode } from "react";
4
+ import { act, render } from "@testing-library/react";
5
+ import { describe, expect, it, vi } from "vitest";
6
+ import { useExternalStoreRuntime } from "./useExternalStoreRuntime";
7
+ import type { AssistantRuntime } from "../../runtime/api/assistant-runtime";
8
+
9
+ describe("useExternalStoreRuntime lifecycle", () => {
10
+ it("keeps dispatching appends after StrictMode's simulated remount", async () => {
11
+ const onNew = vi.fn(async () => {});
12
+ const capture: { runtime: AssistantRuntime | null } = { runtime: null };
13
+ const App = () => {
14
+ const runtime = useExternalStoreRuntime({ messages: [], onNew });
15
+ capture.runtime = runtime;
16
+ return null;
17
+ };
18
+ render(
19
+ <StrictMode>
20
+ <App />
21
+ </StrictMode>,
22
+ );
23
+ expect(capture.runtime).not.toBeNull();
24
+
25
+ await act(async () => {
26
+ await capture.runtime!.thread.append({
27
+ role: "user",
28
+ content: [{ type: "text", text: "hello" }],
29
+ });
30
+ });
31
+
32
+ expect(onNew).toHaveBeenCalledTimes(1);
33
+ });
34
+
35
+ it("dispatches an append before unmount", async () => {
36
+ let resolveInitialization!: () => void;
37
+ const initialization = new Promise<void>((resolve) => {
38
+ resolveInitialization = resolve;
39
+ });
40
+ const onNew = vi.fn(async () => {});
41
+ const capture: { runtime: AssistantRuntime | null } = { runtime: null };
42
+ const App = () => {
43
+ const runtime = useExternalStoreRuntime({ messages: [], onNew });
44
+ capture.runtime = runtime;
45
+ return null;
46
+ };
47
+ const view = render(<App />);
48
+ expect(capture.runtime).not.toBeNull();
49
+ const core = (
50
+ capture.runtime!.thread as unknown as {
51
+ __internal_threadBinding: {
52
+ getState(): {
53
+ __internal_setGetInitializePromise(
54
+ getPromise: () => Promise<unknown> | undefined,
55
+ ): void;
56
+ append(message: unknown): Promise<void>;
57
+ };
58
+ };
59
+ }
60
+ ).__internal_threadBinding.getState();
61
+ core.__internal_setGetInitializePromise(() => initialization);
62
+
63
+ const appendPromise = core.append({
64
+ parentId: null,
65
+ sourceId: null,
66
+ runConfig: {},
67
+ role: "user",
68
+ content: [{ type: "text", text: "hello" }],
69
+ attachments: [],
70
+ metadata: { custom: {} },
71
+ createdAt: new Date(0),
72
+ });
73
+ await Promise.resolve();
74
+
75
+ expect(onNew).toHaveBeenCalledTimes(1);
76
+
77
+ view.unmount();
78
+ resolveInitialization();
79
+
80
+ await appendPromise;
81
+ expect(onNew).toHaveBeenCalledTimes(1);
82
+ });
83
+ });
@@ -52,20 +52,30 @@ afterEach(() => {
52
52
  describe("useExternalStoreRuntime suggestions scope", () => {
53
53
  it("exposes runtime suggestions on the suggestions scope", () => {
54
54
  render(
55
- <App suggestions={[{ prompt: "Tell me a joke" }, { prompt: "Help" }]} />,
55
+ <App
56
+ suggestions={[
57
+ { title: "Weather", label: "in SF", prompt: "What's the weather?" },
58
+ { prompt: "Help" },
59
+ ]}
60
+ />,
56
61
  );
57
62
 
58
63
  expect(scopeSuggestions).toEqual([
59
- { title: "Tell me a joke", label: "", prompt: "Tell me a joke" },
64
+ { title: "Weather", label: "in SF", prompt: "What's the weather?" },
60
65
  { title: "Help", label: "", prompt: "Help" },
61
66
  ]);
67
+ expect(aui.suggestions.suggestion({ index: 0 }).getState()).toEqual({
68
+ title: "Weather",
69
+ label: "in SF",
70
+ prompt: "What's the weather?",
71
+ });
62
72
  expect(aui.suggestions.suggestion({ index: 1 }).getState()).toEqual({
63
73
  title: "Help",
64
74
  label: "",
65
75
  prompt: "Help",
66
76
  });
67
77
  expect(aui.thread.getState().suggestions).toEqual([
68
- { prompt: "Tell me a joke" },
78
+ { title: "Weather", label: "in SF", prompt: "What's the weather?" },
69
79
  { prompt: "Help" },
70
80
  ]);
71
81
  });
@@ -5,6 +5,7 @@ import { ExternalStoreRuntimeCore } from "../../runtimes/internal";
5
5
  import type { ExternalStoreAdapter } from "../../runtimes/external-store/external-store-adapter";
6
6
  import type { AssistantRuntime } from "../../runtime/api/assistant-runtime";
7
7
  import { AssistantRuntimeImpl } from "../../runtime/internal";
8
+ import { invalidateThreadRuntime } from "../../runtime/utils/thread-runtime-lifecycle";
8
9
  import { useRuntimeAdapters } from "./RuntimeAdapterProvider";
9
10
 
10
11
  export const useExternalStoreRuntime = <T>(
@@ -12,6 +13,12 @@ export const useExternalStoreRuntime = <T>(
12
13
  ): AssistantRuntime => {
13
14
  const [runtime] = useState(() => new ExternalStoreRuntimeCore(store));
14
15
 
16
+ useEffect(() => {
17
+ return () => {
18
+ invalidateThreadRuntime(runtime.threads.getMainThreadRuntimeCore());
19
+ };
20
+ }, [runtime]);
21
+
15
22
  useEffect(() => {
16
23
  runtime.setAdapter(store);
17
24
  });
@@ -16,7 +16,9 @@ export const useExternalStoreSharedOptions = (
16
16
  unstable_capabilities,
17
17
  suggestions,
18
18
  }) satisfies {
19
- [K in keyof Required<ExternalStoreSharedOptions>]: ExternalStoreSharedOptions[K];
19
+ [
20
+ K in keyof Required<ExternalStoreSharedOptions>
21
+ ]: ExternalStoreSharedOptions[K];
20
22
  },
21
23
  [isDisabled, isSendDisabled, unstable_capabilities, suggestions],
22
24
  );
@@ -1,9 +1,10 @@
1
1
  // @vitest-environment jsdom
2
2
 
3
- import { render, waitFor } from "@testing-library/react";
4
- import { StrictMode } from "react";
3
+ import { act, render, waitFor } from "@testing-library/react";
4
+ import { type FC, StrictMode } from "react";
5
5
  import { afterEach, describe, expect, it, vi } from "vitest";
6
6
  import type { AssistantCloud } from "assistant-cloud";
7
+ import { useAui, useAuiState } from "@assistant-ui/store";
7
8
  import type { ChatModelAdapter } from "../../runtime/utils/chat-model-adapter";
8
9
  import { AssistantRuntimeProvider } from "../AssistantRuntimeProvider";
9
10
  import { useLocalRuntime } from "./useLocalRuntime";
@@ -17,13 +18,49 @@ const makeCloud = () =>
17
18
  threads: {
18
19
  list: vi.fn().mockResolvedValue({ threads: [] }),
19
20
  },
21
+ files: {
22
+ generatePresignedUploadUrl: vi.fn().mockResolvedValue({
23
+ signedUrl: "https://storage.example/upload",
24
+ publicUrl: "https://cdn.example/file.txt",
25
+ }),
26
+ },
20
27
  }) as unknown as AssistantCloud;
21
28
 
22
29
  afterEach(() => {
30
+ vi.unstubAllGlobals();
23
31
  vi.restoreAllMocks();
24
32
  });
25
33
 
26
34
  describe("useLocalRuntime", () => {
35
+ it("surfaces the live thread after mount without user input", async () => {
36
+ const auiRef: { current: ReturnType<typeof useAui> | null } = {
37
+ current: null,
38
+ };
39
+ const loadingRef = { current: true };
40
+ const Capture: FC = () => {
41
+ auiRef.current = useAui();
42
+ loadingRef.current = useAuiState((s) => s.thread.isLoading);
43
+ return null;
44
+ };
45
+
46
+ const App = () => {
47
+ const runtime = useLocalRuntime(chatModel, {
48
+ unstable_enableMessageQueue: true,
49
+ });
50
+ return (
51
+ <AssistantRuntimeProvider runtime={runtime}>
52
+ <Capture />
53
+ </AssistantRuntimeProvider>
54
+ );
55
+ };
56
+
57
+ render(<App />);
58
+ await waitFor(() => {
59
+ expect(loadingRef.current).toBe(false);
60
+ expect(auiRef.current!.thread.getState().capabilities.queue).toBe(true);
61
+ });
62
+ });
63
+
27
64
  it("keeps the Cloud thread list loaded across unrelated rerenders", async () => {
28
65
  const firstCloud = makeCloud();
29
66
  const secondCloud = makeCloud();
@@ -59,6 +96,47 @@ describe("useLocalRuntime", () => {
59
96
  expect(firstCloud.threads.list).toHaveBeenCalledOnce();
60
97
  });
61
98
 
99
+ it("uses the current Cloud client for attachment uploads", async () => {
100
+ vi.stubGlobal("fetch", vi.fn().mockResolvedValue({ ok: true }));
101
+ const firstCloud = makeCloud();
102
+ const secondCloud = makeCloud();
103
+ let addAttachment: ((file: File) => Promise<void>) | undefined;
104
+ let getAttachmentStatus: (() => unknown) | undefined;
105
+
106
+ const App = ({ cloud }: { cloud: AssistantCloud }) => {
107
+ const runtime = useLocalRuntime(chatModel, { cloud });
108
+ addAttachment = (file) => runtime.thread.composer.addAttachment(file);
109
+ getAttachmentStatus = () =>
110
+ runtime.thread.composer.getState().attachments[0]?.status;
111
+ return (
112
+ <AssistantRuntimeProvider runtime={runtime}>
113
+ <div />
114
+ </AssistantRuntimeProvider>
115
+ );
116
+ };
117
+
118
+ const { rerender } = render(<App cloud={firstCloud} />);
119
+
120
+ await waitFor(() => {
121
+ expect(firstCloud.threads.list).toHaveBeenCalledOnce();
122
+ });
123
+
124
+ rerender(<App cloud={secondCloud} />);
125
+
126
+ await act(async () => {
127
+ await addAttachment!(
128
+ new File(["hello"], "notes.txt", { type: "text/plain" }),
129
+ );
130
+ });
131
+
132
+ expect(firstCloud.files.generatePresignedUploadUrl).not.toHaveBeenCalled();
133
+ expect(secondCloud.files.generatePresignedUploadUrl).toHaveBeenCalledOnce();
134
+ expect(getAttachmentStatus!()).toEqual({
135
+ type: "requires-action",
136
+ reason: "composer-send",
137
+ });
138
+ });
139
+
62
140
  it("handles rejected history loads", async () => {
63
141
  const error = new Error("history unavailable");
64
142
  const consoleError = vi
@@ -92,8 +170,56 @@ describe("useLocalRuntime", () => {
92
170
  );
93
171
  });
94
172
 
173
+ const loadsAfterMount = history.load.mock.calls.length;
174
+ const errorsAfterMount = consoleError.mock.calls.length;
175
+ expect(loadsAfterMount).toBeGreaterThan(0);
95
176
  rerender(renderApp());
96
- expect(history.load).toHaveBeenCalledTimes(1);
97
- expect(consoleError).toHaveBeenCalledTimes(1);
177
+ expect(history.load).toHaveBeenCalledTimes(loadsAfterMount);
178
+ expect(consoleError).toHaveBeenCalledTimes(errorsAfterMount);
179
+ });
180
+
181
+ it("exposes composer.canCancel while a run started after initial messages is in flight", async () => {
182
+ const hangingModel: ChatModelAdapter = {
183
+ async *run({ abortSignal }) {
184
+ await new Promise<void>((resolve) => {
185
+ if (abortSignal.aborted) {
186
+ resolve();
187
+ return;
188
+ }
189
+ abortSignal.addEventListener("abort", () => resolve(), {
190
+ once: true,
191
+ });
192
+ });
193
+ },
194
+ };
195
+ let runtime: ReturnType<typeof useLocalRuntime> | null = null;
196
+ const App = () => {
197
+ runtime = useLocalRuntime(hangingModel, {
198
+ initialMessages: [
199
+ {
200
+ role: "assistant",
201
+ content: [{ type: "text", text: "Hello" }],
202
+ status: { type: "complete", reason: "stop" },
203
+ },
204
+ ],
205
+ });
206
+ return (
207
+ <AssistantRuntimeProvider runtime={runtime}>
208
+ <div />
209
+ </AssistantRuntimeProvider>
210
+ );
211
+ };
212
+
213
+ render(<App />);
214
+ act(() => {
215
+ runtime!.thread.append("Run");
216
+ });
217
+ await waitFor(() => {
218
+ expect(runtime!.thread.getState().isRunning).toBe(true);
219
+ expect(runtime!.thread.composer.getState().canCancel).toBe(true);
220
+ });
221
+ act(() => {
222
+ runtime!.thread.cancelRun();
223
+ });
98
224
  });
99
225
  });
@@ -0,0 +1,62 @@
1
+ // @vitest-environment jsdom
2
+
3
+ import { renderHook } from "@testing-library/react";
4
+ import { describe, expect, it } from "vitest";
5
+ import { useStableRuntimeAdapters } from "./useRuntimeAdapters";
6
+ import type { RuntimeAdapters } from "../../runtimes/remote-thread-list/types";
7
+ import type { ThreadHistoryAdapter } from "../../adapters/thread-history";
8
+
9
+ const makeHistory = (): ThreadHistoryAdapter => ({
10
+ load: async () => ({ messages: [] }),
11
+ append: async () => {},
12
+ });
13
+
14
+ describe("useStableRuntimeAdapters", () => {
15
+ it("keeps the previous bag when a fresh literal is shallow-equal", () => {
16
+ const history = makeHistory();
17
+ const { result, rerender } = renderHook(
18
+ ({ adapters }: { adapters: RuntimeAdapters | null }) =>
19
+ useStableRuntimeAdapters(adapters),
20
+ { initialProps: { adapters: { history } } },
21
+ );
22
+ const first = result.current;
23
+
24
+ rerender({ adapters: { history } });
25
+
26
+ expect(result.current).toBe(first);
27
+ });
28
+
29
+ it("adopts the new bag when a field changes", () => {
30
+ const first = makeHistory();
31
+ const second = makeHistory();
32
+ const { result, rerender } = renderHook(
33
+ ({ adapters }: { adapters: RuntimeAdapters | null }) =>
34
+ useStableRuntimeAdapters(adapters),
35
+ { initialProps: { adapters: { history: first } } },
36
+ );
37
+
38
+ rerender({ adapters: { history: second } });
39
+
40
+ expect(result.current?.history).toBe(second);
41
+ });
42
+
43
+ it("moves between null and a bag", () => {
44
+ const history = makeHistory();
45
+ const { result, rerender } = renderHook(
46
+ ({ adapters }: { adapters: RuntimeAdapters | null }) =>
47
+ useStableRuntimeAdapters(adapters),
48
+ { initialProps: { adapters: null as RuntimeAdapters | null } },
49
+ );
50
+ expect(result.current).toBeNull();
51
+
52
+ rerender({ adapters: { history } });
53
+ expect(result.current?.history).toBe(history);
54
+
55
+ rerender({ adapters: null });
56
+ expect(result.current).toBeNull();
57
+
58
+ rerender({ adapters: {} });
59
+ expect(result.current).not.toBeNull();
60
+ expect(result.current).toEqual({});
61
+ });
62
+ });
@@ -0,0 +1,28 @@
1
+ import { createContext, useContext } from "react";
2
+ import { useContextProvider } from "@assistant-ui/tap";
3
+ import { useShallowStable } from "@assistant-ui/store/internal";
4
+ import type { RuntimeAdapters } from "../../runtimes/remote-thread-list/types";
5
+
6
+ const RuntimeAdaptersContext = createContext<RuntimeAdapters | null>(null);
7
+
8
+ export const useRuntimeAdaptersProvider = <T>(
9
+ adapters: RuntimeAdapters | null,
10
+ fn: () => T,
11
+ ): T => useContextProvider(RuntimeAdaptersContext, adapters, fn);
12
+
13
+ export const useRuntimeAdapters = () => {
14
+ return useContext(RuntimeAdaptersContext);
15
+ };
16
+
17
+ const NO_ADAPTERS: RuntimeAdapters = {};
18
+
19
+ // Both adapter faces absorb a fresh but shallow-equal bag from
20
+ // `unstable_useAdapters`, so a per-render literal does not churn the context.
21
+ export const useStableRuntimeAdapters = (
22
+ adapters: RuntimeAdapters | null | undefined,
23
+ ): RuntimeAdapters | null => {
24
+ const stable = useShallowStable(adapters ?? NO_ADAPTERS);
25
+ return adapters == null ? null : stable;
26
+ };
27
+
28
+ export { RuntimeAdaptersContext };
@@ -42,6 +42,11 @@ export type {
42
42
  };
43
43
 
44
44
  type BaseComposerState = {
45
+ /**
46
+ * Whether the composer can cancel the current run. `true` when the runtime
47
+ * supports cancel and a run is in flight, not merely when cancel is a
48
+ * capability.
49
+ */
45
50
  readonly canCancel: boolean;
46
51
  readonly canSend: boolean;
47
52
  readonly isEditing: boolean;
@@ -114,6 +114,7 @@ export type ThreadListRuntimeCoreBinding = ThreadListRuntimeCore;
114
114
 
115
115
  export class ThreadListRuntimeImpl implements ThreadListRuntime {
116
116
  private _getState;
117
+ private _stateBinding: LazyMemoizeSubject<ThreadListState, object>;
117
118
  private _core: ThreadListRuntimeCoreBinding;
118
119
  private _runtimeFactory: new (
119
120
  binding: ThreadRuntimeCoreBinding,
@@ -136,6 +137,7 @@ export class ThreadListRuntimeImpl implements ThreadListRuntime {
136
137
  });
137
138
 
138
139
  this._getState = stateBinding.getState.bind(stateBinding);
140
+ this._stateBinding = stateBinding;
139
141
 
140
142
  this._mainThreadListItemRuntime = new ThreadListItemRuntimeImpl(
141
143
  new ShallowMemoizeSubject({
@@ -213,7 +215,7 @@ export class ThreadListRuntimeImpl implements ThreadListRuntime {
213
215
  }
214
216
 
215
217
  public subscribe(callback: () => void): Unsubscribe {
216
- return this._core.subscribe(callback);
218
+ return this._stateBinding.subscribe(callback);
217
219
  }
218
220
 
219
221
  private _mainThreadListItemRuntime;
@@ -199,7 +199,7 @@ export type ThreadState = {
199
199
  * reports it directly; the rest fall back to the trailing assistant message.
200
200
  */
201
201
  export const getThreadRuntimeCoreIsRunning = (
202
- runtime: ThreadRuntimeCore,
202
+ runtime: Pick<ThreadRuntimeCore, "isRunning" | "messages">,
203
203
  ): boolean => {
204
204
  if (runtime.isRunning !== undefined) return runtime.isRunning;
205
205
  const lastMessage = runtime.messages.at(-1);
@@ -294,6 +294,13 @@ export type ThreadRuntime = {
294
294
 
295
295
  subscribe(callback: () => void): Unsubscribe;
296
296
  cancelRun(): void;
297
+ /**
298
+ * Notifies the runtime that the adapter discarded its backing session.
299
+ * Clears session-scoped tool-invocation state without run-cancel side
300
+ * effects such as composer draft restoration. Internal API for
301
+ * external-store adapter authors.
302
+ */
303
+ unstable_notifySessionReset(): void;
297
304
  getModelContext(): ModelContext;
298
305
 
299
306
  export(): ExportedMessageRepository;
@@ -339,6 +346,10 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
339
346
  private readonly _threadBinding: ThreadRuntimeCoreBinding & {
340
347
  getStateState(): ThreadState;
341
348
  };
349
+ private readonly _stateBinding: ShallowMemoizeSubject<
350
+ ThreadState,
351
+ ThreadRuntimePath
352
+ >;
342
353
 
343
354
  constructor(
344
355
  threadBinding: ThreadRuntimeCoreBinding,
@@ -361,6 +372,7 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
361
372
  },
362
373
  });
363
374
 
375
+ this._stateBinding = stateBinding;
364
376
  this._threadBinding = {
365
377
  path: threadBinding.path,
366
378
  getState: () => threadBinding.getState(),
@@ -392,6 +404,8 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
392
404
  this.exportExternalState = this.exportExternalState.bind(this);
393
405
  this.startRun = this.startRun.bind(this);
394
406
  this.cancelRun = this.cancelRun.bind(this);
407
+ this.unstable_notifySessionReset =
408
+ this.unstable_notifySessionReset.bind(this);
395
409
  this.stopSpeaking = this.stopSpeaking.bind(this);
396
410
  this.connectVoice = this.connectVoice.bind(this);
397
411
  this.disconnectVoice = this.disconnectVoice.bind(this);
@@ -435,7 +449,7 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
435
449
  }
436
450
 
437
451
  public subscribe(callback: () => void) {
438
- return this._threadBinding.subscribe(callback);
452
+ return this._stateBinding.subscribe(callback);
439
453
  }
440
454
 
441
455
  public getModelContext() {
@@ -462,6 +476,10 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
462
476
  this._threadBinding.getState().cancelRun();
463
477
  }
464
478
 
479
+ public unstable_notifySessionReset() {
480
+ this._threadBinding.getState().unstable_notifySessionReset();
481
+ }
482
+
465
483
  public stopSpeaking() {
466
484
  return this._threadBinding.getState().stopSpeaking();
467
485
  }
@@ -240,6 +240,8 @@ export abstract class BaseComposerRuntimeCore
240
240
  const originalAttachments = this.attachments;
241
241
  const text = this.text;
242
242
  const quote = this._quote;
243
+ const role = this.role;
244
+ const runConfig = this.runConfig;
243
245
  this._quote = undefined;
244
246
  this._text = "";
245
247
  this._isSending = true;
@@ -291,10 +293,10 @@ export abstract class BaseComposerRuntimeCore
291
293
 
292
294
  const message: Omit<AppendMessage, "parentId" | "sourceId"> = {
293
295
  createdAt: new Date(),
294
- role: this.role,
296
+ role,
295
297
  content: text ? [{ type: "text", text }] : [],
296
298
  attachments: finalAttachments,
297
- runConfig: this.runConfig,
299
+ runConfig,
298
300
  metadata: { custom: { ...(quote ? { quote } : {}) } },
299
301
  };
300
302
 
@@ -718,9 +720,8 @@ export abstract class BaseComposerRuntimeCore
718
720
 
719
721
  const session = this._dictationSession;
720
722
  const sessionId = this._activeDictationSessionId;
721
- session.stop().finally(() => {
722
- this._cleanupDictation({ sessionId });
723
- });
723
+ const cleanup = () => this._cleanupDictation({ sessionId });
724
+ void session.stop().then(cleanup, cleanup);
724
725
  }
725
726
 
726
727
  private _cleanupDictation(options?: { sessionId: number | undefined }): void {