@assistant-ui/core 0.2.21 → 0.2.23

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 (345) hide show
  1. package/dist/adapters/attachment.d.ts.map +1 -1
  2. package/dist/adapters/speech.d.ts.map +1 -1
  3. package/dist/adapters/speech.js +9 -2
  4. package/dist/adapters/speech.js.map +1 -1
  5. package/dist/adapters/thread-history.d.ts +8 -0
  6. package/dist/adapters/thread-history.d.ts.map +1 -1
  7. package/dist/adapters/voice.d.ts.map +1 -1
  8. package/dist/adapters/voice.js +13 -5
  9. package/dist/adapters/voice.js.map +1 -1
  10. package/dist/internal.d.ts +5 -2
  11. package/dist/internal.js +5 -2
  12. package/dist/model-context/frame/host.d.ts +1 -0
  13. package/dist/model-context/frame/host.d.ts.map +1 -1
  14. package/dist/model-context/frame/host.js +41 -21
  15. package/dist/model-context/frame/host.js.map +1 -1
  16. package/dist/model-context/frame/provider.d.ts.map +1 -1
  17. package/dist/model-context/frame/provider.js +1 -0
  18. package/dist/model-context/frame/provider.js.map +1 -1
  19. package/dist/model-context/interactable-composer-metadata.js.map +1 -1
  20. package/dist/model-context/types.d.ts.map +1 -1
  21. package/dist/model-context/types.js +13 -4
  22. package/dist/model-context/types.js.map +1 -1
  23. package/dist/react/AssistantProvider.js.map +1 -1
  24. package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
  25. package/dist/react/adapters/LocalStorageThreadListAdapter.js +78 -50
  26. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  27. package/dist/react/client/Interactables.js.map +1 -1
  28. package/dist/react/client/Tools.d.ts.map +1 -1
  29. package/dist/react/client/interactable-model-context.d.ts.map +1 -1
  30. package/dist/react/client/interactable-model-context.js +1 -0
  31. package/dist/react/client/interactable-model-context.js.map +1 -1
  32. package/dist/react/interactables-legacy/useInteractableState.js +1 -0
  33. package/dist/react/interactables-legacy/useInteractableState.js.map +1 -1
  34. package/dist/react/model-context/useInteractable.js.map +1 -1
  35. package/dist/react/model-context/useInteractableState.js +1 -0
  36. package/dist/react/model-context/useInteractableState.js.map +1 -1
  37. package/dist/react/model-context/useInteractableVersions.js +1 -0
  38. package/dist/react/model-context/useInteractableVersions.js.map +1 -1
  39. package/dist/react/model-context/useToolArgsStatus.js +1 -0
  40. package/dist/react/model-context/useToolArgsStatus.js.map +1 -1
  41. package/dist/react/primitive-hooks/useActionBarCopy.js +14 -13
  42. package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
  43. package/dist/react/primitive-hooks/useActionBarEdit.js +1 -0
  44. package/dist/react/primitive-hooks/useActionBarEdit.js.map +1 -1
  45. package/dist/react/primitive-hooks/useActionBarFeedback.js +1 -0
  46. package/dist/react/primitive-hooks/useActionBarFeedback.js.map +1 -1
  47. package/dist/react/primitive-hooks/useActionBarReload.js +1 -0
  48. package/dist/react/primitive-hooks/useActionBarReload.js.map +1 -1
  49. package/dist/react/primitive-hooks/useActionBarSpeak.js +1 -0
  50. package/dist/react/primitive-hooks/useActionBarSpeak.js.map +1 -1
  51. package/dist/react/primitive-hooks/useActionBarStopSpeaking.js +1 -0
  52. package/dist/react/primitive-hooks/useActionBarStopSpeaking.js.map +1 -1
  53. package/dist/react/primitive-hooks/useBranchPickerNext.js +1 -0
  54. package/dist/react/primitive-hooks/useBranchPickerNext.js.map +1 -1
  55. package/dist/react/primitive-hooks/useBranchPickerPrevious.js +1 -0
  56. package/dist/react/primitive-hooks/useBranchPickerPrevious.js.map +1 -1
  57. package/dist/react/primitive-hooks/useComposerAddAttachment.d.ts.map +1 -1
  58. package/dist/react/primitive-hooks/useComposerAddAttachment.js +1 -0
  59. package/dist/react/primitive-hooks/useComposerAddAttachment.js.map +1 -1
  60. package/dist/react/primitive-hooks/useComposerCancel.js +1 -0
  61. package/dist/react/primitive-hooks/useComposerCancel.js.map +1 -1
  62. package/dist/react/primitive-hooks/useComposerDictate.js +1 -0
  63. package/dist/react/primitive-hooks/useComposerDictate.js.map +1 -1
  64. package/dist/react/primitive-hooks/useComposerSend.d.ts.map +1 -1
  65. package/dist/react/primitive-hooks/useComposerSend.js +1 -0
  66. package/dist/react/primitive-hooks/useComposerSend.js.map +1 -1
  67. package/dist/react/primitive-hooks/useEditComposerCancel.js +1 -0
  68. package/dist/react/primitive-hooks/useEditComposerCancel.js.map +1 -1
  69. package/dist/react/primitive-hooks/useEditComposerSend.js +1 -0
  70. package/dist/react/primitive-hooks/useEditComposerSend.js.map +1 -1
  71. package/dist/react/primitive-hooks/useMessageBranching.js +1 -0
  72. package/dist/react/primitive-hooks/useMessageBranching.js.map +1 -1
  73. package/dist/react/primitive-hooks/useMessageReload.js +1 -0
  74. package/dist/react/primitive-hooks/useMessageReload.js.map +1 -1
  75. package/dist/react/primitive-hooks/useSuggestionTrigger.js +1 -0
  76. package/dist/react/primitive-hooks/useSuggestionTrigger.js.map +1 -1
  77. package/dist/react/primitive-hooks/useThreadListItemArchive.js +1 -0
  78. package/dist/react/primitive-hooks/useThreadListItemArchive.js.map +1 -1
  79. package/dist/react/primitive-hooks/useThreadListItemDelete.js +1 -0
  80. package/dist/react/primitive-hooks/useThreadListItemDelete.js.map +1 -1
  81. package/dist/react/primitive-hooks/useThreadListItemTrigger.js +1 -0
  82. package/dist/react/primitive-hooks/useThreadListItemTrigger.js.map +1 -1
  83. package/dist/react/primitive-hooks/useThreadListItemUnarchive.js +1 -0
  84. package/dist/react/primitive-hooks/useThreadListItemUnarchive.js.map +1 -1
  85. package/dist/react/primitive-hooks/useThreadListLoadMore.js +1 -0
  86. package/dist/react/primitive-hooks/useThreadListLoadMore.js.map +1 -1
  87. package/dist/react/primitive-hooks/useThreadListNew.js +1 -0
  88. package/dist/react/primitive-hooks/useThreadListNew.js.map +1 -1
  89. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.d.ts.map +1 -1
  90. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js +1 -1
  91. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js.map +1 -1
  92. package/dist/react/primitives/composer/ComposerAttachments.js.map +1 -1
  93. package/dist/react/primitives/composer/ComposerQueue.d.ts.map +1 -1
  94. package/dist/react/primitives/composer/ComposerQueue.js.map +1 -1
  95. package/dist/react/primitives/generativeUI/GenerativeUI.d.ts.map +1 -1
  96. package/dist/react/primitives/message/MessageAttachments.js.map +1 -1
  97. package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
  98. package/dist/react/primitives/message/MessageParts.d.ts +2 -1
  99. package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
  100. package/dist/react/primitives/message/MessageParts.js +46 -36
  101. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  102. package/dist/react/primitives/part/PartMessages.js.map +1 -1
  103. package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
  104. package/dist/react/primitives/thread/ThreadSuggestions.js.map +1 -1
  105. package/dist/react/primitives/threadList/ThreadListItems.js.map +1 -1
  106. package/dist/react/providers/ChainOfThoughtPartByIndexProvider.d.ts.map +1 -1
  107. package/dist/react/providers/ChainOfThoughtPartByIndexProvider.js +18 -30
  108. package/dist/react/providers/ChainOfThoughtPartByIndexProvider.js.map +1 -1
  109. package/dist/react/providers/PartByIndexProvider.d.ts.map +1 -1
  110. package/dist/react/providers/PartByIndexProvider.js +18 -30
  111. package/dist/react/providers/PartByIndexProvider.js.map +1 -1
  112. package/dist/react/providers/TextMessagePartProvider.js +1 -0
  113. package/dist/react/providers/TextMessagePartProvider.js.map +1 -1
  114. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  115. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +1 -0
  116. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  117. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +9 -2
  118. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  119. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +55 -12
  120. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  121. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +31 -1
  122. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  123. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +12 -2
  124. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  125. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +1 -1
  126. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
  127. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +3 -2
  128. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
  129. package/dist/react/runtimes/cloud/auiV0.d.ts +12 -1
  130. package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
  131. package/dist/react/runtimes/cloud/auiV0.js +2 -1
  132. package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
  133. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +75 -73
  134. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  135. package/dist/react/runtimes/createMessageConverter.d.ts.map +1 -1
  136. package/dist/react/runtimes/external-message-converter.js +2 -2
  137. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  138. package/dist/react/runtimes/useExternalStoreSharedOptions.js +1 -0
  139. package/dist/react/runtimes/useExternalStoreSharedOptions.js.map +1 -1
  140. package/dist/react/runtimes/useLocalRuntime.d.ts.map +1 -1
  141. package/dist/react/runtimes/useLocalRuntime.js +9 -1
  142. package/dist/react/runtimes/useLocalRuntime.js.map +1 -1
  143. package/dist/runtime/api/assistant-runtime.d.ts +1 -1
  144. package/dist/runtime/api/assistant-runtime.d.ts.map +1 -1
  145. package/dist/runtime/api/assistant-runtime.js +1 -1
  146. package/dist/runtime/api/assistant-runtime.js.map +1 -1
  147. package/dist/runtime/api/attachment-runtime.d.ts +1 -1
  148. package/dist/runtime/api/attachment-runtime.d.ts.map +1 -1
  149. package/dist/runtime/api/attachment-runtime.js +1 -1
  150. package/dist/runtime/api/attachment-runtime.js.map +1 -1
  151. package/dist/runtime/api/composer-runtime.d.ts +2 -2
  152. package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
  153. package/dist/runtime/api/composer-runtime.js +2 -2
  154. package/dist/runtime/api/composer-runtime.js.map +1 -1
  155. package/dist/runtime/api/message-part-runtime.d.ts +4 -4
  156. package/dist/runtime/api/message-part-runtime.d.ts.map +1 -1
  157. package/dist/runtime/api/message-part-runtime.js +3 -3
  158. package/dist/runtime/api/message-part-runtime.js.map +1 -1
  159. package/dist/runtime/api/message-runtime.d.ts +1 -1
  160. package/dist/runtime/api/message-runtime.d.ts.map +1 -1
  161. package/dist/runtime/api/message-runtime.js +6 -6
  162. package/dist/runtime/api/message-runtime.js.map +1 -1
  163. package/dist/runtime/api/thread-list-item-runtime.d.ts +1 -1
  164. package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
  165. package/dist/runtime/api/thread-list-item-runtime.js +4 -3
  166. package/dist/runtime/api/thread-list-item-runtime.js.map +1 -1
  167. package/dist/runtime/api/thread-list-runtime.d.ts +1 -1
  168. package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
  169. package/dist/runtime/api/thread-list-runtime.js +1 -1
  170. package/dist/runtime/api/thread-list-runtime.js.map +1 -1
  171. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  172. package/dist/runtime/base/base-composer-runtime-core.d.ts +4 -1
  173. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  174. package/dist/runtime/base/base-composer-runtime-core.js +41 -14
  175. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  176. package/dist/runtime/base/base-thread-runtime-core.d.ts +1 -1
  177. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  178. package/dist/runtime/base/base-thread-runtime-core.js +3 -2
  179. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  180. package/dist/runtime/base/default-edit-composer-runtime-core.d.ts +2 -2
  181. package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
  182. package/dist/runtime/base/default-edit-composer-runtime-core.js +6 -4
  183. package/dist/runtime/base/default-edit-composer-runtime-core.js.map +1 -1
  184. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +1 -1
  185. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
  186. package/dist/runtime/base/default-thread-composer-runtime-core.js +3 -3
  187. package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
  188. package/dist/runtime/utils/message-repository.d.ts.map +1 -1
  189. package/dist/runtime/utils/message-repository.js +4 -2
  190. package/dist/runtime/utils/message-repository.js.map +1 -1
  191. package/dist/runtime/utils/thread-message-like.js +4 -1
  192. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  193. package/dist/runtimes/external-store/external-store-runtime-core.d.ts.map +1 -1
  194. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts +1 -1
  195. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  196. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +1 -1
  197. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  198. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  199. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +12 -0
  200. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  201. package/dist/runtimes/internal.d.ts +2 -1
  202. package/dist/runtimes/internal.js +2 -1
  203. package/dist/runtimes/local/local-runtime-core.d.ts.map +1 -1
  204. package/dist/runtimes/local/local-thread-list-runtime-core.d.ts.map +1 -1
  205. package/dist/runtimes/local/local-thread-runtime-core.d.ts +3 -0
  206. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  207. package/dist/runtimes/local/local-thread-runtime-core.js +49 -15
  208. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  209. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
  210. package/dist/runtimes/remote-thread-list/optimistic-state.d.ts +4 -4
  211. package/dist/runtimes/remote-thread-list/optimistic-state.d.ts.map +1 -1
  212. package/dist/runtimes/remote-thread-list/optimistic-state.js +22 -9
  213. package/dist/runtimes/remote-thread-list/optimistic-state.js.map +1 -1
  214. package/dist/runtimes/remote-thread-list/types.d.ts +1 -1
  215. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +32 -27
  216. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
  217. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +3 -2
  218. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
  219. package/dist/store/clients/chain-of-thought-client.d.ts.map +1 -1
  220. package/dist/store/clients/no-op-composer-client.d.ts.map +1 -1
  221. package/dist/store/clients/no-op-composer-client.js +1 -0
  222. package/dist/store/clients/no-op-composer-client.js.map +1 -1
  223. package/dist/store/runtime-clients/attachment-runtime-client.d.ts.map +1 -1
  224. package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
  225. package/dist/store/runtime-clients/message-part-runtime-client.d.ts.map +1 -1
  226. package/dist/store/runtime-clients/message-runtime-client.d.ts.map +1 -1
  227. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  228. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
  229. package/dist/store/runtime-clients/thread-list-runtime-client.js +1 -0
  230. package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
  231. package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
  232. package/dist/store/runtime-clients/thread-runtime-client.js +17 -15
  233. package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
  234. package/dist/store/scopes/thread.d.ts +1 -0
  235. package/dist/store/scopes/thread.d.ts.map +1 -1
  236. package/dist/subscribable/subscribable.d.ts +4 -4
  237. package/dist/subscribable/subscribable.d.ts.map +1 -1
  238. package/dist/subscribable/subscribable.js +14 -6
  239. package/dist/subscribable/subscribable.js.map +1 -1
  240. package/dist/tests/remote-thread-list-test-helpers.d.ts +2 -1
  241. package/dist/tests/remote-thread-list-test-helpers.d.ts.map +1 -1
  242. package/dist/tests/remote-thread-list-test-helpers.js +5 -2
  243. package/dist/tests/remote-thread-list-test-helpers.js.map +1 -1
  244. package/dist/types/attachment.d.ts +2 -1
  245. package/dist/types/attachment.d.ts.map +1 -1
  246. package/dist/types/attachment.js +6 -0
  247. package/dist/types/attachment.js.map +1 -0
  248. package/dist/types/message.d.ts +1 -0
  249. package/dist/types/message.d.ts.map +1 -1
  250. package/dist/types/message.js.map +1 -1
  251. package/dist/utils/data-url.d.ts +9 -0
  252. package/dist/utils/data-url.d.ts.map +1 -0
  253. package/dist/utils/data-url.js +14 -0
  254. package/dist/utils/data-url.js.map +1 -0
  255. package/dist/utils/notify-event-listeners.d.ts +6 -0
  256. package/dist/utils/notify-event-listeners.d.ts.map +1 -0
  257. package/dist/utils/notify-event-listeners.js +16 -0
  258. package/dist/utils/notify-event-listeners.js.map +1 -0
  259. package/package.json +10 -9
  260. package/src/adapters/speech.test.ts +88 -0
  261. package/src/adapters/speech.ts +17 -2
  262. package/src/adapters/thread-history.ts +8 -0
  263. package/src/adapters/voice.test.ts +130 -0
  264. package/src/adapters/voice.ts +26 -6
  265. package/src/internal.ts +6 -1
  266. package/src/model-context/frame/host.test.ts +147 -0
  267. package/src/model-context/frame/host.ts +56 -19
  268. package/src/model-context/frame/provider.test.ts +83 -0
  269. package/src/model-context/frame/provider.ts +1 -0
  270. package/src/model-context/types.ts +16 -6
  271. package/src/react/adapters/LocalStorageThreadListAdapter.test.ts +82 -0
  272. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +108 -58
  273. package/src/react/primitive-hooks/useActionBarCopy.test.ts +79 -0
  274. package/src/react/primitive-hooks/useActionBarCopy.ts +4 -3
  275. package/src/react/primitives/chainOfThought/ChainOfThoughtParts.tsx +1 -3
  276. package/src/react/primitives/message/MessageParts.tsx +48 -35
  277. package/src/react/providers/ChainOfThoughtPartByIndexProvider.tsx +19 -2
  278. package/src/react/providers/PartByIndexProvider.tsx +16 -2
  279. package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +18 -0
  280. package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +1 -0
  281. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +68 -13
  282. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.ts +34 -0
  283. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +69 -0
  284. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +27 -6
  285. package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.test.ts +16 -0
  286. package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +7 -2
  287. package/src/react/runtimes/cloud/auiV0.ts +14 -0
  288. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +90 -88
  289. package/src/react/runtimes/external-message-converter.test.ts +346 -0
  290. package/src/react/runtimes/external-message-converter.test.tsx +21 -0
  291. package/src/react/runtimes/external-message-converter.ts +2 -2
  292. package/src/react/runtimes/useLocalRuntime.test.tsx +99 -0
  293. package/src/react/runtimes/useLocalRuntime.ts +13 -1
  294. package/src/runtime/api/assistant-runtime.ts +4 -1
  295. package/src/runtime/api/attachment-runtime.ts +8 -2
  296. package/src/runtime/api/composer-runtime.ts +9 -5
  297. package/src/runtime/api/message-part-runtime.ts +10 -3
  298. package/src/runtime/api/message-runtime.test.ts +81 -0
  299. package/src/runtime/api/message-runtime.ts +11 -8
  300. package/src/runtime/api/thread-list-item-runtime.ts +13 -3
  301. package/src/runtime/api/thread-list-runtime.ts +10 -2
  302. package/src/runtime/base/base-composer-runtime-core.ts +77 -31
  303. package/src/runtime/base/base-thread-runtime-core.ts +7 -2
  304. package/src/runtime/base/default-edit-composer-runtime-core.ts +18 -4
  305. package/src/runtime/base/default-thread-composer-runtime-core.ts +13 -3
  306. package/src/runtime/utils/message-repository.ts +19 -13
  307. package/src/runtime/utils/thread-message-like.ts +1 -0
  308. package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +4 -1
  309. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +15 -0
  310. package/src/runtimes/internal.ts +3 -0
  311. package/src/runtimes/local/local-thread-runtime-core.test.ts +746 -1
  312. package/src/runtimes/local/local-thread-runtime-core.ts +89 -23
  313. package/src/runtimes/local/should-continue.test.ts +122 -0
  314. package/src/runtimes/remote-thread-list/optimistic-state.test.ts +63 -0
  315. package/src/runtimes/remote-thread-list/optimistic-state.ts +49 -17
  316. package/src/runtimes/remote-thread-list/types.ts +1 -1
  317. package/src/runtimes/tool-invocations/EDGE_CASES.md +13 -19
  318. package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +128 -8
  319. package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +42 -34
  320. package/src/store/clients/model-context-client.test.ts +21 -1
  321. package/src/store/runtime-clients/thread-runtime-client.ts +2 -1
  322. package/src/store/scopes/thread.ts +1 -0
  323. package/src/subscribable/subscribable.test.ts +58 -0
  324. package/src/subscribable/subscribable.ts +29 -11
  325. package/src/tests/MessageRepository.test.ts +12 -0
  326. package/src/tests/OptimisticState-list-race.test.ts +33 -0
  327. package/src/tests/RemoteThreadListThreadListRuntimeCore-switchToThread-order.test.ts +223 -0
  328. package/src/tests/RemoteThreadListThreadListRuntimeCore-switchToThread-position.test.ts +121 -0
  329. package/src/tests/auiV0Encode.test.ts +74 -0
  330. package/src/tests/base-composer-runtime-core-addAttachment.test.ts +44 -0
  331. package/src/tests/base-composer-runtime-core-send.test.ts +433 -5
  332. package/src/tests/base-composer-runtime-core.test.ts +422 -0
  333. package/src/tests/default-edit-composer-runtime-core.test.ts +43 -5
  334. package/src/tests/event-subscription-listener-errors.test.ts +205 -0
  335. package/src/tests/external-store-thread-list-runtime-core.test.ts +6 -6
  336. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +575 -0
  337. package/src/tests/external-store-thread-runtime-core.test.ts +55 -1
  338. package/src/tests/remote-thread-list-test-helpers.ts +14 -7
  339. package/src/tests/thread-message-like.test.ts +57 -0
  340. package/src/types/attachment.ts +5 -0
  341. package/src/types/message.ts +1 -0
  342. package/src/utils/data-url.test.ts +50 -0
  343. package/src/utils/data-url.ts +9 -0
  344. package/src/utils/notify-event-listeners.ts +30 -0
  345. package/src/tests/OptimisticState-delete-crash.test.ts +0 -208
@@ -1 +1 @@
1
- {"version":3,"file":"attachment.d.ts","names":[],"sources":["../../src/adapters/attachment.ts"],"mappings":";;;KAQY;EACV;EACA,IAAI;IACF,MAAM;MACJ,QAAQ,qBAAqB,eAAe;EAChD,OAAO,YAAY,aAAa;EAChC,KAAK,YAAY,oBAAoB,QAAQ;;cAGlC,wCAAwC;EAC5C;EAEM,IAAI;IAAS,MAAM;MAAS,QAAQ;EAWpC,KACX,YAAY,oBACX,QAAQ;EAaE,UAAM;;cA0BR,iBAAwB,MAAM,SAAO;cAarC,uCAAuC;EAC3C;EAGM,IAAI;IAAS,MAAM;MAAS,QAAQ;EAWpC,KACX,YAAY,oBACX,QAAQ;EAaE,UAAM;;iBAiBL,kBACd;EAAQ;EAAc;GACtB;iBAiCc,iBACd,YAAY,sBACZ,YAAY;iBAME,yBACd,MAAM,QAAQ;EAAyB;KACtC;iBA4Ca,iBACd,kBAAkB,0BACjB;cAUU,sCAAsC;UACzC;EAED;cAEK,UAAU;EAgBf,IAAI;IAAS,MAAM;MAAM,QAAA,qBAAA,eAAA;EASnB,KAAK,YAAY,oBAAiB,QAAA;EAUlC,OAAO,YAAY,aAAU"}
1
+ {"version":3,"file":"attachment.d.ts","names":[],"sources":["../../src/adapters/attachment.ts"],"mappings":";;;KAQY;EACV;EACA,IAAI;IACF,MAAM;MACJ,QAAQ,qBAAqB,eAAe;EAChD,OAAO,YAAY,aAAa;EAChC,KAAK,YAAY,oBAAoB,QAAQ;;cAGlC,wCAAwC;EAC5C;EAEM,IAAI;IAAS,MAAM;MAAS,QAAQ;EAWpC,KACX,YAAY,oBACX,QAAQ;EAaE,UAAM;;cA0BR,iBAAwB,MAAM,SAAO;cAarC,uCAAuC;EAC3C;EAGM,IAAI;IAAS,MAAM;MAAS,QAAQ;EAWpC,KACX,YAAY,oBACX,QAAQ;EAaE,UAAM;;iBAiBL,kBACd;EAAQ;EAAc;GACtB;iBAiCc,iBACd,YAAY,sBACZ,YAAY;iBAME,yBACd,MAAM,QAAQ;EAAyB;KACtC;iBA4Ca,iBACd,kBAAkB,0BACjB;cAUU,sCAAsC;UACzC;EAED;EAEK,YAAA,UAAU;EAgBf,IAAI;IAAS,MAAM;MAAM,QAAA,qBAAA,eAAA;EASnB,KAAK,YAAY,oBAAiB,QAAA;EAUlC,OAAO,YAAY,aAAU"}
@@ -1 +1 @@
1
- {"version":3,"file":"speech.d.ts","names":[],"sources":["../../src/adapters/speech.ts"],"mappings":";;kBAEiB;OACH;IAEN;;IAGA;IACA;IACA;;OAGM;IACV,QAAQ;IACR;IACA,YAAY,yBAAyB;;;KAI7B;EACV,QAAQ,iBAAiB,uBAAuB;;kBAGjC;OACH;IAEN;;IAGA;IACA;;OAGM;IACV;IACA;;OAGU;IACV,QAAQ;IACR,YAAY;IACZ;IACA,gBAAgB,yBAAyB;IACzC,cAAc,WAAW,QAAQ,oBAAoB;IACrD,WAAW,WAAW,QAAQ,oBAAoB;;;KAI1C;EACV,cAAc,iBAAiB;EAC/B;;cAGW,qCAAqC;EAChD,MAAM,eAAe,uBAAuB;;UA0EpC,kCAAkC;EAC1C;EACA;EACA;EACA;EACA;EACA;;UAGQ;UACA;;QAGF;YACI;IACR,oBAAoB;IACpB,0BAA0B;;;cAWjB,qCAAqC;UACxC;UACA;UACA;cAGN;IACE;IACA;IACA;;SAYG;EAIP,UAAU,iBAAiB"}
1
+ {"version":3,"file":"speech.d.ts","names":[],"sources":["../../src/adapters/speech.ts"],"mappings":";;kBAEiB;OACH;IAEN;;IAGA;IACA;IACA;;OAGM;IACV,QAAQ;IACR;IACA,YAAY,yBAAyB;;;KAI7B;EACV,QAAQ,iBAAiB,uBAAuB;;kBAkBjC;OACH;IAEN;;IAGA;IACA;;OAGM;IACV;IACA;;OAGU;IACV,QAAQ;IACR,YAAY;IACZ;IACA,gBAAgB,yBAAyB;IACzC,cAAc,WAAW,QAAQ,oBAAoB;IACrD,WAAW,WAAW,QAAQ,oBAAoB;;;KAI1C;EACV,cAAc,iBAAiB;EAC/B;;cAGW,qCAAqC;EAChD,MAAM,eAAe,uBAAuB;;UA0EpC,kCAAkC;EAC1C;EACA;EACA;EACA;EACA;EACA;;UAGQ;UACA;;QAGF;YACI;IACR,oBAAoB;IACpB,0BAA0B;;;cAWjB,qCAAqC;UACxC;UACA;UACA;EAGN,YAAA;IACE;IACA;IACA;;SAYG;EAIP,UAAU,iBAAiB"}
@@ -1,4 +1,11 @@
1
1
  //#region src/adapters/speech.ts
2
+ const notifySpeechSynthesisListeners = (listeners) => {
3
+ for (const listener of listeners) try {
4
+ listener();
5
+ } catch (error) {
6
+ console.error("[assistant-ui] Speech synthesis listener threw an error", error);
7
+ }
8
+ };
2
9
  var WebSpeechSynthesisAdapter = class {
3
10
  speak(text) {
4
11
  const utterance = new SpeechSynthesisUtterance(text);
@@ -10,7 +17,7 @@ var WebSpeechSynthesisAdapter = class {
10
17
  reason,
11
18
  error
12
19
  };
13
- subscribers.forEach((handler) => handler());
20
+ notifySpeechSynthesisListeners(subscribers);
14
21
  };
15
22
  utterance.addEventListener("end", () => handleEnd("finished"));
16
23
  utterance.addEventListener("error", (e) => handleEnd("error", e.error));
@@ -25,7 +32,7 @@ var WebSpeechSynthesisAdapter = class {
25
32
  if (res.status.type === "ended") {
26
33
  let cancelled = false;
27
34
  queueMicrotask(() => {
28
- if (!cancelled) callback();
35
+ if (!cancelled) notifySpeechSynthesisListeners([callback]);
29
36
  });
30
37
  return () => {
31
38
  cancelled = true;
@@ -1 +1 @@
1
- {"version":3,"file":"speech.js","names":["Unsubscribe","SpeechSynthesisAdapter","Status","type","reason","error","Utterance","status","cancel","subscribe","callback","speak","text","DictationAdapter","Result","transcript","isFinal","Session","stop","Promise","onSpeechStart","onSpeechEnd","result","onSpeech","listen","disableInputDuringDictation","WebSpeechSynthesisAdapter","utterance","SpeechSynthesisUtterance","subscribers","Set","handleEnd","res","forEach","handler","addEventListener","e","window","speechSynthesis","cancelled","queueMicrotask","add","delete","SpeechRecognitionResultItem","confidence","SpeechRecognitionResult","length","item","index","SpeechRecognitionResultList","SpeechRecognitionEvent","Event","resultIndex","results","SpeechRecognitionErrorEvent","message","SpeechRecognitionInstance","EventTarget","lang","continuous","interimResults","start","abort","SpeechRecognitionConstructor","global","Window","SpeechRecognition","webkitSpeechRecognition","getSpeechRecognitionAPI","undefined","WebSpeechDictationAdapter","_language","_continuous","_interimResults","constructor","options","language","defaultLanguage","navigator","isSupported","SpeechRecognitionAPI","Error","recognition","speechStartCallbacks","speechEndCallbacks","speechCallbacks","finalTranscript","session","resolve","checkEnded","setTimeout","updateStatus","newStatus","cb","event","speechEvent","i","currentStatus","errorEvent","console"],"sources":["../../src/adapters/speech.ts"],"sourcesContent":["import type { Unsubscribe } from \"../types/unsubscribe\";\n\nexport namespace SpeechSynthesisAdapter {\n export type Status =\n | {\n type: \"starting\" | \"running\";\n }\n | {\n type: \"ended\";\n reason: \"finished\" | \"cancelled\" | \"error\";\n error?: unknown;\n };\n\n export type Utterance = {\n status: Status;\n cancel: () => void;\n subscribe: (callback: () => void) => Unsubscribe;\n };\n}\n\nexport type SpeechSynthesisAdapter = {\n speak: (text: string) => SpeechSynthesisAdapter.Utterance;\n};\n\nexport namespace DictationAdapter {\n export type Status =\n | {\n type: \"starting\" | \"running\";\n }\n | {\n type: \"ended\";\n reason: \"stopped\" | \"cancelled\" | \"error\";\n };\n\n export type Result = {\n transcript: string;\n isFinal?: boolean;\n };\n\n export type Session = {\n status: Status;\n stop: () => Promise<void>;\n cancel: () => void;\n onSpeechStart: (callback: () => void) => Unsubscribe;\n onSpeechEnd: (callback: (result: Result) => void) => Unsubscribe;\n onSpeech: (callback: (result: Result) => void) => Unsubscribe;\n };\n}\n\nexport type DictationAdapter = {\n listen: () => DictationAdapter.Session;\n disableInputDuringDictation?: boolean;\n};\n\nexport class WebSpeechSynthesisAdapter implements SpeechSynthesisAdapter {\n speak(text: string): SpeechSynthesisAdapter.Utterance {\n const utterance = new SpeechSynthesisUtterance(text);\n\n const subscribers = new Set<() => void>();\n const handleEnd = (\n reason: \"finished\" | \"error\" | \"cancelled\",\n error?: unknown,\n ) => {\n if (res.status.type === \"ended\") return;\n\n res.status = { type: \"ended\", reason, error };\n subscribers.forEach((handler) => handler());\n };\n\n utterance.addEventListener(\"end\", () => handleEnd(\"finished\"));\n utterance.addEventListener(\"error\", (e) => handleEnd(\"error\", e.error));\n\n window.speechSynthesis.speak(utterance);\n\n const res: SpeechSynthesisAdapter.Utterance = {\n status: { type: \"running\" },\n cancel: () => {\n window.speechSynthesis.cancel();\n handleEnd(\"cancelled\");\n },\n subscribe: (callback) => {\n if (res.status.type === \"ended\") {\n let cancelled = false;\n queueMicrotask(() => {\n if (!cancelled) callback();\n });\n return () => {\n cancelled = true;\n };\n } else {\n subscribers.add(callback);\n return () => {\n subscribers.delete(callback);\n };\n }\n },\n };\n return res;\n }\n}\n\ninterface SpeechRecognitionResultItem {\n transcript: string;\n confidence: number;\n}\n\ninterface SpeechRecognitionResult {\n readonly length: number;\n item(index: number): SpeechRecognitionResultItem;\n readonly isFinal: boolean;\n [index: number]: SpeechRecognitionResultItem;\n}\n\ninterface SpeechRecognitionResultList {\n readonly length: number;\n item(index: number): SpeechRecognitionResult;\n [index: number]: SpeechRecognitionResult;\n}\n\ninterface SpeechRecognitionEvent extends Event {\n readonly resultIndex: number;\n readonly results: SpeechRecognitionResultList;\n}\n\ninterface SpeechRecognitionErrorEvent extends Event {\n readonly error: string;\n readonly message: string;\n}\n\ninterface SpeechRecognitionInstance extends EventTarget {\n lang: string;\n continuous: boolean;\n interimResults: boolean;\n start(): void;\n stop(): void;\n abort(): void;\n}\n\ninterface SpeechRecognitionConstructor {\n new (): SpeechRecognitionInstance;\n}\n\ndeclare global {\n interface Window {\n SpeechRecognition?: SpeechRecognitionConstructor;\n webkitSpeechRecognition?: SpeechRecognitionConstructor;\n }\n}\n\nconst getSpeechRecognitionAPI = ():\n | SpeechRecognitionConstructor\n | undefined => {\n if (typeof window === \"undefined\") return undefined;\n return window.SpeechRecognition ?? window.webkitSpeechRecognition;\n};\n\nexport class WebSpeechDictationAdapter implements DictationAdapter {\n private _language: string;\n private _continuous: boolean;\n private _interimResults: boolean;\n\n constructor(\n options: {\n language?: string;\n continuous?: boolean;\n interimResults?: boolean;\n } = {},\n ) {\n const defaultLanguage =\n typeof navigator !== \"undefined\" && navigator.language\n ? navigator.language\n : \"en-US\";\n this._language = options.language ?? defaultLanguage;\n this._continuous = options.continuous ?? true;\n this._interimResults = options.interimResults ?? true;\n }\n\n static isSupported(): boolean {\n return getSpeechRecognitionAPI() !== undefined;\n }\n\n listen(): DictationAdapter.Session {\n const SpeechRecognitionAPI = getSpeechRecognitionAPI();\n if (!SpeechRecognitionAPI) {\n throw new Error(\n \"SpeechRecognition is not supported in this browser. \" +\n \"Try using Chrome, Edge, or Safari.\",\n );\n }\n\n const recognition = new SpeechRecognitionAPI();\n recognition.lang = this._language;\n recognition.continuous = this._continuous;\n recognition.interimResults = this._interimResults;\n\n const speechStartCallbacks = new Set<() => void>();\n const speechEndCallbacks = new Set<\n (result: DictationAdapter.Result) => void\n >();\n const speechCallbacks = new Set<\n (result: DictationAdapter.Result) => void\n >();\n\n let finalTranscript = \"\";\n\n const session: DictationAdapter.Session = {\n status: { type: \"starting\" },\n\n stop: async () => {\n recognition.stop();\n return new Promise<void>((resolve) => {\n const checkEnded = () => {\n if (session.status.type === \"ended\") {\n resolve();\n } else {\n setTimeout(checkEnded, 50);\n }\n };\n checkEnded();\n });\n },\n\n cancel: () => {\n recognition.abort();\n },\n\n onSpeechStart: (callback: () => void): Unsubscribe => {\n speechStartCallbacks.add(callback);\n return () => {\n speechStartCallbacks.delete(callback);\n };\n },\n\n onSpeechEnd: (\n callback: (result: DictationAdapter.Result) => void,\n ): Unsubscribe => {\n speechEndCallbacks.add(callback);\n return () => {\n speechEndCallbacks.delete(callback);\n };\n },\n\n onSpeech: (\n callback: (result: DictationAdapter.Result) => void,\n ): Unsubscribe => {\n speechCallbacks.add(callback);\n return () => {\n speechCallbacks.delete(callback);\n };\n },\n };\n\n const updateStatus = (newStatus: DictationAdapter.Status) => {\n session.status = newStatus;\n };\n\n recognition.addEventListener(\"speechstart\", () => {\n for (const cb of speechStartCallbacks) cb();\n });\n\n recognition.addEventListener(\"start\", () => {\n updateStatus({ type: \"running\" });\n });\n\n recognition.addEventListener(\"result\", (event) => {\n const speechEvent = event as unknown as SpeechRecognitionEvent;\n\n for (\n let i = speechEvent.resultIndex;\n i < speechEvent.results.length;\n i++\n ) {\n const result = speechEvent.results[i];\n if (!result) continue;\n\n const transcript = result[0]?.transcript ?? \"\";\n\n if (result.isFinal) {\n finalTranscript += transcript;\n for (const cb of speechCallbacks) cb({ transcript, isFinal: true });\n } else {\n for (const cb of speechCallbacks) cb({ transcript, isFinal: false });\n }\n }\n });\n\n recognition.addEventListener(\"speechend\", () => {\n // speechend fires when user stops speaking, but 'end' handles final cleanup\n });\n\n recognition.addEventListener(\"end\", () => {\n const currentStatus = session.status;\n if (currentStatus.type !== \"ended\") {\n updateStatus({ type: \"ended\", reason: \"stopped\" });\n }\n if (finalTranscript) {\n for (const cb of speechEndCallbacks)\n cb({ transcript: finalTranscript });\n finalTranscript = \"\";\n }\n });\n\n recognition.addEventListener(\"error\", (event) => {\n const errorEvent = event as unknown as SpeechRecognitionErrorEvent;\n if (errorEvent.error === \"aborted\") {\n updateStatus({ type: \"ended\", reason: \"cancelled\" });\n } else {\n updateStatus({ type: \"ended\", reason: \"error\" });\n console.error(\"Dictation error:\", errorEvent.error, errorEvent.message);\n }\n });\n\n try {\n recognition.start();\n } catch (error) {\n updateStatus({ type: \"ended\", reason: \"error\" });\n throw error;\n }\n\n return session;\n }\n}\n"],"mappings":";AAsDA,IAAa0B,4BAAb,MAAyE;CACvEf,MAAMC,MAAgD;EACpD,MAAMe,YAAY,IAAIC,yBAAyBhB,IAAI;EAEnD,MAAMiB,8BAAc,IAAIC,IAAgB;EACxC,MAAMC,aACJ3B,QACAC,UACG;GACH,IAAI2B,IAAIzB,OAAOJ,SAAS,SAAS;GAEjC6B,IAAIzB,SAAS;IAAEJ,MAAM;IAASC;IAAQC;GAAM;GAC5CwB,YAAYI,SAASC,YAAYA,QAAQ,CAAC;EAC5C;EAEAP,UAAUQ,iBAAiB,aAAaJ,UAAU,UAAU,CAAC;EAC7DJ,UAAUQ,iBAAiB,UAAUC,MAAML,UAAU,SAASK,EAAE/B,KAAK,CAAC;EAEtEgC,OAAOC,gBAAgB3B,MAAMgB,SAAS;EAEtC,MAAMK,MAAwC;GAC5CzB,QAAQ,EAAEJ,MAAM,UAAU;GAC1BK,cAAc;IACZ6B,OAAOC,gBAAgB9B,OAAO;IAC9BuB,UAAU,WAAW;GACvB;GACAtB,YAAYC,aAAa;IACvB,IAAIsB,IAAIzB,OAAOJ,SAAS,SAAS;KAC/B,IAAIoC,YAAY;KAChBC,qBAAqB;MACnB,IAAI,CAACD,WAAW7B,SAAS;KAC3B,CAAC;KACD,aAAa;MACX6B,YAAY;KACd;IACF,OAAO;KACLV,YAAYY,IAAI/B,QAAQ;KACxB,aAAa;MACXmB,YAAYa,OAAOhC,QAAQ;KAC7B;IACF;GACF;EACF;EACA,OAAOsB;CACT;AACF;AAkDA,MAAMoC,gCAEW;CACf,IAAI,OAAO/B,WAAW,aAAa,OAAOgC,KAAAA;CAC1C,OAAOhC,OAAO6B,qBAAqB7B,OAAO8B;AAC5C;AAEA,IAAaG,4BAAb,MAAmE;CACjE;CACA;CACA;CAEAI,YACEC,UAII,CAAC,GACL;EACA,MAAME,kBACJ,OAAOC,cAAc,eAAeA,UAAUF,WAC1CE,UAAUF,WACV;EACN,KAAKL,YAAYI,QAAQC,YAAYC;EACrC,KAAKL,cAAcG,QAAQhB,cAAc;EACzC,KAAKc,kBAAkBE,QAAQf,kBAAkB;CACnD;CAEA,OAAOmB,cAAuB;EAC5B,OAAOX,wBAAwB,MAAMC,KAAAA;CACvC;CAEA7C,SAAmC;EACjC,MAAMwD,uBAAuBZ,wBAAwB;EACrD,IAAI,CAACY,sBACH,MAAM,IAAIC,MACR,wFAEF;EAGF,MAAMC,cAAc,IAAIF,qBAAqB;EAC7CE,YAAYxB,OAAO,KAAKa;EACxBW,YAAYvB,aAAa,KAAKa;EAC9BU,YAAYtB,iBAAiB,KAAKa;EAElC,MAAMU,uCAAuB,IAAIrD,IAAgB;EACjD,MAAMsD,qCAAqB,IAAItD,IAE7B;EACF,MAAMuD,kCAAkB,IAAIvD,IAE1B;EAEF,IAAIwD,kBAAkB;EAEtB,MAAMC,UAAoC;GACxChF,QAAQ,EAAEJ,MAAM,WAAW;GAE3Be,MAAM,YAAY;IAChBgE,YAAYhE,KAAK;IACjB,OAAO,IAAIC,SAAeqE,YAAY;KACpC,MAAMC,mBAAmB;MACvB,IAAIF,QAAQhF,OAAOJ,SAAS,SAC1BqF,QAAQ;WAERE,WAAWD,YAAY,EAAE;KAE7B;KACAA,WAAW;IACb,CAAC;GACH;GAEAjF,cAAc;IACZ0E,YAAYpB,MAAM;GACpB;GAEA1C,gBAAgBV,aAAsC;IACpDyE,qBAAqB1C,IAAI/B,QAAQ;IACjC,aAAa;KACXyE,qBAAqBzC,OAAOhC,QAAQ;IACtC;GACF;GAEAW,cACEX,aACgB;IAChB0E,mBAAmB3C,IAAI/B,QAAQ;IAC/B,aAAa;KACX0E,mBAAmB1C,OAAOhC,QAAQ;IACpC;GACF;GAEAa,WACEb,aACgB;IAChB2E,gBAAgB5C,IAAI/B,QAAQ;IAC5B,aAAa;KACX2E,gBAAgB3C,OAAOhC,QAAQ;IACjC;GACF;EACF;EAEA,MAAMiF,gBAAgBC,cAAuC;GAC3DL,QAAQhF,SAASqF;EACnB;EAEAV,YAAY/C,iBAAiB,qBAAqB;GAChD,KAAK,MAAM0D,MAAMV,sBAAsBU,GAAG;EAC5C,CAAC;EAEDX,YAAY/C,iBAAiB,eAAe;GAC1CwD,aAAa,EAAExF,MAAM,UAAU,CAAC;EAClC,CAAC;EAED+E,YAAY/C,iBAAiB,WAAW2D,UAAU;GAChD,MAAMC,cAAcD;GAEpB,KACE,IAAIE,IAAID,YAAY3C,aACpB4C,IAAID,YAAY1C,QAAQP,QACxBkD,KACA;IACA,MAAM1E,SAASyE,YAAY1C,QAAQ2C;IACnC,IAAI,CAAC1E,QAAQ;IAEb,MAAMP,aAAaO,OAAO,EAAE,EAAEP,cAAc;IAE5C,IAAIO,OAAON,SAAS;KAClBsE,mBAAmBvE;KACnB,KAAK,MAAM8E,MAAMR,iBAAiBQ,GAAG;MAAE9E;MAAYC,SAAS;KAAK,CAAC;IACpE,OACE,KAAK,MAAM6E,MAAMR,iBAAiBQ,GAAG;KAAE9E;KAAYC,SAAS;IAAM,CAAC;GAEvE;EACF,CAAC;EAEDkE,YAAY/C,iBAAiB,mBAAmB,CAC9C,CACD;EAED+C,YAAY/C,iBAAiB,aAAa;GAExC,IADsBoD,QAAQhF,OACZJ,SAAS,SACzBwF,aAAa;IAAExF,MAAM;IAASC,QAAQ;GAAU,CAAC;GAEnD,IAAIkF,iBAAiB;IACnB,KAAK,MAAMO,MAAMT,oBACfS,GAAG,EAAE9E,YAAYuE,gBAAgB,CAAC;IACpCA,kBAAkB;GACpB;EACF,CAAC;EAEDJ,YAAY/C,iBAAiB,UAAU2D,UAAU;GAC/C,MAAMI,aAAaJ;GACnB,IAAII,WAAW7F,UAAU,WACvBsF,aAAa;IAAExF,MAAM;IAASC,QAAQ;GAAY,CAAC;QAC9C;IACLuF,aAAa;KAAExF,MAAM;KAASC,QAAQ;IAAQ,CAAC;IAC/C+F,QAAQ9F,MAAM,oBAAoB6F,WAAW7F,OAAO6F,WAAW3C,OAAO;GACxE;EACF,CAAC;EAED,IAAI;GACF2B,YAAYrB,MAAM;EACpB,SAASxD,OAAO;GACdsF,aAAa;IAAExF,MAAM;IAASC,QAAQ;GAAQ,CAAC;GAC/C,MAAMC;EACR;EAEA,OAAOkF;CACT;AACF"}
1
+ {"version":3,"file":"speech.js","names":["Unsubscribe","SpeechSynthesisAdapter","Status","type","reason","error","Utterance","status","cancel","subscribe","callback","speak","text","notifySpeechSynthesisListeners","listeners","Iterable","listener","console","DictationAdapter","Result","transcript","isFinal","Session","stop","Promise","onSpeechStart","onSpeechEnd","result","onSpeech","listen","disableInputDuringDictation","WebSpeechSynthesisAdapter","utterance","SpeechSynthesisUtterance","subscribers","Set","handleEnd","res","addEventListener","e","window","speechSynthesis","cancelled","queueMicrotask","add","delete","SpeechRecognitionResultItem","confidence","SpeechRecognitionResult","length","item","index","SpeechRecognitionResultList","SpeechRecognitionEvent","Event","resultIndex","results","SpeechRecognitionErrorEvent","message","SpeechRecognitionInstance","EventTarget","lang","continuous","interimResults","start","abort","SpeechRecognitionConstructor","global","Window","SpeechRecognition","webkitSpeechRecognition","getSpeechRecognitionAPI","undefined","WebSpeechDictationAdapter","_language","_continuous","_interimResults","constructor","options","language","defaultLanguage","navigator","isSupported","SpeechRecognitionAPI","Error","recognition","speechStartCallbacks","speechEndCallbacks","speechCallbacks","finalTranscript","session","resolve","checkEnded","setTimeout","updateStatus","newStatus","cb","event","speechEvent","i","currentStatus","errorEvent"],"sources":["../../src/adapters/speech.ts"],"sourcesContent":["import type { Unsubscribe } from \"../types/unsubscribe\";\n\nexport namespace SpeechSynthesisAdapter {\n export type Status =\n | {\n type: \"starting\" | \"running\";\n }\n | {\n type: \"ended\";\n reason: \"finished\" | \"cancelled\" | \"error\";\n error?: unknown;\n };\n\n export type Utterance = {\n status: Status;\n cancel: () => void;\n subscribe: (callback: () => void) => Unsubscribe;\n };\n}\n\nexport type SpeechSynthesisAdapter = {\n speak: (text: string) => SpeechSynthesisAdapter.Utterance;\n};\n\nconst notifySpeechSynthesisListeners = (\n listeners: Iterable<() => void>,\n): void => {\n for (const listener of listeners) {\n try {\n listener();\n } catch (error) {\n console.error(\n \"[assistant-ui] Speech synthesis listener threw an error\",\n error,\n );\n }\n }\n};\n\nexport namespace DictationAdapter {\n export type Status =\n | {\n type: \"starting\" | \"running\";\n }\n | {\n type: \"ended\";\n reason: \"stopped\" | \"cancelled\" | \"error\";\n };\n\n export type Result = {\n transcript: string;\n isFinal?: boolean;\n };\n\n export type Session = {\n status: Status;\n stop: () => Promise<void>;\n cancel: () => void;\n onSpeechStart: (callback: () => void) => Unsubscribe;\n onSpeechEnd: (callback: (result: Result) => void) => Unsubscribe;\n onSpeech: (callback: (result: Result) => void) => Unsubscribe;\n };\n}\n\nexport type DictationAdapter = {\n listen: () => DictationAdapter.Session;\n disableInputDuringDictation?: boolean;\n};\n\nexport class WebSpeechSynthesisAdapter implements SpeechSynthesisAdapter {\n speak(text: string): SpeechSynthesisAdapter.Utterance {\n const utterance = new SpeechSynthesisUtterance(text);\n\n const subscribers = new Set<() => void>();\n const handleEnd = (\n reason: \"finished\" | \"error\" | \"cancelled\",\n error?: unknown,\n ) => {\n if (res.status.type === \"ended\") return;\n\n res.status = { type: \"ended\", reason, error };\n notifySpeechSynthesisListeners(subscribers);\n };\n\n utterance.addEventListener(\"end\", () => handleEnd(\"finished\"));\n utterance.addEventListener(\"error\", (e) => handleEnd(\"error\", e.error));\n\n window.speechSynthesis.speak(utterance);\n\n const res: SpeechSynthesisAdapter.Utterance = {\n status: { type: \"running\" },\n cancel: () => {\n window.speechSynthesis.cancel();\n handleEnd(\"cancelled\");\n },\n subscribe: (callback) => {\n if (res.status.type === \"ended\") {\n let cancelled = false;\n queueMicrotask(() => {\n if (!cancelled) notifySpeechSynthesisListeners([callback]);\n });\n return () => {\n cancelled = true;\n };\n } else {\n subscribers.add(callback);\n return () => {\n subscribers.delete(callback);\n };\n }\n },\n };\n return res;\n }\n}\n\ninterface SpeechRecognitionResultItem {\n transcript: string;\n confidence: number;\n}\n\ninterface SpeechRecognitionResult {\n readonly length: number;\n item(index: number): SpeechRecognitionResultItem;\n readonly isFinal: boolean;\n [index: number]: SpeechRecognitionResultItem;\n}\n\ninterface SpeechRecognitionResultList {\n readonly length: number;\n item(index: number): SpeechRecognitionResult;\n [index: number]: SpeechRecognitionResult;\n}\n\ninterface SpeechRecognitionEvent extends Event {\n readonly resultIndex: number;\n readonly results: SpeechRecognitionResultList;\n}\n\ninterface SpeechRecognitionErrorEvent extends Event {\n readonly error: string;\n readonly message: string;\n}\n\ninterface SpeechRecognitionInstance extends EventTarget {\n lang: string;\n continuous: boolean;\n interimResults: boolean;\n start(): void;\n stop(): void;\n abort(): void;\n}\n\ninterface SpeechRecognitionConstructor {\n new (): SpeechRecognitionInstance;\n}\n\ndeclare global {\n interface Window {\n SpeechRecognition?: SpeechRecognitionConstructor;\n webkitSpeechRecognition?: SpeechRecognitionConstructor;\n }\n}\n\nconst getSpeechRecognitionAPI = ():\n | SpeechRecognitionConstructor\n | undefined => {\n if (typeof window === \"undefined\") return undefined;\n return window.SpeechRecognition ?? window.webkitSpeechRecognition;\n};\n\nexport class WebSpeechDictationAdapter implements DictationAdapter {\n private _language: string;\n private _continuous: boolean;\n private _interimResults: boolean;\n\n constructor(\n options: {\n language?: string;\n continuous?: boolean;\n interimResults?: boolean;\n } = {},\n ) {\n const defaultLanguage =\n typeof navigator !== \"undefined\" && navigator.language\n ? navigator.language\n : \"en-US\";\n this._language = options.language ?? defaultLanguage;\n this._continuous = options.continuous ?? true;\n this._interimResults = options.interimResults ?? true;\n }\n\n static isSupported(): boolean {\n return getSpeechRecognitionAPI() !== undefined;\n }\n\n listen(): DictationAdapter.Session {\n const SpeechRecognitionAPI = getSpeechRecognitionAPI();\n if (!SpeechRecognitionAPI) {\n throw new Error(\n \"SpeechRecognition is not supported in this browser. \" +\n \"Try using Chrome, Edge, or Safari.\",\n );\n }\n\n const recognition = new SpeechRecognitionAPI();\n recognition.lang = this._language;\n recognition.continuous = this._continuous;\n recognition.interimResults = this._interimResults;\n\n const speechStartCallbacks = new Set<() => void>();\n const speechEndCallbacks = new Set<\n (result: DictationAdapter.Result) => void\n >();\n const speechCallbacks = new Set<\n (result: DictationAdapter.Result) => void\n >();\n\n let finalTranscript = \"\";\n\n const session: DictationAdapter.Session = {\n status: { type: \"starting\" },\n\n stop: async () => {\n recognition.stop();\n return new Promise<void>((resolve) => {\n const checkEnded = () => {\n if (session.status.type === \"ended\") {\n resolve();\n } else {\n setTimeout(checkEnded, 50);\n }\n };\n checkEnded();\n });\n },\n\n cancel: () => {\n recognition.abort();\n },\n\n onSpeechStart: (callback: () => void): Unsubscribe => {\n speechStartCallbacks.add(callback);\n return () => {\n speechStartCallbacks.delete(callback);\n };\n },\n\n onSpeechEnd: (\n callback: (result: DictationAdapter.Result) => void,\n ): Unsubscribe => {\n speechEndCallbacks.add(callback);\n return () => {\n speechEndCallbacks.delete(callback);\n };\n },\n\n onSpeech: (\n callback: (result: DictationAdapter.Result) => void,\n ): Unsubscribe => {\n speechCallbacks.add(callback);\n return () => {\n speechCallbacks.delete(callback);\n };\n },\n };\n\n const updateStatus = (newStatus: DictationAdapter.Status) => {\n session.status = newStatus;\n };\n\n recognition.addEventListener(\"speechstart\", () => {\n for (const cb of speechStartCallbacks) cb();\n });\n\n recognition.addEventListener(\"start\", () => {\n updateStatus({ type: \"running\" });\n });\n\n recognition.addEventListener(\"result\", (event) => {\n const speechEvent = event as unknown as SpeechRecognitionEvent;\n\n for (\n let i = speechEvent.resultIndex;\n i < speechEvent.results.length;\n i++\n ) {\n const result = speechEvent.results[i];\n if (!result) continue;\n\n const transcript = result[0]?.transcript ?? \"\";\n\n if (result.isFinal) {\n finalTranscript += transcript;\n for (const cb of speechCallbacks) cb({ transcript, isFinal: true });\n } else {\n for (const cb of speechCallbacks) cb({ transcript, isFinal: false });\n }\n }\n });\n\n recognition.addEventListener(\"speechend\", () => {\n // speechend fires when user stops speaking, but 'end' handles final cleanup\n });\n\n recognition.addEventListener(\"end\", () => {\n const currentStatus = session.status;\n if (currentStatus.type !== \"ended\") {\n updateStatus({ type: \"ended\", reason: \"stopped\" });\n }\n if (finalTranscript) {\n for (const cb of speechEndCallbacks)\n cb({ transcript: finalTranscript });\n finalTranscript = \"\";\n }\n });\n\n recognition.addEventListener(\"error\", (event) => {\n const errorEvent = event as unknown as SpeechRecognitionErrorEvent;\n if (errorEvent.error === \"aborted\") {\n updateStatus({ type: \"ended\", reason: \"cancelled\" });\n } else {\n updateStatus({ type: \"ended\", reason: \"error\" });\n console.error(\"Dictation error:\", errorEvent.error, errorEvent.message);\n }\n });\n\n try {\n recognition.start();\n } catch (error) {\n updateStatus({ type: \"ended\", reason: \"error\" });\n throw error;\n }\n\n return session;\n }\n}\n"],"mappings":"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"}
@@ -42,6 +42,14 @@ type ThreadHistoryAdapter = {
42
42
  }>;
43
43
  resume?(options: ChatModelRunOptions): AsyncGenerator<ChatModelRunResult, void, unknown>;
44
44
  append(item: ExportedMessageRepositoryItem): Promise<void>;
45
+ /**
46
+ * Rewrites a previously appended message in place, keyed by its message id.
47
+ * Adapters that implement this let a runtime persist a run paused for tool
48
+ * approval and finalize the same message once the run resumes. An update may
49
+ * arrive for an id whose earlier write failed; treat it as an upsert keyed
50
+ * on the message id rather than assuming the entry exists.
51
+ */
52
+ update?(item: ExportedMessageRepositoryItem): Promise<void>;
45
53
  delete?(items: ExportedMessageRepositoryItem[]): Promise<void>;
46
54
  /** Required when used with `useAISDKRuntime` / `useChatRuntime`. */
47
55
  withFormat?<TMessage, TStorageFormat extends Record<string, unknown>>(formatAdapter: MessageFormatAdapter<TMessage, TStorageFormat>): GenericThreadHistoryAdapter<TMessage>;
@@ -1 +1 @@
1
- {"version":3,"file":"thread-history.d.ts","names":[],"sources":["../../src/adapters/thread-history.ts"],"mappings":";;;;UAUiB,oBAAoB;EACnC;EACA;EACA;EACA,SAAS;;UAGM,kBAAkB;EACjC;EACA,SAAS;;UAGM,wBAAwB;EACvC;EACA,UAAU,kBAAkB;;UAGb,qBACf,UACA,uBAAuB;EAEvB;EACA,OAAO,MAAM,kBAAkB,YAAY;EAC3C,OACE,QAAQ,oBAAoB,kBAC3B,kBAAkB;EACrB,MAAM,SAAS;;KAGL,4BAA4B;EACtC,QAAQ,QAAQ,wBAAwB;EACxC,OAAO,MAAM,kBAAkB,YAAY;EAC3C,QACE,MAAM,kBAAkB,WACxB,yBACC;EACH,QAAQ,OAAO,kBAAkB,cAAc;EAC/C,iBACE,OAAO,kBAAkB,aACzB;IACE;IACA;MAAmB;MAAkB;;;;KAK/B;EACV,QAAQ,QACN;IACE,QAAQ;IACR;;EAGJ,QACE,SAAS,sBACR,eAAe;EAClB,OAAO,MAAM,gCAAgC;EAC7C,QAAQ,OAAO,kCAAkC;;EAEjD,YAAY,UAAU,uBAAuB,yBAC3C,eAAe,qBAAqB,UAAU,kBAC7C,4BAA4B"}
1
+ {"version":3,"file":"thread-history.d.ts","names":[],"sources":["../../src/adapters/thread-history.ts"],"mappings":";;;;UAUiB,oBAAoB;EACnC;EACA;EACA;EACA,SAAS;;UAGM,kBAAkB;EACjC;EACA,SAAS;;UAGM,wBAAwB;EACvC;EACA,UAAU,kBAAkB;;UAGb,qBACf,UACA,uBAAuB;EAEvB;EACA,OAAO,MAAM,kBAAkB,YAAY;EAC3C,OACE,QAAQ,oBAAoB,kBAC3B,kBAAkB;EACrB,MAAM,SAAS;;KAGL,4BAA4B;EACtC,QAAQ,QAAQ,wBAAwB;EACxC,OAAO,MAAM,kBAAkB,YAAY;EAC3C,QACE,MAAM,kBAAkB,WACxB,yBACC;EACH,QAAQ,OAAO,kBAAkB,cAAc;EAC/C,iBACE,OAAO,kBAAkB,aACzB;IACE;IACA;MAAmB;MAAkB;;;;KAK/B;EACV,QAAQ,QACN;IACE,QAAQ;IACR;;EAGJ,QACE,SAAS,sBACR,eAAe;EAClB,OAAO,MAAM,gCAAgC;;;;;;;;EAQ7C,QAAQ,MAAM,gCAAgC;EAC9C,QAAQ,OAAO,kCAAkC;;EAEjD,YAAY,UAAU,uBAAuB,yBAC3C,eAAe,qBAAqB,UAAU,kBAC7C,4BAA4B"}
@@ -1 +1 @@
1
- {"version":3,"file":"voice.d.ts","names":[],"sources":["../../src/adapters/voice.ts"],"mappings":";;kBAEiB;OACH;IAEN;;IAGA;IACA;IACA;;OAGM;OAEA;IACV;IACA;IACA;;OAGU;IACV,QAAQ;IACR;IAEA;IACA;IACA;IAEA,iBAAiB,WAAW,QAAQ,oBAAoB;IACxD,eACE,WAAW,YAAY,4BACpB;IACL,eAAe,WAAW,MAAM,kBAAkB;IAClD,iBAAiB,WAAW,4BAA4B;;;KAIhD;EACV,UAAU;IACR,cAAc;QACV,qBAAqB;;KAGjB;EACV;EACA;EACA;;KAGU;EACV,YAAY,QAAQ,qBAAqB;EACzC,MAAM,4CAA4C;EAClD,iBAAiB,MAAM,qBAAqB;EAC5C,WAAW,MAAM,qBAAqB;EACtC,aAAa;EACb;;iBAGc,mBACd;EAAW,cAAc;GACzB,QAAQ,SAAS,wBAAwB,QAAQ,wBAChD,qBAAqB"}
1
+ {"version":3,"file":"voice.d.ts","names":[],"sources":["../../src/adapters/voice.ts"],"mappings":";;kBAEiB;OACH;IAEN;;IAGA;IACA;IACA;;OAGM;OAEA;IACV;IACA;IACA;;OAGU;IACV,QAAQ;IACR;IAEA;IACA;IACA;IAEA,iBAAiB,WAAW,QAAQ,oBAAoB;IACxD,eACE,WAAW,YAAY,4BACpB;IACL,eAAe,WAAW,MAAM,kBAAkB;IAClD,iBAAiB,WAAW,4BAA4B;;;KAIhD;EACV,UAAU;IACR,cAAc;QACV,qBAAqB;;KAGjB;EACV;EACA;EACA;;KAGU;EACV,YAAY,QAAQ,qBAAqB;EACzC,MAAM,4CAA4C;EAClD,iBAAiB,MAAM,qBAAqB;EAC5C,WAAW,MAAM,qBAAqB;EACtC,aAAa;EACb;;iBAmBc,mBACd;EAAW,cAAc;GACzB,QAAQ,SAAS,wBAAwB,QAAQ,wBAChD,qBAAqB"}
@@ -1,4 +1,11 @@
1
1
  //#region src/adapters/voice.ts
2
+ const notifyListeners = (listeners, value) => {
3
+ for (const listener of listeners) try {
4
+ listener(value);
5
+ } catch (error) {
6
+ console.error("[assistant-ui] Voice session listener threw an error", error);
7
+ }
8
+ };
2
9
  function createVoiceSession(options, setup) {
3
10
  const statusCbs = /* @__PURE__ */ new Set();
4
11
  const transcriptCbs = /* @__PURE__ */ new Set();
@@ -19,7 +26,7 @@ function createVoiceSession(options, setup) {
19
26
  setStatus: (status) => {
20
27
  if (disposed) return;
21
28
  currentStatus = status;
22
- for (const cb of statusCbs) cb(status);
29
+ notifyListeners(statusCbs, status);
23
30
  },
24
31
  end: (reason, error) => {
25
32
  if (disposed) return;
@@ -28,20 +35,20 @@ function createVoiceSession(options, setup) {
28
35
  reason,
29
36
  error
30
37
  };
31
- for (const cb of statusCbs) cb(currentStatus);
38
+ notifyListeners(statusCbs, currentStatus);
32
39
  cleanup();
33
40
  },
34
41
  emitTranscript: (item) => {
35
42
  if (disposed) return;
36
- for (const cb of transcriptCbs) cb(item);
43
+ notifyListeners(transcriptCbs, item);
37
44
  },
38
45
  emitMode: (mode) => {
39
46
  if (disposed) return;
40
- for (const cb of modeCbs) cb(mode);
47
+ notifyListeners(modeCbs, mode);
41
48
  },
42
49
  emitVolume: (volume) => {
43
50
  if (disposed) return;
44
- for (const cb of volumeCbs) cb(volume);
51
+ notifyListeners(volumeCbs, volume);
45
52
  },
46
53
  isDisposed: () => disposed
47
54
  };
@@ -87,6 +94,7 @@ function createVoiceSession(options, setup) {
87
94
  if (disposed) return;
88
95
  controls = await setup(helpers);
89
96
  if (disposed) controls.disconnect();
97
+ else if (isMuted) controls.mute();
90
98
  } catch (error) {
91
99
  helpers.end("error", error);
92
100
  }
@@ -1 +1 @@
1
- {"version":3,"file":"voice.js","names":["Unsubscribe","RealtimeVoiceAdapter","Status","type","reason","error","Mode","TranscriptItem","role","text","isFinal","Session","status","isMuted","disconnect","mute","unmute","onStatusChange","callback","onTranscript","transcript","onModeChange","mode","onVolumeChange","volume","connect","options","abortSignal","AbortSignal","VoiceSessionControls","VoiceSessionHelpers","setStatus","end","emitTranscript","item","emitMode","emitVolume","isDisposed","createVoiceSession","setup","helpers","Promise","statusCbs","Set","s","transcriptCbs","t","modeCbs","m","volumeCbs","v","currentStatus","disposed","controls","cleanup","clear","cb","session","add","delete","addEventListener","once","doSetup"],"sources":["../../src/adapters/voice.ts"],"sourcesContent":["import type { Unsubscribe } from \"../types/unsubscribe\";\n\nexport namespace RealtimeVoiceAdapter {\n export type Status =\n | {\n type: \"starting\" | \"running\";\n }\n | {\n type: \"ended\";\n reason: \"finished\" | \"cancelled\" | \"error\";\n error?: unknown;\n };\n\n export type Mode = \"listening\" | \"speaking\";\n\n export type TranscriptItem = {\n role: \"user\" | \"assistant\";\n text: string;\n isFinal?: boolean;\n };\n\n export type Session = {\n status: Status;\n isMuted: boolean;\n\n disconnect: () => void;\n mute: () => void;\n unmute: () => void;\n\n onStatusChange: (callback: (status: Status) => void) => Unsubscribe;\n onTranscript: (\n callback: (transcript: TranscriptItem) => void,\n ) => Unsubscribe;\n onModeChange: (callback: (mode: Mode) => void) => Unsubscribe;\n onVolumeChange: (callback: (volume: number) => void) => Unsubscribe;\n };\n}\n\nexport type RealtimeVoiceAdapter = {\n connect: (options: {\n abortSignal?: AbortSignal;\n }) => RealtimeVoiceAdapter.Session;\n};\n\nexport type VoiceSessionControls = {\n disconnect: () => void;\n mute: () => void;\n unmute: () => void;\n};\n\nexport type VoiceSessionHelpers = {\n setStatus: (status: RealtimeVoiceAdapter.Status) => void;\n end: (reason: \"finished\" | \"cancelled\" | \"error\", error?: unknown) => void;\n emitTranscript: (item: RealtimeVoiceAdapter.TranscriptItem) => void;\n emitMode: (mode: RealtimeVoiceAdapter.Mode) => void;\n emitVolume: (volume: number) => void;\n isDisposed: () => boolean;\n};\n\nexport function createVoiceSession(\n options: { abortSignal?: AbortSignal },\n setup: (helpers: VoiceSessionHelpers) => Promise<VoiceSessionControls>,\n): RealtimeVoiceAdapter.Session {\n const statusCbs = new Set<(s: RealtimeVoiceAdapter.Status) => void>();\n const transcriptCbs = new Set<\n (t: RealtimeVoiceAdapter.TranscriptItem) => void\n >();\n const modeCbs = new Set<(m: RealtimeVoiceAdapter.Mode) => void>();\n const volumeCbs = new Set<(v: number) => void>();\n\n let currentStatus: RealtimeVoiceAdapter.Status = { type: \"starting\" };\n let isMuted = false;\n let disposed = false;\n let controls: VoiceSessionControls | null = null;\n\n const cleanup = () => {\n disposed = true;\n statusCbs.clear();\n transcriptCbs.clear();\n modeCbs.clear();\n volumeCbs.clear();\n };\n\n const helpers: VoiceSessionHelpers = {\n setStatus: (status) => {\n if (disposed) return;\n currentStatus = status;\n for (const cb of statusCbs) cb(status);\n },\n end: (reason, error?) => {\n if (disposed) return;\n currentStatus = { type: \"ended\", reason, error };\n for (const cb of statusCbs) cb(currentStatus);\n cleanup();\n },\n emitTranscript: (item) => {\n if (disposed) return;\n for (const cb of transcriptCbs) cb(item);\n },\n emitMode: (mode) => {\n if (disposed) return;\n for (const cb of modeCbs) cb(mode);\n },\n emitVolume: (volume) => {\n if (disposed) return;\n for (const cb of volumeCbs) cb(volume);\n },\n isDisposed: () => disposed,\n };\n\n const session: RealtimeVoiceAdapter.Session = {\n get status() {\n return currentStatus;\n },\n get isMuted() {\n return isMuted;\n },\n disconnect: () => {\n controls?.disconnect();\n cleanup();\n },\n mute: () => {\n controls?.mute();\n isMuted = true;\n },\n unmute: () => {\n controls?.unmute();\n isMuted = false;\n },\n onStatusChange: (cb) => {\n statusCbs.add(cb);\n return () => statusCbs.delete(cb);\n },\n onTranscript: (cb) => {\n transcriptCbs.add(cb);\n return () => transcriptCbs.delete(cb);\n },\n onModeChange: (cb) => {\n modeCbs.add(cb);\n return () => modeCbs.delete(cb);\n },\n onVolumeChange: (cb) => {\n volumeCbs.add(cb);\n return () => volumeCbs.delete(cb);\n },\n };\n\n if (options.abortSignal) {\n options.abortSignal.addEventListener(\"abort\", () => session.disconnect(), {\n once: true,\n });\n }\n\n const doSetup = async () => {\n try {\n if (disposed) return;\n controls = await setup(helpers);\n if (disposed) controls.disconnect();\n } catch (error) {\n helpers.end(\"error\", error);\n }\n };\n\n doSetup();\n return session;\n}\n"],"mappings":";AA2DA,SAAgBsC,mBACdZ,SACAa,OAC8B;CAC9B,MAAMG,4BAAY,IAAIC,IAA8C;CACpE,MAAME,gCAAgB,IAAIF,IAExB;CACF,MAAMI,0BAAU,IAAIJ,IAA4C;CAChE,MAAMM,4BAAY,IAAIN,IAAyB;CAE/C,IAAIQ,gBAA6C,EAAEhD,MAAM,WAAW;CACpE,IAAIU,UAAU;CACd,IAAIuC,WAAW;CACf,IAAIC,WAAwC;CAE5C,MAAMC,gBAAgB;EACpBF,WAAW;EACXV,UAAUa,MAAM;EAChBV,cAAcU,MAAM;EACpBR,QAAQQ,MAAM;EACdN,UAAUM,MAAM;CAClB;CAEA,MAAMf,UAA+B;EACnCT,YAAYnB,WAAW;GACrB,IAAIwC,UAAU;GACdD,gBAAgBvC;GAChB,KAAK,MAAM4C,MAAMd,WAAWc,GAAG5C,MAAM;EACvC;EACAoB,MAAM5B,QAAQC,UAAW;GACvB,IAAI+C,UAAU;GACdD,gBAAgB;IAAEhD,MAAM;IAASC;IAAQC;GAAM;GAC/C,KAAK,MAAMmD,MAAMd,WAAWc,GAAGL,aAAa;GAC5CG,QAAQ;EACV;EACArB,iBAAiBC,SAAS;GACxB,IAAIkB,UAAU;GACd,KAAK,MAAMI,MAAMX,eAAeW,GAAGtB,IAAI;EACzC;EACAC,WAAWb,SAAS;GAClB,IAAI8B,UAAU;GACd,KAAK,MAAMI,MAAMT,SAASS,GAAGlC,IAAI;EACnC;EACAc,aAAaZ,WAAW;GACtB,IAAI4B,UAAU;GACd,KAAK,MAAMI,MAAMP,WAAWO,GAAGhC,MAAM;EACvC;EACAa,kBAAkBe;CACpB;CAEA,MAAMK,UAAwC;EAC5C,IAAI7C,SAAS;GACX,OAAOuC;EACT;EACA,IAAItC,UAAU;GACZ,OAAOA;EACT;EACAC,kBAAkB;GAChBuC,UAAUvC,WAAW;GACrBwC,QAAQ;EACV;EACAvC,YAAY;GACVsC,UAAUtC,KAAK;GACfF,UAAU;EACZ;EACAG,cAAc;GACZqC,UAAUrC,OAAO;GACjBH,UAAU;EACZ;EACAI,iBAAiBuC,OAAO;GACtBd,UAAUgB,IAAIF,EAAE;GAChB,aAAad,UAAUiB,OAAOH,EAAE;EAClC;EACArC,eAAeqC,OAAO;GACpBX,cAAca,IAAIF,EAAE;GACpB,aAAaX,cAAcc,OAAOH,EAAE;EACtC;EACAnC,eAAemC,OAAO;GACpBT,QAAQW,IAAIF,EAAE;GACd,aAAaT,QAAQY,OAAOH,EAAE;EAChC;EACAjC,iBAAiBiC,OAAO;GACtBP,UAAUS,IAAIF,EAAE;GAChB,aAAaP,UAAUU,OAAOH,EAAE;EAClC;CACF;CAEA,IAAI9B,QAAQC,aACVD,QAAQC,YAAYiC,iBAAiB,eAAeH,QAAQ3C,WAAW,GAAG,EACxE+C,MAAM,KACR,CAAC;CAGH,MAAMC,UAAU,YAAY;EAC1B,IAAI;GACF,IAAIV,UAAU;GACdC,WAAW,MAAMd,MAAMC,OAAO;GAC9B,IAAIY,UAAUC,SAASvC,WAAW;EACpC,SAAST,OAAO;GACdmC,QAAQR,IAAI,SAAS3B,KAAK;EAC5B;CACF;CAEAyD,QAAQ;CACR,OAAOL;AACT"}
1
+ {"version":3,"file":"voice.js","names":["Unsubscribe","RealtimeVoiceAdapter","Status","type","reason","error","Mode","TranscriptItem","role","text","isFinal","Session","status","isMuted","disconnect","mute","unmute","onStatusChange","callback","onTranscript","transcript","onModeChange","mode","onVolumeChange","volume","connect","options","abortSignal","AbortSignal","VoiceSessionControls","VoiceSessionHelpers","setStatus","end","emitTranscript","item","emitMode","emitVolume","isDisposed","notifyListeners","listeners","ReadonlySet","value","T","listener","console","createVoiceSession","setup","helpers","Promise","statusCbs","Set","s","transcriptCbs","t","modeCbs","m","volumeCbs","v","currentStatus","disposed","controls","cleanup","clear","session","cb","add","delete","addEventListener","once","doSetup"],"sources":["../../src/adapters/voice.ts"],"sourcesContent":["import type { Unsubscribe } from \"../types/unsubscribe\";\n\nexport namespace RealtimeVoiceAdapter {\n export type Status =\n | {\n type: \"starting\" | \"running\";\n }\n | {\n type: \"ended\";\n reason: \"finished\" | \"cancelled\" | \"error\";\n error?: unknown;\n };\n\n export type Mode = \"listening\" | \"speaking\";\n\n export type TranscriptItem = {\n role: \"user\" | \"assistant\";\n text: string;\n isFinal?: boolean;\n };\n\n export type Session = {\n status: Status;\n isMuted: boolean;\n\n disconnect: () => void;\n mute: () => void;\n unmute: () => void;\n\n onStatusChange: (callback: (status: Status) => void) => Unsubscribe;\n onTranscript: (\n callback: (transcript: TranscriptItem) => void,\n ) => Unsubscribe;\n onModeChange: (callback: (mode: Mode) => void) => Unsubscribe;\n onVolumeChange: (callback: (volume: number) => void) => Unsubscribe;\n };\n}\n\nexport type RealtimeVoiceAdapter = {\n connect: (options: {\n abortSignal?: AbortSignal;\n }) => RealtimeVoiceAdapter.Session;\n};\n\nexport type VoiceSessionControls = {\n disconnect: () => void;\n mute: () => void;\n unmute: () => void;\n};\n\nexport type VoiceSessionHelpers = {\n setStatus: (status: RealtimeVoiceAdapter.Status) => void;\n end: (reason: \"finished\" | \"cancelled\" | \"error\", error?: unknown) => void;\n emitTranscript: (item: RealtimeVoiceAdapter.TranscriptItem) => void;\n emitMode: (mode: RealtimeVoiceAdapter.Mode) => void;\n emitVolume: (volume: number) => void;\n isDisposed: () => boolean;\n};\n\nconst notifyListeners = <T>(\n listeners: ReadonlySet<(value: T) => void>,\n value: T,\n) => {\n for (const listener of listeners) {\n try {\n listener(value);\n } catch (error) {\n console.error(\n \"[assistant-ui] Voice session listener threw an error\",\n error,\n );\n }\n }\n};\n\nexport function createVoiceSession(\n options: { abortSignal?: AbortSignal },\n setup: (helpers: VoiceSessionHelpers) => Promise<VoiceSessionControls>,\n): RealtimeVoiceAdapter.Session {\n const statusCbs = new Set<(s: RealtimeVoiceAdapter.Status) => void>();\n const transcriptCbs = new Set<\n (t: RealtimeVoiceAdapter.TranscriptItem) => void\n >();\n const modeCbs = new Set<(m: RealtimeVoiceAdapter.Mode) => void>();\n const volumeCbs = new Set<(v: number) => void>();\n\n let currentStatus: RealtimeVoiceAdapter.Status = { type: \"starting\" };\n let isMuted = false;\n let disposed = false;\n let controls: VoiceSessionControls | null = null;\n\n const cleanup = () => {\n disposed = true;\n statusCbs.clear();\n transcriptCbs.clear();\n modeCbs.clear();\n volumeCbs.clear();\n };\n\n const helpers: VoiceSessionHelpers = {\n setStatus: (status) => {\n if (disposed) return;\n currentStatus = status;\n notifyListeners(statusCbs, status);\n },\n end: (reason, error?) => {\n if (disposed) return;\n currentStatus = { type: \"ended\", reason, error };\n notifyListeners(statusCbs, currentStatus);\n cleanup();\n },\n emitTranscript: (item) => {\n if (disposed) return;\n notifyListeners(transcriptCbs, item);\n },\n emitMode: (mode) => {\n if (disposed) return;\n notifyListeners(modeCbs, mode);\n },\n emitVolume: (volume) => {\n if (disposed) return;\n notifyListeners(volumeCbs, volume);\n },\n isDisposed: () => disposed,\n };\n\n const session: RealtimeVoiceAdapter.Session = {\n get status() {\n return currentStatus;\n },\n get isMuted() {\n return isMuted;\n },\n disconnect: () => {\n controls?.disconnect();\n cleanup();\n },\n mute: () => {\n controls?.mute();\n isMuted = true;\n },\n unmute: () => {\n controls?.unmute();\n isMuted = false;\n },\n onStatusChange: (cb) => {\n statusCbs.add(cb);\n return () => statusCbs.delete(cb);\n },\n onTranscript: (cb) => {\n transcriptCbs.add(cb);\n return () => transcriptCbs.delete(cb);\n },\n onModeChange: (cb) => {\n modeCbs.add(cb);\n return () => modeCbs.delete(cb);\n },\n onVolumeChange: (cb) => {\n volumeCbs.add(cb);\n return () => volumeCbs.delete(cb);\n },\n };\n\n if (options.abortSignal) {\n options.abortSignal.addEventListener(\"abort\", () => session.disconnect(), {\n once: true,\n });\n }\n\n const doSetup = async () => {\n try {\n if (disposed) return;\n controls = await setup(helpers);\n if (disposed) {\n controls.disconnect();\n } else if (isMuted) {\n controls.mute();\n }\n } catch (error) {\n helpers.end(\"error\", error);\n }\n };\n\n doSetup();\n return session;\n}\n"],"mappings":";AA2DA,MAAMsC,mBACJC,WACAE,UACG;CACH,KAAK,MAAME,YAAYJ,WACrB,IAAI;EACFI,SAASF,KAAK;CAChB,SAASpC,OAAO;EACduC,QAAQvC,MACN,wDACAA,KACF;CACF;AAEJ;AAEA,SAAgBwC,mBACdnB,SACAoB,OAC8B;CAC9B,MAAMG,4BAAY,IAAIC,IAA8C;CACpE,MAAME,gCAAgB,IAAIF,IAExB;CACF,MAAMI,0BAAU,IAAIJ,IAA4C;CAChE,MAAMM,4BAAY,IAAIN,IAAyB;CAE/C,IAAIQ,gBAA6C,EAAEvD,MAAM,WAAW;CACpE,IAAIU,UAAU;CACd,IAAI8C,WAAW;CACf,IAAIC,WAAwC;CAE5C,MAAMC,gBAAgB;EACpBF,WAAW;EACXV,UAAUa,MAAM;EAChBV,cAAcU,MAAM;EACpBR,QAAQQ,MAAM;EACdN,UAAUM,MAAM;CAClB;CAEA,MAAMf,UAA+B;EACnChB,YAAYnB,WAAW;GACrB,IAAI+C,UAAU;GACdD,gBAAgB9C;GAChB0B,gBAAgBW,WAAWrC,MAAM;EACnC;EACAoB,MAAM5B,QAAQC,UAAW;GACvB,IAAIsD,UAAU;GACdD,gBAAgB;IAAEvD,MAAM;IAASC;IAAQC;GAAM;GAC/CiC,gBAAgBW,WAAWS,aAAa;GACxCG,QAAQ;EACV;EACA5B,iBAAiBC,SAAS;GACxB,IAAIyB,UAAU;GACdrB,gBAAgBc,eAAelB,IAAI;EACrC;EACAC,WAAWb,SAAS;GAClB,IAAIqC,UAAU;GACdrB,gBAAgBgB,SAAShC,IAAI;EAC/B;EACAc,aAAaZ,WAAW;GACtB,IAAImC,UAAU;GACdrB,gBAAgBkB,WAAWhC,MAAM;EACnC;EACAa,kBAAkBsB;CACpB;CAEA,MAAMI,UAAwC;EAC5C,IAAInD,SAAS;GACX,OAAO8C;EACT;EACA,IAAI7C,UAAU;GACZ,OAAOA;EACT;EACAC,kBAAkB;GAChB8C,UAAU9C,WAAW;GACrB+C,QAAQ;EACV;EACA9C,YAAY;GACV6C,UAAU7C,KAAK;GACfF,UAAU;EACZ;EACAG,cAAc;GACZ4C,UAAU5C,OAAO;GACjBH,UAAU;EACZ;EACAI,iBAAiB+C,OAAO;GACtBf,UAAUgB,IAAID,EAAE;GAChB,aAAaf,UAAUiB,OAAOF,EAAE;EAClC;EACA7C,eAAe6C,OAAO;GACpBZ,cAAca,IAAID,EAAE;GACpB,aAAaZ,cAAcc,OAAOF,EAAE;EACtC;EACA3C,eAAe2C,OAAO;GACpBV,QAAQW,IAAID,EAAE;GACd,aAAaV,QAAQY,OAAOF,EAAE;EAChC;EACAzC,iBAAiByC,OAAO;GACtBR,UAAUS,IAAID,EAAE;GAChB,aAAaR,UAAUU,OAAOF,EAAE;EAClC;CACF;CAEA,IAAItC,QAAQC,aACVD,QAAQC,YAAYwC,iBAAiB,eAAeJ,QAAQjD,WAAW,GAAG,EACxEsD,MAAM,KACR,CAAC;CAGH,MAAMC,UAAU,YAAY;EAC1B,IAAI;GACF,IAAIV,UAAU;GACdC,WAAW,MAAMd,MAAMC,OAAO;GAC9B,IAAIY,UACFC,SAAS9C,WAAW;QACf,IAAID,SACT+C,SAAS7C,KAAK;EAElB,SAASV,OAAO;GACd0C,QAAQf,IAAI,SAAS3B,KAAK;EAC5B;CACF;CAEAgE,QAAQ;CACR,OAAON;AACT"}
@@ -1,7 +1,9 @@
1
- import { getFileDataURL } from "./adapters/attachment.js";
1
+ import { isCreateAttachment } from "./types/attachment.js";
2
+ import { fileMatchesAccept, getFileDataURL } from "./adapters/attachment.js";
2
3
  import { fromThreadMessageLike } from "./runtime/utils/thread-message-like.js";
3
4
  import { ExportedMessageRepository, ExportedMessageRepositoryItem, MessageRepository } from "./runtime/utils/message-repository.js";
4
5
  import { consumeSuggestionResult } from "./adapters/suggestion.js";
6
+ import { ToolInvocationTracker } from "./runtimes/tool-invocations/ToolInvocationTracker.js";
5
7
  import { BaseSubject, BaseSubscribable, EventSubscribable, EventSubscriptionSubject, LazyMemoizeSubject, NestedSubscribable, NestedSubscriptionSubject, SKIP_UPDATE, ShallowMemoizeSubject, Subscribable, SubscribableWithState } from "./subscribable/subscribable.js";
6
8
  import { generateErrorMessageId, generateId, isErrorMessageId } from "./utils/id.js";
7
9
  import { getThreadMessageText } from "./utils/text.js";
@@ -9,6 +11,7 @@ import { resolveToolApprovalResponse } from "./runtime/utils/resolveToolApproval
9
11
  import { CompositeContextProvider } from "./utils/composite-context-provider.js";
10
12
  import { stableStringifyToolArgs, trackToolArgsKeyOrder } from "./utils/json/stable-stringify-tool-args.js";
11
13
  import { isJSONValue, isRecord } from "./utils/json/is-json.js";
14
+ import { httpUrlPattern, parseDataUrl } from "./utils/data-url.js";
12
15
  import { RuntimeExtras, createRuntimeExtras } from "./react/runtimes/createRuntimeExtras.js";
13
16
  import { ComposerRuntimeCoreBinding, EditComposerRuntimeCoreBinding, MessageStateBinding, ThreadComposerRuntimeCoreBinding } from "./runtime/api/bindings.js";
14
17
  import { BaseAssistantRuntimeCore } from "./runtime/base/base-assistant-runtime-core.js";
@@ -42,4 +45,4 @@ import { RemoteThreadData, RemoteThreadState, THREAD_MAPPING_ID, createThreadMap
42
45
  import "./runtimes/internal.js";
43
46
  import { ThreadListItemRuntimeBinding, ThreadRuntimeCoreBinding, ThreadRuntimeImpl, getThreadState } from "./runtime/api/thread-runtime.js";
44
47
  import { AssistantRuntimeImpl } from "./runtime/api/assistant-runtime.js";
45
- export { AssistantRuntimeImpl, AttachmentRuntimeImpl, BaseAssistantRuntimeCore, BaseComposerRuntimeCore, BaseSubject, BaseSubscribable, BaseThreadRuntimeCore, type ComposerRuntimeCoreBinding, ComposerRuntimeImpl, CompositeContextProvider, type ConverterCallback, DefaultEditComposerRuntimeCore, DefaultThreadComposerRuntimeCore, EMPTY_THREAD_CORE, EditComposerAttachmentRuntimeImpl, type EditComposerRuntimeCoreBinding, EditComposerRuntimeImpl, type EventSubscribable, EventSubscriptionSubject, ExportedMessageRepository, type ExportedMessageRepositoryItem, ExternalStoreRuntimeCore, type ExternalStoreThreadFactory, ExternalStoreThreadListRuntimeCore, ExternalStoreThreadRuntimeCore, LazyMemoizeSubject, LocalRuntimeCore, type LocalRuntimeOptionsBase, type LocalThreadFactory, LocalThreadListRuntimeCore, LocalThreadRuntimeCore, MessageAttachmentRuntimeImpl, MessagePartRuntimeImpl, MessageRepository, MessageRuntimeImpl, type MessageStateBinding, type NestedSubscribable, NestedSubscriptionSubject, OptimisticState, ReadonlyThreadRuntimeCore, type RemoteThreadData, type RemoteThreadInitializeResponse, type RemoteThreadListOptions, type RemoteThreadState, type RuntimeExtras, SKIP_UPDATE, type SKIP_UPDATE as SKIP_UPDATE_TYPE, ShallowMemoizeSubject, type Subscribable, type SubscribableWithState, type THREAD_MAPPING_ID, ThreadComposerAttachmentRuntimeImpl, type ThreadComposerRuntimeCoreBinding, ThreadComposerRuntimeImpl, type ThreadListItemRuntimeBinding, ThreadListItemRuntimeImpl, type ThreadListItemStateBinding, type ThreadListRuntimeCoreBinding, ThreadListRuntimeImpl, ThreadMessageConverter, type ThreadRuntimeCoreBinding, ThreadRuntimeImpl, consumeSuggestionResult, createRuntimeExtras, createThreadMappingId, fromThreadMessageLike, generateErrorMessageId, generateId, getAutoStatus, getFileDataURL, getThreadData, getThreadMessageText, getThreadState, hasUpcomingMessage, isAutoStatus, isErrorMessageId, isJSONValue, isRecord, resolveToolApprovalResponse, shouldContinue, stableStringifyToolArgs, symbolInnerMessage, trackToolArgsKeyOrder, updateStatusReducer };
48
+ export { AssistantRuntimeImpl, AttachmentRuntimeImpl, BaseAssistantRuntimeCore, BaseComposerRuntimeCore, BaseSubject, BaseSubscribable, BaseThreadRuntimeCore, type ComposerRuntimeCoreBinding, ComposerRuntimeImpl, CompositeContextProvider, type ConverterCallback, DefaultEditComposerRuntimeCore, DefaultThreadComposerRuntimeCore, EMPTY_THREAD_CORE, EditComposerAttachmentRuntimeImpl, type EditComposerRuntimeCoreBinding, EditComposerRuntimeImpl, type EventSubscribable, EventSubscriptionSubject, ExportedMessageRepository, type ExportedMessageRepositoryItem, ExternalStoreRuntimeCore, type ExternalStoreThreadFactory, ExternalStoreThreadListRuntimeCore, ExternalStoreThreadRuntimeCore, LazyMemoizeSubject, LocalRuntimeCore, type LocalRuntimeOptionsBase, type LocalThreadFactory, LocalThreadListRuntimeCore, LocalThreadRuntimeCore, MessageAttachmentRuntimeImpl, MessagePartRuntimeImpl, MessageRepository, MessageRuntimeImpl, type MessageStateBinding, type NestedSubscribable, NestedSubscriptionSubject, OptimisticState, ReadonlyThreadRuntimeCore, type RemoteThreadData, type RemoteThreadInitializeResponse, type RemoteThreadListOptions, type RemoteThreadState, type RuntimeExtras, SKIP_UPDATE, type SKIP_UPDATE as SKIP_UPDATE_TYPE, ShallowMemoizeSubject, type Subscribable, type SubscribableWithState, type THREAD_MAPPING_ID, ThreadComposerAttachmentRuntimeImpl, type ThreadComposerRuntimeCoreBinding, ThreadComposerRuntimeImpl, type ThreadListItemRuntimeBinding, ThreadListItemRuntimeImpl, type ThreadListItemStateBinding, type ThreadListRuntimeCoreBinding, ThreadListRuntimeImpl, ThreadMessageConverter, type ThreadRuntimeCoreBinding, ThreadRuntimeImpl, ToolInvocationTracker, consumeSuggestionResult, createRuntimeExtras, createThreadMappingId, fileMatchesAccept, fromThreadMessageLike, generateErrorMessageId, generateId, getAutoStatus, getFileDataURL, getThreadData, getThreadMessageText, getThreadState, hasUpcomingMessage, httpUrlPattern, isAutoStatus, isCreateAttachment, isErrorMessageId, isJSONValue, isRecord, parseDataUrl, resolveToolApprovalResponse, shouldContinue, stableStringifyToolArgs, symbolInnerMessage, trackToolArgsKeyOrder, updateStatusReducer };
package/dist/internal.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { isJSONValue, isRecord } from "./utils/json/is-json.js";
2
2
  import { generateErrorMessageId, generateId, isErrorMessageId } from "./utils/id.js";
3
- import { getFileDataURL } from "./adapters/attachment.js";
3
+ import { fileMatchesAccept, getFileDataURL } from "./adapters/attachment.js";
4
4
  import { getThreadMessageText } from "./utils/text.js";
5
5
  import { consumeSuggestionResult } from "./adapters/suggestion.js";
6
6
  import { fromThreadMessageLike } from "./runtime/utils/thread-message-like.js";
@@ -10,7 +10,9 @@ import { ExportedMessageRepository, MessageRepository } from "./runtime/utils/me
10
10
  import { BaseSubject, BaseSubscribable, EventSubscriptionSubject, LazyMemoizeSubject, NestedSubscriptionSubject, SKIP_UPDATE, ShallowMemoizeSubject } from "./subscribable/subscribable.js";
11
11
  import { resolveToolApprovalResponse } from "./runtime/utils/resolveToolApprovalResponse.js";
12
12
  import { CompositeContextProvider } from "./utils/composite-context-provider.js";
13
+ import { isCreateAttachment } from "./types/attachment.js";
13
14
  import { stableStringifyToolArgs, trackToolArgsKeyOrder } from "./utils/json/stable-stringify-tool-args.js";
15
+ import { httpUrlPattern, parseDataUrl } from "./utils/data-url.js";
14
16
  import { createRuntimeExtras } from "./react/runtimes/createRuntimeExtras.js";
15
17
  import { BaseAssistantRuntimeCore } from "./runtime/base/base-assistant-runtime-core.js";
16
18
  import { BaseComposerRuntimeCore } from "./runtime/base/base-composer-runtime-core.js";
@@ -31,10 +33,11 @@ import { LocalThreadListRuntimeCore } from "./runtimes/local/local-thread-list-r
31
33
  import { LocalRuntimeCore } from "./runtimes/local/local-runtime-core.js";
32
34
  import { ExternalStoreThreadListRuntimeCore } from "./runtimes/external-store/external-store-thread-list-runtime-core.js";
33
35
  import { ThreadMessageConverter } from "./runtimes/external-store/thread-message-converter.js";
36
+ import { ToolInvocationTracker } from "./runtimes/tool-invocations/ToolInvocationTracker.js";
34
37
  import { ExternalStoreThreadRuntimeCore, hasUpcomingMessage } from "./runtimes/external-store/external-store-thread-runtime-core.js";
35
38
  import { ExternalStoreRuntimeCore } from "./runtimes/external-store/external-store-runtime-core.js";
36
39
  import { ReadonlyThreadRuntimeCore } from "./runtimes/readonly/ReadonlyThreadRuntimeCore.js";
37
40
  import { OptimisticState } from "./runtimes/remote-thread-list/optimistic-state.js";
38
41
  import { EMPTY_THREAD_CORE } from "./runtimes/remote-thread-list/empty-thread-core.js";
39
42
  import { createThreadMappingId, getThreadData, updateStatusReducer } from "./runtimes/remote-thread-list/remote-thread-state.js";
40
- export { AssistantRuntimeImpl, AttachmentRuntimeImpl, BaseAssistantRuntimeCore, BaseComposerRuntimeCore, BaseSubject, BaseSubscribable, BaseThreadRuntimeCore, ComposerRuntimeImpl, CompositeContextProvider, DefaultEditComposerRuntimeCore, DefaultThreadComposerRuntimeCore, EMPTY_THREAD_CORE, EditComposerAttachmentRuntimeImpl, EditComposerRuntimeImpl, EventSubscriptionSubject, ExportedMessageRepository, ExternalStoreRuntimeCore, ExternalStoreThreadListRuntimeCore, ExternalStoreThreadRuntimeCore, LazyMemoizeSubject, LocalRuntimeCore, LocalThreadListRuntimeCore, LocalThreadRuntimeCore, MessageAttachmentRuntimeImpl, MessagePartRuntimeImpl, MessageRepository, MessageRuntimeImpl, NestedSubscriptionSubject, OptimisticState, ReadonlyThreadRuntimeCore, SKIP_UPDATE, ShallowMemoizeSubject, ThreadComposerAttachmentRuntimeImpl, ThreadComposerRuntimeImpl, ThreadListItemRuntimeImpl, ThreadListRuntimeImpl, ThreadMessageConverter, ThreadRuntimeImpl, consumeSuggestionResult, createRuntimeExtras, createThreadMappingId, fromThreadMessageLike, generateErrorMessageId, generateId, getAutoStatus, getFileDataURL, getThreadData, getThreadMessageText, getThreadState, hasUpcomingMessage, isAutoStatus, isErrorMessageId, isJSONValue, isRecord, resolveToolApprovalResponse, shouldContinue, stableStringifyToolArgs, symbolInnerMessage, trackToolArgsKeyOrder, updateStatusReducer };
43
+ export { AssistantRuntimeImpl, AttachmentRuntimeImpl, BaseAssistantRuntimeCore, BaseComposerRuntimeCore, BaseSubject, BaseSubscribable, BaseThreadRuntimeCore, ComposerRuntimeImpl, CompositeContextProvider, DefaultEditComposerRuntimeCore, DefaultThreadComposerRuntimeCore, EMPTY_THREAD_CORE, EditComposerAttachmentRuntimeImpl, EditComposerRuntimeImpl, EventSubscriptionSubject, ExportedMessageRepository, ExternalStoreRuntimeCore, ExternalStoreThreadListRuntimeCore, ExternalStoreThreadRuntimeCore, LazyMemoizeSubject, LocalRuntimeCore, LocalThreadListRuntimeCore, LocalThreadRuntimeCore, MessageAttachmentRuntimeImpl, MessagePartRuntimeImpl, MessageRepository, MessageRuntimeImpl, NestedSubscriptionSubject, OptimisticState, ReadonlyThreadRuntimeCore, SKIP_UPDATE, ShallowMemoizeSubject, ThreadComposerAttachmentRuntimeImpl, ThreadComposerRuntimeImpl, ThreadListItemRuntimeImpl, ThreadListRuntimeImpl, ThreadMessageConverter, ThreadRuntimeImpl, ToolInvocationTracker, consumeSuggestionResult, createRuntimeExtras, createThreadMappingId, fileMatchesAccept, fromThreadMessageLike, generateErrorMessageId, generateId, getAutoStatus, getFileDataURL, getThreadData, getThreadMessageText, getThreadState, hasUpcomingMessage, httpUrlPattern, isAutoStatus, isCreateAttachment, isErrorMessageId, isJSONValue, isRecord, parseDataUrl, resolveToolApprovalResponse, shouldContinue, stableStringifyToolArgs, symbolInnerMessage, trackToolArgsKeyOrder, updateStatusReducer };
@@ -8,6 +8,7 @@ declare class AssistantFrameHost implements ModelContextProvider {
8
8
  private _requestCounter;
9
9
  private _iframeWindow;
10
10
  private _targetOrigin;
11
+ private _disposed;
11
12
  constructor(iframeWindow: Window, targetOrigin?: string);
12
13
  private handleMessage;
13
14
  private updateContext;
@@ -1 +1 @@
1
- {"version":3,"file":"host.d.ts","names":[],"sources":["../../../src/model-context/frame/host.ts"],"mappings":";;;cA0Ca,8BAA8B;UACjC;UACA;UACA;UAOA;UACA;UACA;cAEI,cAAc,QAAQ;UAU1B;UA6BA;UAmBA;UAaA;UAqCA;UAYA;EAIR,mBAAmB;EAInB,UAAU,uBAAuB;EAKjC"}
1
+ {"version":3,"file":"host.d.ts","names":[],"sources":["../../../src/model-context/frame/host.ts"],"mappings":";;;cAiDa,8BAA8B;UACjC;UACA;UACA;UAOA;UACA;UACA;UACA;EAEI,YAAA,cAAc,QAAQ;UAU1B;UA6BA;UAoBA;UAkBA;UAuDA;UAYA;EAIR,mBAAmB;EAInB,UAAU,uBAAuB;EAKjC"}
@@ -16,6 +16,12 @@ const deserializeModelContext = (serialized) => ({
16
16
  ...serialized.system !== void 0 && { system: serialized.system },
17
17
  ...serialized.tools && { tools: Object.fromEntries(Object.entries(serialized.tools).map(([name, tool]) => [name, deserializeTool(tool)])) }
18
18
  });
19
+ const getAbortReason = (signal) => {
20
+ if (signal.reason !== void 0) return signal.reason;
21
+ const error = /* @__PURE__ */ new Error("Tool call was aborted");
22
+ error.name = "AbortError";
23
+ return error;
24
+ };
19
25
  var AssistantFrameHost = class {
20
26
  _context = {};
21
27
  _subscribers = /* @__PURE__ */ new Set();
@@ -23,6 +29,7 @@ var AssistantFrameHost = class {
23
29
  _requestCounter = 0;
24
30
  _iframeWindow;
25
31
  _targetOrigin;
32
+ _disposed = false;
26
33
  constructor(iframeWindow, targetOrigin = "*") {
27
34
  this._iframeWindow = iframeWindow;
28
35
  this._targetOrigin = targetOrigin;
@@ -56,48 +63,58 @@ var AssistantFrameHost = class {
56
63
  ...context,
57
64
  tools: context.tools && Object.fromEntries(Object.entries(context.tools).map(([name, tool]) => [name, {
58
65
  ...tool,
59
- execute: (args) => this.callTool(name, args)
66
+ execute: (args, context) => this.callTool(name, args, context.abortSignal)
60
67
  }]))
61
68
  };
62
69
  this.notifySubscribers();
63
70
  }
64
- callTool(toolName, args) {
71
+ callTool(toolName, args, abortSignal) {
65
72
  return this.sendRequest({
66
73
  type: "tool-call",
67
74
  id: `tool-${this._requestCounter++}`,
68
75
  toolName,
69
76
  args
70
- }, 3e4, `Tool call "${toolName}" timed out`);
77
+ }, 3e4, `Tool call "${toolName}" timed out`, abortSignal);
71
78
  }
72
- sendRequest(message, timeout = 3e4, timeoutMessage = "Request timed out") {
79
+ sendRequest(message, timeout = 3e4, timeoutMessage = "Request timed out", abortSignal) {
80
+ if (this._disposed) return Promise.reject(/* @__PURE__ */ new Error("AssistantFrameHost has been disposed"));
81
+ if (abortSignal?.aborted) return Promise.reject(getAbortReason(abortSignal));
73
82
  return new Promise((resolve, reject) => {
74
- this._pendingRequests.set(message.id, {
75
- resolve,
76
- reject
77
- });
78
- this._iframeWindow.postMessage({
79
- channel: FRAME_MESSAGE_CHANNEL,
80
- message
81
- }, this._targetOrigin);
82
- const timeoutId = setTimeout(() => {
83
+ let timeoutId;
84
+ const onAbort = () => {
85
+ if (!abortSignal) return;
83
86
  const pending = this._pendingRequests.get(message.id);
84
87
  if (pending) {
85
- pending.reject(new Error(timeoutMessage));
88
+ pending.reject(getAbortReason(abortSignal));
86
89
  this._pendingRequests.delete(message.id);
87
90
  }
88
- }, timeout);
89
- const originalResolve = this._pendingRequests.get(message.id).resolve;
90
- const originalReject = this._pendingRequests.get(message.id).reject;
91
+ };
92
+ const cleanup = () => {
93
+ if (timeoutId !== void 0) clearTimeout(timeoutId);
94
+ abortSignal?.removeEventListener("abort", onAbort);
95
+ };
91
96
  this._pendingRequests.set(message.id, {
92
97
  resolve: (value) => {
93
- clearTimeout(timeoutId);
94
- originalResolve(value);
98
+ cleanup();
99
+ resolve(value);
95
100
  },
96
101
  reject: (error) => {
97
- clearTimeout(timeoutId);
98
- originalReject(error);
102
+ cleanup();
103
+ reject(error);
99
104
  }
100
105
  });
106
+ timeoutId = setTimeout(() => {
107
+ const pending = this._pendingRequests.get(message.id);
108
+ if (pending) {
109
+ pending.reject(new Error(timeoutMessage));
110
+ this._pendingRequests.delete(message.id);
111
+ }
112
+ }, timeout);
113
+ abortSignal?.addEventListener("abort", onAbort, { once: true });
114
+ this._iframeWindow.postMessage({
115
+ channel: FRAME_MESSAGE_CHANNEL,
116
+ message
117
+ }, this._targetOrigin);
101
118
  });
102
119
  }
103
120
  requestContext() {
@@ -117,8 +134,11 @@ var AssistantFrameHost = class {
117
134
  return () => this._subscribers.delete(callback);
118
135
  }
119
136
  dispose() {
137
+ this._disposed = true;
120
138
  window.removeEventListener("message", this.handleMessage);
121
139
  this._subscribers.clear();
140
+ const error = /* @__PURE__ */ new Error("AssistantFrameHost has been disposed");
141
+ for (const pending of this._pendingRequests.values()) pending.reject(error);
122
142
  this._pendingRequests.clear();
123
143
  }
124
144
  };
@@ -1 +1 @@
1
- {"version":3,"file":"host.js","names":["ModelContextProvider","ModelContext","Unsubscribe","Tool","FrameMessage","FRAME_MESSAGE_CHANNEL","SerializedModelContext","SerializedTool","deserializeTool","serializedTool","parameters","description","disabled","undefined","type","deserializeModelContext","serialized","system","tools","Object","fromEntries","entries","map","name","tool","AssistantFrameHost","_context","_subscribers","Set","_pendingRequests","Map","resolve","value","reject","error","_requestCounter","_iframeWindow","Window","_targetOrigin","constructor","iframeWindow","targetOrigin","handleMessage","bind","window","addEventListener","requestContext","event","MessageEvent","origin","source","data","channel","message","updateContext","context","pending","get","id","Error","result","delete","serializedContext","execute","args","callTool","notifySubscribers","toolName","Promise","sendRequest","T","timeout","timeoutMessage","set","postMessage","timeoutId","setTimeout","originalResolve","originalReject","clearTimeout","forEach","callback","getModelContext","subscribe","add","dispose","removeEventListener","clear"],"sources":["../../../src/model-context/frame/host.ts"],"sourcesContent":["import type { ModelContextProvider, ModelContext } from \"../types\";\nimport type { Unsubscribe } from \"../../types/unsubscribe\";\nimport type { Tool } from \"assistant-stream\";\nimport {\n type FrameMessage,\n FRAME_MESSAGE_CHANNEL,\n type SerializedModelContext,\n type SerializedTool,\n} from \"./types\";\n\n/**\n * Deserializes tools from JSON Schema format back to Tool objects\n */\nconst deserializeTool = (serializedTool: SerializedTool): Tool<any, any> =>\n ({\n parameters: serializedTool.parameters,\n ...(serializedTool.description && {\n description: serializedTool.description,\n }),\n ...(serializedTool.disabled !== undefined && {\n disabled: serializedTool.disabled,\n }),\n ...(serializedTool.type && { type: serializedTool.type }),\n }) as Tool<any, any>;\n\n/**\n * Deserializes a ModelContext from transmission format\n */\nconst deserializeModelContext = (\n serialized: SerializedModelContext,\n): ModelContext => ({\n ...(serialized.system !== undefined && { system: serialized.system }),\n ...(serialized.tools && {\n tools: Object.fromEntries(\n Object.entries(serialized.tools).map(([name, tool]) => [\n name,\n deserializeTool(tool),\n ]),\n ),\n }),\n});\n\nexport class AssistantFrameHost implements ModelContextProvider {\n private _context: ModelContext = {};\n private _subscribers = new Set<() => void>();\n private _pendingRequests = new Map<\n string,\n {\n resolve: (value: any) => void;\n reject: (error: any) => void;\n }\n >();\n private _requestCounter = 0;\n private _iframeWindow: Window;\n private _targetOrigin: string;\n\n constructor(iframeWindow: Window, targetOrigin: string = \"*\") {\n this._iframeWindow = iframeWindow;\n this._targetOrigin = targetOrigin;\n\n this.handleMessage = this.handleMessage.bind(this);\n window.addEventListener(\"message\", this.handleMessage);\n\n this.requestContext();\n }\n\n private handleMessage(event: MessageEvent) {\n if (this._targetOrigin !== \"*\" && event.origin !== this._targetOrigin)\n return;\n if (event.source !== this._iframeWindow) return;\n if (event.data?.channel !== FRAME_MESSAGE_CHANNEL) return;\n\n const message = event.data.message as FrameMessage;\n\n switch (message.type) {\n case \"model-context-update\": {\n this.updateContext(message.context);\n break;\n }\n\n case \"tool-result\": {\n const pending = this._pendingRequests.get(message.id);\n if (pending) {\n if (message.error) {\n pending.reject(new Error(message.error));\n } else {\n pending.resolve(message.result);\n }\n this._pendingRequests.delete(message.id);\n }\n break;\n }\n }\n }\n\n private updateContext(serializedContext: SerializedModelContext) {\n const context = deserializeModelContext(serializedContext);\n this._context = {\n ...context,\n tools:\n context.tools &&\n Object.fromEntries(\n Object.entries(context.tools).map(([name, tool]) => [\n name,\n {\n ...tool,\n execute: (args: any) => this.callTool(name, args),\n } as Tool<any, any>,\n ]),\n ),\n };\n this.notifySubscribers();\n }\n\n private callTool(toolName: string, args: any): Promise<any> {\n return this.sendRequest(\n {\n type: \"tool-call\",\n id: `tool-${this._requestCounter++}`,\n toolName,\n args,\n },\n 30000,\n `Tool call \"${toolName}\" timed out`,\n );\n }\n\n private sendRequest<T extends FrameMessage & { id: string }>(\n message: T,\n timeout = 30000,\n timeoutMessage = \"Request timed out\",\n ): Promise<any> {\n return new Promise((resolve, reject) => {\n this._pendingRequests.set(message.id, { resolve, reject });\n\n this._iframeWindow.postMessage(\n { channel: FRAME_MESSAGE_CHANNEL, message },\n this._targetOrigin,\n );\n\n const timeoutId = setTimeout(() => {\n const pending = this._pendingRequests.get(message.id);\n if (pending) {\n pending.reject(new Error(timeoutMessage));\n this._pendingRequests.delete(message.id);\n }\n }, timeout);\n\n const originalResolve = this._pendingRequests.get(message.id)!.resolve;\n const originalReject = this._pendingRequests.get(message.id)!.reject;\n\n this._pendingRequests.set(message.id, {\n resolve: (value: any) => {\n clearTimeout(timeoutId);\n originalResolve(value);\n },\n reject: (error: any) => {\n clearTimeout(timeoutId);\n originalReject(error);\n },\n });\n });\n }\n\n private requestContext() {\n this._iframeWindow.postMessage(\n {\n channel: FRAME_MESSAGE_CHANNEL,\n message: {\n type: \"model-context-request\",\n } as FrameMessage,\n },\n this._targetOrigin,\n );\n }\n\n private notifySubscribers() {\n this._subscribers.forEach((callback) => callback());\n }\n\n getModelContext(): ModelContext {\n return this._context;\n }\n\n subscribe(callback: () => void): Unsubscribe {\n this._subscribers.add(callback);\n return () => this._subscribers.delete(callback);\n }\n\n dispose() {\n window.removeEventListener(\"message\", this.handleMessage);\n this._subscribers.clear();\n this._pendingRequests.clear();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"host.js","names":["ModelContextProvider","ModelContext","Unsubscribe","Tool","FrameMessage","FRAME_MESSAGE_CHANNEL","SerializedModelContext","SerializedTool","deserializeTool","serializedTool","parameters","description","disabled","undefined","type","deserializeModelContext","serialized","system","tools","Object","fromEntries","entries","map","name","tool","getAbortReason","signal","AbortSignal","reason","error","Error","AssistantFrameHost","_context","_subscribers","Set","_pendingRequests","Map","resolve","value","reject","_requestCounter","_iframeWindow","Window","_targetOrigin","_disposed","constructor","iframeWindow","targetOrigin","handleMessage","bind","window","addEventListener","requestContext","event","MessageEvent","origin","source","data","channel","message","updateContext","context","pending","get","id","result","delete","serializedContext","execute","args","abortSignal","callTool","notifySubscribers","toolName","Promise","sendRequest","T","timeout","timeoutMessage","aborted","timeoutId","ReturnType","setTimeout","onAbort","cleanup","clearTimeout","removeEventListener","set","once","postMessage","forEach","callback","getModelContext","subscribe","add","dispose","clear","values"],"sources":["../../../src/model-context/frame/host.ts"],"sourcesContent":["import type { ModelContextProvider, ModelContext } from \"../types\";\nimport type { Unsubscribe } from \"../../types/unsubscribe\";\nimport type { Tool } from \"assistant-stream\";\nimport {\n type FrameMessage,\n FRAME_MESSAGE_CHANNEL,\n type SerializedModelContext,\n type SerializedTool,\n} from \"./types\";\n\n/**\n * Deserializes tools from JSON Schema format back to Tool objects\n */\nconst deserializeTool = (serializedTool: SerializedTool): Tool<any, any> =>\n ({\n parameters: serializedTool.parameters,\n ...(serializedTool.description && {\n description: serializedTool.description,\n }),\n ...(serializedTool.disabled !== undefined && {\n disabled: serializedTool.disabled,\n }),\n ...(serializedTool.type && { type: serializedTool.type }),\n }) as Tool<any, any>;\n\n/**\n * Deserializes a ModelContext from transmission format\n */\nconst deserializeModelContext = (\n serialized: SerializedModelContext,\n): ModelContext => ({\n ...(serialized.system !== undefined && { system: serialized.system }),\n ...(serialized.tools && {\n tools: Object.fromEntries(\n Object.entries(serialized.tools).map(([name, tool]) => [\n name,\n deserializeTool(tool),\n ]),\n ),\n }),\n});\n\nconst getAbortReason = (signal: AbortSignal): unknown => {\n if (signal.reason !== undefined) return signal.reason;\n const error = new Error(\"Tool call was aborted\");\n error.name = \"AbortError\";\n return error;\n};\n\nexport class AssistantFrameHost implements ModelContextProvider {\n private _context: ModelContext = {};\n private _subscribers = new Set<() => void>();\n private _pendingRequests = new Map<\n string,\n {\n resolve: (value: any) => void;\n reject: (error: any) => void;\n }\n >();\n private _requestCounter = 0;\n private _iframeWindow: Window;\n private _targetOrigin: string;\n private _disposed = false;\n\n constructor(iframeWindow: Window, targetOrigin: string = \"*\") {\n this._iframeWindow = iframeWindow;\n this._targetOrigin = targetOrigin;\n\n this.handleMessage = this.handleMessage.bind(this);\n window.addEventListener(\"message\", this.handleMessage);\n\n this.requestContext();\n }\n\n private handleMessage(event: MessageEvent) {\n if (this._targetOrigin !== \"*\" && event.origin !== this._targetOrigin)\n return;\n if (event.source !== this._iframeWindow) return;\n if (event.data?.channel !== FRAME_MESSAGE_CHANNEL) return;\n\n const message = event.data.message as FrameMessage;\n\n switch (message.type) {\n case \"model-context-update\": {\n this.updateContext(message.context);\n break;\n }\n\n case \"tool-result\": {\n const pending = this._pendingRequests.get(message.id);\n if (pending) {\n if (message.error) {\n pending.reject(new Error(message.error));\n } else {\n pending.resolve(message.result);\n }\n this._pendingRequests.delete(message.id);\n }\n break;\n }\n }\n }\n\n private updateContext(serializedContext: SerializedModelContext) {\n const context = deserializeModelContext(serializedContext);\n this._context = {\n ...context,\n tools:\n context.tools &&\n Object.fromEntries(\n Object.entries(context.tools).map(([name, tool]) => [\n name,\n {\n ...tool,\n execute: (args: any, context: { abortSignal: AbortSignal }) =>\n this.callTool(name, args, context.abortSignal),\n } as Tool<any, any>,\n ]),\n ),\n };\n this.notifySubscribers();\n }\n\n private callTool(\n toolName: string,\n args: any,\n abortSignal: AbortSignal,\n ): Promise<any> {\n return this.sendRequest(\n {\n type: \"tool-call\",\n id: `tool-${this._requestCounter++}`,\n toolName,\n args,\n },\n 30000,\n `Tool call \"${toolName}\" timed out`,\n abortSignal,\n );\n }\n\n private sendRequest<T extends FrameMessage & { id: string }>(\n message: T,\n timeout = 30000,\n timeoutMessage = \"Request timed out\",\n abortSignal?: AbortSignal,\n ): Promise<any> {\n if (this._disposed) {\n return Promise.reject(new Error(\"AssistantFrameHost has been disposed\"));\n }\n if (abortSignal?.aborted) {\n return Promise.reject(getAbortReason(abortSignal));\n }\n\n return new Promise((resolve, reject) => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n const onAbort = () => {\n if (!abortSignal) return;\n const pending = this._pendingRequests.get(message.id);\n if (pending) {\n pending.reject(getAbortReason(abortSignal));\n this._pendingRequests.delete(message.id);\n }\n };\n const cleanup = () => {\n if (timeoutId !== undefined) clearTimeout(timeoutId);\n abortSignal?.removeEventListener(\"abort\", onAbort);\n };\n\n this._pendingRequests.set(message.id, {\n resolve: (value: any) => {\n cleanup();\n resolve(value);\n },\n reject: (error: any) => {\n cleanup();\n reject(error);\n },\n });\n\n timeoutId = setTimeout(() => {\n const pending = this._pendingRequests.get(message.id);\n if (pending) {\n pending.reject(new Error(timeoutMessage));\n this._pendingRequests.delete(message.id);\n }\n }, timeout);\n abortSignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n this._iframeWindow.postMessage(\n { channel: FRAME_MESSAGE_CHANNEL, message },\n this._targetOrigin,\n );\n });\n }\n\n private requestContext() {\n this._iframeWindow.postMessage(\n {\n channel: FRAME_MESSAGE_CHANNEL,\n message: {\n type: \"model-context-request\",\n } as FrameMessage,\n },\n this._targetOrigin,\n );\n }\n\n private notifySubscribers() {\n this._subscribers.forEach((callback) => callback());\n }\n\n getModelContext(): ModelContext {\n return this._context;\n }\n\n subscribe(callback: () => void): Unsubscribe {\n this._subscribers.add(callback);\n return () => this._subscribers.delete(callback);\n }\n\n dispose() {\n this._disposed = true;\n window.removeEventListener(\"message\", this.handleMessage);\n this._subscribers.clear();\n const error = new Error(\"AssistantFrameHost has been disposed\");\n for (const pending of this._pendingRequests.values()) {\n pending.reject(error);\n }\n this._pendingRequests.clear();\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","names":[],"sources":["../../../src/model-context/frame/provider.ts"],"mappings":";;;cA+Ba;iBACI;UAEP;UACA;UAIA;UAED;iBAQQ;UASP;UAqBM;UAoCN;UAOA;UAkBA;SAcD,wBACL,UAAU,sBACV,wBACC;SAmBI"}
1
+ {"version":3,"file":"provider.d.ts","names":[],"sources":["../../../src/model-context/frame/provider.ts"],"mappings":";;;cA+Ba;iBACI;UAEP;UACA;UAIA;UAED;iBAQQ;UASP;UAsBM;UAoCN;UAOA;UAkBA;SAcD,wBACL,UAAU,sBACV,wBACC;SAmBI"}
@@ -28,6 +28,7 @@ var AssistantFrameProvider = class AssistantFrameProvider {
28
28
  }
29
29
  handleMessage(event) {
30
30
  if (this._targetOrigin !== "*" && event.origin !== this._targetOrigin) return;
31
+ if (event.source !== window.parent) return;
31
32
  if (event.data?.channel !== "assistant-ui-frame") return;
32
33
  const message = event.data.message;
33
34
  switch (message.type) {
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","names":["ModelContextProvider","ModelContext","Unsubscribe","Tool","toJSONSchema","FrameMessage","FRAME_MESSAGE_CHANNEL","SerializedModelContext","SerializedTool","serializeTool","tool","description","parameters","undefined","disabled","type","serializeModelContext","context","system","tools","Object","fromEntries","entries","map","name","AssistantFrameProvider","_instance","_providers","Set","_providerUnsubscribes","Map","_targetOrigin","constructor","targetOrigin","handleMessage","bind","window","addEventListener","setTimeout","broadcastUpdate","getInstance","event","MessageEvent","origin","data","channel","message","sendMessage","getModelContext","handleToolCall","Extract","toolName","result","error","execute","args","toolCallId","id","abortSignal","AbortController","signal","human","Error","e","String","source","postMessage","contexts","Array","from","p","reduce","merged","parent","updateMessage","addModelContextProvider","provider","instance","add","unsubscribe","subscribe","set","delete","get","dispose","removeEventListener","forEach","clear"],"sources":["../../../src/model-context/frame/provider.ts"],"sourcesContent":["import type { ModelContextProvider, ModelContext } from \"../types\";\nimport type { Unsubscribe } from \"../../types/unsubscribe\";\nimport { type Tool, toJSONSchema } from \"assistant-stream\";\nimport {\n type FrameMessage,\n FRAME_MESSAGE_CHANNEL,\n type SerializedModelContext,\n type SerializedTool,\n} from \"./types\";\n\nconst serializeTool = (tool: Tool<any, any>): SerializedTool => ({\n ...(tool.description && { description: tool.description }),\n parameters: tool.parameters ? toJSONSchema(tool.parameters) : undefined,\n ...(tool.disabled !== undefined && { disabled: tool.disabled }),\n ...(tool.type && { type: tool.type }),\n});\n\nconst serializeModelContext = (\n context: ModelContext,\n): SerializedModelContext => ({\n ...(context.system !== undefined && { system: context.system }),\n ...(context.tools && {\n tools: Object.fromEntries(\n Object.entries(context.tools).map(([name, tool]) => [\n name,\n serializeTool(tool),\n ]),\n ),\n }),\n});\n\nexport class AssistantFrameProvider {\n private static _instance: AssistantFrameProvider | null = null;\n\n private _providers = new Set<ModelContextProvider>();\n private _providerUnsubscribes = new Map<\n ModelContextProvider,\n Unsubscribe | undefined\n >();\n private _targetOrigin: string;\n\n private constructor(targetOrigin: string = \"*\") {\n this._targetOrigin = targetOrigin;\n this.handleMessage = this.handleMessage.bind(this);\n window.addEventListener(\"message\", this.handleMessage);\n\n setTimeout(() => this.broadcastUpdate(), 0);\n }\n\n private static getInstance(targetOrigin?: string): AssistantFrameProvider {\n if (!AssistantFrameProvider._instance) {\n AssistantFrameProvider._instance = new AssistantFrameProvider(\n targetOrigin,\n );\n }\n return AssistantFrameProvider._instance;\n }\n\n private handleMessage(event: MessageEvent) {\n if (this._targetOrigin !== \"*\" && event.origin !== this._targetOrigin)\n return;\n if (event.data?.channel !== FRAME_MESSAGE_CHANNEL) return;\n\n const message = event.data.message as FrameMessage;\n\n switch (message.type) {\n case \"model-context-request\":\n this.sendMessage(event, {\n type: \"model-context-update\",\n context: serializeModelContext(this.getModelContext()),\n });\n break;\n\n case \"tool-call\":\n this.handleToolCall(message, event);\n break;\n }\n }\n\n private async handleToolCall(\n message: Extract<FrameMessage, { type: \"tool-call\" }>,\n event: MessageEvent,\n ) {\n const tool = this.getModelContext().tools?.[message.toolName];\n\n let result: any;\n let error: string | undefined;\n\n if (!tool) {\n error = `Tool \"${message.toolName}\" not found`;\n } else {\n try {\n result = tool.execute\n ? await tool.execute(message.args, {\n toolCallId: message.id,\n abortSignal: new AbortController().signal,\n human: async () => {\n throw new Error(\n \"Tool human input is not supported in frame context\",\n );\n },\n })\n : undefined;\n } catch (e) {\n error = e instanceof Error ? e.message : String(e);\n }\n }\n\n this.sendMessage(event, {\n type: \"tool-result\",\n id: message.id,\n ...(error ? { error } : { result }),\n });\n }\n\n private sendMessage(event: MessageEvent, message: FrameMessage) {\n event.source?.postMessage(\n { channel: FRAME_MESSAGE_CHANNEL, message },\n { targetOrigin: event.origin },\n );\n }\n\n private getModelContext(): ModelContext {\n const contexts = Array.from(this._providers).map((p) =>\n p.getModelContext(),\n );\n\n return contexts.reduce(\n (merged, context) => ({\n system: context.system\n ? merged.system\n ? `${merged.system}\\n\\n${context.system}`\n : context.system\n : merged.system,\n tools: { ...(merged.tools || {}), ...(context.tools || {}) },\n }),\n {} as ModelContext,\n );\n }\n\n private broadcastUpdate() {\n if (window.parent && window.parent !== window) {\n const updateMessage: FrameMessage = {\n type: \"model-context-update\",\n context: serializeModelContext(this.getModelContext()),\n };\n\n window.parent.postMessage(\n { channel: FRAME_MESSAGE_CHANNEL, message: updateMessage },\n this._targetOrigin,\n );\n }\n }\n\n static addModelContextProvider(\n provider: ModelContextProvider,\n targetOrigin?: string,\n ): Unsubscribe {\n const instance = AssistantFrameProvider.getInstance(targetOrigin);\n instance._providers.add(provider);\n\n const unsubscribe = provider.subscribe?.(() => instance.broadcastUpdate());\n if (unsubscribe) {\n instance._providerUnsubscribes.set(provider, unsubscribe);\n }\n\n instance.broadcastUpdate();\n\n return () => {\n instance._providers.delete(provider);\n instance._providerUnsubscribes.get(provider)?.();\n instance._providerUnsubscribes.delete(provider);\n instance.broadcastUpdate();\n };\n }\n\n static dispose() {\n if (AssistantFrameProvider._instance) {\n const instance = AssistantFrameProvider._instance;\n window.removeEventListener(\"message\", instance.handleMessage);\n\n instance._providerUnsubscribes.forEach((unsubscribe) => unsubscribe?.());\n instance._providerUnsubscribes.clear();\n instance._providers.clear();\n\n AssistantFrameProvider._instance = null;\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"provider.js","names":["ModelContextProvider","ModelContext","Unsubscribe","Tool","toJSONSchema","FrameMessage","FRAME_MESSAGE_CHANNEL","SerializedModelContext","SerializedTool","serializeTool","tool","description","parameters","undefined","disabled","type","serializeModelContext","context","system","tools","Object","fromEntries","entries","map","name","AssistantFrameProvider","_instance","_providers","Set","_providerUnsubscribes","Map","_targetOrigin","constructor","targetOrigin","handleMessage","bind","window","addEventListener","setTimeout","broadcastUpdate","getInstance","event","MessageEvent","origin","source","parent","data","channel","message","sendMessage","getModelContext","handleToolCall","Extract","toolName","result","error","execute","args","toolCallId","id","abortSignal","AbortController","signal","human","Error","e","String","postMessage","contexts","Array","from","p","reduce","merged","updateMessage","addModelContextProvider","provider","instance","add","unsubscribe","subscribe","set","delete","get","dispose","removeEventListener","forEach","clear"],"sources":["../../../src/model-context/frame/provider.ts"],"sourcesContent":["import type { ModelContextProvider, ModelContext } from \"../types\";\nimport type { Unsubscribe } from \"../../types/unsubscribe\";\nimport { type Tool, toJSONSchema } from \"assistant-stream\";\nimport {\n type FrameMessage,\n FRAME_MESSAGE_CHANNEL,\n type SerializedModelContext,\n type SerializedTool,\n} from \"./types\";\n\nconst serializeTool = (tool: Tool<any, any>): SerializedTool => ({\n ...(tool.description && { description: tool.description }),\n parameters: tool.parameters ? toJSONSchema(tool.parameters) : undefined,\n ...(tool.disabled !== undefined && { disabled: tool.disabled }),\n ...(tool.type && { type: tool.type }),\n});\n\nconst serializeModelContext = (\n context: ModelContext,\n): SerializedModelContext => ({\n ...(context.system !== undefined && { system: context.system }),\n ...(context.tools && {\n tools: Object.fromEntries(\n Object.entries(context.tools).map(([name, tool]) => [\n name,\n serializeTool(tool),\n ]),\n ),\n }),\n});\n\nexport class AssistantFrameProvider {\n private static _instance: AssistantFrameProvider | null = null;\n\n private _providers = new Set<ModelContextProvider>();\n private _providerUnsubscribes = new Map<\n ModelContextProvider,\n Unsubscribe | undefined\n >();\n private _targetOrigin: string;\n\n private constructor(targetOrigin: string = \"*\") {\n this._targetOrigin = targetOrigin;\n this.handleMessage = this.handleMessage.bind(this);\n window.addEventListener(\"message\", this.handleMessage);\n\n setTimeout(() => this.broadcastUpdate(), 0);\n }\n\n private static getInstance(targetOrigin?: string): AssistantFrameProvider {\n if (!AssistantFrameProvider._instance) {\n AssistantFrameProvider._instance = new AssistantFrameProvider(\n targetOrigin,\n );\n }\n return AssistantFrameProvider._instance;\n }\n\n private handleMessage(event: MessageEvent) {\n if (this._targetOrigin !== \"*\" && event.origin !== this._targetOrigin)\n return;\n if (event.source !== window.parent) return;\n if (event.data?.channel !== FRAME_MESSAGE_CHANNEL) return;\n\n const message = event.data.message as FrameMessage;\n\n switch (message.type) {\n case \"model-context-request\":\n this.sendMessage(event, {\n type: \"model-context-update\",\n context: serializeModelContext(this.getModelContext()),\n });\n break;\n\n case \"tool-call\":\n this.handleToolCall(message, event);\n break;\n }\n }\n\n private async handleToolCall(\n message: Extract<FrameMessage, { type: \"tool-call\" }>,\n event: MessageEvent,\n ) {\n const tool = this.getModelContext().tools?.[message.toolName];\n\n let result: any;\n let error: string | undefined;\n\n if (!tool) {\n error = `Tool \"${message.toolName}\" not found`;\n } else {\n try {\n result = tool.execute\n ? await tool.execute(message.args, {\n toolCallId: message.id,\n abortSignal: new AbortController().signal,\n human: async () => {\n throw new Error(\n \"Tool human input is not supported in frame context\",\n );\n },\n })\n : undefined;\n } catch (e) {\n error = e instanceof Error ? e.message : String(e);\n }\n }\n\n this.sendMessage(event, {\n type: \"tool-result\",\n id: message.id,\n ...(error ? { error } : { result }),\n });\n }\n\n private sendMessage(event: MessageEvent, message: FrameMessage) {\n event.source?.postMessage(\n { channel: FRAME_MESSAGE_CHANNEL, message },\n { targetOrigin: event.origin },\n );\n }\n\n private getModelContext(): ModelContext {\n const contexts = Array.from(this._providers).map((p) =>\n p.getModelContext(),\n );\n\n return contexts.reduce(\n (merged, context) => ({\n system: context.system\n ? merged.system\n ? `${merged.system}\\n\\n${context.system}`\n : context.system\n : merged.system,\n tools: { ...(merged.tools || {}), ...(context.tools || {}) },\n }),\n {} as ModelContext,\n );\n }\n\n private broadcastUpdate() {\n if (window.parent && window.parent !== window) {\n const updateMessage: FrameMessage = {\n type: \"model-context-update\",\n context: serializeModelContext(this.getModelContext()),\n };\n\n window.parent.postMessage(\n { channel: FRAME_MESSAGE_CHANNEL, message: updateMessage },\n this._targetOrigin,\n );\n }\n }\n\n static addModelContextProvider(\n provider: ModelContextProvider,\n targetOrigin?: string,\n ): Unsubscribe {\n const instance = AssistantFrameProvider.getInstance(targetOrigin);\n instance._providers.add(provider);\n\n const unsubscribe = provider.subscribe?.(() => instance.broadcastUpdate());\n if (unsubscribe) {\n instance._providerUnsubscribes.set(provider, unsubscribe);\n }\n\n instance.broadcastUpdate();\n\n return () => {\n instance._providers.delete(provider);\n instance._providerUnsubscribes.get(provider)?.();\n instance._providerUnsubscribes.delete(provider);\n instance.broadcastUpdate();\n };\n }\n\n static dispose() {\n if (AssistantFrameProvider._instance) {\n const instance = AssistantFrameProvider._instance;\n window.removeEventListener(\"message\", instance.handleMessage);\n\n instance._providerUnsubscribes.forEach((unsubscribe) => unsubscribe?.());\n instance._providerUnsubscribes.clear();\n instance._providers.clear();\n\n AssistantFrameProvider._instance = null;\n }\n }\n}\n"],"mappings":"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"}