@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
@@ -1,16 +1,18 @@
1
- import type { Unsubscribe } from "../../types/unsubscribe";
2
1
  import type { ThreadMessage } from "../../types/message";
3
- import type { ThreadRuntimeCore } from "../../runtime/interfaces/thread-runtime-core";
4
- import { BaseSubscribable } from "../../subscribable/subscribable";
2
+ import {
3
+ InertThreadRuntimeCore,
4
+ createInertComposer,
5
+ } from "../inert/InertThreadRuntimeCore";
5
6
 
6
7
  const READONLY_THREAD_ERROR = new Error(
7
8
  "This is a readonly thread. You cannot perform mutations on readonly threads.",
8
9
  );
9
10
 
10
- export class ReadonlyThreadRuntimeCore
11
- extends BaseSubscribable
12
- implements ThreadRuntimeCore
13
- {
11
+ export class ReadonlyThreadRuntimeCore extends InertThreadRuntimeCore {
12
+ protected get error() {
13
+ return READONLY_THREAD_ERROR;
14
+ }
15
+
14
16
  private _messages: readonly ThreadMessage[] = [];
15
17
 
16
18
  get messages() {
@@ -39,202 +41,6 @@ export class ReadonlyThreadRuntimeCore
39
41
  return [messageId];
40
42
  }
41
43
 
42
- switchToBranch(): void {
43
- throw READONLY_THREAD_ERROR;
44
- }
45
-
46
- append(): void {
47
- throw READONLY_THREAD_ERROR;
48
- }
49
-
50
- deleteMessage(): void {
51
- throw READONLY_THREAD_ERROR;
52
- }
53
-
54
- startRun(): void {
55
- throw READONLY_THREAD_ERROR;
56
- }
57
-
58
- resumeRun(): void {
59
- throw READONLY_THREAD_ERROR;
60
- }
61
-
62
- cancelRun(): void {}
63
-
64
- addToolResult(): void {
65
- throw READONLY_THREAD_ERROR;
66
- }
67
-
68
- resumeToolCall(): void {
69
- throw READONLY_THREAD_ERROR;
70
- }
71
-
72
- respondToToolApproval(): void {
73
- throw READONLY_THREAD_ERROR;
74
- }
75
-
76
- speak(): void {
77
- throw READONLY_THREAD_ERROR;
78
- }
79
-
80
- stopSpeaking(): void {}
81
-
82
- connectVoice(): void {
83
- throw READONLY_THREAD_ERROR;
84
- }
85
-
86
- disconnectVoice(): void {}
87
-
88
- getVoiceVolume = () => 0;
89
- subscribeVoiceVolume = (): Unsubscribe => () => {};
90
-
91
- muteVoice(): void {
92
- throw READONLY_THREAD_ERROR;
93
- }
94
-
95
- unmuteVoice(): void {
96
- throw READONLY_THREAD_ERROR;
97
- }
98
-
99
- submitFeedback(): void {
100
- throw READONLY_THREAD_ERROR;
101
- }
102
-
103
- getModelContext() {
104
- return {};
105
- }
106
-
107
- exportExternalState() {
108
- throw READONLY_THREAD_ERROR;
109
- }
110
-
111
- importExternalState(): void {
112
- throw READONLY_THREAD_ERROR;
113
- }
114
-
115
- unstable_notifySessionReset(): void {
116
- throw READONLY_THREAD_ERROR;
117
- }
118
-
119
- composer = {
120
- attachments: [] as never[],
121
- attachmentAccept: "*",
122
-
123
- async addAttachment() {
124
- throw READONLY_THREAD_ERROR;
125
- },
126
-
127
- async removeAttachment() {
128
- throw READONLY_THREAD_ERROR;
129
- },
130
-
131
- isEditing: false as const,
132
- canCancel: false,
133
- canSend: false,
134
- isEmpty: true,
135
- text: "",
136
-
137
- setText() {
138
- throw READONLY_THREAD_ERROR;
139
- },
140
-
141
- role: "user" as const,
142
-
143
- setRole() {
144
- throw READONLY_THREAD_ERROR;
145
- },
146
-
147
- runConfig: {},
148
-
149
- setRunConfig() {
150
- throw READONLY_THREAD_ERROR;
151
- },
152
-
153
- async reset() {
154
- // noop
155
- },
156
-
157
- async clearAttachments() {
158
- // noop
159
- },
160
-
161
- send() {
162
- throw READONLY_THREAD_ERROR;
163
- },
164
-
165
- cancel() {
166
- // noop
167
- },
168
-
169
- queue: [] as never[],
170
- moveQueueItem() {},
171
- removeQueueItem() {},
172
-
173
- dictation: undefined,
174
-
175
- startDictation() {
176
- throw READONLY_THREAD_ERROR;
177
- },
178
-
179
- stopDictation() {
180
- // noop
181
- },
182
-
183
- quote: undefined,
184
-
185
- setQuote() {
186
- throw READONLY_THREAD_ERROR;
187
- },
188
-
189
- subscribe() {
190
- return () => {};
191
- },
192
-
193
- unstable_on() {
194
- return () => {};
195
- },
196
- };
197
-
198
- getEditComposer() {
199
- return undefined;
200
- }
201
-
202
- beginEdit(): void {
203
- throw READONLY_THREAD_ERROR;
204
- }
205
-
206
- speech = undefined;
207
- voice = undefined;
208
-
209
- capabilities = {
210
- switchToBranch: false,
211
- switchBranchDuringRun: false,
212
- edit: false,
213
- delete: false,
214
- reload: false,
215
- refetchThread: false,
216
- cancel: false,
217
- unstable_copy: false,
218
- speech: false,
219
- dictation: false,
220
- voice: false,
221
- attachments: false,
222
- feedback: false,
223
- queue: false,
224
- } as const;
225
-
226
- isDisabled = false;
227
- isSendDisabled = false;
228
- isLoading = false;
229
-
230
- state = null;
231
- suggestions = [] as never[];
232
- extras = undefined;
233
-
234
- import(): void {
235
- throw READONLY_THREAD_ERROR;
236
- }
237
-
238
44
  export() {
239
45
  return {
240
46
  messages: this._messages.map((message, idx) => ({
@@ -244,11 +50,13 @@ export class ReadonlyThreadRuntimeCore
244
50
  };
245
51
  }
246
52
 
247
- reset(): void {
248
- throw READONLY_THREAD_ERROR;
249
- }
53
+ composer = createInertComposer(READONLY_THREAD_ERROR, false);
250
54
 
251
- unstable_on(): Unsubscribe {
252
- return () => {};
253
- }
55
+ isLoading = false;
56
+
57
+ override cancelRun(): void {}
58
+
59
+ override stopSpeaking(): void {}
60
+
61
+ override disconnectVoice(): void {}
254
62
  }
@@ -0,0 +1,10 @@
1
+ import { SILENT_RUNTIME_ACTION } from "../../utils/silent-runtime-action";
2
+
3
+ export class ThreadListAdapterChangedError extends Error {
4
+ readonly [SILENT_RUNTIME_ACTION] = true;
5
+
6
+ constructor() {
7
+ super("Thread list adapter changed while an operation was pending.");
8
+ this.name = "ThreadListAdapterChangedError";
9
+ }
10
+ }
@@ -1,238 +1,45 @@
1
+ import type { Unsubscribe } from "../../types/unsubscribe";
1
2
  import type { ThreadRuntimeCore } from "../../runtime/interfaces/thread-runtime-core";
3
+ import {
4
+ InertThreadRuntimeCore,
5
+ createInertComposer,
6
+ } from "../inert/InertThreadRuntimeCore";
2
7
 
3
8
  const EMPTY_THREAD_ERROR = new Error(
4
9
  "This is the empty thread, a placeholder for the main thread. You cannot perform any actions on this thread instance. This error is probably because you tried to call a thread method in your render function. Call the method inside a `useEffect` hook instead.",
5
10
  );
6
- export const EMPTY_THREAD_CORE: ThreadRuntimeCore = {
7
- getMessageById() {
8
- return undefined;
9
- },
10
-
11
- getBranches() {
12
- return [];
13
- },
14
-
15
- switchToBranch() {
16
- throw EMPTY_THREAD_ERROR;
17
- },
18
-
19
- append() {
20
- throw EMPTY_THREAD_ERROR;
21
- },
22
-
23
- deleteMessage() {
24
- throw EMPTY_THREAD_ERROR;
25
- },
26
-
27
- startRun() {
28
- throw EMPTY_THREAD_ERROR;
29
- },
30
-
31
- resumeRun() {
32
- throw EMPTY_THREAD_ERROR;
33
- },
34
-
35
- cancelRun() {
36
- throw EMPTY_THREAD_ERROR;
37
- },
38
-
39
- addToolResult() {
40
- throw EMPTY_THREAD_ERROR;
41
- },
42
-
43
- resumeToolCall() {
44
- throw EMPTY_THREAD_ERROR;
45
- },
46
-
47
- respondToToolApproval() {
48
- throw EMPTY_THREAD_ERROR;
49
- },
50
-
51
- speak() {
52
- throw EMPTY_THREAD_ERROR;
53
- },
54
-
55
- stopSpeaking() {
56
- throw EMPTY_THREAD_ERROR;
57
- },
58
-
59
- connectVoice() {
60
- throw EMPTY_THREAD_ERROR;
61
- },
62
-
63
- disconnectVoice() {
64
- throw EMPTY_THREAD_ERROR;
65
- },
66
-
67
- getVoiceVolume: () => 0,
68
- subscribeVoiceVolume: () => () => {},
69
-
70
- muteVoice() {
71
- throw EMPTY_THREAD_ERROR;
72
- },
73
-
74
- unmuteVoice() {
75
- throw EMPTY_THREAD_ERROR;
76
- },
77
-
78
- submitFeedback() {
79
- throw EMPTY_THREAD_ERROR;
80
- },
81
-
82
- getModelContext() {
83
- return {};
84
- },
85
-
86
- exportExternalState() {
87
- throw EMPTY_THREAD_ERROR;
88
- },
89
-
90
- importExternalState() {
91
- throw EMPTY_THREAD_ERROR;
92
- },
93
-
94
- unstable_notifySessionReset() {
95
- throw EMPTY_THREAD_ERROR;
96
- },
97
-
98
- composer: {
99
- attachments: [],
100
- attachmentAccept: "*",
101
-
102
- async addAttachment() {
103
- throw EMPTY_THREAD_ERROR;
104
- },
105
-
106
- async removeAttachment() {
107
- throw EMPTY_THREAD_ERROR;
108
- },
109
-
110
- isEditing: true,
111
-
112
- canCancel: false,
113
- canSend: false,
114
- isEmpty: true,
115
11
 
116
- text: "",
12
+ class EmptyThreadRuntimeCore extends InertThreadRuntimeCore {
13
+ protected get error() {
14
+ return EMPTY_THREAD_ERROR;
15
+ }
117
16
 
118
- setText() {
119
- throw EMPTY_THREAD_ERROR;
120
- },
17
+ messages = [] as never[];
121
18
 
122
- role: "user",
19
+ composer = createInertComposer(EMPTY_THREAD_ERROR, true);
123
20
 
124
- setRole() {
125
- throw EMPTY_THREAD_ERROR;
126
- },
21
+ isLoading = true;
127
22
 
128
- runConfig: {},
129
-
130
- setRunConfig() {
131
- throw EMPTY_THREAD_ERROR;
132
- },
133
-
134
- async reset() {
135
- // noop
136
- },
137
-
138
- async clearAttachments() {
139
- // noop
140
- },
141
-
142
- send() {
143
- throw EMPTY_THREAD_ERROR;
144
- },
145
-
146
- cancel() {
147
- // noop
148
- },
149
-
150
- queue: [] as never[],
151
- moveQueueItem() {},
152
- removeQueueItem() {},
153
-
154
- dictation: undefined,
155
-
156
- startDictation() {
157
- throw EMPTY_THREAD_ERROR;
158
- },
159
-
160
- stopDictation() {
161
- // noop
162
- },
163
-
164
- quote: undefined,
165
-
166
- setQuote() {
167
- throw EMPTY_THREAD_ERROR;
168
- },
169
-
170
- subscribe() {
171
- return () => {};
172
- },
173
-
174
- unstable_on() {
175
- return () => {};
176
- },
177
- },
178
-
179
- getEditComposer() {
23
+ getMessageById() {
180
24
  return undefined;
181
- },
25
+ }
182
26
 
183
- beginEdit() {
184
- throw EMPTY_THREAD_ERROR;
185
- },
186
-
187
- speech: undefined,
188
- voice: undefined,
189
-
190
- capabilities: {
191
- switchToBranch: false,
192
- switchBranchDuringRun: false,
193
- edit: false,
194
- delete: false,
195
- reload: false,
196
- refetchThread: false,
197
- cancel: false,
198
- unstable_copy: false,
199
- speech: false,
200
- dictation: false,
201
- voice: false,
202
- attachments: false,
203
- feedback: false,
204
- queue: false,
205
- },
206
-
207
- isDisabled: false,
208
- isSendDisabled: false,
209
- isLoading: true,
210
-
211
- messages: [],
212
-
213
- state: null,
214
-
215
- suggestions: [],
216
-
217
- extras: undefined,
218
-
219
- subscribe() {
220
- return () => {};
221
- },
222
-
223
- import() {
224
- throw EMPTY_THREAD_ERROR;
225
- },
27
+ getBranches() {
28
+ return [];
29
+ }
226
30
 
227
31
  export() {
228
32
  return { messages: [] };
229
- },
33
+ }
230
34
 
231
- reset() {
232
- throw EMPTY_THREAD_ERROR;
233
- },
234
-
235
- unstable_on() {
35
+ override subscribe(): Unsubscribe {
236
36
  return () => {};
237
- },
238
- };
37
+ }
38
+
39
+ override waitForUpdate(): Promise<void> {
40
+ return Promise.reject(EMPTY_THREAD_ERROR);
41
+ }
42
+ }
43
+
44
+ export const EMPTY_THREAD_CORE: ThreadRuntimeCore =
45
+ new EmptyThreadRuntimeCore();
@@ -60,4 +60,22 @@ describe("OptimisticState", () => {
60
60
 
61
61
  expect(state.value.title).toBe("Project Beta");
62
62
  });
63
+
64
+ it("drops an in-flight transform after reset", async () => {
65
+ const state = new OptimisticState({ title: "Untitled", extra: 0 });
66
+ const request = deferred();
67
+ const update = state.optimisticUpdate({
68
+ execute: () => request.promise,
69
+ optimistic: (value) => ({ ...value, title: "Pending" }),
70
+ then: (value) => ({ ...value, extra: 1 }),
71
+ });
72
+
73
+ expect(state.value.title).toBe("Pending");
74
+ state.reset({ title: "Fresh", extra: 0 });
75
+ expect(state.value).toEqual({ title: "Fresh", extra: 0 });
76
+
77
+ request.resolve();
78
+ await update;
79
+ expect(state.value).toEqual({ title: "Fresh", extra: 0 });
80
+ });
63
81
  });
@@ -48,6 +48,7 @@ export class OptimisticState<TState> extends BaseSubscribable {
48
48
  [];
49
49
 
50
50
  private _nextTransformOrder = 0;
51
+ private _epoch = 0;
51
52
 
52
53
  private _baseValue: TState;
53
54
  private _cachedValue: TState;
@@ -95,9 +96,20 @@ export class OptimisticState<TState> extends BaseSubscribable {
95
96
  this._updateState();
96
97
  }
97
98
 
99
+ public reset(state: TState): void {
100
+ // In-flight optimisticUpdate calls must not write into the replacement state.
101
+ this._epoch++;
102
+ this._pendingTransforms.length = 0;
103
+ this._completedOptimistics.length = 0;
104
+ this._baseValue = state;
105
+ this._cachedValue = state;
106
+ this._notifySubscribers();
107
+ }
108
+
98
109
  public async optimisticUpdate<TResult>(
99
110
  transform: Transform<TState, TResult>,
100
111
  ): Promise<TResult> {
112
+ const epoch = this._epoch;
101
113
  const order = this._nextTransformOrder++;
102
114
  const task = transform.execute();
103
115
  const pendingTransform = {
@@ -110,6 +122,7 @@ export class OptimisticState<TState> extends BaseSubscribable {
110
122
  this._updateState();
111
123
 
112
124
  const result = await task;
125
+ if (epoch !== this._epoch) return result;
113
126
  this._baseValue = pipeTransforms(this._baseValue, result, [
114
127
  transform.optimistic,
115
128
  transform.then,
@@ -0,0 +1,37 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ createEmptyRemoteThreadState,
4
+ createThreadMappingId,
5
+ seedNewThread,
6
+ } from "./remote-thread-state";
7
+
8
+ describe("remote thread state", () => {
9
+ it("creates an empty state", () => {
10
+ expect(createEmptyRemoteThreadState()).toEqual({
11
+ isLoading: true,
12
+ isLoadingMore: false,
13
+ cursor: undefined,
14
+ newThreadId: undefined,
15
+ threadIds: [],
16
+ archivedThreadIds: [],
17
+ threadIdMap: {},
18
+ threadData: {},
19
+ });
20
+ });
21
+
22
+ it("seeds unique local threads with matching mapping ids", () => {
23
+ const first = seedNewThread(createEmptyRemoteThreadState());
24
+ const second = seedNewThread(first.state);
25
+
26
+ expect(second.id).not.toBe(first.id);
27
+ expect(first.state.newThreadId).toBe(first.id);
28
+ expect(second.state.newThreadId).toBe(second.id);
29
+ expect(first.state.threadIdMap[first.id]).toBe(
30
+ createThreadMappingId(first.id),
31
+ );
32
+ expect(second.state.threadIdMap[second.id]).toBe(
33
+ createThreadMappingId(second.id),
34
+ );
35
+ expect(Object.keys(second.state.threadData)).toEqual([first.id, second.id]);
36
+ });
37
+ });