@assistant-ui/core 0.3.13 → 0.3.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (396) hide show
  1. package/dist/adapters/speech.d.ts.map +1 -1
  2. package/dist/adapters/speech.js +9 -15
  3. package/dist/adapters/speech.js.map +1 -1
  4. package/dist/adapters/thread-history.d.ts +2 -0
  5. package/dist/adapters/thread-history.d.ts.map +1 -1
  6. package/dist/adapters/voice.d.ts.map +1 -1
  7. package/dist/adapters/voice.js +27 -15
  8. package/dist/adapters/voice.js.map +1 -1
  9. package/dist/index.d.ts +2 -2
  10. package/dist/index.js.map +1 -1
  11. package/dist/internal.d.ts +1 -1
  12. package/dist/internal.js +6 -6
  13. package/dist/model-context/frame/host.d.ts.map +1 -1
  14. package/dist/model-context/frame/host.js +2 -1
  15. package/dist/model-context/frame/host.js.map +1 -1
  16. package/dist/model-context/registry.d.ts.map +1 -1
  17. package/dist/model-context/registry.js +16 -4
  18. package/dist/model-context/registry.js.map +1 -1
  19. package/dist/react/RuntimeAdapter.d.ts +8 -1
  20. package/dist/react/RuntimeAdapter.d.ts.map +1 -1
  21. package/dist/react/RuntimeAdapter.js +23 -18
  22. package/dist/react/RuntimeAdapter.js.map +1 -1
  23. package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
  24. package/dist/react/adapters/LocalStorageThreadListAdapter.js +28 -12
  25. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  26. package/dist/react/client/AdaptedRemoteThread.d.ts +11 -0
  27. package/dist/react/client/AdaptedRemoteThread.d.ts.map +1 -0
  28. package/dist/react/client/AdaptedRemoteThread.js +27 -0
  29. package/dist/react/client/AdaptedRemoteThread.js.map +1 -0
  30. package/dist/react/client/InMemoryThreadList.d.ts +19 -0
  31. package/dist/react/client/InMemoryThreadList.d.ts.map +1 -0
  32. package/dist/react/client/InMemoryThreadList.js +418 -0
  33. package/dist/react/client/InMemoryThreadList.js.map +1 -0
  34. package/dist/react/client/Interactables.d.ts.map +1 -1
  35. package/dist/react/client/Interactables.js +159 -102
  36. package/dist/react/client/Interactables.js.map +1 -1
  37. package/dist/react/client/RemoteThreadList.d.ts +34 -0
  38. package/dist/react/client/RemoteThreadList.d.ts.map +1 -0
  39. package/dist/react/client/RemoteThreadList.js +826 -0
  40. package/dist/react/client/RemoteThreadList.js.map +1 -0
  41. package/dist/react/client/Tools.d.ts.map +1 -1
  42. package/dist/react/client/Tools.js +38 -27
  43. package/dist/react/client/Tools.js.map +1 -1
  44. package/dist/react/index.d.ts +7 -2
  45. package/dist/react/index.js +5 -2
  46. package/dist/react/interactables-legacy/Interactables.d.ts.map +1 -1
  47. package/dist/react/interactables-legacy/Interactables.js +145 -110
  48. package/dist/react/interactables-legacy/Interactables.js.map +1 -1
  49. package/dist/react/primitive-hooks/useActionBarCopy.d.ts.map +1 -1
  50. package/dist/react/primitive-hooks/useActionBarCopy.js +13 -18
  51. package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
  52. package/dist/react/primitive-hooks/useActionBarEdit.d.ts.map +1 -1
  53. package/dist/react/primitive-hooks/useActionBarEdit.js +2 -4
  54. package/dist/react/primitive-hooks/useActionBarEdit.js.map +1 -1
  55. package/dist/react/primitive-hooks/useActionBarReload.d.ts.map +1 -1
  56. package/dist/react/primitive-hooks/useActionBarReload.js +2 -4
  57. package/dist/react/primitive-hooks/useActionBarReload.js.map +1 -1
  58. package/dist/react/primitive-hooks/useBranchPickerNext.d.ts.map +1 -1
  59. package/dist/react/primitive-hooks/useBranchPickerNext.js +2 -6
  60. package/dist/react/primitive-hooks/useBranchPickerNext.js.map +1 -1
  61. package/dist/react/primitive-hooks/useBranchPickerPrevious.d.ts.map +1 -1
  62. package/dist/react/primitive-hooks/useBranchPickerPrevious.js +2 -6
  63. package/dist/react/primitive-hooks/useBranchPickerPrevious.js.map +1 -1
  64. package/dist/react/primitive-hooks/useComposerCancel.d.ts.map +1 -1
  65. package/dist/react/primitive-hooks/useComposerCancel.js +2 -4
  66. package/dist/react/primitive-hooks/useComposerCancel.js.map +1 -1
  67. package/dist/react/primitive-hooks/useComposerSend.d.ts.map +1 -1
  68. package/dist/react/primitive-hooks/useComposerSend.js +2 -4
  69. package/dist/react/primitive-hooks/useComposerSend.js.map +1 -1
  70. package/dist/react/primitive-hooks/useSuggestionTrigger.d.ts.map +1 -1
  71. package/dist/react/primitive-hooks/useSuggestionTrigger.js +6 -2
  72. package/dist/react/primitive-hooks/useSuggestionTrigger.js.map +1 -1
  73. package/dist/react/primitives/message/MessageParts.d.ts +13 -0
  74. package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
  75. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  76. package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
  77. package/dist/react/primitives/thread/ThreadMessages.js +1 -1
  78. package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
  79. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +22 -10
  80. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  81. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +109 -71
  82. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  83. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +8 -2
  84. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  85. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +40 -13
  86. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  87. package/dist/react/runtimes/RemoteThreadResource.d.ts +30 -0
  88. package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -0
  89. package/dist/react/runtimes/RemoteThreadResource.js +134 -0
  90. package/dist/react/runtimes/RemoteThreadResource.js.map +1 -0
  91. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts +3 -10
  92. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts.map +1 -1
  93. package/dist/react/runtimes/RuntimeAdapterProvider.js +3 -6
  94. package/dist/react/runtimes/RuntimeAdapterProvider.js.map +1 -1
  95. package/dist/react/runtimes/assistant-transport/commandQueue.d.ts +17 -0
  96. package/dist/react/runtimes/assistant-transport/commandQueue.d.ts.map +1 -0
  97. package/dist/react/runtimes/assistant-transport/commandQueue.js +55 -0
  98. package/dist/react/runtimes/assistant-transport/commandQueue.js.map +1 -0
  99. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.d.ts +11 -0
  100. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.d.ts.map +1 -0
  101. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.js +165 -0
  102. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.js.map +1 -0
  103. package/dist/react/runtimes/assistant-transport/runManager.d.ts +15 -0
  104. package/dist/react/runtimes/assistant-transport/runManager.d.ts.map +1 -0
  105. package/dist/react/runtimes/assistant-transport/runManager.js +86 -0
  106. package/dist/react/runtimes/assistant-transport/runManager.js.map +1 -0
  107. package/dist/react/runtimes/assistant-transport/types.d.ts +130 -0
  108. package/dist/react/runtimes/assistant-transport/types.d.ts.map +1 -0
  109. package/dist/react/runtimes/assistant-transport/types.js +0 -0
  110. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts +14 -0
  111. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -0
  112. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js +296 -0
  113. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js.map +1 -0
  114. package/dist/react/runtimes/assistant-transport/useConvertedState.d.ts +7 -0
  115. package/dist/react/runtimes/assistant-transport/useConvertedState.d.ts.map +1 -0
  116. package/dist/react/runtimes/assistant-transport/useConvertedState.js +25 -0
  117. package/dist/react/runtimes/assistant-transport/useConvertedState.js.map +1 -0
  118. package/dist/react/runtimes/assistant-transport/useLatestRef.d.ts +7 -0
  119. package/dist/react/runtimes/assistant-transport/useLatestRef.d.ts.map +1 -0
  120. package/dist/react/runtimes/assistant-transport/useLatestRef.js +27 -0
  121. package/dist/react/runtimes/assistant-transport/useLatestRef.js.map +1 -0
  122. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  123. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +39 -13
  124. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  125. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +2 -1
  126. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
  127. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +3 -3
  128. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
  129. package/dist/react/runtimes/cloud/auiV0.d.ts +4 -0
  130. package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
  131. package/dist/react/runtimes/cloud/auiV0.js +7 -0
  132. package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
  133. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  134. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +22 -12
  135. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  136. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.d.ts +16 -0
  137. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.d.ts.map +1 -0
  138. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js +36 -0
  139. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js.map +1 -0
  140. package/dist/react/runtimes/external-message-converter.js +14 -14
  141. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  142. package/dist/react/runtimes/useExternalStoreRuntime.d.ts.map +1 -1
  143. package/dist/react/runtimes/useExternalStoreRuntime.js +44 -28
  144. package/dist/react/runtimes/useExternalStoreRuntime.js.map +1 -1
  145. package/dist/react/runtimes/useExternalStoreSharedOptions.js.map +1 -1
  146. package/dist/react/runtimes/useLocalRuntime.js +1 -1
  147. package/dist/react/runtimes/useRuntimeAdapters.d.ts +9 -0
  148. package/dist/react/runtimes/useRuntimeAdapters.d.ts.map +1 -0
  149. package/dist/react/runtimes/useRuntimeAdapters.js +20 -0
  150. package/dist/react/runtimes/useRuntimeAdapters.js.map +1 -0
  151. package/dist/runtime/api/composer-runtime.d.ts +5 -0
  152. package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
  153. package/dist/runtime/api/composer-runtime.js.map +1 -1
  154. package/dist/runtime/api/message-runtime.js +1 -1
  155. package/dist/runtime/api/thread-list-runtime.d.ts +1 -0
  156. package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
  157. package/dist/runtime/api/thread-list-runtime.js +4 -2
  158. package/dist/runtime/api/thread-list-runtime.js.map +1 -1
  159. package/dist/runtime/api/thread-runtime.d.ts +12 -2
  160. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  161. package/dist/runtime/api/thread-runtime.js +8 -2
  162. package/dist/runtime/api/thread-runtime.js.map +1 -1
  163. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  164. package/dist/runtime/base/base-composer-runtime-core.js +8 -7
  165. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  166. package/dist/runtime/base/base-thread-runtime-core.d.ts +1 -0
  167. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  168. package/dist/runtime/base/base-thread-runtime-core.js +3 -3
  169. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  170. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +0 -1
  171. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
  172. package/dist/runtime/base/default-thread-composer-runtime-core.js +10 -4
  173. package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
  174. package/dist/runtime/interfaces/thread-runtime-core.d.ts +6 -0
  175. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  176. package/dist/runtime/internal.js +5 -5
  177. package/dist/runtime/queue/message-queue.d.ts.map +1 -1
  178. package/dist/runtime/queue/message-queue.js +2 -1
  179. package/dist/runtime/queue/message-queue.js.map +1 -1
  180. package/dist/runtime/utils/thread-runtime-lifecycle.d.ts +8 -0
  181. package/dist/runtime/utils/thread-runtime-lifecycle.d.ts.map +1 -0
  182. package/dist/runtime/utils/thread-runtime-lifecycle.js +11 -0
  183. package/dist/runtime/utils/thread-runtime-lifecycle.js.map +1 -0
  184. package/dist/runtimes/external-store/external-store-shared-options.js.map +1 -1
  185. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  186. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +4 -1
  187. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  188. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +8 -0
  189. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  190. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +35 -13
  191. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  192. package/dist/runtimes/internal.d.ts +1 -1
  193. package/dist/runtimes/local/local-thread-runtime-core.d.ts +3 -0
  194. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  195. package/dist/runtimes/local/local-thread-runtime-core.js +53 -13
  196. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  197. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +1 -0
  198. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
  199. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +3 -0
  200. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
  201. package/dist/runtimes/remote-thread-list/empty-thread-core.js +3 -0
  202. package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
  203. package/dist/runtimes/remote-thread-list/types.d.ts +29 -1
  204. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  205. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +1 -12
  206. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
  207. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +67 -38
  208. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
  209. package/dist/store/clients/suggestions.js +2 -2
  210. package/dist/store/clients/suggestions.js.map +1 -1
  211. package/dist/store/clients/thread-selection-events.d.ts +10 -0
  212. package/dist/store/clients/thread-selection-events.d.ts.map +1 -0
  213. package/dist/store/clients/thread-selection-events.js +40 -0
  214. package/dist/store/clients/thread-selection-events.js.map +1 -0
  215. package/dist/store/env.d.ts +5 -0
  216. package/dist/store/env.d.ts.map +1 -0
  217. package/dist/store/env.js +12 -0
  218. package/dist/store/env.js.map +1 -0
  219. package/dist/store/index.d.ts +5 -3
  220. package/dist/store/index.js +4 -2
  221. package/dist/store/internal.d.ts +4 -1
  222. package/dist/store/internal.js +4 -1
  223. package/dist/store/primitive-predicates.d.ts +19 -0
  224. package/dist/store/primitive-predicates.d.ts.map +1 -0
  225. package/dist/store/primitive-predicates.js +19 -0
  226. package/dist/store/primitive-predicates.js.map +1 -0
  227. package/dist/store/runtime-clients/attachment-runtime-client.d.ts.map +1 -1
  228. package/dist/store/runtime-clients/attachment-runtime-client.js +18 -11
  229. package/dist/store/runtime-clients/attachment-runtime-client.js.map +1 -1
  230. package/dist/store/runtime-clients/handle-runtime-action.d.ts +5 -0
  231. package/dist/store/runtime-clients/handle-runtime-action.d.ts.map +1 -0
  232. package/dist/store/runtime-clients/handle-runtime-action.js +12 -0
  233. package/dist/store/runtime-clients/handle-runtime-action.js.map +1 -0
  234. package/dist/store/runtime-clients/handle-thread-list-action.d.ts +5 -0
  235. package/dist/store/runtime-clients/handle-thread-list-action.d.ts.map +1 -0
  236. package/dist/store/runtime-clients/handle-thread-list-action.js +7 -0
  237. package/dist/store/runtime-clients/handle-thread-list-action.js.map +1 -0
  238. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  239. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +62 -29
  240. package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
  241. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
  242. package/dist/store/runtime-clients/thread-list-runtime-client.js +5 -6
  243. package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
  244. package/dist/store/scopes/composer.d.ts +9 -4
  245. package/dist/store/scopes/composer.d.ts.map +1 -1
  246. package/dist/store/scopes/thread-list-item.d.ts +7 -6
  247. package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
  248. package/dist/store/scopes/thread.d.ts +8 -7
  249. package/dist/store/scopes/thread.d.ts.map +1 -1
  250. package/dist/store/scopes/threads.d.ts +17 -1
  251. package/dist/store/scopes/threads.d.ts.map +1 -1
  252. package/dist/subscribable/subscribable.d.ts +2 -1
  253. package/dist/subscribable/subscribable.d.ts.map +1 -1
  254. package/dist/subscribable/subscribable.js +23 -18
  255. package/dist/subscribable/subscribable.js.map +1 -1
  256. package/dist/utils/composite-context-provider.d.ts +1 -0
  257. package/dist/utils/composite-context-provider.d.ts.map +1 -1
  258. package/dist/utils/composite-context-provider.js +25 -9
  259. package/dist/utils/composite-context-provider.js.map +1 -1
  260. package/dist/utils/notify-event-listeners.d.ts +2 -2
  261. package/dist/utils/notify-event-listeners.d.ts.map +1 -1
  262. package/dist/utils/notify-event-listeners.js +2 -2
  263. package/dist/utils/notify-event-listeners.js.map +1 -1
  264. package/package.json +7 -7
  265. package/src/adapters/speech.test.ts +118 -1
  266. package/src/adapters/speech.ts +21 -22
  267. package/src/adapters/thread-history.ts +2 -0
  268. package/src/adapters/voice.test.ts +69 -0
  269. package/src/adapters/voice.ts +27 -27
  270. package/src/index.ts +1 -0
  271. package/src/model-context/frame/host.test.ts +23 -0
  272. package/src/model-context/frame/host.ts +2 -1
  273. package/src/model-context/registry.test.ts +131 -0
  274. package/src/model-context/registry.ts +16 -6
  275. package/src/react/RuntimeAdapter.test.ts +2 -0
  276. package/src/react/RuntimeAdapter.ts +20 -8
  277. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +34 -17
  278. package/src/react/client/AdaptedRemoteThread.ts +41 -0
  279. package/src/react/client/InMemoryThreadList.test.tsx +148 -0
  280. package/src/react/client/InMemoryThreadList.ts +290 -0
  281. package/src/react/client/Interactables.test.ts +326 -2
  282. package/src/react/client/Interactables.ts +227 -110
  283. package/src/react/client/RemoteThreadList.test.ts +1026 -0
  284. package/src/react/client/RemoteThreadList.ts +1067 -0
  285. package/src/react/client/Tools.ts +36 -29
  286. package/src/react/index.ts +13 -0
  287. package/src/react/interactables-legacy/Interactables.test.ts +317 -0
  288. package/src/react/interactables-legacy/Interactables.ts +204 -128
  289. package/src/react/primitive-hooks/useActionBarCopy.ts +2 -7
  290. package/src/react/primitive-hooks/useActionBarEdit.ts +2 -1
  291. package/src/react/primitive-hooks/useActionBarReload.ts +2 -6
  292. package/src/react/primitive-hooks/useBranchPickerNext.ts +2 -7
  293. package/src/react/primitive-hooks/useBranchPickerPrevious.ts +2 -7
  294. package/src/react/primitive-hooks/useComposerCancel.ts +2 -1
  295. package/src/react/primitive-hooks/useComposerSend.ts +2 -5
  296. package/src/react/primitive-hooks/useSuggestionTrigger.test.ts +11 -0
  297. package/src/react/primitive-hooks/useSuggestionTrigger.ts +4 -5
  298. package/src/react/primitives/message/MessageParts.tsx +0 -1
  299. package/src/react/primitives/thread/ThreadMessages.tsx +2 -1
  300. package/src/react/runtimes/RemoteThreadListHookInstanceManager.retry.test.tsx +116 -0
  301. package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +1 -1
  302. package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +57 -6
  303. package/src/react/runtimes/RemoteThreadListHookInstanceManager.title.test.tsx +272 -0
  304. package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +159 -124
  305. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +59 -20
  306. package/src/react/runtimes/RemoteThreadResource.test.ts +141 -0
  307. package/src/react/runtimes/RemoteThreadResource.ts +231 -0
  308. package/src/react/runtimes/RuntimeAdapterProvider.tsx +8 -20
  309. package/src/react/runtimes/assistant-transport/commandQueue.ts +68 -0
  310. package/src/react/runtimes/assistant-transport/replayBoundaryStream.test.ts +455 -0
  311. package/src/react/runtimes/assistant-transport/replayBoundaryStream.ts +172 -0
  312. package/src/react/runtimes/assistant-transport/runManager.ts +124 -0
  313. package/src/react/runtimes/assistant-transport/transport-delivery.test.tsx +79 -0
  314. package/src/react/runtimes/assistant-transport/transport-parentid.test.tsx +97 -0
  315. package/src/react/runtimes/assistant-transport/transport-scheduling.test.ts +414 -0
  316. package/src/react/runtimes/assistant-transport/types.ts +170 -0
  317. package/src/react/runtimes/assistant-transport/useAssistantTransport.spec.md +141 -0
  318. package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.test.tsx +625 -0
  319. package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.ts +481 -0
  320. package/src/react/runtimes/assistant-transport/useConvertedState.ts +20 -0
  321. package/src/react/runtimes/assistant-transport/useLatestRef.ts +9 -0
  322. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +131 -6
  323. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +61 -15
  324. package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +6 -4
  325. package/src/react/runtimes/cloud/auiV0.ts +17 -1
  326. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +36 -21
  327. package/src/react/runtimes/cloud/useCloudThreadListRuntime.test.tsx +56 -0
  328. package/src/react/runtimes/cloud/useCloudThreadListRuntime.ts +31 -0
  329. package/src/react/runtimes/external-message-converter.test.ts +143 -0
  330. package/src/react/runtimes/external-message-converter.ts +41 -41
  331. package/src/react/runtimes/remote-thread-hook-on-tap.test.ts +58 -0
  332. package/src/react/runtimes/useExternalStoreRuntime.lifecycle.test.tsx +83 -0
  333. package/src/react/runtimes/useExternalStoreRuntime.suggestions.test.tsx +13 -3
  334. package/src/react/runtimes/useExternalStoreRuntime.ts +7 -0
  335. package/src/react/runtimes/useExternalStoreSharedOptions.ts +3 -1
  336. package/src/react/runtimes/useLocalRuntime.test.tsx +130 -4
  337. package/src/react/runtimes/useRuntimeAdapters.test.tsx +62 -0
  338. package/src/react/runtimes/useRuntimeAdapters.ts +28 -0
  339. package/src/runtime/api/composer-runtime.ts +5 -0
  340. package/src/runtime/api/thread-list-runtime.ts +3 -1
  341. package/src/runtime/api/thread-runtime.ts +20 -2
  342. package/src/runtime/base/base-composer-runtime-core.ts +6 -5
  343. package/src/runtime/base/base-thread-runtime-core.test.ts +191 -0
  344. package/src/runtime/base/base-thread-runtime-core.ts +11 -2
  345. package/src/runtime/base/default-thread-composer-runtime-core.ts +12 -4
  346. package/src/runtime/interfaces/thread-runtime-core.ts +6 -0
  347. package/src/runtime/queue/message-queue.ts +2 -1
  348. package/src/runtime/utils/thread-runtime-lifecycle.ts +18 -0
  349. package/src/runtimes/external-store/external-store-shared-options.ts +3 -1
  350. package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +4 -1
  351. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +99 -34
  352. package/src/runtimes/local/local-thread-runtime-core.test.ts +373 -4
  353. package/src/runtimes/local/local-thread-runtime-core.ts +79 -14
  354. package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +4 -0
  355. package/src/runtimes/remote-thread-list/empty-thread-core.ts +4 -0
  356. package/src/runtimes/remote-thread-list/types.ts +30 -0
  357. package/src/runtimes/tool-invocations/EDGE_CASES.md +17 -6
  358. package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +243 -0
  359. package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +127 -61
  360. package/src/store/clients/model-context-client.test.ts +16 -8
  361. package/src/store/clients/suggestions.ts +2 -2
  362. package/src/store/clients/thread-selection-events.ts +21 -0
  363. package/src/store/env.ts +11 -0
  364. package/src/store/index.ts +14 -1
  365. package/src/store/internal.ts +13 -0
  366. package/src/store/primitive-predicates.test.ts +184 -0
  367. package/src/store/primitive-predicates.ts +43 -0
  368. package/src/store/runtime-clients/attachment-runtime-client.test.ts +41 -0
  369. package/src/store/runtime-clients/attachment-runtime-client.ts +2 -1
  370. package/src/store/runtime-clients/handle-runtime-action.ts +11 -0
  371. package/src/store/runtime-clients/handle-thread-list-action.test.ts +69 -0
  372. package/src/store/runtime-clients/handle-thread-list-action.ts +6 -0
  373. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +15 -7
  374. package/src/store/runtime-clients/thread-list-runtime-client.ts +9 -6
  375. package/src/store/scopes/composer.ts +9 -4
  376. package/src/store/scopes/thread-list-item.ts +7 -6
  377. package/src/store/scopes/thread.ts +8 -7
  378. package/src/store/scopes/threads.ts +14 -0
  379. package/src/subscribable/subscribable.test.ts +77 -1
  380. package/src/subscribable/subscribable.ts +38 -23
  381. package/src/tests/RemoteThreadListThreadListRuntimeCore-switchToThread-unarchive.test.ts +25 -0
  382. package/src/tests/auiV0Encode.test.ts +66 -0
  383. package/src/tests/base-composer-runtime-core-send.test.ts +30 -0
  384. package/src/tests/base-composer-runtime-core.test.ts +28 -0
  385. package/src/tests/composer-can-cancel.test.ts +101 -0
  386. package/src/tests/external-store-thread-list-runtime-core.test.ts +101 -0
  387. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +191 -1
  388. package/src/tests/external-store-thread-runtime-core.test.ts +124 -0
  389. package/src/tests/interactables-toolui-migration.test.tsx +66 -0
  390. package/src/tests/message-queue.test.ts +28 -0
  391. package/src/tests/session-reset-notification.test.ts +145 -0
  392. package/src/tests/thread-switch-events.test.tsx +99 -1
  393. package/src/tests/tools-scope-migration.test.tsx +58 -0
  394. package/src/utils/composite-context-provider.test.ts +139 -0
  395. package/src/utils/composite-context-provider.ts +26 -8
  396. package/src/utils/notify-event-listeners.ts +10 -5
@@ -4,6 +4,7 @@ import type { ClientOutput } from "@assistant-ui/store";
4
4
  import {
5
5
  attachTransformScopes,
6
6
  useAssistantClientRef,
7
+ useAssistantScopeEffect,
7
8
  } from "@assistant-ui/store/client";
8
9
  import type {
9
10
  Unstable_InteractablesState,
@@ -22,6 +23,7 @@ import {
22
23
  findModelKnownState,
23
24
  interactableToolName,
24
25
  } from "../../model-context/interactable-composer-metadata";
26
+ import { notifySubscribers as notifyStateSubscribers } from "../../subscribable/subscribable";
25
27
 
26
28
  const PERSISTENCE_DEBOUNCE_MS = 500;
27
29
 
@@ -49,6 +51,12 @@ type InternalInteractableRegistration = Unstable_InteractableRegistration & {
49
51
  scope?: "thread" | undefined;
50
52
  };
51
53
 
54
+ type UpdateToolUIEntry = {
55
+ count: number;
56
+ render: NonNullable<Unstable_InteractableRegistration["updateRender"]>;
57
+ unsubscribe: (() => void) | undefined;
58
+ };
59
+
52
60
  const hasInteractableCreateCall = (
53
61
  messages: readonly MessageLike[],
54
62
  id: string,
@@ -92,9 +100,7 @@ const useInteractablesResource = ({
92
100
  const registrationCountsRef = useRef(new Map<string, number>());
93
101
  // One update-tool UI per interactable name, alive while any registrant
94
102
  // that supplied an updateRender is mounted.
95
- const updateToolUIsRef = useRef(
96
- new Map<string, { count: number; unsubscribe: () => void }>(),
97
- );
103
+ const updateToolUIsRef = useRef(new Map<string, UpdateToolUIEntry>());
98
104
  // App-scoped state restored via adapter.load(), consumed as components register.
99
105
  const loadedStateRef = useRef(new Map<string, unknown>());
100
106
  // Ids edited locally this session — a local edit always wins over a slow load.
@@ -107,10 +113,23 @@ const useInteractablesResource = ({
107
113
  undefined,
108
114
  );
109
115
  const syncSeqRef = useRef(0);
110
- const hasPendingLocalChangeRef = useRef(false);
116
+ const latestSyncSeqByIdRef = useRef(new Map<string, number>());
117
+ const inFlightPersistenceRef = useRef(0);
111
118
  const flushResolversRef = useRef<Array<() => void>>([]);
112
119
  const dirtyIdsRef = useRef(new Set<string>());
113
120
 
121
+ type PersistenceBatch = {
122
+ adapter: Unstable_InteractablePersistenceAdapter;
123
+ payload: Unstable_InteractablePersistedState;
124
+ dirtyIds: Set<string>;
125
+ seq: number;
126
+ };
127
+
128
+ const outgoingQueueRef = useRef<PersistenceBatch[]>([]);
129
+ const runPersistenceRef = useRef<(batch?: PersistenceBatch) => void>(
130
+ () => {},
131
+ );
132
+
114
133
  const setStateAndRef = useCallback(
115
134
  (
116
135
  updater: (
@@ -133,67 +152,127 @@ const useInteractablesResource = ({
133
152
  return result;
134
153
  }, []);
135
154
 
136
- const runPersistence = useCallback(async () => {
137
- const adapter = adapterRef.current;
138
- if (!adapter) {
139
- for (const resolve of flushResolversRef.current) resolve();
140
- flushResolversRef.current = [];
141
- return;
142
- }
155
+ const takeDirtyBatch = useCallback(
156
+ (
157
+ adapter: Unstable_InteractablePersistenceAdapter,
158
+ ): PersistenceBatch | undefined => {
159
+ if (dirtyIdsRef.current.size === 0) return;
160
+ const dirtyIds = new Set(dirtyIdsRef.current);
161
+ dirtyIdsRef.current.clear();
162
+ const seq = ++syncSeqRef.current;
163
+ for (const id of dirtyIds) latestSyncSeqByIdRef.current.set(id, seq);
164
+ return { adapter, payload: exportState(), dirtyIds, seq };
165
+ },
166
+ [exportState],
167
+ );
143
168
 
144
- const seq = ++syncSeqRef.current;
145
- const dirtyIds = new Set(dirtyIdsRef.current);
146
- dirtyIdsRef.current.clear();
147
- hasPendingLocalChangeRef.current = true;
148
-
149
- // Snapshot before any await so unregistered definitions are still included.
150
- const payload = exportState();
151
-
152
- setStateAndRef((prev) => ({
153
- ...prev,
154
- persistence: {
155
- ...prev.persistence,
156
- ...Object.fromEntries(
157
- [...dirtyIds].map((id) => [
158
- id,
159
- { isPending: true, error: undefined },
160
- ]),
161
- ),
162
- },
163
- }));
169
+ const enqueuePersistence = useCallback(
170
+ (adapter: Unstable_InteractablePersistenceAdapter) => {
171
+ const batch = takeDirtyBatch(adapter);
172
+ if (!batch) return;
173
+ if (inFlightPersistenceRef.current === 0) {
174
+ runPersistenceRef.current(batch);
175
+ } else {
176
+ outgoingQueueRef.current.push(batch);
177
+ }
178
+ },
179
+ [takeDirtyBatch],
180
+ );
181
+
182
+ const runPersistence = useCallback(
183
+ async (batch?: PersistenceBatch) => {
184
+ const resolved =
185
+ batch ??
186
+ (adapterRef.current ? takeDirtyBatch(adapterRef.current) : undefined);
187
+ if (!resolved) {
188
+ if (inFlightPersistenceRef.current === 0) {
189
+ for (const resolve of flushResolversRef.current) resolve();
190
+ flushResolversRef.current = [];
191
+ }
192
+ return;
193
+ }
164
194
 
165
- try {
166
- await adapter.save(payload);
167
- if (syncSeqRef.current === seq) {
168
- hasPendingLocalChangeRef.current = false;
195
+ const { adapter, payload, dirtyIds, seq } = resolved;
196
+ inFlightPersistenceRef.current += 1;
197
+
198
+ setStateAndRef((prev) => ({
199
+ ...prev,
200
+ persistence: {
201
+ ...prev.persistence,
202
+ ...Object.fromEntries(
203
+ [...dirtyIds].map((id) => [
204
+ id,
205
+ { isPending: true, error: undefined },
206
+ ]),
207
+ ),
208
+ },
209
+ }));
210
+
211
+ try {
212
+ await adapter.save(payload);
169
213
  setStateAndRef((prev) => {
214
+ let changed = false;
170
215
  const persistence = { ...prev.persistence };
171
- for (const id of dirtyIds) delete persistence[id];
172
- return { ...prev, persistence };
216
+ for (const id of dirtyIds) {
217
+ if (
218
+ latestSyncSeqByIdRef.current.get(id) !== seq ||
219
+ dirtyIdsRef.current.has(id)
220
+ )
221
+ continue;
222
+ latestSyncSeqByIdRef.current.delete(id);
223
+ delete persistence[id];
224
+ changed = true;
225
+ }
226
+ return changed ? { ...prev, persistence } : prev;
173
227
  });
228
+ } catch (e) {
229
+ setStateAndRef((prev) => {
230
+ let changed = false;
231
+ const persistence = { ...prev.persistence };
232
+ for (const id of dirtyIds) {
233
+ if (
234
+ latestSyncSeqByIdRef.current.get(id) !== seq ||
235
+ dirtyIdsRef.current.has(id)
236
+ )
237
+ continue;
238
+ latestSyncSeqByIdRef.current.delete(id);
239
+ persistence[id] = { isPending: false, error: e };
240
+ changed = true;
241
+ }
242
+ return changed ? { ...prev, persistence } : prev;
243
+ });
244
+ } finally {
245
+ inFlightPersistenceRef.current -= 1;
246
+ const next =
247
+ outgoingQueueRef.current.shift() ??
248
+ (adapterRef.current && dirtyIdsRef.current.size > 0
249
+ ? takeDirtyBatch(adapterRef.current)
250
+ : undefined);
251
+ if (next) {
252
+ if (debounceTimerRef.current !== undefined) {
253
+ clearTimeout(debounceTimerRef.current);
254
+ debounceTimerRef.current = undefined;
255
+ }
256
+ runPersistenceRef.current(next);
257
+ } else if (inFlightPersistenceRef.current === 0) {
258
+ for (const resolve of flushResolversRef.current) resolve();
259
+ flushResolversRef.current = [];
260
+ }
174
261
  }
175
- } catch (e) {
176
- if (syncSeqRef.current === seq) {
177
- hasPendingLocalChangeRef.current = false;
178
- setStateAndRef((prev) => ({
179
- ...prev,
180
- persistence: {
181
- ...prev.persistence,
182
- ...Object.fromEntries(
183
- [...dirtyIds].map((id) => [id, { isPending: false, error: e }]),
184
- ),
185
- },
186
- }));
187
- }
188
- } finally {
189
- if (dirtyIdsRef.current.size > 0 && adapterRef.current) {
190
- runPersistence();
191
- } else {
192
- for (const resolve of flushResolversRef.current) resolve();
193
- flushResolversRef.current = [];
194
- }
262
+ },
263
+ [setStateAndRef, takeDirtyBatch],
264
+ );
265
+ runPersistenceRef.current = (nextBatch) => {
266
+ void runPersistence(nextBatch);
267
+ };
268
+
269
+ const flushIfPending = useCallback(() => {
270
+ if (debounceTimerRef.current !== undefined) {
271
+ clearTimeout(debounceTimerRef.current);
272
+ debounceTimerRef.current = undefined;
195
273
  }
196
- }, [exportState, setStateAndRef]);
274
+ if (adapterRef.current) enqueuePersistence(adapterRef.current);
275
+ }, [enqueuePersistence]);
197
276
 
198
277
  const schedulePersistence = useCallback(
199
278
  (id: string) => {
@@ -204,17 +283,17 @@ const useInteractablesResource = ({
204
283
  }
205
284
  debounceTimerRef.current = setTimeout(() => {
206
285
  debounceTimerRef.current = undefined;
207
- if (!hasPendingLocalChangeRef.current) {
208
- runPersistence();
286
+ if (inFlightPersistenceRef.current === 0 && adapterRef.current) {
287
+ enqueuePersistence(adapterRef.current);
209
288
  } else {
210
289
  debounceTimerRef.current = setTimeout(() => {
211
290
  debounceTimerRef.current = undefined;
212
- runPersistence();
291
+ if (adapterRef.current) enqueuePersistence(adapterRef.current);
213
292
  }, PERSISTENCE_DEBOUNCE_MS);
214
293
  }
215
294
  }, PERSISTENCE_DEBOUNCE_MS);
216
295
  },
217
- [runPersistence],
296
+ [enqueuePersistence],
218
297
  );
219
298
 
220
299
  const restorePersistedState = useCallback(
@@ -281,10 +360,11 @@ const useInteractablesResource = ({
281
360
 
282
361
  const setPersistenceAdapter = useCallback(
283
362
  (adapter: Unstable_InteractablePersistenceAdapter | undefined) => {
363
+ if (adapterRef.current !== adapter) flushIfPending();
284
364
  adapterRef.current = adapter;
285
365
  if (adapter) void loadFromAdapter(adapter);
286
366
  },
287
- [loadFromAdapter],
367
+ [flushIfPending, loadFromAdapter],
288
368
  );
289
369
 
290
370
  const getCurrentThreadId = useCallback((): string | undefined => {
@@ -309,7 +389,7 @@ const useInteractablesResource = ({
309
389
  setPersistenceAdapter(persistence);
310
390
  return () => {
311
391
  if (adapterRef.current === persistence) {
312
- adapterRef.current = undefined;
392
+ setPersistenceAdapter(undefined);
313
393
  }
314
394
  };
315
395
  }, [persistence, setPersistenceAdapter]);
@@ -319,25 +399,17 @@ const useInteractablesResource = ({
319
399
  clearTimeout(debounceTimerRef.current);
320
400
  debounceTimerRef.current = undefined;
321
401
  }
322
- if (!adapterRef.current) return;
323
- if (!hasPendingLocalChangeRef.current && dirtyIdsRef.current.size === 0)
324
- return;
402
+ const hasWork =
403
+ inFlightPersistenceRef.current > 0 ||
404
+ dirtyIdsRef.current.size > 0 ||
405
+ outgoingQueueRef.current.length > 0;
406
+ if (!hasWork) return;
325
407
  const p = new Promise<void>((resolve) => {
326
408
  flushResolversRef.current.push(resolve);
327
409
  });
328
- if (!hasPendingLocalChangeRef.current) {
329
- runPersistence();
330
- }
410
+ if (adapterRef.current) enqueuePersistence(adapterRef.current);
331
411
  return p;
332
- }, [runPersistence]);
333
-
334
- const flushIfPending = useCallback(() => {
335
- if (adapterRef.current && debounceTimerRef.current !== undefined) {
336
- clearTimeout(debounceTimerRef.current);
337
- debounceTimerRef.current = undefined;
338
- runPersistence();
339
- }
340
- }, [runPersistence]);
412
+ }, [enqueuePersistence]);
341
413
 
342
414
  const setDefState = useCallback(
343
415
  (id: string, updater: (prev: unknown) => unknown) => {
@@ -384,12 +456,52 @@ const useInteractablesResource = ({
384
456
  );
385
457
 
386
458
  useEffect(() => {
387
- for (const cb of subscribersRef.current) cb();
459
+ notifyStateSubscribers(subscribersRef.current);
388
460
  }, [state]);
389
461
 
390
- useEffect(() => {
391
- return clientRef.current!.modelContext().register(provider);
392
- }, [clientRef, provider]);
462
+ useAssistantScopeEffect(
463
+ "modelContext",
464
+ () => clientRef.current!.modelContext().register(provider),
465
+ [provider],
466
+ );
467
+
468
+ const installUpdateToolUI = useCallback(
469
+ (name: string, entry: UpdateToolUIEntry) => {
470
+ const toolsAccessor = clientRef.current?.tools;
471
+ if (!toolsAccessor || toolsAccessor.source == null) return false;
472
+ entry.unsubscribe = toolsAccessor().setToolUI(
473
+ interactableToolName(name),
474
+ entry.render,
475
+ { standalone: true },
476
+ );
477
+ return true;
478
+ },
479
+ [clientRef],
480
+ );
481
+
482
+ // register() installs update-tool UIs against the tools instance bound at
483
+ // call time; this re-applies the retained entries when that instance is
484
+ // structurally replaced and installs entries recorded while no tools
485
+ // scope was available. Each re-apply releases the entry's previous
486
+ // install first, so it is an orphaned no-op against a replaced instance
487
+ // and an idempotent replacement against a live one.
488
+ useAssistantScopeEffect(
489
+ "tools",
490
+ () => {
491
+ for (const [name, entry] of updateToolUIsRef.current) {
492
+ entry.unsubscribe?.();
493
+ entry.unsubscribe = undefined;
494
+ installUpdateToolUI(name, entry);
495
+ }
496
+ return () => {
497
+ for (const entry of updateToolUIsRef.current.values()) {
498
+ entry.unsubscribe?.();
499
+ entry.unsubscribe = undefined;
500
+ }
501
+ };
502
+ },
503
+ [installUpdateToolUI],
504
+ );
393
505
 
394
506
  const register = useCallback(
395
507
  (def: InternalInteractableRegistration) => {
@@ -423,36 +535,35 @@ const useInteractablesResource = ({
423
535
 
424
536
  let releaseUpdateToolUI: (() => void) | undefined;
425
537
  if (def.updateRender) {
426
- const toolsAccessor = clientRef.current?.tools;
427
- if (toolsAccessor && toolsAccessor.source != null) {
428
- const toolName = interactableToolName(def.name);
429
- const existing = updateToolUIsRef.current.get(def.name);
430
- if (existing) {
431
- existing.count++;
432
- } else {
433
- updateToolUIsRef.current.set(def.name, {
434
- count: 1,
435
- unsubscribe: toolsAccessor().setToolUI(
436
- toolName,
437
- def.updateRender,
438
- { standalone: true },
439
- ),
440
- });
441
- }
442
- releaseUpdateToolUI = () => {
443
- const entry = updateToolUIsRef.current.get(def.name);
444
- if (!entry) return;
445
- if (--entry.count === 0) {
446
- updateToolUIsRef.current.delete(def.name);
447
- entry.unsubscribe();
448
- }
449
- };
450
- } else if (process.env.NODE_ENV !== "production") {
538
+ const existing = updateToolUIsRef.current.get(def.name);
539
+ const entry = existing ?? {
540
+ count: 0,
541
+ render: def.updateRender,
542
+ unsubscribe: undefined,
543
+ };
544
+ entry.count++;
545
+ if (!existing) updateToolUIsRef.current.set(def.name, entry);
546
+
547
+ if (
548
+ !entry.unsubscribe &&
549
+ !installUpdateToolUI(def.name, entry) &&
550
+ process.env.NODE_ENV !== "production"
551
+ ) {
451
552
  console.warn(
452
553
  `[Interactables] "${def.name}" supplied an updateRender, but no ` +
453
- `tools scope is available to install it into.`,
554
+ `tools scope is available yet; it will be installed once one appears.`,
454
555
  );
455
556
  }
557
+
558
+ releaseUpdateToolUI = () => {
559
+ const entry = updateToolUIsRef.current.get(def.name);
560
+ if (!entry) return;
561
+ if (--entry.count === 0) {
562
+ updateToolUIsRef.current.delete(def.name);
563
+ entry.unsubscribe?.();
564
+ entry.unsubscribe = undefined;
565
+ }
566
+ };
456
567
  }
457
568
 
458
569
  // The same id re-registers once per anchor (its create call + each update_*).
@@ -552,7 +663,13 @@ const useInteractablesResource = ({
552
663
  });
553
664
  };
554
665
  },
555
- [flushIfPending, clientRef, getCurrentThreadId, setStateAndRef],
666
+ [
667
+ flushIfPending,
668
+ clientRef,
669
+ getCurrentThreadId,
670
+ installUpdateToolUI,
671
+ setStateAndRef,
672
+ ],
556
673
  );
557
674
 
558
675
  return {