@assistant-ui/core 0.3.14 → 0.3.16

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 (341) hide show
  1. package/dist/adapters/voice.js +11 -0
  2. package/dist/adapters/voice.js.map +1 -1
  3. package/dist/index.js +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 +1 -1
  7. package/dist/model-context/frame/host.d.ts.map +1 -1
  8. package/dist/model-context/frame/host.js +20 -5
  9. package/dist/model-context/frame/host.js.map +1 -1
  10. package/dist/model-context/frame/provider.d.ts +6 -0
  11. package/dist/model-context/frame/provider.d.ts.map +1 -1
  12. package/dist/model-context/frame/provider.js +126 -16
  13. package/dist/model-context/frame/provider.js.map +1 -1
  14. package/dist/model-context/frame/types.d.ts +4 -1
  15. package/dist/model-context/frame/types.d.ts.map +1 -1
  16. package/dist/model-context/frame/types.js.map +1 -1
  17. package/dist/model-context/interactable-composer-metadata.d.ts +1 -1
  18. package/dist/model-context/interactable-composer-metadata.js +1 -1
  19. package/dist/model-context/interactable-composer-metadata.js.map +1 -1
  20. package/dist/model-context/registry.d.ts +2 -2
  21. package/dist/model-context/registry.d.ts.map +1 -1
  22. package/dist/model-context/registry.js +9 -28
  23. package/dist/model-context/registry.js.map +1 -1
  24. package/dist/react/client/InMemoryThreadList.d.ts.map +1 -1
  25. package/dist/react/client/InMemoryThreadList.js +24 -20
  26. package/dist/react/client/InMemoryThreadList.js.map +1 -1
  27. package/dist/react/client/Interactables.d.ts.map +1 -1
  28. package/dist/react/client/Interactables.js +59 -177
  29. package/dist/react/client/Interactables.js.map +1 -1
  30. package/dist/react/client/RemoteThreadList.d.ts +1 -1
  31. package/dist/react/client/RemoteThreadList.d.ts.map +1 -1
  32. package/dist/react/client/RemoteThreadList.js +117 -78
  33. package/dist/react/client/RemoteThreadList.js.map +1 -1
  34. package/dist/react/index.d.ts +2 -1
  35. package/dist/react/interactables-legacy/Interactables.d.ts.map +1 -1
  36. package/dist/react/interactables-legacy/Interactables.js +56 -174
  37. package/dist/react/interactables-legacy/Interactables.js.map +1 -1
  38. package/dist/react/interactables-shared/useInteractablePersistenceQueue.d.ts +24 -0
  39. package/dist/react/interactables-shared/useInteractablePersistenceQueue.d.ts.map +1 -0
  40. package/dist/react/interactables-shared/useInteractablePersistenceQueue.js +138 -0
  41. package/dist/react/interactables-shared/useInteractablePersistenceQueue.js.map +1 -0
  42. package/dist/react/primitive-hooks/useActionBarCopy.js +7 -1
  43. package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
  44. package/dist/react/primitive-hooks/useThreadIsEmpty.d.ts +3 -0
  45. package/dist/react/primitive-hooks/useThreadIsEmpty.d.ts.map +1 -1
  46. package/dist/react/primitive-hooks/useThreadIsEmpty.js +3 -0
  47. package/dist/react/primitive-hooks/useThreadIsEmpty.js.map +1 -1
  48. package/dist/react/primitive-hooks/useThreadIsRunning.d.ts +3 -0
  49. package/dist/react/primitive-hooks/useThreadIsRunning.d.ts.map +1 -1
  50. package/dist/react/primitive-hooks/useThreadIsRunning.js +3 -0
  51. package/dist/react/primitive-hooks/useThreadIsRunning.js.map +1 -1
  52. package/dist/react/primitives/composer/ComposerIf.js.map +1 -1
  53. package/dist/react/primitives/composer/ComposerQueue.d.ts +2 -1
  54. package/dist/react/primitives/composer/ComposerQueue.d.ts.map +1 -1
  55. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  56. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +3 -1
  57. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  58. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +6 -0
  59. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  60. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +7 -1
  61. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  62. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +174 -64
  63. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  64. package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -1
  65. package/dist/react/runtimes/RemoteThreadResource.js +2 -0
  66. package/dist/react/runtimes/RemoteThreadResource.js.map +1 -1
  67. package/dist/react/runtimes/assistant-transport/runManager.d.ts.map +1 -1
  68. package/dist/react/runtimes/assistant-transport/runManager.js +2 -12
  69. package/dist/react/runtimes/assistant-transport/runManager.js.map +1 -1
  70. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -1
  71. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js +1 -1
  72. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js.map +1 -1
  73. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +3 -10
  74. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  75. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +20 -67
  76. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  77. package/dist/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.d.ts +12 -0
  78. package/dist/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.d.ts.map +1 -0
  79. package/dist/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.js +10 -0
  80. package/dist/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.js.map +1 -0
  81. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  82. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +38 -5
  83. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  84. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js.map +1 -1
  85. package/dist/react/runtimes/createMessageConverter.d.ts +2 -1
  86. package/dist/react/runtimes/createMessageConverter.d.ts.map +1 -1
  87. package/dist/react/runtimes/external-message-converter.d.ts +6 -25
  88. package/dist/react/runtimes/external-message-converter.d.ts.map +1 -1
  89. package/dist/react/runtimes/external-message-converter.js +33 -233
  90. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  91. package/dist/runtime/api/composer-runtime.d.ts +1 -1
  92. package/dist/runtime/api/composer-runtime.js.map +1 -1
  93. package/dist/runtime/api/thread-runtime.d.ts +1 -2
  94. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  95. package/dist/runtime/base/base-composer-runtime-core.d.ts +1 -1
  96. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  97. package/dist/runtime/base/base-composer-runtime-core.js +14 -29
  98. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  99. package/dist/runtime/base/base-thread-runtime-core.d.ts +2 -4
  100. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  101. package/dist/runtime/base/base-thread-runtime-core.js +3 -9
  102. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  103. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +1 -1
  104. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
  105. package/dist/runtime/base/default-thread-composer-runtime-core.js +1 -1
  106. package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
  107. package/dist/runtime/interfaces/composer-runtime-core.d.ts +1 -1
  108. package/dist/runtime/interfaces/thread-runtime-core.d.ts +1 -1
  109. package/dist/runtime/internal.d.ts +2 -1
  110. package/dist/runtime/internal.js +2 -1
  111. package/dist/runtime/queue/external-thread-queue-adapter.d.ts +1 -1
  112. package/dist/runtime/queue/message-queue.d.ts.map +1 -1
  113. package/dist/runtime/queue/message-queue.js +1 -1
  114. package/dist/runtime/queue/message-queue.js.map +1 -1
  115. package/dist/runtime/queue/queue-item.d.ts +12 -0
  116. package/dist/runtime/queue/queue-item.d.ts.map +1 -0
  117. package/dist/runtime/queue/queue-item.js +6 -0
  118. package/dist/runtime/queue/queue-item.js.map +1 -0
  119. package/dist/runtime/utils/abortable-thread-load.d.ts +15 -0
  120. package/dist/runtime/utils/abortable-thread-load.d.ts.map +1 -0
  121. package/dist/runtime/utils/abortable-thread-load.js +35 -0
  122. package/dist/runtime/utils/abortable-thread-load.js.map +1 -0
  123. package/dist/runtime/utils/attachment-add-operations.d.ts +18 -0
  124. package/dist/runtime/utils/attachment-add-operations.d.ts.map +1 -0
  125. package/dist/runtime/utils/attachment-add-operations.js +43 -0
  126. package/dist/runtime/utils/attachment-add-operations.js.map +1 -0
  127. package/dist/runtime/utils/auto-status.d.ts +6 -1
  128. package/dist/runtime/utils/auto-status.d.ts.map +1 -1
  129. package/dist/runtime/utils/auto-status.js +7 -1
  130. package/dist/runtime/utils/auto-status.js.map +1 -1
  131. package/dist/runtime/utils/external-message-conversion.d.ts +47 -0
  132. package/dist/runtime/utils/external-message-conversion.d.ts.map +1 -0
  133. package/dist/runtime/utils/external-message-conversion.js +221 -0
  134. package/dist/runtime/utils/external-message-conversion.js.map +1 -0
  135. package/dist/runtime/utils/external-store-message.d.ts +2 -1
  136. package/dist/runtime/utils/external-store-message.d.ts.map +1 -1
  137. package/dist/runtime/utils/external-store-message.js +2 -1
  138. package/dist/runtime/utils/external-store-message.js.map +1 -1
  139. package/dist/runtime/utils/message-repository-session.d.ts +30 -0
  140. package/dist/runtime/utils/message-repository-session.d.ts.map +1 -0
  141. package/dist/runtime/utils/message-repository-session.js +130 -0
  142. package/dist/runtime/utils/message-repository-session.js.map +1 -0
  143. package/dist/runtime/utils/message-repository.d.ts.map +1 -1
  144. package/dist/runtime/utils/message-repository.js +30 -22
  145. package/dist/runtime/utils/message-repository.js.map +1 -1
  146. package/dist/runtime/utils/pending-tool-calls.d.ts +20 -0
  147. package/dist/runtime/utils/pending-tool-calls.d.ts.map +1 -0
  148. package/dist/runtime/utils/pending-tool-calls.js +22 -0
  149. package/dist/runtime/utils/pending-tool-calls.js.map +1 -0
  150. package/dist/runtime/utils/thread-message-like.d.ts +2 -1
  151. package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
  152. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  153. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts +2 -5
  154. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  155. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +3 -10
  156. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  157. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +19 -1
  158. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  159. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +124 -20
  160. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  161. package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts +102 -0
  162. package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts.map +1 -0
  163. package/dist/runtimes/inert/InertThreadRuntimeCore.js +156 -0
  164. package/dist/runtimes/inert/InertThreadRuntimeCore.js.map +1 -0
  165. package/dist/runtimes/local/local-thread-runtime-core.d.ts +3 -1
  166. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  167. package/dist/runtimes/local/local-thread-runtime-core.js +45 -8
  168. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  169. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +12 -60
  170. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
  171. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +10 -145
  172. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
  173. package/dist/runtimes/remote-thread-list/adapter-changed.d.ts +9 -0
  174. package/dist/runtimes/remote-thread-list/adapter-changed.d.ts.map +1 -0
  175. package/dist/runtimes/remote-thread-list/adapter-changed.js +13 -0
  176. package/dist/runtimes/remote-thread-list/adapter-changed.js.map +1 -0
  177. package/dist/runtimes/remote-thread-list/empty-thread-core.d.ts.map +1 -1
  178. package/dist/runtimes/remote-thread-list/empty-thread-core.js +16 -155
  179. package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
  180. package/dist/runtimes/remote-thread-list/optimistic-state.d.ts +2 -0
  181. package/dist/runtimes/remote-thread-list/optimistic-state.d.ts.map +1 -1
  182. package/dist/runtimes/remote-thread-list/optimistic-state.js +11 -0
  183. package/dist/runtimes/remote-thread-list/optimistic-state.js.map +1 -1
  184. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts +12 -1
  185. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts.map +1 -1
  186. package/dist/runtimes/remote-thread-list/remote-thread-state.js +77 -1
  187. package/dist/runtimes/remote-thread-list/remote-thread-state.js.map +1 -1
  188. package/dist/runtimes/remote-thread-list/types.d.ts +3 -0
  189. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  190. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
  191. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +2 -0
  192. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
  193. package/dist/store/clients/external-thread.d.ts.map +1 -1
  194. package/dist/store/clients/external-thread.js +75 -100
  195. package/dist/store/clients/external-thread.js.map +1 -1
  196. package/dist/store/clients/single-thread-list.d.ts.map +1 -1
  197. package/dist/store/clients/single-thread-list.js +1 -1
  198. package/dist/store/clients/single-thread-list.js.map +1 -1
  199. package/dist/store/clients/suggestions.d.ts.map +1 -1
  200. package/dist/store/clients/suggestions.js +16 -7
  201. package/dist/store/clients/suggestions.js.map +1 -1
  202. package/dist/store/index.d.ts +4 -2
  203. package/dist/store/runtime-clients/handle-runtime-action.d.ts.map +1 -1
  204. package/dist/store/runtime-clients/handle-runtime-action.js +2 -0
  205. package/dist/store/runtime-clients/handle-runtime-action.js.map +1 -1
  206. package/dist/store/scope-registration.d.ts +1 -1
  207. package/dist/store/scopes/composer.d.ts +2 -1
  208. package/dist/store/scopes/composer.d.ts.map +1 -1
  209. package/dist/store/scopes/message.d.ts +1 -1
  210. package/dist/store/scopes/queue-item.d.ts +2 -9
  211. package/dist/store/scopes/queue-item.d.ts.map +1 -1
  212. package/dist/store/scopes/queue-item.js +0 -6
  213. package/dist/types/message.d.ts +8 -4
  214. package/dist/types/message.d.ts.map +1 -1
  215. package/dist/types/message.js.map +1 -1
  216. package/dist/utils/data-url.d.ts +14 -1
  217. package/dist/utils/data-url.d.ts.map +1 -1
  218. package/dist/utils/data-url.js +13 -1
  219. package/dist/utils/data-url.js.map +1 -1
  220. package/dist/utils/invoke-user-callback.d.ts +5 -0
  221. package/dist/utils/invoke-user-callback.d.ts.map +1 -0
  222. package/dist/utils/invoke-user-callback.js +19 -0
  223. package/dist/utils/invoke-user-callback.js.map +1 -0
  224. package/dist/utils/normalizePartStatus.js.map +1 -1
  225. package/dist/utils/silent-runtime-action.d.ts +6 -0
  226. package/dist/utils/silent-runtime-action.d.ts.map +1 -0
  227. package/dist/utils/silent-runtime-action.js +7 -0
  228. package/dist/utils/silent-runtime-action.js.map +1 -0
  229. package/package.json +10 -10
  230. package/src/adapters/voice.test.ts +66 -1
  231. package/src/adapters/voice.ts +8 -0
  232. package/src/internal.ts +13 -0
  233. package/src/model-context/frame/host.test.ts +152 -9
  234. package/src/model-context/frame/host.ts +23 -5
  235. package/src/model-context/frame/provider.test.ts +601 -19
  236. package/src/model-context/frame/provider.ts +158 -20
  237. package/src/model-context/frame/types.ts +5 -0
  238. package/src/model-context/interactable-composer-metadata.ts +1 -1
  239. package/src/model-context/registry.test.ts +44 -0
  240. package/src/model-context/registry.ts +13 -35
  241. package/src/react/client/InMemoryThreadList.test.tsx +49 -0
  242. package/src/react/client/InMemoryThreadList.ts +7 -1
  243. package/src/react/client/Interactables.ts +19 -178
  244. package/src/react/client/RemoteThreadList.test.ts +292 -0
  245. package/src/react/client/RemoteThreadList.ts +119 -82
  246. package/src/react/interactables-legacy/Interactables.ts +20 -177
  247. package/src/react/interactables-shared/useInteractablePersistenceQueue.test.tsx +161 -0
  248. package/src/react/interactables-shared/useInteractablePersistenceQueue.ts +206 -0
  249. package/src/react/primitive-hooks/useActionBarCopy.test.ts +15 -0
  250. package/src/react/primitive-hooks/useActionBarCopy.ts +13 -3
  251. package/src/react/primitive-hooks/useThreadIsEmpty.ts +3 -0
  252. package/src/react/primitive-hooks/useThreadIsRunning.ts +3 -0
  253. package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +12 -0
  254. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.republish.test.ts +87 -0
  255. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +251 -76
  256. package/src/react/runtimes/RemoteThreadResource.ts +2 -0
  257. package/src/react/runtimes/assistant-transport/runManager.ts +4 -17
  258. package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.test.tsx +58 -0
  259. package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.ts +3 -1
  260. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +92 -0
  261. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +40 -141
  262. package/src/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.test.ts +37 -0
  263. package/src/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.ts +18 -0
  264. package/src/react/runtimes/cloud/useCloudThreadListAdapter.test.tsx +98 -3
  265. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +68 -6
  266. package/src/react/runtimes/external-message-converter.test.ts +0 -14
  267. package/src/react/runtimes/external-message-converter.test.tsx +77 -0
  268. package/src/react/runtimes/external-message-converter.ts +58 -481
  269. package/src/react/runtimes/useLocalRuntime.test.tsx +5 -5
  270. package/src/runtime/api/composer-runtime.ts +1 -1
  271. package/src/runtime/api/message-runtime.test.ts +28 -1
  272. package/src/runtime/base/base-composer-runtime-core.ts +20 -40
  273. package/src/runtime/base/base-thread-runtime-core.test.ts +16 -0
  274. package/src/runtime/base/base-thread-runtime-core.ts +6 -11
  275. package/src/runtime/base/default-thread-composer-runtime-core.ts +1 -4
  276. package/src/runtime/interfaces/composer-runtime-core.ts +1 -1
  277. package/src/runtime/interfaces/thread-runtime-core.ts +1 -1
  278. package/src/runtime/internal.ts +5 -0
  279. package/src/runtime/queue/external-thread-queue-adapter.ts +1 -1
  280. package/src/runtime/queue/message-queue.ts +1 -4
  281. package/src/runtime/queue/queue-item.ts +10 -0
  282. package/src/runtime/utils/abortable-thread-load.test.ts +87 -0
  283. package/src/runtime/utils/abortable-thread-load.ts +53 -0
  284. package/src/runtime/utils/attachment-add-operations.ts +59 -0
  285. package/src/runtime/utils/auto-status.ts +33 -0
  286. package/src/runtime/utils/external-message-conversion.test.ts +113 -0
  287. package/src/runtime/utils/external-message-conversion.ts +494 -0
  288. package/src/runtime/utils/external-store-message.ts +2 -0
  289. package/src/runtime/utils/message-repository-session.test.ts +195 -0
  290. package/src/runtime/utils/message-repository-session.ts +176 -0
  291. package/src/runtime/utils/message-repository.ts +33 -22
  292. package/src/runtime/utils/pending-tool-calls.test.ts +57 -0
  293. package/src/runtime/utils/pending-tool-calls.ts +35 -0
  294. package/src/runtime/utils/thread-message-like.ts +2 -0
  295. package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +6 -14
  296. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +179 -28
  297. package/src/runtimes/inert/InertThreadRuntimeCore.test.ts +253 -0
  298. package/src/runtimes/inert/InertThreadRuntimeCore.ts +232 -0
  299. package/src/runtimes/local/local-thread-runtime-core.test.ts +491 -1
  300. package/src/runtimes/local/local-thread-runtime-core.ts +86 -11
  301. package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +17 -209
  302. package/src/runtimes/remote-thread-list/adapter-changed.ts +10 -0
  303. package/src/runtimes/remote-thread-list/empty-thread-core.ts +28 -221
  304. package/src/runtimes/remote-thread-list/optimistic-state.test.ts +18 -0
  305. package/src/runtimes/remote-thread-list/optimistic-state.ts +13 -0
  306. package/src/runtimes/remote-thread-list/remote-thread-state.test.ts +37 -0
  307. package/src/runtimes/remote-thread-list/remote-thread-state.ts +123 -0
  308. package/src/runtimes/remote-thread-list/types.ts +4 -0
  309. package/src/runtimes/tool-invocations/EDGE_CASES.md +17 -0
  310. package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +140 -0
  311. package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +3 -0
  312. package/src/store/clients/external-thread.ts +17 -62
  313. package/src/store/clients/single-thread-list.ts +4 -1
  314. package/src/store/clients/suggestions.test.ts +31 -0
  315. package/src/store/clients/suggestions.ts +18 -19
  316. package/src/store/runtime-clients/handle-runtime-action.test.ts +40 -0
  317. package/src/store/runtime-clients/handle-runtime-action.ts +3 -0
  318. package/src/store/scopes/message.ts +1 -1
  319. package/src/store/scopes/queue-item.ts +2 -9
  320. package/src/tests/MessageRepository.test.ts +125 -0
  321. package/src/tests/RemoteThreadListThreadListRuntimeCore-errors.test.ts +2 -2
  322. package/src/tests/RemoteThreadListThreadListRuntimeCore-load-race.test.ts +194 -0
  323. package/src/tests/RemoteThreadListThreadListRuntimeCore-loadMore.test.ts +8 -6
  324. package/src/tests/RemoteThreadListThreadListRuntimeCore-title-race.test.ts +158 -0
  325. package/src/tests/empty-thread-core.test.ts +6 -0
  326. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +184 -0
  327. package/src/tests/external-store-thread-runtime-core.test.ts +642 -0
  328. package/src/tests/external-thread-attachments.test.tsx +173 -0
  329. package/src/tests/external-thread-isEmpty.test.tsx +100 -0
  330. package/src/tests/remote-thread-list-adapter-switch.test.ts +383 -0
  331. package/src/tests/single-thread-list-item.test.tsx +47 -0
  332. package/src/tests/thread-message-like.test.ts +39 -1
  333. package/src/tests/useRemoteThreadListRuntime-controlled.test.tsx +67 -0
  334. package/src/types/message.ts +9 -4
  335. package/src/utils/data-url.test.ts +52 -1
  336. package/src/utils/data-url.ts +21 -0
  337. package/src/utils/invoke-user-callback.test.ts +82 -0
  338. package/src/utils/invoke-user-callback.ts +31 -0
  339. package/src/utils/normalizePartStatus.ts +1 -1
  340. package/src/utils/silent-runtime-action.ts +6 -0
  341. package/dist/store/scopes/queue-item.js.map +0 -1
@@ -0,0 +1,176 @@
1
+ import type { ThreadMessage } from "../../types/message";
2
+ import {
3
+ MessageRepository,
4
+ type ExportedMessageRepository,
5
+ } from "./message-repository";
6
+
7
+ export type MessageRepositorySessionOptions = {
8
+ decorateExport?: (
9
+ exported: ExportedMessageRepository,
10
+ repository: MessageRepository,
11
+ ) => ExportedMessageRepository;
12
+ };
13
+
14
+ export const createMessageRepositorySession = (
15
+ options: MessageRepositorySessionOptions = {},
16
+ ) => {
17
+ const repository = new MessageRepository();
18
+ let exportedRepository: ExportedMessageRepository | undefined;
19
+
20
+ const getMessages = (): readonly ThreadMessage[] => {
21
+ return repository.getMessages();
22
+ };
23
+
24
+ const tryGetMessage = (messageId: string) => {
25
+ try {
26
+ return repository.getMessage(messageId);
27
+ } catch {
28
+ return undefined;
29
+ }
30
+ };
31
+
32
+ const tryGetMessages = (
33
+ messageId: string,
34
+ ): readonly ThreadMessage[] | undefined => {
35
+ try {
36
+ return repository.getMessages(messageId);
37
+ } catch {
38
+ return undefined;
39
+ }
40
+ };
41
+
42
+ const hasMessage = (messageId: string): boolean => {
43
+ return tryGetMessage(messageId) !== undefined;
44
+ };
45
+
46
+ const addOrUpdateMessage = (
47
+ parentId: string | null,
48
+ message: ThreadMessage,
49
+ ): void => {
50
+ repository.addOrUpdateMessage(parentId, message);
51
+ exportedRepository = undefined;
52
+ };
53
+
54
+ const deleteMessage = (
55
+ messageId: string,
56
+ replacementId?: string | null,
57
+ ): void => {
58
+ repository.deleteMessage(messageId, replacementId);
59
+ exportedRepository = undefined;
60
+ };
61
+
62
+ const tryDeleteMessage = (messageId: string): boolean => {
63
+ if (!hasMessage(messageId)) return false;
64
+ deleteMessage(messageId);
65
+ return true;
66
+ };
67
+
68
+ const switchToBranch = (messageId: string): void => {
69
+ repository.switchToBranch(messageId);
70
+ exportedRepository = undefined;
71
+ };
72
+
73
+ const resetHead = (messageId: string | null): void => {
74
+ repository.resetHead(messageId);
75
+ exportedRepository = undefined;
76
+ };
77
+
78
+ const clear = (): void => {
79
+ repository.clear();
80
+ exportedRepository = undefined;
81
+ };
82
+
83
+ const updateMessage = (
84
+ messageId: string,
85
+ updater: (message: ThreadMessage) => ThreadMessage,
86
+ ): boolean => {
87
+ const item = tryGetMessage(messageId);
88
+ if (!item) return false;
89
+ const message = updater(item.message);
90
+ if (message === item.message) return false;
91
+ addOrUpdateMessage(item.parentId, message);
92
+ return true;
93
+ };
94
+
95
+ const applyExternalMessageRepository = (
96
+ loaded: ExportedMessageRepository,
97
+ ): void => {
98
+ const headId = loaded.headId ?? loaded.messages.at(-1)?.message.id ?? null;
99
+ const ids = new Set<string>();
100
+ let degenerate = false;
101
+ for (const { message } of loaded.messages) {
102
+ if (ids.has(message.id)) {
103
+ degenerate = true;
104
+ break;
105
+ }
106
+ ids.add(message.id);
107
+ }
108
+ if (headId !== null && !ids.has(headId)) degenerate = true;
109
+
110
+ if (!degenerate) {
111
+ clear();
112
+ let pending = [...loaded.messages];
113
+ const importedIds = new Set<string>();
114
+
115
+ while (pending.length > 0) {
116
+ const unresolved: typeof pending = [];
117
+ let progressed = false;
118
+ for (const item of pending) {
119
+ if (item.parentId !== null && !importedIds.has(item.parentId)) {
120
+ unresolved.push(item);
121
+ continue;
122
+ }
123
+ addOrUpdateMessage(item.parentId, item.message);
124
+ importedIds.add(item.message.id);
125
+ progressed = true;
126
+ }
127
+ if (!progressed) {
128
+ degenerate = true;
129
+ break;
130
+ }
131
+ pending = unresolved;
132
+ }
133
+ }
134
+
135
+ if (degenerate) {
136
+ clear();
137
+ let previousId: string | null = null;
138
+ for (const { message } of loaded.messages) {
139
+ const existing = tryGetMessage(message.id);
140
+ addOrUpdateMessage(existing ? existing.parentId : previousId, message);
141
+ previousId = message.id;
142
+ }
143
+ resetHead(previousId);
144
+ } else {
145
+ resetHead(headId);
146
+ }
147
+ };
148
+
149
+ return {
150
+ getMessages,
151
+ get headId() {
152
+ return repository.headId;
153
+ },
154
+ export: (): ExportedMessageRepository => {
155
+ exportedRepository ??= options.decorateExport
156
+ ? options.decorateExport(repository.export(), repository)
157
+ : repository.export();
158
+ return exportedRepository;
159
+ },
160
+ tryGetMessage,
161
+ tryGetMessages,
162
+ hasMessage,
163
+ addOrUpdateMessage,
164
+ deleteMessage,
165
+ tryDeleteMessage,
166
+ switchToBranch,
167
+ resetHead,
168
+ clear,
169
+ updateMessage,
170
+ applyExternalMessageRepository,
171
+ };
172
+ };
173
+
174
+ export type MessageRepositorySession = ReturnType<
175
+ typeof createMessageRepositorySession
176
+ >;
@@ -2,7 +2,7 @@ import type { ThreadMessage } from "../../types/message";
2
2
  import type { RunConfig } from "../../types/message";
3
3
  import { generateId } from "../../utils/id";
4
4
  import type { ThreadMessageLike } from "./thread-message-like";
5
- import { getAutoStatus } from "./auto-status";
5
+ import { getContentAutoStatus } from "./auto-status";
6
6
  import { fromThreadMessageLike } from "./thread-message-like";
7
7
 
8
8
  export type ExportedMessageRepositoryItem = {
@@ -28,7 +28,7 @@ export const ExportedMessageRepository = {
28
28
  fromThreadMessageLike(
29
29
  m,
30
30
  generateId(),
31
- getAutoStatus(false, false, false, false, undefined),
31
+ getContentAutoStatus(m.content, false, false),
32
32
  ),
33
33
  );
34
34
 
@@ -47,7 +47,6 @@ export const ExportedMessageRepository = {
47
47
  }[],
48
48
  options?: { headId?: string | null },
49
49
  ): ExportedMessageRepository => {
50
- const fallbackStatus = getAutoStatus(false, false, false, false, undefined);
51
50
  return {
52
51
  ...(options?.headId !== undefined
53
52
  ? { headId: options.headId }
@@ -60,7 +59,11 @@ export const ExportedMessageRepository = {
60
59
  }
61
60
  return {
62
61
  parentId,
63
- message: fromThreadMessageLike(message, message.id, fallbackStatus),
62
+ message: fromThreadMessageLike(
63
+ message,
64
+ message.id,
65
+ getContentAutoStatus(message.content, false, false),
66
+ ),
64
67
  };
65
68
  }),
66
69
  };
@@ -81,9 +84,9 @@ type RepositoryMessage = RepositoryParent & {
81
84
  const findHead = (
82
85
  message: RepositoryMessage | RepositoryParent,
83
86
  ): RepositoryMessage | null => {
84
- if (message.next) return findHead(message.next);
85
- if ("current" in message) return message;
86
- return null;
87
+ let current = message;
88
+ while (current.next) current = current.next;
89
+ return "current" in current ? current : null;
87
90
  };
88
91
 
89
92
  class CachedValue<T> {
@@ -116,11 +119,17 @@ export class MessageRepository {
116
119
  };
117
120
 
118
121
  private updateLevels(message: RepositoryMessage, newLevel: number) {
119
- message.level = newLevel;
120
- for (const childId of message.children) {
121
- const childMessage = this.messages.get(childId);
122
- if (childMessage) {
123
- this.updateLevels(childMessage, newLevel + 1);
122
+ const pending = [{ message, level: newLevel }];
123
+
124
+ while (pending.length > 0) {
125
+ const current = pending.pop()!;
126
+ current.message.level = current.level;
127
+
128
+ for (const childId of current.message.children) {
129
+ const childMessage = this.messages.get(childId);
130
+ if (childMessage) {
131
+ pending.push({ message: childMessage, level: current.level + 1 });
132
+ }
124
133
  }
125
134
  }
126
135
  }
@@ -135,7 +144,8 @@ export class MessageRepository {
135
144
 
136
145
  if (operation === "relink" && parentOrRoot === newParentOrRoot) return;
137
146
 
138
- if (operation !== "cut") {
147
+ // `link` receives a fresh ID from `addOrUpdateMessage`; only `relink` can introduce a cycle.
148
+ if (operation === "relink") {
139
149
  for (
140
150
  let current: RepositoryMessage | null = newParent;
141
151
  current;
@@ -143,7 +153,7 @@ export class MessageRepository {
143
153
  ) {
144
154
  if (current.current.id === child.current.id) {
145
155
  throw new Error(
146
- "MessageRepository(performOp/link): A message with the same id already exists in the parent tree. This error occurs if the same message id is found multiple times. This is likely an internal bug in assistant-ui.",
156
+ "MessageRepository(performOp/relink): A message with the same id already exists in the parent tree. This error occurs if the same message id is found multiple times. This is likely an internal bug in assistant-ui.",
147
157
  );
148
158
  }
149
159
  }
@@ -396,16 +406,17 @@ export class MessageRepository {
396
406
  const previousHead = this.head;
397
407
 
398
408
  if (message.children.length > 0) {
399
- const deleteDescendants = (msg: RepositoryMessage) => {
400
- for (const childId of msg.children) {
401
- const childMessage = this.messages.get(childId);
402
- if (childMessage) {
403
- deleteDescendants(childMessage);
404
- this.messages.delete(childId);
409
+ const pending = [...message.children];
410
+ while (pending.length > 0) {
411
+ const childId = pending.pop()!;
412
+ const childMessage = this.messages.get(childId);
413
+ if (childMessage) {
414
+ for (const descendantId of childMessage.children) {
415
+ pending.push(descendantId);
405
416
  }
417
+ this.messages.delete(childId);
406
418
  }
407
- };
408
- deleteDescendants(message);
419
+ }
409
420
 
410
421
  message.children = [];
411
422
  message.next = null;
@@ -0,0 +1,57 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ createToolCallCancellationStub,
4
+ scanPendingToolCalls,
5
+ } from "./pending-tool-calls";
6
+
7
+ type Message =
8
+ | { type: "assistant"; toolCalls: { id: string; name: string }[] }
9
+ | { type: "tool"; toolCallId: string };
10
+
11
+ const getPendingToolCalls = (messages: readonly Message[]) =>
12
+ scanPendingToolCalls(
13
+ messages,
14
+ (message) =>
15
+ message.type === "assistant"
16
+ ? { toolCalls: message.toolCalls }
17
+ : { toolCallId: message.toolCallId },
18
+ (toolCall) => toolCall.id,
19
+ );
20
+
21
+ describe("scanPendingToolCalls", () => {
22
+ it("returns tool calls without matching results in history order", () => {
23
+ expect(
24
+ getPendingToolCalls([
25
+ {
26
+ type: "assistant",
27
+ toolCalls: [
28
+ { id: "call-1", name: "first" },
29
+ { id: "call-2", name: "second" },
30
+ ],
31
+ },
32
+ { type: "tool", toolCallId: "call-1" },
33
+ {
34
+ type: "assistant",
35
+ toolCalls: [{ id: "call-3", name: "third" }],
36
+ },
37
+ ]),
38
+ ).toEqual([
39
+ { id: "call-2", name: "second" },
40
+ { id: "call-3", name: "third" },
41
+ ]);
42
+ });
43
+ });
44
+
45
+ describe("createToolCallCancellationStub", () => {
46
+ it("creates an error tool result with the cancellation payload", () => {
47
+ expect(
48
+ createToolCallCancellationStub({ id: "call-1", name: "lookup" }),
49
+ ).toEqual({
50
+ type: "tool",
51
+ name: "lookup",
52
+ tool_call_id: "call-1",
53
+ content: JSON.stringify({ cancelled: true }),
54
+ status: "error",
55
+ });
56
+ });
57
+ });
@@ -0,0 +1,35 @@
1
+ type PendingToolCallMessage<TToolCall> =
2
+ | { toolCalls: readonly TToolCall[] }
3
+ | { toolCallId: string }
4
+ | undefined;
5
+
6
+ export const scanPendingToolCalls = <TMessage, TToolCall>(
7
+ messages: readonly TMessage[],
8
+ getMessage: (message: TMessage) => PendingToolCallMessage<TToolCall>,
9
+ getToolCallId: (toolCall: TToolCall) => string,
10
+ ): TToolCall[] => {
11
+ const pending = new Map<string, TToolCall>();
12
+ for (const message of messages) {
13
+ const value = getMessage(message);
14
+ if (!value) continue;
15
+ if ("toolCalls" in value) {
16
+ for (const toolCall of value.toolCalls) {
17
+ pending.set(getToolCallId(toolCall), toolCall);
18
+ }
19
+ } else {
20
+ pending.delete(value.toolCallId);
21
+ }
22
+ }
23
+ return [...pending.values()];
24
+ };
25
+
26
+ export const createToolCallCancellationStub = (toolCall: {
27
+ readonly id: string;
28
+ readonly name: string;
29
+ }) => ({
30
+ type: "tool" as const,
31
+ name: toolCall.name,
32
+ tool_call_id: toolCall.id,
33
+ content: JSON.stringify({ cancelled: true }),
34
+ status: "error" as const,
35
+ });
@@ -25,6 +25,7 @@ import type {
25
25
  TextMessagePart,
26
26
  ToolApprovalOption,
27
27
  ToolCallTiming,
28
+ ToolCallMessagePartMcpMetadata,
28
29
  } from "../../types/message";
29
30
  import type {
30
31
  ReadonlyJSONObject,
@@ -63,6 +64,7 @@ export type ThreadMessageLike = {
63
64
  readonly messages?: readonly ThreadMessage[] | undefined;
64
65
  readonly interrupt?: { type: "human"; payload: unknown };
65
66
  readonly timing?: ToolCallTiming;
67
+ readonly mcp?: ToolCallMessagePartMcpMetadata;
66
68
  readonly providerMetadata?: PartProviderMetadata;
67
69
  readonly approval?: {
68
70
  readonly id: string;
@@ -1,4 +1,3 @@
1
- import type { Unsubscribe } from "../../types/unsubscribe";
2
1
  import type { ExternalStoreThreadRuntimeCore } from "./external-store-thread-runtime-core";
3
2
  import type {
4
3
  ThreadListItemCoreState,
@@ -6,7 +5,7 @@ import type {
6
5
  } from "../../runtime/interfaces/thread-list-runtime-core";
7
6
  import type { ExternalStoreThreadListAdapter } from "./external-store-adapter";
8
7
  import { invalidateThreadRuntime } from "../../runtime/utils/thread-runtime-lifecycle";
9
- import { notifySubscribers } from "../../subscribable/subscribable";
8
+ import { BaseSubscribable } from "../../subscribable/subscribable";
10
9
 
11
10
  export type ExternalStoreThreadFactory = () => ExternalStoreThreadRuntimeCore;
12
11
 
@@ -24,7 +23,10 @@ const DEFAULT_THREAD_DATA = Object.freeze({
24
23
  [DEFAULT_THREAD_ID]: DEFAULT_THREAD,
25
24
  });
26
25
 
27
- export class ExternalStoreThreadListRuntimeCore implements ThreadListRuntimeCore {
26
+ export class ExternalStoreThreadListRuntimeCore
27
+ extends BaseSubscribable
28
+ implements ThreadListRuntimeCore
29
+ {
28
30
  private _mainThreadId: string = DEFAULT_THREAD_ID;
29
31
  private _threads: readonly string[] = DEFAULT_THREADS;
30
32
  private _archivedThreads: readonly string[] = EMPTY_ARRAY;
@@ -68,6 +70,7 @@ export class ExternalStoreThreadListRuntimeCore implements ThreadListRuntimeCore
68
70
  adapter: ExternalStoreThreadListAdapter = {},
69
71
  threadFactory: ExternalStoreThreadFactory,
70
72
  ) {
73
+ super();
71
74
  this.threadFactory = threadFactory;
72
75
  this.__internal_setAdapter(adapter, true);
73
76
  }
@@ -262,15 +265,4 @@ export class ExternalStoreThreadListRuntimeCore implements ThreadListRuntimeCore
262
265
  public generateTitle(): never {
263
266
  throw new Error("Method not implemented.");
264
267
  }
265
-
266
- private _subscriptions = new Set<() => void>();
267
-
268
- public subscribe(callback: () => void): Unsubscribe {
269
- this._subscriptions.add(callback);
270
- return () => this._subscriptions.delete(callback);
271
- }
272
-
273
- private _notifySubscribers() {
274
- notifySubscribers(this._subscriptions);
275
- }
276
268
  }