@assistant-ui/core 0.3.12 → 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 (452) 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 +3 -3
  10. package/dist/index.js +2 -2
  11. package/dist/index.js.map +1 -1
  12. package/dist/internal.d.ts +1 -1
  13. package/dist/internal.js +6 -6
  14. package/dist/model-context/frame/host.d.ts.map +1 -1
  15. package/dist/model-context/frame/host.js +2 -1
  16. package/dist/model-context/frame/host.js.map +1 -1
  17. package/dist/model-context/registry.d.ts.map +1 -1
  18. package/dist/model-context/registry.js +16 -4
  19. package/dist/model-context/registry.js.map +1 -1
  20. package/dist/react/RuntimeAdapter.d.ts +8 -1
  21. package/dist/react/RuntimeAdapter.d.ts.map +1 -1
  22. package/dist/react/RuntimeAdapter.js +23 -18
  23. package/dist/react/RuntimeAdapter.js.map +1 -1
  24. package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
  25. package/dist/react/adapters/LocalStorageThreadListAdapter.js +28 -12
  26. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  27. package/dist/react/client/AdaptedRemoteThread.d.ts +11 -0
  28. package/dist/react/client/AdaptedRemoteThread.d.ts.map +1 -0
  29. package/dist/react/client/AdaptedRemoteThread.js +27 -0
  30. package/dist/react/client/AdaptedRemoteThread.js.map +1 -0
  31. package/dist/react/client/InMemoryThreadList.d.ts +19 -0
  32. package/dist/react/client/InMemoryThreadList.d.ts.map +1 -0
  33. package/dist/react/client/InMemoryThreadList.js +418 -0
  34. package/dist/react/client/InMemoryThreadList.js.map +1 -0
  35. package/dist/react/client/Interactables.d.ts.map +1 -1
  36. package/dist/react/client/Interactables.js +159 -102
  37. package/dist/react/client/Interactables.js.map +1 -1
  38. package/dist/react/client/RemoteThreadList.d.ts +34 -0
  39. package/dist/react/client/RemoteThreadList.d.ts.map +1 -0
  40. package/dist/react/client/RemoteThreadList.js +826 -0
  41. package/dist/react/client/RemoteThreadList.js.map +1 -0
  42. package/dist/react/client/Tools.d.ts.map +1 -1
  43. package/dist/react/client/Tools.js +38 -27
  44. package/dist/react/client/Tools.js.map +1 -1
  45. package/dist/react/client/interactable-model-context.d.ts.map +1 -1
  46. package/dist/react/client/interactable-model-context.js +5 -1
  47. package/dist/react/client/interactable-model-context.js.map +1 -1
  48. package/dist/react/index.d.ts +7 -2
  49. package/dist/react/index.js +5 -2
  50. package/dist/react/interactables-legacy/Interactables.d.ts.map +1 -1
  51. package/dist/react/interactables-legacy/Interactables.js +145 -110
  52. package/dist/react/interactables-legacy/Interactables.js.map +1 -1
  53. package/dist/react/primitive-hooks/useActionBarCopy.d.ts.map +1 -1
  54. package/dist/react/primitive-hooks/useActionBarCopy.js +13 -18
  55. package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
  56. package/dist/react/primitive-hooks/useActionBarEdit.d.ts.map +1 -1
  57. package/dist/react/primitive-hooks/useActionBarEdit.js +2 -4
  58. package/dist/react/primitive-hooks/useActionBarEdit.js.map +1 -1
  59. package/dist/react/primitive-hooks/useActionBarReload.d.ts.map +1 -1
  60. package/dist/react/primitive-hooks/useActionBarReload.js +2 -4
  61. package/dist/react/primitive-hooks/useActionBarReload.js.map +1 -1
  62. package/dist/react/primitive-hooks/useBranchPickerNext.d.ts.map +1 -1
  63. package/dist/react/primitive-hooks/useBranchPickerNext.js +2 -6
  64. package/dist/react/primitive-hooks/useBranchPickerNext.js.map +1 -1
  65. package/dist/react/primitive-hooks/useBranchPickerPrevious.d.ts.map +1 -1
  66. package/dist/react/primitive-hooks/useBranchPickerPrevious.js +2 -6
  67. package/dist/react/primitive-hooks/useBranchPickerPrevious.js.map +1 -1
  68. package/dist/react/primitive-hooks/useComposerCancel.d.ts.map +1 -1
  69. package/dist/react/primitive-hooks/useComposerCancel.js +2 -4
  70. package/dist/react/primitive-hooks/useComposerCancel.js.map +1 -1
  71. package/dist/react/primitive-hooks/useComposerSend.d.ts.map +1 -1
  72. package/dist/react/primitive-hooks/useComposerSend.js +2 -4
  73. package/dist/react/primitive-hooks/useComposerSend.js.map +1 -1
  74. package/dist/react/primitive-hooks/useSuggestionTrigger.d.ts.map +1 -1
  75. package/dist/react/primitive-hooks/useSuggestionTrigger.js +6 -2
  76. package/dist/react/primitive-hooks/useSuggestionTrigger.js.map +1 -1
  77. package/dist/react/primitives/message/MessageParts.d.ts +13 -0
  78. package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
  79. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  80. package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
  81. package/dist/react/primitives/thread/ThreadMessages.js +1 -1
  82. package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
  83. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +22 -10
  84. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  85. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +109 -71
  86. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  87. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +8 -2
  88. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  89. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +40 -13
  90. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  91. package/dist/react/runtimes/RemoteThreadResource.d.ts +30 -0
  92. package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -0
  93. package/dist/react/runtimes/RemoteThreadResource.js +134 -0
  94. package/dist/react/runtimes/RemoteThreadResource.js.map +1 -0
  95. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts +3 -10
  96. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts.map +1 -1
  97. package/dist/react/runtimes/RuntimeAdapterProvider.js +3 -6
  98. package/dist/react/runtimes/RuntimeAdapterProvider.js.map +1 -1
  99. package/dist/react/runtimes/assistant-transport/commandQueue.d.ts +17 -0
  100. package/dist/react/runtimes/assistant-transport/commandQueue.d.ts.map +1 -0
  101. package/dist/react/runtimes/assistant-transport/commandQueue.js +55 -0
  102. package/dist/react/runtimes/assistant-transport/commandQueue.js.map +1 -0
  103. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.d.ts +11 -0
  104. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.d.ts.map +1 -0
  105. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.js +165 -0
  106. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.js.map +1 -0
  107. package/dist/react/runtimes/assistant-transport/runManager.d.ts +15 -0
  108. package/dist/react/runtimes/assistant-transport/runManager.d.ts.map +1 -0
  109. package/dist/react/runtimes/assistant-transport/runManager.js +86 -0
  110. package/dist/react/runtimes/assistant-transport/runManager.js.map +1 -0
  111. package/dist/react/runtimes/assistant-transport/types.d.ts +130 -0
  112. package/dist/react/runtimes/assistant-transport/types.d.ts.map +1 -0
  113. package/dist/react/runtimes/assistant-transport/types.js +0 -0
  114. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts +14 -0
  115. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -0
  116. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js +296 -0
  117. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js.map +1 -0
  118. package/dist/react/runtimes/assistant-transport/useConvertedState.d.ts +7 -0
  119. package/dist/react/runtimes/assistant-transport/useConvertedState.d.ts.map +1 -0
  120. package/dist/react/runtimes/assistant-transport/useConvertedState.js +25 -0
  121. package/dist/react/runtimes/assistant-transport/useConvertedState.js.map +1 -0
  122. package/dist/react/runtimes/assistant-transport/useLatestRef.d.ts +7 -0
  123. package/dist/react/runtimes/assistant-transport/useLatestRef.d.ts.map +1 -0
  124. package/dist/react/runtimes/assistant-transport/useLatestRef.js +27 -0
  125. package/dist/react/runtimes/assistant-transport/useLatestRef.js.map +1 -0
  126. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  127. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +39 -13
  128. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  129. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +2 -1
  130. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
  131. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +3 -3
  132. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
  133. package/dist/react/runtimes/cloud/auiV0.d.ts +4 -0
  134. package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
  135. package/dist/react/runtimes/cloud/auiV0.js +7 -0
  136. package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
  137. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  138. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +22 -12
  139. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  140. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.d.ts +16 -0
  141. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.d.ts.map +1 -0
  142. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js +36 -0
  143. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js.map +1 -0
  144. package/dist/react/runtimes/external-message-converter.js +14 -14
  145. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  146. package/dist/react/runtimes/useExternalStoreRuntime.d.ts.map +1 -1
  147. package/dist/react/runtimes/useExternalStoreRuntime.js +44 -28
  148. package/dist/react/runtimes/useExternalStoreRuntime.js.map +1 -1
  149. package/dist/react/runtimes/useExternalStoreSharedOptions.js.map +1 -1
  150. package/dist/react/runtimes/useLocalRuntime.js +1 -1
  151. package/dist/react/runtimes/useRuntimeAdapters.d.ts +9 -0
  152. package/dist/react/runtimes/useRuntimeAdapters.d.ts.map +1 -0
  153. package/dist/react/runtimes/useRuntimeAdapters.js +20 -0
  154. package/dist/react/runtimes/useRuntimeAdapters.js.map +1 -0
  155. package/dist/runtime/api/composer-runtime.d.ts +5 -0
  156. package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
  157. package/dist/runtime/api/composer-runtime.js.map +1 -1
  158. package/dist/runtime/api/message-runtime.js +1 -1
  159. package/dist/runtime/api/thread-list-runtime.d.ts +1 -0
  160. package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
  161. package/dist/runtime/api/thread-list-runtime.js +4 -2
  162. package/dist/runtime/api/thread-list-runtime.js.map +1 -1
  163. package/dist/runtime/api/thread-runtime.d.ts +12 -2
  164. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  165. package/dist/runtime/api/thread-runtime.js +13 -3
  166. package/dist/runtime/api/thread-runtime.js.map +1 -1
  167. package/dist/runtime/base/base-composer-runtime-core.d.ts +25 -0
  168. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  169. package/dist/runtime/base/base-composer-runtime-core.js +72 -18
  170. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  171. package/dist/runtime/base/base-thread-runtime-core.d.ts +15 -0
  172. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  173. package/dist/runtime/base/base-thread-runtime-core.js +34 -3
  174. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  175. package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
  176. package/dist/runtime/base/default-edit-composer-runtime-core.js +1 -6
  177. package/dist/runtime/base/default-edit-composer-runtime-core.js.map +1 -1
  178. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +0 -1
  179. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
  180. package/dist/runtime/base/default-thread-composer-runtime-core.js +11 -8
  181. package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
  182. package/dist/runtime/interfaces/thread-runtime-core.d.ts +6 -0
  183. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  184. package/dist/runtime/internal.js +5 -5
  185. package/dist/runtime/queue/external-thread-queue-adapter.d.ts +15 -0
  186. package/dist/runtime/queue/external-thread-queue-adapter.d.ts.map +1 -1
  187. package/dist/runtime/queue/message-queue.d.ts.map +1 -1
  188. package/dist/runtime/queue/message-queue.js +25 -11
  189. package/dist/runtime/queue/message-queue.js.map +1 -1
  190. package/dist/runtime/utils/thread-runtime-lifecycle.d.ts +8 -0
  191. package/dist/runtime/utils/thread-runtime-lifecycle.d.ts.map +1 -0
  192. package/dist/runtime/utils/thread-runtime-lifecycle.js +11 -0
  193. package/dist/runtime/utils/thread-runtime-lifecycle.js.map +1 -0
  194. package/dist/runtimes/external-store/external-store-adapter.d.ts +7 -0
  195. package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
  196. package/dist/runtimes/external-store/external-store-shared-options.js.map +1 -1
  197. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  198. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +4 -1
  199. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  200. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +11 -1
  201. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  202. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +78 -20
  203. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  204. package/dist/runtimes/internal.d.ts +1 -1
  205. package/dist/runtimes/local/local-thread-runtime-core.d.ts +3 -0
  206. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  207. package/dist/runtimes/local/local-thread-runtime-core.js +55 -14
  208. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  209. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +1 -0
  210. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
  211. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +3 -0
  212. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
  213. package/dist/runtimes/remote-thread-list/empty-thread-core.js +3 -0
  214. package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
  215. package/dist/runtimes/remote-thread-list/types.d.ts +29 -1
  216. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  217. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +1 -12
  218. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
  219. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +67 -38
  220. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
  221. package/dist/store/clients/external-thread.d.ts +7 -0
  222. package/dist/store/clients/external-thread.d.ts.map +1 -1
  223. package/dist/store/clients/external-thread.js +460 -369
  224. package/dist/store/clients/external-thread.js.map +1 -1
  225. package/dist/store/clients/runtime-adapter.d.ts.map +1 -1
  226. package/dist/store/clients/runtime-adapter.js +5 -2
  227. package/dist/store/clients/runtime-adapter.js.map +1 -1
  228. package/dist/store/clients/single-thread-list.d.ts.map +1 -1
  229. package/dist/store/clients/single-thread-list.js +31 -27
  230. package/dist/store/clients/single-thread-list.js.map +1 -1
  231. package/dist/store/clients/suggestions.d.ts +3 -1
  232. package/dist/store/clients/suggestions.d.ts.map +1 -1
  233. package/dist/store/clients/suggestions.js +65 -37
  234. package/dist/store/clients/suggestions.js.map +1 -1
  235. package/dist/store/clients/thread-selection-events.d.ts +10 -0
  236. package/dist/store/clients/thread-selection-events.d.ts.map +1 -0
  237. package/dist/store/clients/thread-selection-events.js +40 -0
  238. package/dist/store/clients/thread-selection-events.js.map +1 -0
  239. package/dist/store/env.d.ts +5 -0
  240. package/dist/store/env.d.ts.map +1 -0
  241. package/dist/store/env.js +12 -0
  242. package/dist/store/env.js.map +1 -0
  243. package/dist/store/index.d.ts +6 -4
  244. package/dist/store/index.js +5 -3
  245. package/dist/store/internal.d.ts +4 -1
  246. package/dist/store/internal.js +4 -1
  247. package/dist/store/primitive-predicates.d.ts +19 -0
  248. package/dist/store/primitive-predicates.d.ts.map +1 -0
  249. package/dist/store/primitive-predicates.js +19 -0
  250. package/dist/store/primitive-predicates.js.map +1 -0
  251. package/dist/store/runtime-clients/attachment-runtime-client.d.ts.map +1 -1
  252. package/dist/store/runtime-clients/attachment-runtime-client.js +18 -11
  253. package/dist/store/runtime-clients/attachment-runtime-client.js.map +1 -1
  254. package/dist/store/runtime-clients/handle-runtime-action.d.ts +5 -0
  255. package/dist/store/runtime-clients/handle-runtime-action.d.ts.map +1 -0
  256. package/dist/store/runtime-clients/handle-runtime-action.js +12 -0
  257. package/dist/store/runtime-clients/handle-runtime-action.js.map +1 -0
  258. package/dist/store/runtime-clients/handle-thread-list-action.d.ts +5 -0
  259. package/dist/store/runtime-clients/handle-thread-list-action.d.ts.map +1 -0
  260. package/dist/store/runtime-clients/handle-thread-list-action.js +7 -0
  261. package/dist/store/runtime-clients/handle-thread-list-action.js.map +1 -0
  262. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  263. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +104 -57
  264. package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
  265. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
  266. package/dist/store/runtime-clients/thread-list-runtime-client.js +5 -6
  267. package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
  268. package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
  269. package/dist/store/runtime-clients/thread-runtime-client.js +98 -82
  270. package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
  271. package/dist/store/scope-registration.d.ts +2 -2
  272. package/dist/store/scopes/composer.d.ts +9 -4
  273. package/dist/store/scopes/composer.d.ts.map +1 -1
  274. package/dist/store/scopes/suggestions.d.ts +6 -1
  275. package/dist/store/scopes/suggestions.d.ts.map +1 -1
  276. package/dist/store/scopes/thread-list-item.d.ts +7 -6
  277. package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
  278. package/dist/store/scopes/thread.d.ts +25 -7
  279. package/dist/store/scopes/thread.d.ts.map +1 -1
  280. package/dist/store/scopes/threads.d.ts +17 -1
  281. package/dist/store/scopes/threads.d.ts.map +1 -1
  282. package/dist/subscribable/subscribable.d.ts +2 -1
  283. package/dist/subscribable/subscribable.d.ts.map +1 -1
  284. package/dist/subscribable/subscribable.js +23 -18
  285. package/dist/subscribable/subscribable.js.map +1 -1
  286. package/dist/types/error.d.ts +15 -1
  287. package/dist/types/error.d.ts.map +1 -1
  288. package/dist/types/error.js +18 -1
  289. package/dist/types/error.js.map +1 -1
  290. package/dist/types/message.d.ts +2 -0
  291. package/dist/types/message.d.ts.map +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/package.json +7 -7
  302. package/src/adapters/speech.test.ts +118 -1
  303. package/src/adapters/speech.ts +21 -22
  304. package/src/adapters/thread-history.ts +2 -0
  305. package/src/adapters/voice.test.ts +69 -0
  306. package/src/adapters/voice.ts +27 -27
  307. package/src/index.ts +2 -0
  308. package/src/model-context/frame/host.test.ts +23 -0
  309. package/src/model-context/frame/host.ts +2 -1
  310. package/src/model-context/registry.test.ts +131 -0
  311. package/src/model-context/registry.ts +16 -6
  312. package/src/react/RuntimeAdapter.test.ts +2 -0
  313. package/src/react/RuntimeAdapter.ts +20 -8
  314. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +34 -17
  315. package/src/react/client/AdaptedRemoteThread.ts +41 -0
  316. package/src/react/client/InMemoryThreadList.test.tsx +148 -0
  317. package/src/react/client/InMemoryThreadList.ts +290 -0
  318. package/src/react/client/Interactables.test.ts +326 -2
  319. package/src/react/client/Interactables.ts +227 -110
  320. package/src/react/client/RemoteThreadList.test.ts +1026 -0
  321. package/src/react/client/RemoteThreadList.ts +1067 -0
  322. package/src/react/client/Tools.ts +36 -29
  323. package/src/react/client/interactable-model-context.ts +6 -1
  324. package/src/react/index.ts +13 -0
  325. package/src/react/interactables-legacy/Interactables.test.ts +317 -0
  326. package/src/react/interactables-legacy/Interactables.ts +204 -128
  327. package/src/react/primitive-hooks/useActionBarCopy.ts +2 -7
  328. package/src/react/primitive-hooks/useActionBarEdit.ts +2 -1
  329. package/src/react/primitive-hooks/useActionBarReload.ts +2 -6
  330. package/src/react/primitive-hooks/useBranchPickerNext.ts +2 -7
  331. package/src/react/primitive-hooks/useBranchPickerPrevious.ts +2 -7
  332. package/src/react/primitive-hooks/useComposerCancel.ts +2 -1
  333. package/src/react/primitive-hooks/useComposerSend.ts +2 -5
  334. package/src/react/primitive-hooks/useSuggestionTrigger.test.ts +11 -0
  335. package/src/react/primitive-hooks/useSuggestionTrigger.ts +4 -5
  336. package/src/react/primitives/message/MessageParts.tsx +0 -1
  337. package/src/react/primitives/thread/ThreadMessages.tsx +2 -1
  338. package/src/react/runtimes/RemoteThreadListHookInstanceManager.retry.test.tsx +116 -0
  339. package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +1 -1
  340. package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +57 -6
  341. package/src/react/runtimes/RemoteThreadListHookInstanceManager.title.test.tsx +272 -0
  342. package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +159 -124
  343. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +59 -20
  344. package/src/react/runtimes/RemoteThreadResource.test.ts +141 -0
  345. package/src/react/runtimes/RemoteThreadResource.ts +231 -0
  346. package/src/react/runtimes/RuntimeAdapterProvider.tsx +8 -20
  347. package/src/react/runtimes/assistant-transport/commandQueue.ts +68 -0
  348. package/src/react/runtimes/assistant-transport/replayBoundaryStream.test.ts +455 -0
  349. package/src/react/runtimes/assistant-transport/replayBoundaryStream.ts +172 -0
  350. package/src/react/runtimes/assistant-transport/runManager.ts +124 -0
  351. package/src/react/runtimes/assistant-transport/transport-delivery.test.tsx +79 -0
  352. package/src/react/runtimes/assistant-transport/transport-parentid.test.tsx +97 -0
  353. package/src/react/runtimes/assistant-transport/transport-scheduling.test.ts +414 -0
  354. package/src/react/runtimes/assistant-transport/types.ts +170 -0
  355. package/src/react/runtimes/assistant-transport/useAssistantTransport.spec.md +141 -0
  356. package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.test.tsx +625 -0
  357. package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.ts +481 -0
  358. package/src/react/runtimes/assistant-transport/useConvertedState.ts +20 -0
  359. package/src/react/runtimes/assistant-transport/useLatestRef.ts +9 -0
  360. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +131 -6
  361. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +61 -15
  362. package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +6 -4
  363. package/src/react/runtimes/cloud/auiV0.ts +17 -1
  364. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +36 -21
  365. package/src/react/runtimes/cloud/useCloudThreadListRuntime.test.tsx +56 -0
  366. package/src/react/runtimes/cloud/useCloudThreadListRuntime.ts +31 -0
  367. package/src/react/runtimes/external-message-converter.test.ts +143 -0
  368. package/src/react/runtimes/external-message-converter.ts +41 -41
  369. package/src/react/runtimes/remote-thread-hook-on-tap.test.ts +58 -0
  370. package/src/react/runtimes/useExternalStoreRuntime.lifecycle.test.tsx +83 -0
  371. package/src/react/runtimes/useExternalStoreRuntime.suggestions.test.tsx +124 -0
  372. package/src/react/runtimes/useExternalStoreRuntime.ts +7 -0
  373. package/src/react/runtimes/useExternalStoreSharedOptions.ts +3 -1
  374. package/src/react/runtimes/useLocalRuntime.test.tsx +130 -4
  375. package/src/react/runtimes/useRuntimeAdapters.test.tsx +62 -0
  376. package/src/react/runtimes/useRuntimeAdapters.ts +28 -0
  377. package/src/runtime/api/composer-runtime.ts +5 -0
  378. package/src/runtime/api/thread-list-runtime.ts +3 -1
  379. package/src/runtime/api/thread-runtime.ts +28 -3
  380. package/src/runtime/base/base-composer-runtime-core.ts +106 -13
  381. package/src/runtime/base/base-thread-runtime-core.test.ts +191 -0
  382. package/src/runtime/base/base-thread-runtime-core.ts +47 -2
  383. package/src/runtime/base/default-edit-composer-runtime-core.ts +1 -15
  384. package/src/runtime/base/default-thread-composer-runtime-core.ts +13 -15
  385. package/src/runtime/interfaces/thread-runtime-core.ts +6 -0
  386. package/src/runtime/queue/external-thread-queue-adapter.ts +17 -0
  387. package/src/runtime/queue/message-queue.ts +28 -10
  388. package/src/runtime/utils/thread-runtime-lifecycle.ts +18 -0
  389. package/src/runtimes/external-store/external-store-adapter.ts +7 -0
  390. package/src/runtimes/external-store/external-store-shared-options.ts +3 -1
  391. package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +4 -1
  392. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +187 -48
  393. package/src/runtimes/local/local-thread-runtime-core.test.ts +373 -4
  394. package/src/runtimes/local/local-thread-runtime-core.ts +83 -15
  395. package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +4 -0
  396. package/src/runtimes/remote-thread-list/empty-thread-core.ts +4 -0
  397. package/src/runtimes/remote-thread-list/types.ts +30 -0
  398. package/src/runtimes/tool-invocations/EDGE_CASES.md +17 -6
  399. package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +243 -0
  400. package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +127 -61
  401. package/src/store/clients/external-thread.ts +119 -16
  402. package/src/store/clients/model-context-client.test.ts +16 -8
  403. package/src/store/clients/runtime-adapter.ts +5 -2
  404. package/src/store/clients/single-thread-list.ts +2 -1
  405. package/src/store/clients/suggestions.ts +39 -13
  406. package/src/store/clients/thread-selection-events.ts +21 -0
  407. package/src/store/env.ts +11 -0
  408. package/src/store/index.ts +14 -1
  409. package/src/store/internal.ts +13 -0
  410. package/src/store/primitive-predicates.test.ts +184 -0
  411. package/src/store/primitive-predicates.ts +43 -0
  412. package/src/store/runtime-clients/attachment-runtime-client.test.ts +41 -0
  413. package/src/store/runtime-clients/attachment-runtime-client.ts +2 -1
  414. package/src/store/runtime-clients/handle-runtime-action.ts +11 -0
  415. package/src/store/runtime-clients/handle-thread-list-action.test.ts +69 -0
  416. package/src/store/runtime-clients/handle-thread-list-action.ts +6 -0
  417. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +28 -35
  418. package/src/store/runtime-clients/thread-list-runtime-client.ts +9 -6
  419. package/src/store/runtime-clients/thread-runtime-client.ts +5 -0
  420. package/src/store/scopes/composer.ts +9 -4
  421. package/src/store/scopes/suggestions.ts +6 -0
  422. package/src/store/scopes/thread-list-item.ts +7 -6
  423. package/src/store/scopes/thread.ts +25 -7
  424. package/src/store/scopes/threads.ts +14 -0
  425. package/src/subscribable/subscribable.test.ts +77 -1
  426. package/src/subscribable/subscribable.ts +38 -23
  427. package/src/tests/RemoteThreadListThreadListRuntimeCore-switchToThread-unarchive.test.ts +25 -0
  428. package/src/tests/append-interactable-snapshots.test.ts +350 -0
  429. package/src/tests/auiV0Encode.test.ts +66 -0
  430. package/src/tests/base-composer-runtime-core-send.test.ts +156 -0
  431. package/src/tests/base-composer-runtime-core.test.ts +136 -1
  432. package/src/tests/composer-can-cancel.test.ts +101 -0
  433. package/src/tests/default-edit-composer-runtime-core.test.ts +0 -68
  434. package/src/tests/external-store-thread-list-runtime-core.test.ts +101 -0
  435. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +491 -1
  436. package/src/tests/external-store-thread-runtime-core.test.ts +124 -0
  437. package/src/tests/external-thread-attachments.test.tsx +214 -0
  438. package/src/tests/external-thread-parity.test.tsx +54 -0
  439. package/src/tests/external-thread-refetch.test.tsx +117 -0
  440. package/src/tests/external-thread-suggestions.test.tsx +59 -0
  441. package/src/tests/interactables-toolui-migration.test.tsx +66 -0
  442. package/src/tests/message-queue.test.ts +54 -0
  443. package/src/tests/session-reset-notification.test.ts +145 -0
  444. package/src/tests/thread-message-like.test.ts +39 -0
  445. package/src/tests/thread-switch-events.test.tsx +234 -0
  446. package/src/tests/tools-scope-migration.test.tsx +58 -0
  447. package/src/types/error.ts +24 -0
  448. package/src/types/message.ts +2 -0
  449. package/src/utils/composite-context-provider.test.ts +139 -0
  450. package/src/utils/composite-context-provider.ts +26 -8
  451. package/src/utils/notify-event-listeners.ts +10 -5
  452. package/src/tests/default-thread-composer-runtime-core.test.ts +0 -82
@@ -0,0 +1,18 @@
1
+ import type { ThreadRuntimeCore } from "../interfaces/thread-runtime-core";
2
+
3
+ // Invalidation must stay re-entrant: StrictMode's simulated unmount runs the
4
+ // effect cleanup while the runtime object survives into the next mount, so a
5
+ // permanent disposed mark would swallow every later append.
6
+ const generations = new WeakMap<ThreadRuntimeCore, number>();
7
+
8
+ export const captureThreadRuntimeGeneration = (runtime: ThreadRuntimeCore) =>
9
+ generations.get(runtime) ?? 0;
10
+
11
+ export const isThreadRuntimeGenerationCurrent = (
12
+ runtime: ThreadRuntimeCore,
13
+ generation: number,
14
+ ) => captureThreadRuntimeGeneration(runtime) === generation;
15
+
16
+ export const invalidateThreadRuntime = (runtime: ThreadRuntimeCore) => {
17
+ generations.set(runtime, captureThreadRuntimeGeneration(runtime) + 1);
18
+ };
@@ -109,6 +109,13 @@ type ExternalStoreAdapterBase<T> = {
109
109
  state?: ReadonlyJSONValue | undefined;
110
110
  extras?: unknown;
111
111
 
112
+ /**
113
+ * Applies a message list the runtime rewrote, and is what tells the runtime
114
+ * a removal it makes will survive the next snapshot. Without it, cancelling a
115
+ * run leaves a trailing user message in the thread and the composer
116
+ * untouched; an adapter that removes that message itself owns handing it
117
+ * back, because the runtime cannot see a removal it did not make.
118
+ */
112
119
  setMessages?: ((messages: readonly T[]) => void) | undefined;
113
120
  /**
114
121
  * Fires when the user explicitly switches branches via the runtime's
@@ -14,5 +14,7 @@ export const pickExternalStoreSharedOptions = (
14
14
  unstable_capabilities: options.unstable_capabilities,
15
15
  suggestions: options.suggestions,
16
16
  }) satisfies {
17
- [K in keyof Required<ExternalStoreSharedOptions>]: ExternalStoreSharedOptions[K];
17
+ [
18
+ K in keyof Required<ExternalStoreSharedOptions>
19
+ ]: ExternalStoreSharedOptions[K];
18
20
  };
@@ -5,6 +5,8 @@ import type {
5
5
  ThreadListRuntimeCore,
6
6
  } from "../../runtime/interfaces/thread-list-runtime-core";
7
7
  import type { ExternalStoreThreadListAdapter } from "./external-store-adapter";
8
+ import { invalidateThreadRuntime } from "../../runtime/utils/thread-runtime-lifecycle";
9
+ import { notifySubscribers } from "../../subscribable/subscribable";
8
10
 
9
11
  export type ExternalStoreThreadFactory = () => ExternalStoreThreadRuntimeCore;
10
12
 
@@ -150,6 +152,7 @@ export class ExternalStoreThreadListRuntimeCore implements ThreadListRuntimeCore
150
152
 
151
153
  // `initialLoad ||`: `_mainThread!` must be assigned on construction.
152
154
  if (initialLoad || previousThreadId !== newThreadId) {
155
+ if (!initialLoad) invalidateThreadRuntime(this._mainThread);
153
156
  this._mainThreadId = newThreadId;
154
157
  this._mainThread = this.threadFactory();
155
158
  }
@@ -268,6 +271,6 @@ export class ExternalStoreThreadListRuntimeCore implements ThreadListRuntimeCore
268
271
  }
269
272
 
270
273
  private _notifySubscribers() {
271
- for (const callback of this._subscriptions) callback();
274
+ notifySubscribers(this._subscriptions);
272
275
  }
273
276
  }
@@ -1,4 +1,5 @@
1
1
  import type { AppendMessage, ThreadMessage } from "../../types/message";
2
+ import type { Attachment } from "../../types/attachment";
2
3
  import type {
3
4
  AddToolResultOptions,
4
5
  ResumeRunConfig,
@@ -27,7 +28,10 @@ import type {
27
28
  RuntimeCapabilities,
28
29
  ThreadRuntimeCore,
29
30
  } from "../../runtime/interfaces/thread-runtime-core";
30
- import type { QueuePlacement } from "../../runtime/queue/external-thread-queue-adapter";
31
+ import type {
32
+ ExternalThreadQueueAdapter,
33
+ QueuePlacement,
34
+ } from "../../runtime/queue/external-thread-queue-adapter";
31
35
  import { BaseThreadRuntimeCore } from "../../runtime/base/base-thread-runtime-core";
32
36
  import type { ModelContextProvider } from "../../model-context/types";
33
37
  import {
@@ -37,9 +41,26 @@ import {
37
41
  import { generateId } from "../../utils/id";
38
42
  import { ToolInvocationTracker } from "../tool-invocations/ToolInvocationTracker";
39
43
  import { EMPTY_QUEUE_ITEMS } from "../../store/scopes/queue-item";
44
+ import type { QuoteInfo } from "../../types/quote";
45
+ import {
46
+ captureThreadRuntimeGeneration,
47
+ isThreadRuntimeGenerationCurrent,
48
+ } from "../../runtime/utils/thread-runtime-lifecycle";
40
49
 
41
50
  const EMPTY_ARRAY: readonly ThreadSuggestion[] = Object.freeze([]);
42
51
 
52
+ const observeAdapterCallback = (
53
+ name: "onAddToolResult" | "onRespondToToolApproval" | "onCancel",
54
+ result: Promise<void> | void,
55
+ ) => {
56
+ void Promise.resolve(result).catch((error) => {
57
+ console.error(
58
+ `[ExternalStoreThreadRuntimeCore] ${name} callback rejected`,
59
+ error,
60
+ );
61
+ });
62
+ };
63
+
43
64
  const shallowEqual = (a: object, b: object): boolean => {
44
65
  const aKeys = Object.keys(a);
45
66
  if (aKeys.length !== Object.keys(b).length) return false;
@@ -117,6 +138,16 @@ export class ExternalStoreThreadRuntimeCore
117
138
 
118
139
  private _store!: ExternalStoreAdapter<any>;
119
140
 
141
+ private _getInitializePromise?: () => Promise<unknown> | undefined;
142
+
143
+ public __internal_setGetInitializePromise(
144
+ getPromise: () => Promise<unknown> | undefined,
145
+ ) {
146
+ this._getInitializePromise = getPromise;
147
+ }
148
+
149
+ private _transformedQueue: ExternalThreadQueueAdapter | undefined;
150
+
120
151
  /**
121
152
  * Client-side tool-invocations pipeline. Constructed lazily on first
122
153
  * snapshot — only when `adapter.unstable_enableToolInvocations === true`.
@@ -147,6 +178,19 @@ export class ExternalStoreThreadRuntimeCore
147
178
 
148
179
  const oldStore = this._store as ExternalStoreAdapter<any> | undefined;
149
180
  this._store = store;
181
+ if (oldStore?.queue !== store.queue) {
182
+ this._transformedQueue = undefined;
183
+ store.queue?.__internal_setDispatchTransform?.((message) => {
184
+ // Re-point at the tail, as LocalThreadRuntimeCore's driver does, so
185
+ // the prefix gated against is the one the message lands on whatever
186
+ // the host routes by. Queuing only ever accepts a tail append, so a
187
+ // later tail is the same intent.
188
+ const parentId = this.messages.at(-1)?.id ?? null;
189
+ return this.enrichAppendMetadata({ ...message, parentId }, parentId);
190
+ });
191
+ if (store.queue?.__internal_setDispatchTransform)
192
+ this._transformedQueue = store.queue;
193
+ }
150
194
  if (this.extras !== store.extras) {
151
195
  this.extras = store.extras;
152
196
  }
@@ -355,19 +399,22 @@ export class ExternalStoreThreadRuntimeCore
355
399
  // rolled back). Drop the result.
356
400
  return;
357
401
  }
358
- this._store.onAddToolResult?.({
359
- messageId,
360
- toolCallId: command.toolCallId,
361
- toolName: command.toolName,
362
- result: command.result,
363
- isError: command.isError,
364
- ...(command.artifact !== undefined && {
365
- artifact: command.artifact,
366
- }),
367
- ...(command.modelContent !== undefined && {
368
- modelContent: command.modelContent,
402
+ observeAdapterCallback(
403
+ "onAddToolResult",
404
+ this._store.onAddToolResult?.({
405
+ messageId,
406
+ toolCallId: command.toolCallId,
407
+ toolName: command.toolName,
408
+ result: command.result,
409
+ isError: command.isError,
410
+ ...(command.artifact !== undefined && {
411
+ artifact: command.artifact,
412
+ }),
413
+ ...(command.modelContent !== undefined && {
414
+ modelContent: command.modelContent,
415
+ }),
369
416
  }),
370
- });
417
+ );
371
418
  } catch (err) {
372
419
  console.error(
373
420
  "[ExternalStoreThreadRuntimeCore] onAddToolResult dispatch failed",
@@ -465,22 +512,54 @@ export class ExternalStoreThreadRuntimeCore
465
512
  });
466
513
  }
467
514
 
468
- public async append(message: AppendMessage): Promise<void> {
515
+ public async append(rawMessage: AppendMessage): Promise<void> {
469
516
  // sourceId marks an edit send; the parent may coincide with the head
470
517
  // after a resync (e.g. cancelRun dropped the edited message).
471
518
  const isEdit =
472
- message.sourceId != null ||
473
- message.parentId !== (this.messages.at(-1)?.id ?? null);
474
-
475
- // Buffering does not start a run, so the tool-abort below must wait until
476
- // the queue flushes. By then the prior run (and its tools) has settled.
519
+ rawMessage.sourceId != null ||
520
+ rawMessage.parentId !== (this.messages.at(-1)?.id ?? null);
521
+
522
+ // A transformed-queue send is stamped at flush; any other queue's
523
+ // transform would gate against its own thread's messages, so those stamp
524
+ // at send.
525
+ const message =
526
+ !isEdit &&
527
+ this._store.queue &&
528
+ this._store.queue === this._transformedQueue
529
+ ? rawMessage
530
+ : this.enrichAppendMetadata(rawMessage);
531
+
532
+ const generation = captureThreadRuntimeGeneration(this);
533
+ this.ensureInitialized();
534
+
535
+ // The getter call is what starts thread initialization.
536
+ const initPromise = this._getInitializePromise?.();
537
+
538
+ // The queue driver dispatches through the host adapter, outside this
539
+ // core, so the initialization barrier must run before a message can
540
+ // enter the queue.
477
541
  if (!isEdit && this._store.queue) {
542
+ if (initPromise) {
543
+ await initPromise;
544
+ }
545
+ if (!isThreadRuntimeGenerationCurrent(this, generation)) return;
546
+
547
+ // Buffering does not start a run, so the tool-abort below must wait
548
+ // until the queue flushes. By then the prior run (and its tools) has
549
+ // settled.
478
550
  if (message.steer ?? this._store.isRunning ?? false)
479
551
  this._store.queue.steer(message);
480
552
  else this._store.queue.enqueue(message);
481
553
  return;
482
554
  }
483
555
 
556
+ // The optimistic insert lives inside the adapter's dispatch, so holding
557
+ // `onNew` on initialization would keep the message off screen for the
558
+ // whole roundtrip. Seams that need the remote identity await
559
+ // `threadListItem.initialize()` themselves, and a rejection surfaces
560
+ // there.
561
+ void initPromise?.catch(() => {});
562
+
484
563
  // Auto-abort in-flight client-side tool executions when a new run is
485
564
  // about to start. Without this, a tool that finishes after the new turn
486
565
  // begins would feed a stale result into `onAddToolResult`, racing with
@@ -490,6 +569,7 @@ export class ExternalStoreThreadRuntimeCore
490
569
  if (message.startRun ?? message.role === "user") {
491
570
  await this._toolInvocations?.abort();
492
571
  }
572
+ if (!isThreadRuntimeGenerationCurrent(this, generation)) return;
493
573
 
494
574
  if (isEdit) {
495
575
  if (!this._store.onEdit)
@@ -572,17 +652,24 @@ export class ExternalStoreThreadRuntimeCore
572
652
  // imported state) is treated as historical — no streamCall/execute
573
653
  // fires for the loaded tool calls. The adapter is expected to update
574
654
  // its messages in response to onLoadExternalState; that update flows
575
- // back here via __internal_setAdapter. We only clear adapter-side
576
- // tool statuses when the tracker is the source of truth — otherwise
577
- // we'd wipe statuses the adapter is managing on its own.
578
- if (this._toolInvocations) {
579
- this._toolInvocations.reset();
580
- this._store.setToolStatuses?.({});
581
- }
655
+ // back here via __internal_setAdapter. The tracker publishes the
656
+ // cleared status map itself, so adapter-side statuses reset only when
657
+ // the tracker is the source of truth.
658
+ this._toolInvocations?.reset();
582
659
 
583
660
  this._store.onLoadExternalState(state);
584
661
  }
585
662
 
663
+ /**
664
+ * Adapter-facing notification that the backing session was discarded.
665
+ * Clears session-scoped tool-invocation state and parks queued work,
666
+ * without run-cancel semantics (`onCancel`, composer draft restoration).
667
+ */
668
+ public unstable_notifySessionReset(): void {
669
+ this._toolInvocations?.reset();
670
+ this._store.queue?.__internal_notifyCancelled?.();
671
+ }
672
+
586
673
  public cancelRun(): void {
587
674
  if (!this._store.onCancel)
588
675
  throw new Error("Runtime does not support cancelling runs.");
@@ -592,41 +679,90 @@ export class ExternalStoreThreadRuntimeCore
592
679
  // cancel on it.
593
680
  void this._toolInvocations?.abort();
594
681
 
595
- this._store.onCancel();
682
+ // Before the run is aborted, so the settle it produces keeps the pending
683
+ // items instead of dispatching the next one at the moment the user
684
+ // stopped.
685
+ this._store.queue?.__internal_notifyCancelled?.();
596
686
 
597
- // Drop an empty optimistic head (placeholder or pre-stream message); a
598
- // partially-streamed one is kept and re-supplied by the store on resync.
599
- const head = this.repository.getMessages().at(-1);
600
- if (head && head.metadata.isOptimistic && head.content.length === 0) {
601
- this.repository.deleteMessage(head.id);
602
- }
687
+ observeAdapterCallback("onCancel", this._store.onCancel());
688
+
689
+ this.dropEmptyOptimisticHead();
603
690
 
604
- let messages = this.repository.getMessages();
691
+ const messages = this.repository.getMessages();
605
692
  const previousMessage = messages[messages.length - 1];
606
- if (
693
+ const trailingUserLeaf =
694
+ this._store.setMessages !== undefined &&
607
695
  previousMessage?.role === "user" &&
608
- previousMessage.id === messages.at(-1)?.id // ensure the previous message is a leaf node
609
- ) {
610
- this.repository.deleteMessage(previousMessage.id);
611
- if (!this.composer.text.trim()) {
612
- this.composer.setText(getThreadMessageText(previousMessage));
696
+ previousMessage.id === messages.at(-1)?.id && // ensure the previous message is a leaf node
697
+ previousMessage.content.every((part) => part.type === "text")
698
+ ? previousMessage
699
+ : undefined;
700
+
701
+ // Handing the message to the composer and taking it out of the thread are
702
+ // one move: the composer refuses while the user is writing, and removing
703
+ // the message then would leave it nowhere. A message the composer cannot
704
+ // hold whole, carrying content parts it has no home for, is not moved.
705
+ let movedLeaf:
706
+ | {
707
+ id: string;
708
+ draft: {
709
+ text: string;
710
+ attachments: readonly Attachment[];
711
+ quote: QuoteInfo | undefined;
712
+ };
713
+ }
714
+ | undefined;
715
+ if (trailingUserLeaf) {
716
+ const draft = {
717
+ text: getThreadMessageText(trailingUserLeaf),
718
+ attachments: trailingUserLeaf.attachments,
719
+ quote: trailingUserLeaf.metadata.custom.quote as QuoteInfo | undefined,
720
+ };
721
+ if (this.composer.restoreDraft(draft)) {
722
+ this.repository.deleteMessage(trailingUserLeaf.id);
723
+ movedLeaf = { id: trailingUserLeaf.id, draft };
613
724
  }
614
-
615
- messages = this.repository.getMessages();
616
- } else {
617
- this._notifySubscribers();
618
725
  }
726
+ if (!movedLeaf) this._notifySubscribers();
619
727
 
620
- // resync messages (for reloading, to restore the previous branch)
728
+ // The resync commits what the cancel left (a kept optimistic message, the
729
+ // restored branch) back to the store a macrotask later. The store may move
730
+ // in that gap; a server settling the cancelled turn lands in the same
731
+ // tick. Read the repository at flush time and re-apply the rollbacks to
732
+ // it, instead of stamping a snapshot captured above over the newer state.
621
733
  setTimeout(() => {
622
- this.updateMessages(messages);
734
+ this.dropEmptyOptimisticHead();
735
+ if (movedLeaf) {
736
+ const current = this.repository.getMessages();
737
+ if (current.at(-1)?.id === movedLeaf.id) {
738
+ // Unanswered tail: the removal has not reached the store yet.
739
+ this.repository.deleteMessage(movedLeaf.id);
740
+ } else if (current.some((m) => m.id === movedLeaf.id)) {
741
+ // The store kept the turn in the thread; take the untouched draft
742
+ // back so the same content does not sit in both places.
743
+ this.composer.retractDraft(movedLeaf.draft);
744
+ }
745
+ }
746
+ this.updateMessages(this.repository.getMessages());
623
747
  }, 0);
624
748
  }
625
749
 
750
+ // Placeholder or pre-stream message; a partially-streamed one is kept and
751
+ // committed to the store by the cancel resync.
752
+ private dropEmptyOptimisticHead(): void {
753
+ const head = this.repository.getMessages().at(-1);
754
+ if (head && head.metadata.isOptimistic && head.content.length === 0) {
755
+ this.repository.deleteMessage(head.id);
756
+ }
757
+ }
758
+
626
759
  public addToolResult(options: AddToolResultOptions) {
627
760
  if (!this._store.onAddToolResult)
628
761
  throw new Error("Runtime does not support tool results.");
629
- this._store.onAddToolResult?.(options);
762
+ observeAdapterCallback(
763
+ "onAddToolResult",
764
+ this._store.onAddToolResult(options),
765
+ );
630
766
  }
631
767
 
632
768
  public resumeToolCall(options: ResumeToolCallOptions) {
@@ -652,7 +788,10 @@ export class ExternalStoreThreadRuntimeCore
652
788
  public respondToToolApproval(options: RespondToToolApprovalOptions) {
653
789
  if (!this._store.onRespondToToolApproval)
654
790
  throw new Error("Runtime does not support tool approvals.");
655
- this._store.onRespondToToolApproval(options);
791
+ observeAdapterCallback(
792
+ "onRespondToToolApproval",
793
+ this._store.onRespondToToolApproval(options),
794
+ );
656
795
  }
657
796
 
658
797
  public override reset(initialMessages?: readonly ThreadMessageLike[]) {