@assistant-ui/core 0.3.17 → 0.3.19

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 (470) hide show
  1. package/dist/adapters/attachment.d.ts.map +1 -1
  2. package/dist/adapters/attachment.js +5 -4
  3. package/dist/adapters/attachment.js.map +1 -1
  4. package/dist/adapters/speech.d.ts.map +1 -1
  5. package/dist/adapters/speech.js +13 -3
  6. package/dist/adapters/speech.js.map +1 -1
  7. package/dist/adapters/thread-history.d.ts +4 -0
  8. package/dist/adapters/thread-history.d.ts.map +1 -1
  9. package/dist/index.d.ts +3 -3
  10. package/dist/index.js.map +1 -1
  11. package/dist/internal.d.ts +4 -3
  12. package/dist/internal.js +3 -2
  13. package/dist/model-context/frame/host.d.ts.map +1 -1
  14. package/dist/model-context/frame/host.js +35 -14
  15. package/dist/model-context/frame/host.js.map +1 -1
  16. package/dist/model-context/frame/provider.d.ts +2 -0
  17. package/dist/model-context/frame/provider.d.ts.map +1 -1
  18. package/dist/model-context/frame/provider.js +30 -7
  19. package/dist/model-context/frame/provider.js.map +1 -1
  20. package/dist/model-context/interactable-composer-metadata.d.ts.map +1 -1
  21. package/dist/model-context/interactable-composer-metadata.js +27 -18
  22. package/dist/model-context/interactable-composer-metadata.js.map +1 -1
  23. package/dist/model-context/registry.d.ts.map +1 -1
  24. package/dist/model-context/registry.js +3 -5
  25. package/dist/model-context/registry.js.map +1 -1
  26. package/dist/model-context/types.d.ts.map +1 -1
  27. package/dist/model-context/types.js +5 -4
  28. package/dist/model-context/types.js.map +1 -1
  29. package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
  30. package/dist/react/adapters/LocalStorageThreadListAdapter.js +45 -7
  31. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  32. package/dist/react/client/DataRenderers.d.ts.map +1 -1
  33. package/dist/react/client/DataRenderers.js +20 -15
  34. package/dist/react/client/DataRenderers.js.map +1 -1
  35. package/dist/react/client/InMemoryThreadList.d.ts.map +1 -1
  36. package/dist/react/client/InMemoryThreadList.js +62 -56
  37. package/dist/react/client/InMemoryThreadList.js.map +1 -1
  38. package/dist/react/client/Interactables.d.ts.map +1 -1
  39. package/dist/react/client/Interactables.js +35 -32
  40. package/dist/react/client/Interactables.js.map +1 -1
  41. package/dist/react/client/RemoteThreadList.d.ts +1 -0
  42. package/dist/react/client/RemoteThreadList.d.ts.map +1 -1
  43. package/dist/react/client/RemoteThreadList.js +154 -143
  44. package/dist/react/client/RemoteThreadList.js.map +1 -1
  45. package/dist/react/client/Tools.d.ts.map +1 -1
  46. package/dist/react/client/Tools.js +18 -16
  47. package/dist/react/client/Tools.js.map +1 -1
  48. package/dist/react/client/interactable-model-context.d.ts.map +1 -1
  49. package/dist/react/client/interactable-model-context.js +3 -2
  50. package/dist/react/client/interactable-model-context.js.map +1 -1
  51. package/dist/react/index.d.ts +2 -2
  52. package/dist/react/index.js +2 -2
  53. package/dist/react/interactables-legacy/Interactables.js +242 -121
  54. package/dist/react/interactables-legacy/Interactables.js.map +1 -1
  55. package/dist/react/interactables-legacy/useAssistantInteractable.d.ts.map +1 -1
  56. package/dist/react/interactables-legacy/useAssistantInteractable.js +3 -0
  57. package/dist/react/interactables-legacy/useAssistantInteractable.js.map +1 -1
  58. package/dist/react/interactables-shared/useInteractablePersistenceQueue.d.ts.map +1 -1
  59. package/dist/react/interactables-shared/useInteractablePersistenceQueue.js +11 -9
  60. package/dist/react/interactables-shared/useInteractablePersistenceQueue.js.map +1 -1
  61. package/dist/react/model-context/makeAssistantTool.d.ts +2 -2
  62. package/dist/react/model-context/makeAssistantTool.js +1 -1
  63. package/dist/react/model-context/makeAssistantTool.js.map +1 -1
  64. package/dist/react/model-context/useAssistantTool.d.ts +2 -2
  65. package/dist/react/model-context/useAssistantTool.js +1 -1
  66. package/dist/react/model-context/useAssistantTool.js.map +1 -1
  67. package/dist/react/model-context/useInteractable.d.ts.map +1 -1
  68. package/dist/react/model-context/useInteractable.js +4 -1
  69. package/dist/react/model-context/useInteractable.js.map +1 -1
  70. package/dist/react/model-context/useInteractableVersions.js +1 -1
  71. package/dist/react/model-context/useToolArgsStatus.d.ts.map +1 -1
  72. package/dist/react/model-context/useToolArgsStatus.js +2 -1
  73. package/dist/react/model-context/useToolArgsStatus.js.map +1 -1
  74. package/dist/react/primitives/message/MessageGroupedParts.d.ts +11 -2
  75. package/dist/react/primitives/message/MessageGroupedParts.d.ts.map +1 -1
  76. package/dist/react/primitives/message/MessageGroupedParts.js +3 -2
  77. package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
  78. package/dist/react/primitives/part/PartMessages.d.ts +1 -0
  79. package/dist/react/primitives/part/PartMessages.d.ts.map +1 -1
  80. package/dist/react/primitives/part/PartMessages.js +1 -0
  81. package/dist/react/primitives/part/PartMessages.js.map +1 -1
  82. package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
  83. package/dist/react/primitives/thread/ThreadMessages.js +6 -5
  84. package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
  85. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  86. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +16 -8
  87. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  88. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +5 -1
  89. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  90. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +105 -104
  91. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  92. package/dist/react/runtimes/RemoteThreadResource.d.ts +1 -0
  93. package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -1
  94. package/dist/react/runtimes/RemoteThreadResource.js +13 -11
  95. package/dist/react/runtimes/RemoteThreadResource.js.map +1 -1
  96. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +5 -24
  97. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  98. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +354 -226
  99. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  100. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +1 -0
  101. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
  102. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +22 -2
  103. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
  104. package/dist/react/runtimes/cloud/auiV0.d.ts +40 -15
  105. package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
  106. package/dist/react/runtimes/cloud/auiV0.js +62 -15
  107. package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
  108. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts +2 -1
  109. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts.map +1 -1
  110. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js +6 -1
  111. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js.map +1 -1
  112. package/dist/react/runtimes/cloud/sdkIdentity.d.ts +6 -0
  113. package/dist/react/runtimes/cloud/sdkIdentity.d.ts.map +1 -0
  114. package/dist/react/runtimes/cloud/sdkIdentity.js +9 -0
  115. package/dist/react/runtimes/cloud/sdkIdentity.js.map +1 -0
  116. package/dist/react/runtimes/external-message-converter.d.ts +12 -2
  117. package/dist/react/runtimes/external-message-converter.d.ts.map +1 -1
  118. package/dist/react/runtimes/external-message-converter.js +26 -61
  119. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  120. package/dist/react/runtimes/useExternalStoreRuntime.js +75 -46
  121. package/dist/react/runtimes/useExternalStoreRuntime.js.map +1 -1
  122. package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
  123. package/dist/react/runtimes/useRemoteThreadListRuntime.js +64 -24
  124. package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
  125. package/dist/react/utils/groupParts.d.ts +6 -1
  126. package/dist/react/utils/groupParts.d.ts.map +1 -1
  127. package/dist/react/utils/groupParts.js +6 -0
  128. package/dist/react/utils/groupParts.js.map +1 -1
  129. package/dist/react/utils/useJSONEqual.d.ts +3 -1
  130. package/dist/react/utils/useJSONEqual.d.ts.map +1 -1
  131. package/dist/react/utils/useJSONEqual.js +6 -1
  132. package/dist/react/utils/useJSONEqual.js.map +1 -1
  133. package/dist/react/utils/useJSONSchemaDependency.d.ts +7 -0
  134. package/dist/react/utils/useJSONSchemaDependency.d.ts.map +1 -0
  135. package/dist/react/utils/useJSONSchemaDependency.js +20 -0
  136. package/dist/react/utils/useJSONSchemaDependency.js.map +1 -0
  137. package/dist/runtime/api/thread-list-item-runtime.d.ts +7 -3
  138. package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
  139. package/dist/runtime/api/thread-list-item-runtime.js +2 -2
  140. package/dist/runtime/api/thread-list-item-runtime.js.map +1 -1
  141. package/dist/runtime/api/thread-list-runtime.d.ts +3 -0
  142. package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
  143. package/dist/runtime/api/thread-list-runtime.js +18 -14
  144. package/dist/runtime/api/thread-list-runtime.js.map +1 -1
  145. package/dist/runtime/api/thread-runtime.d.ts +4 -0
  146. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  147. package/dist/runtime/api/thread-runtime.js +3 -6
  148. package/dist/runtime/api/thread-runtime.js.map +1 -1
  149. package/dist/runtime/base/base-composer-runtime-core.d.ts +1 -0
  150. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  151. package/dist/runtime/base/base-composer-runtime-core.js +62 -22
  152. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  153. package/dist/runtime/base/base-thread-runtime-core.d.ts +2 -0
  154. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  155. package/dist/runtime/base/base-thread-runtime-core.js +161 -69
  156. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  157. package/dist/runtime/interfaces/composer-runtime-core.d.ts +12 -5
  158. package/dist/runtime/interfaces/composer-runtime-core.d.ts.map +1 -1
  159. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +4 -1
  160. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
  161. package/dist/runtime/interfaces/thread-runtime-core.d.ts +6 -0
  162. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  163. package/dist/runtime/queue/message-queue.d.ts +5 -0
  164. package/dist/runtime/queue/message-queue.d.ts.map +1 -1
  165. package/dist/runtime/queue/message-queue.js +61 -6
  166. package/dist/runtime/queue/message-queue.js.map +1 -1
  167. package/dist/runtime/utils/auto-status.d.ts +6 -2
  168. package/dist/runtime/utils/auto-status.d.ts.map +1 -1
  169. package/dist/runtime/utils/auto-status.js +12 -4
  170. package/dist/runtime/utils/auto-status.js.map +1 -1
  171. package/dist/runtime/utils/external-message-conversion.d.ts +16 -4
  172. package/dist/runtime/utils/external-message-conversion.d.ts.map +1 -1
  173. package/dist/runtime/utils/external-message-conversion.js +49 -13
  174. package/dist/runtime/utils/external-message-conversion.js.map +1 -1
  175. package/dist/runtime/utils/message-repository.d.ts +1 -0
  176. package/dist/runtime/utils/message-repository.d.ts.map +1 -1
  177. package/dist/runtime/utils/message-repository.js +18 -9
  178. package/dist/runtime/utils/message-repository.js.map +1 -1
  179. package/dist/runtime/utils/thread-message-like.d.ts +2 -1
  180. package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
  181. package/dist/runtime/utils/thread-message-like.js +5 -3
  182. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  183. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  184. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +21 -27
  185. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  186. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  187. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +8 -1
  188. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  189. package/dist/runtimes/internal.d.ts +3 -3
  190. package/dist/runtimes/internal.js +2 -2
  191. package/dist/runtimes/local/local-thread-runtime-core.d.ts +1 -1
  192. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  193. package/dist/runtimes/local/local-thread-runtime-core.js +4 -1
  194. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  195. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts +18 -1
  196. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts.map +1 -1
  197. package/dist/runtimes/remote-thread-list/remote-thread-state.js +130 -42
  198. package/dist/runtimes/remote-thread-list/remote-thread-state.js.map +1 -1
  199. package/dist/runtimes/remote-thread-list/title-generation.d.ts +49 -0
  200. package/dist/runtimes/remote-thread-list/title-generation.d.ts.map +1 -0
  201. package/dist/runtimes/remote-thread-list/title-generation.js +197 -0
  202. package/dist/runtimes/remote-thread-list/title-generation.js.map +1 -0
  203. package/dist/runtimes/remote-thread-list/title.d.ts +3 -1
  204. package/dist/runtimes/remote-thread-list/title.d.ts.map +1 -1
  205. package/dist/runtimes/remote-thread-list/title.js +9 -1
  206. package/dist/runtimes/remote-thread-list/title.js.map +1 -1
  207. package/dist/runtimes/remote-thread-list/types.d.ts +10 -0
  208. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  209. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
  210. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +2 -1
  211. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
  212. package/dist/store/clients/external-thread.d.ts.map +1 -1
  213. package/dist/store/clients/external-thread.js +260 -203
  214. package/dist/store/clients/external-thread.js.map +1 -1
  215. package/dist/store/clients/model-context-client.d.ts.map +1 -1
  216. package/dist/store/clients/model-context-client.js +2 -1
  217. package/dist/store/clients/model-context-client.js.map +1 -1
  218. package/dist/store/clients/single-thread-list.d.ts.map +1 -1
  219. package/dist/store/clients/single-thread-list.js +1 -0
  220. package/dist/store/clients/single-thread-list.js.map +1 -1
  221. package/dist/store/clients/suggestions.d.ts.map +1 -1
  222. package/dist/store/clients/suggestions.js +5 -4
  223. package/dist/store/clients/suggestions.js.map +1 -1
  224. package/dist/store/clients/thread-tasks.d.ts +13 -0
  225. package/dist/store/clients/thread-tasks.d.ts.map +1 -0
  226. package/dist/store/clients/thread-tasks.js +69 -0
  227. package/dist/store/clients/thread-tasks.js.map +1 -0
  228. package/dist/store/index.d.ts +3 -2
  229. package/dist/store/index.js +3 -3
  230. package/dist/store/primitive-predicates.d.ts.map +1 -1
  231. package/dist/store/primitive-predicates.js +4 -4
  232. package/dist/store/primitive-predicates.js.map +1 -1
  233. package/dist/store/runtime-clients/composer-runtime-client.d.ts +1 -0
  234. package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
  235. package/dist/store/runtime-clients/composer-runtime-client.js +97 -61
  236. package/dist/store/runtime-clients/composer-runtime-client.js.map +1 -1
  237. package/dist/store/runtime-clients/message-runtime-client.d.ts +1 -0
  238. package/dist/store/runtime-clients/message-runtime-client.d.ts.map +1 -1
  239. package/dist/store/runtime-clients/message-runtime-client.js +221 -144
  240. package/dist/store/runtime-clients/message-runtime-client.js.map +1 -1
  241. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  242. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +1 -1
  243. package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
  244. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
  245. package/dist/store/runtime-clients/thread-list-runtime-client.js +54 -52
  246. package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
  247. package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
  248. package/dist/store/runtime-clients/thread-runtime-client.js +246 -126
  249. package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
  250. package/dist/store/scope-registration.d.ts +2 -0
  251. package/dist/store/scope-registration.d.ts.map +1 -1
  252. package/dist/store/scopes/composer.d.ts +10 -2
  253. package/dist/store/scopes/composer.d.ts.map +1 -1
  254. package/dist/store/scopes/message.d.ts +30 -1
  255. package/dist/store/scopes/message.d.ts.map +1 -1
  256. package/dist/store/scopes/task.d.ts +36 -0
  257. package/dist/store/scopes/task.d.ts.map +1 -0
  258. package/dist/store/scopes/task.js +0 -0
  259. package/dist/store/scopes/thread-list-item.d.ts +2 -2
  260. package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
  261. package/dist/store/scopes/thread.d.ts +28 -0
  262. package/dist/store/scopes/thread.d.ts.map +1 -1
  263. package/dist/store/scopes/threads.d.ts +1 -0
  264. package/dist/store/scopes/threads.d.ts.map +1 -1
  265. package/dist/subscribable/subscribable.d.ts +2 -1
  266. package/dist/subscribable/subscribable.d.ts.map +1 -1
  267. package/dist/subscribable/subscribable.js +23 -15
  268. package/dist/subscribable/subscribable.js.map +1 -1
  269. package/dist/types/attachment.d.ts +2 -1
  270. package/dist/types/attachment.d.ts.map +1 -1
  271. package/dist/types/attachment.js +2 -1
  272. package/dist/types/attachment.js.map +1 -1
  273. package/dist/types/index.d.ts +2 -2
  274. package/dist/types/message.d.ts +8 -1
  275. package/dist/types/message.d.ts.map +1 -1
  276. package/dist/types/message.js.map +1 -1
  277. package/dist/utils/abortable-iterable.d.ts +19 -0
  278. package/dist/utils/abortable-iterable.d.ts.map +1 -0
  279. package/dist/utils/abortable-iterable.js +88 -0
  280. package/dist/utils/abortable-iterable.js.map +1 -0
  281. package/dist/utils/composite-context-provider.d.ts.map +1 -1
  282. package/dist/utils/composite-context-provider.js +20 -2
  283. package/dist/utils/composite-context-provider.js.map +1 -1
  284. package/dist/utils/getGroupStatus.d.ts +18 -2
  285. package/dist/utils/getGroupStatus.d.ts.map +1 -1
  286. package/dist/utils/getGroupStatus.js +32 -7
  287. package/dist/utils/getGroupStatus.js.map +1 -1
  288. package/dist/utils/record.d.ts +11 -0
  289. package/dist/utils/record.d.ts.map +1 -0
  290. package/dist/utils/record.js +12 -0
  291. package/dist/utils/record.js.map +1 -0
  292. package/dist/utils/wire-media.d.ts.map +1 -1
  293. package/dist/utils/wire-media.js +2 -2
  294. package/dist/utils/wire-media.js.map +1 -1
  295. package/package.json +11 -11
  296. package/src/adapters/attachment.test.ts +50 -1
  297. package/src/adapters/attachment.ts +7 -4
  298. package/src/adapters/speech.test.ts +236 -0
  299. package/src/adapters/speech.ts +17 -10
  300. package/src/adapters/thread-history.ts +3 -0
  301. package/src/index.ts +2 -0
  302. package/src/internal.ts +4 -0
  303. package/src/model-context/frame/host.test.ts +137 -1
  304. package/src/model-context/frame/host.ts +49 -16
  305. package/src/model-context/frame/provider.test.ts +71 -0
  306. package/src/model-context/frame/provider.ts +37 -7
  307. package/src/model-context/interactable-composer-metadata.test.ts +58 -0
  308. package/src/model-context/interactable-composer-metadata.ts +19 -13
  309. package/src/model-context/registry.test.ts +12 -0
  310. package/src/model-context/registry.ts +3 -2
  311. package/src/model-context/types.test.ts +25 -0
  312. package/src/model-context/types.ts +9 -4
  313. package/src/react/RuntimeAdapter.test.ts +34 -0
  314. package/src/react/adapters/LocalStorageThreadListAdapter.test.ts +244 -0
  315. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +104 -7
  316. package/src/react/client/DataRenderers.test.tsx +45 -0
  317. package/src/react/client/DataRenderers.ts +13 -9
  318. package/src/react/client/InMemoryThreadList.ts +1 -0
  319. package/src/react/client/Interactables.test.ts +72 -1
  320. package/src/react/client/Interactables.ts +22 -14
  321. package/src/react/client/RemoteThreadList.background.test.ts +148 -6
  322. package/src/react/client/RemoteThreadList.concurrent.test.tsx +42 -1
  323. package/src/react/client/RemoteThreadList.test.ts +386 -4
  324. package/src/react/client/RemoteThreadList.ts +181 -112
  325. package/src/react/client/Tools.ts +22 -11
  326. package/src/react/client/interactable-model-context.test.ts +44 -0
  327. package/src/react/client/interactable-model-context.ts +3 -2
  328. package/src/react/index.ts +5 -1
  329. package/src/react/interactables-legacy/Interactables.ts +16 -16
  330. package/src/react/interactables-legacy/useAssistantInteractable.test.tsx +132 -0
  331. package/src/react/interactables-legacy/useAssistantInteractable.ts +10 -1
  332. package/src/react/interactables-shared/useInteractablePersistenceQueue.ts +9 -10
  333. package/src/react/model-context/makeAssistantTool.ts +2 -2
  334. package/src/react/model-context/useAssistantTool.ts +2 -2
  335. package/src/react/model-context/useInteractable.test.tsx +177 -0
  336. package/src/react/model-context/useInteractable.ts +3 -0
  337. package/src/react/model-context/useToolArgsStatus.test.tsx +30 -0
  338. package/src/react/model-context/useToolArgsStatus.ts +2 -1
  339. package/src/react/primitive-hooks/useActionBarCopy.test.ts +0 -1
  340. package/src/react/primitive-hooks/useSuggestionTrigger.test.ts +0 -1
  341. package/src/react/primitives/message/MessageGroupedParts.test.tsx +96 -0
  342. package/src/react/primitives/message/MessageGroupedParts.tsx +15 -4
  343. package/src/react/primitives/part/PartMessages.test.tsx +104 -1
  344. package/src/react/primitives/part/PartMessages.tsx +1 -0
  345. package/src/react/primitives/thread/ThreadMessages.test.tsx +142 -0
  346. package/src/react/primitives/thread/ThreadMessages.tsx +8 -5
  347. package/src/react/providers/ReadonlyThreadProvider.test.tsx +56 -0
  348. package/src/react/runtimes/RemoteThreadListHookInstanceManager.destroy.test.tsx +172 -0
  349. package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +33 -0
  350. package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +7 -1
  351. package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +28 -5
  352. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.load-error.test.ts +132 -0
  353. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.switch-delete.test.ts +105 -0
  354. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +143 -112
  355. package/src/react/runtimes/RemoteThreadResource.test.ts +9 -0
  356. package/src/react/runtimes/RemoteThreadResource.ts +19 -12
  357. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.ts +20 -14
  358. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +703 -6
  359. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +492 -402
  360. package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.test.ts +77 -0
  361. package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +27 -1
  362. package/src/react/runtimes/cloud/auiV0.ts +160 -25
  363. package/src/react/runtimes/cloud/createCloudThreadListAdapter.test.ts +36 -0
  364. package/src/react/runtimes/cloud/createCloudThreadListAdapter.ts +8 -1
  365. package/src/react/runtimes/cloud/sdkIdentity.ts +9 -0
  366. package/src/react/runtimes/cloud/useCloudThreadListAdapter.test.tsx +18 -4
  367. package/src/react/runtimes/external-message-converter.test.ts +136 -1
  368. package/src/react/runtimes/external-message-converter.ts +39 -93
  369. package/src/react/runtimes/useExternalStoreRuntime.lifecycle.test.tsx +41 -0
  370. package/src/react/runtimes/useExternalStoreRuntime.ts +10 -4
  371. package/src/react/runtimes/useLocalRuntime.test.tsx +20 -0
  372. package/src/react/runtimes/useRemoteThreadListRuntime.load-error.test.tsx +108 -0
  373. package/src/react/runtimes/useRemoteThreadListRuntime.ts +34 -1
  374. package/src/react/utils/groupParts.ts +12 -1
  375. package/src/react/utils/useJSONEqual.ts +9 -0
  376. package/src/react/utils/useJSONSchemaDependency.ts +22 -0
  377. package/src/runtime/api/message-runtime.test.ts +75 -0
  378. package/src/runtime/api/thread-list-item-runtime.ts +10 -3
  379. package/src/runtime/api/thread-list-runtime.ts +21 -11
  380. package/src/runtime/api/thread-runtime.test.ts +136 -0
  381. package/src/runtime/api/thread-runtime.ts +10 -5
  382. package/src/runtime/base/base-composer-runtime-core.ts +105 -24
  383. package/src/runtime/base/base-thread-runtime-core.test.ts +1063 -2
  384. package/src/runtime/base/base-thread-runtime-core.ts +228 -87
  385. package/src/runtime/interfaces/composer-runtime-core.ts +10 -5
  386. package/src/runtime/interfaces/thread-list-runtime-core.ts +5 -1
  387. package/src/runtime/interfaces/thread-runtime-core.ts +6 -0
  388. package/src/runtime/queue/message-queue.ts +68 -6
  389. package/src/runtime/utils/auto-status.test.ts +112 -1
  390. package/src/runtime/utils/auto-status.ts +31 -5
  391. package/src/runtime/utils/external-message-conversion.test.ts +202 -0
  392. package/src/runtime/utils/external-message-conversion.ts +123 -32
  393. package/src/runtime/utils/message-repository.test.ts +49 -0
  394. package/src/runtime/utils/message-repository.ts +32 -20
  395. package/src/runtime/utils/thread-message-like.test.ts +52 -0
  396. package/src/runtime/utils/thread-message-like.ts +5 -1
  397. package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +18 -13
  398. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +31 -1
  399. package/src/runtimes/internal.ts +1 -0
  400. package/src/runtimes/local/local-thread-runtime-core.test.ts +21 -0
  401. package/src/runtimes/local/local-thread-runtime-core.ts +11 -1
  402. package/src/runtimes/remote-thread-list/remote-thread-state.test.ts +128 -2
  403. package/src/runtimes/remote-thread-list/remote-thread-state.ts +182 -42
  404. package/src/runtimes/remote-thread-list/title-generation.test.ts +602 -0
  405. package/src/runtimes/remote-thread-list/title-generation.ts +329 -0
  406. package/src/runtimes/remote-thread-list/title.test.ts +62 -0
  407. package/src/runtimes/remote-thread-list/title.ts +13 -0
  408. package/src/runtimes/remote-thread-list/types.ts +10 -0
  409. package/src/runtimes/tool-invocations/EDGE_CASES.md +2 -6
  410. package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +133 -0
  411. package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +10 -6
  412. package/src/store/clients/external-thread.ts +67 -4
  413. package/src/store/clients/model-context-client.ts +5 -1
  414. package/src/store/clients/single-thread-list.ts +1 -0
  415. package/src/store/clients/suggestions.test.ts +40 -0
  416. package/src/store/clients/suggestions.ts +13 -10
  417. package/src/store/clients/thread-tasks.test.ts +274 -0
  418. package/src/store/clients/thread-tasks.ts +138 -0
  419. package/src/store/index.ts +8 -0
  420. package/src/store/primitive-predicates.test.ts +48 -5
  421. package/src/store/primitive-predicates.ts +7 -2
  422. package/src/store/runtime-clients/composer-runtime-client.ts +42 -9
  423. package/src/store/runtime-clients/message-runtime-client.ts +54 -6
  424. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +4 -2
  425. package/src/store/runtime-clients/thread-list-runtime-client.ts +1 -0
  426. package/src/store/runtime-clients/thread-runtime-client.ts +89 -11
  427. package/src/store/scope-registration.ts +2 -0
  428. package/src/store/scopes/composer.ts +16 -4
  429. package/src/store/scopes/message.ts +14 -0
  430. package/src/store/scopes/task.ts +34 -0
  431. package/src/store/scopes/thread-list-item.ts +5 -2
  432. package/src/store/scopes/thread.ts +20 -0
  433. package/src/store/scopes/threads.ts +1 -0
  434. package/src/store/thread-tasks.test.tsx +209 -0
  435. package/src/subscribable/subscribable.test.ts +156 -1
  436. package/src/subscribable/subscribable.ts +25 -15
  437. package/src/tests/MessageRepository.test.ts +117 -5
  438. package/src/tests/OptimisticState-list-race.test.ts +1 -0
  439. package/src/tests/RemoteThreadListThreadListRuntimeCore-initialize-adapter-change.test.ts +38 -0
  440. package/src/tests/RemoteThreadListThreadListRuntimeCore-load-race.test.ts +47 -0
  441. package/src/tests/RemoteThreadListThreadListRuntimeCore-title-race.test.ts +89 -0
  442. package/src/tests/attachment-adapters.test.ts +14 -0
  443. package/src/tests/auiV0Encode.test.ts +300 -0
  444. package/src/tests/base-composer-runtime-core-send.test.ts +51 -0
  445. package/src/tests/base-composer-runtime-core.test.ts +353 -2
  446. package/src/tests/external-store-thread-list-runtime-core.test.ts +83 -0
  447. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +178 -18
  448. package/src/tests/external-thread-attachments.test.tsx +208 -0
  449. package/src/tests/external-thread-parity.test.tsx +57 -0
  450. package/src/tests/groupParts.test.ts +71 -0
  451. package/src/tests/message-queue.test.ts +253 -0
  452. package/src/tests/remote-thread-list-isLoading.test.ts +1 -0
  453. package/src/tests/remote-thread-list-reactive-threadId.test.ts +51 -0
  454. package/src/tests/thread-list-runtime-getLoadThreadsPromise.test.ts +1 -0
  455. package/src/tests/thread-switch-events.test.tsx +78 -0
  456. package/src/tests/tools-scope-migration.test.tsx +28 -0
  457. package/src/tests/useRemoteThreadListRuntime-controlled.test.tsx +43 -0
  458. package/src/types/attachment.ts +4 -0
  459. package/src/types/index.ts +1 -0
  460. package/src/types/message.ts +8 -0
  461. package/src/utils/abortable-iterable.test.ts +328 -0
  462. package/src/utils/abortable-iterable.ts +104 -0
  463. package/src/utils/composite-context-provider.test.ts +25 -0
  464. package/src/utils/composite-context-provider.ts +23 -2
  465. package/src/utils/getGroupStatus.test.ts +70 -4
  466. package/src/utils/getGroupStatus.ts +35 -12
  467. package/src/utils/record.test.ts +48 -0
  468. package/src/utils/record.ts +11 -0
  469. package/src/utils/wire-media.test.ts +10 -0
  470. package/src/utils/wire-media.ts +6 -2
@@ -1 +1 @@
1
- {"version":3,"file":"base-composer-runtime-core.js","names":["isCreateAttachment","Attachment","CompleteAttachment","CreateAttachment","PendingAttachment","MessageRole","AppendMessage","isMessageNotSentError","QuoteInfo","Unsubscribe","RunConfig","BaseSubscribable","AttachmentAdapter","fileMatchesAccept","AttachmentAddErrorReason","ComposerRuntimeCore","ComposerRuntimeEventCallback","ComposerRuntimeEventPayload","ComposerRuntimeEventType","DictationState","SendOptions","DictationAdapter","QueuePlacement","EMPTY_QUEUE_ITEMS","QueueItemState","generateId","notifyEventListeners","AttachmentAddOperations","drainAttachmentAdd","isAttachmentComplete","a","status","type","BaseComposerRuntimeCore","isEditing","getAttachmentAdapter","getDictationAdapter","enrichWithComposerMetadata","metadata","custom","Record","message","T","composerMetadata","attachmentAccept","accept","_attachments","attachments","setAttachments","value","_notifySubscribers","canCancel","canSend","isEmpty","text","trim","length","_text","_role","role","_runConfig","runConfig","_quote","undefined","quote","setQuote","setText","_rebaseDictation","_dictation","_dictationBaseText","_currentInterimText","inputDisabled","setRole","setRunConfig","_isSending","_removedDuringSend","Set","_sendGeneration","_attachmentAddOperations","_cancelAttachmentAdd","attachmentId","cancel","_cancelAllAttachmentAdds","cancelAll","_emptyTextAndAttachments","_onClearAttachments","adapter","pending","filter","Promise","all","map","remove","reset","clear","Object","keys","task","clearAttachments","send","options","_dictationSession","_cleanupDictation","attachmentTasks","Error","result","originalAttachments","generation","resolvedAttachments","e","allSettled","then","sentIds","id","has","finalAttachments","Omit","createdAt","Date","content","draft","sendTask","handleSend","error","_restoreUnsentDraft","catch","_notifyEventSubscribers","restoreDraft","retractDraft","attachmentsUntouched","handleCancel","queue","moveQueueItem","_queueItemId","_placement","removeQueueItem","addAttachment","fileOrAttachment","File","name","contentType","err","_safeEmitAttachmentAddError","operation","start","upsertAttachment","idx","findIndex","attachment","slice","lastAttachment","add","file","isCancelled","reason","String","finish","subscriberError","console","removeAttachment","index","candidate","Session","_dictationUnsubscribes","_dictationSessionIdCounter","_activeDictationSessionId","_isCleaningDictation","dictation","_isActiveSession","sessionId","session","startDictation","unsub","oldSession","stop","disableInputDuringDictation","listen","unsubSpeech","onSpeech","isFinal","needsSeparator","endsWith","transcript","separator","_","rest","push","unsubStart","onSpeechStart","unsubEnd","onSpeechEnd","statusInterval","setInterval","clearInterval","stopDictation","cleanup","isStaleSession","_eventSubscribers","Map","payload","event","E","subscribers","get","unstable_on","callback","wrapped","set","delete"],"sources":["../../../src/runtime/base/base-composer-runtime-core.ts"],"sourcesContent":["import {\n isCreateAttachment,\n type Attachment,\n type CompleteAttachment,\n type CreateAttachment,\n type PendingAttachment,\n} from \"../../types/attachment\";\nimport type { MessageRole, AppendMessage } from \"../../types/message\";\nimport { isMessageNotSentError } from \"../../types/error\";\nimport type { QuoteInfo } from \"../../types/quote\";\nimport type { Unsubscribe } from \"../../types/unsubscribe\";\nimport type { RunConfig } from \"../../types/message\";\nimport { BaseSubscribable } from \"../../subscribable/subscribable\";\nimport {\n type AttachmentAdapter,\n fileMatchesAccept,\n} from \"../../adapters/attachment\";\nimport type {\n AttachmentAddErrorReason,\n ComposerRuntimeCore,\n ComposerRuntimeEventCallback,\n ComposerRuntimeEventPayload,\n ComposerRuntimeEventType,\n DictationState,\n SendOptions,\n} from \"../interfaces/composer-runtime-core\";\nimport type { DictationAdapter } from \"../../adapters/speech\";\nimport type { QueuePlacement } from \"../queue/external-thread-queue-adapter\";\nimport { EMPTY_QUEUE_ITEMS, type QueueItemState } from \"../queue/queue-item\";\nimport { generateId } from \"../../utils/id\";\nimport { notifyEventListeners } from \"../../utils/notify-event-listeners\";\nimport {\n AttachmentAddOperations,\n drainAttachmentAdd,\n} from \"../utils/attachment-add-operations\";\n\nconst isAttachmentComplete = (a: Attachment): a is CompleteAttachment =>\n a.status.type === \"complete\";\n\nexport abstract class BaseComposerRuntimeCore\n extends BaseSubscribable\n implements ComposerRuntimeCore\n{\n public readonly isEditing = true;\n\n protected abstract getAttachmentAdapter(): AttachmentAdapter | undefined;\n protected abstract getDictationAdapter(): DictationAdapter | undefined;\n\n protected enrichWithComposerMetadata<\n T extends { metadata?: { custom?: Record<string, unknown> } },\n >(message: T, composerMetadata: Record<string, unknown> | undefined): T {\n if (!composerMetadata) return message;\n return {\n ...message,\n metadata: {\n ...message.metadata,\n custom: { ...message.metadata?.custom, ...composerMetadata },\n },\n } as T;\n }\n\n public get attachmentAccept(): string {\n return this.getAttachmentAdapter()?.accept ?? \"*\";\n }\n\n private _attachments: readonly Attachment[] = [];\n public get attachments() {\n return this._attachments;\n }\n\n protected setAttachments(value: readonly Attachment[]) {\n this._attachments = value;\n this._notifySubscribers();\n }\n\n public abstract get canCancel(): boolean;\n public abstract get canSend(): boolean;\n\n public get isEmpty() {\n return !this.text.trim() && !this.attachments.length;\n }\n\n private _text = \"\";\n\n get text() {\n return this._text;\n }\n\n private _role: MessageRole = \"user\";\n\n get role() {\n return this._role;\n }\n\n private _runConfig: RunConfig = {};\n\n get runConfig() {\n return this._runConfig;\n }\n\n private _quote: QuoteInfo | undefined = undefined;\n\n get quote() {\n return this._quote;\n }\n\n public setQuote(quote: QuoteInfo | undefined) {\n if (this._quote === quote) return;\n\n this._quote = quote;\n this._notifySubscribers();\n }\n\n public setText(value: string) {\n if (this._text === value) return;\n\n this._text = value;\n this._rebaseDictation(value);\n this._notifySubscribers();\n }\n\n // A live dictation session appends to the text it last saw, so any write\n // that bypasses `setText` has to move that baseline or the next transcript\n // overwrites what was just written.\n private _rebaseDictation(value: string) {\n if (!this._dictation) return;\n\n this._dictationBaseText = value;\n this._currentInterimText = \"\";\n const { status, inputDisabled } = this._dictation;\n this._dictation = inputDisabled ? { status, inputDisabled } : { status };\n }\n\n public setRole(role: MessageRole) {\n if (this._role === role) return;\n\n this._role = role;\n this._notifySubscribers();\n }\n\n public setRunConfig(runConfig: RunConfig) {\n if (this._runConfig === runConfig) return;\n\n this._runConfig = runConfig;\n this._notifySubscribers();\n }\n\n protected _isSending = false;\n private _removedDuringSend = new Set<string>();\n private _sendGeneration = 0;\n private _attachmentAddOperations = new AttachmentAddOperations();\n\n private _cancelAttachmentAdd(attachmentId: string) {\n this._attachmentAddOperations.cancel(attachmentId);\n }\n\n private _cancelAllAttachmentAdds() {\n this._attachmentAddOperations.cancelAll();\n }\n\n private _emptyTextAndAttachments() {\n this._attachments = [];\n this._text = \"\";\n this._notifySubscribers();\n }\n\n private async _onClearAttachments() {\n const adapter = this.getAttachmentAdapter();\n if (adapter) {\n const pending = this._attachments.filter((a) => !isAttachmentComplete(a));\n await Promise.all(pending.map((a) => adapter.remove(a)));\n }\n }\n\n public async reset() {\n this._cancelAllAttachmentAdds();\n\n // A send whose adapter never settles must not brick the composer; reset is\n // the escape hatch that releases the in-flight lock. Bumping the generation\n // invalidates that send entirely so a late-settling upload can neither\n // append the discarded draft nor touch a newer send's lock.\n this._sendGeneration++;\n this._isSending = false;\n this._removedDuringSend.clear();\n\n if (\n this._attachments.length === 0 &&\n this._text === \"\" &&\n this._role === \"user\" &&\n Object.keys(this._runConfig).length === 0 &&\n this._quote === undefined\n ) {\n return;\n }\n\n this._role = \"user\";\n this._runConfig = {};\n this._quote = undefined;\n\n const task = this._onClearAttachments();\n this._emptyTextAndAttachments();\n await task;\n }\n\n public async clearAttachments() {\n this._cancelAllAttachmentAdds();\n const task = this._onClearAttachments();\n this.setAttachments([]);\n\n await task;\n }\n\n public async send(options?: SendOptions) {\n if (!this.canSend || this._isSending) return;\n\n if (this._dictationSession) {\n this._dictationSession.cancel();\n this._cleanupDictation();\n }\n\n const adapter = this.getAttachmentAdapter();\n const attachmentTasks = this.attachments.map(async (a) => {\n if (isAttachmentComplete(a)) return a;\n if (!adapter) throw new Error(\"Attachments are not supported\");\n const result = await adapter.send(a);\n return result as CompleteAttachment;\n });\n\n const originalAttachments = this.attachments;\n const text = this.text;\n const quote = this._quote;\n const role = this.role;\n const runConfig = this.runConfig;\n this._quote = undefined;\n this._text = \"\";\n this._isSending = true;\n const generation = ++this._sendGeneration;\n this._notifySubscribers();\n\n let resolvedAttachments: CompleteAttachment[];\n try {\n resolvedAttachments = await Promise.all(attachmentTasks);\n } catch (e) {\n if (generation === this._sendGeneration) {\n if (!this.text.trim() && this._quote === undefined) {\n this._text = text;\n this._rebaseDictation(text);\n this._quote = quote;\n this._notifySubscribers();\n }\n // Promise.all rejects on the first failure, but sibling uploads from\n // this batch keep running; the send rejects immediately while the\n // retry lock is held until they settle, or a retry could re-send\n // attachments that are still in flight.\n void Promise.allSettled(attachmentTasks).then(() => {\n if (generation !== this._sendGeneration) return;\n this._removedDuringSend.clear();\n this._isSending = false;\n this._notifySubscribers();\n });\n }\n throw e;\n }\n\n // A reset during the upload discarded this send's draft; the settled\n // uploads must not append it or touch the lock a newer send may own.\n if (generation !== this._sendGeneration) return;\n\n // Drop by id, not wholesale: the user may have added or removed chips while\n // the upload was in flight.\n const sentIds = new Set(originalAttachments.map((a) => a.id));\n this._attachments = this._attachments.filter((a) => !sentIds.has(a.id));\n this._isSending = false;\n this._notifySubscribers();\n\n // An attachment removed mid-upload can't be cancelled, but it can still be\n // dropped from the outgoing message instead of silently being sent anyway.\n const finalAttachments = resolvedAttachments.filter(\n (a) => !this._removedDuringSend.has(a.id),\n );\n this._removedDuringSend.clear();\n\n const message: Omit<AppendMessage, \"parentId\" | \"sourceId\"> = {\n createdAt: new Date(),\n role,\n content: text ? [{ type: \"text\", text }] : [],\n attachments: finalAttachments,\n runConfig,\n metadata: { custom: { ...(quote ? { quote } : {}) } },\n };\n\n const draft = { text, quote, attachments: finalAttachments };\n let sendTask: void | Promise<void>;\n try {\n sendTask = this.handleSend(message, options);\n } catch (error) {\n this._restoreUnsentDraft(error, generation, draft);\n throw error;\n }\n if (sendTask)\n void sendTask.catch((error) => {\n this._restoreUnsentDraft(error, generation, draft);\n });\n this._notifyEventSubscribers(\"send\", {});\n }\n\n /**\n * Take a message back into the composer when it has nowhere else to live:\n * a send the runtime never dispatched, or a message a cancelled run is\n * removing from the thread. Reports whether the composer accepted it, so a\n * caller that is also removing the message can keep it instead of dropping\n * it. Refused, and left untouched, while the composer holds anything of its\n * own.\n */\n public restoreDraft(draft: {\n text: string;\n quote?: QuoteInfo | undefined;\n attachments?: readonly Attachment[] | undefined;\n }): boolean {\n if (\n this._text.trim() ||\n this._quote !== undefined ||\n this._attachments.length > 0\n )\n return false;\n\n this._text = draft.text;\n this._rebaseDictation(draft.text);\n this._quote = draft.quote;\n this._attachments = draft.attachments ?? [];\n this._notifySubscribers();\n return true;\n }\n\n /**\n * Inverse of `restoreDraft`: clears the composer while it still holds\n * exactly the given draft. A draft the user has edited since is left\n * untouched.\n */\n public retractDraft(draft: {\n text: string;\n quote?: QuoteInfo | undefined;\n attachments?: readonly Attachment[] | undefined;\n }): void {\n const attachmentsUntouched =\n draft.attachments !== undefined\n ? this._attachments === draft.attachments\n : this._attachments.length === 0;\n if (\n this._text !== draft.text ||\n this._quote !== draft.quote ||\n !attachmentsUntouched\n )\n return;\n\n this._text = \"\";\n this._rebaseDictation(\"\");\n this._quote = undefined;\n this._attachments = [];\n this._notifySubscribers();\n }\n\n // The generation check is what a reset and a later send use to invalidate a\n // draft, so of several queued drafts only the most recent one is still\n // restorable.\n private _restoreUnsentDraft(\n error: unknown,\n generation: number,\n draft: {\n text: string;\n quote: QuoteInfo | undefined;\n attachments: readonly CompleteAttachment[];\n },\n ) {\n if (!isMessageNotSentError(error)) return;\n if (generation !== this._sendGeneration) return;\n this.restoreDraft(draft);\n }\n\n public cancel() {\n this.handleCancel();\n }\n\n public get queue(): readonly QueueItemState[] {\n return EMPTY_QUEUE_ITEMS;\n }\n\n public moveQueueItem(\n _queueItemId: string,\n _placement: QueuePlacement,\n ): void {}\n public removeQueueItem(_queueItemId: string): void {}\n\n protected abstract handleSend(\n message: Omit<AppendMessage, \"parentId\" | \"sourceId\">,\n options?: SendOptions,\n ): void | Promise<void>;\n protected abstract handleCancel(): void;\n\n async addAttachment(fileOrAttachment: File | CreateAttachment) {\n if (isCreateAttachment(fileOrAttachment)) {\n const adapter = this.getAttachmentAdapter();\n if (\n adapter &&\n !fileMatchesAccept(\n {\n name: fileOrAttachment.name,\n type: fileOrAttachment.contentType ?? \"\",\n },\n adapter.accept,\n )\n ) {\n const message = `File type ${fileOrAttachment.contentType || \"unknown\"} is not accepted. Accepted types: ${adapter.accept}`;\n const err = new Error(message);\n this._safeEmitAttachmentAddError(\n \"not-accepted\",\n message,\n undefined,\n err,\n );\n throw err;\n }\n\n const a: CompleteAttachment = {\n id: fileOrAttachment.id ?? generateId(),\n type: fileOrAttachment.type ?? \"document\",\n name: fileOrAttachment.name,\n contentType: fileOrAttachment.contentType,\n content: fileOrAttachment.content,\n status: { type: \"complete\" },\n };\n this._attachments = [...this._attachments, a];\n this._notifySubscribers();\n this._notifyEventSubscribers(\"attachmentAdd\", {});\n return;\n }\n\n const adapter = this.getAttachmentAdapter();\n if (!adapter) {\n const message = \"Attachments are not supported\";\n const err = new Error(message);\n this._safeEmitAttachmentAddError(\"no-adapter\", message, undefined, err);\n throw err;\n }\n\n if (\n !fileMatchesAccept(\n { name: fileOrAttachment.name, type: fileOrAttachment.type },\n adapter.accept,\n )\n ) {\n const message = `File type ${fileOrAttachment.type || \"unknown\"} is not accepted. Accepted types: ${adapter.accept}`;\n const err = new Error(message);\n this._safeEmitAttachmentAddError(\"not-accepted\", message, undefined, err);\n throw err;\n }\n\n const operation = this._attachmentAddOperations.start();\n const upsertAttachment = (a: PendingAttachment) => {\n if (!this._attachmentAddOperations.accept(operation, a.id)) return false;\n\n const idx = this._attachments.findIndex(\n (attachment) => attachment.id === a.id,\n );\n if (idx !== -1)\n this._attachments = [\n ...this._attachments.slice(0, idx),\n a,\n ...this._attachments.slice(idx + 1),\n ];\n else {\n this._attachments = [...this._attachments, a];\n }\n\n this._notifySubscribers();\n return true;\n };\n let lastAttachment: PendingAttachment | undefined;\n try {\n await drainAttachmentAdd(\n adapter.add({ file: fileOrAttachment }),\n (attachment) => {\n lastAttachment = attachment;\n return upsertAttachment(attachment);\n },\n );\n } catch (e) {\n if (this._attachmentAddOperations.isCancelled(operation)) return;\n if (lastAttachment) {\n upsertAttachment({\n ...lastAttachment,\n status: {\n type: \"incomplete\",\n reason: \"error\",\n message: e instanceof Error ? e.message : String(e),\n },\n });\n }\n this._safeEmitAttachmentAddError(\n \"adapter-error\",\n e instanceof Error ? e.message : String(e),\n lastAttachment?.id,\n e instanceof Error ? e : undefined,\n );\n throw e;\n } finally {\n this._attachmentAddOperations.finish(operation);\n }\n\n if (this._attachmentAddOperations.isCancelled(operation)) return;\n if (\n lastAttachment?.status.type === \"incomplete\" &&\n lastAttachment.status.reason === \"error\"\n ) {\n this._safeEmitAttachmentAddError(\n \"adapter-error\",\n lastAttachment.status.message ??\n \"Attachment upload did not complete successfully.\",\n lastAttachment.id,\n );\n } else {\n this._notifyEventSubscribers(\"attachmentAdd\", {});\n }\n }\n\n private _safeEmitAttachmentAddError(\n reason: AttachmentAddErrorReason,\n message: string,\n attachmentId?: string,\n error?: Error,\n ) {\n try {\n this._notifyEventSubscribers(\"attachmentAddError\", {\n reason,\n message,\n ...(attachmentId !== undefined && { attachmentId }),\n ...(error !== undefined && { error }),\n });\n } catch (subscriberError) {\n console.error(\n \"[assistant-ui] attachmentAddError subscriber threw:\",\n subscriberError,\n );\n }\n }\n\n async removeAttachment(attachmentId: string) {\n const index = this._attachments.findIndex((a) => a.id === attachmentId);\n if (index === -1) throw new Error(\"Attachment not found\");\n const attachment = this._attachments[index]!;\n\n this._cancelAttachmentAdd(attachmentId);\n\n // A send in flight may already be uploading this attachment; the upload\n // can't be cancelled, so mark it to be dropped from the outgoing message\n // before any await gives the upload a chance to settle first.\n if (this._isSending) this._removedDuringSend.add(attachmentId);\n\n if (!isAttachmentComplete(attachment)) {\n const adapter = this.getAttachmentAdapter();\n if (!adapter) throw new Error(\"Attachments are not supported\");\n try {\n await adapter.remove(attachment);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this._attachments = this._attachments.map((candidate) =>\n candidate.id === attachmentId && !isAttachmentComplete(candidate)\n ? {\n ...candidate,\n status: { type: \"incomplete\", reason: \"error\", message },\n }\n : candidate,\n );\n this._notifySubscribers();\n throw error;\n }\n }\n this._attachments = this._attachments.filter((a) => a.id !== attachmentId);\n this._notifySubscribers();\n }\n\n private _dictation: DictationState | undefined;\n private _dictationSession: DictationAdapter.Session | undefined;\n private _dictationUnsubscribes: Unsubscribe[] = [];\n private _dictationBaseText = \"\";\n private _currentInterimText = \"\";\n private _dictationSessionIdCounter = 0;\n private _activeDictationSessionId: number | undefined;\n private _isCleaningDictation = false;\n\n public get dictation(): DictationState | undefined {\n return this._dictation;\n }\n\n private _isActiveSession(\n sessionId: number,\n session: DictationAdapter.Session,\n ): boolean {\n return (\n this._activeDictationSessionId === sessionId &&\n this._dictationSession === session\n );\n }\n\n public startDictation(): void {\n const adapter = this.getDictationAdapter();\n if (!adapter) {\n throw new Error(\"Dictation adapter not configured\");\n }\n\n if (this._dictationSession) {\n for (const unsub of this._dictationUnsubscribes) {\n unsub();\n }\n this._dictationUnsubscribes = [];\n const oldSession = this._dictationSession;\n oldSession.stop().catch(() => {});\n this._dictationSession = undefined;\n }\n\n const inputDisabled = adapter.disableInputDuringDictation ?? false;\n\n this._dictationBaseText = this._text;\n this._currentInterimText = \"\";\n\n const session = adapter.listen();\n this._dictationSession = session;\n const sessionId = ++this._dictationSessionIdCounter;\n this._activeDictationSessionId = sessionId;\n this._dictation = { status: session.status, inputDisabled };\n this._notifySubscribers();\n\n const unsubSpeech = session.onSpeech((result) => {\n if (!this._isActiveSession(sessionId, session)) return;\n const isFinal = result.isFinal !== false;\n\n const needsSeparator =\n this._dictationBaseText &&\n !this._dictationBaseText.endsWith(\" \") &&\n result.transcript;\n const separator = needsSeparator ? \" \" : \"\";\n\n if (isFinal) {\n this._dictationBaseText =\n this._dictationBaseText + separator + result.transcript;\n this._currentInterimText = \"\";\n this._text = this._dictationBaseText;\n\n if (this._dictation) {\n const { transcript: _, ...rest } = this._dictation;\n this._dictation = rest;\n }\n this._notifySubscribers();\n } else {\n this._currentInterimText = separator + result.transcript;\n this._text = this._dictationBaseText + this._currentInterimText;\n\n if (this._dictation) {\n this._dictation = {\n ...this._dictation,\n transcript: result.transcript,\n };\n }\n this._notifySubscribers();\n }\n });\n this._dictationUnsubscribes.push(unsubSpeech);\n\n const unsubStart = session.onSpeechStart(() => {\n if (!this._isActiveSession(sessionId, session)) return;\n\n this._dictation = {\n status: { type: \"running\" },\n inputDisabled,\n ...(this._dictation?.transcript && {\n transcript: this._dictation.transcript,\n }),\n };\n this._notifySubscribers();\n });\n this._dictationUnsubscribes.push(unsubStart);\n\n const unsubEnd = session.onSpeechEnd(() => {\n this._cleanupDictation({ sessionId });\n });\n this._dictationUnsubscribes.push(unsubEnd);\n\n const statusInterval = setInterval(() => {\n if (!this._isActiveSession(sessionId, session)) return;\n\n if (session.status.type === \"ended\") {\n this._cleanupDictation({ sessionId });\n }\n }, 100);\n this._dictationUnsubscribes.push(() => clearInterval(statusInterval));\n }\n\n public stopDictation(): void {\n if (!this._dictationSession) return;\n\n const session = this._dictationSession;\n const sessionId = this._activeDictationSessionId;\n const cleanup = () => this._cleanupDictation({ sessionId });\n void session.stop().then(cleanup, cleanup);\n }\n\n private _cleanupDictation(options?: { sessionId: number | undefined }): void {\n const isStaleSession =\n options?.sessionId !== undefined &&\n options.sessionId !== this._activeDictationSessionId;\n if (isStaleSession || this._isCleaningDictation) return;\n\n this._isCleaningDictation = true;\n try {\n for (const unsub of this._dictationUnsubscribes) {\n unsub();\n }\n this._dictationUnsubscribes = [];\n this._dictationSession = undefined;\n this._activeDictationSessionId = undefined;\n this._dictation = undefined;\n this._dictationBaseText = \"\";\n this._currentInterimText = \"\";\n this._notifySubscribers();\n } finally {\n this._isCleaningDictation = false;\n }\n }\n\n private _eventSubscribers = new Map<\n ComposerRuntimeEventType,\n Set<(payload?: unknown) => void>\n >();\n\n protected _notifyEventSubscribers<E extends ComposerRuntimeEventType>(\n event: E,\n payload: ComposerRuntimeEventPayload[E],\n ) {\n const subscribers = this._eventSubscribers.get(event);\n if (!subscribers) return;\n\n notifyEventListeners(subscribers, payload, `Composer runtime \"${event}\"`);\n }\n\n public unstable_on<E extends ComposerRuntimeEventType>(\n event: E,\n callback: ComposerRuntimeEventCallback<E>,\n ) {\n const wrapped = callback as (payload?: unknown) => void;\n let subscribers = this._eventSubscribers.get(event);\n if (!subscribers) {\n subscribers = new Set();\n this._eventSubscribers.set(event, subscribers);\n }\n subscribers.add(wrapped);\n\n return () => {\n this._eventSubscribers.get(event)?.delete(wrapped);\n };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"base-composer-runtime-core.js","names":["isAttachmentComplete","isCreateAttachment","Attachment","CompleteAttachment","CreateAttachment","PendingAttachment","MessageRole","AppendMessage","isMessageNotSentError","QuoteInfo","Unsubscribe","RunConfig","BaseSubscribable","AttachmentAdapter","fileMatchesAccept","AttachmentAddErrorReason","ComposerRuntimeCore","ComposerRuntimeEventCallback","ComposerRuntimeEventPayload","ComposerRuntimeEventType","DictationState","SendOptions","DictationAdapter","QueuePlacement","EMPTY_QUEUE_ITEMS","QueueItemState","generateId","notifyEventListeners","AttachmentAddOperations","drainAttachmentAdd","BaseComposerRuntimeCore","isEditing","getAttachmentAdapter","getDictationAdapter","enrichWithComposerMetadata","metadata","custom","Record","message","T","composerMetadata","attachmentAccept","accept","_attachments","attachments","setAttachments","value","_notifySubscribers","canCancel","canSend","isEmpty","text","trim","length","_text","_role","role","_runConfig","runConfig","_quote","undefined","quote","setQuote","setText","_rebaseDictation","_dictation","_dictationBaseText","_currentInterimText","status","inputDisabled","setRole","setRunConfig","_isSending","_removedDuringSend","Set","_sendGeneration","_attachmentAddOperations","_cancelAttachmentAdd","attachmentId","cancel","_cancelAllAttachmentAdds","cancelAll","_emptyTextAndAttachments","_onClearAttachments","adapter","pending","filter","a","Promise","all","map","remove","reset","clear","Object","keys","task","clearAttachments","attachment","add","id","send","options","_dictationSession","error","console","_cleanupDictation","attachmentTasks","Error","result","originalAttachments","generation","resolvedAttachments","e","allSettled","then","sentIds","has","finalAttachments","Omit","createdAt","Date","content","type","draft","sendTask","handleSend","_restoreUnsentDraft","catch","_notifyEventSubscribers","chars","restoreDraft","retractDraft","attachmentsUntouched","handleCancel","queue","moveQueueItem","_queueItemId","_placement","removeQueueItem","addAttachment","fileOrAttachment","File","name","contentType","err","_safeEmitAttachmentAddError","operation","start","upsertAttachment","idx","findIndex","slice","lastAttachment","file","isCancelled","reason","String","finish","subscriberError","removeAttachment","index","candidate","Session","_dictationUnsubscribes","_dictationSessionIdCounter","_activeDictationSessionId","_isCleaningDictation","dictation","_isActiveSession","sessionId","session","startDictation","isReplacing","oldSession","notify","_stopDictationSession","disableInputDuringDictation","listen","notifyError","unsubSpeech","onSpeech","isFinal","needsSeparator","endsWith","transcript","separator","_","rest","push","unsubStart","onSpeechStart","unsubEnd","onSpeechEnd","statusInterval","setInterval","clearInterval","stopDictation","cleanup","onSettled","stop","isStaleSession","runCleanup","unsubscribes","unsubscribe","_eventSubscribers","Map","payload","event","E","subscribers","get","unstable_on","callback","wrapped","set","delete"],"sources":["../../../src/runtime/base/base-composer-runtime-core.ts"],"sourcesContent":["import {\n isAttachmentComplete,\n isCreateAttachment,\n type Attachment,\n type CompleteAttachment,\n type CreateAttachment,\n type PendingAttachment,\n} from \"../../types/attachment\";\nimport type { MessageRole, AppendMessage } from \"../../types/message\";\nimport { isMessageNotSentError } from \"../../types/error\";\nimport type { QuoteInfo } from \"../../types/quote\";\nimport type { Unsubscribe } from \"../../types/unsubscribe\";\nimport type { RunConfig } from \"../../types/message\";\nimport { BaseSubscribable } from \"../../subscribable/subscribable\";\nimport {\n type AttachmentAdapter,\n fileMatchesAccept,\n} from \"../../adapters/attachment\";\nimport type {\n AttachmentAddErrorReason,\n ComposerRuntimeCore,\n ComposerRuntimeEventCallback,\n ComposerRuntimeEventPayload,\n ComposerRuntimeEventType,\n DictationState,\n SendOptions,\n} from \"../interfaces/composer-runtime-core\";\nimport type { DictationAdapter } from \"../../adapters/speech\";\nimport type { QueuePlacement } from \"../queue/external-thread-queue-adapter\";\nimport { EMPTY_QUEUE_ITEMS, type QueueItemState } from \"../queue/queue-item\";\nimport { generateId } from \"../../utils/id\";\nimport { notifyEventListeners } from \"../../utils/notify-event-listeners\";\nimport {\n AttachmentAddOperations,\n drainAttachmentAdd,\n} from \"../utils/attachment-add-operations\";\n\nexport abstract class BaseComposerRuntimeCore\n extends BaseSubscribable\n implements ComposerRuntimeCore\n{\n public readonly isEditing = true;\n\n protected abstract getAttachmentAdapter(): AttachmentAdapter | undefined;\n protected abstract getDictationAdapter(): DictationAdapter | undefined;\n\n protected enrichWithComposerMetadata<\n T extends { metadata?: { custom?: Record<string, unknown> } },\n >(message: T, composerMetadata: Record<string, unknown> | undefined): T {\n if (!composerMetadata) return message;\n return {\n ...message,\n metadata: {\n ...message.metadata,\n custom: { ...message.metadata?.custom, ...composerMetadata },\n },\n } as T;\n }\n\n public get attachmentAccept(): string {\n return this.getAttachmentAdapter()?.accept ?? \"*\";\n }\n\n private _attachments: readonly Attachment[] = [];\n public get attachments() {\n return this._attachments;\n }\n\n protected setAttachments(value: readonly Attachment[]) {\n this._attachments = value;\n this._notifySubscribers();\n }\n\n public abstract get canCancel(): boolean;\n public abstract get canSend(): boolean;\n\n public get isEmpty() {\n return !this.text.trim() && !this.attachments.length;\n }\n\n private _text = \"\";\n\n get text() {\n return this._text;\n }\n\n private _role: MessageRole = \"user\";\n\n get role() {\n return this._role;\n }\n\n private _runConfig: RunConfig = {};\n\n get runConfig() {\n return this._runConfig;\n }\n\n private _quote: QuoteInfo | undefined = undefined;\n\n get quote() {\n return this._quote;\n }\n\n public setQuote(quote: QuoteInfo | undefined) {\n if (this._quote === quote) return;\n\n this._quote = quote;\n this._notifySubscribers();\n }\n\n public setText(value: string) {\n if (this._text === value) return;\n\n this._text = value;\n this._rebaseDictation(value);\n this._notifySubscribers();\n }\n\n // A live dictation session appends to the text it last saw, so any write\n // that bypasses `setText` has to move that baseline or the next transcript\n // overwrites what was just written.\n private _rebaseDictation(value: string) {\n if (!this._dictation) return;\n\n this._dictationBaseText = value;\n this._currentInterimText = \"\";\n const { status, inputDisabled } = this._dictation;\n this._dictation = inputDisabled ? { status, inputDisabled } : { status };\n }\n\n public setRole(role: MessageRole) {\n if (this._role === role) return;\n\n this._role = role;\n this._notifySubscribers();\n }\n\n public setRunConfig(runConfig: RunConfig) {\n if (this._runConfig === runConfig) return;\n\n this._runConfig = runConfig;\n this._notifySubscribers();\n }\n\n protected _isSending = false;\n private _removedDuringSend = new Set<string>();\n private _sendGeneration = 0;\n private _attachmentAddOperations = new AttachmentAddOperations();\n\n private _cancelAttachmentAdd(attachmentId: string) {\n this._attachmentAddOperations.cancel(attachmentId);\n }\n\n private _cancelAllAttachmentAdds() {\n this._attachmentAddOperations.cancelAll();\n }\n\n private _emptyTextAndAttachments() {\n this._attachments = [];\n this._text = \"\";\n this._rebaseDictation(\"\");\n this._notifySubscribers();\n }\n\n private async _onClearAttachments() {\n const adapter = this.getAttachmentAdapter();\n if (adapter) {\n const pending = this._attachments.filter((a) => !isAttachmentComplete(a));\n await Promise.all(pending.map(async (a) => adapter.remove(a)));\n }\n }\n\n public async reset() {\n this._cancelAllAttachmentAdds();\n\n // A send whose adapter never settles must not brick the composer; reset is\n // the escape hatch that releases the in-flight lock. Bumping the generation\n // invalidates that send entirely so a late-settling upload can neither\n // append the discarded draft nor touch a newer send's lock.\n this._sendGeneration++;\n this._isSending = false;\n this._removedDuringSend.clear();\n\n if (\n this._attachments.length === 0 &&\n this._text === \"\" &&\n this._role === \"user\" &&\n Object.keys(this._runConfig).length === 0 &&\n this._quote === undefined\n ) {\n return;\n }\n\n this._role = \"user\";\n this._runConfig = {};\n this._quote = undefined;\n\n const task = this._onClearAttachments();\n this._emptyTextAndAttachments();\n await task;\n }\n\n public async clearAttachments() {\n this._cancelAllAttachmentAdds();\n if (this._isSending) {\n for (const attachment of this._attachments)\n this._removedDuringSend.add(attachment.id);\n }\n const task = this._onClearAttachments();\n this.setAttachments([]);\n\n await task;\n }\n\n public async send(options?: SendOptions) {\n if (!this.canSend || this._isSending) return;\n\n if (this._dictationSession) {\n try {\n this._dictationSession.cancel();\n } catch (error) {\n console.error(\"[assistant-ui] Dictation session cancel threw\", error);\n } finally {\n this._cleanupDictation();\n }\n }\n\n const adapter = this.getAttachmentAdapter();\n const attachmentTasks = this.attachments.map(async (a) => {\n if (isAttachmentComplete(a)) return a;\n if (!adapter) throw new Error(\"Attachments are not supported\");\n const result = await adapter.send(a);\n return result as CompleteAttachment;\n });\n\n const originalAttachments = this.attachments;\n const text = this.text;\n const quote = this._quote;\n const role = this.role;\n const runConfig = this.runConfig;\n this._quote = undefined;\n this._text = \"\";\n this._isSending = true;\n const generation = ++this._sendGeneration;\n this._notifySubscribers();\n\n let resolvedAttachments: CompleteAttachment[];\n try {\n resolvedAttachments = await Promise.all(attachmentTasks);\n } catch (e) {\n if (generation === this._sendGeneration) {\n if (!this.text.trim() && this._quote === undefined) {\n this._text = text;\n this._rebaseDictation(text);\n this._quote = quote;\n this._notifySubscribers();\n }\n // Promise.all rejects on the first failure, but sibling uploads from\n // this batch keep running; the send rejects immediately while the\n // retry lock is held until they settle, or a retry could re-send\n // attachments that are still in flight.\n void Promise.allSettled(attachmentTasks).then(() => {\n if (generation !== this._sendGeneration) return;\n this._removedDuringSend.clear();\n this._isSending = false;\n this._notifySubscribers();\n });\n }\n throw e;\n }\n\n // A reset during the upload discarded this send's draft; the settled\n // uploads must not append it or touch the lock a newer send may own.\n if (generation !== this._sendGeneration) return;\n\n // Drop by id, not wholesale: the user may have added or removed chips while\n // the upload was in flight.\n const sentIds = new Set(originalAttachments.map((a) => a.id));\n this._attachments = this._attachments.filter((a) => !sentIds.has(a.id));\n this._isSending = false;\n this._notifySubscribers();\n\n // An attachment removed mid-upload can't be cancelled, but it can still be\n // dropped from the outgoing message instead of silently being sent anyway.\n const finalAttachments = resolvedAttachments.filter(\n (a) => !this._removedDuringSend.has(a.id),\n );\n this._removedDuringSend.clear();\n\n const message: Omit<AppendMessage, \"parentId\" | \"sourceId\"> = {\n createdAt: new Date(),\n role,\n content: text ? [{ type: \"text\", text }] : [],\n attachments: finalAttachments,\n runConfig,\n metadata: { custom: { ...(quote ? { quote } : {}) } },\n };\n\n const draft = { text, quote, attachments: finalAttachments };\n let sendTask: void | Promise<void>;\n try {\n sendTask = this.handleSend(message, options);\n } catch (error) {\n this._restoreUnsentDraft(error, generation, draft);\n throw error;\n }\n if (sendTask)\n void sendTask.catch((error) => {\n this._restoreUnsentDraft(error, generation, draft);\n });\n this._notifyEventSubscribers(\"send\", {\n chars: text.length,\n attachments: finalAttachments.length,\n });\n }\n\n /**\n * Take a message back into the composer when it has nowhere else to live:\n * a send the runtime never dispatched, or a message a cancelled run is\n * removing from the thread. Reports whether the composer accepted it, so a\n * caller that is also removing the message can keep it instead of dropping\n * it. Refused, and left untouched, while the composer holds anything of its\n * own.\n */\n public restoreDraft(draft: {\n text: string;\n quote?: QuoteInfo | undefined;\n attachments?: readonly Attachment[] | undefined;\n }): boolean {\n if (\n this._text.trim() ||\n this._quote !== undefined ||\n this._attachments.length > 0\n )\n return false;\n\n this._text = draft.text;\n this._rebaseDictation(draft.text);\n this._quote = draft.quote;\n this._attachments = draft.attachments ?? [];\n this._notifySubscribers();\n return true;\n }\n\n /**\n * Inverse of `restoreDraft`: clears the composer while it still holds\n * exactly the given draft. A draft the user has edited since is left\n * untouched.\n */\n public retractDraft(draft: {\n text: string;\n quote?: QuoteInfo | undefined;\n attachments?: readonly Attachment[] | undefined;\n }): void {\n const attachmentsUntouched =\n draft.attachments !== undefined\n ? this._attachments === draft.attachments\n : this._attachments.length === 0;\n if (\n this._text !== draft.text ||\n this._quote !== draft.quote ||\n !attachmentsUntouched\n )\n return;\n\n this._text = \"\";\n this._rebaseDictation(\"\");\n this._quote = undefined;\n this._attachments = [];\n this._notifySubscribers();\n }\n\n // The generation check is what a reset and a later send use to invalidate a\n // draft, so of several queued drafts only the most recent one is still\n // restorable.\n private _restoreUnsentDraft(\n error: unknown,\n generation: number,\n draft: {\n text: string;\n quote: QuoteInfo | undefined;\n attachments: readonly CompleteAttachment[];\n },\n ) {\n if (!isMessageNotSentError(error)) return;\n if (generation !== this._sendGeneration) return;\n this.restoreDraft(draft);\n }\n\n public cancel() {\n this.handleCancel();\n }\n\n public get queue(): readonly QueueItemState[] {\n return EMPTY_QUEUE_ITEMS;\n }\n\n public moveQueueItem(\n _queueItemId: string,\n _placement: QueuePlacement,\n ): void {}\n public removeQueueItem(_queueItemId: string): void {}\n\n protected abstract handleSend(\n message: Omit<AppendMessage, \"parentId\" | \"sourceId\">,\n options?: SendOptions,\n ): void | Promise<void>;\n protected abstract handleCancel(): void;\n\n async addAttachment(fileOrAttachment: File | CreateAttachment) {\n if (isCreateAttachment(fileOrAttachment)) {\n const adapter = this.getAttachmentAdapter();\n if (\n adapter &&\n !fileMatchesAccept(\n {\n name: fileOrAttachment.name,\n type: fileOrAttachment.contentType ?? \"\",\n },\n adapter.accept,\n )\n ) {\n const message = `File type ${fileOrAttachment.contentType || \"unknown\"} is not accepted. Accepted types: ${adapter.accept}`;\n const err = new Error(message);\n this._safeEmitAttachmentAddError(\n \"not-accepted\",\n message,\n undefined,\n err,\n fileOrAttachment.contentType,\n );\n throw err;\n }\n\n const a: CompleteAttachment = {\n id: fileOrAttachment.id ?? generateId(),\n type: fileOrAttachment.type ?? \"document\",\n name: fileOrAttachment.name,\n contentType: fileOrAttachment.contentType,\n content: fileOrAttachment.content,\n status: { type: \"complete\" },\n };\n this._attachments = [...this._attachments, a];\n this._notifySubscribers();\n this._notifyEventSubscribers(\"attachmentAdd\", {\n ...(a.contentType ? { contentType: a.contentType } : undefined),\n });\n return;\n }\n\n const adapter = this.getAttachmentAdapter();\n if (!adapter) {\n const message = \"Attachments are not supported\";\n const err = new Error(message);\n this._safeEmitAttachmentAddError(\n \"no-adapter\",\n message,\n undefined,\n err,\n fileOrAttachment.type,\n );\n throw err;\n }\n\n if (\n !fileMatchesAccept(\n { name: fileOrAttachment.name, type: fileOrAttachment.type },\n adapter.accept,\n )\n ) {\n const message = `File type ${fileOrAttachment.type || \"unknown\"} is not accepted. Accepted types: ${adapter.accept}`;\n const err = new Error(message);\n this._safeEmitAttachmentAddError(\n \"not-accepted\",\n message,\n undefined,\n err,\n fileOrAttachment.type,\n );\n throw err;\n }\n\n const operation = this._attachmentAddOperations.start();\n const upsertAttachment = (a: PendingAttachment) => {\n if (!this._attachmentAddOperations.accept(operation, a.id)) return false;\n\n const idx = this._attachments.findIndex(\n (attachment) => attachment.id === a.id,\n );\n if (idx !== -1)\n this._attachments = [\n ...this._attachments.slice(0, idx),\n a,\n ...this._attachments.slice(idx + 1),\n ];\n else {\n this._attachments = [...this._attachments, a];\n }\n\n this._notifySubscribers();\n return true;\n };\n let lastAttachment: PendingAttachment | undefined;\n try {\n await drainAttachmentAdd(\n adapter.add({ file: fileOrAttachment }),\n (attachment) => {\n lastAttachment = attachment;\n return upsertAttachment(attachment);\n },\n );\n } catch (e) {\n if (this._attachmentAddOperations.isCancelled(operation)) return;\n if (lastAttachment) {\n upsertAttachment({\n ...lastAttachment,\n status: {\n type: \"incomplete\",\n reason: \"error\",\n message: e instanceof Error ? e.message : String(e),\n },\n });\n }\n this._safeEmitAttachmentAddError(\n \"adapter-error\",\n e instanceof Error ? e.message : String(e),\n lastAttachment?.id,\n e instanceof Error ? e : undefined,\n lastAttachment?.contentType || fileOrAttachment.type,\n );\n throw e;\n } finally {\n this._attachmentAddOperations.finish(operation);\n }\n\n if (this._attachmentAddOperations.isCancelled(operation)) return;\n if (\n lastAttachment?.status.type === \"incomplete\" &&\n lastAttachment.status.reason === \"error\"\n ) {\n this._safeEmitAttachmentAddError(\n \"adapter-error\",\n lastAttachment.status.message ??\n \"Attachment upload did not complete successfully.\",\n lastAttachment.id,\n undefined,\n lastAttachment.contentType || fileOrAttachment.type,\n );\n } else {\n this._notifyEventSubscribers(\"attachmentAdd\", {\n ...(lastAttachment?.contentType\n ? { contentType: lastAttachment.contentType }\n : fileOrAttachment.type\n ? { contentType: fileOrAttachment.type }\n : undefined),\n });\n }\n }\n\n private _safeEmitAttachmentAddError(\n reason: AttachmentAddErrorReason,\n message: string,\n attachmentId?: string,\n error?: Error,\n contentType?: string,\n ) {\n try {\n this._notifyEventSubscribers(\"attachmentAddError\", {\n reason,\n message,\n ...(attachmentId !== undefined && { attachmentId }),\n ...(error !== undefined && { error }),\n ...(contentType ? { contentType } : undefined),\n });\n } catch (subscriberError) {\n console.error(\n \"[assistant-ui] attachmentAddError subscriber threw:\",\n subscriberError,\n );\n }\n }\n\n async removeAttachment(attachmentId: string) {\n const index = this._attachments.findIndex((a) => a.id === attachmentId);\n if (index === -1) throw new Error(\"Attachment not found\");\n const attachment = this._attachments[index]!;\n\n this._cancelAttachmentAdd(attachmentId);\n\n // A send in flight may already be uploading this attachment; the upload\n // can't be cancelled, so mark it to be dropped from the outgoing message\n // before any await gives the upload a chance to settle first.\n if (this._isSending) this._removedDuringSend.add(attachmentId);\n\n if (!isAttachmentComplete(attachment)) {\n const adapter = this.getAttachmentAdapter();\n if (!adapter) throw new Error(\"Attachments are not supported\");\n try {\n await adapter.remove(attachment);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this._attachments = this._attachments.map((candidate) =>\n candidate.id === attachmentId && !isAttachmentComplete(candidate)\n ? {\n ...candidate,\n status: { type: \"incomplete\", reason: \"error\", message },\n }\n : candidate,\n );\n this._notifySubscribers();\n throw error;\n }\n }\n this._attachments = this._attachments.filter((a) => a.id !== attachmentId);\n this._notifySubscribers();\n }\n\n private _dictation: DictationState | undefined;\n private _dictationSession: DictationAdapter.Session | undefined;\n private _dictationUnsubscribes: Unsubscribe[] = [];\n private _dictationBaseText = \"\";\n private _currentInterimText = \"\";\n private _dictationSessionIdCounter = 0;\n private _activeDictationSessionId: number | undefined;\n private _isCleaningDictation = false;\n\n public get dictation(): DictationState | undefined {\n return this._dictation;\n }\n\n private _isActiveSession(\n sessionId: number,\n session: DictationAdapter.Session,\n ): boolean {\n return (\n this._activeDictationSessionId === sessionId &&\n this._dictationSession === session\n );\n }\n\n public startDictation(): void {\n const adapter = this.getDictationAdapter();\n if (!adapter) {\n throw new Error(\"Dictation adapter not configured\");\n }\n\n const isReplacing = this._dictationSession !== undefined;\n if (this._dictationSession) {\n const oldSession = this._dictationSession;\n this._cleanupDictation({ notify: false });\n this._stopDictationSession(oldSession);\n }\n\n const inputDisabled = adapter.disableInputDuringDictation ?? false;\n\n this._dictationBaseText = this._text;\n this._currentInterimText = \"\";\n\n let session: DictationAdapter.Session;\n try {\n session = adapter.listen();\n } catch (error) {\n if (isReplacing) {\n try {\n this._notifySubscribers();\n } catch (notifyError) {\n console.error(\n \"[assistant-ui] Dictation replacement rollback notification threw\",\n notifyError,\n );\n }\n }\n throw error;\n }\n this._dictationSession = session;\n const sessionId = ++this._dictationSessionIdCounter;\n this._activeDictationSessionId = sessionId;\n this._dictation = { status: session.status, inputDisabled };\n this._notifySubscribers();\n\n const unsubSpeech = session.onSpeech((result) => {\n if (!this._isActiveSession(sessionId, session)) return;\n const isFinal = result.isFinal !== false;\n\n const needsSeparator =\n this._dictationBaseText &&\n !this._dictationBaseText.endsWith(\" \") &&\n result.transcript;\n const separator = needsSeparator ? \" \" : \"\";\n\n if (isFinal) {\n this._dictationBaseText =\n this._dictationBaseText + separator + result.transcript;\n this._currentInterimText = \"\";\n this._text = this._dictationBaseText;\n\n if (this._dictation) {\n const { transcript: _, ...rest } = this._dictation;\n this._dictation = rest;\n }\n this._notifySubscribers();\n } else {\n this._currentInterimText = separator + result.transcript;\n this._text = this._dictationBaseText + this._currentInterimText;\n\n if (this._dictation) {\n this._dictation = {\n ...this._dictation,\n transcript: result.transcript,\n };\n }\n this._notifySubscribers();\n }\n });\n this._dictationUnsubscribes.push(unsubSpeech);\n\n const unsubStart = session.onSpeechStart(() => {\n if (!this._isActiveSession(sessionId, session)) return;\n\n this._dictation = {\n status: { type: \"running\" },\n inputDisabled,\n ...(this._dictation?.transcript && {\n transcript: this._dictation.transcript,\n }),\n };\n this._notifySubscribers();\n });\n this._dictationUnsubscribes.push(unsubStart);\n\n const unsubEnd = session.onSpeechEnd(() => {\n this._cleanupDictation({ sessionId });\n });\n this._dictationUnsubscribes.push(unsubEnd);\n\n const statusInterval = setInterval(() => {\n if (!this._isActiveSession(sessionId, session)) return;\n\n if (session.status.type === \"ended\") {\n this._cleanupDictation({ sessionId });\n }\n }, 100);\n this._dictationUnsubscribes.push(() => clearInterval(statusInterval));\n }\n\n public stopDictation(): void {\n if (!this._dictationSession) return;\n\n const session = this._dictationSession;\n const sessionId = this._activeDictationSessionId;\n const cleanup = () => this._cleanupDictation({ sessionId });\n this._stopDictationSession(session, cleanup);\n }\n\n private _stopDictationSession(\n session: DictationAdapter.Session,\n onSettled: () => void = () => {},\n ): void {\n let task: Promise<void>;\n try {\n task = session.stop();\n } catch (error) {\n console.error(\"[assistant-ui] Dictation session stop threw\", error);\n onSettled();\n return;\n }\n\n void task.then(onSettled, (error) => {\n console.error(\"[assistant-ui] Dictation session stop rejected\", error);\n onSettled();\n });\n }\n\n private _cleanupDictation(options?: {\n sessionId?: number | undefined;\n notify?: boolean | undefined;\n }): void {\n const isStaleSession =\n options?.sessionId !== undefined &&\n options.sessionId !== this._activeDictationSessionId;\n if (isStaleSession || this._isCleaningDictation) return;\n\n this._isCleaningDictation = true;\n const runCleanup = (cleanup: () => void) => {\n try {\n cleanup();\n } catch (error) {\n console.error(\"[assistant-ui] Dictation cleanup threw\", error);\n }\n };\n\n try {\n const unsubscribes = this._dictationUnsubscribes;\n this._dictationUnsubscribes = [];\n this._dictationSession = undefined;\n this._activeDictationSessionId = undefined;\n this._dictation = undefined;\n this._dictationBaseText = \"\";\n this._currentInterimText = \"\";\n\n for (const unsubscribe of unsubscribes) runCleanup(unsubscribe);\n if (options?.notify !== false) {\n runCleanup(() => this._notifySubscribers());\n }\n } finally {\n this._isCleaningDictation = false;\n }\n }\n\n private _eventSubscribers = new Map<\n ComposerRuntimeEventType,\n Set<(payload?: unknown) => void>\n >();\n\n protected _notifyEventSubscribers<E extends ComposerRuntimeEventType>(\n event: E,\n payload: ComposerRuntimeEventPayload[E],\n ) {\n const subscribers = this._eventSubscribers.get(event);\n if (!subscribers) return;\n\n notifyEventListeners(subscribers, payload, `Composer runtime \"${event}\"`);\n }\n\n public unstable_on<E extends ComposerRuntimeEventType>(\n event: E,\n callback: ComposerRuntimeEventCallback<E>,\n ) {\n const wrapped = callback as (payload?: unknown) => void;\n let subscribers = this._eventSubscribers.get(event);\n if (!subscribers) {\n subscribers = new Set();\n this._eventSubscribers.set(event, subscribers);\n }\n subscribers.add(wrapped);\n\n return () => {\n this._eventSubscribers.get(event)?.delete(wrapped);\n };\n }\n}\n"],"mappings":"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"}
@@ -69,6 +69,7 @@ declare abstract class BaseThreadRuntimeCore extends BaseSubscribable implements
69
69
  protected enrichAppendMetadata(message: AppendMessage, anchorId?: string | null): AppendMessage;
70
70
  private _editComposers;
71
71
  getEditComposer(messageId: string): DefaultEditComposerRuntimeCore | undefined;
72
+ protected _isVoiceMessage(messageId: string | null): boolean;
72
73
  beginEdit(messageId: string): void;
73
74
  getMessageById(messageId: string): {
74
75
  parentId: string | null;
@@ -78,6 +79,7 @@ declare abstract class BaseThreadRuntimeCore extends BaseSubscribable implements
78
79
  getBranches(messageId: string): string[];
79
80
  switchToBranch(branchId: string): void;
80
81
  _notifyEventSubscribers<E extends ThreadRuntimeEventType>(event: E, payload: ThreadRuntimeEventPayload[E]): void;
82
+ protected _notifyToolApprovalAnswered(messageId: string, toolCallId: string, toolName: string, approved: boolean): void;
81
83
  submitFeedback({ messageId, type }: SubmitFeedbackOptions): void;
82
84
  private _stopSpeaking;
83
85
  speech: SpeechState | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"base-thread-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/base/base-thread-runtime-core.ts"],"mappings":";;;;;;;;;;;;;;;KAwCK;EACH,SAAS;EACT,WAAW;EACX,cAAc;EACd,QAAQ;;uBAGY,8BACZ,4BACG;UAEH;YAEE,YAAU;eACA,YAAY;eACZ;eACA;eACA;eACA,wBAAwB;eACxB;eAEA,gBAAgB;WACpB,OAAO,SAAS;WAChB,cAAc,2BAA2B;WACzC,SAAS,QAAQ;WACjB,UAAU,QAAQ;WAClB,cAAc,SAAS;WACvB,eAAe,SAAS;WACxB,sBACd,SAAS,+BACR;WACa;WACA;WACA,oBAAoB;WACpB;YAEN,gBAAgB;YAChB;UACF;UACA;UACA;YAEE;YAKA,6BAA6B;MAI5B,qBAAqB;MAgBrB,sEAAK,sDAAA;WAWA,UAAQ;mBAEP;EAEL,YAAA,kBAAkB;EAKvB,mBALuB;;;;;;;;;;;;;;YAsBpB,qBACR,SAAS,eACT,2BACC;UAmBK;EACD,gBAAgB,oBAAiB;EAGjC,UAAU;EAeV,eAAe;;;;;EAsBf,YAAY;EAOZ,eAAe;EAKf,wBAAwB,UAAU,wBACvC,OAAO,GACP,SAAS,0BAA0B;EAQ9B,iBAAiB,WAAW,QAAQ;UAqBnC;EACD,QAAQ;EAER,MAAM;EA8BN;UAMC;UACA;EACD,OAAO;UAEN;UACA;EAED;EAEA,uBAAwB,yBAAuB;EAK/C;UAmEC;UAEA;UA8DA;EAaD;EAmBA;EAUA;YAUG;EAOH,UAAM;EAIN,OAAO,MAAM;EAOb,MAAM,2BAA2B;UAIhC;EAKD,YAAY,UAAU,wBAC3B,OAAO,GACP,UAAU,2BAA2B,KAAE"}
1
+ {"version":3,"file":"base-thread-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/base/base-thread-runtime-core.ts"],"mappings":";;;;;;;;;;;;;;;KA2CK;EACH,SAAS;EACT,WAAW;EACX,cAAc;EACd,QAAQ;;uBAGY,8BACZ,4BACG;UAEH;YAEE,YAAU;eACA,YAAY;eACZ;eACA;eACA;eACA,wBAAwB;eACxB;eAEA,gBAAgB;WACpB,OAAO,SAAS;WAChB,cAAc,2BAA2B;WACzC,SAAS,QAAQ;WACjB,UAAU,QAAQ;WAClB,cAAc,SAAS;WACvB,eAAe,SAAS;WACxB,sBACd,SAAS,+BACR;WACa;WACA;WACA,oBAAoB;WACpB;YAEN,gBAAgB;YAChB;UACF;UACA;UACA;YAEE;YAKA,6BAA6B;MAI5B,qBAAqB;MAgBrB,sEAAK,sDAAA;WAWA,UAAQ;mBAEP;EAEL,YAAA,kBAAkB;EAKvB,mBALuB;;;;;;;;;;;;;;YAsBpB,qBACR,SAAS,eACT,2BACC;UAmBK;EACD,gBAAgB,oBAAiB;YAG9B,gBAAgB;EAMnB,UAAU;EAkBV,eAAe;;;;;EAsBf,YAAY;EAOZ,eAAe;EAKf,wBAAwB,UAAU,wBACvC,OAAO,GACP,SAAS,0BAA0B;YAQ3B,4BACR,mBACA,oBACA,kBACA;EAUK,iBAAiB,WAAW,QAAQ;UAkCnC;EACD,QAAQ;EAER,MAAM;EA2EN;UAKC;UACA;EACD,OAAO;UAEN;UACA;EAED;EAEA,uBAAwB,yBAAuB;EAK/C;UA+GC;UAEA;UAiEA;EAaD;EA8BA;EAUA;YAUG;EAOH,UAAM;EAIN,OAAO,MAAM;EAOb,MAAM,2BAA2B;UAIhC;EAKD,YAAY,UAAU,wBAC3B,OAAO,GACP,UAAU,2BAA2B,KAAE"}
@@ -1,6 +1,6 @@
1
1
  import { gateInteractableComposerMetadata } from "../../model-context/interactable-composer-metadata.js";
2
2
  import { notifyEventListeners } from "../../utils/notify-event-listeners.js";
3
- import { BaseSubscribable } from "../../subscribable/subscribable.js";
3
+ import { BaseSubscribable, notifySubscribers } from "../../subscribable/subscribable.js";
4
4
  import { generateId } from "../../utils/id.js";
5
5
  import { getThreadMessageText } from "../../utils/text.js";
6
6
  import { ExportedMessageRepository, MessageRepository } from "../utils/message-repository.js";
@@ -80,7 +80,11 @@ var BaseThreadRuntimeCore = class extends BaseSubscribable {
80
80
  getEditComposer(messageId) {
81
81
  return this._editComposers.get(messageId);
82
82
  }
83
+ _isVoiceMessage(messageId) {
84
+ return messageId !== null && this._voiceMessages.some((m) => m.id === messageId);
85
+ }
83
86
  beginEdit(messageId) {
87
+ if (this._isVoiceMessage(messageId)) throw new Error("Voice transcript messages cannot be edited");
84
88
  if (this._editComposers.has(messageId)) throw new Error("Edit already in progress");
85
89
  this._editComposers.set(messageId, new DefaultEditComposerRuntimeCore(this, () => this._editComposers.delete(messageId), this.repository.getMessage(messageId)));
86
90
  this._notifySubscribers();
@@ -112,10 +116,20 @@ var BaseThreadRuntimeCore = class extends BaseSubscribable {
112
116
  if (!subscribers) return;
113
117
  notifyEventListeners(subscribers, payload, `Thread runtime "${event}"`);
114
118
  }
119
+ _notifyToolApprovalAnswered(messageId, toolCallId, toolName, approved) {
120
+ this._notifyEventSubscribers("toolApprovalAnswered", {
121
+ messageId,
122
+ toolCallId,
123
+ toolName,
124
+ approved
125
+ });
126
+ }
115
127
  submitFeedback({ messageId, type }) {
116
128
  const adapter = this.adapters?.feedback;
117
129
  if (!adapter) throw new Error("Feedback adapter not configured");
118
- const { message, parentId } = this.repository.getMessage(messageId);
130
+ const entry = this.getMessageById(messageId);
131
+ if (!entry) throw new Error(`Message not found: ${messageId}`);
132
+ const { message, parentId } = entry;
119
133
  adapter.submit({
120
134
  message,
121
135
  type
@@ -128,7 +142,13 @@ var BaseThreadRuntimeCore = class extends BaseSubscribable {
128
142
  submittedFeedback: { type }
129
143
  }
130
144
  };
131
- this.repository.addOrUpdateMessage(parentId, updatedMessage);
145
+ const voiceIdx = this._voiceMessages.findIndex((voiceMessage) => voiceMessage.id === messageId);
146
+ if (voiceIdx === -1) this.repository.addOrUpdateMessage(parentId, updatedMessage);
147
+ else {
148
+ this._voiceMessages[voiceIdx] = updatedMessage;
149
+ if (this._currentAssistantMsg === message) this._currentAssistantMsg = updatedMessage;
150
+ this._markVoiceMessagesDirty();
151
+ }
132
152
  }
133
153
  this._notifySubscribers();
134
154
  }
@@ -137,35 +157,69 @@ var BaseThreadRuntimeCore = class extends BaseSubscribable {
137
157
  speak(messageId) {
138
158
  const adapter = this.adapters?.speech;
139
159
  if (!adapter) throw new Error("Speech adapter not configured");
140
- const { message } = this.repository.getMessage(messageId);
141
- this._stopSpeaking?.();
142
- const utterance = adapter.speak(getThreadMessageText(message));
143
- const unsub = utterance.subscribe(() => {
144
- if (utterance.status.type === "ended") {
145
- this._stopSpeaking = void 0;
146
- this.speech = void 0;
147
- } else this.speech = {
148
- messageId,
149
- status: utterance.status
150
- };
151
- this._notifySubscribers();
152
- });
153
- this.speech = {
154
- messageId,
155
- status: utterance.status
156
- };
157
- this._notifySubscribers();
158
- this._stopSpeaking = () => {
159
- utterance.cancel();
160
- unsub();
161
- this.speech = void 0;
160
+ const entry = this.getMessageById(messageId);
161
+ if (!entry) throw new Error(`Message not found: ${messageId}`);
162
+ const { message } = entry;
163
+ const previousStop = this._stopSpeaking;
164
+ let utterance;
165
+ try {
166
+ previousStop?.();
167
+ utterance = adapter.speak(getThreadMessageText(message));
168
+ } catch (error) {
169
+ if (previousStop && !this._stopSpeaking) try {
170
+ this._notifySubscribers();
171
+ } catch (notificationError) {
172
+ console.error("[assistant-ui] Speech rollback notification threw", notificationError);
173
+ }
174
+ throw error;
175
+ }
176
+ let unsub;
177
+ const clear = () => {
162
178
  this._stopSpeaking = void 0;
179
+ this.speech = void 0;
180
+ const cleanup = unsub;
181
+ unsub = void 0;
182
+ cleanup?.();
163
183
  };
184
+ const stop = () => {
185
+ if (this._stopSpeaking !== stop) return;
186
+ try {
187
+ clear();
188
+ } finally {
189
+ utterance.cancel();
190
+ }
191
+ };
192
+ const update = () => {
193
+ if (this._stopSpeaking !== stop) return;
194
+ if (utterance.status.type === "ended") notifySubscribers([clear, () => this._notifySubscribers()]);
195
+ else {
196
+ this.speech = {
197
+ messageId,
198
+ status: utterance.status
199
+ };
200
+ this._notifySubscribers();
201
+ }
202
+ };
203
+ this._stopSpeaking = stop;
204
+ try {
205
+ unsub = utterance.subscribe(update);
206
+ if (this._stopSpeaking !== stop) {
207
+ unsub();
208
+ return;
209
+ }
210
+ update();
211
+ } catch (error) {
212
+ if (this._stopSpeaking === stop) try {
213
+ notifySubscribers([stop, () => this._notifySubscribers()]);
214
+ } catch (cleanupError) {
215
+ console.error("[assistant-ui] Speech rollback cleanup threw", cleanupError);
216
+ }
217
+ throw error;
218
+ }
164
219
  }
165
220
  stopSpeaking() {
166
221
  if (!this._stopSpeaking) throw new Error("No message is being spoken");
167
- this._stopSpeaking();
168
- this._notifySubscribers();
222
+ notifySubscribers([this._stopSpeaking, () => this._notifySubscribers()]);
169
223
  }
170
224
  _voiceSession;
171
225
  _voiceUnsubs = [];
@@ -180,48 +234,76 @@ var BaseThreadRuntimeCore = class extends BaseSubscribable {
180
234
  connectVoice() {
181
235
  const adapter = this.adapters?.voice;
182
236
  if (!adapter) throw new Error("Voice adapter not configured");
183
- this.disconnectVoice();
237
+ try {
238
+ this.disconnectVoice();
239
+ } catch (error) {
240
+ console.error("[assistant-ui] Voice cleanup threw before reconnect", error);
241
+ }
184
242
  const session = adapter.connect({});
185
243
  this._voiceSession = session;
186
244
  const unsubs = [];
187
- let currentMode = "listening";
188
- this.voice = {
189
- status: session.status,
190
- isMuted: session.isMuted,
191
- mode: currentMode
245
+ this._voiceUnsubs = unsubs;
246
+ const finishDetachedSetup = () => {
247
+ if (this._voiceSession === session && this._voiceUnsubs === unsubs) return false;
248
+ try {
249
+ notifySubscribers(unsubs.splice(0));
250
+ } catch (error) {
251
+ console.error("[assistant-ui] Detached voice setup cleanup threw", error);
252
+ }
253
+ return true;
192
254
  };
193
- this._voiceVolume = 0;
194
- this._notifySubscribers();
195
- unsubs.push(session.onStatusChange((status) => {
196
- if (status.type === "ended") {
197
- this._finishVoiceAssistantMessage();
198
- this._voiceSession = void 0;
199
- this.voice = void 0;
200
- } else this.voice = {
201
- status,
255
+ try {
256
+ let currentMode = "listening";
257
+ this.voice = {
258
+ status: session.status,
202
259
  isMuted: session.isMuted,
203
260
  mode: currentMode
204
261
  };
262
+ this._voiceVolume = 0;
205
263
  this._notifySubscribers();
206
- }));
207
- unsubs.push(session.onModeChange((mode) => {
208
- currentMode = mode;
209
- if (this.voice) {
210
- this.voice = {
211
- ...this.voice,
212
- mode
264
+ if (finishDetachedSetup()) return;
265
+ unsubs.push(session.onStatusChange((status) => {
266
+ if (status.type === "ended") {
267
+ this._finishVoiceAssistantMessage();
268
+ this._voiceSession = void 0;
269
+ this.voice = void 0;
270
+ } else this.voice = {
271
+ status,
272
+ isMuted: session.isMuted,
273
+ mode: currentMode
213
274
  };
214
275
  this._notifySubscribers();
276
+ }));
277
+ if (finishDetachedSetup()) return;
278
+ unsubs.push(session.onModeChange((mode) => {
279
+ currentMode = mode;
280
+ if (this.voice) {
281
+ this.voice = {
282
+ ...this.voice,
283
+ mode
284
+ };
285
+ this._notifySubscribers();
286
+ }
287
+ }));
288
+ if (finishDetachedSetup()) return;
289
+ unsubs.push(session.onVolumeChange((volume) => {
290
+ this._voiceVolume = volume;
291
+ notifyEventListeners(this._voiceVolumeSubscribers, void 0, "Voice volume");
292
+ }));
293
+ if (finishDetachedSetup()) return;
294
+ unsubs.push(session.onTranscript((transcript) => {
295
+ this._handleVoiceTranscript(transcript);
296
+ }));
297
+ finishDetachedSetup();
298
+ } catch (error) {
299
+ if (this._voiceSession === session && this._voiceUnsubs === unsubs) try {
300
+ this.disconnectVoice();
301
+ } catch (cleanupError) {
302
+ console.error("[assistant-ui] Voice rollback cleanup threw", cleanupError);
215
303
  }
216
- }));
217
- unsubs.push(session.onVolumeChange((volume) => {
218
- this._voiceVolume = volume;
219
- notifyEventListeners(this._voiceVolumeSubscribers, void 0, "Voice volume");
220
- }));
221
- unsubs.push(session.onTranscript((transcript) => {
222
- this._handleVoiceTranscript(transcript);
223
- }));
224
- this._voiceUnsubs = unsubs;
304
+ else finishDetachedSetup();
305
+ throw error;
306
+ }
225
307
  }
226
308
  _currentAssistantMsg = null;
227
309
  _handleVoiceTranscript(transcript) {
@@ -237,7 +319,10 @@ var BaseThreadRuntimeCore = class extends BaseSubscribable {
237
319
  type: "text",
238
320
  text: transcript.text
239
321
  }],
240
- metadata: { custom: {} },
322
+ metadata: {
323
+ modality: "voice",
324
+ custom: {}
325
+ },
241
326
  createdAt: /* @__PURE__ */ new Date(),
242
327
  status: {
243
328
  type: "complete",
@@ -249,6 +334,10 @@ var BaseThreadRuntimeCore = class extends BaseSubscribable {
249
334
  this._notifySubscribers();
250
335
  }
251
336
  } else {
337
+ const status = transcript.isFinal ? {
338
+ type: "complete",
339
+ reason: "stop"
340
+ } : { type: "running" };
252
341
  if (!this._currentAssistantMsg) {
253
342
  this._currentAssistantMsg = {
254
343
  id: generateId(),
@@ -262,9 +351,10 @@ var BaseThreadRuntimeCore = class extends BaseSubscribable {
262
351
  unstable_annotations: [],
263
352
  unstable_data: [],
264
353
  steps: [],
354
+ modality: "voice",
265
355
  custom: {}
266
356
  },
267
- status: { type: "running" },
357
+ status,
268
358
  createdAt: /* @__PURE__ */ new Date()
269
359
  };
270
360
  this._voiceMessages.push(this._currentAssistantMsg);
@@ -277,10 +367,7 @@ var BaseThreadRuntimeCore = class extends BaseSubscribable {
277
367
  type: "text",
278
368
  text: transcript.text
279
369
  }],
280
- ...transcript.isFinal ? { status: {
281
- type: "complete",
282
- reason: "stop"
283
- } } : {}
370
+ status
284
371
  };
285
372
  this._voiceMessages[idx] = updated;
286
373
  this._currentAssistantMsg = updated;
@@ -306,18 +393,23 @@ var BaseThreadRuntimeCore = class extends BaseSubscribable {
306
393
  }
307
394
  }
308
395
  disconnectVoice() {
309
- this._finishVoiceAssistantMessage();
310
396
  this._currentAssistantMsg = null;
311
- for (const unsub of this._voiceUnsubs) unsub();
397
+ const unsubs = this._voiceUnsubs.splice(0);
312
398
  this._voiceUnsubs = [];
313
- this._voiceSession?.disconnect();
399
+ const session = this._voiceSession;
314
400
  this._voiceSession = void 0;
315
401
  this.voice = void 0;
316
402
  this._voiceVolume = 0;
317
- notifyEventListeners(this._voiceVolumeSubscribers, void 0, "Voice volume");
403
+ const stopSpeaking = this.speech && this._isVoiceMessage(this.speech.messageId) ? this._stopSpeaking : void 0;
318
404
  this._voiceMessages = [];
319
405
  this._markVoiceMessagesDirty();
320
- this._notifySubscribers();
406
+ notifySubscribers([
407
+ ...unsubs,
408
+ ...stopSpeaking ? [stopSpeaking] : [],
409
+ ...session ? [() => session.disconnect()] : [],
410
+ () => notifyEventListeners(this._voiceVolumeSubscribers, void 0, "Voice volume"),
411
+ () => this._notifySubscribers()
412
+ ]);
321
413
  }
322
414
  muteVoice() {
323
415
  if (!this._voiceSession) throw new Error("No active voice session");