@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,6 +1,6 @@
1
- import { QueueItemClientSchema } from "./scopes/queue-item.js";
2
1
  import { ThreadListItemClientSchema } from "./scopes/thread-list-item.js";
3
2
  import { AttachmentClientSchema } from "./scopes/attachment.js";
3
+ import { QueueItemClientSchema } from "./scopes/queue-item.js";
4
4
  import { ComposerClientSchema } from "./scopes/composer.js";
5
5
  import { PartClientSchema } from "./scopes/part.js";
6
6
  import { MessageClientSchema } from "./scopes/message.js";
@@ -1,10 +1,11 @@
1
1
  import { MessageRole, RunConfig } from "../../types/message.js";
2
2
  import { Attachment, CreateAttachment } from "../../types/attachment.js";
3
3
  import { QuoteInfo } from "../../types/quote.js";
4
- import { QueueItemMethods, QueueItemState } from "./queue-item.js";
4
+ import { QueueItemState } from "../../runtime/queue/queue-item.js";
5
5
  import { AttachmentAddErrorReason, DictationState, SendOptions } from "../../runtime/interfaces/composer-runtime-core.js";
6
6
  import { ComposerRuntime } from "../../runtime/api/composer-runtime.js";
7
7
  import { AttachmentMethods } from "./attachment.js";
8
+ import { QueueItemMethods } from "./queue-item.js";
8
9
  //#region src/store/scopes/composer.d.ts
9
10
  type ComposerSendOptions = SendOptions & {
10
11
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"composer.d.ts","names":[],"sources":["../../../src/store/scopes/composer.ts"],"mappings":";;;;;;;;KAaY,sBAAsB;;;;;;;EAOhC;;KAGU;WACD;WACA,MAAM;WACN,sBAAsB;WACtB,WAAW;WACX;;;;;;WAMA;;;;;;;;;WASA;WACA;WACA;WACA;;;;;WAMA,WAAW;;;;;WAMX,OAAO;;;;;WAMP,gBAAgB;;KAGf;EACV,YAAY;EACZ,QAAQ;EACR,QAAQ,MAAM;EACd,aAAa,WAAW;EACxB,cAAc,kBAAkB,OAAO,mBAAmB;EAC1D,oBAAoB;EACpB,WAAW;IAAY;;IAAoB;MAAe;EAC1D,SAAS;EACT,KAAK,OAAO;EACZ;EACA;;;;;EAMA;;;;EAKA;;;;EAKA,SAAS,OAAO;;;;EAKhB,UAAU;IAAY;;IAAoB;MAAe;EAEzD,0BAA0B;;KAGhB;EACV;EACA,OAAO;;KAGG;;;;;EAKV;IAAmB;IAAkB;;;;;;EAKrC;IAA4B;IAAkB;;EAC9C;IACE;IACA;IACA;IACA,QAAQ;IACR;;;KAIQ;EACV,SAAS;EACT,MAAM;EACN,QAAQ"}
1
+ {"version":3,"file":"composer.d.ts","names":[],"sources":["../../../src/store/scopes/composer.ts"],"mappings":";;;;;;;;;KAaY,sBAAsB;;;;;;;EAOhC;;KAGU;WACD;WACA,MAAM;WACN,sBAAsB;WACtB,WAAW;WACX;;;;;;WAMA;;;;;;;;;WASA;WACA;WACA;WACA;;;;;WAMA,WAAW;;;;;WAMX,OAAO;;;;;WAMP,gBAAgB;;KAGf;EACV,YAAY;EACZ,QAAQ;EACR,QAAQ,MAAM;EACd,aAAa,WAAW;EACxB,cAAc,kBAAkB,OAAO,mBAAmB;EAC1D,oBAAoB;EACpB,WAAW;IAAY;;IAAoB;MAAe;EAC1D,SAAS;EACT,KAAK,OAAO;EACZ;EACA;;;;;EAMA;;;;EAKA;;;;EAKA,SAAS,OAAO;;;;EAKhB,UAAU;IAAY;;IAAoB;MAAe;EAEzD,0BAA0B;;KAGhB;EACV;EACA,OAAO;;KAGG;;;;;EAKV;IAAmB;IAAkB;;;;;;EAKrC;IAA4B;IAAkB;;EAC9C;IACE;IACA;IACA;IACA,QAAQ;IACR;;;KAIQ;EACV,SAAS;EACT,MAAM;EACN,QAAQ"}
@@ -18,7 +18,7 @@ type MessageState = ThreadMessage & {
18
18
  * @example
19
19
  * ```ts
20
20
  * import { WebSpeechSynthesisAdapter } from "@assistant-ui/react";
21
- * import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
21
+ * import { useChatRuntime } from "@assistant-ui/ai-sdk";
22
22
  *
23
23
  * const runtime = useChatRuntime({
24
24
  * adapters: {
@@ -1,13 +1,6 @@
1
- import { FileMessagePart, TextMessagePart } from "../../types/message.js";
1
+ import { QueueItemState } from "../../runtime/queue/queue-item.js";
2
2
  import { QueuePlacement } from "../../runtime/queue/external-thread-queue-adapter.js";
3
3
  //#region src/store/scopes/queue-item.d.ts
4
- type QueueItemState = {
5
- readonly id: string;
6
- /** @deprecated Derive from the text parts of `parts` instead. Removal after 2026-11-05. */
7
- readonly prompt: string;
8
- readonly parts: readonly (FileMessagePart | TextMessagePart)[];
9
- };
10
- declare const EMPTY_QUEUE_ITEMS: readonly QueueItemState[];
11
4
  type QueueItemMethods = {
12
5
  getState(): QueueItemState;
13
6
  /** @deprecated Use `move({ lane: "steer", insertAfter: null })` instead. Removal after 2026-11-05. */
@@ -30,5 +23,5 @@ type QueueItemClientSchema = {
30
23
  meta: QueueItemMeta;
31
24
  };
32
25
  //#endregion
33
- export { EMPTY_QUEUE_ITEMS, QueueItemClientSchema, QueueItemMeta, QueueItemMethods, QueueItemState };
26
+ export { QueueItemClientSchema, QueueItemMeta, QueueItemMethods, type QueueItemState };
34
27
  //# sourceMappingURL=queue-item.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"queue-item.d.ts","names":[],"sources":["../../../src/store/scopes/queue-item.ts"],"mappings":";;;KAGY;WACD;;WAEA;WACA,iBAAiB,kBAAkB;;cAGjC,4BAA4B;KAE7B;EACV,YAAY;;EAEZ;EACA,KAAK,WAAW;EAChB;;KAGU;EACV;EACA;IAAS;IAAe;;IAAoB;IAAY;;;KAG9C;EACV,SAAS;EACT,MAAM"}
1
+ {"version":3,"file":"queue-item.d.ts","names":[],"sources":["../../../src/store/scopes/queue-item.ts"],"mappings":";;;KAKY;EACV,YAAY;;EAEZ;EACA,KAAK,WAAW;EAChB;;KAGU;EACV;EACA;IAAS;IAAe;;IAAoB;IAAY;;;KAG9C;EACV,SAAS;EACT,MAAM"}
@@ -1,6 +0,0 @@
1
- //#region src/store/scopes/queue-item.ts
2
- const EMPTY_QUEUE_ITEMS = Object.freeze([]);
3
- //#endregion
4
- export { EMPTY_QUEUE_ITEMS };
5
-
6
- //# sourceMappingURL=queue-item.js.map
@@ -137,9 +137,9 @@ type ToolApprovalOption = {
137
137
  readonly id: string;
138
138
  /**
139
139
  * Decision class. Drives approved-resolution and default rendering.
140
- * Open union: `_`-prefixed custom kinds are never auto-resolved and the
141
- * default kit skips them; they must be answered with an explicit
142
- * `approved` value (optionally alongside the `optionId`).
140
+ * Open union: `_`-prefixed custom kinds are never auto-resolved; they must
141
+ * be answered with an explicit `approved` value (optionally alongside the
142
+ * `optionId`), which is what the default kit sends when one is chosen.
143
143
  */
144
144
  readonly kind: ToolApprovalOptionKind | (string & {});
145
145
  /** Human label. Renderers supply defaults per kind when omitted. */
@@ -242,7 +242,11 @@ type ToolCallMessagePartStatus = {
242
242
  /** The tool call is waiting for UI or human input before continuing. */
243
243
  readonly type: "requires-action";
244
244
  /** Reason the tool call requires action. */
245
- readonly reason: "interrupt";
245
+ readonly reason: "tool-calls" | "interrupt";
246
+ } | {
247
+ readonly type: "incomplete";
248
+ readonly reason: "tool-calls";
249
+ readonly error?: ReadonlyJSONValue;
246
250
  } | MessagePartStatus;
247
251
  type MessageStatus = {
248
252
  readonly type: "running";
@@ -1 +1 @@
1
- {"version":3,"file":"message.d.ts","names":[],"sources":["../../src/types/message.ts"],"mappings":";;;;KASY;YACA,uBAAuB;;KAGvB;WACD;WACA;WACA,SAAS;WACT,mBAAmB;WACnB;;KAGC;WACD;WACA;WACA,SAAS;WACT;WACA,mBAAmB;WACnB;;KAGC,yBAAyB;KAEzB;WAEG;WACA;WACA;WACA;WACA;WACA,mBAAmB;WACnB;;WAGA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,mBAAmB;WACnB;;KAGH;WACD;WACA;WACA;WACA,mBAAmB;;KAGlB;WACD;WACA;WACA;WACA;;WAEA;WACA,mBAAmB;WACnB;;;;;;;;;;;KAYC;WACD;WACA;aACE;aACA;;;KAID,gBAAgB;WACjB;WACA;WACA,MAAM;;;;;;;;;;;KAYL;;WAIG;;WAEA,QAAQ;;WAER,oBAAoB;;WAEpB;;;;;KAMH;;WAED,MAAM,4BAA4B;;;;;;;;;;KAWjC;WACD;;WAEA,MAAM;;WAEN;WACA;;KAGC;WACD;WACA;WACA;;WAEA;;cAGE;cAEA,cAAe;KAGhB;WACD,MAAM;;KAGL;KAMA;;WAED;;;;;;;WAOA,MAAM;;WAEN;WACA;;WAEA;;WAEA;IAAsB;IAAgB;;;KAGrC;WACG;WAA4B;;WAC5B;WAA2B;;WAE3B;WACA;WACA;;KAGH,oBACV,QAAQ,oBACR;;WAGS;;WAEA;;WAEA;;;;;;WAMA,MAAM;;WAEN,SAAS;;WAET;;WAEA;;WAEA;;WAEA,SAAS;;WAET,MAAM;;WAEN,mBAAmB;;WAEnB,wBAAwB;;WAExB;IAAc;IAAe;;;WAE7B;aACE;aACA;aACA;aACA;;aAEA,mBAAmB;;aAEnB;;aAEA;;;WAGF;;;;;WAKA,oBAAoB;;KAGnB,wBACR,kBACA,mBACA,kBACA,kBACA;KAEQ,6BACR,kBACA,uBACA,sBACA,oBACA,kBACA,mBACA,kBACA;KAEQ;WAEG;;WAGA;;WAGA;WACA;WAMA;;KAGH;WAEG;;WAGA;;WAGA;WACA;;KAQH;;WAGG;;WAEA;IAEX;KAEQ;WAEG;;WAGA;WACA;;WAGA;WACA;;WAGA;WACA;WAOA,QAAQ;;KAGX;WACD;WACA;WACA;WACA;WACA;WACA;WACA;;KAGC;WACD;WACA;aAEM;aACA;;;KAKZ;WACM;WACA,WAAW;;KAGV,sBAAsB;WACvB;WACA,mBAAmB;WACnB;aACE;aACA;aACA;aACA;aACA;aACA;aACA,QAAQ;;;KAIT,oBAAoB;WACrB;WACA,kBAAkB;WAClB,sBAAsB;WACtB;aACE;aACA;aACA;aACA;aACA;aACA;aACA;aACA,QAAQ;;;KAIT,yBAAyB;WAC1B;WACA,kBAAkB;WAClB,QAAQ;WACR;aACE,gBAAgB;aAChB,+BAA+B;aAC/B,wBAAwB;aACxB,gBAAgB;aAChB;eAA+B;;aAC/B,SAAS;;;;;aAKT;aACA,QAAQ;;;KAIhB;WACM,SAAS;WACT;aACE,iBAAiB;aACjB,gCAAgC;aAChC,yBAAyB;aACzB,iBAAiB;aACjB;eAA+B;;aAC/B,SAAS;aACT;aACA,QAAQ;;WAEV,cAAc;;KAGb,gBAAgB,qBACzB,sBAAsB,oBAAoB;KAEjC,cAAc;KAEd;WACD,SAAS;;KAGR,gBAAgB,KAAK;EAC/B;;EAGA;EACA,WAAW;EACX;;EAEA"}
1
+ {"version":3,"file":"message.d.ts","names":[],"sources":["../../src/types/message.ts"],"mappings":";;;;KASY;YACA,uBAAuB;;KAGvB;WACD;WACA;WACA,SAAS;WACT,mBAAmB;WACnB;;KAGC;WACD;WACA;WACA,SAAS;WACT;WACA,mBAAmB;WACnB;;KAGC,yBAAyB;KAEzB;WAEG;WACA;WACA;WACA;WACA;WACA,mBAAmB;WACnB;;WAGA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,mBAAmB;WACnB;;KAGH;WACD;WACA;WACA;WACA,mBAAmB;;KAGlB;WACD;WACA;WACA;WACA;;WAEA;WACA,mBAAmB;WACnB;;;;;;;;;;;KAYC;WACD;WACA;aACE;aACA;;;KAID,gBAAgB;WACjB;WACA;WACA,MAAM;;;;;;;;;;;KAYL;;WAIG;;WAEA,QAAQ;;WAER,oBAAoB;;WAEpB;;;;;KAMH;;WAED,MAAM,4BAA4B;;;;;;;;;;KAWjC;WACD;;WAEA,MAAM;;WAEN;WACA;;KAGC;WACD;WACA;WACA;;WAEA;;cAGE;cAEA,cAAe;KAGhB;WACD,MAAM;;KAGL;KAMA;;WAED;;;;;;;WAOA,MAAM;;WAEN;WACA;;WAEA;;WAEA;IAAsB;IAAgB;;;KAGrC;WACG;WAA4B;;WAC5B;WAA2B;;WAE3B;WACA;WACA;;KAGH,oBACV,QAAQ,oBACR;;WAGS;;WAEA;;WAEA;;;;;;WAMA,MAAM;;WAEN,SAAS;;WAET;;WAEA;;WAEA;;WAEA,SAAS;;WAET,MAAM;;WAEN,mBAAmB;;WAEnB,wBAAwB;;WAExB;IAAc;IAAe;;;WAE7B;aACE;aACA;aACA;aACA;;aAEA,mBAAmB;;aAEnB;;aAEA;;;WAGF;;;;;WAKA,oBAAoB;;KAGnB,wBACR,kBACA,mBACA,kBACA,kBACA;KAEQ,6BACR,kBACA,uBACA,sBACA,oBACA,kBACA,mBACA,kBACA;KAEQ;WAEG;;WAGA;;WAGA;WACA;WAMA;;KAGH;WAEG;;WAGA;;WAGA;WACA;;KAQH;;WAGG;;WAEA;;WAGA;WACA;WACA,QAAQ;IAEnB;KAEQ;WAEG;;WAGA;WACA;;WAGA;WACA;;WAGA;WACA;WAOA,QAAQ;;KAGX;WACD;WACA;WACA;WACA;WACA;WACA;WACA;;KAGC;WACD;WACA;aAEM;aACA;;;KAKZ;WACM;WACA,WAAW;;KAGV,sBAAsB;WACvB;WACA,mBAAmB;WACnB;aACE;aACA;aACA;aACA;aACA;aACA;aACA,QAAQ;;;KAIT,oBAAoB;WACrB;WACA,kBAAkB;WAClB,sBAAsB;WACtB;aACE;aACA;aACA;aACA;aACA;aACA;aACA;aACA,QAAQ;;;KAIT,yBAAyB;WAC1B;WACA,kBAAkB;WAClB,QAAQ;WACR;aACE,gBAAgB;aAChB,+BAA+B;aAC/B,wBAAwB;aACxB,gBAAgB;aAChB;eAA+B;;aAC/B,SAAS;;;;;aAKT;aACA,QAAQ;;;KAIhB;WACM,SAAS;WACT;aACE,iBAAiB;aACjB,gCAAgC;aAChC,yBAAyB;aACzB,iBAAiB;aACjB;eAA+B;;aAC/B,SAAS;aACT;aACA,QAAQ;;WAEV,cAAc;;KAGb,gBAAgB,qBACzB,sBAAsB,oBAAoB;KAEjC,cAAc;KAEd;WACD,SAAS;;KAGR,gBAAgB,KAAK;EAC/B;;EAGA;EACA,WAAW;EACX;;EAEA"}
@@ -1 +1 @@
1
- {"version":3,"file":"message.js","names":["ReadonlyJSONObject","ReadonlyJSONValue","ToolCallTiming","ToolModelContentPart","CompleteAttachment","PartProviderMetadata","providerName","TextMessagePart","type","text","status","MessagePartStreamStatus","providerMetadata","parentId","ReasoningMessagePart","unstable_summary","SourceProviderMetadata","SourceMessagePart","sourceType","id","url","title","mediaType","filename","ImageMessagePart","image","FileMessagePart","data","mimeType","Unstable_AudioMessagePart","audio","format","DataMessagePart","name","T","GenerativeUINode","component","props","Record","children","key","GenerativeUISpec","root","GenerativeUIMessagePart","spec","McpAppMetadata","resourceUri","visibility","serverId","MCP_APP_URI_SCHEME","isMcpAppUri","uri","startsWith","ToolCallMessagePartMcpMetadata","app","ToolApprovalOptionKind","ToolApprovalOption","kind","label","description","grants","confirm","ToolApprovalResponse","approved","reason","optionId","ToolCallMessagePart","toolCallId","toolName","args","TArgs","result","TResult","isError","argsText","artifact","timing","mcp","modelContent","interrupt","payload","approval","isAutomatic","options","resolution","messages","ThreadMessage","ThreadUserMessagePart","ThreadAssistantMessagePart","MessagePartStatus","error","ToolCallMessagePartStatus","MessageStatus","MessageTiming","streamStartTime","firstTokenTime","totalStreamTime","tokenCount","tokensPerSecond","totalChunks","toolCallCount","ThreadStep","messageId","usage","inputTokens","outputTokens","MessageCommonProps","createdAt","Date","ThreadSystemMessage","role","content","metadata","unstable_state","unstable_annotations","unstable_data","steps","submittedFeedback","custom","ThreadUserMessage","attachments","isOptimistic","ThreadAssistantMessage","BaseThreadMessage","MessageRole","RunConfig","AppendMessage","Omit","sourceId","runConfig","startRun","steer"],"sources":["../../src/types/message.ts"],"sourcesContent":["import type {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from \"assistant-stream/utils\";\nimport type { ToolCallTiming, ToolModelContentPart } from \"assistant-stream\";\nimport type { CompleteAttachment } from \"./attachment\";\n\nexport type { ToolCallTiming, ToolModelContentPart };\n\nexport type PartProviderMetadata = {\n readonly [providerName: string]: ReadonlyJSONObject;\n};\n\nexport type TextMessagePart = {\n readonly type: \"text\";\n readonly text: string;\n readonly status?: MessagePartStreamStatus;\n readonly providerMetadata?: PartProviderMetadata;\n readonly parentId?: string;\n};\n\nexport type ReasoningMessagePart = {\n readonly type: \"reasoning\";\n readonly text: string;\n readonly status?: MessagePartStreamStatus;\n readonly unstable_summary?: string;\n readonly providerMetadata?: PartProviderMetadata;\n readonly parentId?: string;\n};\n\nexport type SourceProviderMetadata = PartProviderMetadata;\n\nexport type SourceMessagePart =\n | {\n readonly type: \"source\";\n readonly sourceType: \"url\";\n readonly id: string;\n readonly url: string;\n readonly title?: string;\n readonly providerMetadata?: SourceProviderMetadata;\n readonly parentId?: string;\n }\n | {\n readonly type: \"source\";\n readonly sourceType: \"document\";\n readonly id: string;\n readonly url?: undefined;\n readonly title: string;\n readonly mediaType: string;\n readonly filename?: string;\n readonly providerMetadata?: SourceProviderMetadata;\n readonly parentId?: string;\n };\n\nexport type ImageMessagePart = {\n readonly type: \"image\";\n readonly image: string;\n readonly filename?: string;\n readonly providerMetadata?: PartProviderMetadata;\n};\n\nexport type FileMessagePart = {\n readonly type: \"file\";\n readonly filename?: string;\n readonly data: string;\n readonly mimeType: string;\n /** How `data` goes on the wire: a url or id reference; omitted = inferred (http(s) → url, else base64). \"url\" is honored by the LangChain-family, A2A, AG-UI, and Google ADK runtimes; \"id\" by the LangChain family only. */\n readonly sourceType?: \"url\" | \"id\";\n readonly providerMetadata?: PartProviderMetadata;\n readonly parentId?: string;\n};\n\n/**\n * @deprecated Use {@link FileMessagePart} with an `audio/*` mime type. `file`\n * is the carrier for every non-image binary modality: it is a member of both\n * the user and assistant unions, carries a filename, and can declare how its\n * payload goes on the wire, none of which this shape can express. The payload\n * form a `file` part needs is still adapter specific; see the Part Types\n * section of the message primitive docs. Honored everywhere it is accepted; it\n * will not gain fields.\n */\nexport type Unstable_AudioMessagePart = {\n readonly type: \"audio\";\n readonly audio: {\n readonly data: string;\n readonly format: \"mp3\" | \"wav\";\n };\n};\n\nexport type DataMessagePart<T = any> = {\n readonly type: \"data\";\n readonly name: string;\n readonly data: T;\n};\n\n/**\n * A JSON spec describing a tree of UI components to render.\n *\n * The agent emits a {@link GenerativeUIMessagePart} containing this spec, and\n * the consumer-provided component allowlist is used to resolve `component`\n * names. Any component referenced that is not present in the allowlist is\n * rejected with a typed error — the allowlist is the security boundary in the\n * default same-realm rendering path.\n */\nexport type GenerativeUINode =\n | string\n | {\n /** Allowlisted component name (resolved against the consumer registry). */\n readonly component: string;\n /** Props passed to the resolved component (must be JSON-serializable). */\n readonly props?: Record<string, unknown>;\n /** Optional children — strings render as text, objects recurse. */\n readonly children?: readonly GenerativeUINode[];\n /** Optional stable key for React reconciliation. */\n readonly key?: string;\n };\n\n/**\n * The root spec for a generative UI tree.\n */\nexport type GenerativeUISpec = {\n /** Root node(s) to render. */\n readonly root: GenerativeUINode | readonly GenerativeUINode[];\n};\n\n/**\n * A message part that carries a JSON spec describing UI to render.\n *\n * Render with `<MessagePrimitive.GenerativeUI components={...} />`. The\n * primitive resolves component names against the consumer-provided allowlist\n * — any unknown name throws a typed error rather than rendering. Stream-\n * friendly: a partially-streamed spec renders progressively.\n */\nexport type GenerativeUIMessagePart = {\n readonly type: \"generative-ui\";\n /** The JSON spec describing the UI tree. */\n readonly spec: GenerativeUISpec;\n /** Optional id (useful for replays / stable keys). */\n readonly id?: string;\n readonly parentId?: string;\n};\n\nexport type McpAppMetadata = {\n readonly resourceUri: string;\n readonly mimeType?: string;\n readonly visibility?: readonly (\"model\" | \"app\")[];\n /** Routable server identity emitted by the agent stack when multiple MCP servers back one agent; for @ag-ui/mcp-apps-middleware this is the configured serverId, falling back to its serverHash. */\n readonly serverId?: string;\n};\n\nexport const MCP_APP_URI_SCHEME = \"ui://\";\n\nexport const isMcpAppUri = (uri: string | undefined): boolean =>\n !!uri?.startsWith(MCP_APP_URI_SCHEME);\n\nexport type ToolCallMessagePartMcpMetadata = {\n readonly app?: McpAppMetadata;\n};\n\nexport type ToolApprovalOptionKind =\n | \"allow-once\"\n | \"allow-always\"\n | \"reject-once\"\n | \"reject-always\";\n\nexport type ToolApprovalOption = {\n /** Opaque, host-defined identifier. Scope semantics (session vs project vs global) belong to the option supplier. */\n readonly id: string;\n /**\n * Decision class. Drives approved-resolution and default rendering.\n * Open union: `_`-prefixed custom kinds are never auto-resolved and the\n * default kit skips them; they must be answered with an explicit\n * `approved` value (optionally alongside the `optionId`).\n */\n readonly kind: ToolApprovalOptionKind | (string & {});\n /** Human label. Renderers supply defaults per kind when omitted. */\n readonly label?: string;\n readonly description?: string;\n /** Patterns or rules this option would persist, shown before the user commits. Supplied by the host; never derived by the library. */\n readonly grants?: readonly string[];\n /** Opt-in confirmation step before this option resolves. */\n readonly confirm?: boolean | { title?: string; description?: string };\n};\n\nexport type ToolApprovalResponse =\n | { readonly approved: boolean; readonly reason?: string }\n | { readonly optionId: string; readonly reason?: string }\n | {\n readonly approved: boolean;\n readonly optionId: string;\n readonly reason?: string;\n };\n\nexport type ToolCallMessagePart<\n TArgs = ReadonlyJSONObject,\n TResult = unknown,\n> = {\n /** Identifies this part as a tool call. */\n readonly type: \"tool-call\";\n /** Stable identifier for this invocation of the tool. */\n readonly toolCallId: string;\n /** Name of the tool requested by the model. */\n readonly toolName: string;\n /**\n * Arguments supplied by the model. During streaming this is a partial parse:\n * fields may be missing or incomplete. From a tool-call renderer, use\n * `useToolArgsStatus` to detect which fields are still arriving.\n */\n readonly args: TArgs;\n /** Result returned by the tool, if it has completed. */\n readonly result?: TResult | undefined;\n /** Whether the result represents a tool execution error. */\n readonly isError?: boolean | undefined;\n /** Raw JSON argument text streamed by the model. */\n readonly argsText: string;\n /** UI-only artifact associated with the tool result. */\n readonly artifact?: unknown;\n /** Wall-clock timing for this call, when the runtime or host tracks it. */\n readonly timing?: ToolCallTiming;\n /** MCP app metadata associated with this tool call, when present. */\n readonly mcp?: ToolCallMessagePartMcpMetadata;\n /** Provider metadata associated with this tool call, when present. */\n readonly providerMetadata?: PartProviderMetadata;\n /** Content returned to the model for this tool result. */\n readonly modelContent?: readonly ToolModelContentPart[] | undefined;\n /** Human-input request that must be resolved before the run can continue. */\n readonly interrupt?: { type: \"human\"; payload: unknown };\n /** Server-side approval gate. `respondToApproval` may only be called while `approved` is undefined and no `resolution` is recorded. */\n readonly approval?: {\n readonly id: string;\n readonly approved?: boolean;\n readonly reason?: string;\n readonly isAutomatic?: boolean;\n /** Available decisions for this call. Absent: a plain allow / deny pair. */\n readonly options?: readonly ToolApprovalOption[];\n /** The option chosen at resolution, when options were present. */\n readonly optionId?: string;\n /** Terminal non-decision state: the request was cancelled or expired without a user decision. Set by the host. */\n readonly resolution?: \"cancelled\" | \"expired\";\n };\n /** Parent message-part ID when this part belongs to a nested structure. */\n readonly parentId?: string;\n /**\n * Nested thread messages produced by this tool call, for example a sub-agent\n * conversation.\n */\n readonly messages?: readonly ThreadMessage[];\n};\n\nexport type ThreadUserMessagePart =\n | TextMessagePart\n | ImageMessagePart\n | FileMessagePart\n | DataMessagePart\n | Unstable_AudioMessagePart;\n\nexport type ThreadAssistantMessagePart =\n | TextMessagePart\n | ReasoningMessagePart\n | ToolCallMessagePart\n | SourceMessagePart\n | FileMessagePart\n | ImageMessagePart\n | DataMessagePart\n | GenerativeUIMessagePart;\n\nexport type MessagePartStatus =\n | {\n readonly type: \"running\";\n }\n | {\n readonly type: \"complete\";\n }\n | {\n readonly type: \"incomplete\";\n readonly reason:\n | \"cancelled\"\n | \"length\"\n | \"content-filter\"\n | \"other\"\n | \"error\";\n readonly error?: unknown;\n };\n\nexport type MessagePartStreamStatus =\n | {\n readonly type: \"running\";\n }\n | {\n readonly type: \"complete\";\n }\n | {\n readonly type: \"incomplete\";\n readonly reason:\n | \"cancelled\"\n | \"length\"\n | \"content-filter\"\n | \"other\"\n | \"error\";\n };\n\nexport type ToolCallMessagePartStatus =\n | {\n /** The tool call is waiting for UI or human input before continuing. */\n readonly type: \"requires-action\";\n /** Reason the tool call requires action. */\n readonly reason: \"interrupt\";\n }\n | MessagePartStatus;\n\nexport type MessageStatus =\n | {\n readonly type: \"running\";\n }\n | {\n readonly type: \"requires-action\";\n readonly reason: \"tool-calls\" | \"interrupt\";\n }\n | {\n readonly type: \"complete\";\n readonly reason: \"stop\" | \"unknown\";\n }\n | {\n readonly type: \"incomplete\";\n readonly reason:\n | \"cancelled\"\n | \"tool-calls\"\n | \"length\"\n | \"content-filter\"\n | \"other\"\n | \"error\";\n readonly error?: ReadonlyJSONValue;\n };\n\nexport type MessageTiming = {\n readonly streamStartTime: number;\n readonly firstTokenTime?: number;\n readonly totalStreamTime?: number;\n readonly tokenCount?: number;\n readonly tokensPerSecond?: number;\n readonly totalChunks: number;\n readonly toolCallCount: number;\n};\n\nexport type ThreadStep = {\n readonly messageId?: string;\n readonly usage?:\n | {\n readonly inputTokens: number;\n readonly outputTokens: number;\n }\n | undefined;\n};\n\ntype MessageCommonProps = {\n readonly id: string;\n readonly createdAt: Date;\n};\n\nexport type ThreadSystemMessage = MessageCommonProps & {\n readonly role: \"system\";\n readonly content: readonly [TextMessagePart];\n readonly metadata: {\n readonly unstable_state?: undefined;\n readonly unstable_annotations?: undefined;\n readonly unstable_data?: undefined;\n readonly steps?: undefined;\n readonly submittedFeedback?: undefined;\n readonly timing?: undefined;\n readonly custom: Record<string, unknown>;\n };\n};\n\nexport type ThreadUserMessage = MessageCommonProps & {\n readonly role: \"user\";\n readonly content: readonly ThreadUserMessagePart[];\n readonly attachments: readonly CompleteAttachment[];\n readonly metadata: {\n readonly unstable_state?: undefined;\n readonly unstable_annotations?: undefined;\n readonly unstable_data?: undefined;\n readonly steps?: undefined;\n readonly submittedFeedback?: undefined;\n readonly timing?: undefined;\n readonly isOptimistic?: boolean;\n readonly custom: Record<string, unknown>;\n };\n};\n\nexport type ThreadAssistantMessage = MessageCommonProps & {\n readonly role: \"assistant\";\n readonly content: readonly ThreadAssistantMessagePart[];\n readonly status: MessageStatus;\n readonly metadata: {\n readonly unstable_state: ReadonlyJSONValue;\n readonly unstable_annotations: readonly ReadonlyJSONValue[];\n readonly unstable_data: readonly ReadonlyJSONValue[];\n readonly steps: readonly ThreadStep[];\n readonly submittedFeedback?: { readonly type: \"positive\" | \"negative\" };\n readonly timing?: MessageTiming;\n /**\n * Marks a client-side optimistic placeholder. Such messages are evicted\n * once off the head branch and are never persisted.\n */\n readonly isOptimistic?: boolean;\n readonly custom: Record<string, unknown>;\n };\n};\n\ntype BaseThreadMessage = {\n readonly status?: ThreadAssistantMessage[\"status\"];\n readonly metadata: {\n readonly unstable_state?: ReadonlyJSONValue;\n readonly unstable_annotations?: readonly ReadonlyJSONValue[];\n readonly unstable_data?: readonly ReadonlyJSONValue[];\n readonly steps?: readonly ThreadStep[];\n readonly submittedFeedback?: { readonly type: \"positive\" | \"negative\" };\n readonly timing?: MessageTiming;\n readonly isOptimistic?: boolean;\n readonly custom: Record<string, unknown>;\n };\n readonly attachments?: ThreadUserMessage[\"attachments\"];\n};\n\nexport type ThreadMessage = BaseThreadMessage &\n (ThreadSystemMessage | ThreadUserMessage | ThreadAssistantMessage);\n\nexport type MessageRole = ThreadMessage[\"role\"];\n\nexport type RunConfig = {\n readonly custom?: Record<string, unknown>;\n};\n\nexport type AppendMessage = Omit<ThreadMessage, \"id\"> & {\n parentId: string | null;\n\n /** The ID of the message that was edited or undefined. */\n sourceId: string | null;\n runConfig: RunConfig | undefined;\n startRun?: boolean | undefined;\n /** Process this message next; only meaningful for queue-capable runtimes. */\n steer?: boolean | undefined;\n};\n"],"mappings":";AAsJA,MAAaiD,qBAAqB;AAElC,MAAaC,eAAeC,QAC1B,CAAC,CAACA,KAAKC,WAAWH,kBAAkB"}
1
+ {"version":3,"file":"message.js","names":["ReadonlyJSONObject","ReadonlyJSONValue","ToolCallTiming","ToolModelContentPart","CompleteAttachment","PartProviderMetadata","providerName","TextMessagePart","type","text","status","MessagePartStreamStatus","providerMetadata","parentId","ReasoningMessagePart","unstable_summary","SourceProviderMetadata","SourceMessagePart","sourceType","id","url","title","mediaType","filename","ImageMessagePart","image","FileMessagePart","data","mimeType","Unstable_AudioMessagePart","audio","format","DataMessagePart","name","T","GenerativeUINode","component","props","Record","children","key","GenerativeUISpec","root","GenerativeUIMessagePart","spec","McpAppMetadata","resourceUri","visibility","serverId","MCP_APP_URI_SCHEME","isMcpAppUri","uri","startsWith","ToolCallMessagePartMcpMetadata","app","ToolApprovalOptionKind","ToolApprovalOption","kind","label","description","grants","confirm","ToolApprovalResponse","approved","reason","optionId","ToolCallMessagePart","toolCallId","toolName","args","TArgs","result","TResult","isError","argsText","artifact","timing","mcp","modelContent","interrupt","payload","approval","isAutomatic","options","resolution","messages","ThreadMessage","ThreadUserMessagePart","ThreadAssistantMessagePart","MessagePartStatus","error","ToolCallMessagePartStatus","MessageStatus","MessageTiming","streamStartTime","firstTokenTime","totalStreamTime","tokenCount","tokensPerSecond","totalChunks","toolCallCount","ThreadStep","messageId","usage","inputTokens","outputTokens","MessageCommonProps","createdAt","Date","ThreadSystemMessage","role","content","metadata","unstable_state","unstable_annotations","unstable_data","steps","submittedFeedback","custom","ThreadUserMessage","attachments","isOptimistic","ThreadAssistantMessage","BaseThreadMessage","MessageRole","RunConfig","AppendMessage","Omit","sourceId","runConfig","startRun","steer"],"sources":["../../src/types/message.ts"],"sourcesContent":["import type {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from \"assistant-stream/utils\";\nimport type { ToolCallTiming, ToolModelContentPart } from \"assistant-stream\";\nimport type { CompleteAttachment } from \"./attachment\";\n\nexport type { ToolCallTiming, ToolModelContentPart };\n\nexport type PartProviderMetadata = {\n readonly [providerName: string]: ReadonlyJSONObject;\n};\n\nexport type TextMessagePart = {\n readonly type: \"text\";\n readonly text: string;\n readonly status?: MessagePartStreamStatus;\n readonly providerMetadata?: PartProviderMetadata;\n readonly parentId?: string;\n};\n\nexport type ReasoningMessagePart = {\n readonly type: \"reasoning\";\n readonly text: string;\n readonly status?: MessagePartStreamStatus;\n readonly unstable_summary?: string;\n readonly providerMetadata?: PartProviderMetadata;\n readonly parentId?: string;\n};\n\nexport type SourceProviderMetadata = PartProviderMetadata;\n\nexport type SourceMessagePart =\n | {\n readonly type: \"source\";\n readonly sourceType: \"url\";\n readonly id: string;\n readonly url: string;\n readonly title?: string;\n readonly providerMetadata?: SourceProviderMetadata;\n readonly parentId?: string;\n }\n | {\n readonly type: \"source\";\n readonly sourceType: \"document\";\n readonly id: string;\n readonly url?: undefined;\n readonly title: string;\n readonly mediaType: string;\n readonly filename?: string;\n readonly providerMetadata?: SourceProviderMetadata;\n readonly parentId?: string;\n };\n\nexport type ImageMessagePart = {\n readonly type: \"image\";\n readonly image: string;\n readonly filename?: string;\n readonly providerMetadata?: PartProviderMetadata;\n};\n\nexport type FileMessagePart = {\n readonly type: \"file\";\n readonly filename?: string;\n readonly data: string;\n readonly mimeType: string;\n /** How `data` goes on the wire: a url or id reference; omitted = inferred (http(s) → url, else base64). \"url\" is honored by the LangChain-family, A2A, AG-UI, and Google ADK runtimes; \"id\" by the LangChain family only. */\n readonly sourceType?: \"url\" | \"id\";\n readonly providerMetadata?: PartProviderMetadata;\n readonly parentId?: string;\n};\n\n/**\n * @deprecated Use {@link FileMessagePart} with an `audio/*` mime type. `file`\n * is the carrier for every non-image binary modality: it is a member of both\n * the user and assistant unions, carries a filename, and can declare how its\n * payload goes on the wire, none of which this shape can express. The payload\n * form a `file` part needs is still adapter specific; see the Part Types\n * section of the message primitive docs. Honored everywhere it is accepted; it\n * will not gain fields.\n */\nexport type Unstable_AudioMessagePart = {\n readonly type: \"audio\";\n readonly audio: {\n readonly data: string;\n readonly format: \"mp3\" | \"wav\";\n };\n};\n\nexport type DataMessagePart<T = any> = {\n readonly type: \"data\";\n readonly name: string;\n readonly data: T;\n};\n\n/**\n * A JSON spec describing a tree of UI components to render.\n *\n * The agent emits a {@link GenerativeUIMessagePart} containing this spec, and\n * the consumer-provided component allowlist is used to resolve `component`\n * names. Any component referenced that is not present in the allowlist is\n * rejected with a typed error — the allowlist is the security boundary in the\n * default same-realm rendering path.\n */\nexport type GenerativeUINode =\n | string\n | {\n /** Allowlisted component name (resolved against the consumer registry). */\n readonly component: string;\n /** Props passed to the resolved component (must be JSON-serializable). */\n readonly props?: Record<string, unknown>;\n /** Optional children — strings render as text, objects recurse. */\n readonly children?: readonly GenerativeUINode[];\n /** Optional stable key for React reconciliation. */\n readonly key?: string;\n };\n\n/**\n * The root spec for a generative UI tree.\n */\nexport type GenerativeUISpec = {\n /** Root node(s) to render. */\n readonly root: GenerativeUINode | readonly GenerativeUINode[];\n};\n\n/**\n * A message part that carries a JSON spec describing UI to render.\n *\n * Render with `<MessagePrimitive.GenerativeUI components={...} />`. The\n * primitive resolves component names against the consumer-provided allowlist\n * — any unknown name throws a typed error rather than rendering. Stream-\n * friendly: a partially-streamed spec renders progressively.\n */\nexport type GenerativeUIMessagePart = {\n readonly type: \"generative-ui\";\n /** The JSON spec describing the UI tree. */\n readonly spec: GenerativeUISpec;\n /** Optional id (useful for replays / stable keys). */\n readonly id?: string;\n readonly parentId?: string;\n};\n\nexport type McpAppMetadata = {\n readonly resourceUri: string;\n readonly mimeType?: string;\n readonly visibility?: readonly (\"model\" | \"app\")[];\n /** Routable server identity emitted by the agent stack when multiple MCP servers back one agent; for @ag-ui/mcp-apps-middleware this is the configured serverId, falling back to its serverHash. */\n readonly serverId?: string;\n};\n\nexport const MCP_APP_URI_SCHEME = \"ui://\";\n\nexport const isMcpAppUri = (uri: string | undefined): boolean =>\n !!uri?.startsWith(MCP_APP_URI_SCHEME);\n\nexport type ToolCallMessagePartMcpMetadata = {\n readonly app?: McpAppMetadata;\n};\n\nexport type ToolApprovalOptionKind =\n | \"allow-once\"\n | \"allow-always\"\n | \"reject-once\"\n | \"reject-always\";\n\nexport type ToolApprovalOption = {\n /** Opaque, host-defined identifier. Scope semantics (session vs project vs global) belong to the option supplier. */\n readonly id: string;\n /**\n * Decision class. Drives approved-resolution and default rendering.\n * Open union: `_`-prefixed custom kinds are never auto-resolved; they must\n * be answered with an explicit `approved` value (optionally alongside the\n * `optionId`), which is what the default kit sends when one is chosen.\n */\n readonly kind: ToolApprovalOptionKind | (string & {});\n /** Human label. Renderers supply defaults per kind when omitted. */\n readonly label?: string;\n readonly description?: string;\n /** Patterns or rules this option would persist, shown before the user commits. Supplied by the host; never derived by the library. */\n readonly grants?: readonly string[];\n /** Opt-in confirmation step before this option resolves. */\n readonly confirm?: boolean | { title?: string; description?: string };\n};\n\nexport type ToolApprovalResponse =\n | { readonly approved: boolean; readonly reason?: string }\n | { readonly optionId: string; readonly reason?: string }\n | {\n readonly approved: boolean;\n readonly optionId: string;\n readonly reason?: string;\n };\n\nexport type ToolCallMessagePart<\n TArgs = ReadonlyJSONObject,\n TResult = unknown,\n> = {\n /** Identifies this part as a tool call. */\n readonly type: \"tool-call\";\n /** Stable identifier for this invocation of the tool. */\n readonly toolCallId: string;\n /** Name of the tool requested by the model. */\n readonly toolName: string;\n /**\n * Arguments supplied by the model. During streaming this is a partial parse:\n * fields may be missing or incomplete. From a tool-call renderer, use\n * `useToolArgsStatus` to detect which fields are still arriving.\n */\n readonly args: TArgs;\n /** Result returned by the tool, if it has completed. */\n readonly result?: TResult | undefined;\n /** Whether the result represents a tool execution error. */\n readonly isError?: boolean | undefined;\n /** Raw JSON argument text streamed by the model. */\n readonly argsText: string;\n /** UI-only artifact associated with the tool result. */\n readonly artifact?: unknown;\n /** Wall-clock timing for this call, when the runtime or host tracks it. */\n readonly timing?: ToolCallTiming;\n /** MCP app metadata associated with this tool call, when present. */\n readonly mcp?: ToolCallMessagePartMcpMetadata;\n /** Provider metadata associated with this tool call, when present. */\n readonly providerMetadata?: PartProviderMetadata;\n /** Content returned to the model for this tool result. */\n readonly modelContent?: readonly ToolModelContentPart[] | undefined;\n /** Human-input request that must be resolved before the run can continue. */\n readonly interrupt?: { type: \"human\"; payload: unknown };\n /** Server-side approval gate. `respondToApproval` may only be called while `approved` is undefined and no `resolution` is recorded. */\n readonly approval?: {\n readonly id: string;\n readonly approved?: boolean;\n readonly reason?: string;\n readonly isAutomatic?: boolean;\n /** Available decisions for this call. Absent: a plain allow / deny pair. */\n readonly options?: readonly ToolApprovalOption[];\n /** The option chosen at resolution, when options were present. */\n readonly optionId?: string;\n /** Terminal non-decision state: the request was cancelled or expired without a user decision. Set by the host. */\n readonly resolution?: \"cancelled\" | \"expired\";\n };\n /** Parent message-part ID when this part belongs to a nested structure. */\n readonly parentId?: string;\n /**\n * Nested thread messages produced by this tool call, for example a sub-agent\n * conversation.\n */\n readonly messages?: readonly ThreadMessage[];\n};\n\nexport type ThreadUserMessagePart =\n | TextMessagePart\n | ImageMessagePart\n | FileMessagePart\n | DataMessagePart\n | Unstable_AudioMessagePart;\n\nexport type ThreadAssistantMessagePart =\n | TextMessagePart\n | ReasoningMessagePart\n | ToolCallMessagePart\n | SourceMessagePart\n | FileMessagePart\n | ImageMessagePart\n | DataMessagePart\n | GenerativeUIMessagePart;\n\nexport type MessagePartStatus =\n | {\n readonly type: \"running\";\n }\n | {\n readonly type: \"complete\";\n }\n | {\n readonly type: \"incomplete\";\n readonly reason:\n | \"cancelled\"\n | \"length\"\n | \"content-filter\"\n | \"other\"\n | \"error\";\n readonly error?: unknown;\n };\n\nexport type MessagePartStreamStatus =\n | {\n readonly type: \"running\";\n }\n | {\n readonly type: \"complete\";\n }\n | {\n readonly type: \"incomplete\";\n readonly reason:\n | \"cancelled\"\n | \"length\"\n | \"content-filter\"\n | \"other\"\n | \"error\";\n };\n\nexport type ToolCallMessagePartStatus =\n | {\n /** The tool call is waiting for UI or human input before continuing. */\n readonly type: \"requires-action\";\n /** Reason the tool call requires action. */\n readonly reason: \"tool-calls\" | \"interrupt\";\n }\n | {\n readonly type: \"incomplete\";\n readonly reason: \"tool-calls\";\n readonly error?: ReadonlyJSONValue;\n }\n | MessagePartStatus;\n\nexport type MessageStatus =\n | {\n readonly type: \"running\";\n }\n | {\n readonly type: \"requires-action\";\n readonly reason: \"tool-calls\" | \"interrupt\";\n }\n | {\n readonly type: \"complete\";\n readonly reason: \"stop\" | \"unknown\";\n }\n | {\n readonly type: \"incomplete\";\n readonly reason:\n | \"cancelled\"\n | \"tool-calls\"\n | \"length\"\n | \"content-filter\"\n | \"other\"\n | \"error\";\n readonly error?: ReadonlyJSONValue;\n };\n\nexport type MessageTiming = {\n readonly streamStartTime: number;\n readonly firstTokenTime?: number;\n readonly totalStreamTime?: number;\n readonly tokenCount?: number;\n readonly tokensPerSecond?: number;\n readonly totalChunks: number;\n readonly toolCallCount: number;\n};\n\nexport type ThreadStep = {\n readonly messageId?: string;\n readonly usage?:\n | {\n readonly inputTokens: number;\n readonly outputTokens: number;\n }\n | undefined;\n};\n\ntype MessageCommonProps = {\n readonly id: string;\n readonly createdAt: Date;\n};\n\nexport type ThreadSystemMessage = MessageCommonProps & {\n readonly role: \"system\";\n readonly content: readonly [TextMessagePart];\n readonly metadata: {\n readonly unstable_state?: undefined;\n readonly unstable_annotations?: undefined;\n readonly unstable_data?: undefined;\n readonly steps?: undefined;\n readonly submittedFeedback?: undefined;\n readonly timing?: undefined;\n readonly custom: Record<string, unknown>;\n };\n};\n\nexport type ThreadUserMessage = MessageCommonProps & {\n readonly role: \"user\";\n readonly content: readonly ThreadUserMessagePart[];\n readonly attachments: readonly CompleteAttachment[];\n readonly metadata: {\n readonly unstable_state?: undefined;\n readonly unstable_annotations?: undefined;\n readonly unstable_data?: undefined;\n readonly steps?: undefined;\n readonly submittedFeedback?: undefined;\n readonly timing?: undefined;\n readonly isOptimistic?: boolean;\n readonly custom: Record<string, unknown>;\n };\n};\n\nexport type ThreadAssistantMessage = MessageCommonProps & {\n readonly role: \"assistant\";\n readonly content: readonly ThreadAssistantMessagePart[];\n readonly status: MessageStatus;\n readonly metadata: {\n readonly unstable_state: ReadonlyJSONValue;\n readonly unstable_annotations: readonly ReadonlyJSONValue[];\n readonly unstable_data: readonly ReadonlyJSONValue[];\n readonly steps: readonly ThreadStep[];\n readonly submittedFeedback?: { readonly type: \"positive\" | \"negative\" };\n readonly timing?: MessageTiming;\n /**\n * Marks a client-side optimistic placeholder. Such messages are evicted\n * once off the head branch and are never persisted.\n */\n readonly isOptimistic?: boolean;\n readonly custom: Record<string, unknown>;\n };\n};\n\ntype BaseThreadMessage = {\n readonly status?: ThreadAssistantMessage[\"status\"];\n readonly metadata: {\n readonly unstable_state?: ReadonlyJSONValue;\n readonly unstable_annotations?: readonly ReadonlyJSONValue[];\n readonly unstable_data?: readonly ReadonlyJSONValue[];\n readonly steps?: readonly ThreadStep[];\n readonly submittedFeedback?: { readonly type: \"positive\" | \"negative\" };\n readonly timing?: MessageTiming;\n readonly isOptimistic?: boolean;\n readonly custom: Record<string, unknown>;\n };\n readonly attachments?: ThreadUserMessage[\"attachments\"];\n};\n\nexport type ThreadMessage = BaseThreadMessage &\n (ThreadSystemMessage | ThreadUserMessage | ThreadAssistantMessage);\n\nexport type MessageRole = ThreadMessage[\"role\"];\n\nexport type RunConfig = {\n readonly custom?: Record<string, unknown>;\n};\n\nexport type AppendMessage = Omit<ThreadMessage, \"id\"> & {\n parentId: string | null;\n\n /** The ID of the message that was edited or undefined. */\n sourceId: string | null;\n runConfig: RunConfig | undefined;\n startRun?: boolean | undefined;\n /** Process this message next; only meaningful for queue-capable runtimes. */\n steer?: boolean | undefined;\n};\n"],"mappings":";AAsJA,MAAaiD,qBAAqB;AAElC,MAAaC,eAAeC,QAC1B,CAAC,CAACA,KAAKC,WAAWH,kBAAkB"}
@@ -1,9 +1,22 @@
1
1
  //#region src/utils/data-url.d.ts
2
2
  declare const httpUrlPattern: RegExp;
3
+ type FilePartSource = {
4
+ kind: "url";
5
+ url: string;
6
+ } | {
7
+ kind: "data";
8
+ data: string;
9
+ mimeType: string;
10
+ };
3
11
  declare function parseDataUrl(value: string): {
4
12
  mimeType: string;
5
13
  data: string;
6
14
  } | null;
15
+ declare const resolveFilePartSource: (part: {
16
+ data: string;
17
+ mimeType: string;
18
+ sourceType?: string | undefined;
19
+ }) => FilePartSource;
7
20
  /**
8
21
  * Whether a payload is something `new URL()` accepts. Adapters that place a
9
22
  * `FileMessagePart` payload into a url-typed wire field use this to decide
@@ -18,5 +31,5 @@ declare function isParsableUrl(value: string): boolean;
18
31
  */
19
32
  declare function dataUrlMediaType(value: string): string | undefined;
20
33
  //#endregion
21
- export { dataUrlMediaType, httpUrlPattern, isParsableUrl, parseDataUrl };
34
+ export { FilePartSource, dataUrlMediaType, httpUrlPattern, isParsableUrl, parseDataUrl, resolveFilePartSource };
22
35
  //# sourceMappingURL=data-url.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"data-url.d.ts","names":[],"sources":["../../src/utils/data-url.ts"],"mappings":";cAAa,gBAAc;iBAEX,aACd;EACG;EAAkB;;;;;;;;iBAYP,cAAc;;;;;;iBAcd,iBAAiB"}
1
+ {"version":3,"file":"data-url.d.ts","names":[],"sources":["../../src/utils/data-url.ts"],"mappings":";cAAa,gBAAc;KAEf;EACN;EAAa;;EACb;EAAc;EAAc;;iBAElB,aACd;EACG;EAAkB;;cAMV,wBAAyB;EACpC;EACA;EACA;MACE;;;;;;;iBAmBY,cAAc;;;;;;iBAcd,iBAAiB"}
@@ -8,6 +8,18 @@ function parseDataUrl(value) {
8
8
  data: match[2]
9
9
  };
10
10
  }
11
+ const resolveFilePartSource = (part) => {
12
+ if (part.sourceType === "url" || httpUrlPattern.test(part.data)) return {
13
+ kind: "url",
14
+ url: part.data
15
+ };
16
+ const parsed = parseDataUrl(part.data);
17
+ return {
18
+ kind: "data",
19
+ data: parsed?.data ?? part.data,
20
+ mimeType: parsed?.mimeType ?? part.mimeType
21
+ };
22
+ };
11
23
  /**
12
24
  * Whether a payload is something `new URL()` accepts. Adapters that place a
13
25
  * `FileMessagePart` payload into a url-typed wire field use this to decide
@@ -31,6 +43,6 @@ function dataUrlMediaType(value) {
31
43
  return /^data:([^;,]+)(?:[;,])/i.exec(value)?.[1]?.toLowerCase();
32
44
  }
33
45
  //#endregion
34
- export { dataUrlMediaType, httpUrlPattern, isParsableUrl, parseDataUrl };
46
+ export { dataUrlMediaType, httpUrlPattern, isParsableUrl, parseDataUrl, resolveFilePartSource };
35
47
 
36
48
  //# sourceMappingURL=data-url.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"data-url.js","names":["httpUrlPattern","parseDataUrl","value","mimeType","data","match","toLowerCase","isParsableUrl","URL","dataUrlMediaType","exec"],"sources":["../../src/utils/data-url.ts"],"sourcesContent":["export const httpUrlPattern = /^https?:\\/\\//i;\n\nexport function parseDataUrl(\n value: string,\n): { mimeType: string; data: string } | null {\n const match = value.match(/^data:([^;,]+)(?:;[^;,]+)*;base64,(.*)$/i);\n if (!match) return null;\n return { mimeType: match[1]!.toLowerCase(), data: match[2]! };\n}\n\n/**\n * Whether a payload is something `new URL()` accepts. Adapters that place a\n * `FileMessagePart` payload into a url-typed wire field use this to decide\n * whether it has to be wrapped in a data URL envelope first; base64 cannot\n * contain a colon, so a real payload is never misread as a url.\n */\nexport function isParsableUrl(value: string): boolean {\n try {\n new URL(value);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * The media type a data URL declares, whether or not its payload is base64.\n * `parseDataUrl` only matches base64 payloads because it also returns the\n * bytes; this reads the declaration alone.\n */\nexport function dataUrlMediaType(value: string): string | undefined {\n return /^data:([^;,]+)(?:[;,])/i.exec(value)?.[1]?.toLowerCase();\n}\n"],"mappings":";AAAA,MAAaA,iBAAiB;AAE9B,SAAgBC,aACdC,OAC2C;CAC3C,MAAMG,QAAQH,MAAMG,MAAM,0CAA0C;CACpE,IAAI,CAACA,OAAO,OAAO;CACnB,OAAO;EAAEF,UAAUE,MAAM,EAAE,CAAEC,YAAY;EAAGF,MAAMC,MAAM;CAAI;AAC9D;;;;;;;AAQA,SAAgBE,cAAcL,OAAwB;CACpD,IAAI;EACF,IAAIM,IAAIN,KAAK;EACb,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;;;;;;AAOA,SAAgBO,iBAAiBP,OAAmC;CAClE,OAAO,0BAA0BQ,KAAKR,KAAK,CAAC,GAAG,EAAE,EAAEI,YAAY;AACjE"}
1
+ {"version":3,"file":"data-url.js","names":["httpUrlPattern","FilePartSource","kind","url","data","mimeType","parseDataUrl","value","match","toLowerCase","resolveFilePartSource","part","sourceType","test","parsed","isParsableUrl","URL","dataUrlMediaType","exec"],"sources":["../../src/utils/data-url.ts"],"sourcesContent":["export const httpUrlPattern = /^https?:\\/\\//i;\n\nexport type FilePartSource =\n | { kind: \"url\"; url: string }\n | { kind: \"data\"; data: string; mimeType: string };\n\nexport function parseDataUrl(\n value: string,\n): { mimeType: string; data: string } | null {\n const match = value.match(/^data:([^;,]+)(?:;[^;,]+)*;base64,(.*)$/i);\n if (!match) return null;\n return { mimeType: match[1]!.toLowerCase(), data: match[2]! };\n}\n\nexport const resolveFilePartSource = (part: {\n data: string;\n mimeType: string;\n sourceType?: string | undefined;\n}): FilePartSource => {\n if (part.sourceType === \"url\" || httpUrlPattern.test(part.data)) {\n return { kind: \"url\", url: part.data };\n }\n\n const parsed = parseDataUrl(part.data);\n return {\n kind: \"data\",\n data: parsed?.data ?? part.data,\n mimeType: parsed?.mimeType ?? part.mimeType,\n };\n};\n\n/**\n * Whether a payload is something `new URL()` accepts. Adapters that place a\n * `FileMessagePart` payload into a url-typed wire field use this to decide\n * whether it has to be wrapped in a data URL envelope first; base64 cannot\n * contain a colon, so a real payload is never misread as a url.\n */\nexport function isParsableUrl(value: string): boolean {\n try {\n new URL(value);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * The media type a data URL declares, whether or not its payload is base64.\n * `parseDataUrl` only matches base64 payloads because it also returns the\n * bytes; this reads the declaration alone.\n */\nexport function dataUrlMediaType(value: string): string | undefined {\n return /^data:([^;,]+)(?:[;,])/i.exec(value)?.[1]?.toLowerCase();\n}\n"],"mappings":";AAAA,MAAaA,iBAAiB;AAM9B,SAAgBM,aACdC,OAC2C;CAC3C,MAAMC,QAAQD,MAAMC,MAAM,0CAA0C;CACpE,IAAI,CAACA,OAAO,OAAO;CACnB,OAAO;EAAEH,UAAUG,MAAM,EAAE,CAAEC,YAAY;EAAGL,MAAMI,MAAM;CAAI;AAC9D;AAEA,MAAaE,yBAAyBC,SAIhB;CACpB,IAAIA,KAAKC,eAAe,SAASZ,eAAea,KAAKF,KAAKP,IAAI,GAC5D,OAAO;EAAEF,MAAM;EAAOC,KAAKQ,KAAKP;CAAK;CAGvC,MAAMU,SAASR,aAAaK,KAAKP,IAAI;CACrC,OAAO;EACLF,MAAM;EACNE,MAAMU,QAAQV,QAAQO,KAAKP;EAC3BC,UAAUS,QAAQT,YAAYM,KAAKN;CACrC;AACF;;;;;;;AAQA,SAAgBU,cAAcR,OAAwB;CACpD,IAAI;EACF,IAAIS,IAAIT,KAAK;EACb,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;;;;;;AAOA,SAAgBU,iBAAiBV,OAAmC;CAClE,OAAO,0BAA0BW,KAAKX,KAAK,CAAC,GAAG,EAAE,EAAEE,YAAY;AACjE"}
@@ -0,0 +1,5 @@
1
+ //#region src/utils/invoke-user-callback.d.ts
2
+ declare function invokeUserCallback<TArgs extends readonly unknown[]>(tag: string, name: string, callback: ((...args: TArgs) => unknown) | undefined, ...args: TArgs): void | Promise<void>;
3
+ //#endregion
4
+ export { invokeUserCallback };
5
+ //# sourceMappingURL=invoke-user-callback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoke-user-callback.d.ts","names":[],"sources":["../../src/utils/invoke-user-callback.ts"],"mappings":";iBAAgB,mBAAmB,kCACjC,aACA,cACA,eAAe,MAAM,mCAClB,MAAM,eACD"}
@@ -0,0 +1,19 @@
1
+ //#region src/utils/invoke-user-callback.ts
2
+ function invokeUserCallback(tag, name, callback, ...args) {
3
+ if (!callback) return;
4
+ const reportError = (error) => {
5
+ try {
6
+ console.error(`[${tag}] ${name} callback threw an error`, error);
7
+ } catch {}
8
+ };
9
+ try {
10
+ const result = callback(...args);
11
+ if (result !== null && (typeof result === "object" || typeof result === "function") && "then" in result && typeof result.then === "function") return Promise.resolve(result).then(() => void 0, (error) => reportError(error));
12
+ } catch (error) {
13
+ reportError(error);
14
+ }
15
+ }
16
+ //#endregion
17
+ export { invokeUserCallback };
18
+
19
+ //# sourceMappingURL=invoke-user-callback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoke-user-callback.js","names":["invokeUserCallback","tag","name","callback","args","TArgs","Promise","reportError","error","console","result","then","resolve","undefined"],"sources":["../../src/utils/invoke-user-callback.ts"],"sourcesContent":["export function invokeUserCallback<TArgs extends readonly unknown[]>(\n tag: string,\n name: string,\n callback: ((...args: TArgs) => unknown) | undefined,\n ...args: TArgs\n): void | Promise<void> {\n if (!callback) return;\n\n const reportError = (error: unknown) => {\n try {\n console.error(`[${tag}] ${name} callback threw an error`, error);\n } catch {}\n };\n\n try {\n const result = callback(...args);\n if (\n result !== null &&\n (typeof result === \"object\" || typeof result === \"function\") &&\n \"then\" in result &&\n typeof result.then === \"function\"\n ) {\n return Promise.resolve(result).then(\n () => undefined,\n (error) => reportError(error),\n );\n }\n } catch (error) {\n reportError(error);\n }\n}\n"],"mappings":";AAAA,SAAgBA,mBACdC,KACAC,MACAC,UACA,GAAGC,MACmB;CACtB,IAAI,CAACD,UAAU;CAEf,MAAMI,eAAeC,UAAmB;EACtC,IAAI;GACFC,QAAQD,MAAM,IAAIP,IAAG,IAAKC,KAAI,2BAA4BM,KAAK;EACjE,QAAQ,CAAC;CACX;CAEA,IAAI;EACF,MAAME,SAASP,SAAS,GAAGC,IAAI;EAC/B,IACEM,WAAW,SACV,OAAOA,WAAW,YAAY,OAAOA,WAAW,eACjD,UAAUA,UACV,OAAOA,OAAOC,SAAS,YAEvB,OAAOL,QAAQM,QAAQF,MAAM,CAAC,CAACC,WACvBE,KAAAA,IACLL,UAAUD,YAAYC,KAAK,CAC9B;CAEJ,SAASA,OAAO;EACdD,YAAYC,KAAK;CACnB;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"normalizePartStatus.js","names":["MessagePartStatus","MessagePartStreamStatus","ThreadAssistantMessagePart","ThreadMessage","ThreadUserMessagePart","ToolCallMessagePartStatus","COMPLETE_STATUS","Object","freeze","type","RUNNING_STATUS","IncompleteMessagePartStatus","Extract","INCOMPLETE_STATUSES","Readonly","Record","cancelled","reason","length","other","error","normalizePartStatus","part","status","undefined","normalizedReason","toMessagePartStatus","message","partIndex","role","result","isLastPart","Math","max","content"],"sources":["../../src/utils/normalizePartStatus.ts"],"sourcesContent":["import type {\n MessagePartStatus,\n MessagePartStreamStatus,\n ThreadAssistantMessagePart,\n ThreadMessage,\n ThreadUserMessagePart,\n ToolCallMessagePartStatus,\n} from \"../types/message\";\n\nexport const COMPLETE_STATUS: MessagePartStatus = Object.freeze({\n type: \"complete\",\n});\nexport const RUNNING_STATUS: MessagePartStatus = Object.freeze({\n type: \"running\",\n});\ntype IncompleteMessagePartStatus = Extract<\n MessagePartStreamStatus,\n { readonly type: \"incomplete\" }\n>;\nconst INCOMPLETE_STATUSES: Readonly<\n Record<IncompleteMessagePartStatus[\"reason\"], IncompleteMessagePartStatus>\n> = Object.freeze({\n cancelled: Object.freeze({ type: \"incomplete\", reason: \"cancelled\" }),\n length: Object.freeze({ type: \"incomplete\", reason: \"length\" }),\n \"content-filter\": Object.freeze({\n type: \"incomplete\",\n reason: \"content-filter\",\n }),\n other: Object.freeze({ type: \"incomplete\", reason: \"other\" }),\n error: Object.freeze({ type: \"incomplete\", reason: \"error\" }),\n});\n\nexport const normalizePartStatus = (\n part: ThreadUserMessagePart | ThreadAssistantMessagePart,\n): MessagePartStatus | undefined => {\n const status = (part as { readonly status?: unknown }).status;\n if (!status || typeof status !== \"object\") return undefined;\n\n const { type } = status as { readonly type?: unknown };\n if (type === \"running\") return RUNNING_STATUS;\n if (type === \"complete\") return COMPLETE_STATUS;\n if (type !== \"incomplete\") return undefined;\n\n const { reason } = status as {\n readonly reason?: unknown;\n };\n const normalizedReason: IncompleteMessagePartStatus[\"reason\"] =\n reason === \"cancelled\" ||\n reason === \"length\" ||\n reason === \"content-filter\" ||\n reason === \"other\" ||\n reason === \"error\"\n ? reason\n : \"other\";\n\n return INCOMPLETE_STATUSES[normalizedReason];\n};\n\nexport const toMessagePartStatus = (\n message: ThreadMessage,\n partIndex: number,\n part: ThreadUserMessagePart | ThreadAssistantMessagePart,\n): ToolCallMessagePartStatus => {\n if (message.role !== \"assistant\") return COMPLETE_STATUS;\n\n if (part.type === \"tool-call\") {\n if (part.result === undefined) {\n return message.status as ToolCallMessagePartStatus;\n } else {\n return COMPLETE_STATUS;\n }\n }\n\n if (message.status.type === \"running\") {\n const status = normalizePartStatus(part);\n if (status) return status;\n }\n\n const isLastPart = partIndex === Math.max(0, message.content.length - 1);\n if (message.status.type === \"requires-action\") return COMPLETE_STATUS;\n return isLastPart ? (message.status as MessagePartStatus) : COMPLETE_STATUS;\n};\n"],"mappings":";AASA,MAAaM,kBAAqCC,OAAOC,OAAO,EAC9DC,MAAM,WACR,CAAC;AACD,MAAaC,iBAAoCH,OAAOC,OAAO,EAC7DC,MAAM,UACR,CAAC;AAKD,MAAMI,sBAEFN,OAAOC,OAAO;CAChBQ,WAAWT,OAAOC,OAAO;EAAEC,MAAM;EAAcQ,QAAQ;CAAY,CAAC;CACpEC,QAAQX,OAAOC,OAAO;EAAEC,MAAM;EAAcQ,QAAQ;CAAS,CAAC;CAC9D,kBAAkBV,OAAOC,OAAO;EAC9BC,MAAM;EACNQ,QAAQ;CACV,CAAC;CACDE,OAAOZ,OAAOC,OAAO;EAAEC,MAAM;EAAcQ,QAAQ;CAAQ,CAAC;CAC5DG,OAAOb,OAAOC,OAAO;EAAEC,MAAM;EAAcQ,QAAQ;CAAQ,CAAC;AAC9D,CAAC;AAED,MAAaI,uBACXC,SACkC;CAClC,MAAMC,SAAUD,KAAuCC;CACvD,IAAI,CAACA,UAAU,OAAOA,WAAW,UAAU,OAAOC,KAAAA;CAElD,MAAM,EAAEf,SAASc;CACjB,IAAId,SAAS,WAAW,OAAOC;CAC/B,IAAID,SAAS,YAAY,OAAOH;CAChC,IAAIG,SAAS,cAAc,OAAOe,KAAAA;CAElC,MAAM,EAAEP,WAAWM;CAYnB,OAAOV,oBARLI,WAAW,eACXA,WAAW,YACXA,WAAW,oBACXA,WAAW,WACXA,WAAW,UACPA,SACA;AAGR;AAEA,MAAaS,uBACXC,SACAC,WACAN,SAC8B;CAC9B,IAAIK,QAAQE,SAAS,aAAa,OAAOvB;CAEzC,IAAIgB,KAAKb,SAAS,aAAa;EAC7B,IAAIa,KAAKQ,WAAWN,KAAAA,GAClB,OAAOG,QAAQJ;OAEf,OAAOjB;CAEX;CAEA,IAAIqB,QAAQJ,OAAOd,SAAS,WAAW;EACrC,MAAMc,SAASF,oBAAoBC,IAAI;EACvC,IAAIC,QAAQ,OAAOA;CACrB;CAEA,MAAMQ,aAAaH,cAAcI,KAAKC,IAAI,GAAGN,QAAQO,QAAQhB,SAAS,CAAC;CACvE,IAAIS,QAAQJ,OAAOd,SAAS,mBAAmB,OAAOH;CACtD,OAAOyB,aAAcJ,QAAQJ,SAA+BjB;AAC9D"}
1
+ {"version":3,"file":"normalizePartStatus.js","names":["MessagePartStatus","MessagePartStreamStatus","ThreadAssistantMessagePart","ThreadMessage","ThreadUserMessagePart","ToolCallMessagePartStatus","COMPLETE_STATUS","Object","freeze","type","RUNNING_STATUS","IncompleteMessagePartStatus","Extract","INCOMPLETE_STATUSES","Readonly","Record","cancelled","reason","length","other","error","normalizePartStatus","part","status","undefined","normalizedReason","toMessagePartStatus","message","partIndex","role","result","isLastPart","Math","max","content"],"sources":["../../src/utils/normalizePartStatus.ts"],"sourcesContent":["import type {\n MessagePartStatus,\n MessagePartStreamStatus,\n ThreadAssistantMessagePart,\n ThreadMessage,\n ThreadUserMessagePart,\n ToolCallMessagePartStatus,\n} from \"../types/message\";\n\nexport const COMPLETE_STATUS: MessagePartStatus = Object.freeze({\n type: \"complete\",\n});\nexport const RUNNING_STATUS: MessagePartStatus = Object.freeze({\n type: \"running\",\n});\ntype IncompleteMessagePartStatus = Extract<\n MessagePartStreamStatus,\n { readonly type: \"incomplete\" }\n>;\nconst INCOMPLETE_STATUSES: Readonly<\n Record<IncompleteMessagePartStatus[\"reason\"], IncompleteMessagePartStatus>\n> = Object.freeze({\n cancelled: Object.freeze({ type: \"incomplete\", reason: \"cancelled\" }),\n length: Object.freeze({ type: \"incomplete\", reason: \"length\" }),\n \"content-filter\": Object.freeze({\n type: \"incomplete\",\n reason: \"content-filter\",\n }),\n other: Object.freeze({ type: \"incomplete\", reason: \"other\" }),\n error: Object.freeze({ type: \"incomplete\", reason: \"error\" }),\n});\n\nexport const normalizePartStatus = (\n part: ThreadUserMessagePart | ThreadAssistantMessagePart,\n): MessagePartStatus | undefined => {\n const status = (part as { readonly status?: unknown }).status;\n if (!status || typeof status !== \"object\") return undefined;\n\n const { type } = status as { readonly type?: unknown };\n if (type === \"running\") return RUNNING_STATUS;\n if (type === \"complete\") return COMPLETE_STATUS;\n if (type !== \"incomplete\") return undefined;\n\n const { reason } = status as {\n readonly reason?: unknown;\n };\n const normalizedReason: IncompleteMessagePartStatus[\"reason\"] =\n reason === \"cancelled\" ||\n reason === \"length\" ||\n reason === \"content-filter\" ||\n reason === \"other\" ||\n reason === \"error\"\n ? reason\n : \"other\";\n\n return INCOMPLETE_STATUSES[normalizedReason];\n};\n\nexport const toMessagePartStatus = (\n message: ThreadMessage,\n partIndex: number,\n part: ThreadUserMessagePart | ThreadAssistantMessagePart,\n): ToolCallMessagePartStatus => {\n if (message.role !== \"assistant\") return COMPLETE_STATUS;\n\n if (part.type === \"tool-call\") {\n if (part.result === undefined) {\n return message.status;\n } else {\n return COMPLETE_STATUS;\n }\n }\n\n if (message.status.type === \"running\") {\n const status = normalizePartStatus(part);\n if (status) return status;\n }\n\n const isLastPart = partIndex === Math.max(0, message.content.length - 1);\n if (message.status.type === \"requires-action\") return COMPLETE_STATUS;\n return isLastPart ? (message.status as MessagePartStatus) : COMPLETE_STATUS;\n};\n"],"mappings":";AASA,MAAaM,kBAAqCC,OAAOC,OAAO,EAC9DC,MAAM,WACR,CAAC;AACD,MAAaC,iBAAoCH,OAAOC,OAAO,EAC7DC,MAAM,UACR,CAAC;AAKD,MAAMI,sBAEFN,OAAOC,OAAO;CAChBQ,WAAWT,OAAOC,OAAO;EAAEC,MAAM;EAAcQ,QAAQ;CAAY,CAAC;CACpEC,QAAQX,OAAOC,OAAO;EAAEC,MAAM;EAAcQ,QAAQ;CAAS,CAAC;CAC9D,kBAAkBV,OAAOC,OAAO;EAC9BC,MAAM;EACNQ,QAAQ;CACV,CAAC;CACDE,OAAOZ,OAAOC,OAAO;EAAEC,MAAM;EAAcQ,QAAQ;CAAQ,CAAC;CAC5DG,OAAOb,OAAOC,OAAO;EAAEC,MAAM;EAAcQ,QAAQ;CAAQ,CAAC;AAC9D,CAAC;AAED,MAAaI,uBACXC,SACkC;CAClC,MAAMC,SAAUD,KAAuCC;CACvD,IAAI,CAACA,UAAU,OAAOA,WAAW,UAAU,OAAOC,KAAAA;CAElD,MAAM,EAAEf,SAASc;CACjB,IAAId,SAAS,WAAW,OAAOC;CAC/B,IAAID,SAAS,YAAY,OAAOH;CAChC,IAAIG,SAAS,cAAc,OAAOe,KAAAA;CAElC,MAAM,EAAEP,WAAWM;CAYnB,OAAOV,oBARLI,WAAW,eACXA,WAAW,YACXA,WAAW,oBACXA,WAAW,WACXA,WAAW,UACPA,SACA;AAGR;AAEA,MAAaS,uBACXC,SACAC,WACAN,SAC8B;CAC9B,IAAIK,QAAQE,SAAS,aAAa,OAAOvB;CAEzC,IAAIgB,KAAKb,SAAS,aAAa;EAC7B,IAAIa,KAAKQ,WAAWN,KAAAA,GAClB,OAAOG,QAAQJ;OAEf,OAAOjB;CAEX;CAEA,IAAIqB,QAAQJ,OAAOd,SAAS,WAAW;EACrC,MAAMc,SAASF,oBAAoBC,IAAI;EACvC,IAAIC,QAAQ,OAAOA;CACrB;CAEA,MAAMQ,aAAaH,cAAcI,KAAKC,IAAI,GAAGN,QAAQO,QAAQhB,SAAS,CAAC;CACvE,IAAIS,QAAQJ,OAAOd,SAAS,mBAAmB,OAAOH;CACtD,OAAOyB,aAAcJ,QAAQJ,SAA+BjB;AAC9D"}
@@ -0,0 +1,6 @@
1
+ //#region src/utils/silent-runtime-action.d.ts
2
+ declare const SILENT_RUNTIME_ACTION: unique symbol;
3
+ declare const isSilentRuntimeAction: (error: unknown) => boolean;
4
+ //#endregion
5
+ export { SILENT_RUNTIME_ACTION, isSilentRuntimeAction };
6
+ //# sourceMappingURL=silent-runtime-action.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"silent-runtime-action.d.ts","names":[],"sources":["../../src/utils/silent-runtime-action.ts"],"mappings":";cAAa;cAIA,wBAAyB"}
@@ -0,0 +1,7 @@
1
+ //#region src/utils/silent-runtime-action.ts
2
+ const SILENT_RUNTIME_ACTION = Symbol.for("assistant-ui.silent-runtime-action");
3
+ const isSilentRuntimeAction = (error) => typeof error === "object" && error !== null && SILENT_RUNTIME_ACTION in error;
4
+ //#endregion
5
+ export { SILENT_RUNTIME_ACTION, isSilentRuntimeAction };
6
+
7
+ //# sourceMappingURL=silent-runtime-action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"silent-runtime-action.js","names":["SILENT_RUNTIME_ACTION","Symbol","for","isSilentRuntimeAction","error"],"sources":["../../src/utils/silent-runtime-action.ts"],"sourcesContent":["export const SILENT_RUNTIME_ACTION = Symbol.for(\n \"assistant-ui.silent-runtime-action\",\n);\n\nexport const isSilentRuntimeAction = (error: unknown): boolean =>\n typeof error === \"object\" && error !== null && SILENT_RUNTIME_ACTION in error;\n"],"mappings":";AAAA,MAAaA,wBAAwBC,OAAOC,IAC1C,oCACF;AAEA,MAAaC,yBAAyBC,UACpC,OAAOA,UAAU,YAAYA,UAAU,QAAQJ,yBAAyBI"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/core",
3
- "version": "0.3.14",
3
+ "version": "0.3.16",
4
4
  "description": "Framework-agnostic core runtime for assistant-ui",
5
5
  "keywords": [
6
6
  "assistant",
@@ -59,7 +59,7 @@
59
59
  ],
60
60
  "sideEffects": false,
61
61
  "dependencies": {
62
- "assistant-stream": "^0.3.38",
62
+ "assistant-stream": "^0.3.40",
63
63
  "nanoid": "^6.0.1"
64
64
  },
65
65
  "optionalDevDependencies": {
@@ -70,7 +70,7 @@
70
70
  "@assistant-ui/tap": "^0.9.0",
71
71
  "@types/react": "*",
72
72
  "react": "^18 || ^19",
73
- "assistant-cloud": "^0.1.31",
73
+ "assistant-cloud": "^0.1.42",
74
74
  "zustand": "^5.0.11"
75
75
  },
76
76
  "peerDependenciesMeta": {
@@ -88,18 +88,18 @@
88
88
  }
89
89
  },
90
90
  "devDependencies": {
91
+ "@assistant-ui/store": "0.3.11",
92
+ "@assistant-ui/tap": "0.9.15",
93
+ "@assistant-ui/vite": "0.0.15",
94
+ "@assistant-ui/x-buildutils": "0.0.24",
91
95
  "@testing-library/react": "^16.3.2",
92
96
  "@types/react": "^19.2.18",
97
+ "assistant-cloud": "0.1.42",
93
98
  "jsdom": "^30.0.1",
94
99
  "react": "^19.2.8",
95
100
  "react-dom": "^19.2.8",
96
- "vitest": "^4.1.10",
97
- "zustand": "^5.0.14",
98
- "@assistant-ui/store": "0.3.10",
99
- "@assistant-ui/tap": "0.9.13",
100
- "@assistant-ui/vite": "0.0.14",
101
- "@assistant-ui/x-buildutils": "0.0.23",
102
- "assistant-cloud": "0.1.41"
101
+ "vitest": "^4.1.11",
102
+ "zustand": "^5.0.15"
103
103
  },
104
104
  "publishConfig": {
105
105
  "access": "public",
@@ -73,6 +73,25 @@ describe("createVoiceSession", () => {
73
73
  expect(controls.mute).not.toHaveBeenCalled();
74
74
  });
75
75
 
76
+ it("disconnects immediately when created with an already-aborted signal", async () => {
77
+ const abortController = new AbortController();
78
+ abortController.abort();
79
+ const setup = vi.fn(async () => ({
80
+ disconnect: vi.fn(),
81
+ mute: vi.fn(),
82
+ unmute: vi.fn(),
83
+ }));
84
+
85
+ const session = createVoiceSession(
86
+ { abortSignal: abortController.signal },
87
+ setup,
88
+ );
89
+ await Promise.resolve();
90
+
91
+ expect(setup).not.toHaveBeenCalled();
92
+ expect(session.status).toEqual({ type: "ended", reason: "cancelled" });
93
+ });
94
+
76
95
  it("removes the abort listener after disconnecting", async () => {
77
96
  const abortController = new AbortController();
78
97
  const controls = {
@@ -85,11 +104,52 @@ describe("createVoiceSession", () => {
85
104
  async () => controls,
86
105
  );
87
106
  await Promise.resolve();
107
+ const statusListener = vi.fn();
108
+ session.onStatusChange(statusListener);
88
109
 
89
110
  session.disconnect();
90
111
  session.disconnect();
91
112
  abortController.abort();
92
113
 
114
+ expect(session.status).toEqual({ type: "ended", reason: "cancelled" });
115
+ expect(statusListener).toHaveBeenCalledOnce();
116
+ expect(statusListener).toHaveBeenCalledWith({
117
+ type: "ended",
118
+ reason: "cancelled",
119
+ });
120
+ expect(controls.disconnect).toHaveBeenCalledOnce();
121
+ });
122
+
123
+ it("ends a running session when the abort signal fires", async () => {
124
+ const abortController = new AbortController();
125
+ const controls = {
126
+ disconnect: vi.fn(),
127
+ mute: vi.fn(),
128
+ unmute: vi.fn(),
129
+ };
130
+ let helpers: VoiceSessionHelpers | undefined;
131
+ const session = createVoiceSession(
132
+ { abortSignal: abortController.signal },
133
+ async (sessionHelpers) => {
134
+ helpers = sessionHelpers;
135
+ return controls;
136
+ },
137
+ );
138
+ await Promise.resolve();
139
+ if (!helpers) throw new Error("Voice session setup did not start");
140
+
141
+ helpers.setStatus({ type: "running" });
142
+ const statusListener = vi.fn();
143
+ session.onStatusChange(statusListener);
144
+
145
+ abortController.abort();
146
+
147
+ expect(session.status).toEqual({ type: "ended", reason: "cancelled" });
148
+ expect(statusListener).toHaveBeenCalledOnce();
149
+ expect(statusListener).toHaveBeenCalledWith({
150
+ type: "ended",
151
+ reason: "cancelled",
152
+ });
93
153
  expect(controls.disconnect).toHaveBeenCalledOnce();
94
154
  });
95
155
 
@@ -101,7 +161,7 @@ describe("createVoiceSession", () => {
101
161
  unmute: vi.fn(),
102
162
  };
103
163
  let helpers: VoiceSessionHelpers | undefined;
104
- createVoiceSession(
164
+ const session = createVoiceSession(
105
165
  { abortSignal: abortController.signal },
106
166
  async (sessionHelpers) => {
107
167
  helpers = sessionHelpers;
@@ -114,6 +174,11 @@ describe("createVoiceSession", () => {
114
174
  helpers.end("error");
115
175
  abortController.abort();
116
176
 
177
+ expect(session.status).toEqual({
178
+ type: "ended",
179
+ reason: "error",
180
+ error: undefined,
181
+ });
117
182
  expect(controls.disconnect).toHaveBeenCalledOnce();
118
183
  });
119
184
 
@@ -130,6 +130,10 @@ export function createVoiceSession(
130
130
  if (disconnected) return;
131
131
  disconnected = true;
132
132
  detachAbortHandler();
133
+ if (currentStatus.type !== "ended") {
134
+ currentStatus = { type: "ended", reason: "cancelled" };
135
+ notifyEventListeners(statusCbs, currentStatus, "Voice session");
136
+ }
133
137
  try {
134
138
  controls?.disconnect();
135
139
  } finally {
@@ -165,6 +169,10 @@ export function createVoiceSession(
165
169
  if (abortSignal) {
166
170
  abortHandler = () => session.disconnect();
167
171
  abortSignal.addEventListener("abort", abortHandler, { once: true });
172
+ if (abortSignal.aborted) {
173
+ session.disconnect();
174
+ return session;
175
+ }
168
176
  }
169
177
 
170
178
  const doSetup = async () => {
package/src/internal.ts CHANGED
@@ -33,6 +33,7 @@ export {
33
33
  // Message utilities
34
34
  export { getThreadMessageText } from "./utils/text";
35
35
  export { toMessagePartStatus } from "./utils/normalizePartStatus";
36
+ export { notifyEventListeners } from "./utils/notify-event-listeners";
36
37
  export { resolveToolApprovalResponse } from "./runtime/utils/resolveToolApprovalResponse";
37
38
  export { consumeSuggestionResult } from "./adapters/suggestion";
38
39
 
@@ -59,16 +60,28 @@ export { isJSONValue, isRecord } from "./utils/json/is-json";
59
60
  // outbound part conversion lives in one place.
60
61
  export {
61
62
  dataUrlMediaType,
63
+ type FilePartSource,
62
64
  httpUrlPattern,
63
65
  isParsableUrl,
64
66
  parseDataUrl,
67
+ resolveFilePartSource,
65
68
  } from "./utils/data-url";
69
+ export { invokeUserCallback } from "./utils/invoke-user-callback";
66
70
  export { detectImageMediaType } from "./utils/image-media-type";
67
71
  export {
68
72
  resolveFileMediaType,
69
73
  resolveImageMediaType,
70
74
  toMediaWireUrl,
71
75
  } from "./utils/wire-media";
76
+ export {
77
+ createToolCallCancellationStub,
78
+ scanPendingToolCalls,
79
+ } from "./runtime/utils/pending-tool-calls";
80
+ export {
81
+ createAbortableThreadLoad,
82
+ type AbortableThreadLoadPurpose,
83
+ } from "./runtime/utils/abortable-thread-load";
84
+ export { createCloudThreadListAdapterCreateFallback } from "./react/runtimes/cloud/createCloudThreadListAdapterCreateFallback";
72
85
 
73
86
  export * from "./runtime/internal";
74
87
  export * from "./runtimes/internal";