@assistant-ui/core 0.3.16 → 0.3.18

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 (474) hide show
  1. package/dist/adapters/attachment.d.ts.map +1 -1
  2. package/dist/adapters/attachment.js +5 -4
  3. package/dist/adapters/attachment.js.map +1 -1
  4. package/dist/index.d.ts +3 -3
  5. package/dist/index.js +2 -2
  6. package/dist/index.js.map +1 -1
  7. package/dist/internal.d.ts +4 -2
  8. package/dist/internal.js +4 -2
  9. package/dist/model-context/frame/host.d.ts.map +1 -1
  10. package/dist/model-context/frame/host.js +10 -4
  11. package/dist/model-context/frame/host.js.map +1 -1
  12. package/dist/model-context/frame/provider.d.ts +5 -0
  13. package/dist/model-context/frame/provider.d.ts.map +1 -1
  14. package/dist/model-context/frame/provider.js +101 -28
  15. package/dist/model-context/frame/provider.js.map +1 -1
  16. package/dist/model-context/interactable-composer-metadata.d.ts.map +1 -1
  17. package/dist/model-context/interactable-composer-metadata.js +16 -9
  18. package/dist/model-context/interactable-composer-metadata.js.map +1 -1
  19. package/dist/model-context/registry.d.ts.map +1 -1
  20. package/dist/model-context/registry.js +3 -5
  21. package/dist/model-context/registry.js.map +1 -1
  22. package/dist/model-context/tool-call-text.d.ts +26 -0
  23. package/dist/model-context/tool-call-text.d.ts.map +1 -0
  24. package/dist/model-context/tool-call-text.js +18 -0
  25. package/dist/model-context/tool-call-text.js.map +1 -0
  26. package/dist/model-context/types.d.ts.map +1 -1
  27. package/dist/model-context/types.js +5 -4
  28. package/dist/model-context/types.js.map +1 -1
  29. package/dist/react/RuntimeAdapter.js +1 -1
  30. package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
  31. package/dist/react/adapters/LocalStorageThreadListAdapter.js +1 -1
  32. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  33. package/dist/react/client/AdaptedRemoteThread.js +1 -1
  34. package/dist/react/client/InMemoryThreadList.d.ts.map +1 -1
  35. package/dist/react/client/InMemoryThreadList.js +63 -57
  36. package/dist/react/client/InMemoryThreadList.js.map +1 -1
  37. package/dist/react/client/Interactables.d.ts.map +1 -1
  38. package/dist/react/client/Interactables.js +25 -28
  39. package/dist/react/client/Interactables.js.map +1 -1
  40. package/dist/react/client/RemoteThreadList.d.ts +16 -0
  41. package/dist/react/client/RemoteThreadList.d.ts.map +1 -1
  42. package/dist/react/client/RemoteThreadList.js +354 -242
  43. package/dist/react/client/RemoteThreadList.js.map +1 -1
  44. package/dist/react/client/Tools.d.ts.map +1 -1
  45. package/dist/react/client/Tools.js +24 -18
  46. package/dist/react/client/Tools.js.map +1 -1
  47. package/dist/react/index.d.ts +2 -1
  48. package/dist/react/index.js +2 -1
  49. package/dist/react/interactables-legacy/Interactables.js +246 -125
  50. package/dist/react/interactables-legacy/Interactables.js.map +1 -1
  51. package/dist/react/interactables-shared/useInteractablePersistenceQueue.d.ts.map +1 -1
  52. package/dist/react/interactables-shared/useInteractablePersistenceQueue.js +11 -9
  53. package/dist/react/interactables-shared/useInteractablePersistenceQueue.js.map +1 -1
  54. package/dist/react/model-context/makeAssistantTool.d.ts +2 -2
  55. package/dist/react/model-context/makeAssistantTool.js +1 -1
  56. package/dist/react/model-context/makeAssistantTool.js.map +1 -1
  57. package/dist/react/model-context/toolbox.d.ts +2 -14
  58. package/dist/react/model-context/toolbox.d.ts.map +1 -1
  59. package/dist/react/model-context/toolbox.js +1 -13
  60. package/dist/react/model-context/toolbox.js.map +1 -1
  61. package/dist/react/model-context/useAssistantContext.js +37 -7
  62. package/dist/react/model-context/useAssistantContext.js.map +1 -1
  63. package/dist/react/model-context/useAssistantTool.d.ts +2 -2
  64. package/dist/react/model-context/useAssistantTool.js +1 -1
  65. package/dist/react/model-context/useAssistantTool.js.map +1 -1
  66. package/dist/react/model-context/useAuiToolOverrides.js +31 -5
  67. package/dist/react/model-context/useAuiToolOverrides.js.map +1 -1
  68. package/dist/react/model-context/useInlineRender.d.ts.map +1 -1
  69. package/dist/react/model-context/useInlineRender.js +10 -36
  70. package/dist/react/model-context/useInlineRender.js.map +1 -1
  71. package/dist/react/model-context/useToolArgsStatus.d.ts.map +1 -1
  72. package/dist/react/model-context/useToolArgsStatus.js +2 -1
  73. package/dist/react/model-context/useToolArgsStatus.js.map +1 -1
  74. package/dist/react/primitive-hooks/useMessageError.d.ts.map +1 -1
  75. package/dist/react/primitive-hooks/useMessageError.js +2 -8
  76. package/dist/react/primitive-hooks/useMessageError.js.map +1 -1
  77. package/dist/react/primitive-hooks/useThreadListLoadMore.d.ts.map +1 -1
  78. package/dist/react/primitive-hooks/useThreadListLoadMore.js +2 -4
  79. package/dist/react/primitive-hooks/useThreadListLoadMore.js.map +1 -1
  80. package/dist/react/primitives/composer/ComposerAttachments.d.ts.map +1 -1
  81. package/dist/react/primitives/composer/ComposerAttachments.js +4 -3
  82. package/dist/react/primitives/composer/ComposerAttachments.js.map +1 -1
  83. package/dist/react/primitives/composer/ComposerQueue.d.ts.map +1 -1
  84. package/dist/react/primitives/composer/ComposerQueue.js +4 -3
  85. package/dist/react/primitives/composer/ComposerQueue.js.map +1 -1
  86. package/dist/react/primitives/message/MessageAttachments.d.ts.map +1 -1
  87. package/dist/react/primitives/message/MessageAttachments.js +7 -6
  88. package/dist/react/primitives/message/MessageAttachments.js.map +1 -1
  89. package/dist/react/primitives/message/MessageGroupedParts.js +2 -2
  90. package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
  91. package/dist/react/primitives/message/MessageParts.js +3 -3
  92. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  93. package/dist/react/primitives/threadList/ThreadListItems.d.ts.map +1 -1
  94. package/dist/react/primitives/threadList/ThreadListItems.js +5 -4
  95. package/dist/react/primitives/threadList/ThreadListItems.js.map +1 -1
  96. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +6 -4
  97. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  98. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +59 -29
  99. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  100. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +11 -6
  101. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  102. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +160 -143
  103. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  104. package/dist/react/runtimes/RemoteThreadResource.d.ts +2 -6
  105. package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -1
  106. package/dist/react/runtimes/RemoteThreadResource.js +15 -13
  107. package/dist/react/runtimes/RemoteThreadResource.js.map +1 -1
  108. package/dist/react/runtimes/assistant-transport/useLatestRef.js +2 -2
  109. package/dist/react/runtimes/assistant-transport/useLatestRef.js.map +1 -1
  110. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +4 -1
  111. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  112. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +424 -52
  113. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  114. package/dist/react/runtimes/cloud/auiV0.d.ts +5 -1
  115. package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
  116. package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
  117. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts +29 -0
  118. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts.map +1 -0
  119. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js +160 -0
  120. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js.map +1 -0
  121. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts +1 -9
  122. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  123. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +16 -153
  124. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  125. package/dist/react/runtimes/external-message-converter.js +1 -1
  126. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  127. package/dist/react/runtimes/useExternalStoreRuntime.js +75 -46
  128. package/dist/react/runtimes/useExternalStoreRuntime.js.map +1 -1
  129. package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
  130. package/dist/react/runtimes/useRemoteThreadListRuntime.js +77 -29
  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/message-part-runtime.d.ts +2 -2
  137. package/dist/runtime/api/message-part-runtime.d.ts.map +1 -1
  138. package/dist/runtime/api/message-part-runtime.js +1 -1
  139. package/dist/runtime/api/message-part-runtime.js.map +1 -1
  140. package/dist/runtime/api/thread-list-item-runtime.d.ts +7 -3
  141. package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
  142. package/dist/runtime/api/thread-list-item-runtime.js +2 -2
  143. package/dist/runtime/api/thread-list-item-runtime.js.map +1 -1
  144. package/dist/runtime/api/thread-list-runtime.d.ts +12 -1
  145. package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
  146. package/dist/runtime/api/thread-list-runtime.js +23 -14
  147. package/dist/runtime/api/thread-list-runtime.js.map +1 -1
  148. package/dist/runtime/api/thread-runtime.d.ts +5 -1
  149. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  150. package/dist/runtime/api/thread-runtime.js +1 -1
  151. package/dist/runtime/api/thread-runtime.js.map +1 -1
  152. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  153. package/dist/runtime/base/base-composer-runtime-core.js +16 -12
  154. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  155. package/dist/runtime/base/base-thread-runtime-core.d.ts +2 -2
  156. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  157. package/dist/runtime/base/base-thread-runtime-core.js +8 -7
  158. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  159. package/dist/runtime/interfaces/composer-runtime-core.d.ts +12 -5
  160. package/dist/runtime/interfaces/composer-runtime-core.d.ts.map +1 -1
  161. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +18 -3
  162. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
  163. package/dist/runtime/interfaces/thread-runtime-core.d.ts +15 -1
  164. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  165. package/dist/runtime/utils/auto-status.d.ts +1 -1
  166. package/dist/runtime/utils/auto-status.d.ts.map +1 -1
  167. package/dist/runtime/utils/auto-status.js +6 -2
  168. package/dist/runtime/utils/auto-status.js.map +1 -1
  169. package/dist/runtime/utils/external-message-conversion.d.ts +3 -2
  170. package/dist/runtime/utils/external-message-conversion.d.ts.map +1 -1
  171. package/dist/runtime/utils/external-message-conversion.js +5 -4
  172. package/dist/runtime/utils/external-message-conversion.js.map +1 -1
  173. package/dist/runtime/utils/message-repository.d.ts +1 -0
  174. package/dist/runtime/utils/message-repository.d.ts.map +1 -1
  175. package/dist/runtime/utils/message-repository.js +15 -6
  176. package/dist/runtime/utils/message-repository.js.map +1 -1
  177. package/dist/runtime/utils/resolveToolApprovalResponse.d.ts +6 -3
  178. package/dist/runtime/utils/resolveToolApprovalResponse.d.ts.map +1 -1
  179. package/dist/runtime/utils/resolveToolApprovalResponse.js +12 -3
  180. package/dist/runtime/utils/resolveToolApprovalResponse.js.map +1 -1
  181. package/dist/runtime/utils/thread-message-like.d.ts +2 -10
  182. package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
  183. package/dist/runtime/utils/thread-message-like.js +1 -1
  184. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  185. package/dist/runtime/utils/tool-call-tree.d.ts +39 -0
  186. package/dist/runtime/utils/tool-call-tree.d.ts.map +1 -0
  187. package/dist/runtime/utils/tool-call-tree.js +85 -0
  188. package/dist/runtime/utils/tool-call-tree.js.map +1 -0
  189. package/dist/runtimes/external-store/external-store-adapter.d.ts +29 -2
  190. package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
  191. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  192. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +21 -27
  193. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  194. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +2 -1
  195. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  196. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +34 -28
  197. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  198. package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts +1 -1
  199. package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts.map +1 -1
  200. package/dist/runtimes/inert/InertThreadRuntimeCore.js.map +1 -1
  201. package/dist/runtimes/internal.d.ts +2 -2
  202. package/dist/runtimes/internal.js +2 -2
  203. package/dist/runtimes/local/local-thread-runtime-core.d.ts +1 -1
  204. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  205. package/dist/runtimes/local/local-thread-runtime-core.js +3 -1
  206. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  207. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts +18 -1
  208. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts.map +1 -1
  209. package/dist/runtimes/remote-thread-list/remote-thread-state.js +148 -43
  210. package/dist/runtimes/remote-thread-list/remote-thread-state.js.map +1 -1
  211. package/dist/runtimes/remote-thread-list/title-generation.d.ts +49 -0
  212. package/dist/runtimes/remote-thread-list/title-generation.d.ts.map +1 -0
  213. package/dist/runtimes/remote-thread-list/title-generation.js +197 -0
  214. package/dist/runtimes/remote-thread-list/title-generation.js.map +1 -0
  215. package/dist/runtimes/remote-thread-list/title.d.ts +11 -0
  216. package/dist/runtimes/remote-thread-list/title.d.ts.map +1 -0
  217. package/dist/runtimes/remote-thread-list/title.js +14 -0
  218. package/dist/runtimes/remote-thread-list/title.js.map +1 -0
  219. package/dist/runtimes/remote-thread-list/types.d.ts +16 -5
  220. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  221. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +31 -8
  222. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
  223. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +97 -60
  224. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
  225. package/dist/store/clients/external-thread.d.ts +1 -1
  226. package/dist/store/clients/external-thread.d.ts.map +1 -1
  227. package/dist/store/clients/external-thread.js +30 -7
  228. package/dist/store/clients/external-thread.js.map +1 -1
  229. package/dist/store/clients/model-context-client.d.ts.map +1 -1
  230. package/dist/store/clients/model-context-client.js +2 -1
  231. package/dist/store/clients/model-context-client.js.map +1 -1
  232. package/dist/store/clients/single-thread-list.d.ts.map +1 -1
  233. package/dist/store/clients/single-thread-list.js +2 -1
  234. package/dist/store/clients/single-thread-list.js.map +1 -1
  235. package/dist/store/clients/suggestions.d.ts.map +1 -1
  236. package/dist/store/clients/suggestions.js +19 -6
  237. package/dist/store/clients/suggestions.js.map +1 -1
  238. package/dist/store/clients/thread-message-client.js +1 -1
  239. package/dist/store/clients/thread-selection-events.js +1 -1
  240. package/dist/store/index.d.ts +2 -1
  241. package/dist/store/index.js +2 -1
  242. package/dist/store/internal.d.ts +2 -2
  243. package/dist/store/internal.js +2 -2
  244. package/dist/store/primitive-predicates.d.ts +4 -1
  245. package/dist/store/primitive-predicates.d.ts.map +1 -1
  246. package/dist/store/primitive-predicates.js +9 -1
  247. package/dist/store/primitive-predicates.js.map +1 -1
  248. package/dist/store/runtime-clients/composer-runtime-client.d.ts +1 -0
  249. package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
  250. package/dist/store/runtime-clients/composer-runtime-client.js +98 -62
  251. package/dist/store/runtime-clients/composer-runtime-client.js.map +1 -1
  252. package/dist/store/runtime-clients/message-runtime-client.d.ts +1 -0
  253. package/dist/store/runtime-clients/message-runtime-client.d.ts.map +1 -1
  254. package/dist/store/runtime-clients/message-runtime-client.js +221 -144
  255. package/dist/store/runtime-clients/message-runtime-client.js.map +1 -1
  256. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  257. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +2 -2
  258. package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
  259. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
  260. package/dist/store/runtime-clients/thread-list-runtime-client.js +128 -107
  261. package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
  262. package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
  263. package/dist/store/runtime-clients/thread-runtime-client.js +194 -122
  264. package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
  265. package/dist/store/runtime-clients/useSubscribable.d.ts +3 -1
  266. package/dist/store/runtime-clients/useSubscribable.d.ts.map +1 -1
  267. package/dist/store/runtime-clients/useSubscribable.js +1 -1
  268. package/dist/store/runtime-clients/useSubscribable.js.map +1 -1
  269. package/dist/store/scopes/composer.d.ts +10 -2
  270. package/dist/store/scopes/composer.d.ts.map +1 -1
  271. package/dist/store/scopes/message.d.ts +30 -1
  272. package/dist/store/scopes/message.d.ts.map +1 -1
  273. package/dist/store/scopes/part.d.ts +6 -3
  274. package/dist/store/scopes/part.d.ts.map +1 -1
  275. package/dist/store/scopes/thread-list-item.d.ts +2 -2
  276. package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
  277. package/dist/store/scopes/thread.d.ts +8 -0
  278. package/dist/store/scopes/thread.d.ts.map +1 -1
  279. package/dist/store/scopes/threads.d.ts +1 -0
  280. package/dist/store/scopes/threads.d.ts.map +1 -1
  281. package/dist/subscribable/subscribable.d.ts +8 -1
  282. package/dist/subscribable/subscribable.d.ts.map +1 -1
  283. package/dist/subscribable/subscribable.js +24 -16
  284. package/dist/subscribable/subscribable.js.map +1 -1
  285. package/dist/types/attachment.d.ts +2 -1
  286. package/dist/types/attachment.d.ts.map +1 -1
  287. package/dist/types/attachment.js +2 -1
  288. package/dist/types/attachment.js.map +1 -1
  289. package/dist/types/message.d.ts +40 -1
  290. package/dist/types/message.d.ts.map +1 -1
  291. package/dist/types/message.js +7 -1
  292. package/dist/types/message.js.map +1 -1
  293. package/dist/utils/abortable-iterable.d.ts +19 -0
  294. package/dist/utils/abortable-iterable.d.ts.map +1 -0
  295. package/dist/utils/abortable-iterable.js +72 -0
  296. package/dist/utils/abortable-iterable.js.map +1 -0
  297. package/dist/utils/composite-context-provider.d.ts.map +1 -1
  298. package/dist/utils/composite-context-provider.js +20 -2
  299. package/dist/utils/composite-context-provider.js.map +1 -1
  300. package/dist/utils/record.d.ts +11 -0
  301. package/dist/utils/record.d.ts.map +1 -0
  302. package/dist/utils/record.js +12 -0
  303. package/dist/utils/record.js.map +1 -0
  304. package/package.json +12 -17
  305. package/src/adapters/attachment.test.ts +50 -1
  306. package/src/adapters/attachment.ts +7 -4
  307. package/src/index.ts +7 -1
  308. package/src/internal.ts +12 -0
  309. package/src/model-context/frame/host.test.ts +24 -0
  310. package/src/model-context/frame/host.ts +10 -4
  311. package/src/model-context/frame/provider.test.ts +288 -1
  312. package/src/model-context/frame/provider.ts +148 -30
  313. package/src/model-context/interactable-composer-metadata.test.ts +28 -0
  314. package/src/model-context/interactable-composer-metadata.ts +9 -3
  315. package/src/model-context/registry.test.ts +12 -0
  316. package/src/model-context/registry.ts +3 -2
  317. package/src/model-context/tool-call-text.test.ts +67 -0
  318. package/src/model-context/tool-call-text.ts +67 -0
  319. package/src/model-context/types.test.ts +25 -0
  320. package/src/model-context/types.ts +9 -4
  321. package/src/react/AssistantRuntimeProvider.test.tsx +66 -2
  322. package/src/react/RuntimeAdapter.test.ts +34 -0
  323. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +1 -3
  324. package/src/react/client/InMemoryThreadList.ts +1 -0
  325. package/src/react/client/Interactables.test.ts +28 -0
  326. package/src/react/client/Interactables.ts +15 -13
  327. package/src/react/client/RemoteThreadList.background.test.ts +526 -0
  328. package/src/react/client/RemoteThreadList.concurrent.test.tsx +315 -0
  329. package/src/react/client/RemoteThreadList.test.ts +617 -3
  330. package/src/react/client/RemoteThreadList.ts +433 -167
  331. package/src/react/client/Tools.ts +29 -12
  332. package/src/react/index.ts +4 -0
  333. package/src/react/interactables-legacy/Interactables.ts +16 -16
  334. package/src/react/interactables-shared/useInteractablePersistenceQueue.ts +9 -10
  335. package/src/react/model-context/makeAssistantTool.ts +2 -2
  336. package/src/react/model-context/modelContextHooks.test.tsx +131 -0
  337. package/src/react/model-context/toolbox.test.ts +9 -9
  338. package/src/react/model-context/toolbox.ts +9 -36
  339. package/src/react/model-context/useAssistantContext.ts +4 -2
  340. package/src/react/model-context/useAssistantTool.ts +2 -2
  341. package/src/react/model-context/useAuiToolOverrides.ts +4 -2
  342. package/src/react/model-context/useInlineRender.test.tsx +48 -0
  343. package/src/react/model-context/useInlineRender.ts +14 -10
  344. package/src/react/model-context/useToolArgsStatus.test.tsx +30 -0
  345. package/src/react/model-context/useToolArgsStatus.ts +2 -1
  346. package/src/react/primitive-hooks/useMessageError.ts +2 -19
  347. package/src/react/primitive-hooks/useThreadListLoadMore.ts +2 -3
  348. package/src/react/primitives/composer/ComposerAttachments.test.tsx +76 -0
  349. package/src/react/primitives/composer/ComposerAttachments.tsx +9 -4
  350. package/src/react/primitives/composer/ComposerQueue.test.tsx +72 -0
  351. package/src/react/primitives/composer/ComposerQueue.tsx +7 -4
  352. package/src/react/primitives/message/MessageAttachments.test.tsx +107 -37
  353. package/src/react/primitives/message/MessageAttachments.tsx +10 -7
  354. package/src/react/primitives/message/MessageGroupedParts.tsx +2 -2
  355. package/src/react/primitives/message/MessageParts.tsx +3 -3
  356. package/src/react/primitives/threadList/ThreadListItems.test.tsx +99 -0
  357. package/src/react/primitives/threadList/ThreadListItems.tsx +8 -5
  358. package/src/react/runtimes/RemoteThreadListHookInstanceManager.destroy.test.tsx +172 -0
  359. package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +127 -1
  360. package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +7 -1
  361. package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +99 -35
  362. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.load-error.test.ts +132 -0
  363. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.switch-delete.test.ts +274 -0
  364. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +223 -152
  365. package/src/react/runtimes/RemoteThreadResource.test.ts +9 -0
  366. package/src/react/runtimes/RemoteThreadResource.ts +20 -16
  367. package/src/react/runtimes/assistant-transport/transport-scheduling.test.ts +51 -2
  368. package/src/react/runtimes/assistant-transport/useLatestRef.ts +2 -2
  369. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.ts +45 -0
  370. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +546 -5
  371. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +546 -103
  372. package/src/react/runtimes/cloud/auiV0.ts +5 -0
  373. package/src/react/runtimes/cloud/createCloudThreadListAdapter.test.ts +103 -0
  374. package/src/react/runtimes/cloud/createCloudThreadListAdapter.ts +237 -0
  375. package/src/react/runtimes/cloud/useCloudThreadListAdapter.test.tsx +90 -1
  376. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +33 -238
  377. package/src/react/runtimes/external-message-converter.ts +1 -0
  378. package/src/react/runtimes/useExternalStoreRuntime.lifecycle.test.tsx +41 -0
  379. package/src/react/runtimes/useExternalStoreRuntime.ts +10 -4
  380. package/src/react/runtimes/useLocalRuntime.test.tsx +20 -0
  381. package/src/react/runtimes/useRemoteThreadListRuntime.concurrent.test.tsx +216 -0
  382. package/src/react/runtimes/useRemoteThreadListRuntime.load-error.test.tsx +108 -0
  383. package/src/react/runtimes/useRemoteThreadListRuntime.ts +57 -6
  384. package/src/react/types/MessagePartComponentTypes.ts +7 -3
  385. package/src/react/types/scopes/tools.ts +2 -0
  386. package/src/runtime/api/message-part-runtime.ts +3 -3
  387. package/src/runtime/api/message-runtime.test.ts +75 -0
  388. package/src/runtime/api/thread-list-item-runtime.ts +10 -3
  389. package/src/runtime/api/thread-list-runtime.ts +46 -12
  390. package/src/runtime/api/thread-runtime.test.ts +78 -0
  391. package/src/runtime/api/thread-runtime.ts +8 -1
  392. package/src/runtime/base/base-composer-runtime-core.ts +36 -8
  393. package/src/runtime/base/base-thread-runtime-core.test.ts +149 -4
  394. package/src/runtime/base/base-thread-runtime-core.ts +16 -8
  395. package/src/runtime/interfaces/composer-runtime-core.ts +10 -5
  396. package/src/runtime/interfaces/thread-list-runtime-core.ts +25 -2
  397. package/src/runtime/interfaces/thread-runtime-core.ts +17 -1
  398. package/src/runtime/utils/auto-status.test.ts +57 -0
  399. package/src/runtime/utils/auto-status.ts +13 -1
  400. package/src/runtime/utils/external-message-conversion.test.ts +165 -0
  401. package/src/runtime/utils/external-message-conversion.ts +18 -2
  402. package/src/runtime/utils/message-repository.ts +29 -17
  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 +3 -11
  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 +18 -13
  410. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +56 -33
  411. package/src/runtimes/inert/InertThreadRuntimeCore.ts +1 -1
  412. package/src/runtimes/internal.ts +1 -0
  413. package/src/runtimes/local/local-thread-runtime-core.test.ts +29 -3
  414. package/src/runtimes/local/local-thread-runtime-core.ts +5 -1
  415. package/src/runtimes/remote-thread-list/remote-thread-state.test.ts +238 -0
  416. package/src/runtimes/remote-thread-list/remote-thread-state.ts +223 -44
  417. package/src/runtimes/remote-thread-list/title-generation.test.ts +602 -0
  418. package/src/runtimes/remote-thread-list/title-generation.ts +329 -0
  419. package/src/runtimes/remote-thread-list/title.test.ts +62 -0
  420. package/src/runtimes/remote-thread-list/title.ts +16 -0
  421. package/src/runtimes/remote-thread-list/types.ts +16 -5
  422. package/src/runtimes/tool-invocations/EDGE_CASES.md +110 -5
  423. package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +750 -136
  424. package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +144 -91
  425. package/src/store/clients/external-thread.ts +62 -11
  426. package/src/store/clients/model-context-client.ts +5 -1
  427. package/src/store/clients/single-thread-list.ts +1 -0
  428. package/src/store/clients/suggestions.test.ts +195 -1
  429. package/src/store/clients/suggestions.ts +45 -34
  430. package/src/store/index.ts +4 -0
  431. package/src/store/internal.ts +2 -0
  432. package/src/store/primitive-predicates.ts +35 -0
  433. package/src/store/runtime-clients/composer-runtime-client.ts +42 -9
  434. package/src/store/runtime-clients/message-runtime-client.ts +54 -6
  435. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +4 -2
  436. package/src/store/runtime-clients/thread-list-runtime-client.ts +17 -2
  437. package/src/store/runtime-clients/thread-runtime-client.ts +58 -10
  438. package/src/store/runtime-clients/useSubscribable.ts +8 -2
  439. package/src/store/scopes/composer.ts +16 -4
  440. package/src/store/scopes/message.ts +14 -0
  441. package/src/store/scopes/part.ts +6 -3
  442. package/src/store/scopes/thread-list-item.ts +5 -2
  443. package/src/store/scopes/thread.ts +4 -0
  444. package/src/store/scopes/threads.ts +1 -0
  445. package/src/subscribable/subscribable.test.ts +50 -0
  446. package/src/subscribable/subscribable.ts +33 -21
  447. package/src/tests/MessageRepository.test.ts +116 -0
  448. package/src/tests/OptimisticState-list-race.test.ts +1 -0
  449. package/src/tests/RemoteThreadListThreadListRuntimeCore-initialize-adapter-change.test.ts +38 -0
  450. package/src/tests/RemoteThreadListThreadListRuntimeCore-load-race.test.ts +158 -0
  451. package/src/tests/RemoteThreadListThreadListRuntimeCore-loadMore.test.ts +78 -0
  452. package/src/tests/RemoteThreadListThreadListRuntimeCore-reload.test.ts +52 -0
  453. package/src/tests/RemoteThreadListThreadListRuntimeCore-title-race.test.ts +89 -0
  454. package/src/tests/attachment-adapters.test.ts +14 -0
  455. package/src/tests/base-composer-runtime-core.test.ts +39 -0
  456. package/src/tests/external-store-optimistic-id.test.ts +79 -0
  457. package/src/tests/external-store-repository-instance.test.ts +166 -0
  458. package/src/tests/external-store-thread-list-runtime-core.test.ts +83 -0
  459. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +49 -34
  460. package/src/tests/external-thread-attachments.test.tsx +224 -1
  461. package/src/tests/external-thread-parity.test.tsx +23 -0
  462. package/src/tests/remote-thread-list-adapter-switch.test.ts +66 -1
  463. package/src/tests/remote-thread-list-isLoading.test.ts +1 -0
  464. package/src/tests/thread-list-runtime-getLoadThreadsPromise.test.ts +1 -0
  465. package/src/tests/thread-switch-events.test.tsx +475 -2
  466. package/src/tests/tools-scope-migration.test.tsx +28 -0
  467. package/src/types/attachment.ts +4 -0
  468. package/src/types/message.ts +50 -2
  469. package/src/utils/abortable-iterable.test.ts +213 -0
  470. package/src/utils/abortable-iterable.ts +93 -0
  471. package/src/utils/composite-context-provider.test.ts +25 -0
  472. package/src/utils/composite-context-provider.ts +23 -2
  473. package/src/utils/record.test.ts +48 -0
  474. package/src/utils/record.ts +11 -0
@@ -1,8 +1,17 @@
1
- import type { ThreadListRuntimeCore } from "../../runtime/interfaces/thread-list-runtime-core";
2
- 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";
10
+ import { nullProtoRecord } from "../../utils/record";
3
11
  import { OptimisticState } from "../../runtimes/remote-thread-list/optimistic-state";
4
12
  import { EMPTY_THREAD_CORE } from "../../runtimes/remote-thread-list/empty-thread-core";
5
13
  import type {
14
+ ClassifyAccumulator,
6
15
  RemoteThreadData,
7
16
  RemoteThreadState,
8
17
  } from "../../runtimes/remote-thread-list/remote-thread-state";
@@ -12,6 +21,8 @@ import {
12
21
  createThreadMappingId,
13
22
  getThreadData,
14
23
  normalizeCursor,
24
+ reconcileInitializedThread,
25
+ promoteNewThreadReducer,
15
26
  updateStatusReducer,
16
27
  preserveMidLoadTransitions,
17
28
  seedNewThread,
@@ -24,7 +35,17 @@ import type {
24
35
  } from "../../runtimes/remote-thread-list/types";
25
36
  import { ThreadListAdapterChangedError } from "../../runtimes/remote-thread-list/adapter-changed";
26
37
  import { RemoteThreadListHookInstanceManager } from "./RemoteThreadListHookInstanceManager";
27
- import { isTitleSourceMessage } from "./RemoteThreadResource";
38
+ import {
39
+ applyTitleStream,
40
+ isTitleSourceMessage,
41
+ } from "../../runtimes/remote-thread-list/title";
42
+ import {
43
+ clearThreadTitleState,
44
+ finishThreadTitleRename,
45
+ runThreadTitleGeneration,
46
+ startThreadTitleRename,
47
+ type ThreadTitleState,
48
+ } from "../../runtimes/remote-thread-list/title-generation";
28
49
  import {
29
50
  type ComponentType,
30
51
  type FC,
@@ -34,8 +55,6 @@ import {
34
55
  useId,
35
56
  } from "react";
36
57
  import { useAui } from "@assistant-ui/store";
37
- import { create } from "zustand";
38
- import { AssistantMessageStream } from "assistant-stream";
39
58
  import type { ModelContextProvider } from "../../model-context/types";
40
59
  import { RuntimeAdapterProvider } from "./RuntimeAdapterProvider";
41
60
  import { useStableRuntimeAdapters } from "./useRuntimeAdapters";
@@ -70,6 +89,7 @@ export class RemoteThreadListThreadListRuntimeCore
70
89
  private _staleThreadIdsOnReplace: ReadonlySet<string> | undefined;
71
90
  private _switchGeneration = 0;
72
91
  private _switchTask: Promise<void> | undefined;
92
+ private readonly _titleStates = new Map<string, ThreadTitleState>();
73
93
 
74
94
  private _mainThreadId!: string;
75
95
  private readonly _state = new OptimisticState<RemoteThreadState>(
@@ -126,9 +146,11 @@ export class RemoteThreadListThreadListRuntimeCore
126
146
  .optimisticUpdate({
127
147
  execute: () => this._options.adapter.list(),
128
148
  loading: (state) => {
149
+ if (generation !== this._loadGeneration) return state;
129
150
  return {
130
151
  ...state,
131
152
  isLoading: true,
153
+ loadError: undefined,
132
154
  };
133
155
  },
134
156
  then: (state, l) => {
@@ -138,7 +160,7 @@ export class RemoteThreadListThreadListRuntimeCore
138
160
  this._replaceListOnNextLoad = false;
139
161
  replacedList = true;
140
162
  return this._replaceWithThreads(
141
- state,
163
+ { ...state, loadError: undefined },
142
164
  l.threads,
143
165
  normalizeCursor(l.nextCursor),
144
166
  );
@@ -147,17 +169,18 @@ export class RemoteThreadListThreadListRuntimeCore
147
169
  const fresh = classifyThreads(l.threads, {
148
170
  threadIds: [],
149
171
  archivedThreadIds: [],
150
- threadIdMap: {},
151
- threadData: {},
172
+ threadIdMap: { ...state.threadIdMap },
173
+ threadData: { ...state.threadData },
152
174
  });
153
175
  const merged = {
154
176
  ...state,
155
177
  isLoading: false,
178
+ loadError: undefined,
156
179
  cursor: normalizeCursor(l.nextCursor),
157
180
  threadIds: fresh.threadIds,
158
181
  archivedThreadIds: fresh.archivedThreadIds,
159
- threadIdMap: { ...state.threadIdMap, ...fresh.threadIdMap },
160
- threadData: { ...state.threadData, ...fresh.threadData },
182
+ threadIdMap: fresh.threadIdMap,
183
+ threadData: fresh.threadData,
161
184
  };
162
185
  return preserveMidLoadTransitions(merged, state, statusAtRequest);
163
186
  },
@@ -170,13 +193,18 @@ export class RemoteThreadListThreadListRuntimeCore
170
193
  this._state.update({
171
194
  ...this._state.baseValue,
172
195
  isLoading: false,
196
+ loadError: error,
173
197
  });
174
198
  return;
175
199
  }
176
200
  this._replaceListOnNextLoad = false;
177
201
  replacedList = true;
178
202
  this._state.update(
179
- this._replaceWithThreads(this._state.baseValue, [], undefined),
203
+ this._replaceWithThreads(
204
+ { ...this._state.baseValue, loadError: error },
205
+ [],
206
+ undefined,
207
+ ),
180
208
  );
181
209
  })
182
210
  .then(() => {
@@ -206,7 +234,10 @@ export class RemoteThreadListThreadListRuntimeCore
206
234
  const dedup = this._state
207
235
  .optimisticUpdate({
208
236
  execute: () => adapter.list({ after: cursor }),
209
- loading: (state) => ({ ...state, isLoadingMore: true }),
237
+ loading: (state) => {
238
+ if (generation !== this._loadGeneration) return state;
239
+ return { ...state, isLoadingMore: true };
240
+ },
210
241
  then: (state, l) => {
211
242
  if (generation !== this._loadGeneration) return state;
212
243
  if (adapter !== this._options.adapter) return state;
@@ -267,15 +298,15 @@ export class RemoteThreadListThreadListRuntimeCore
267
298
  // synchronous notify would re-enter store consumers mid-render.
268
299
  queueMicrotask(() => this._notifySubscribers());
269
300
  });
270
- this.useProvider = create(() => ({
271
- Provider: this.resolveProvider(options.adapter),
272
- }));
301
+ this.providerStore = new WritableSubscribable(
302
+ this.resolveProvider(options.adapter),
303
+ );
273
304
  this.__internal_setOptions(options);
274
305
  this.switchToNewThread();
275
306
  }
276
307
 
277
308
  private _initialThreadLoaded = false;
278
- private useProvider;
309
+ private providerStore;
279
310
 
280
311
  public __internal_setOptions(options: RemoteThreadListOptions) {
281
312
  if (this._options === options) return;
@@ -289,10 +320,7 @@ export class RemoteThreadListThreadListRuntimeCore
289
320
 
290
321
  this._options = options;
291
322
 
292
- const Provider = this.resolveProvider(options.adapter);
293
- if (Provider !== this.useProvider.getState().Provider) {
294
- this.useProvider.setState({ Provider }, true);
295
- }
323
+ this.providerStore.setState(this.resolveProvider(options.adapter));
296
324
 
297
325
  this._hookManager.setRuntimeHook(options.runtimeHook);
298
326
 
@@ -312,7 +340,9 @@ export class RemoteThreadListThreadListRuntimeCore
312
340
  this._state.update({
313
341
  ...this._state.baseValue,
314
342
  cursor: undefined,
343
+ loadError: undefined,
315
344
  });
345
+ this._titleStates.clear();
316
346
  }
317
347
 
318
348
  if (controlledThreadIdChanged) {
@@ -337,24 +367,16 @@ export class RemoteThreadListThreadListRuntimeCore
337
367
  threads: readonly RemoteThreadMetadata[],
338
368
  cursor: string | undefined,
339
369
  ): RemoteThreadState {
340
- const fresh = classifyThreads(threads, {
341
- threadIds: [],
342
- archivedThreadIds: [],
343
- threadIdMap: {},
344
- threadData: {},
345
- });
346
- const threadIdMap = { ...fresh.threadIdMap };
347
- const threadData = { ...fresh.threadData };
348
- const threadIds = [...fresh.threadIds];
349
- const archivedThreadIds = [...fresh.archivedThreadIds];
350
-
370
+ const carried: RemoteThreadData[] = [];
351
371
  if (state.newThreadId) {
352
- const mappingId = state.threadIdMap[state.newThreadId];
353
- const draft = mappingId ? state.threadData[mappingId] : undefined;
354
- if (draft?.status === "new") {
355
- threadIdMap[state.newThreadId] = mappingId!;
356
- threadData[mappingId!] = draft;
357
- }
372
+ const mappingId = Object.hasOwn(state.threadIdMap, state.newThreadId)
373
+ ? state.threadIdMap[state.newThreadId]
374
+ : undefined;
375
+ const draft =
376
+ mappingId && Object.hasOwn(state.threadData, mappingId)
377
+ ? state.threadData[mappingId]
378
+ : undefined;
379
+ if (draft?.status === "new") carried.push(draft);
358
380
  }
359
381
 
360
382
  const stale = this._staleThreadIdsOnReplace;
@@ -362,26 +384,47 @@ export class RemoteThreadListThreadListRuntimeCore
362
384
  for (const item of Object.values(state.threadData)) {
363
385
  if (stale.has(item.id)) continue;
364
386
  if (item.status !== "new" && item.remoteId === undefined) continue;
365
- const mappingId = createThreadMappingId(item.id);
366
- if (threadData[mappingId]) continue;
367
- threadIdMap[item.id] = mappingId;
368
- if (item.remoteId !== undefined) {
369
- threadIdMap[item.remoteId] = mappingId;
370
- }
371
- threadData[mappingId] = item;
372
- if (item.remoteId === undefined) continue;
373
- if (item.status === "regular" && !threadIds.includes(item.remoteId)) {
374
- threadIds.push(item.remoteId);
375
- } else if (
376
- item.status === "archived" &&
377
- !archivedThreadIds.includes(item.remoteId)
378
- ) {
379
- archivedThreadIds.push(item.remoteId);
380
- }
387
+ carried.push(item);
381
388
  }
382
389
  }
383
390
  this._staleThreadIdsOnReplace = undefined;
384
391
 
392
+ const seed: ClassifyAccumulator = {
393
+ threadIds: [],
394
+ archivedThreadIds: [],
395
+ threadIdMap: nullProtoRecord(),
396
+ threadData: nullProtoRecord(),
397
+ };
398
+ for (const item of carried) {
399
+ const mappingId = createThreadMappingId(item.id);
400
+ if (Object.hasOwn(seed.threadData, mappingId)) continue;
401
+ seed.threadIdMap[item.id] = mappingId;
402
+ if (item.remoteId !== undefined) {
403
+ seed.threadIdMap[item.remoteId] = mappingId;
404
+ }
405
+ seed.threadData[mappingId] = item;
406
+ }
407
+
408
+ const { threadIds, archivedThreadIds, threadIdMap, threadData } =
409
+ classifyThreads(threads, seed);
410
+
411
+ for (const item of carried) {
412
+ if (item.remoteId === undefined) continue;
413
+ const currentMappingId = createThreadMappingId(item.id);
414
+ const current = Object.hasOwn(threadData, currentMappingId)
415
+ ? threadData[currentMappingId]
416
+ : undefined;
417
+ if (current === undefined) continue;
418
+ if (current.status === "regular" && !threadIds.includes(current.id)) {
419
+ threadIds.push(current.id);
420
+ } else if (
421
+ current.status === "archived" &&
422
+ !archivedThreadIds.includes(current.id)
423
+ ) {
424
+ archivedThreadIds.push(current.id);
425
+ }
426
+ }
427
+
385
428
  let nextState: RemoteThreadState = {
386
429
  ...state,
387
430
  isLoading: false,
@@ -392,7 +435,7 @@ export class RemoteThreadListThreadListRuntimeCore
392
435
  threadData,
393
436
  newThreadId:
394
437
  state.newThreadId !== undefined &&
395
- threadIdMap[state.newThreadId] === undefined
438
+ !Object.hasOwn(threadIdMap, state.newThreadId)
396
439
  ? undefined
397
440
  : state.newThreadId,
398
441
  };
@@ -488,6 +531,10 @@ export class RemoteThreadListThreadListRuntimeCore
488
531
  return this._state.value.isLoading;
489
532
  }
490
533
 
534
+ public get loadError() {
535
+ return this._state.value.loadError;
536
+ }
537
+
491
538
  public get isLoadingMore() {
492
539
  return this._state.value.isLoadingMore;
493
540
  }
@@ -555,6 +602,12 @@ export class RemoteThreadListThreadListRuntimeCore
555
602
  return this._hookManager.__internal_isThreadRunning(data.id);
556
603
  }
557
604
 
605
+ public unstable_subscribeThreadEvents(
606
+ callback: (event: ThreadListRuntimeEvent) => void,
607
+ ) {
608
+ return this._hookManager.__internal_subscribeThreadEvents(callback);
609
+ }
610
+
558
611
  public getItemById(threadIdOrRemoteId: string) {
559
612
  return getThreadData(this._state.value, threadIdOrRemoteId);
560
613
  }
@@ -629,9 +682,8 @@ export class RemoteThreadListThreadListRuntimeCore
629
682
  // A concurrent `list()` may already have placed this thread; keep that
630
683
  // position and only merge metadata. A genuinely absent thread stays
631
684
  // appended: it may live on an unloaded page, and a prepend would pin it
632
- // above newer threads permanently since `classifyThreads` skips ids it
633
- // has already seen. Filtering both arrays first still prevents
634
- // duplication or a wrong-status entry from `list()`.
685
+ // above newer threads permanently. Filtering both arrays first still
686
+ // prevents duplication or a wrong-status entry from `list()`.
635
687
  const remoteId = remoteMetadata.remoteId;
636
688
  const wasInTarget =
637
689
  remoteMetadata.status === "regular"
@@ -684,11 +736,22 @@ export class RemoteThreadListThreadListRuntimeCore
684
736
 
685
737
  if (generation !== this._switchGeneration) return;
686
738
 
687
- if (data.status === "archived" && options?.unarchive !== false) {
688
- await this.unarchive(data.id);
739
+ let current = this.getItemById(data.id);
740
+ if (current?.id !== data.id) return;
741
+
742
+ if (current.status === "archived" && options?.unarchive !== false) {
743
+ await current.initializeTask;
689
744
  if (generation !== this._switchGeneration) return;
745
+ current = this.getItemById(data.id);
746
+ if (current?.id !== data.id) return;
747
+ if (current.status === "archived") {
748
+ await this.unarchive(current.id);
749
+ if (generation !== this._switchGeneration) return;
750
+ current = this.getItemById(data.id);
751
+ if (current?.id !== data.id) return;
752
+ }
690
753
  }
691
- this._mainThreadId = data.id;
754
+ this._mainThreadId = current.id;
692
755
 
693
756
  this._notifySubscribers();
694
757
  this._notifyThreadIdChange(emitThreadIdChange);
@@ -749,56 +812,40 @@ export class RemoteThreadListThreadListRuntimeCore
749
812
  return { remoteId, externalId };
750
813
  }
751
814
 
815
+ this._requireAdapterGeneration(adapterGeneration);
816
+ const initializeTask = adapter.initialize(threadId);
817
+ let removedMappingId: string | undefined;
752
818
  const { remoteId, externalId } = await this._state.optimisticUpdate({
753
- execute: () => {
754
- this._requireAdapterGeneration(adapterGeneration);
755
- return adapter.initialize(threadId);
756
- },
757
- optimistic: (state) => {
758
- return updateStatusReducer(state, threadId, "regular");
759
- },
760
- loading: (state, task) => {
761
- const mappingId = createThreadMappingId(threadId);
762
- return {
763
- ...state,
764
- threadData: {
765
- ...state.threadData,
766
- [mappingId]: {
767
- ...state.threadData[mappingId],
768
- initializeTask: task,
769
- },
770
- },
771
- };
772
- },
819
+ execute: () => initializeTask,
820
+ optimistic: (state) =>
821
+ promoteNewThreadReducer(state, threadId, initializeTask),
773
822
  then: (state, { remoteId, externalId }) => {
774
823
  if (adapterGeneration !== this._adapterGeneration) return state;
775
- const data = getThreadData(state, threadId);
776
- if (!data) return state;
777
-
778
- const mappingId = createThreadMappingId(threadId);
779
- return {
780
- ...state,
781
- threadIdMap: {
782
- ...state.threadIdMap,
783
- [remoteId]: mappingId,
784
- },
785
- threadData: {
786
- ...state.threadData,
787
- [mappingId]: {
788
- ...data,
789
- initializeTask: Promise.resolve({ remoteId, externalId }),
790
- remoteId,
791
- externalId,
792
- },
793
- },
794
- };
824
+ const reconciliation = reconcileInitializedThread(
825
+ state,
826
+ threadId,
827
+ remoteId,
828
+ externalId,
829
+ threadId,
830
+ );
831
+ removedMappingId = reconciliation.removedMappingId;
832
+ if (removedMappingId === this._mainThreadId) {
833
+ this._mainThreadId = reconciliation.survivorMappingId;
834
+ }
835
+ return reconciliation.state;
795
836
  },
796
837
  });
797
838
  this._requireAdapterGeneration(adapterGeneration);
839
+ if (removedMappingId !== undefined) {
840
+ this._hookManager.stopThreadRuntime(removedMappingId);
841
+ }
798
842
  return { remoteId, externalId };
799
843
  };
800
844
 
801
- public generateTitle = async (threadId: string) => {
845
+ public generateTitle = async (
846
+ threadId: string,
847
+ options?: { automatic?: boolean },
848
+ ) => {
802
849
  this._requireAdapterSettled();
803
850
  const adapter = this._options.adapter;
804
851
  const adapterGeneration = this._adapterGeneration;
@@ -817,30 +864,40 @@ export class RemoteThreadListThreadListRuntimeCore
817
864
  // would make the payload race-dependent; the title reads settled
818
865
  // messages only, matching the trigger's readiness gate.
819
866
  const messages = runtimeCore.messages.filter(isTitleSourceMessage);
820
- const stream = await adapter.generateTitle(remoteId, messages);
821
- const messageStream = AssistantMessageStream.fromAssistantStream(stream);
822
- for await (const result of messageStream) {
823
- if (adapterGeneration !== this._adapterGeneration) return;
824
- const newTitle = result.parts.filter((c) => c.type === "text")[0]?.text;
825
- await this._state.optimisticUpdate({
826
- execute: async () => {},
827
- optimistic: (state) => {
828
- if (adapterGeneration !== this._adapterGeneration) return state;
829
- const currentData = getThreadData(state, data.id);
830
- if (!currentData) return state;
831
- return {
832
- ...state,
833
- threadData: {
834
- ...state.threadData,
835
- [currentData.id]: {
836
- ...currentData,
837
- title: newTitle,
867
+ await runThreadTitleGeneration({
868
+ states: this._titleStates,
869
+ threadId: data.id,
870
+ automatic: options?.automatic === true,
871
+ generate: async (onTitle) => {
872
+ const stream = await adapter.generateTitle(remoteId, messages);
873
+ this._requireAdapterGeneration(adapterGeneration);
874
+ await applyTitleStream(stream, onTitle);
875
+ },
876
+ rename: async (title) => {
877
+ this._requireAdapterGeneration(adapterGeneration);
878
+ await adapter.rename(remoteId, title);
879
+ },
880
+ applyTitle: async (title) => {
881
+ await this._state.optimisticUpdate({
882
+ execute: async () => {},
883
+ optimistic: (state) => {
884
+ if (adapterGeneration !== this._adapterGeneration) return state;
885
+ const currentData = getThreadData(state, data.id);
886
+ if (!currentData) return state;
887
+ return {
888
+ ...state,
889
+ threadData: {
890
+ ...state.threadData,
891
+ [currentData.id]: {
892
+ ...currentData,
893
+ title,
894
+ },
838
895
  },
839
- },
840
- };
841
- },
842
- });
843
- }
896
+ };
897
+ },
898
+ });
899
+ },
900
+ });
844
901
  };
845
902
 
846
903
  public async rename(
@@ -855,28 +912,36 @@ export class RemoteThreadListThreadListRuntimeCore
855
912
  if (data.status === "new")
856
913
  throw threadStatusError(threadIdOrRemoteId, data.status, "be renamed");
857
914
 
858
- return this._state.optimisticUpdate({
859
- execute: async () => {
860
- const { remoteId } = await data.initializeTask;
861
- this._requireAdapterGeneration(adapterGeneration);
862
- return adapter.rename(remoteId, newTitle);
863
- },
864
- optimistic: (state) => {
865
- const data = getThreadData(state, threadIdOrRemoteId);
866
- if (!data) return state;
915
+ const claim = startThreadTitleRename(this._titleStates, data.id, newTitle);
916
+ try {
917
+ const result = await this._state.optimisticUpdate({
918
+ execute: async () => {
919
+ const { remoteId } = await data.initializeTask;
920
+ this._requireAdapterGeneration(adapterGeneration);
921
+ return adapter.rename(remoteId, newTitle);
922
+ },
923
+ optimistic: (state) => {
924
+ const currentData = getThreadData(state, threadIdOrRemoteId);
925
+ if (!currentData) return state;
867
926
 
868
- return {
869
- ...state,
870
- threadData: {
871
- ...state.threadData,
872
- [data.id]: {
873
- ...data,
874
- title: newTitle,
927
+ return {
928
+ ...state,
929
+ threadData: {
930
+ ...state.threadData,
931
+ [currentData.id]: {
932
+ ...currentData,
933
+ title: newTitle,
934
+ },
875
935
  },
876
- },
877
- };
878
- },
879
- });
936
+ };
937
+ },
938
+ });
939
+ finishThreadTitleRename(this._titleStates, data.id, claim, true);
940
+ return result;
941
+ } catch (error) {
942
+ finishThreadTitleRename(this._titleStates, data.id, claim, false);
943
+ throw error;
944
+ }
880
945
  }
881
946
 
882
947
  public async updateCustom(
@@ -1019,9 +1084,7 @@ export class RemoteThreadListThreadListRuntimeCore
1019
1084
 
1020
1085
  await this._ensureThreadIsNotMain(data.id);
1021
1086
  this._requireAdapterGeneration(adapterGeneration);
1022
- this._hookManager.stopThreadRuntime(data.id);
1023
-
1024
- return this._state.optimisticUpdate({
1087
+ const result = await this._state.optimisticUpdate({
1025
1088
  execute: async () => {
1026
1089
  const { remoteId } = await data.initializeTask;
1027
1090
  this._requireAdapterGeneration(adapterGeneration);
@@ -1031,6 +1094,12 @@ export class RemoteThreadListThreadListRuntimeCore
1031
1094
  return updateStatusReducer(state, data.id, "deleted");
1032
1095
  },
1033
1096
  });
1097
+ // The optimistic layer survives an adapter swap, so a resolved deletion has
1098
+ // dropped the slot from `threadData`, where `_replaceWithThreads` would
1099
+ // otherwise have found it to stop.
1100
+ this._hookManager.stopThreadRuntime(data.id);
1101
+ clearThreadTitleState(this._titleStates, data.id);
1102
+ return result;
1034
1103
  }
1035
1104
 
1036
1105
  public __internal_dispose() {
@@ -1049,19 +1118,21 @@ export class RemoteThreadListThreadListRuntimeCore
1049
1118
  this._hookManager.stopThreadRuntime(data.id);
1050
1119
  }
1051
1120
 
1052
- private useBoundIds = create<string[]>(() => []);
1121
+ private boundIdsStore = new WritableSubscribable<readonly string[]>([]);
1053
1122
 
1054
1123
  public __internal_RenderComponent: FC = () => {
1055
1124
  const id = useId();
1056
1125
  useEffect(() => {
1057
- this.useBoundIds.setState((s) => [...s, id], true);
1126
+ this.boundIdsStore.setState([...this.boundIdsStore.getState(), id]);
1058
1127
  return () => {
1059
- this.useBoundIds.setState((s) => s.filter((i) => i !== id), true);
1128
+ this.boundIdsStore.setState(
1129
+ this.boundIdsStore.getState().filter((i) => i !== id),
1130
+ );
1060
1131
  };
1061
1132
  }, [id]);
1062
1133
 
1063
- const boundIds = this.useBoundIds();
1064
- const { Provider } = this.useProvider();
1134
+ const boundIds = useSubscribable(this.boundIdsStore);
1135
+ const Provider = useSubscribable(this.providerStore);
1065
1136
  const aui = useAui();
1066
1137
  const enabled = boundIds.length === 0 || boundIds[0] === id;
1067
1138
 
@@ -53,6 +53,9 @@ describe("subscribeToTitleGeneration", () => {
53
53
 
54
54
  await vi.waitFor(() => {
55
55
  expect(itemRuntime.generateTitle).toHaveBeenCalledOnce();
56
+ expect(itemRuntime.generateTitle).toHaveBeenCalledWith({
57
+ automatic: true,
58
+ });
56
59
  expect(consoleError).toHaveBeenCalledWith(
57
60
  "[assistant-ui] Thread title generation failed",
58
61
  error,
@@ -97,6 +100,9 @@ describe("subscribeToTitleGeneration", () => {
97
100
 
98
101
  await vi.waitFor(() => {
99
102
  expect(itemRuntime.generateTitle).toHaveBeenCalledOnce();
103
+ expect(itemRuntime.generateTitle).toHaveBeenCalledWith({
104
+ automatic: true,
105
+ });
100
106
  });
101
107
  });
102
108
 
@@ -136,6 +142,9 @@ describe("subscribeToTitleGeneration", () => {
136
142
 
137
143
  await vi.waitFor(() => {
138
144
  expect(itemRuntime.generateTitle).toHaveBeenCalledOnce();
145
+ expect(itemRuntime.generateTitle).toHaveBeenCalledWith({
146
+ automatic: true,
147
+ });
139
148
  });
140
149
  });
141
150
  });