@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
@@ -1,44 +1,53 @@
1
1
  import {
2
2
  type FC,
3
3
  type RefObject,
4
- useCallback,
5
- useRef,
6
4
  useEffect,
7
- useEffectEvent,
8
5
  useLayoutEffect,
6
+ useMemo,
7
+ useRef,
9
8
  memo,
10
9
  type PropsWithChildren,
11
10
  type ComponentType,
12
- useMemo,
13
11
  Fragment,
14
12
  } from "react";
15
- import { type UseBoundStore, type StoreApi, create } from "zustand";
16
- import { useAui } from "@assistant-ui/store";
13
+ import { create } from "zustand";
14
+ import { useResources, withKey } from "@assistant-ui/tap";
15
+ import type { AssistantClient } from "@assistant-ui/store";
17
16
  import { ThreadListItemRuntimeProvider } from "../providers/ThreadListItemRuntimeProvider";
18
17
  import type { ThreadRuntimeCore } from "../../runtime/interfaces/thread-runtime-core";
19
18
  import type { ThreadListRuntimeCore } from "../../runtime/interfaces/thread-list-runtime-core";
20
- import type { AssistantRuntime } from "../../runtime/api/assistant-runtime";
21
19
  import type { Unsubscribe } from "../../types/unsubscribe";
22
20
  import { BaseSubscribable } from "../../subscribable/subscribable";
23
- import {
24
- getThreadRuntimeCoreIsRunning,
25
- type ThreadRuntimeImpl,
26
- } from "../../runtime/api/thread-runtime";
21
+ import { getThreadRuntimeCoreIsRunning } from "../../runtime/api/thread-runtime";
27
22
  import { ThreadListRuntimeImpl } from "../../runtime/api/thread-list-runtime";
28
-
29
- type RemoteThreadListHook = () => AssistantRuntime;
23
+ import { invalidateThreadRuntime } from "../../runtime/utils/thread-runtime-lifecycle";
24
+ import {
25
+ useRuntimeAdapters,
26
+ type RuntimeAdapters,
27
+ } from "./RuntimeAdapterProvider";
28
+ import {
29
+ RemoteThreadResource,
30
+ type RemoteThreadListHook,
31
+ } from "./RemoteThreadResource";
30
32
 
31
33
  type RemoteThreadListHookInstance = {
32
34
  runtime?: ThreadRuntimeCore | undefined;
33
- // A runtime riding across a restart stays readable, but only counts as
34
- // attached once a binder of the current generation re-publishes it.
35
35
  publishedGeneration?: number | undefined;
36
- // Part of the binder's React key, so only a bump remounts the hook.
37
36
  generation: number;
38
37
  isRunning: boolean;
39
38
  unsubscribeRunning?: Unsubscribe | undefined;
40
39
  };
41
40
 
41
+ type AdapterSnapshot = {
42
+ defaultAdapters: RuntimeAdapters | null;
43
+ threadAdapters: ReadonlyMap<string, RuntimeAdapters | null>;
44
+ };
45
+
46
+ type HostSnapshot = {
47
+ threads: readonly { id: string; generation: number }[];
48
+ hookEpoch: number;
49
+ };
50
+
42
51
  const ProviderRenderDetector: FC<{
43
52
  detectorRef: RefObject<boolean>;
44
53
  }> = ({ detectorRef }) => {
@@ -47,15 +56,23 @@ const ProviderRenderDetector: FC<{
47
56
  }, [detectorRef]);
48
57
  return null;
49
58
  };
59
+
50
60
  export class RemoteThreadListHookInstanceManager extends BaseSubscribable {
51
- private useRuntimeHook: UseBoundStore<
52
- StoreApi<{ useRuntime: RemoteThreadListHook }>
53
- >;
61
+ private runtimeHook: RemoteThreadListHook;
62
+ private readonly adapterStore = create<AdapterSnapshot>(() => ({
63
+ defaultAdapters: null,
64
+ threadAdapters: new Map(),
65
+ }));
66
+ private readonly hostStore = create<HostSnapshot>(() => ({
67
+ threads: [],
68
+ hookEpoch: 0,
69
+ }));
70
+ private readonly pendingThreadAdapters = new Map<
71
+ string,
72
+ RuntimeAdapters | null
73
+ >();
54
74
  private instances = new Map<string, RemoteThreadListHookInstance>();
55
- // Manager-wide so it survives instance deletion: a stop and start within one
56
- // React commit must not reuse a binder key.
57
75
  private nextGeneration = 0;
58
- private useAliveThreadsKeysChanged = create(() => ({}));
59
76
  private parent: ThreadListRuntimeCore;
60
77
 
61
78
  constructor(
@@ -64,7 +81,7 @@ export class RemoteThreadListHookInstanceManager extends BaseSubscribable {
64
81
  ) {
65
82
  super();
66
83
  this.parent = parent;
67
- this.useRuntimeHook = create(() => ({ useRuntime: runtimeHook }));
84
+ this.runtimeHook = runtimeHook;
68
85
  }
69
86
 
70
87
  private _whenRuntimeAttached(threadId: string) {
@@ -78,7 +95,7 @@ export class RemoteThreadListHookInstanceManager extends BaseSubscribable {
78
95
  !instance.runtime ||
79
96
  instance.publishedGeneration !== instance.generation
80
97
  ) {
81
- return; // not yet published by the current generation's binder
98
+ return;
82
99
  } else {
83
100
  dispose();
84
101
  resolve(instance.runtime);
@@ -91,11 +108,12 @@ export class RemoteThreadListHookInstanceManager extends BaseSubscribable {
91
108
 
92
109
  public startThreadRuntime(threadId: string) {
93
110
  if (!this.instances.has(threadId)) {
111
+ const generation = this.nextGeneration++;
94
112
  this.instances.set(threadId, {
95
- generation: this.nextGeneration++,
113
+ generation,
96
114
  isRunning: false,
97
115
  });
98
- this.useAliveThreadsKeysChanged.setState({}, true);
116
+ this._syncHostThreads();
99
117
  }
100
118
 
101
119
  return this._whenRuntimeAttached(threadId);
@@ -105,8 +123,9 @@ export class RemoteThreadListHookInstanceManager extends BaseSubscribable {
105
123
  const instance = this.instances.get(threadId);
106
124
  if (!instance) return this.startThreadRuntime(threadId);
107
125
 
126
+ if (instance.runtime) invalidateThreadRuntime(instance.runtime);
108
127
  instance.generation = this.nextGeneration++;
109
- this.useAliveThreadsKeysChanged.setState({}, true);
128
+ this._syncHostThreads();
110
129
  this._notifySubscribers();
111
130
 
112
131
  return this._whenRuntimeAttached(threadId);
@@ -124,29 +143,27 @@ export class RemoteThreadListHookInstanceManager extends BaseSubscribable {
124
143
 
125
144
  private runningSubscribers = new Set<() => void>();
126
145
 
127
- /**
128
- * Fires when any thread crosses the running boundary. Separate from the
129
- * general subscription so a run does not push the thread list through the
130
- * channel that resolves pending runtime attachments.
131
- */
132
146
  public __internal_subscribeRunningChanged(callback: () => void): Unsubscribe {
133
147
  this.runningSubscribers.add(callback);
134
148
  return () => this.runningSubscribers.delete(callback);
135
149
  }
136
150
 
151
+ private _publish = (
152
+ threadId: string,
153
+ runtime: ThreadRuntimeCore,
154
+ generation: number,
155
+ ) => {
156
+ this._publishThreadRuntime(threadId, runtime, generation);
157
+ };
158
+
137
159
  private _publishThreadRuntime(
138
160
  threadId: string,
139
161
  runtime: ThreadRuntimeCore,
140
162
  generation: number,
141
163
  ) {
142
164
  const instance = this.instances.get(threadId);
143
- if (!instance)
144
- throw new Error(
145
- `Thread "${threadId}" runtime binding not found. This is a bug in assistant-ui.`,
146
- );
165
+ if (!instance) return;
147
166
 
148
- // An outgoing binder outlives its generation until React commits the key
149
- // change, and must not publish over the incoming one.
150
167
  if (instance.generation !== generation) return;
151
168
 
152
169
  const previousRuntime = instance.runtime;
@@ -158,8 +175,6 @@ export class RemoteThreadListHookInstanceManager extends BaseSubscribable {
158
175
  this._notifySubscribers();
159
176
  }
160
177
 
161
- // Run state changes far more often than the thread list does, so the list is
162
- // only notified when a thread crosses the running boundary.
163
178
  private _trackRunning(instance: RemoteThreadListHookInstance) {
164
179
  instance.unsubscribeRunning?.();
165
180
 
@@ -186,90 +201,111 @@ export class RemoteThreadListHookInstanceManager extends BaseSubscribable {
186
201
  }
187
202
 
188
203
  public stopThreadRuntime(threadId: string) {
189
- this.instances.get(threadId)?.unsubscribeRunning?.();
204
+ const instance = this.instances.get(threadId);
205
+ if (instance?.runtime) invalidateThreadRuntime(instance.runtime);
206
+ instance?.unsubscribeRunning?.();
190
207
  this.instances.delete(threadId);
191
- this.useAliveThreadsKeysChanged.setState({}, true);
208
+ this.pendingThreadAdapters.delete(threadId);
209
+ this._syncHostThreads();
192
210
  this._notifySubscribers();
193
211
  }
194
212
 
195
213
  public setRuntimeHook(newRuntimeHook: RemoteThreadListHook) {
196
- const prevRuntimeHook = this.useRuntimeHook.getState().useRuntime;
197
- if (prevRuntimeHook !== newRuntimeHook) {
198
- this.useRuntimeHook.setState({ useRuntime: newRuntimeHook }, true);
199
- }
214
+ if (this.runtimeHook === newRuntimeHook) return;
215
+ this.runtimeHook = newRuntimeHook;
216
+ this.hostStore.setState(
217
+ (state) => ({ ...state, hookEpoch: state.hookEpoch + 1 }),
218
+ true,
219
+ );
200
220
  }
201
221
 
202
- // Rendered as a child of the user's Provider so the runtime hook can
203
- // read context the Provider injects (e.g. RuntimeAdapterProvider).
204
- private _RuntimeBinder: FC<
205
- PropsWithChildren<{ threadId: string; generation: number }>
206
- > = ({ threadId, generation, children }) => {
207
- const { useRuntime } = this.useRuntimeHook();
208
- const runtime = useRuntime();
209
-
210
- const threadBinding = (runtime.thread as ThreadRuntimeImpl)
211
- .__internal_threadBinding;
212
-
213
- const updateRuntime = useCallback(() => {
214
- this._publishThreadRuntime(
215
- threadId,
216
- threadBinding.getState(),
217
- generation,
218
- );
219
- }, [threadId, generation, threadBinding]);
220
-
221
- const isMounted = useRef(false);
222
- if (!isMounted.current) {
223
- updateRuntime();
224
- }
225
-
226
- useEffect(() => {
227
- isMounted.current = true;
228
- updateRuntime();
229
- return threadBinding.outerSubscribe(updateRuntime);
230
- }, [threadBinding, updateRuntime]);
231
-
232
- const aui = useAui();
233
- const initPromiseRef = useRef<Promise<unknown> | undefined>(undefined);
234
- const hasInitializedRef = useRef(false);
222
+ public __internal_setDefaultAdapters(adapters: RuntimeAdapters | null) {
223
+ const current = this.adapterStore.getState();
224
+ if (current.defaultAdapters === adapters) return;
225
+ this.adapterStore.setState({ ...current, defaultAdapters: adapters }, true);
226
+ }
235
227
 
236
- useEffect(() => {
237
- const runtimeCore = threadBinding.getState();
238
- const setGetInitializePromise = (runtimeCore as Record<string, unknown>)
239
- .__internal_setGetInitializePromise;
240
- if (typeof setGetInitializePromise === "function") {
241
- setGetInitializePromise.call(runtimeCore, () => initPromiseRef.current);
242
- }
243
- }, [threadBinding]);
228
+ public __internal_setThreadAdapters(
229
+ threadId: string,
230
+ adapters: RuntimeAdapters | null,
231
+ ) {
232
+ const current = this.adapterStore.getState();
233
+ const next = new Map(current.threadAdapters);
234
+ if (adapters === null) next.delete(threadId);
235
+ else next.set(threadId, adapters);
236
+ this.adapterStore.setState({ ...current, threadAdapters: next }, true);
237
+ }
244
238
 
245
- const handleInitialize = useEffectEvent(() => {
246
- if (hasInitializedRef.current) return;
239
+ public __internal_dispose() {
240
+ for (const threadId of [...this.instances.keys()]) {
241
+ this.stopThreadRuntime(threadId);
242
+ }
243
+ }
247
244
 
248
- const state = aui.threadListItem.getState();
249
- if (state.status !== "new") return;
250
- hasInitializedRef.current = true;
245
+ private _syncHostThreads() {
246
+ this.hostStore.setState(
247
+ (state) => ({
248
+ ...state,
249
+ threads: Array.from(this.instances.entries()).map(
250
+ ([id, { generation }]) => ({ id, generation }),
251
+ ),
252
+ }),
253
+ true,
254
+ );
255
+ }
251
256
 
252
- initPromiseRef.current = aui.threadListItem.initialize();
257
+ public __internal_useHost(parentClient: AssistantClient) {
258
+ const { threads, hookEpoch } = this.hostStore();
259
+ const adapters = this.adapterStore();
260
+ const runtimeHook = this.runtimeHook;
261
+ return useResources(
262
+ threads.map(({ id, generation }) => {
263
+ const threadAdapters = this.pendingThreadAdapters.has(id)
264
+ ? this.pendingThreadAdapters.get(id)!
265
+ : (adapters.threadAdapters.get(id) ?? adapters.defaultAdapters);
266
+ return withKey(
267
+ `${id}:${generation}:${hookEpoch}`,
268
+ RemoteThreadResource({
269
+ threadId: id,
270
+ generation,
271
+ parentList: this.parent,
272
+ runtimeHook,
273
+ parentClient,
274
+ adapters: threadAdapters,
275
+ publish: this._publish,
276
+ }),
277
+ );
278
+ }),
279
+ );
280
+ }
253
281
 
254
- const dispose = runtime.thread.unstable_on("runEnd", () => {
255
- dispose();
256
- aui.threadListItem.generateTitle();
257
- });
258
- });
282
+ public __internal_RenderThreadRuntimes: FC<{
283
+ provider: ComponentType<PropsWithChildren>;
284
+ }> = ({ provider }) => {
285
+ this.hostStore();
259
286
 
260
- useEffect(() => {
261
- hasInitializedRef.current = false;
262
- return runtime.threads.main.unstable_on("initialize", handleInitialize);
263
- }, [runtime]);
287
+ return Array.from(this.instances.entries()).map(
288
+ ([threadId, { generation }]) => (
289
+ <this._OuterActiveThreadProvider
290
+ key={`${threadId}:${generation}`}
291
+ threadId={threadId}
292
+ provider={provider}
293
+ />
294
+ ),
295
+ );
296
+ };
264
297
 
265
- return <>{children}</>;
298
+ public __internal_Host: FC<{ parentClient: AssistantClient }> = ({
299
+ parentClient,
300
+ }) => {
301
+ this.__internal_useHost(parentClient);
302
+ return null;
266
303
  };
267
304
 
268
305
  private _OuterActiveThreadProvider: FC<{
269
306
  threadId: string;
270
- generation: number;
271
307
  provider: ComponentType<PropsWithChildren>;
272
- }> = memo(({ threadId, generation, provider: Provider }) => {
308
+ }> = memo(({ threadId, provider: Provider }) => {
273
309
  const runtime = useMemo(
274
310
  () => new ThreadListRuntimeImpl(this.parent).getItemById(threadId),
275
311
  [threadId],
@@ -283,7 +319,7 @@ export class RemoteThreadListHookInstanceManager extends BaseSubscribable {
283
319
  console.warn(
284
320
  "RemoteThreadListAdapter.unstable_Provider did not render its `children` synchronously. " +
285
321
  "Render `children` on first commit; deferring them behind a loading state, Suspense boundary, " +
286
- "or `useEffect` gate strands the runtime binder and leaves the thread without context.",
322
+ "or `useEffect` gate strands the runtime host and leaves the thread without context.",
287
323
  );
288
324
  }
289
325
  }, 100);
@@ -295,28 +331,27 @@ export class RemoteThreadListHookInstanceManager extends BaseSubscribable {
295
331
  return (
296
332
  <ThreadListItemRuntimeProvider runtime={runtime}>
297
333
  <Provider>
298
- <this._RuntimeBinder threadId={threadId} generation={generation}>
299
- <ProviderRenderDetector detectorRef={detectorRef} />
300
- </this._RuntimeBinder>
334
+ <this._AdapterSink threadId={threadId} detectorRef={detectorRef} />
301
335
  </Provider>
302
336
  </ThreadListItemRuntimeProvider>
303
337
  );
304
338
  });
305
339
 
306
- public __internal_RenderThreadRuntimes: FC<{
307
- provider: ComponentType<PropsWithChildren>;
308
- }> = ({ provider }) => {
309
- this.useAliveThreadsKeysChanged(); // trigger re-render on alive threads change
310
-
311
- return Array.from(this.instances.entries()).map(
312
- ([threadId, { generation }]) => (
313
- <this._OuterActiveThreadProvider
314
- key={`${threadId}:${generation}`}
315
- threadId={threadId}
316
- generation={generation}
317
- provider={provider}
318
- />
319
- ),
320
- );
340
+ private _AdapterSink: FC<{
341
+ threadId: string;
342
+ detectorRef: RefObject<boolean>;
343
+ }> = ({ threadId, detectorRef }) => {
344
+ const adapters = useRuntimeAdapters();
345
+ this.pendingThreadAdapters.set(threadId, adapters);
346
+ useLayoutEffect(() => {
347
+ this.__internal_setThreadAdapters(threadId, adapters);
348
+ return () => {
349
+ if (this.pendingThreadAdapters.get(threadId) === adapters) {
350
+ this.pendingThreadAdapters.delete(threadId);
351
+ }
352
+ this.__internal_setThreadAdapters(threadId, null);
353
+ };
354
+ }, [threadId, adapters]);
355
+ return <ProviderRenderDetector detectorRef={detectorRef} />;
321
356
  };
322
357
  }
@@ -15,10 +15,11 @@ import {
15
15
  updateStatusReducer,
16
16
  } from "../../runtimes/remote-thread-list/remote-thread-state";
17
17
  import type {
18
+ RemoteThreadListAdapter,
18
19
  RemoteThreadListOptions,
19
- RemoteThreadListProviderComponent,
20
20
  } from "../../runtimes/remote-thread-list/types";
21
21
  import { RemoteThreadListHookInstanceManager } from "./RemoteThreadListHookInstanceManager";
22
+ import { isTitleSourceMessage } from "./RemoteThreadResource";
22
23
  import {
23
24
  type ComponentType,
24
25
  type FC,
@@ -27,15 +28,12 @@ import {
27
28
  useEffect,
28
29
  useId,
29
30
  } from "react";
31
+ import { useAui } from "@assistant-ui/store";
30
32
  import { create } from "zustand";
31
33
  import { AssistantMessageStream } from "assistant-stream";
32
34
  import type { ModelContextProvider } from "../../model-context/types";
33
35
  import { RuntimeAdapterProvider } from "./RuntimeAdapterProvider";
34
-
35
- const asProviderComponent = (
36
- provider: RemoteThreadListProviderComponent | undefined,
37
- ): ComponentType<PropsWithChildren> =>
38
- (provider ?? Fragment) as ComponentType<PropsWithChildren>;
36
+ import { useStableRuntimeAdapters } from "./useRuntimeAdapters";
39
37
 
40
38
  const threadNotFoundError = (threadIdOrRemoteId: string, action: string) =>
41
39
  new Error(`Thread "${threadIdOrRemoteId}" not found while ${action}.`);
@@ -55,6 +53,7 @@ export class RemoteThreadListThreadListRuntimeCore
55
53
  {
56
54
  private _options!: RemoteThreadListOptions;
57
55
  private readonly _hookManager: RemoteThreadListHookInstanceManager;
56
+ private readonly _runtimeAdapters: { modelContext: ModelContextProvider };
58
57
 
59
58
  private _loadThreadsPromise: Promise<void> | undefined;
60
59
  private _loadMorePromise: Promise<void> | undefined;
@@ -74,6 +73,42 @@ export class RemoteThreadListThreadListRuntimeCore
74
73
  threadData: {},
75
74
  });
76
75
 
76
+ private readonly _useAdaptersProvider: FC<PropsWithChildren> = ({
77
+ children,
78
+ }) => {
79
+ const useAdapters = this._options.adapter.unstable_useAdapters;
80
+ if (useAdapters === undefined) return children;
81
+ return (
82
+ <this._SynthesizedAdapters useAdapters={useAdapters}>
83
+ {children}
84
+ </this._SynthesizedAdapters>
85
+ );
86
+ };
87
+
88
+ private readonly _SynthesizedAdapters: FC<
89
+ PropsWithChildren<{
90
+ useAdapters: NonNullable<RemoteThreadListAdapter["unstable_useAdapters"]>;
91
+ }>
92
+ > = ({ useAdapters, children }) => {
93
+ const adapters = useStableRuntimeAdapters(useAdapters());
94
+ if (adapters == null) return children;
95
+ return (
96
+ <RuntimeAdapterProvider adapters={adapters}>
97
+ {children}
98
+ </RuntimeAdapterProvider>
99
+ );
100
+ };
101
+
102
+ private resolveProvider(
103
+ adapter: RemoteThreadListAdapter,
104
+ ): ComponentType<PropsWithChildren> {
105
+ if (adapter.unstable_Provider !== undefined) {
106
+ return adapter.unstable_Provider as ComponentType<PropsWithChildren>;
107
+ }
108
+ if (adapter.unstable_useAdapters === undefined) return Fragment;
109
+ return this._useAdaptersProvider;
110
+ }
111
+
77
112
  public get threadItems() {
78
113
  return this._state.value.threadData;
79
114
  }
@@ -183,28 +218,27 @@ export class RemoteThreadListThreadListRuntimeCore
183
218
  return dedup;
184
219
  }
185
220
 
186
- private readonly contextProvider: ModelContextProvider;
187
-
188
221
  constructor(
189
222
  options: RemoteThreadListOptions,
190
223
  contextProvider: ModelContextProvider,
191
224
  ) {
192
225
  super();
193
- this.contextProvider = contextProvider;
194
226
 
195
227
  this._state.subscribe(() => {
196
228
  this._notifySubscribers();
197
229
  this._notifyThreadIdChange();
198
230
  });
231
+ this._runtimeAdapters = { modelContext: contextProvider };
199
232
  this._hookManager = new RemoteThreadListHookInstanceManager(
200
233
  options.runtimeHook,
201
234
  this,
202
235
  );
236
+ this._hookManager.__internal_setDefaultAdapters(this._runtimeAdapters);
203
237
  this._hookManager.__internal_subscribeRunningChanged(() =>
204
238
  this._notifySubscribers(),
205
239
  );
206
240
  this.useProvider = create(() => ({
207
- Provider: asProviderComponent(options.adapter.unstable_Provider),
241
+ Provider: this.resolveProvider(options.adapter),
208
242
  }));
209
243
  this.__internal_setOptions(options);
210
244
  this.switchToNewThread();
@@ -225,7 +259,7 @@ export class RemoteThreadListThreadListRuntimeCore
225
259
 
226
260
  this._options = options;
227
261
 
228
- const Provider = asProviderComponent(options.adapter.unstable_Provider);
262
+ const Provider = this.resolveProvider(options.adapter);
229
263
  if (Provider !== this.useProvider.getState().Provider) {
230
264
  this.useProvider.setState({ Provider }, true);
231
265
  }
@@ -536,7 +570,7 @@ export class RemoteThreadListThreadListRuntimeCore
536
570
  if (generation !== this._switchGeneration) return;
537
571
  }
538
572
 
539
- const state = this._state.value;
573
+ const state = this._state.baseValue;
540
574
  let id: string | undefined = this._state.value.newThreadId;
541
575
  if (id === undefined) {
542
576
  do {
@@ -635,7 +669,10 @@ export class RemoteThreadListThreadListRuntimeCore
635
669
  const runtimeCore = this._hookManager.getThreadRuntimeCore(data.id);
636
670
  if (!runtimeCore) return; // thread is no longer running
637
671
 
638
- const messages = runtimeCore.messages;
672
+ // Incomplete assistant turns (running status, possibly empty content)
673
+ // would make the payload race-dependent; the title reads settled
674
+ // messages only, matching the trigger's readiness gate.
675
+ const messages = runtimeCore.messages.filter(isTitleSourceMessage);
639
676
  const stream = await this._options.adapter.generateTitle(
640
677
  remoteId,
641
678
  messages,
@@ -823,6 +860,10 @@ export class RemoteThreadListThreadListRuntimeCore
823
860
  });
824
861
  }
825
862
 
863
+ public __internal_dispose() {
864
+ this._hookManager.__internal_dispose();
865
+ }
866
+
826
867
  public async detach(threadIdOrRemoteId: string): Promise<void> {
827
868
  const data = this.getItemById(threadIdOrRemoteId);
828
869
  if (!data) throw threadNotFoundError(threadIdOrRemoteId, "detaching it");
@@ -846,18 +887,16 @@ export class RemoteThreadListThreadListRuntimeCore
846
887
 
847
888
  const boundIds = this.useBoundIds();
848
889
  const { Provider } = this.useProvider();
849
-
850
- const adapters = {
851
- modelContext: this.contextProvider,
852
- };
890
+ const aui = useAui();
891
+ const enabled = boundIds.length === 0 || boundIds[0] === id;
853
892
 
854
893
  return (
855
- (boundIds.length === 0 || boundIds[0] === id) && (
856
- // only render if the component is the first one mounted
857
- <RuntimeAdapterProvider adapters={adapters}>
894
+ enabled && (
895
+ <RuntimeAdapterProvider adapters={this._runtimeAdapters}>
858
896
  <this._hookManager.__internal_RenderThreadRuntimes
859
897
  provider={Provider}
860
898
  />
899
+ <this._hookManager.__internal_Host parentClient={aui} />
861
900
  </RuntimeAdapterProvider>
862
901
  )
863
902
  );