@assistant-ui/core 0.3.13 → 0.3.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/dist/adapters/speech.d.ts.map +1 -1
  2. package/dist/adapters/speech.js +9 -15
  3. package/dist/adapters/speech.js.map +1 -1
  4. package/dist/adapters/thread-history.d.ts +2 -0
  5. package/dist/adapters/thread-history.d.ts.map +1 -1
  6. package/dist/adapters/voice.d.ts.map +1 -1
  7. package/dist/adapters/voice.js +38 -15
  8. package/dist/adapters/voice.js.map +1 -1
  9. package/dist/index.d.ts +2 -2
  10. package/dist/index.js +1 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/internal.d.ts +3 -2
  13. package/dist/internal.js +8 -7
  14. package/dist/model-context/frame/host.d.ts +1 -1
  15. package/dist/model-context/frame/host.d.ts.map +1 -1
  16. package/dist/model-context/frame/host.js +19 -4
  17. package/dist/model-context/frame/host.js.map +1 -1
  18. package/dist/model-context/frame/provider.d.ts +4 -0
  19. package/dist/model-context/frame/provider.d.ts.map +1 -1
  20. package/dist/model-context/frame/provider.js +50 -3
  21. package/dist/model-context/frame/provider.js.map +1 -1
  22. package/dist/model-context/frame/types.d.ts +4 -1
  23. package/dist/model-context/frame/types.d.ts.map +1 -1
  24. package/dist/model-context/frame/types.js.map +1 -1
  25. package/dist/model-context/registry.d.ts.map +1 -1
  26. package/dist/model-context/registry.js +16 -4
  27. package/dist/model-context/registry.js.map +1 -1
  28. package/dist/react/RuntimeAdapter.d.ts +8 -1
  29. package/dist/react/RuntimeAdapter.d.ts.map +1 -1
  30. package/dist/react/RuntimeAdapter.js +23 -18
  31. package/dist/react/RuntimeAdapter.js.map +1 -1
  32. package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
  33. package/dist/react/adapters/LocalStorageThreadListAdapter.js +28 -12
  34. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  35. package/dist/react/client/AdaptedRemoteThread.d.ts +11 -0
  36. package/dist/react/client/AdaptedRemoteThread.d.ts.map +1 -0
  37. package/dist/react/client/AdaptedRemoteThread.js +27 -0
  38. package/dist/react/client/AdaptedRemoteThread.js.map +1 -0
  39. package/dist/react/client/InMemoryThreadList.d.ts +19 -0
  40. package/dist/react/client/InMemoryThreadList.d.ts.map +1 -0
  41. package/dist/react/client/InMemoryThreadList.js +418 -0
  42. package/dist/react/client/InMemoryThreadList.js.map +1 -0
  43. package/dist/react/client/Interactables.d.ts.map +1 -1
  44. package/dist/react/client/Interactables.js +159 -102
  45. package/dist/react/client/Interactables.js.map +1 -1
  46. package/dist/react/client/RemoteThreadList.d.ts +34 -0
  47. package/dist/react/client/RemoteThreadList.d.ts.map +1 -0
  48. package/dist/react/client/RemoteThreadList.js +898 -0
  49. package/dist/react/client/RemoteThreadList.js.map +1 -0
  50. package/dist/react/client/Tools.d.ts.map +1 -1
  51. package/dist/react/client/Tools.js +38 -27
  52. package/dist/react/client/Tools.js.map +1 -1
  53. package/dist/react/index.d.ts +7 -2
  54. package/dist/react/index.js +5 -2
  55. package/dist/react/interactables-legacy/Interactables.d.ts.map +1 -1
  56. package/dist/react/interactables-legacy/Interactables.js +145 -110
  57. package/dist/react/interactables-legacy/Interactables.js.map +1 -1
  58. package/dist/react/primitive-hooks/useActionBarCopy.d.ts.map +1 -1
  59. package/dist/react/primitive-hooks/useActionBarCopy.js +20 -19
  60. package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
  61. package/dist/react/primitive-hooks/useActionBarEdit.d.ts.map +1 -1
  62. package/dist/react/primitive-hooks/useActionBarEdit.js +2 -4
  63. package/dist/react/primitive-hooks/useActionBarEdit.js.map +1 -1
  64. package/dist/react/primitive-hooks/useActionBarReload.d.ts.map +1 -1
  65. package/dist/react/primitive-hooks/useActionBarReload.js +2 -4
  66. package/dist/react/primitive-hooks/useActionBarReload.js.map +1 -1
  67. package/dist/react/primitive-hooks/useBranchPickerNext.d.ts.map +1 -1
  68. package/dist/react/primitive-hooks/useBranchPickerNext.js +2 -6
  69. package/dist/react/primitive-hooks/useBranchPickerNext.js.map +1 -1
  70. package/dist/react/primitive-hooks/useBranchPickerPrevious.d.ts.map +1 -1
  71. package/dist/react/primitive-hooks/useBranchPickerPrevious.js +2 -6
  72. package/dist/react/primitive-hooks/useBranchPickerPrevious.js.map +1 -1
  73. package/dist/react/primitive-hooks/useComposerCancel.d.ts.map +1 -1
  74. package/dist/react/primitive-hooks/useComposerCancel.js +2 -4
  75. package/dist/react/primitive-hooks/useComposerCancel.js.map +1 -1
  76. package/dist/react/primitive-hooks/useComposerSend.d.ts.map +1 -1
  77. package/dist/react/primitive-hooks/useComposerSend.js +2 -4
  78. package/dist/react/primitive-hooks/useComposerSend.js.map +1 -1
  79. package/dist/react/primitive-hooks/useSuggestionTrigger.d.ts.map +1 -1
  80. package/dist/react/primitive-hooks/useSuggestionTrigger.js +6 -2
  81. package/dist/react/primitive-hooks/useSuggestionTrigger.js.map +1 -1
  82. package/dist/react/primitive-hooks/useThreadIsEmpty.d.ts +3 -0
  83. package/dist/react/primitive-hooks/useThreadIsEmpty.d.ts.map +1 -1
  84. package/dist/react/primitive-hooks/useThreadIsEmpty.js +3 -0
  85. package/dist/react/primitive-hooks/useThreadIsEmpty.js.map +1 -1
  86. package/dist/react/primitive-hooks/useThreadIsRunning.d.ts +3 -0
  87. package/dist/react/primitive-hooks/useThreadIsRunning.d.ts.map +1 -1
  88. package/dist/react/primitive-hooks/useThreadIsRunning.js +3 -0
  89. package/dist/react/primitive-hooks/useThreadIsRunning.js.map +1 -1
  90. package/dist/react/primitives/message/MessageParts.d.ts +13 -0
  91. package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
  92. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  93. package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
  94. package/dist/react/primitives/thread/ThreadMessages.js +1 -1
  95. package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
  96. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +24 -10
  97. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  98. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +115 -71
  99. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  100. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +14 -2
  101. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  102. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +232 -63
  103. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  104. package/dist/react/runtimes/RemoteThreadResource.d.ts +30 -0
  105. package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -0
  106. package/dist/react/runtimes/RemoteThreadResource.js +136 -0
  107. package/dist/react/runtimes/RemoteThreadResource.js.map +1 -0
  108. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts +3 -10
  109. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts.map +1 -1
  110. package/dist/react/runtimes/RuntimeAdapterProvider.js +3 -6
  111. package/dist/react/runtimes/RuntimeAdapterProvider.js.map +1 -1
  112. package/dist/react/runtimes/assistant-transport/commandQueue.d.ts +17 -0
  113. package/dist/react/runtimes/assistant-transport/commandQueue.d.ts.map +1 -0
  114. package/dist/react/runtimes/assistant-transport/commandQueue.js +55 -0
  115. package/dist/react/runtimes/assistant-transport/commandQueue.js.map +1 -0
  116. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.d.ts +11 -0
  117. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.d.ts.map +1 -0
  118. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.js +165 -0
  119. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.js.map +1 -0
  120. package/dist/react/runtimes/assistant-transport/runManager.d.ts +15 -0
  121. package/dist/react/runtimes/assistant-transport/runManager.d.ts.map +1 -0
  122. package/dist/react/runtimes/assistant-transport/runManager.js +86 -0
  123. package/dist/react/runtimes/assistant-transport/runManager.js.map +1 -0
  124. package/dist/react/runtimes/assistant-transport/types.d.ts +130 -0
  125. package/dist/react/runtimes/assistant-transport/types.d.ts.map +1 -0
  126. package/dist/react/runtimes/assistant-transport/types.js +0 -0
  127. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts +14 -0
  128. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -0
  129. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js +296 -0
  130. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js.map +1 -0
  131. package/dist/react/runtimes/assistant-transport/useConvertedState.d.ts +7 -0
  132. package/dist/react/runtimes/assistant-transport/useConvertedState.d.ts.map +1 -0
  133. package/dist/react/runtimes/assistant-transport/useConvertedState.js +25 -0
  134. package/dist/react/runtimes/assistant-transport/useConvertedState.js.map +1 -0
  135. package/dist/react/runtimes/assistant-transport/useLatestRef.d.ts +7 -0
  136. package/dist/react/runtimes/assistant-transport/useLatestRef.d.ts.map +1 -0
  137. package/dist/react/runtimes/assistant-transport/useLatestRef.js +27 -0
  138. package/dist/react/runtimes/assistant-transport/useLatestRef.js.map +1 -0
  139. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  140. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +39 -13
  141. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  142. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +2 -1
  143. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
  144. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +3 -3
  145. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
  146. package/dist/react/runtimes/cloud/auiV0.d.ts +4 -0
  147. package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
  148. package/dist/react/runtimes/cloud/auiV0.js +7 -0
  149. package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
  150. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  151. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +60 -17
  152. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  153. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.d.ts +16 -0
  154. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.d.ts.map +1 -0
  155. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js +36 -0
  156. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js.map +1 -0
  157. package/dist/react/runtimes/external-message-converter.js +14 -14
  158. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  159. package/dist/react/runtimes/useExternalStoreRuntime.d.ts.map +1 -1
  160. package/dist/react/runtimes/useExternalStoreRuntime.js +44 -28
  161. package/dist/react/runtimes/useExternalStoreRuntime.js.map +1 -1
  162. package/dist/react/runtimes/useExternalStoreSharedOptions.js.map +1 -1
  163. package/dist/react/runtimes/useLocalRuntime.js +1 -1
  164. package/dist/react/runtimes/useRuntimeAdapters.d.ts +9 -0
  165. package/dist/react/runtimes/useRuntimeAdapters.d.ts.map +1 -0
  166. package/dist/react/runtimes/useRuntimeAdapters.js +20 -0
  167. package/dist/react/runtimes/useRuntimeAdapters.js.map +1 -0
  168. package/dist/runtime/api/composer-runtime.d.ts +5 -0
  169. package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
  170. package/dist/runtime/api/composer-runtime.js.map +1 -1
  171. package/dist/runtime/api/message-runtime.js +1 -1
  172. package/dist/runtime/api/thread-list-runtime.d.ts +1 -0
  173. package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
  174. package/dist/runtime/api/thread-list-runtime.js +4 -2
  175. package/dist/runtime/api/thread-list-runtime.js.map +1 -1
  176. package/dist/runtime/api/thread-runtime.d.ts +12 -2
  177. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  178. package/dist/runtime/api/thread-runtime.js +8 -2
  179. package/dist/runtime/api/thread-runtime.js.map +1 -1
  180. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  181. package/dist/runtime/base/base-composer-runtime-core.js +8 -7
  182. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  183. package/dist/runtime/base/base-thread-runtime-core.d.ts +1 -0
  184. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  185. package/dist/runtime/base/base-thread-runtime-core.js +3 -3
  186. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  187. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +0 -1
  188. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
  189. package/dist/runtime/base/default-thread-composer-runtime-core.js +10 -4
  190. package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
  191. package/dist/runtime/interfaces/thread-runtime-core.d.ts +6 -0
  192. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  193. package/dist/runtime/internal.js +5 -5
  194. package/dist/runtime/queue/message-queue.d.ts.map +1 -1
  195. package/dist/runtime/queue/message-queue.js +2 -1
  196. package/dist/runtime/queue/message-queue.js.map +1 -1
  197. package/dist/runtime/utils/message-repository.d.ts.map +1 -1
  198. package/dist/runtime/utils/message-repository.js +27 -18
  199. package/dist/runtime/utils/message-repository.js.map +1 -1
  200. package/dist/runtime/utils/thread-runtime-lifecycle.d.ts +8 -0
  201. package/dist/runtime/utils/thread-runtime-lifecycle.d.ts.map +1 -0
  202. package/dist/runtime/utils/thread-runtime-lifecycle.js +11 -0
  203. package/dist/runtime/utils/thread-runtime-lifecycle.js.map +1 -0
  204. package/dist/runtimes/external-store/external-store-shared-options.js.map +1 -1
  205. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  206. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +4 -1
  207. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  208. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +8 -0
  209. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  210. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +37 -13
  211. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  212. package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts +102 -0
  213. package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts.map +1 -0
  214. package/dist/runtimes/inert/InertThreadRuntimeCore.js +156 -0
  215. package/dist/runtimes/inert/InertThreadRuntimeCore.js.map +1 -0
  216. package/dist/runtimes/internal.d.ts +1 -1
  217. package/dist/runtimes/local/local-thread-runtime-core.d.ts +3 -0
  218. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  219. package/dist/runtimes/local/local-thread-runtime-core.js +78 -19
  220. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  221. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +12 -59
  222. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
  223. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +10 -142
  224. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
  225. package/dist/runtimes/remote-thread-list/adapter-changed.d.ts +9 -0
  226. package/dist/runtimes/remote-thread-list/adapter-changed.d.ts.map +1 -0
  227. package/dist/runtimes/remote-thread-list/adapter-changed.js +13 -0
  228. package/dist/runtimes/remote-thread-list/adapter-changed.js.map +1 -0
  229. package/dist/runtimes/remote-thread-list/empty-thread-core.d.ts.map +1 -1
  230. package/dist/runtimes/remote-thread-list/empty-thread-core.js +16 -152
  231. package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
  232. package/dist/runtimes/remote-thread-list/optimistic-state.d.ts +2 -0
  233. package/dist/runtimes/remote-thread-list/optimistic-state.d.ts.map +1 -1
  234. package/dist/runtimes/remote-thread-list/optimistic-state.js +11 -0
  235. package/dist/runtimes/remote-thread-list/optimistic-state.js.map +1 -1
  236. package/dist/runtimes/remote-thread-list/types.d.ts +32 -1
  237. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  238. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +1 -12
  239. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
  240. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +67 -38
  241. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
  242. package/dist/store/clients/external-thread.js +1 -1
  243. package/dist/store/clients/external-thread.js.map +1 -1
  244. package/dist/store/clients/suggestions.js +2 -2
  245. package/dist/store/clients/suggestions.js.map +1 -1
  246. package/dist/store/clients/thread-selection-events.d.ts +10 -0
  247. package/dist/store/clients/thread-selection-events.d.ts.map +1 -0
  248. package/dist/store/clients/thread-selection-events.js +40 -0
  249. package/dist/store/clients/thread-selection-events.js.map +1 -0
  250. package/dist/store/env.d.ts +5 -0
  251. package/dist/store/env.d.ts.map +1 -0
  252. package/dist/store/env.js +12 -0
  253. package/dist/store/env.js.map +1 -0
  254. package/dist/store/index.d.ts +5 -3
  255. package/dist/store/index.js +4 -2
  256. package/dist/store/internal.d.ts +4 -1
  257. package/dist/store/internal.js +4 -1
  258. package/dist/store/primitive-predicates.d.ts +19 -0
  259. package/dist/store/primitive-predicates.d.ts.map +1 -0
  260. package/dist/store/primitive-predicates.js +19 -0
  261. package/dist/store/primitive-predicates.js.map +1 -0
  262. package/dist/store/runtime-clients/attachment-runtime-client.d.ts.map +1 -1
  263. package/dist/store/runtime-clients/attachment-runtime-client.js +18 -11
  264. package/dist/store/runtime-clients/attachment-runtime-client.js.map +1 -1
  265. package/dist/store/runtime-clients/handle-runtime-action.d.ts +5 -0
  266. package/dist/store/runtime-clients/handle-runtime-action.d.ts.map +1 -0
  267. package/dist/store/runtime-clients/handle-runtime-action.js +14 -0
  268. package/dist/store/runtime-clients/handle-runtime-action.js.map +1 -0
  269. package/dist/store/runtime-clients/handle-thread-list-action.d.ts +5 -0
  270. package/dist/store/runtime-clients/handle-thread-list-action.d.ts.map +1 -0
  271. package/dist/store/runtime-clients/handle-thread-list-action.js +7 -0
  272. package/dist/store/runtime-clients/handle-thread-list-action.js.map +1 -0
  273. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  274. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +62 -29
  275. package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
  276. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
  277. package/dist/store/runtime-clients/thread-list-runtime-client.js +5 -6
  278. package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
  279. package/dist/store/scopes/composer.d.ts +9 -4
  280. package/dist/store/scopes/composer.d.ts.map +1 -1
  281. package/dist/store/scopes/thread-list-item.d.ts +7 -6
  282. package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
  283. package/dist/store/scopes/thread.d.ts +8 -7
  284. package/dist/store/scopes/thread.d.ts.map +1 -1
  285. package/dist/store/scopes/threads.d.ts +17 -1
  286. package/dist/store/scopes/threads.d.ts.map +1 -1
  287. package/dist/subscribable/subscribable.d.ts +2 -1
  288. package/dist/subscribable/subscribable.d.ts.map +1 -1
  289. package/dist/subscribable/subscribable.js +23 -18
  290. package/dist/subscribable/subscribable.js.map +1 -1
  291. package/dist/types/message.d.ts +1 -1
  292. package/dist/types/message.js.map +1 -1
  293. package/dist/utils/composite-context-provider.d.ts +1 -0
  294. package/dist/utils/composite-context-provider.d.ts.map +1 -1
  295. package/dist/utils/composite-context-provider.js +25 -9
  296. package/dist/utils/composite-context-provider.js.map +1 -1
  297. package/dist/utils/notify-event-listeners.d.ts +2 -2
  298. package/dist/utils/notify-event-listeners.d.ts.map +1 -1
  299. package/dist/utils/notify-event-listeners.js +2 -2
  300. package/dist/utils/notify-event-listeners.js.map +1 -1
  301. package/dist/utils/silent-runtime-action.d.ts +6 -0
  302. package/dist/utils/silent-runtime-action.d.ts.map +1 -0
  303. package/dist/utils/silent-runtime-action.js +7 -0
  304. package/dist/utils/silent-runtime-action.js.map +1 -0
  305. package/package.json +8 -8
  306. package/src/adapters/speech.test.ts +118 -1
  307. package/src/adapters/speech.ts +21 -22
  308. package/src/adapters/thread-history.ts +2 -0
  309. package/src/adapters/voice.test.ts +134 -0
  310. package/src/adapters/voice.ts +35 -27
  311. package/src/index.ts +1 -0
  312. package/src/internal.ts +1 -0
  313. package/src/model-context/frame/host.test.ts +87 -5
  314. package/src/model-context/frame/host.ts +18 -4
  315. package/src/model-context/frame/provider.test.ts +347 -20
  316. package/src/model-context/frame/provider.ts +58 -2
  317. package/src/model-context/frame/types.ts +5 -0
  318. package/src/model-context/registry.test.ts +131 -0
  319. package/src/model-context/registry.ts +16 -6
  320. package/src/react/RuntimeAdapter.test.ts +2 -0
  321. package/src/react/RuntimeAdapter.ts +20 -8
  322. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +34 -17
  323. package/src/react/client/AdaptedRemoteThread.ts +41 -0
  324. package/src/react/client/InMemoryThreadList.test.tsx +148 -0
  325. package/src/react/client/InMemoryThreadList.ts +290 -0
  326. package/src/react/client/Interactables.test.ts +326 -2
  327. package/src/react/client/Interactables.ts +227 -110
  328. package/src/react/client/RemoteThreadList.test.ts +1222 -0
  329. package/src/react/client/RemoteThreadList.ts +1136 -0
  330. package/src/react/client/Tools.ts +36 -29
  331. package/src/react/index.ts +13 -0
  332. package/src/react/interactables-legacy/Interactables.test.ts +317 -0
  333. package/src/react/interactables-legacy/Interactables.ts +204 -128
  334. package/src/react/primitive-hooks/useActionBarCopy.test.ts +15 -0
  335. package/src/react/primitive-hooks/useActionBarCopy.ts +15 -10
  336. package/src/react/primitive-hooks/useActionBarEdit.ts +2 -1
  337. package/src/react/primitive-hooks/useActionBarReload.ts +2 -6
  338. package/src/react/primitive-hooks/useBranchPickerNext.ts +2 -7
  339. package/src/react/primitive-hooks/useBranchPickerPrevious.ts +2 -7
  340. package/src/react/primitive-hooks/useComposerCancel.ts +2 -1
  341. package/src/react/primitive-hooks/useComposerSend.ts +2 -5
  342. package/src/react/primitive-hooks/useSuggestionTrigger.test.ts +11 -0
  343. package/src/react/primitive-hooks/useSuggestionTrigger.ts +4 -5
  344. package/src/react/primitive-hooks/useThreadIsEmpty.ts +3 -0
  345. package/src/react/primitive-hooks/useThreadIsRunning.ts +3 -0
  346. package/src/react/primitives/message/MessageParts.tsx +0 -1
  347. package/src/react/primitives/thread/ThreadMessages.tsx +2 -1
  348. package/src/react/runtimes/RemoteThreadListHookInstanceManager.retry.test.tsx +116 -0
  349. package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +1 -1
  350. package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +57 -6
  351. package/src/react/runtimes/RemoteThreadListHookInstanceManager.title.test.tsx +272 -0
  352. package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +171 -124
  353. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.republish.test.ts +87 -0
  354. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +327 -83
  355. package/src/react/runtimes/RemoteThreadResource.test.ts +141 -0
  356. package/src/react/runtimes/RemoteThreadResource.ts +233 -0
  357. package/src/react/runtimes/RuntimeAdapterProvider.tsx +8 -20
  358. package/src/react/runtimes/assistant-transport/commandQueue.ts +68 -0
  359. package/src/react/runtimes/assistant-transport/replayBoundaryStream.test.ts +455 -0
  360. package/src/react/runtimes/assistant-transport/replayBoundaryStream.ts +172 -0
  361. package/src/react/runtimes/assistant-transport/runManager.ts +124 -0
  362. package/src/react/runtimes/assistant-transport/transport-delivery.test.tsx +79 -0
  363. package/src/react/runtimes/assistant-transport/transport-parentid.test.tsx +97 -0
  364. package/src/react/runtimes/assistant-transport/transport-scheduling.test.ts +414 -0
  365. package/src/react/runtimes/assistant-transport/types.ts +170 -0
  366. package/src/react/runtimes/assistant-transport/useAssistantTransport.spec.md +141 -0
  367. package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.test.tsx +683 -0
  368. package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.ts +483 -0
  369. package/src/react/runtimes/assistant-transport/useConvertedState.ts +20 -0
  370. package/src/react/runtimes/assistant-transport/useLatestRef.ts +9 -0
  371. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +131 -6
  372. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +61 -15
  373. package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +6 -4
  374. package/src/react/runtimes/cloud/auiV0.ts +17 -1
  375. package/src/react/runtimes/cloud/useCloudThreadListAdapter.test.tsx +98 -3
  376. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +104 -27
  377. package/src/react/runtimes/cloud/useCloudThreadListRuntime.test.tsx +56 -0
  378. package/src/react/runtimes/cloud/useCloudThreadListRuntime.ts +31 -0
  379. package/src/react/runtimes/external-message-converter.test.ts +143 -0
  380. package/src/react/runtimes/external-message-converter.ts +41 -41
  381. package/src/react/runtimes/remote-thread-hook-on-tap.test.ts +58 -0
  382. package/src/react/runtimes/useExternalStoreRuntime.lifecycle.test.tsx +83 -0
  383. package/src/react/runtimes/useExternalStoreRuntime.suggestions.test.tsx +13 -3
  384. package/src/react/runtimes/useExternalStoreRuntime.ts +7 -0
  385. package/src/react/runtimes/useExternalStoreSharedOptions.ts +3 -1
  386. package/src/react/runtimes/useLocalRuntime.test.tsx +134 -8
  387. package/src/react/runtimes/useRuntimeAdapters.test.tsx +62 -0
  388. package/src/react/runtimes/useRuntimeAdapters.ts +28 -0
  389. package/src/runtime/api/composer-runtime.ts +5 -0
  390. package/src/runtime/api/thread-list-runtime.ts +3 -1
  391. package/src/runtime/api/thread-runtime.ts +20 -2
  392. package/src/runtime/base/base-composer-runtime-core.ts +6 -5
  393. package/src/runtime/base/base-thread-runtime-core.test.ts +191 -0
  394. package/src/runtime/base/base-thread-runtime-core.ts +11 -2
  395. package/src/runtime/base/default-thread-composer-runtime-core.ts +12 -4
  396. package/src/runtime/interfaces/thread-runtime-core.ts +6 -0
  397. package/src/runtime/queue/message-queue.ts +2 -1
  398. package/src/runtime/utils/message-repository.ts +26 -18
  399. package/src/runtime/utils/thread-runtime-lifecycle.ts +18 -0
  400. package/src/runtimes/external-store/external-store-shared-options.ts +3 -1
  401. package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +4 -1
  402. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +103 -34
  403. package/src/runtimes/inert/InertThreadRuntimeCore.test.ts +253 -0
  404. package/src/runtimes/inert/InertThreadRuntimeCore.ts +232 -0
  405. package/src/runtimes/local/local-thread-runtime-core.test.ts +692 -4
  406. package/src/runtimes/local/local-thread-runtime-core.ts +117 -22
  407. package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +17 -205
  408. package/src/runtimes/remote-thread-list/adapter-changed.ts +10 -0
  409. package/src/runtimes/remote-thread-list/empty-thread-core.ts +28 -217
  410. package/src/runtimes/remote-thread-list/optimistic-state.test.ts +18 -0
  411. package/src/runtimes/remote-thread-list/optimistic-state.ts +13 -0
  412. package/src/runtimes/remote-thread-list/types.ts +34 -0
  413. package/src/runtimes/tool-invocations/EDGE_CASES.md +17 -6
  414. package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +243 -0
  415. package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +127 -61
  416. package/src/store/clients/external-thread.ts +1 -1
  417. package/src/store/clients/model-context-client.test.ts +16 -8
  418. package/src/store/clients/suggestions.ts +2 -2
  419. package/src/store/clients/thread-selection-events.ts +21 -0
  420. package/src/store/env.ts +11 -0
  421. package/src/store/index.ts +14 -1
  422. package/src/store/internal.ts +13 -0
  423. package/src/store/primitive-predicates.test.ts +184 -0
  424. package/src/store/primitive-predicates.ts +43 -0
  425. package/src/store/runtime-clients/attachment-runtime-client.test.ts +41 -0
  426. package/src/store/runtime-clients/attachment-runtime-client.ts +2 -1
  427. package/src/store/runtime-clients/handle-runtime-action.test.ts +40 -0
  428. package/src/store/runtime-clients/handle-runtime-action.ts +14 -0
  429. package/src/store/runtime-clients/handle-thread-list-action.test.ts +69 -0
  430. package/src/store/runtime-clients/handle-thread-list-action.ts +6 -0
  431. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +15 -7
  432. package/src/store/runtime-clients/thread-list-runtime-client.ts +9 -6
  433. package/src/store/scopes/composer.ts +9 -4
  434. package/src/store/scopes/thread-list-item.ts +7 -6
  435. package/src/store/scopes/thread.ts +8 -7
  436. package/src/store/scopes/threads.ts +14 -0
  437. package/src/subscribable/subscribable.test.ts +77 -1
  438. package/src/subscribable/subscribable.ts +38 -23
  439. package/src/tests/MessageRepository.test.ts +48 -0
  440. package/src/tests/RemoteThreadListThreadListRuntimeCore-errors.test.ts +2 -2
  441. package/src/tests/RemoteThreadListThreadListRuntimeCore-loadMore.test.ts +8 -6
  442. package/src/tests/RemoteThreadListThreadListRuntimeCore-switchToThread-unarchive.test.ts +25 -0
  443. package/src/tests/auiV0Encode.test.ts +66 -0
  444. package/src/tests/base-composer-runtime-core-send.test.ts +30 -0
  445. package/src/tests/base-composer-runtime-core.test.ts +28 -0
  446. package/src/tests/composer-can-cancel.test.ts +101 -0
  447. package/src/tests/empty-thread-core.test.ts +6 -0
  448. package/src/tests/external-store-thread-list-runtime-core.test.ts +101 -0
  449. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +211 -1
  450. package/src/tests/external-store-thread-runtime-core.test.ts +124 -0
  451. package/src/tests/external-thread-isEmpty.test.tsx +100 -0
  452. package/src/tests/interactables-toolui-migration.test.tsx +66 -0
  453. package/src/tests/message-queue.test.ts +28 -0
  454. package/src/tests/remote-thread-list-adapter-switch.test.ts +383 -0
  455. package/src/tests/session-reset-notification.test.ts +145 -0
  456. package/src/tests/thread-switch-events.test.tsx +99 -1
  457. package/src/tests/tools-scope-migration.test.tsx +58 -0
  458. package/src/tests/useRemoteThreadListRuntime-controlled.test.tsx +67 -0
  459. package/src/types/message.ts +1 -1
  460. package/src/utils/composite-context-provider.test.ts +139 -0
  461. package/src/utils/composite-context-provider.ts +26 -8
  462. package/src/utils/notify-event-listeners.ts +10 -5
  463. package/src/utils/silent-runtime-action.ts +6 -0
@@ -1,234 +1,45 @@
1
+ import type { Unsubscribe } from "../../types/unsubscribe";
1
2
  import type { ThreadRuntimeCore } from "../../runtime/interfaces/thread-runtime-core";
3
+ import {
4
+ InertThreadRuntimeCore,
5
+ createInertComposer,
6
+ } from "../inert/InertThreadRuntimeCore";
2
7
 
3
8
  const EMPTY_THREAD_ERROR = new Error(
4
9
  "This is the empty thread, a placeholder for the main thread. You cannot perform any actions on this thread instance. This error is probably because you tried to call a thread method in your render function. Call the method inside a `useEffect` hook instead.",
5
10
  );
6
- export const EMPTY_THREAD_CORE: ThreadRuntimeCore = {
7
- getMessageById() {
8
- return undefined;
9
- },
10
-
11
- getBranches() {
12
- return [];
13
- },
14
-
15
- switchToBranch() {
16
- throw EMPTY_THREAD_ERROR;
17
- },
18
-
19
- append() {
20
- throw EMPTY_THREAD_ERROR;
21
- },
22
-
23
- deleteMessage() {
24
- throw EMPTY_THREAD_ERROR;
25
- },
26
-
27
- startRun() {
28
- throw EMPTY_THREAD_ERROR;
29
- },
30
-
31
- resumeRun() {
32
- throw EMPTY_THREAD_ERROR;
33
- },
34
-
35
- cancelRun() {
36
- throw EMPTY_THREAD_ERROR;
37
- },
38
-
39
- addToolResult() {
40
- throw EMPTY_THREAD_ERROR;
41
- },
42
-
43
- resumeToolCall() {
44
- throw EMPTY_THREAD_ERROR;
45
- },
46
-
47
- respondToToolApproval() {
48
- throw EMPTY_THREAD_ERROR;
49
- },
50
-
51
- speak() {
52
- throw EMPTY_THREAD_ERROR;
53
- },
54
-
55
- stopSpeaking() {
56
- throw EMPTY_THREAD_ERROR;
57
- },
58
-
59
- connectVoice() {
60
- throw EMPTY_THREAD_ERROR;
61
- },
62
-
63
- disconnectVoice() {
64
- throw EMPTY_THREAD_ERROR;
65
- },
66
-
67
- getVoiceVolume: () => 0,
68
- subscribeVoiceVolume: () => () => {},
69
-
70
- muteVoice() {
71
- throw EMPTY_THREAD_ERROR;
72
- },
73
-
74
- unmuteVoice() {
75
- throw EMPTY_THREAD_ERROR;
76
- },
77
-
78
- submitFeedback() {
79
- throw EMPTY_THREAD_ERROR;
80
- },
81
-
82
- getModelContext() {
83
- return {};
84
- },
85
-
86
- exportExternalState() {
87
- throw EMPTY_THREAD_ERROR;
88
- },
89
-
90
- importExternalState() {
91
- throw EMPTY_THREAD_ERROR;
92
- },
93
-
94
- composer: {
95
- attachments: [],
96
- attachmentAccept: "*",
97
-
98
- async addAttachment() {
99
- throw EMPTY_THREAD_ERROR;
100
- },
101
-
102
- async removeAttachment() {
103
- throw EMPTY_THREAD_ERROR;
104
- },
105
-
106
- isEditing: true,
107
-
108
- canCancel: false,
109
- canSend: false,
110
- isEmpty: true,
111
11
 
112
- text: "",
12
+ class EmptyThreadRuntimeCore extends InertThreadRuntimeCore {
13
+ protected get error() {
14
+ return EMPTY_THREAD_ERROR;
15
+ }
113
16
 
114
- setText() {
115
- throw EMPTY_THREAD_ERROR;
116
- },
17
+ messages = [] as never[];
117
18
 
118
- role: "user",
19
+ composer = createInertComposer(EMPTY_THREAD_ERROR, true);
119
20
 
120
- setRole() {
121
- throw EMPTY_THREAD_ERROR;
122
- },
21
+ isLoading = true;
123
22
 
124
- runConfig: {},
125
-
126
- setRunConfig() {
127
- throw EMPTY_THREAD_ERROR;
128
- },
129
-
130
- async reset() {
131
- // noop
132
- },
133
-
134
- async clearAttachments() {
135
- // noop
136
- },
137
-
138
- send() {
139
- throw EMPTY_THREAD_ERROR;
140
- },
141
-
142
- cancel() {
143
- // noop
144
- },
145
-
146
- queue: [] as never[],
147
- moveQueueItem() {},
148
- removeQueueItem() {},
149
-
150
- dictation: undefined,
151
-
152
- startDictation() {
153
- throw EMPTY_THREAD_ERROR;
154
- },
155
-
156
- stopDictation() {
157
- // noop
158
- },
159
-
160
- quote: undefined,
161
-
162
- setQuote() {
163
- throw EMPTY_THREAD_ERROR;
164
- },
165
-
166
- subscribe() {
167
- return () => {};
168
- },
169
-
170
- unstable_on() {
171
- return () => {};
172
- },
173
- },
174
-
175
- getEditComposer() {
23
+ getMessageById() {
176
24
  return undefined;
177
- },
25
+ }
178
26
 
179
- beginEdit() {
180
- throw EMPTY_THREAD_ERROR;
181
- },
182
-
183
- speech: undefined,
184
- voice: undefined,
185
-
186
- capabilities: {
187
- switchToBranch: false,
188
- switchBranchDuringRun: false,
189
- edit: false,
190
- delete: false,
191
- reload: false,
192
- refetchThread: false,
193
- cancel: false,
194
- unstable_copy: false,
195
- speech: false,
196
- dictation: false,
197
- voice: false,
198
- attachments: false,
199
- feedback: false,
200
- queue: false,
201
- },
202
-
203
- isDisabled: false,
204
- isSendDisabled: false,
205
- isLoading: true,
206
-
207
- messages: [],
208
-
209
- state: null,
210
-
211
- suggestions: [],
212
-
213
- extras: undefined,
214
-
215
- subscribe() {
216
- return () => {};
217
- },
218
-
219
- import() {
220
- throw EMPTY_THREAD_ERROR;
221
- },
27
+ getBranches() {
28
+ return [];
29
+ }
222
30
 
223
31
  export() {
224
32
  return { messages: [] };
225
- },
33
+ }
226
34
 
227
- reset() {
228
- throw EMPTY_THREAD_ERROR;
229
- },
230
-
231
- unstable_on() {
35
+ override subscribe(): Unsubscribe {
232
36
  return () => {};
233
- },
234
- };
37
+ }
38
+
39
+ override waitForUpdate(): Promise<void> {
40
+ return Promise.reject(EMPTY_THREAD_ERROR);
41
+ }
42
+ }
43
+
44
+ export const EMPTY_THREAD_CORE: ThreadRuntimeCore =
45
+ new EmptyThreadRuntimeCore();
@@ -60,4 +60,22 @@ describe("OptimisticState", () => {
60
60
 
61
61
  expect(state.value.title).toBe("Project Beta");
62
62
  });
63
+
64
+ it("drops an in-flight transform after reset", async () => {
65
+ const state = new OptimisticState({ title: "Untitled", extra: 0 });
66
+ const request = deferred();
67
+ const update = state.optimisticUpdate({
68
+ execute: () => request.promise,
69
+ optimistic: (value) => ({ ...value, title: "Pending" }),
70
+ then: (value) => ({ ...value, extra: 1 }),
71
+ });
72
+
73
+ expect(state.value.title).toBe("Pending");
74
+ state.reset({ title: "Fresh", extra: 0 });
75
+ expect(state.value).toEqual({ title: "Fresh", extra: 0 });
76
+
77
+ request.resolve();
78
+ await update;
79
+ expect(state.value).toEqual({ title: "Fresh", extra: 0 });
80
+ });
63
81
  });
@@ -48,6 +48,7 @@ export class OptimisticState<TState> extends BaseSubscribable {
48
48
  [];
49
49
 
50
50
  private _nextTransformOrder = 0;
51
+ private _epoch = 0;
51
52
 
52
53
  private _baseValue: TState;
53
54
  private _cachedValue: TState;
@@ -95,9 +96,20 @@ export class OptimisticState<TState> extends BaseSubscribable {
95
96
  this._updateState();
96
97
  }
97
98
 
99
+ public reset(state: TState): void {
100
+ // In-flight optimisticUpdate calls must not write into the replacement state.
101
+ this._epoch++;
102
+ this._pendingTransforms.length = 0;
103
+ this._completedOptimistics.length = 0;
104
+ this._baseValue = state;
105
+ this._cachedValue = state;
106
+ this._notifySubscribers();
107
+ }
108
+
98
109
  public async optimisticUpdate<TResult>(
99
110
  transform: Transform<TState, TResult>,
100
111
  ): Promise<TResult> {
112
+ const epoch = this._epoch;
101
113
  const order = this._nextTransformOrder++;
102
114
  const task = transform.execute();
103
115
  const pendingTransform = {
@@ -110,6 +122,7 @@ export class OptimisticState<TState> extends BaseSubscribable {
110
122
  this._updateState();
111
123
 
112
124
  const result = await task;
125
+ if (epoch !== this._epoch) return result;
113
126
  this._baseValue = pipeTransforms(this._baseValue, result, [
114
127
  transform.optimistic,
115
128
  transform.then,
@@ -1,6 +1,9 @@
1
1
  import type { ThreadMessage } from "../../types/message";
2
2
  import type { AssistantRuntime } from "../../runtime/api/assistant-runtime";
3
3
  import type { AssistantStream } from "assistant-stream";
4
+ import type { ThreadHistoryAdapter } from "../../adapters/thread-history";
5
+ import type { AttachmentAdapter } from "../../adapters/attachment";
6
+ import type { ModelContextProvider } from "../../model-context/types";
4
7
 
5
8
  /* oxlint-disable typescript/no-explicit-any -- structural stand-in for ComponentType without depending on react types */
6
9
  type RemoteThreadListProviderProps = { children?: any };
@@ -33,6 +36,12 @@ export type RemoteThreadListPageOptions = {
33
36
  after?: string | undefined;
34
37
  };
35
38
 
39
+ export type RuntimeAdapters = {
40
+ modelContext?: ModelContextProvider | undefined;
41
+ history?: ThreadHistoryAdapter | undefined;
42
+ attachments?: AttachmentAdapter | undefined;
43
+ };
44
+
36
45
  export type RemoteThreadListAdapter = {
37
46
  list(params?: RemoteThreadListPageOptions): Promise<RemoteThreadListResponse>;
38
47
 
@@ -56,16 +65,41 @@ export type RemoteThreadListAdapter = {
56
65
  * inject per-thread context such as a history or attachments adapter (see
57
66
  * `useCloudThreadListAdapter` for the canonical shape).
58
67
  *
68
+ * `useRemoteThreadListRuntime` renders this component when present. If it
69
+ * is omitted, that host synthesizes a `RuntimeAdapterProvider` from
70
+ * `unstable_useAdapters`. The `RemoteThreadList` store entry ignores it;
71
+ * expose `unstable_useAdapters` for that host.
72
+ *
59
73
  * The Provider must render `children` on its first commit; deferring them
60
74
  * behind a loading state, a Suspense boundary, or a `useEffect`-gated render
61
75
  * is unsupported and leaves thread context unavailable to downstream
62
76
  * consumers. Load data inside an always-mounted child instead.
63
77
  */
64
78
  unstable_Provider?: RemoteThreadListProviderComponent | undefined;
79
+
80
+ /**
81
+ * Hook the `RemoteThreadList` store entry calls once for the main-thread
82
+ * slot, then provides to the `thread` factory. This is not mounted per
83
+ * listed thread. `useRemoteThreadListRuntime` also calls it when
84
+ * `unstable_Provider` is omitted. Resolve `threadListItem` lazily on each
85
+ * adapter call; do not capture it at hook mount. The hook must keep a
86
+ * stable hook count across adapter swaps; a different count throws.
87
+ * Memoize the returned object.
88
+ *
89
+ * Per-thread history also requires the `thread` factory to be keyed by
90
+ * thread id (`withKey(id, thread(...))`). History loaders such as
91
+ * `useExternalHistory` run once per mount; an unkeyed factory keeps one
92
+ * instance across switches and the next thread's messages never load.
93
+ */
94
+ unstable_useAdapters?: (() => RuntimeAdapters | null | undefined) | undefined;
65
95
  };
66
96
 
67
97
  export type RemoteThreadListOptions = {
68
98
  runtimeHook: () => AssistantRuntime;
99
+
100
+ /**
101
+ * The adapter reference should remain stable across renders. Replacing it reloads the list and drops cached threads that are not in the replacement page. In-flight mutations from the previous adapter are cancelled.
102
+ */
69
103
  adapter: RemoteThreadListAdapter;
70
104
 
71
105
  /**
@@ -10,6 +10,9 @@ observe via `setState(snapshot)` and what the current behavior is.
10
10
  > first observation — args regress, args change after first completion,
11
11
  > result is replaced, result is cleared, key order shuffles — the tracker
12
12
  > never invokes the host's tool callback a second time.
13
+ >
14
+ > `reset()` starts a new execution boundary. A reused `toolCallId` in the
15
+ > next boundary gets a new execution identity and may fire once there.
13
16
 
14
17
  This guarantees host-side side effects (the typical reason `streamCall` /
15
18
  `execute` exists at all) can't double-run. The cost: post-completion
@@ -65,7 +68,7 @@ The tracker calls `setResponse` on the active controller and closes it.
65
68
  The backend result is emitted before the args stream closes, so a stale
66
69
  args parse failure cannot replace it. `reader.response.get()` resolves.
67
70
  If the tool also had a frontend `execute`, the executor is short-circuited
68
- via `_skipExecuteStreamIds`. Single fire.
71
+ via the entry's per-execution skip marker. Single fire.
69
72
 
70
73
  ### A.6. Previously-resolved tool's `result` is replaced
71
74
  Silently ignored — `entry.hasResult` short-circuits both the
@@ -153,15 +156,16 @@ tracker's view of "what we last observed". The next snapshot retries.
153
156
 
154
157
  ### F.1. `reset()` called while `execute()` invocations are in flight
155
158
  `abort()` is invoked, in-flight executions reject with
156
- `Tool execution aborted`. Once they settle, the cleanup logic clears
157
- `_executing`. The settled-resolver promises fire so the abort promise
158
- resolves.
159
+ `Tool execution aborted`. Once they settle, the cleanup logic removes their
160
+ execution identities from `_executing`. The settled-resolver promises fire so
161
+ the abort promise resolves.
159
162
 
160
163
  ### F.2. `setState` called during `reset()`'s in-flight abort
161
164
  The new snapshot is processed against an empty `_entries`. Tool calls
162
165
  in it are seeded as restored (because `reset()` re-armed
163
- `_pendingRestore`). Eventual cancellation `result` chunks for the
164
- aborted executions are dropped via `_skipExecuteStreamIds`.
166
+ `_pendingRestore`). Eventual cancellation `result` chunks for the aborted
167
+ executions are dropped when their execution identity no longer matches the
168
+ current entry.
165
169
 
166
170
  ### F.3. `resume(toolCallId, payload)` for an unknown id
167
171
  Silently no-ops. (The pre-class hook *threw*; the tracker softens this
@@ -175,6 +179,13 @@ rebuilt pipeline does not re-fire `streamCall` for them) and the
175
179
  snapshot is processed against the fresh pipeline. Repeated failures
176
180
  keep the tracker dead with a visible error to avoid restart loops.
177
181
 
182
+ ### F.5. Reset followed by same-id reuse
183
+ The assistant-stream pipeline assigns each streamed tool part an opaque
184
+ execution identity. Human-input callbacks, lifecycle callbacks, result chunks,
185
+ and pending execution cleanup are accepted only when that identity is still
186
+ current for the `toolCallId`. A late callback from before `reset()` is therefore
187
+ dropped even when the next session reuses the id.
188
+
178
189
  ## Known limitations
179
190
 
180
191
  ### Host callback throws
@@ -1172,3 +1172,246 @@ describe("ToolInvocationTracker", () => {
1172
1172
  }
1173
1173
  });
1174
1174
  });
1175
+
1176
+ describe("ToolInvocationTracker reset", () => {
1177
+ const trackerWith = (tools: Record<string, Tool>) => {
1178
+ let statuses: Record<string, ToolExecutionStatus> = {};
1179
+ const tracker = new ToolInvocationTracker(() => tools, {
1180
+ onResult: vi.fn(),
1181
+ onStatusesChange: (s: ReadonlyMap<string, ToolExecutionStatus>) => {
1182
+ statuses = Object.fromEntries(s);
1183
+ },
1184
+ });
1185
+ return { tracker, statuses: () => statuses };
1186
+ };
1187
+
1188
+ it("clears statuses for discarded executions that never settle", async () => {
1189
+ const { tracker, statuses } = trackerWith({
1190
+ weatherSearch: {
1191
+ parameters: { type: "object", properties: {} },
1192
+ execute: vi.fn(() => new Promise(() => {})),
1193
+ } satisfies Tool,
1194
+ });
1195
+ tracker.setState(createState([]));
1196
+ tracker.setState(
1197
+ createState([
1198
+ createAssistantMessage('{"query":"London"}', { query: "London" }),
1199
+ ]),
1200
+ );
1201
+ await waitFor(() => {
1202
+ expect(statuses()["tool-1"]?.type).toBe("executing");
1203
+ });
1204
+
1205
+ tracker.reset();
1206
+
1207
+ expect(statuses()).toEqual({});
1208
+
1209
+ // A new-session snapshot restoring tool activity must not drag the
1210
+ // discarded id back in through the whole-map republication. The first
1211
+ // post-reset snapshot is the fresh session's empty state, consuming the
1212
+ // pending-restore mark.
1213
+ tracker.setState(createState([]));
1214
+ tracker.setState(
1215
+ createState([
1216
+ createAssistantMessage(
1217
+ '{"query":"Paris"}',
1218
+ { query: "Paris" },
1219
+ { toolCallId: "tool-2" },
1220
+ ),
1221
+ ]),
1222
+ );
1223
+ await waitFor(() => {
1224
+ expect(statuses()["tool-2"]?.type).toBe("executing");
1225
+ });
1226
+ expect(statuses()["tool-1"]).toBeUndefined();
1227
+ });
1228
+
1229
+ it("does not republish sibling statuses when a discarded execution settles after reset", async () => {
1230
+ const settled = Promise.withResolvers<void>();
1231
+ const { tracker, statuses } = trackerWith({
1232
+ weatherSearch: {
1233
+ parameters: { type: "object", properties: {} },
1234
+ execute: vi.fn(
1235
+ (_args, { abortSignal }: { abortSignal: AbortSignal }) =>
1236
+ new Promise((resolve) => {
1237
+ abortSignal.addEventListener("abort", () => {
1238
+ resolve({ ok: true });
1239
+ settled.resolve();
1240
+ });
1241
+ }),
1242
+ ),
1243
+ } satisfies Tool,
1244
+ pressureSearch: {
1245
+ parameters: { type: "object", properties: {} },
1246
+ execute: vi.fn(() => new Promise(() => {})),
1247
+ } satisfies Tool,
1248
+ });
1249
+ tracker.setState(createState([]));
1250
+ tracker.setState(
1251
+ createState([
1252
+ createAssistantMessage('{"query":"London"}', { query: "London" }),
1253
+ createAssistantMessage(
1254
+ '{"query":"London"}',
1255
+ { query: "London" },
1256
+ {
1257
+ toolCallId: "tool-2",
1258
+ toolName: "pressureSearch",
1259
+ },
1260
+ ),
1261
+ ]),
1262
+ );
1263
+ await waitFor(() => {
1264
+ expect(statuses()["tool-1"]?.type).toBe("executing");
1265
+ expect(statuses()["tool-2"]?.type).toBe("executing");
1266
+ });
1267
+
1268
+ tracker.reset();
1269
+ expect(statuses()).toEqual({});
1270
+
1271
+ // The settle-after-abort of tool-1 is what could republish tool-2;
1272
+ // await it deterministically instead of sleeping.
1273
+ await settled.promise;
1274
+ await new Promise((r) => setTimeout(r, 0));
1275
+ expect(statuses()).toEqual({});
1276
+ });
1277
+
1278
+ it("rejects a human-input request from a discarded execution without resurrecting its status", async () => {
1279
+ let humanFn: ((payload: unknown) => Promise<unknown>) | undefined;
1280
+ const { tracker, statuses } = trackerWith({
1281
+ weatherSearch: {
1282
+ parameters: { type: "object", properties: {} },
1283
+ execute: vi.fn(() => new Promise(() => {})),
1284
+ streamCall: vi.fn((_reader, { human }) => {
1285
+ humanFn = human;
1286
+ }),
1287
+ } satisfies Tool,
1288
+ });
1289
+ tracker.setState(createState([]));
1290
+ tracker.setState(
1291
+ createState([
1292
+ createAssistantMessage('{"query":"London"}', { query: "London" }),
1293
+ ]),
1294
+ );
1295
+ await waitFor(() => {
1296
+ expect(statuses()["tool-1"]?.type).toBe("executing");
1297
+ expect(humanFn).toBeDefined();
1298
+ });
1299
+
1300
+ tracker.reset();
1301
+
1302
+ await expect(humanFn!({ request: "approve" })).rejects.toThrow(
1303
+ "Tool execution aborted",
1304
+ );
1305
+ expect(statuses()).toEqual({});
1306
+ });
1307
+
1308
+ it("rejects a late human-input request when reset reuses the tool call id", async () => {
1309
+ const humanFns: ((payload: unknown) => Promise<unknown>)[] = [];
1310
+ const { tracker, statuses } = trackerWith({
1311
+ weatherSearch: {
1312
+ parameters: { type: "object", properties: {} },
1313
+ execute: vi.fn(() => new Promise(() => {})),
1314
+ streamCall: vi.fn((_reader, { human }) => {
1315
+ humanFns.push(human);
1316
+ }),
1317
+ } satisfies Tool,
1318
+ });
1319
+
1320
+ tracker.setState(createState([]));
1321
+ tracker.setState(
1322
+ createState([
1323
+ createAssistantMessage('{"query":"London"}', { query: "London" }),
1324
+ ]),
1325
+ );
1326
+ await waitFor(() => {
1327
+ expect(humanFns).toHaveLength(1);
1328
+ expect(statuses()["tool-1"]?.type).toBe("executing");
1329
+ });
1330
+
1331
+ tracker.reset();
1332
+ tracker.setState(createState([]));
1333
+ tracker.setState(
1334
+ createState([
1335
+ createAssistantMessage(
1336
+ '{"query":"Paris"}',
1337
+ { query: "Paris" },
1338
+ { toolCallId: "tool-1" },
1339
+ ),
1340
+ ]),
1341
+ );
1342
+ await waitFor(() => expect(humanFns).toHaveLength(2));
1343
+
1344
+ await expect(humanFns[0]!({ stale: true })).rejects.toThrow(
1345
+ "Tool execution aborted",
1346
+ );
1347
+ expect(statuses()["tool-1"]?.type).toBe("executing");
1348
+
1349
+ tracker.reset();
1350
+ });
1351
+
1352
+ it("drops a late result when reset reuses the tool call id", async () => {
1353
+ const executions: Array<{
1354
+ resolve: (value: { session: string }) => void;
1355
+ promise: Promise<{ session: string }>;
1356
+ }> = [];
1357
+ const onResult = vi.fn();
1358
+ const tracker = new ToolInvocationTracker(
1359
+ () => ({
1360
+ weatherSearch: {
1361
+ parameters: { type: "object", properties: {} },
1362
+ execute: vi.fn(
1363
+ (_args: unknown, { abortSignal }: { abortSignal: AbortSignal }) => {
1364
+ let resolveExecution!: (value: { session: string }) => void;
1365
+ const promise = new Promise<{ session: string }>((resolve) => {
1366
+ resolveExecution = resolve;
1367
+ });
1368
+ const execution = { promise, resolve: resolveExecution };
1369
+ abortSignal.addEventListener("abort", () => {
1370
+ execution.resolve({ session: "old" });
1371
+ });
1372
+ executions.push(execution);
1373
+ return promise;
1374
+ },
1375
+ ),
1376
+ } satisfies Tool,
1377
+ }),
1378
+ { onResult, onStatusesChange: vi.fn() },
1379
+ );
1380
+
1381
+ tracker.setState(createState([]));
1382
+ tracker.setState(
1383
+ createState([
1384
+ createAssistantMessage('{"query":"London"}', { query: "London" }),
1385
+ ]),
1386
+ );
1387
+ await waitFor(() => expect(executions).toHaveLength(1));
1388
+
1389
+ tracker.reset();
1390
+ tracker.setState(createState([]));
1391
+ tracker.setState(
1392
+ createState([
1393
+ createAssistantMessage(
1394
+ '{"query":"Paris"}',
1395
+ { query: "Paris" },
1396
+ { toolCallId: "tool-1" },
1397
+ ),
1398
+ ]),
1399
+ );
1400
+ await waitFor(() => expect(executions).toHaveLength(2));
1401
+ await new Promise((resolve) => setTimeout(resolve, 0));
1402
+ expect(onResult).not.toHaveBeenCalled();
1403
+
1404
+ executions[1]!.resolve({ session: "new" });
1405
+ await waitFor(() => {
1406
+ expect(onResult).toHaveBeenCalledOnce();
1407
+ expect(onResult).toHaveBeenCalledWith(
1408
+ expect.objectContaining({
1409
+ toolCallId: "tool-1",
1410
+ result: { session: "new" },
1411
+ }),
1412
+ );
1413
+ });
1414
+
1415
+ tracker.reset();
1416
+ });
1417
+ });