@assistant-ui/core 0.3.15 → 0.3.17

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 (455) hide show
  1. package/dist/index.d.ts +2 -2
  2. package/dist/index.js +2 -2
  3. package/dist/index.js.map +1 -1
  4. package/dist/internal.d.ts +8 -2
  5. package/dist/internal.js +9 -3
  6. package/dist/model-context/frame/host.d.ts.map +1 -1
  7. package/dist/model-context/frame/host.js +3 -2
  8. package/dist/model-context/frame/host.js.map +1 -1
  9. package/dist/model-context/frame/provider.d.ts +5 -0
  10. package/dist/model-context/frame/provider.d.ts.map +1 -1
  11. package/dist/model-context/frame/provider.js +141 -28
  12. package/dist/model-context/frame/provider.js.map +1 -1
  13. package/dist/model-context/interactable-composer-metadata.d.ts +1 -1
  14. package/dist/model-context/interactable-composer-metadata.js +1 -1
  15. package/dist/model-context/interactable-composer-metadata.js.map +1 -1
  16. package/dist/model-context/registry.d.ts +2 -2
  17. package/dist/model-context/registry.d.ts.map +1 -1
  18. package/dist/model-context/registry.js +9 -28
  19. package/dist/model-context/registry.js.map +1 -1
  20. package/dist/model-context/tool-call-text.d.ts +26 -0
  21. package/dist/model-context/tool-call-text.d.ts.map +1 -0
  22. package/dist/model-context/tool-call-text.js +18 -0
  23. package/dist/model-context/tool-call-text.js.map +1 -0
  24. package/dist/react/RuntimeAdapter.js +1 -1
  25. package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
  26. package/dist/react/adapters/LocalStorageThreadListAdapter.js +1 -1
  27. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  28. package/dist/react/client/AdaptedRemoteThread.js +1 -1
  29. package/dist/react/client/InMemoryThreadList.d.ts.map +1 -1
  30. package/dist/react/client/InMemoryThreadList.js +25 -21
  31. package/dist/react/client/InMemoryThreadList.js.map +1 -1
  32. package/dist/react/client/Interactables.d.ts.map +1 -1
  33. package/dist/react/client/Interactables.js +60 -178
  34. package/dist/react/client/Interactables.js.map +1 -1
  35. package/dist/react/client/RemoteThreadList.d.ts +15 -0
  36. package/dist/react/client/RemoteThreadList.d.ts.map +1 -1
  37. package/dist/react/client/RemoteThreadList.js +263 -194
  38. package/dist/react/client/RemoteThreadList.js.map +1 -1
  39. package/dist/react/client/Tools.d.ts.map +1 -1
  40. package/dist/react/client/Tools.js +6 -2
  41. package/dist/react/client/Tools.js.map +1 -1
  42. package/dist/react/index.d.ts +4 -2
  43. package/dist/react/index.js +2 -1
  44. package/dist/react/interactables-legacy/Interactables.d.ts.map +1 -1
  45. package/dist/react/interactables-legacy/Interactables.js +60 -178
  46. package/dist/react/interactables-legacy/Interactables.js.map +1 -1
  47. package/dist/react/interactables-shared/useInteractablePersistenceQueue.d.ts +24 -0
  48. package/dist/react/interactables-shared/useInteractablePersistenceQueue.d.ts.map +1 -0
  49. package/dist/react/interactables-shared/useInteractablePersistenceQueue.js +138 -0
  50. package/dist/react/interactables-shared/useInteractablePersistenceQueue.js.map +1 -0
  51. package/dist/react/model-context/toolbox.d.ts +2 -14
  52. package/dist/react/model-context/toolbox.d.ts.map +1 -1
  53. package/dist/react/model-context/toolbox.js +1 -13
  54. package/dist/react/model-context/toolbox.js.map +1 -1
  55. package/dist/react/model-context/useAssistantContext.js +37 -7
  56. package/dist/react/model-context/useAssistantContext.js.map +1 -1
  57. package/dist/react/model-context/useAuiToolOverrides.js +31 -5
  58. package/dist/react/model-context/useAuiToolOverrides.js.map +1 -1
  59. package/dist/react/model-context/useInlineRender.d.ts.map +1 -1
  60. package/dist/react/model-context/useInlineRender.js +10 -36
  61. package/dist/react/model-context/useInlineRender.js.map +1 -1
  62. package/dist/react/primitive-hooks/useMessageError.d.ts.map +1 -1
  63. package/dist/react/primitive-hooks/useMessageError.js +2 -8
  64. package/dist/react/primitive-hooks/useMessageError.js.map +1 -1
  65. package/dist/react/primitive-hooks/useThreadListLoadMore.d.ts.map +1 -1
  66. package/dist/react/primitive-hooks/useThreadListLoadMore.js +2 -4
  67. package/dist/react/primitive-hooks/useThreadListLoadMore.js.map +1 -1
  68. package/dist/react/primitives/composer/ComposerAttachments.d.ts.map +1 -1
  69. package/dist/react/primitives/composer/ComposerAttachments.js +4 -3
  70. package/dist/react/primitives/composer/ComposerAttachments.js.map +1 -1
  71. package/dist/react/primitives/composer/ComposerIf.js.map +1 -1
  72. package/dist/react/primitives/composer/ComposerQueue.d.ts +2 -1
  73. package/dist/react/primitives/composer/ComposerQueue.d.ts.map +1 -1
  74. package/dist/react/primitives/composer/ComposerQueue.js +4 -3
  75. package/dist/react/primitives/composer/ComposerQueue.js.map +1 -1
  76. package/dist/react/primitives/message/MessageAttachments.d.ts.map +1 -1
  77. package/dist/react/primitives/message/MessageAttachments.js +7 -6
  78. package/dist/react/primitives/message/MessageAttachments.js.map +1 -1
  79. package/dist/react/primitives/message/MessageGroupedParts.js +2 -2
  80. package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
  81. package/dist/react/primitives/message/MessageParts.js +3 -3
  82. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  83. package/dist/react/primitives/threadList/ThreadListItems.d.ts.map +1 -1
  84. package/dist/react/primitives/threadList/ThreadListItems.js +5 -4
  85. package/dist/react/primitives/threadList/ThreadListItems.js.map +1 -1
  86. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +7 -5
  87. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  88. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +44 -22
  89. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  90. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +7 -6
  91. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  92. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +102 -117
  93. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  94. package/dist/react/runtimes/RemoteThreadResource.d.ts +1 -6
  95. package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -1
  96. package/dist/react/runtimes/RemoteThreadResource.js +3 -3
  97. package/dist/react/runtimes/RemoteThreadResource.js.map +1 -1
  98. package/dist/react/runtimes/assistant-transport/runManager.d.ts.map +1 -1
  99. package/dist/react/runtimes/assistant-transport/runManager.js +2 -12
  100. package/dist/react/runtimes/assistant-transport/runManager.js.map +1 -1
  101. package/dist/react/runtimes/assistant-transport/useLatestRef.js +2 -2
  102. package/dist/react/runtimes/assistant-transport/useLatestRef.js.map +1 -1
  103. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +3 -10
  104. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  105. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +43 -85
  106. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  107. package/dist/react/runtimes/cloud/auiV0.d.ts +5 -1
  108. package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
  109. package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
  110. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts +29 -0
  111. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts.map +1 -0
  112. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js +159 -0
  113. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js.map +1 -0
  114. package/dist/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.d.ts +12 -0
  115. package/dist/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.d.ts.map +1 -0
  116. package/dist/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.js +10 -0
  117. package/dist/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.js.map +1 -0
  118. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts +1 -9
  119. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  120. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +16 -153
  121. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  122. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js.map +1 -1
  123. package/dist/react/runtimes/createMessageConverter.d.ts +2 -1
  124. package/dist/react/runtimes/createMessageConverter.d.ts.map +1 -1
  125. package/dist/react/runtimes/external-message-converter.d.ts +6 -25
  126. package/dist/react/runtimes/external-message-converter.d.ts.map +1 -1
  127. package/dist/react/runtimes/external-message-converter.js +33 -233
  128. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  129. package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
  130. package/dist/react/runtimes/useRemoteThreadListRuntime.js +14 -6
  131. package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
  132. package/dist/react/types/MessagePartComponentTypes.d.ts +7 -3
  133. package/dist/react/types/MessagePartComponentTypes.d.ts.map +1 -1
  134. package/dist/react/types/scopes/tools.d.ts +2 -0
  135. package/dist/react/types/scopes/tools.d.ts.map +1 -1
  136. package/dist/runtime/api/composer-runtime.d.ts +1 -1
  137. package/dist/runtime/api/composer-runtime.js.map +1 -1
  138. package/dist/runtime/api/message-part-runtime.d.ts +2 -2
  139. package/dist/runtime/api/message-part-runtime.d.ts.map +1 -1
  140. package/dist/runtime/api/message-part-runtime.js +1 -1
  141. package/dist/runtime/api/message-part-runtime.js.map +1 -1
  142. package/dist/runtime/api/thread-list-runtime.d.ts +9 -1
  143. package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
  144. package/dist/runtime/api/thread-list-runtime.js +5 -0
  145. package/dist/runtime/api/thread-list-runtime.js.map +1 -1
  146. package/dist/runtime/api/thread-runtime.d.ts +2 -3
  147. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  148. package/dist/runtime/base/base-composer-runtime-core.d.ts +1 -1
  149. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  150. package/dist/runtime/base/base-composer-runtime-core.js +14 -29
  151. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  152. package/dist/runtime/base/base-thread-runtime-core.d.ts +4 -6
  153. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  154. package/dist/runtime/base/base-thread-runtime-core.js +5 -11
  155. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  156. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +1 -1
  157. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
  158. package/dist/runtime/base/default-thread-composer-runtime-core.js +1 -1
  159. package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
  160. package/dist/runtime/interfaces/composer-runtime-core.d.ts +1 -1
  161. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +14 -2
  162. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
  163. package/dist/runtime/interfaces/thread-runtime-core.d.ts +16 -2
  164. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  165. package/dist/runtime/internal.d.ts +2 -1
  166. package/dist/runtime/internal.js +2 -1
  167. package/dist/runtime/queue/external-thread-queue-adapter.d.ts +1 -1
  168. package/dist/runtime/queue/message-queue.d.ts.map +1 -1
  169. package/dist/runtime/queue/message-queue.js +1 -1
  170. package/dist/runtime/queue/message-queue.js.map +1 -1
  171. package/dist/runtime/queue/queue-item.d.ts +12 -0
  172. package/dist/runtime/queue/queue-item.d.ts.map +1 -0
  173. package/dist/runtime/queue/queue-item.js +6 -0
  174. package/dist/runtime/queue/queue-item.js.map +1 -0
  175. package/dist/runtime/utils/abortable-thread-load.d.ts +15 -0
  176. package/dist/runtime/utils/abortable-thread-load.d.ts.map +1 -0
  177. package/dist/runtime/utils/abortable-thread-load.js +35 -0
  178. package/dist/runtime/utils/abortable-thread-load.js.map +1 -0
  179. package/dist/runtime/utils/attachment-add-operations.d.ts +18 -0
  180. package/dist/runtime/utils/attachment-add-operations.d.ts.map +1 -0
  181. package/dist/runtime/utils/attachment-add-operations.js +43 -0
  182. package/dist/runtime/utils/attachment-add-operations.js.map +1 -0
  183. package/dist/runtime/utils/auto-status.d.ts +7 -2
  184. package/dist/runtime/utils/auto-status.d.ts.map +1 -1
  185. package/dist/runtime/utils/auto-status.js +13 -3
  186. package/dist/runtime/utils/auto-status.js.map +1 -1
  187. package/dist/runtime/utils/external-message-conversion.d.ts +48 -0
  188. package/dist/runtime/utils/external-message-conversion.d.ts.map +1 -0
  189. package/dist/runtime/utils/external-message-conversion.js +222 -0
  190. package/dist/runtime/utils/external-message-conversion.js.map +1 -0
  191. package/dist/runtime/utils/external-store-message.d.ts +2 -1
  192. package/dist/runtime/utils/external-store-message.d.ts.map +1 -1
  193. package/dist/runtime/utils/external-store-message.js +2 -1
  194. package/dist/runtime/utils/external-store-message.js.map +1 -1
  195. package/dist/runtime/utils/message-repository-session.d.ts +30 -0
  196. package/dist/runtime/utils/message-repository-session.d.ts.map +1 -0
  197. package/dist/runtime/utils/message-repository-session.js +130 -0
  198. package/dist/runtime/utils/message-repository-session.js.map +1 -0
  199. package/dist/runtime/utils/message-repository.d.ts.map +1 -1
  200. package/dist/runtime/utils/message-repository.js +3 -4
  201. package/dist/runtime/utils/message-repository.js.map +1 -1
  202. package/dist/runtime/utils/pending-tool-calls.d.ts +20 -0
  203. package/dist/runtime/utils/pending-tool-calls.d.ts.map +1 -0
  204. package/dist/runtime/utils/pending-tool-calls.js +22 -0
  205. package/dist/runtime/utils/pending-tool-calls.js.map +1 -0
  206. package/dist/runtime/utils/resolveToolApprovalResponse.d.ts +6 -3
  207. package/dist/runtime/utils/resolveToolApprovalResponse.d.ts.map +1 -1
  208. package/dist/runtime/utils/resolveToolApprovalResponse.js +12 -3
  209. package/dist/runtime/utils/resolveToolApprovalResponse.js.map +1 -1
  210. package/dist/runtime/utils/thread-message-like.d.ts +3 -10
  211. package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
  212. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  213. package/dist/runtime/utils/tool-call-tree.d.ts +39 -0
  214. package/dist/runtime/utils/tool-call-tree.d.ts.map +1 -0
  215. package/dist/runtime/utils/tool-call-tree.js +85 -0
  216. package/dist/runtime/utils/tool-call-tree.js.map +1 -0
  217. package/dist/runtimes/external-store/external-store-adapter.d.ts +29 -2
  218. package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
  219. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts +2 -5
  220. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  221. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +3 -10
  222. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  223. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +21 -2
  224. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  225. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +154 -46
  226. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  227. package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts +1 -1
  228. package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts.map +1 -1
  229. package/dist/runtimes/inert/InertThreadRuntimeCore.js.map +1 -1
  230. package/dist/runtimes/local/local-thread-runtime-core.d.ts +4 -2
  231. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  232. package/dist/runtimes/local/local-thread-runtime-core.js +23 -3
  233. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  234. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts +12 -1
  235. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts.map +1 -1
  236. package/dist/runtimes/remote-thread-list/remote-thread-state.js +107 -14
  237. package/dist/runtimes/remote-thread-list/remote-thread-state.js.map +1 -1
  238. package/dist/runtimes/remote-thread-list/title.d.ts +9 -0
  239. package/dist/runtimes/remote-thread-list/title.d.ts.map +1 -0
  240. package/dist/runtimes/remote-thread-list/title.js +6 -0
  241. package/dist/runtimes/remote-thread-list/title.js.map +1 -0
  242. package/dist/runtimes/remote-thread-list/types.d.ts +6 -5
  243. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  244. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +31 -8
  245. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
  246. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +98 -59
  247. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
  248. package/dist/store/clients/external-thread.d.ts +1 -1
  249. package/dist/store/clients/external-thread.d.ts.map +1 -1
  250. package/dist/store/clients/external-thread.js +85 -103
  251. package/dist/store/clients/external-thread.js.map +1 -1
  252. package/dist/store/clients/single-thread-list.d.ts.map +1 -1
  253. package/dist/store/clients/single-thread-list.js +2 -2
  254. package/dist/store/clients/single-thread-list.js.map +1 -1
  255. package/dist/store/clients/suggestions.d.ts.map +1 -1
  256. package/dist/store/clients/suggestions.js +33 -12
  257. package/dist/store/clients/suggestions.js.map +1 -1
  258. package/dist/store/clients/thread-message-client.js +1 -1
  259. package/dist/store/clients/thread-selection-events.js +1 -1
  260. package/dist/store/index.d.ts +6 -3
  261. package/dist/store/index.js +2 -1
  262. package/dist/store/internal.d.ts +2 -2
  263. package/dist/store/internal.js +2 -2
  264. package/dist/store/primitive-predicates.d.ts +4 -1
  265. package/dist/store/primitive-predicates.d.ts.map +1 -1
  266. package/dist/store/primitive-predicates.js +9 -1
  267. package/dist/store/primitive-predicates.js.map +1 -1
  268. package/dist/store/runtime-clients/composer-runtime-client.js +1 -1
  269. package/dist/store/runtime-clients/message-runtime-client.js +1 -1
  270. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +1 -1
  271. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
  272. package/dist/store/runtime-clients/thread-list-runtime-client.js +124 -105
  273. package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
  274. package/dist/store/runtime-clients/thread-runtime-client.js +1 -1
  275. package/dist/store/runtime-clients/useSubscribable.d.ts +3 -1
  276. package/dist/store/runtime-clients/useSubscribable.d.ts.map +1 -1
  277. package/dist/store/runtime-clients/useSubscribable.js +1 -1
  278. package/dist/store/runtime-clients/useSubscribable.js.map +1 -1
  279. package/dist/store/scope-registration.d.ts +1 -1
  280. package/dist/store/scopes/composer.d.ts +2 -1
  281. package/dist/store/scopes/composer.d.ts.map +1 -1
  282. package/dist/store/scopes/message.d.ts +1 -1
  283. package/dist/store/scopes/part.d.ts +6 -3
  284. package/dist/store/scopes/part.d.ts.map +1 -1
  285. package/dist/store/scopes/queue-item.d.ts +2 -9
  286. package/dist/store/scopes/queue-item.d.ts.map +1 -1
  287. package/dist/store/scopes/queue-item.js +0 -6
  288. package/dist/subscribable/subscribable.d.ts +8 -1
  289. package/dist/subscribable/subscribable.d.ts.map +1 -1
  290. package/dist/subscribable/subscribable.js +24 -16
  291. package/dist/subscribable/subscribable.js.map +1 -1
  292. package/dist/types/message.d.ts +47 -4
  293. package/dist/types/message.d.ts.map +1 -1
  294. package/dist/types/message.js +7 -1
  295. package/dist/types/message.js.map +1 -1
  296. package/dist/utils/data-url.d.ts +14 -1
  297. package/dist/utils/data-url.d.ts.map +1 -1
  298. package/dist/utils/data-url.js +13 -1
  299. package/dist/utils/data-url.js.map +1 -1
  300. package/dist/utils/invoke-user-callback.d.ts +5 -0
  301. package/dist/utils/invoke-user-callback.d.ts.map +1 -0
  302. package/dist/utils/invoke-user-callback.js +19 -0
  303. package/dist/utils/invoke-user-callback.js.map +1 -0
  304. package/dist/utils/normalizePartStatus.js.map +1 -1
  305. package/package.json +12 -17
  306. package/src/index.ts +6 -1
  307. package/src/internal.ts +20 -0
  308. package/src/model-context/frame/host.test.ts +91 -7
  309. package/src/model-context/frame/host.ts +7 -2
  310. package/src/model-context/frame/provider.test.ts +484 -13
  311. package/src/model-context/frame/provider.ts +205 -35
  312. package/src/model-context/interactable-composer-metadata.ts +1 -1
  313. package/src/model-context/registry.test.ts +44 -0
  314. package/src/model-context/registry.ts +13 -35
  315. package/src/model-context/tool-call-text.test.ts +67 -0
  316. package/src/model-context/tool-call-text.ts +67 -0
  317. package/src/react/AssistantRuntimeProvider.test.tsx +66 -2
  318. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +1 -3
  319. package/src/react/client/InMemoryThreadList.test.tsx +49 -0
  320. package/src/react/client/InMemoryThreadList.ts +7 -1
  321. package/src/react/client/Interactables.ts +19 -178
  322. package/src/react/client/RemoteThreadList.background.test.ts +384 -0
  323. package/src/react/client/RemoteThreadList.concurrent.test.tsx +274 -0
  324. package/src/react/client/RemoteThreadList.test.ts +369 -1
  325. package/src/react/client/RemoteThreadList.ts +320 -142
  326. package/src/react/client/Tools.ts +7 -1
  327. package/src/react/index.ts +4 -0
  328. package/src/react/interactables-legacy/Interactables.ts +20 -177
  329. package/src/react/interactables-shared/useInteractablePersistenceQueue.test.tsx +161 -0
  330. package/src/react/interactables-shared/useInteractablePersistenceQueue.ts +206 -0
  331. package/src/react/model-context/modelContextHooks.test.tsx +131 -0
  332. package/src/react/model-context/toolbox.test.ts +9 -9
  333. package/src/react/model-context/toolbox.ts +9 -36
  334. package/src/react/model-context/useAssistantContext.ts +4 -2
  335. package/src/react/model-context/useAuiToolOverrides.ts +4 -2
  336. package/src/react/model-context/useInlineRender.test.tsx +48 -0
  337. package/src/react/model-context/useInlineRender.ts +14 -10
  338. package/src/react/primitive-hooks/useMessageError.ts +2 -19
  339. package/src/react/primitive-hooks/useThreadListLoadMore.ts +2 -3
  340. package/src/react/primitives/composer/ComposerAttachments.test.tsx +76 -0
  341. package/src/react/primitives/composer/ComposerAttachments.tsx +9 -4
  342. package/src/react/primitives/composer/ComposerQueue.test.tsx +72 -0
  343. package/src/react/primitives/composer/ComposerQueue.tsx +7 -4
  344. package/src/react/primitives/message/MessageAttachments.test.tsx +107 -37
  345. package/src/react/primitives/message/MessageAttachments.tsx +10 -7
  346. package/src/react/primitives/message/MessageGroupedParts.tsx +2 -2
  347. package/src/react/primitives/message/MessageParts.tsx +3 -3
  348. package/src/react/primitives/threadList/ThreadListItems.test.tsx +99 -0
  349. package/src/react/primitives/threadList/ThreadListItems.tsx +8 -5
  350. package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +94 -1
  351. package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +72 -31
  352. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.switch-delete.test.ts +169 -0
  353. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +140 -124
  354. package/src/react/runtimes/RemoteThreadResource.ts +1 -4
  355. package/src/react/runtimes/assistant-transport/runManager.ts +4 -17
  356. package/src/react/runtimes/assistant-transport/transport-scheduling.test.ts +51 -2
  357. package/src/react/runtimes/assistant-transport/useLatestRef.ts +2 -2
  358. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.ts +45 -0
  359. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +157 -1
  360. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +82 -176
  361. package/src/react/runtimes/cloud/auiV0.ts +5 -0
  362. package/src/react/runtimes/cloud/createCloudThreadListAdapter.test.ts +88 -0
  363. package/src/react/runtimes/cloud/createCloudThreadListAdapter.ts +236 -0
  364. package/src/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.test.ts +37 -0
  365. package/src/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.ts +18 -0
  366. package/src/react/runtimes/cloud/useCloudThreadListAdapter.test.tsx +90 -1
  367. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +33 -238
  368. package/src/react/runtimes/external-message-converter.test.ts +0 -14
  369. package/src/react/runtimes/external-message-converter.test.tsx +77 -0
  370. package/src/react/runtimes/external-message-converter.ts +59 -481
  371. package/src/react/runtimes/useRemoteThreadListRuntime.concurrent.test.tsx +216 -0
  372. package/src/react/runtimes/useRemoteThreadListRuntime.ts +24 -6
  373. package/src/react/types/MessagePartComponentTypes.ts +7 -3
  374. package/src/react/types/scopes/tools.ts +2 -0
  375. package/src/runtime/api/composer-runtime.ts +1 -1
  376. package/src/runtime/api/message-part-runtime.ts +3 -3
  377. package/src/runtime/api/message-runtime.test.ts +28 -1
  378. package/src/runtime/api/thread-list-runtime.ts +25 -1
  379. package/src/runtime/base/base-composer-runtime-core.ts +20 -40
  380. package/src/runtime/base/base-thread-runtime-core.test.ts +110 -3
  381. package/src/runtime/base/base-thread-runtime-core.ts +16 -15
  382. package/src/runtime/base/default-thread-composer-runtime-core.ts +1 -4
  383. package/src/runtime/interfaces/composer-runtime-core.ts +1 -1
  384. package/src/runtime/interfaces/thread-list-runtime-core.ts +20 -1
  385. package/src/runtime/interfaces/thread-runtime-core.ts +18 -2
  386. package/src/runtime/internal.ts +5 -0
  387. package/src/runtime/queue/external-thread-queue-adapter.ts +1 -1
  388. package/src/runtime/queue/message-queue.ts +1 -4
  389. package/src/runtime/queue/queue-item.ts +10 -0
  390. package/src/runtime/utils/abortable-thread-load.test.ts +87 -0
  391. package/src/runtime/utils/abortable-thread-load.ts +53 -0
  392. package/src/runtime/utils/attachment-add-operations.ts +59 -0
  393. package/src/runtime/utils/auto-status.test.ts +57 -0
  394. package/src/runtime/utils/auto-status.ts +46 -1
  395. package/src/runtime/utils/external-message-conversion.test.ts +210 -0
  396. package/src/runtime/utils/external-message-conversion.ts +510 -0
  397. package/src/runtime/utils/external-store-message.ts +2 -0
  398. package/src/runtime/utils/message-repository-session.test.ts +195 -0
  399. package/src/runtime/utils/message-repository-session.ts +176 -0
  400. package/src/runtime/utils/message-repository.ts +7 -4
  401. package/src/runtime/utils/pending-tool-calls.test.ts +57 -0
  402. package/src/runtime/utils/pending-tool-calls.ts +35 -0
  403. package/src/runtime/utils/resolveToolApprovalResponse.test.ts +73 -0
  404. package/src/runtime/utils/resolveToolApprovalResponse.ts +27 -6
  405. package/src/runtime/utils/thread-message-like.ts +4 -10
  406. package/src/runtime/utils/tool-call-tree.test.ts +191 -0
  407. package/src/runtime/utils/tool-call-tree.ts +97 -0
  408. package/src/runtimes/external-store/external-store-adapter.ts +38 -2
  409. package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +6 -14
  410. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +231 -61
  411. package/src/runtimes/inert/InertThreadRuntimeCore.ts +1 -1
  412. package/src/runtimes/local/local-thread-runtime-core.test.ts +201 -4
  413. package/src/runtimes/local/local-thread-runtime-core.ts +53 -4
  414. package/src/runtimes/remote-thread-list/remote-thread-state.test.ts +149 -0
  415. package/src/runtimes/remote-thread-list/remote-thread-state.ts +178 -16
  416. package/src/runtimes/remote-thread-list/title.ts +3 -0
  417. package/src/runtimes/remote-thread-list/types.ts +6 -5
  418. package/src/runtimes/tool-invocations/EDGE_CASES.md +125 -3
  419. package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +856 -102
  420. package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +145 -89
  421. package/src/store/clients/external-thread.ts +30 -69
  422. package/src/store/clients/single-thread-list.ts +4 -1
  423. package/src/store/clients/suggestions.test.ts +185 -0
  424. package/src/store/clients/suggestions.ts +42 -35
  425. package/src/store/index.ts +4 -0
  426. package/src/store/internal.ts +2 -0
  427. package/src/store/primitive-predicates.ts +35 -0
  428. package/src/store/runtime-clients/thread-list-runtime-client.ts +16 -2
  429. package/src/store/runtime-clients/useSubscribable.ts +8 -2
  430. package/src/store/scopes/message.ts +1 -1
  431. package/src/store/scopes/part.ts +6 -3
  432. package/src/store/scopes/queue-item.ts +2 -9
  433. package/src/subscribable/subscribable.test.ts +50 -0
  434. package/src/subscribable/subscribable.ts +33 -21
  435. package/src/tests/MessageRepository.test.ts +77 -0
  436. package/src/tests/RemoteThreadListThreadListRuntimeCore-load-race.test.ts +305 -0
  437. package/src/tests/RemoteThreadListThreadListRuntimeCore-loadMore.test.ts +78 -0
  438. package/src/tests/RemoteThreadListThreadListRuntimeCore-reload.test.ts +52 -0
  439. package/src/tests/RemoteThreadListThreadListRuntimeCore-title-race.test.ts +158 -0
  440. package/src/tests/external-store-optimistic-id.test.ts +79 -0
  441. package/src/tests/external-store-repository-instance.test.ts +166 -0
  442. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +186 -16
  443. package/src/tests/external-store-thread-runtime-core.test.ts +642 -0
  444. package/src/tests/external-thread-attachments.test.tsx +258 -1
  445. package/src/tests/remote-thread-list-adapter-switch.test.ts +66 -1
  446. package/src/tests/single-thread-list-item.test.tsx +47 -0
  447. package/src/tests/thread-message-like.test.ts +39 -1
  448. package/src/tests/thread-switch-events.test.tsx +397 -2
  449. package/src/types/message.ts +58 -5
  450. package/src/utils/data-url.test.ts +52 -1
  451. package/src/utils/data-url.ts +21 -0
  452. package/src/utils/invoke-user-callback.test.ts +82 -0
  453. package/src/utils/invoke-user-callback.ts +31 -0
  454. package/src/utils/normalizePartStatus.ts +1 -1
  455. package/dist/store/scopes/queue-item.js.map +0 -1
@@ -1,18 +1,29 @@
1
- import type { ThreadListRuntimeCore } from "../../runtime/interfaces/thread-list-runtime-core";
2
- import { generateId } from "../../utils/id";
3
- import { BaseSubscribable } from "../../subscribable/subscribable";
1
+ import type {
2
+ ThreadListRuntimeCore,
3
+ ThreadListRuntimeEvent,
4
+ } from "../../runtime/interfaces/thread-list-runtime-core";
5
+ import {
6
+ BaseSubscribable,
7
+ WritableSubscribable,
8
+ } from "../../subscribable/subscribable";
9
+ import { useSubscribable } from "../../store/runtime-clients/useSubscribable";
4
10
  import { OptimisticState } from "../../runtimes/remote-thread-list/optimistic-state";
5
11
  import { EMPTY_THREAD_CORE } from "../../runtimes/remote-thread-list/empty-thread-core";
6
12
  import type {
13
+ ClassifyAccumulator,
7
14
  RemoteThreadData,
8
15
  RemoteThreadState,
9
16
  } from "../../runtimes/remote-thread-list/remote-thread-state";
10
17
  import {
11
18
  classifyThreads,
19
+ createEmptyRemoteThreadState,
12
20
  createThreadMappingId,
13
21
  getThreadData,
14
22
  normalizeCursor,
15
23
  updateStatusReducer,
24
+ preserveMidLoadTransitions,
25
+ seedNewThread,
26
+ statusSnapshot,
16
27
  } from "../../runtimes/remote-thread-list/remote-thread-state";
17
28
  import type {
18
29
  RemoteThreadListAdapter,
@@ -21,7 +32,7 @@ import type {
21
32
  } from "../../runtimes/remote-thread-list/types";
22
33
  import { ThreadListAdapterChangedError } from "../../runtimes/remote-thread-list/adapter-changed";
23
34
  import { RemoteThreadListHookInstanceManager } from "./RemoteThreadListHookInstanceManager";
24
- import { isTitleSourceMessage } from "./RemoteThreadResource";
35
+ import { isTitleSourceMessage } from "../../runtimes/remote-thread-list/title";
25
36
  import {
26
37
  type ComponentType,
27
38
  type FC,
@@ -31,7 +42,6 @@ import {
31
42
  useId,
32
43
  } from "react";
33
44
  import { useAui } from "@assistant-ui/store";
34
- import { create } from "zustand";
35
45
  import { AssistantMessageStream } from "assistant-stream";
36
46
  import type { ModelContextProvider } from "../../model-context/types";
37
47
  import { RuntimeAdapterProvider } from "./RuntimeAdapterProvider";
@@ -49,47 +59,7 @@ const threadStatusError = (
49
59
  `Thread "${threadIdOrRemoteId}" has status "${status}", so it cannot ${action}.`,
50
60
  );
51
61
 
52
- const EMPTY_REMOTE_STATE: RemoteThreadState = {
53
- isLoading: true,
54
- isLoadingMore: false,
55
- cursor: undefined,
56
- newThreadId: undefined,
57
- threadIds: [],
58
- archivedThreadIds: [],
59
- threadIdMap: {},
60
- threadData: {},
61
- };
62
-
63
- const addNewThread = (state: RemoteThreadState) => {
64
- let id: string;
65
- do {
66
- id = `__LOCALID_${generateId()}`;
67
- } while (state.threadIdMap[id]);
68
-
69
- const mappingId = createThreadMappingId(id);
70
- return {
71
- id,
72
- state: {
73
- ...state,
74
- newThreadId: id,
75
- threadIdMap: {
76
- ...state.threadIdMap,
77
- [id]: mappingId,
78
- },
79
- threadData: {
80
- ...state.threadData,
81
- [mappingId]: {
82
- status: "new",
83
- id,
84
- remoteId: undefined,
85
- externalId: undefined,
86
- title: undefined,
87
- custom: undefined,
88
- } satisfies RemoteThreadData,
89
- },
90
- },
91
- };
92
- };
62
+ const EMPTY_REMOTE_STATE = createEmptyRemoteThreadState();
93
63
 
94
64
  export class RemoteThreadListThreadListRuntimeCore
95
65
  extends BaseSubscribable
@@ -158,10 +128,12 @@ export class RemoteThreadListThreadListRuntimeCore
158
128
  if (!this._loadThreadsPromise) {
159
129
  const generation = this._loadGeneration;
160
130
  let replacedList = false;
131
+ const statusAtRequest = statusSnapshot(this._state.baseValue);
161
132
  this._loadThreadsPromise = this._state
162
133
  .optimisticUpdate({
163
134
  execute: () => this._options.adapter.list(),
164
135
  loading: (state) => {
136
+ if (generation !== this._loadGeneration) return state;
165
137
  return {
166
138
  ...state,
167
139
  isLoading: true,
@@ -183,18 +155,19 @@ export class RemoteThreadListThreadListRuntimeCore
183
155
  const fresh = classifyThreads(l.threads, {
184
156
  threadIds: [],
185
157
  archivedThreadIds: [],
186
- threadIdMap: {},
187
- threadData: {},
158
+ threadIdMap: { ...state.threadIdMap },
159
+ threadData: { ...state.threadData },
188
160
  });
189
- return {
161
+ const merged = {
190
162
  ...state,
191
163
  isLoading: false,
192
164
  cursor: normalizeCursor(l.nextCursor),
193
165
  threadIds: fresh.threadIds,
194
166
  archivedThreadIds: fresh.archivedThreadIds,
195
- threadIdMap: { ...state.threadIdMap, ...fresh.threadIdMap },
196
- threadData: { ...state.threadData, ...fresh.threadData },
167
+ threadIdMap: fresh.threadIdMap,
168
+ threadData: fresh.threadData,
197
169
  };
170
+ return preserveMidLoadTransitions(merged, state, statusAtRequest);
198
171
  },
199
172
  })
200
173
  .catch((error: unknown) => {
@@ -241,7 +214,10 @@ export class RemoteThreadListThreadListRuntimeCore
241
214
  const dedup = this._state
242
215
  .optimisticUpdate({
243
216
  execute: () => adapter.list({ after: cursor }),
244
- loading: (state) => ({ ...state, isLoadingMore: true }),
217
+ loading: (state) => {
218
+ if (generation !== this._loadGeneration) return state;
219
+ return { ...state, isLoadingMore: true };
220
+ },
245
221
  then: (state, l) => {
246
222
  if (generation !== this._loadGeneration) return state;
247
223
  if (adapter !== this._options.adapter) return state;
@@ -302,15 +278,15 @@ export class RemoteThreadListThreadListRuntimeCore
302
278
  // synchronous notify would re-enter store consumers mid-render.
303
279
  queueMicrotask(() => this._notifySubscribers());
304
280
  });
305
- this.useProvider = create(() => ({
306
- Provider: this.resolveProvider(options.adapter),
307
- }));
281
+ this.providerStore = new WritableSubscribable(
282
+ this.resolveProvider(options.adapter),
283
+ );
308
284
  this.__internal_setOptions(options);
309
285
  this.switchToNewThread();
310
286
  }
311
287
 
312
288
  private _initialThreadLoaded = false;
313
- private useProvider;
289
+ private providerStore;
314
290
 
315
291
  public __internal_setOptions(options: RemoteThreadListOptions) {
316
292
  if (this._options === options) return;
@@ -324,10 +300,7 @@ export class RemoteThreadListThreadListRuntimeCore
324
300
 
325
301
  this._options = options;
326
302
 
327
- const Provider = this.resolveProvider(options.adapter);
328
- if (Provider !== this.useProvider.getState().Provider) {
329
- this.useProvider.setState({ Provider }, true);
330
- }
303
+ this.providerStore.setState(this.resolveProvider(options.adapter));
331
304
 
332
305
  this._hookManager.setRuntimeHook(options.runtimeHook);
333
306
 
@@ -372,24 +345,11 @@ export class RemoteThreadListThreadListRuntimeCore
372
345
  threads: readonly RemoteThreadMetadata[],
373
346
  cursor: string | undefined,
374
347
  ): RemoteThreadState {
375
- const fresh = classifyThreads(threads, {
376
- threadIds: [],
377
- archivedThreadIds: [],
378
- threadIdMap: {},
379
- threadData: {},
380
- });
381
- const threadIdMap = { ...fresh.threadIdMap };
382
- const threadData = { ...fresh.threadData };
383
- const threadIds = [...fresh.threadIds];
384
- const archivedThreadIds = [...fresh.archivedThreadIds];
385
-
348
+ const carried: RemoteThreadData[] = [];
386
349
  if (state.newThreadId) {
387
350
  const mappingId = state.threadIdMap[state.newThreadId];
388
351
  const draft = mappingId ? state.threadData[mappingId] : undefined;
389
- if (draft?.status === "new") {
390
- threadIdMap[state.newThreadId] = mappingId!;
391
- threadData[mappingId!] = draft;
392
- }
352
+ if (draft?.status === "new") carried.push(draft);
393
353
  }
394
354
 
395
355
  const stale = this._staleThreadIdsOnReplace;
@@ -397,26 +357,44 @@ export class RemoteThreadListThreadListRuntimeCore
397
357
  for (const item of Object.values(state.threadData)) {
398
358
  if (stale.has(item.id)) continue;
399
359
  if (item.status !== "new" && item.remoteId === undefined) continue;
400
- const mappingId = createThreadMappingId(item.id);
401
- if (threadData[mappingId]) continue;
402
- threadIdMap[item.id] = mappingId;
403
- if (item.remoteId !== undefined) {
404
- threadIdMap[item.remoteId] = mappingId;
405
- }
406
- threadData[mappingId] = item;
407
- if (item.remoteId === undefined) continue;
408
- if (item.status === "regular" && !threadIds.includes(item.remoteId)) {
409
- threadIds.push(item.remoteId);
410
- } else if (
411
- item.status === "archived" &&
412
- !archivedThreadIds.includes(item.remoteId)
413
- ) {
414
- archivedThreadIds.push(item.remoteId);
415
- }
360
+ carried.push(item);
416
361
  }
417
362
  }
418
363
  this._staleThreadIdsOnReplace = undefined;
419
364
 
365
+ const seed: ClassifyAccumulator = {
366
+ threadIds: [],
367
+ archivedThreadIds: [],
368
+ threadIdMap: {},
369
+ threadData: {},
370
+ };
371
+ for (const item of carried) {
372
+ const mappingId = createThreadMappingId(item.id);
373
+ if (seed.threadData[mappingId]) continue;
374
+ seed.threadIdMap[item.id] = mappingId;
375
+ if (item.remoteId !== undefined) {
376
+ seed.threadIdMap[item.remoteId] = mappingId;
377
+ }
378
+ seed.threadData[mappingId] = item;
379
+ }
380
+
381
+ const { threadIds, archivedThreadIds, threadIdMap, threadData } =
382
+ classifyThreads(threads, seed);
383
+
384
+ for (const item of carried) {
385
+ if (item.remoteId === undefined) continue;
386
+ const current = threadData[createThreadMappingId(item.id)];
387
+ if (current === undefined) continue;
388
+ if (current.status === "regular" && !threadIds.includes(current.id)) {
389
+ threadIds.push(current.id);
390
+ } else if (
391
+ current.status === "archived" &&
392
+ !archivedThreadIds.includes(current.id)
393
+ ) {
394
+ archivedThreadIds.push(current.id);
395
+ }
396
+ }
397
+
420
398
  let nextState: RemoteThreadState = {
421
399
  ...state,
422
400
  isLoading: false,
@@ -437,7 +415,7 @@ export class RemoteThreadListThreadListRuntimeCore
437
415
  if (preservedDraft !== undefined) {
438
416
  this._mainThreadId = preservedDraft;
439
417
  } else {
440
- const seeded = addNewThread(nextState);
418
+ const seeded = seedNewThread(nextState);
441
419
  this._mainThreadId = seeded.id;
442
420
  nextState = seeded.state;
443
421
  }
@@ -590,6 +568,12 @@ export class RemoteThreadListThreadListRuntimeCore
590
568
  return this._hookManager.__internal_isThreadRunning(data.id);
591
569
  }
592
570
 
571
+ public unstable_subscribeThreadEvents(
572
+ callback: (event: ThreadListRuntimeEvent) => void,
573
+ ) {
574
+ return this._hookManager.__internal_subscribeThreadEvents(callback);
575
+ }
576
+
593
577
  public getItemById(threadIdOrRemoteId: string) {
594
578
  return getThreadData(this._state.value, threadIdOrRemoteId);
595
579
  }
@@ -664,9 +648,8 @@ export class RemoteThreadListThreadListRuntimeCore
664
648
  // A concurrent `list()` may already have placed this thread; keep that
665
649
  // position and only merge metadata. A genuinely absent thread stays
666
650
  // appended: it may live on an unloaded page, and a prepend would pin it
667
- // above newer threads permanently since `classifyThreads` skips ids it
668
- // has already seen. Filtering both arrays first still prevents
669
- // duplication or a wrong-status entry from `list()`.
651
+ // above newer threads permanently. Filtering both arrays first still
652
+ // prevents duplication or a wrong-status entry from `list()`.
670
653
  const remoteId = remoteMetadata.remoteId;
671
654
  const wasInTarget =
672
655
  remoteMetadata.status === "regular"
@@ -719,11 +702,22 @@ export class RemoteThreadListThreadListRuntimeCore
719
702
 
720
703
  if (generation !== this._switchGeneration) return;
721
704
 
722
- if (data.status === "archived" && options?.unarchive !== false) {
723
- await this.unarchive(data.id);
705
+ let current = this.getItemById(data.id);
706
+ if (current?.id !== data.id) return;
707
+
708
+ if (current.status === "archived" && options?.unarchive !== false) {
709
+ await current.initializeTask;
724
710
  if (generation !== this._switchGeneration) return;
711
+ current = this.getItemById(data.id);
712
+ if (current?.id !== data.id) return;
713
+ if (current.status === "archived") {
714
+ await this.unarchive(current.id);
715
+ if (generation !== this._switchGeneration) return;
716
+ current = this.getItemById(data.id);
717
+ if (current?.id !== data.id) return;
718
+ }
725
719
  }
726
- this._mainThreadId = data.id;
720
+ this._mainThreadId = current.id;
727
721
 
728
722
  this._notifySubscribers();
729
723
  this._notifyThreadIdChange(emitThreadIdChange);
@@ -762,7 +756,7 @@ export class RemoteThreadListThreadListRuntimeCore
762
756
  const state = this._state.baseValue;
763
757
  let id: string | undefined = this._state.value.newThreadId;
764
758
  if (id === undefined) {
765
- const next = addNewThread(state);
759
+ const next = seedNewThread(state);
766
760
  id = next.id;
767
761
  this._state.update(next.state);
768
762
  }
@@ -811,21 +805,36 @@ export class RemoteThreadListThreadListRuntimeCore
811
805
  if (!data) return state;
812
806
 
813
807
  const mappingId = createThreadMappingId(threadId);
808
+ // A list() response that landed while this initialize was in flight
809
+ // could not know the remote id yet, so it may have minted its own slot
810
+ // for it; that slot collapses into this one.
811
+ const listedMappingId = state.threadIdMap[remoteId];
812
+ const orphan =
813
+ listedMappingId !== undefined && listedMappingId !== mappingId
814
+ ? state.threadData[listedMappingId]
815
+ : undefined;
816
+
817
+ const threadData = { ...state.threadData };
818
+ if (orphan !== undefined) delete threadData[listedMappingId!];
819
+ threadData[mappingId] = {
820
+ ...data,
821
+ initializeTask: Promise.resolve({ remoteId, externalId }),
822
+ remoteId,
823
+ externalId,
824
+ } as RemoteThreadData;
825
+
826
+ const rewire = (ids: readonly string[]) =>
827
+ orphan === undefined ? ids : ids.filter((id) => id !== orphan.id);
828
+
814
829
  return {
815
830
  ...state,
831
+ threadIds: rewire(state.threadIds),
832
+ archivedThreadIds: rewire(state.archivedThreadIds),
816
833
  threadIdMap: {
817
834
  ...state.threadIdMap,
818
835
  [remoteId]: mappingId,
819
836
  },
820
- threadData: {
821
- ...state.threadData,
822
- [mappingId]: {
823
- ...data,
824
- initializeTask: Promise.resolve({ remoteId, externalId }),
825
- remoteId,
826
- externalId,
827
- },
828
- },
837
+ threadData,
829
838
  };
830
839
  },
831
840
  });
@@ -857,17 +866,22 @@ export class RemoteThreadListThreadListRuntimeCore
857
866
  for await (const result of messageStream) {
858
867
  if (adapterGeneration !== this._adapterGeneration) return;
859
868
  const newTitle = result.parts.filter((c) => c.type === "text")[0]?.text;
860
- const state = this._state.baseValue;
861
- const currentData = getThreadData(state, data.id);
862
- if (!currentData) continue;
863
- this._state.update({
864
- ...state,
865
- threadData: {
866
- ...state.threadData,
867
- [currentData.id]: {
868
- ...currentData,
869
- title: newTitle,
870
- },
869
+ await this._state.optimisticUpdate({
870
+ execute: async () => {},
871
+ optimistic: (state) => {
872
+ if (adapterGeneration !== this._adapterGeneration) return state;
873
+ const currentData = getThreadData(state, data.id);
874
+ if (!currentData) return state;
875
+ return {
876
+ ...state,
877
+ threadData: {
878
+ ...state.threadData,
879
+ [currentData.id]: {
880
+ ...currentData,
881
+ title: newTitle,
882
+ },
883
+ },
884
+ };
871
885
  },
872
886
  });
873
887
  }
@@ -1079,19 +1093,21 @@ export class RemoteThreadListThreadListRuntimeCore
1079
1093
  this._hookManager.stopThreadRuntime(data.id);
1080
1094
  }
1081
1095
 
1082
- private useBoundIds = create<string[]>(() => []);
1096
+ private boundIdsStore = new WritableSubscribable<readonly string[]>([]);
1083
1097
 
1084
1098
  public __internal_RenderComponent: FC = () => {
1085
1099
  const id = useId();
1086
1100
  useEffect(() => {
1087
- this.useBoundIds.setState((s) => [...s, id], true);
1101
+ this.boundIdsStore.setState([...this.boundIdsStore.getState(), id]);
1088
1102
  return () => {
1089
- this.useBoundIds.setState((s) => s.filter((i) => i !== id), true);
1103
+ this.boundIdsStore.setState(
1104
+ this.boundIdsStore.getState().filter((i) => i !== id),
1105
+ );
1090
1106
  };
1091
1107
  }, [id]);
1092
1108
 
1093
- const boundIds = this.useBoundIds();
1094
- const { Provider } = this.useProvider();
1109
+ const boundIds = useSubscribable(this.boundIdsStore);
1110
+ const Provider = useSubscribable(this.providerStore);
1095
1111
  const aui = useAui();
1096
1112
  const enabled = boundIds.length === 0 || boundIds[0] === id;
1097
1113
 
@@ -22,6 +22,7 @@ import {
22
22
  type RuntimeAdapters,
23
23
  } from "./RuntimeAdapterProvider";
24
24
  import { isSilentRuntimeAction } from "../../utils/silent-runtime-action";
25
+ import { isTitleSourceMessage } from "../../runtimes/remote-thread-list/title";
25
26
 
26
27
  export type RemoteThreadListHook = () => AssistantRuntime;
27
28
 
@@ -39,10 +40,6 @@ export type RemoteThreadResourceProps = {
39
40
  ) => void;
40
41
  };
41
42
 
42
- export const isTitleSourceMessage = (message: {
43
- status?: { type: string } | undefined;
44
- }) => message.status?.type !== "running";
45
-
46
43
  export const subscribeToTitleGeneration = (
47
44
  threadRuntime: AssistantRuntime["thread"],
48
45
  itemRuntime: ThreadListItemRuntime,
@@ -1,4 +1,5 @@
1
1
  import { useCallback, useEffect, useRef, useState } from "react";
2
+ import { invokeUserCallback } from "../../../utils/invoke-user-callback";
2
3
  import { useLatestRef } from "./useLatestRef";
3
4
 
4
5
  export type RunManager = Readonly<{
@@ -11,25 +12,11 @@ const disposeReason = Symbol("assistant-transport-dispose");
11
12
 
12
13
  type LifecycleCallbackName = "onCancel" | "onError" | "onFinish";
13
14
 
14
- const reportCallbackError = (name: LifecycleCallbackName, error: unknown) => {
15
- console.error(
16
- `[assistant-ui] Assistant transport ${name} callback threw an error`,
17
- error,
18
- );
19
- };
20
-
21
- const invokeCallback = async (
15
+ const invokeCallback = (
22
16
  name: LifecycleCallbackName,
23
17
  callback: (() => unknown) | undefined,
24
- ): Promise<void> => {
25
- try {
26
- await callback?.();
27
- } catch (error) {
28
- try {
29
- reportCallbackError(name, error);
30
- } catch {}
31
- }
32
- };
18
+ ) =>
19
+ invokeUserCallback("assistant-ui", `Assistant transport ${name}`, callback);
33
20
 
34
21
  export function useRunManager(config: {
35
22
  onRun: (signal: AbortSignal) => Promise<void>;
@@ -1,8 +1,8 @@
1
1
  // @vitest-environment jsdom
2
2
 
3
- import { act, renderHook, waitFor } from "@testing-library/react";
3
+ import { act, render, renderHook, waitFor } from "@testing-library/react";
4
4
  import { describe, expect, it, vi } from "vitest";
5
- import { createElement, StrictMode, useRef } from "react";
5
+ import { createElement, StrictMode, useLayoutEffect, useRef } from "react";
6
6
  import { useCommandQueue } from "./commandQueue";
7
7
  import { useRunManager } from "./runManager";
8
8
  import type { AssistantTransportCommand } from "./types";
@@ -85,6 +85,55 @@ const useTransportSchedulingHarness = (
85
85
  };
86
86
 
87
87
  describe("assistant transport scheduling contracts", () => {
88
+ it("uses current callbacks when scheduled by a descendant layout effect", async () => {
89
+ const onRunA = vi.fn(async () => {});
90
+ const onRunB = vi.fn(async () => {});
91
+ // act flushes passive effects before real microtasks, so preserve the
92
+ // browser's microtask-before-passive-effect ordering at the layout boundary.
93
+ const queueMicrotaskSpy = vi
94
+ .spyOn(globalThis, "queueMicrotask")
95
+ .mockImplementation((callback) => callback());
96
+
97
+ const Scheduler = ({
98
+ schedule,
99
+ enabled,
100
+ }: {
101
+ schedule: () => void;
102
+ enabled: boolean;
103
+ }) => {
104
+ useLayoutEffect(() => {
105
+ if (enabled) schedule();
106
+ }, [enabled, schedule]);
107
+ return null;
108
+ };
109
+ const Probe = ({
110
+ enabled,
111
+ onRun,
112
+ }: {
113
+ enabled: boolean;
114
+ onRun: (signal: AbortSignal) => Promise<void>;
115
+ }) => {
116
+ const runManager = useRunManager({ onRun });
117
+ return createElement(Scheduler, {
118
+ enabled,
119
+ schedule: runManager.schedule,
120
+ });
121
+ };
122
+
123
+ try {
124
+ const view = render(
125
+ createElement(Probe, { enabled: false, onRun: onRunA }),
126
+ );
127
+ view.rerender(createElement(Probe, { enabled: true, onRun: onRunB }));
128
+ await act(async () => {});
129
+
130
+ expect(onRunB).toHaveBeenCalledTimes(1);
131
+ expect(onRunA).not.toHaveBeenCalled();
132
+ } finally {
133
+ queueMicrotaskSpy.mockRestore();
134
+ }
135
+ });
136
+
88
137
  it("runs in single-flight mode and schedules exactly one follow-up run", async () => {
89
138
  const gate = createDeferred();
90
139
  const { result } = renderHook(() =>
@@ -1,8 +1,8 @@
1
- import { useEffect, useRef } from "react";
1
+ import { useInsertionEffect, useRef } from "react";
2
2
 
3
3
  export function useLatestRef<T>(value: T) {
4
4
  const ref = useRef(value);
5
- useEffect(() => {
5
+ useInsertionEffect(() => {
6
6
  ref.current = value;
7
7
  }, [value]);
8
8
  return ref as { current: T };
@@ -31,4 +31,49 @@ describe("extractAuiV0", () => {
31
31
  expect(result?.inputTokens).toBe(1);
32
32
  expect(result?.outputTokens).toBe(2);
33
33
  });
34
+
35
+ it("sums step usage reported under the AI SDK v7 token details", () => {
36
+ const result = extractAuiV0({
37
+ ...auiV0Message({ type: "complete" }),
38
+ metadata: {
39
+ steps: [
40
+ {
41
+ usage: {
42
+ inputTokens: 10,
43
+ outputTokens: 4,
44
+ inputTokenDetails: { cacheReadTokens: 6 },
45
+ outputTokenDetails: { reasoningTokens: 1 },
46
+ },
47
+ },
48
+ {
49
+ usage: {
50
+ inputTokens: 5,
51
+ outputTokens: 2,
52
+ inputTokenDetails: { cacheReadTokens: 3 },
53
+ outputTokenDetails: { reasoningTokens: 1 },
54
+ },
55
+ },
56
+ ],
57
+ },
58
+ });
59
+
60
+ expect(result?.inputTokens).toBe(15);
61
+ expect(result?.outputTokens).toBe(6);
62
+ expect(result?.cachedInputTokens).toBe(9);
63
+ expect(result?.reasoningTokens).toBe(2);
64
+ expect(result?.steps).toEqual([
65
+ {
66
+ input_tokens: 10,
67
+ output_tokens: 4,
68
+ reasoning_tokens: 1,
69
+ cached_input_tokens: 6,
70
+ },
71
+ {
72
+ input_tokens: 5,
73
+ output_tokens: 2,
74
+ reasoning_tokens: 1,
75
+ cached_input_tokens: 3,
76
+ },
77
+ ]);
78
+ });
34
79
  });