@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
@@ -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 {