@assistant-ui/core 0.3.18 → 0.3.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (274) hide show
  1. package/dist/adapters/speech.d.ts.map +1 -1
  2. package/dist/adapters/speech.js +13 -3
  3. package/dist/adapters/speech.js.map +1 -1
  4. package/dist/adapters/thread-history.d.ts +4 -0
  5. package/dist/adapters/thread-history.d.ts.map +1 -1
  6. package/dist/index.d.ts +2 -2
  7. package/dist/index.js.map +1 -1
  8. package/dist/internal.d.ts +1 -1
  9. package/dist/model-context/frame/host.d.ts.map +1 -1
  10. package/dist/model-context/frame/host.js +26 -11
  11. package/dist/model-context/frame/host.js.map +1 -1
  12. package/dist/model-context/interactable-composer-metadata.js +11 -9
  13. package/dist/model-context/interactable-composer-metadata.js.map +1 -1
  14. package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
  15. package/dist/react/adapters/LocalStorageThreadListAdapter.js +45 -7
  16. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  17. package/dist/react/client/DataRenderers.d.ts.map +1 -1
  18. package/dist/react/client/DataRenderers.js +20 -15
  19. package/dist/react/client/DataRenderers.js.map +1 -1
  20. package/dist/react/client/Interactables.d.ts.map +1 -1
  21. package/dist/react/client/Interactables.js +11 -5
  22. package/dist/react/client/Interactables.js.map +1 -1
  23. package/dist/react/client/RemoteThreadList.d.ts.map +1 -1
  24. package/dist/react/client/RemoteThreadList.js +3 -2
  25. package/dist/react/client/RemoteThreadList.js.map +1 -1
  26. package/dist/react/client/interactable-model-context.d.ts.map +1 -1
  27. package/dist/react/client/interactable-model-context.js +3 -2
  28. package/dist/react/client/interactable-model-context.js.map +1 -1
  29. package/dist/react/index.d.ts +2 -2
  30. package/dist/react/index.js +2 -2
  31. package/dist/react/interactables-legacy/useAssistantInteractable.d.ts.map +1 -1
  32. package/dist/react/interactables-legacy/useAssistantInteractable.js +3 -0
  33. package/dist/react/interactables-legacy/useAssistantInteractable.js.map +1 -1
  34. package/dist/react/model-context/useInteractable.d.ts.map +1 -1
  35. package/dist/react/model-context/useInteractable.js +4 -1
  36. package/dist/react/model-context/useInteractable.js.map +1 -1
  37. package/dist/react/model-context/useInteractableVersions.js +1 -1
  38. package/dist/react/primitives/message/MessageGroupedParts.d.ts +11 -2
  39. package/dist/react/primitives/message/MessageGroupedParts.d.ts.map +1 -1
  40. package/dist/react/primitives/message/MessageGroupedParts.js +3 -2
  41. package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
  42. package/dist/react/primitives/part/PartMessages.d.ts +1 -0
  43. package/dist/react/primitives/part/PartMessages.d.ts.map +1 -1
  44. package/dist/react/primitives/part/PartMessages.js +1 -0
  45. package/dist/react/primitives/part/PartMessages.js.map +1 -1
  46. package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
  47. package/dist/react/primitives/thread/ThreadMessages.js +6 -5
  48. package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
  49. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  50. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +2 -1
  51. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  52. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +2 -24
  53. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  54. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +135 -374
  55. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  56. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +1 -0
  57. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
  58. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +22 -2
  59. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
  60. package/dist/react/runtimes/cloud/auiV0.d.ts +40 -15
  61. package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
  62. package/dist/react/runtimes/cloud/auiV0.js +62 -15
  63. package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
  64. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts +2 -1
  65. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts.map +1 -1
  66. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js +4 -0
  67. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js.map +1 -1
  68. package/dist/react/runtimes/cloud/sdkIdentity.d.ts +6 -0
  69. package/dist/react/runtimes/cloud/sdkIdentity.d.ts.map +1 -0
  70. package/dist/react/runtimes/cloud/sdkIdentity.js +9 -0
  71. package/dist/react/runtimes/cloud/sdkIdentity.js.map +1 -0
  72. package/dist/react/runtimes/external-message-converter.d.ts +12 -2
  73. package/dist/react/runtimes/external-message-converter.d.ts.map +1 -1
  74. package/dist/react/runtimes/external-message-converter.js +26 -61
  75. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  76. package/dist/react/runtimes/useRemoteThreadListRuntime.js +1 -1
  77. package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
  78. package/dist/react/utils/groupParts.d.ts +6 -1
  79. package/dist/react/utils/groupParts.d.ts.map +1 -1
  80. package/dist/react/utils/groupParts.js +6 -0
  81. package/dist/react/utils/groupParts.js.map +1 -1
  82. package/dist/react/utils/useJSONEqual.d.ts +3 -1
  83. package/dist/react/utils/useJSONEqual.d.ts.map +1 -1
  84. package/dist/react/utils/useJSONEqual.js +6 -1
  85. package/dist/react/utils/useJSONEqual.js.map +1 -1
  86. package/dist/react/utils/useJSONSchemaDependency.d.ts +7 -0
  87. package/dist/react/utils/useJSONSchemaDependency.d.ts.map +1 -0
  88. package/dist/react/utils/useJSONSchemaDependency.js +20 -0
  89. package/dist/react/utils/useJSONSchemaDependency.js.map +1 -0
  90. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  91. package/dist/runtime/api/thread-runtime.js +2 -5
  92. package/dist/runtime/api/thread-runtime.js.map +1 -1
  93. package/dist/runtime/base/base-composer-runtime-core.d.ts +1 -0
  94. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  95. package/dist/runtime/base/base-composer-runtime-core.js +46 -10
  96. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  97. package/dist/runtime/base/base-thread-runtime-core.d.ts +2 -0
  98. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  99. package/dist/runtime/base/base-thread-runtime-core.js +155 -64
  100. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  101. package/dist/runtime/interfaces/thread-runtime-core.d.ts +6 -0
  102. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  103. package/dist/runtime/queue/message-queue.d.ts +5 -0
  104. package/dist/runtime/queue/message-queue.d.ts.map +1 -1
  105. package/dist/runtime/queue/message-queue.js +61 -6
  106. package/dist/runtime/queue/message-queue.js.map +1 -1
  107. package/dist/runtime/utils/auto-status.d.ts +6 -2
  108. package/dist/runtime/utils/auto-status.d.ts.map +1 -1
  109. package/dist/runtime/utils/auto-status.js +12 -4
  110. package/dist/runtime/utils/auto-status.js.map +1 -1
  111. package/dist/runtime/utils/external-message-conversion.d.ts +16 -4
  112. package/dist/runtime/utils/external-message-conversion.d.ts.map +1 -1
  113. package/dist/runtime/utils/external-message-conversion.js +48 -12
  114. package/dist/runtime/utils/external-message-conversion.js.map +1 -1
  115. package/dist/runtime/utils/message-repository.js +3 -3
  116. package/dist/runtime/utils/message-repository.js.map +1 -1
  117. package/dist/runtime/utils/thread-message-like.d.ts +2 -1
  118. package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
  119. package/dist/runtime/utils/thread-message-like.js +4 -2
  120. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  121. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  122. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +8 -1
  123. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  124. package/dist/runtimes/internal.d.ts +1 -1
  125. package/dist/runtimes/local/local-thread-runtime-core.d.ts +1 -1
  126. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  127. package/dist/runtimes/local/local-thread-runtime-core.js +4 -1
  128. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  129. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
  130. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +2 -1
  131. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
  132. package/dist/store/clients/external-thread.d.ts.map +1 -1
  133. package/dist/store/clients/external-thread.js +241 -200
  134. package/dist/store/clients/external-thread.js.map +1 -1
  135. package/dist/store/clients/thread-tasks.d.ts +13 -0
  136. package/dist/store/clients/thread-tasks.d.ts.map +1 -0
  137. package/dist/store/clients/thread-tasks.js +69 -0
  138. package/dist/store/clients/thread-tasks.js.map +1 -0
  139. package/dist/store/index.d.ts +3 -2
  140. package/dist/store/index.js +3 -3
  141. package/dist/store/primitive-predicates.d.ts.map +1 -1
  142. package/dist/store/primitive-predicates.js +4 -4
  143. package/dist/store/primitive-predicates.js.map +1 -1
  144. package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
  145. package/dist/store/runtime-clients/thread-runtime-client.js +176 -128
  146. package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
  147. package/dist/store/scope-registration.d.ts +2 -0
  148. package/dist/store/scope-registration.d.ts.map +1 -1
  149. package/dist/store/scopes/task.d.ts +36 -0
  150. package/dist/store/scopes/task.d.ts.map +1 -0
  151. package/dist/store/scopes/task.js +0 -0
  152. package/dist/store/scopes/thread.d.ts +20 -0
  153. package/dist/store/scopes/thread.d.ts.map +1 -1
  154. package/dist/subscribable/subscribable.d.ts +2 -1
  155. package/dist/subscribable/subscribable.d.ts.map +1 -1
  156. package/dist/subscribable/subscribable.js +23 -15
  157. package/dist/subscribable/subscribable.js.map +1 -1
  158. package/dist/types/index.d.ts +2 -2
  159. package/dist/types/message.d.ts +8 -1
  160. package/dist/types/message.d.ts.map +1 -1
  161. package/dist/types/message.js.map +1 -1
  162. package/dist/utils/abortable-iterable.d.ts.map +1 -1
  163. package/dist/utils/abortable-iterable.js +30 -14
  164. package/dist/utils/abortable-iterable.js.map +1 -1
  165. package/dist/utils/getGroupStatus.d.ts +18 -2
  166. package/dist/utils/getGroupStatus.d.ts.map +1 -1
  167. package/dist/utils/getGroupStatus.js +32 -7
  168. package/dist/utils/getGroupStatus.js.map +1 -1
  169. package/dist/utils/wire-media.d.ts.map +1 -1
  170. package/dist/utils/wire-media.js +2 -2
  171. package/dist/utils/wire-media.js.map +1 -1
  172. package/package.json +6 -6
  173. package/src/adapters/speech.test.ts +236 -0
  174. package/src/adapters/speech.ts +17 -10
  175. package/src/adapters/thread-history.ts +3 -0
  176. package/src/index.ts +1 -0
  177. package/src/model-context/frame/host.test.ts +113 -1
  178. package/src/model-context/frame/host.ts +39 -12
  179. package/src/model-context/interactable-composer-metadata.test.ts +30 -0
  180. package/src/model-context/interactable-composer-metadata.ts +10 -10
  181. package/src/react/adapters/LocalStorageThreadListAdapter.test.ts +244 -0
  182. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +104 -7
  183. package/src/react/client/DataRenderers.test.tsx +45 -0
  184. package/src/react/client/DataRenderers.ts +13 -9
  185. package/src/react/client/Interactables.test.ts +44 -1
  186. package/src/react/client/Interactables.ts +7 -1
  187. package/src/react/client/RemoteThreadList.test.ts +41 -1
  188. package/src/react/client/RemoteThreadList.ts +15 -2
  189. package/src/react/client/interactable-model-context.test.ts +44 -0
  190. package/src/react/client/interactable-model-context.ts +3 -2
  191. package/src/react/index.ts +5 -1
  192. package/src/react/interactables-legacy/useAssistantInteractable.test.tsx +132 -0
  193. package/src/react/interactables-legacy/useAssistantInteractable.ts +10 -1
  194. package/src/react/model-context/useInteractable.test.tsx +177 -0
  195. package/src/react/model-context/useInteractable.ts +3 -0
  196. package/src/react/primitive-hooks/useActionBarCopy.test.ts +0 -1
  197. package/src/react/primitive-hooks/useSuggestionTrigger.test.ts +0 -1
  198. package/src/react/primitives/message/MessageGroupedParts.test.tsx +96 -0
  199. package/src/react/primitives/message/MessageGroupedParts.tsx +15 -4
  200. package/src/react/primitives/part/PartMessages.test.tsx +104 -1
  201. package/src/react/primitives/part/PartMessages.tsx +1 -0
  202. package/src/react/primitives/thread/ThreadMessages.test.tsx +142 -0
  203. package/src/react/primitives/thread/ThreadMessages.tsx +8 -5
  204. package/src/react/providers/ReadonlyThreadProvider.test.tsx +56 -0
  205. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +7 -1
  206. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.ts +20 -14
  207. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +221 -1
  208. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +166 -512
  209. package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.test.ts +77 -0
  210. package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +27 -1
  211. package/src/react/runtimes/cloud/auiV0.ts +160 -25
  212. package/src/react/runtimes/cloud/createCloudThreadListAdapter.test.ts +21 -0
  213. package/src/react/runtimes/cloud/createCloudThreadListAdapter.ts +7 -1
  214. package/src/react/runtimes/cloud/sdkIdentity.ts +9 -0
  215. package/src/react/runtimes/cloud/useCloudThreadListAdapter.test.tsx +18 -4
  216. package/src/react/runtimes/external-message-converter.test.ts +136 -1
  217. package/src/react/runtimes/external-message-converter.ts +39 -93
  218. package/src/react/runtimes/useRemoteThreadListRuntime.ts +1 -1
  219. package/src/react/utils/groupParts.ts +12 -1
  220. package/src/react/utils/useJSONEqual.ts +9 -0
  221. package/src/react/utils/useJSONSchemaDependency.ts +22 -0
  222. package/src/runtime/api/thread-runtime.test.ts +58 -0
  223. package/src/runtime/api/thread-runtime.ts +2 -4
  224. package/src/runtime/base/base-composer-runtime-core.ts +69 -16
  225. package/src/runtime/base/base-thread-runtime-core.test.ts +1008 -1
  226. package/src/runtime/base/base-thread-runtime-core.ts +222 -83
  227. package/src/runtime/interfaces/thread-runtime-core.ts +6 -0
  228. package/src/runtime/queue/message-queue.ts +68 -6
  229. package/src/runtime/utils/auto-status.test.ts +112 -1
  230. package/src/runtime/utils/auto-status.ts +31 -5
  231. package/src/runtime/utils/external-message-conversion.test.ts +134 -0
  232. package/src/runtime/utils/external-message-conversion.ts +122 -31
  233. package/src/runtime/utils/message-repository.test.ts +49 -0
  234. package/src/runtime/utils/message-repository.ts +3 -3
  235. package/src/runtime/utils/thread-message-like.test.ts +52 -0
  236. package/src/runtime/utils/thread-message-like.ts +4 -0
  237. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +31 -1
  238. package/src/runtimes/local/local-thread-runtime-core.test.ts +21 -0
  239. package/src/runtimes/local/local-thread-runtime-core.ts +11 -1
  240. package/src/runtimes/tool-invocations/EDGE_CASES.md +2 -6
  241. package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +133 -0
  242. package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +10 -6
  243. package/src/store/clients/external-thread.ts +19 -1
  244. package/src/store/clients/thread-tasks.test.ts +274 -0
  245. package/src/store/clients/thread-tasks.ts +138 -0
  246. package/src/store/index.ts +8 -0
  247. package/src/store/primitive-predicates.test.ts +48 -5
  248. package/src/store/primitive-predicates.ts +7 -2
  249. package/src/store/runtime-clients/thread-runtime-client.ts +31 -1
  250. package/src/store/scope-registration.ts +2 -0
  251. package/src/store/scopes/task.ts +34 -0
  252. package/src/store/scopes/thread.ts +16 -0
  253. package/src/store/thread-tasks.test.tsx +209 -0
  254. package/src/subscribable/subscribable.test.ts +156 -1
  255. package/src/subscribable/subscribable.ts +25 -15
  256. package/src/tests/MessageRepository.test.ts +1 -5
  257. package/src/tests/auiV0Encode.test.ts +300 -0
  258. package/src/tests/base-composer-runtime-core-send.test.ts +51 -0
  259. package/src/tests/base-composer-runtime-core.test.ts +314 -2
  260. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +151 -0
  261. package/src/tests/external-thread-attachments.test.tsx +69 -0
  262. package/src/tests/external-thread-parity.test.tsx +34 -0
  263. package/src/tests/groupParts.test.ts +71 -0
  264. package/src/tests/message-queue.test.ts +253 -0
  265. package/src/tests/remote-thread-list-reactive-threadId.test.ts +51 -0
  266. package/src/tests/useRemoteThreadListRuntime-controlled.test.tsx +43 -0
  267. package/src/types/index.ts +1 -0
  268. package/src/types/message.ts +8 -0
  269. package/src/utils/abortable-iterable.test.ts +115 -0
  270. package/src/utils/abortable-iterable.ts +34 -23
  271. package/src/utils/getGroupStatus.test.ts +70 -4
  272. package/src/utils/getGroupStatus.ts +35 -12
  273. package/src/utils/wire-media.test.ts +10 -0
  274. package/src/utils/wire-media.ts +6 -2
@@ -1 +1 @@
1
- {"version":3,"file":"base-thread-runtime-core.js","names":["AppendMessage","ThreadAssistantMessage","ThreadMessage","Unsubscribe","ModelContextProvider","getThreadMessageText","generateId","ExportedMessageRepository","MessageRepository","DefaultThreadComposerRuntimeCore","AddToolResultOptions","ResumeToolCallOptions","RespondToToolApprovalOptions","ThreadSuggestion","SubmitFeedbackOptions","ThreadRuntimeCore","SpeechState","VoiceSessionState","RuntimeCapabilities","ThreadRuntimeEventCallback","ThreadRuntimeEventPayload","ThreadRuntimeEventType","StartRunConfig","ResumeRunConfig","DefaultEditComposerRuntimeCore","SpeechSynthesisAdapter","FeedbackAdapter","AttachmentAdapter","RealtimeVoiceAdapter","ThreadMessageLike","notifyEventListeners","gateInteractableComposerMetadata","BaseSubscribable","BaseThreadAdapters","speech","feedback","attachments","voice","BaseThreadRuntimeCore","_isInitialized","repository","adapters","isDisabled","isSendDisabled","isLoading","suggestions","extras","capabilities","append","message","deleteMessage","messageId","Promise","startRun","config","resumeRun","addToolResult","options","resumeToolCall","respondToToolApproval","cancelRun","exportExternalState","importExternalState","state","unstable_notifySessionReset","_voiceMessages","_voiceGeneration","_cachedMergedMessages","_cachedVoiceGeneration","_cachedMergedBase","_markVoiceMessagesDirty","_getBaseMessages","getMessages","messages","length","base","mostRecentAssistantMessage","this","role","metadata","unstable_state","composer","_contextProvider","constructor","getModelContext","enrichAppendMetadata","anchorId","parentId","parentIndex","findIndex","m","id","composerMetadata","unstable_composerMetadata","slice","custom","_editComposers","Map","getEditComposer","get","beginEdit","has","Error","set","delete","getMessage","_notifySubscribers","getMessageById","baseMessages","voiceIdx","at","index","undefined","getBranches","some","switchToBranch","branchId","_notifyEventSubscribers","event","E","payload","subscribers","_eventSubscribers","submitFeedback","type","adapter","submit","updatedMessage","submittedFeedback","addOrUpdateMessage","_stopSpeaking","speak","utterance","unsub","subscribe","status","cancel","stopSpeaking","_voiceSession","Session","_voiceUnsubs","Array","_voiceVolume","_voiceVolumeSubscribers","Set","getVoiceVolume","subscribeVoiceVolume","callback","add","connectVoice","disconnectVoice","session","connect","unsubs","currentMode","Mode","isMuted","mode","push","onStatusChange","_finishVoiceAssistantMessage","onModeChange","onVolumeChange","volume","onTranscript","transcript","_handleVoiceTranscript","_currentAssistantMsg","TranscriptItem","ensureInitialized","isFinal","content","text","createdAt","Date","reason","unstable_annotations","unstable_data","steps","idx","indexOf","updated","last","disconnect","muteVoice","mute","unmuteVoice","unmute","export","import","data","clear","reset","initialMessages","fromArray","unstable_on","wrapped","queueMicrotask"],"sources":["../../../src/runtime/base/base-thread-runtime-core.ts"],"sourcesContent":["import type {\n AppendMessage,\n ThreadAssistantMessage,\n ThreadMessage,\n} from \"../../types/message\";\nimport type { Unsubscribe } from \"../../types/unsubscribe\";\nimport type { ModelContextProvider } from \"../../model-context/types\";\nimport { getThreadMessageText } from \"../../utils/text\";\nimport { generateId } from \"../../utils/id\";\nimport {\n ExportedMessageRepository,\n MessageRepository,\n} from \"../utils/message-repository\";\nimport { DefaultThreadComposerRuntimeCore } from \"./default-thread-composer-runtime-core\";\nimport type {\n AddToolResultOptions,\n ResumeToolCallOptions,\n RespondToToolApprovalOptions,\n ThreadSuggestion,\n SubmitFeedbackOptions,\n ThreadRuntimeCore,\n SpeechState,\n VoiceSessionState,\n RuntimeCapabilities,\n ThreadRuntimeEventCallback,\n ThreadRuntimeEventPayload,\n ThreadRuntimeEventType,\n StartRunConfig,\n ResumeRunConfig,\n} from \"../interfaces/thread-runtime-core\";\nimport { DefaultEditComposerRuntimeCore } from \"./default-edit-composer-runtime-core\";\nimport type { SpeechSynthesisAdapter } from \"../../adapters/speech\";\nimport type { FeedbackAdapter } from \"../../adapters/feedback\";\nimport type { AttachmentAdapter } from \"../../adapters/attachment\";\nimport type { RealtimeVoiceAdapter } from \"../../adapters/voice\";\nimport type { ThreadMessageLike } from \"../utils/thread-message-like\";\nimport { notifyEventListeners } from \"../../utils/notify-event-listeners\";\nimport { gateInteractableComposerMetadata } from \"../../model-context/interactable-composer-metadata\";\nimport { BaseSubscribable } from \"../../subscribable/subscribable\";\n\ntype BaseThreadAdapters = {\n speech?: SpeechSynthesisAdapter | undefined;\n feedback?: FeedbackAdapter | undefined;\n attachments?: AttachmentAdapter | undefined;\n voice?: RealtimeVoiceAdapter | undefined;\n};\n\nexport abstract class BaseThreadRuntimeCore\n extends BaseSubscribable\n implements ThreadRuntimeCore\n{\n private _isInitialized = false;\n\n protected repository = new MessageRepository();\n public abstract get adapters(): BaseThreadAdapters | undefined;\n public abstract get isDisabled(): boolean;\n public abstract get isSendDisabled(): boolean;\n public abstract get isLoading(): boolean;\n public abstract get suggestions(): readonly ThreadSuggestion[];\n public abstract get extras(): unknown;\n\n public abstract get capabilities(): RuntimeCapabilities;\n public abstract append(message: AppendMessage): void;\n public abstract deleteMessage(messageId: string): void | Promise<void>;\n public abstract startRun(config: StartRunConfig): void;\n public abstract resumeRun(config: ResumeRunConfig): void;\n public abstract addToolResult(options: AddToolResultOptions): void;\n public abstract resumeToolCall(options: ResumeToolCallOptions): void;\n public abstract respondToToolApproval(\n options: RespondToToolApprovalOptions,\n ): Promise<void>;\n public abstract cancelRun(): void;\n public abstract exportExternalState(): any;\n public abstract importExternalState(state: any): void;\n public abstract unstable_notifySessionReset(): void;\n\n protected _voiceMessages: ThreadMessage[] = [];\n protected _voiceGeneration = 0;\n private _cachedMergedMessages: readonly ThreadMessage[] | null = null;\n private _cachedVoiceGeneration = -1;\n private _cachedMergedBase: readonly ThreadMessage[] | null = null;\n\n protected _markVoiceMessagesDirty() {\n this._voiceGeneration++;\n this._cachedMergedMessages = null;\n }\n\n protected _getBaseMessages(): readonly ThreadMessage[] {\n return this.repository.getMessages();\n }\n\n public get messages(): readonly ThreadMessage[] {\n if (this._voiceMessages.length === 0) {\n return this._getBaseMessages();\n }\n const base = this._getBaseMessages();\n if (\n this._cachedVoiceGeneration !== this._voiceGeneration ||\n this._cachedMergedBase !== base\n ) {\n this._cachedMergedMessages = [...base, ...this._voiceMessages];\n this._cachedVoiceGeneration = this._voiceGeneration;\n this._cachedMergedBase = base;\n }\n return this._cachedMergedMessages!;\n }\n\n public get state() {\n let mostRecentAssistantMessage: (typeof this.messages)[number] | undefined;\n for (const message of this.messages) {\n if (message.role === \"assistant\") {\n mostRecentAssistantMessage = message;\n }\n }\n\n return mostRecentAssistantMessage?.metadata.unstable_state ?? null;\n }\n\n public readonly composer = new DefaultThreadComposerRuntimeCore(this);\n\n private readonly _contextProvider: ModelContextProvider;\n\n constructor(_contextProvider: ModelContextProvider) {\n super();\n this._contextProvider = _contextProvider;\n }\n\n public getModelContext() {\n return this._contextProvider.getModelContext();\n }\n\n /**\n * Stamps provider-contributed composer metadata onto an outgoing message.\n * Called at dispatch rather than in the composer, so programmatic sends are\n * covered too, and exactly once per message: a queued send is stamped when\n * it leaves the lane, never when it enters.\n *\n * Only user messages are stamped, matching the readers: both the version\n * fold and the model injection skip every other role.\n *\n * @param anchorId Message the gated branch prefix ends at. A queued send\n * passes the current tail, having waited through a run that grew the prefix\n * past the parent it was created with.\n */\n protected enrichAppendMetadata(\n message: AppendMessage,\n anchorId: string | null = message.parentId,\n ): AppendMessage {\n if (message.role !== \"user\") return message;\n const messages = this.messages;\n const parentIndex =\n anchorId === null ? -1 : messages.findIndex((m) => m.id === anchorId);\n const composerMetadata = gateInteractableComposerMetadata(\n this.getModelContext().unstable_composerMetadata,\n messages.slice(0, parentIndex + 1),\n );\n if (!composerMetadata) return message;\n return {\n ...message,\n metadata: {\n ...message.metadata,\n custom: { ...message.metadata?.custom, ...composerMetadata },\n },\n };\n }\n\n private _editComposers = new Map<string, DefaultEditComposerRuntimeCore>();\n public getEditComposer(messageId: string) {\n return this._editComposers.get(messageId);\n }\n public beginEdit(messageId: string) {\n if (this._editComposers.has(messageId))\n throw new Error(\"Edit already in progress\");\n\n this._editComposers.set(\n messageId,\n new DefaultEditComposerRuntimeCore(\n this,\n () => this._editComposers.delete(messageId),\n this.repository.getMessage(messageId),\n ),\n );\n this._notifySubscribers();\n }\n\n public getMessageById(messageId: string) {\n try {\n return this.repository.getMessage(messageId);\n } catch {\n // Check voice messages\n const baseMessages = this.repository.getMessages();\n const voiceIdx = this._voiceMessages.findIndex((m) => m.id === messageId);\n if (voiceIdx !== -1) {\n const parentId =\n voiceIdx > 0\n ? this._voiceMessages[voiceIdx - 1]!.id\n : (baseMessages.at(-1)?.id ?? null);\n return {\n parentId,\n message: this._voiceMessages[voiceIdx]!,\n index: baseMessages.length + voiceIdx,\n };\n }\n return undefined;\n }\n }\n\n public getBranches(messageId: string): string[] {\n if (this._voiceMessages.some((m) => m.id === messageId)) {\n return [];\n }\n return this.repository.getBranches(messageId);\n }\n\n public switchToBranch(branchId: string): void {\n this.repository.switchToBranch(branchId);\n this._notifySubscribers();\n }\n\n public _notifyEventSubscribers<E extends ThreadRuntimeEventType>(\n event: E,\n payload: ThreadRuntimeEventPayload[E],\n ) {\n const subscribers = this._eventSubscribers.get(event);\n if (!subscribers) return;\n\n notifyEventListeners(subscribers, payload, `Thread runtime \"${event}\"`);\n }\n\n public submitFeedback({ messageId, type }: SubmitFeedbackOptions) {\n const adapter = this.adapters?.feedback;\n if (!adapter) throw new Error(\"Feedback adapter not configured\");\n\n const { message, parentId } = this.repository.getMessage(messageId);\n adapter.submit({ message, type });\n\n if (message.role === \"assistant\") {\n const updatedMessage: ThreadMessage = {\n ...message,\n metadata: {\n ...message.metadata,\n submittedFeedback: { type },\n },\n };\n this.repository.addOrUpdateMessage(parentId, updatedMessage);\n }\n\n this._notifySubscribers();\n }\n\n private _stopSpeaking: Unsubscribe | undefined;\n public speech: SpeechState | undefined;\n\n public speak(messageId: string) {\n const adapter = this.adapters?.speech;\n if (!adapter) throw new Error(\"Speech adapter not configured\");\n\n const { message } = this.repository.getMessage(messageId);\n\n this._stopSpeaking?.();\n\n const utterance = adapter.speak(getThreadMessageText(message));\n const unsub = utterance.subscribe(() => {\n if (utterance.status.type === \"ended\") {\n this._stopSpeaking = undefined;\n this.speech = undefined;\n } else {\n this.speech = { messageId, status: utterance.status };\n }\n this._notifySubscribers();\n });\n\n this.speech = { messageId, status: utterance.status };\n this._notifySubscribers();\n\n this._stopSpeaking = () => {\n utterance.cancel();\n unsub();\n this.speech = undefined;\n this._stopSpeaking = undefined;\n };\n }\n\n public stopSpeaking() {\n if (!this._stopSpeaking) throw new Error(\"No message is being spoken\");\n this._stopSpeaking();\n this._notifySubscribers();\n }\n\n private _voiceSession: RealtimeVoiceAdapter.Session | undefined;\n private _voiceUnsubs: Array<() => void> = [];\n public voice: VoiceSessionState | undefined;\n\n private _voiceVolume = 0;\n private _voiceVolumeSubscribers = new Set<() => void>();\n\n public getVoiceVolume = () => this._voiceVolume;\n\n public subscribeVoiceVolume = (callback: () => void): Unsubscribe => {\n this._voiceVolumeSubscribers.add(callback);\n return () => this._voiceVolumeSubscribers.delete(callback);\n };\n\n public connectVoice() {\n const adapter = this.adapters?.voice;\n if (!adapter) throw new Error(\"Voice adapter not configured\");\n\n this.disconnectVoice();\n\n const session = adapter.connect({});\n this._voiceSession = session;\n const unsubs: Array<() => void> = [];\n\n let currentMode: RealtimeVoiceAdapter.Mode = \"listening\";\n\n this.voice = {\n status: session.status,\n isMuted: session.isMuted,\n mode: currentMode,\n };\n this._voiceVolume = 0;\n this._notifySubscribers();\n\n unsubs.push(\n session.onStatusChange((status) => {\n if (status.type === \"ended\") {\n this._finishVoiceAssistantMessage();\n this._voiceSession = undefined;\n this.voice = undefined;\n } else {\n this.voice = {\n status,\n isMuted: session.isMuted,\n mode: currentMode,\n };\n }\n this._notifySubscribers();\n }),\n );\n\n unsubs.push(\n session.onModeChange((mode) => {\n currentMode = mode;\n if (this.voice) {\n this.voice = { ...this.voice, mode };\n this._notifySubscribers();\n }\n }),\n );\n\n unsubs.push(\n session.onVolumeChange((volume) => {\n this._voiceVolume = volume;\n notifyEventListeners(\n this._voiceVolumeSubscribers,\n undefined,\n \"Voice volume\",\n );\n }),\n );\n\n unsubs.push(\n session.onTranscript((transcript) => {\n this._handleVoiceTranscript(transcript);\n }),\n );\n\n this._voiceUnsubs = unsubs;\n }\n\n private _currentAssistantMsg: ThreadAssistantMessage | null = null;\n\n private _handleVoiceTranscript(\n transcript: RealtimeVoiceAdapter.TranscriptItem,\n ) {\n this.ensureInitialized();\n\n if (transcript.role === \"user\") {\n this._finishVoiceAssistantMessage();\n this._currentAssistantMsg = null;\n\n if (transcript.isFinal) {\n this._voiceMessages.push({\n id: generateId(),\n role: \"user\",\n content: [{ type: \"text\", text: transcript.text }],\n metadata: { custom: {} },\n createdAt: new Date(),\n status: { type: \"complete\", reason: \"unknown\" },\n attachments: [],\n });\n this._markVoiceMessagesDirty();\n this._notifySubscribers();\n }\n } else {\n const status: ThreadAssistantMessage[\"status\"] = transcript.isFinal\n ? { type: \"complete\", reason: \"stop\" }\n : { type: \"running\" };\n\n if (!this._currentAssistantMsg) {\n this._currentAssistantMsg = {\n id: generateId(),\n role: \"assistant\",\n content: [{ type: \"text\", text: transcript.text }],\n metadata: {\n unstable_state: this.state,\n unstable_annotations: [],\n unstable_data: [],\n steps: [],\n custom: {},\n },\n status,\n createdAt: new Date(),\n };\n this._voiceMessages.push(this._currentAssistantMsg);\n } else {\n const idx = this._voiceMessages.indexOf(this._currentAssistantMsg);\n if (idx === -1) return;\n const updated: ThreadAssistantMessage = {\n ...this._currentAssistantMsg,\n content: [{ type: \"text\", text: transcript.text }],\n status,\n };\n this._voiceMessages[idx] = updated;\n this._currentAssistantMsg = updated;\n }\n\n if (transcript.isFinal) {\n this._currentAssistantMsg = null;\n }\n\n this._markVoiceMessagesDirty();\n this._notifySubscribers();\n }\n }\n\n private _finishVoiceAssistantMessage() {\n const last = this._voiceMessages.at(-1);\n if (last?.role === \"assistant\" && last.status.type === \"running\") {\n const idx = this._voiceMessages.length - 1;\n this._voiceMessages[idx] = {\n ...(last as ThreadAssistantMessage),\n status: { type: \"complete\", reason: \"stop\" },\n };\n this._markVoiceMessagesDirty();\n this._notifySubscribers();\n }\n }\n\n public disconnectVoice() {\n this._finishVoiceAssistantMessage();\n this._currentAssistantMsg = null;\n for (const unsub of this._voiceUnsubs) unsub();\n this._voiceUnsubs = [];\n this._voiceSession?.disconnect();\n this._voiceSession = undefined;\n this.voice = undefined;\n this._voiceVolume = 0;\n notifyEventListeners(\n this._voiceVolumeSubscribers,\n undefined,\n \"Voice volume\",\n );\n this._voiceMessages = [];\n this._markVoiceMessagesDirty();\n this._notifySubscribers();\n }\n\n public muteVoice() {\n if (!this._voiceSession) throw new Error(\"No active voice session\");\n this._voiceSession.mute();\n this.voice = {\n ...this.voice!,\n isMuted: true,\n };\n this._notifySubscribers();\n }\n\n public unmuteVoice() {\n if (!this._voiceSession) throw new Error(\"No active voice session\");\n this._voiceSession.unmute();\n this.voice = {\n ...this.voice!,\n isMuted: false,\n };\n this._notifySubscribers();\n }\n\n protected ensureInitialized() {\n if (!this._isInitialized) {\n this._isInitialized = true;\n this._notifyEventSubscribers(\"initialize\", {});\n }\n }\n\n public export() {\n return this.repository.export();\n }\n\n public import(data: ExportedMessageRepository) {\n this.ensureInitialized();\n this.repository.clear();\n this.repository.import(data);\n this._notifySubscribers();\n }\n\n public reset(initialMessages?: readonly ThreadMessageLike[]) {\n this.import(ExportedMessageRepository.fromArray(initialMessages ?? []));\n }\n\n private _eventSubscribers = new Map<\n ThreadRuntimeEventType,\n Set<(payload?: unknown) => void>\n >();\n\n public unstable_on<E extends ThreadRuntimeEventType>(\n event: E,\n callback: ThreadRuntimeEventCallback<E>,\n ) {\n const wrapped = callback as (payload?: unknown) => void;\n if (event === \"modelContextUpdate\") {\n // provider.subscribe is `() => void`; pump the typed empty payload to the user callback.\n return (\n this._contextProvider.subscribe?.(() =>\n notifyEventListeners([wrapped], {}, `Thread runtime \"${event}\"`),\n ) ?? (() => {})\n );\n }\n\n let subscribers = this._eventSubscribers.get(event);\n if (!subscribers) {\n subscribers = new Set();\n this._eventSubscribers.set(event, subscribers);\n }\n subscribers.add(wrapped);\n\n // `initialize` latches: replay it (deferred) to subscribers that attach\n // after the thread already initialized, mirroring a BehaviorSubject.\n if (event === \"initialize\" && this._isInitialized) {\n queueMicrotask(() => {\n if (subscribers.has(wrapped)) {\n notifyEventListeners([wrapped], {}, `Thread runtime \"${event}\"`);\n }\n });\n }\n\n return () => {\n this._eventSubscribers.get(event)?.delete(wrapped);\n };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"base-thread-runtime-core.js","names":["AppendMessage","ThreadAssistantMessage","ThreadMessage","Unsubscribe","ModelContextProvider","getThreadMessageText","generateId","ExportedMessageRepository","MessageRepository","DefaultThreadComposerRuntimeCore","AddToolResultOptions","ResumeToolCallOptions","RespondToToolApprovalOptions","ThreadSuggestion","SubmitFeedbackOptions","ThreadRuntimeCore","SpeechState","VoiceSessionState","RuntimeCapabilities","ThreadRuntimeEventCallback","ThreadRuntimeEventPayload","ThreadRuntimeEventType","StartRunConfig","ResumeRunConfig","DefaultEditComposerRuntimeCore","SpeechSynthesisAdapter","FeedbackAdapter","AttachmentAdapter","RealtimeVoiceAdapter","ThreadMessageLike","notifyEventListeners","gateInteractableComposerMetadata","BaseSubscribable","notifySubscribers","BaseThreadAdapters","speech","feedback","attachments","voice","BaseThreadRuntimeCore","_isInitialized","repository","adapters","isDisabled","isSendDisabled","isLoading","suggestions","extras","capabilities","append","message","deleteMessage","messageId","Promise","startRun","config","resumeRun","addToolResult","options","resumeToolCall","respondToToolApproval","cancelRun","exportExternalState","importExternalState","state","unstable_notifySessionReset","_voiceMessages","_voiceGeneration","_cachedMergedMessages","_cachedVoiceGeneration","_cachedMergedBase","_markVoiceMessagesDirty","_getBaseMessages","getMessages","messages","length","base","mostRecentAssistantMessage","this","role","metadata","unstable_state","composer","_contextProvider","constructor","getModelContext","enrichAppendMetadata","anchorId","parentId","parentIndex","findIndex","m","id","composerMetadata","unstable_composerMetadata","slice","custom","_editComposers","Map","getEditComposer","get","_isVoiceMessage","some","beginEdit","Error","has","set","delete","getMessage","_notifySubscribers","getMessageById","baseMessages","voiceIdx","at","index","undefined","getBranches","switchToBranch","branchId","_notifyEventSubscribers","event","E","payload","subscribers","_eventSubscribers","_notifyToolApprovalAnswered","toolCallId","toolName","approved","submitFeedback","type","adapter","entry","submit","updatedMessage","submittedFeedback","voiceMessage","addOrUpdateMessage","_currentAssistantMsg","_stopSpeaking","speak","previousStop","utterance","Utterance","error","notificationError","console","unsub","clear","cleanup","stop","cancel","update","status","subscribe","cleanupError","stopSpeaking","_voiceSession","Session","_voiceUnsubs","Array","_voiceVolume","_voiceVolumeSubscribers","Set","getVoiceVolume","subscribeVoiceVolume","callback","add","connectVoice","disconnectVoice","session","connect","unsubs","finishDetachedSetup","splice","currentMode","Mode","isMuted","mode","push","onStatusChange","_finishVoiceAssistantMessage","onModeChange","onVolumeChange","volume","onTranscript","transcript","_handleVoiceTranscript","TranscriptItem","ensureInitialized","isFinal","content","text","modality","createdAt","Date","reason","unstable_annotations","unstable_data","steps","idx","indexOf","updated","last","disconnect","muteVoice","mute","unmuteVoice","unmute","export","import","data","reset","initialMessages","fromArray","unstable_on","wrapped","queueMicrotask"],"sources":["../../../src/runtime/base/base-thread-runtime-core.ts"],"sourcesContent":["import type {\n AppendMessage,\n ThreadAssistantMessage,\n ThreadMessage,\n} from \"../../types/message\";\nimport type { Unsubscribe } from \"../../types/unsubscribe\";\nimport type { ModelContextProvider } from \"../../model-context/types\";\nimport { getThreadMessageText } from \"../../utils/text\";\nimport { generateId } from \"../../utils/id\";\nimport {\n ExportedMessageRepository,\n MessageRepository,\n} from \"../utils/message-repository\";\nimport { DefaultThreadComposerRuntimeCore } from \"./default-thread-composer-runtime-core\";\nimport type {\n AddToolResultOptions,\n ResumeToolCallOptions,\n RespondToToolApprovalOptions,\n ThreadSuggestion,\n SubmitFeedbackOptions,\n ThreadRuntimeCore,\n SpeechState,\n VoiceSessionState,\n RuntimeCapabilities,\n ThreadRuntimeEventCallback,\n ThreadRuntimeEventPayload,\n ThreadRuntimeEventType,\n StartRunConfig,\n ResumeRunConfig,\n} from \"../interfaces/thread-runtime-core\";\nimport { DefaultEditComposerRuntimeCore } from \"./default-edit-composer-runtime-core\";\nimport type { SpeechSynthesisAdapter } from \"../../adapters/speech\";\nimport type { FeedbackAdapter } from \"../../adapters/feedback\";\nimport type { AttachmentAdapter } from \"../../adapters/attachment\";\nimport type { RealtimeVoiceAdapter } from \"../../adapters/voice\";\nimport type { ThreadMessageLike } from \"../utils/thread-message-like\";\nimport { notifyEventListeners } from \"../../utils/notify-event-listeners\";\nimport { gateInteractableComposerMetadata } from \"../../model-context/interactable-composer-metadata\";\nimport {\n BaseSubscribable,\n notifySubscribers,\n} from \"../../subscribable/subscribable\";\n\ntype BaseThreadAdapters = {\n speech?: SpeechSynthesisAdapter | undefined;\n feedback?: FeedbackAdapter | undefined;\n attachments?: AttachmentAdapter | undefined;\n voice?: RealtimeVoiceAdapter | undefined;\n};\n\nexport abstract class BaseThreadRuntimeCore\n extends BaseSubscribable\n implements ThreadRuntimeCore\n{\n private _isInitialized = false;\n\n protected repository = new MessageRepository();\n public abstract get adapters(): BaseThreadAdapters | undefined;\n public abstract get isDisabled(): boolean;\n public abstract get isSendDisabled(): boolean;\n public abstract get isLoading(): boolean;\n public abstract get suggestions(): readonly ThreadSuggestion[];\n public abstract get extras(): unknown;\n\n public abstract get capabilities(): RuntimeCapabilities;\n public abstract append(message: AppendMessage): void;\n public abstract deleteMessage(messageId: string): void | Promise<void>;\n public abstract startRun(config: StartRunConfig): void;\n public abstract resumeRun(config: ResumeRunConfig): void;\n public abstract addToolResult(options: AddToolResultOptions): void;\n public abstract resumeToolCall(options: ResumeToolCallOptions): void;\n public abstract respondToToolApproval(\n options: RespondToToolApprovalOptions,\n ): Promise<void>;\n public abstract cancelRun(): void;\n public abstract exportExternalState(): any;\n public abstract importExternalState(state: any): void;\n public abstract unstable_notifySessionReset(): void;\n\n protected _voiceMessages: ThreadMessage[] = [];\n protected _voiceGeneration = 0;\n private _cachedMergedMessages: readonly ThreadMessage[] | null = null;\n private _cachedVoiceGeneration = -1;\n private _cachedMergedBase: readonly ThreadMessage[] | null = null;\n\n protected _markVoiceMessagesDirty() {\n this._voiceGeneration++;\n this._cachedMergedMessages = null;\n }\n\n protected _getBaseMessages(): readonly ThreadMessage[] {\n return this.repository.getMessages();\n }\n\n public get messages(): readonly ThreadMessage[] {\n if (this._voiceMessages.length === 0) {\n return this._getBaseMessages();\n }\n const base = this._getBaseMessages();\n if (\n this._cachedVoiceGeneration !== this._voiceGeneration ||\n this._cachedMergedBase !== base\n ) {\n this._cachedMergedMessages = [...base, ...this._voiceMessages];\n this._cachedVoiceGeneration = this._voiceGeneration;\n this._cachedMergedBase = base;\n }\n return this._cachedMergedMessages!;\n }\n\n public get state() {\n let mostRecentAssistantMessage: (typeof this.messages)[number] | undefined;\n for (const message of this.messages) {\n if (message.role === \"assistant\") {\n mostRecentAssistantMessage = message;\n }\n }\n\n return mostRecentAssistantMessage?.metadata.unstable_state ?? null;\n }\n\n public readonly composer = new DefaultThreadComposerRuntimeCore(this);\n\n private readonly _contextProvider: ModelContextProvider;\n\n constructor(_contextProvider: ModelContextProvider) {\n super();\n this._contextProvider = _contextProvider;\n }\n\n public getModelContext() {\n return this._contextProvider.getModelContext();\n }\n\n /**\n * Stamps provider-contributed composer metadata onto an outgoing message.\n * Called at dispatch rather than in the composer, so programmatic sends are\n * covered too, and exactly once per message: a queued send is stamped when\n * it leaves the lane, never when it enters.\n *\n * Only user messages are stamped, matching the readers: both the version\n * fold and the model injection skip every other role.\n *\n * @param anchorId Message the gated branch prefix ends at. A queued send\n * passes the current tail, having waited through a run that grew the prefix\n * past the parent it was created with.\n */\n protected enrichAppendMetadata(\n message: AppendMessage,\n anchorId: string | null = message.parentId,\n ): AppendMessage {\n if (message.role !== \"user\") return message;\n const messages = this.messages;\n const parentIndex =\n anchorId === null ? -1 : messages.findIndex((m) => m.id === anchorId);\n const composerMetadata = gateInteractableComposerMetadata(\n this.getModelContext().unstable_composerMetadata,\n messages.slice(0, parentIndex + 1),\n );\n if (!composerMetadata) return message;\n return {\n ...message,\n metadata: {\n ...message.metadata,\n custom: { ...message.metadata?.custom, ...composerMetadata },\n },\n };\n }\n\n private _editComposers = new Map<string, DefaultEditComposerRuntimeCore>();\n public getEditComposer(messageId: string) {\n return this._editComposers.get(messageId);\n }\n protected _isVoiceMessage(messageId: string | null) {\n return (\n messageId !== null && this._voiceMessages.some((m) => m.id === messageId)\n );\n }\n\n public beginEdit(messageId: string) {\n if (this._isVoiceMessage(messageId)) {\n throw new Error(\"Voice transcript messages cannot be edited\");\n }\n if (this._editComposers.has(messageId))\n throw new Error(\"Edit already in progress\");\n\n this._editComposers.set(\n messageId,\n new DefaultEditComposerRuntimeCore(\n this,\n () => this._editComposers.delete(messageId),\n this.repository.getMessage(messageId),\n ),\n );\n this._notifySubscribers();\n }\n\n public getMessageById(messageId: string) {\n try {\n return this.repository.getMessage(messageId);\n } catch {\n // Check voice messages\n const baseMessages = this.repository.getMessages();\n const voiceIdx = this._voiceMessages.findIndex((m) => m.id === messageId);\n if (voiceIdx !== -1) {\n const parentId =\n voiceIdx > 0\n ? this._voiceMessages[voiceIdx - 1]!.id\n : (baseMessages.at(-1)?.id ?? null);\n return {\n parentId,\n message: this._voiceMessages[voiceIdx]!,\n index: baseMessages.length + voiceIdx,\n };\n }\n return undefined;\n }\n }\n\n public getBranches(messageId: string): string[] {\n if (this._voiceMessages.some((m) => m.id === messageId)) {\n return [];\n }\n return this.repository.getBranches(messageId);\n }\n\n public switchToBranch(branchId: string): void {\n this.repository.switchToBranch(branchId);\n this._notifySubscribers();\n }\n\n public _notifyEventSubscribers<E extends ThreadRuntimeEventType>(\n event: E,\n payload: ThreadRuntimeEventPayload[E],\n ) {\n const subscribers = this._eventSubscribers.get(event);\n if (!subscribers) return;\n\n notifyEventListeners(subscribers, payload, `Thread runtime \"${event}\"`);\n }\n\n protected _notifyToolApprovalAnswered(\n messageId: string,\n toolCallId: string,\n toolName: string,\n approved: boolean,\n ) {\n this._notifyEventSubscribers(\"toolApprovalAnswered\", {\n messageId,\n toolCallId,\n toolName,\n approved,\n });\n }\n\n public submitFeedback({ messageId, type }: SubmitFeedbackOptions) {\n const adapter = this.adapters?.feedback;\n if (!adapter) throw new Error(\"Feedback adapter not configured\");\n\n const entry = this.getMessageById(messageId);\n if (!entry) throw new Error(`Message not found: ${messageId}`);\n const { message, parentId } = entry;\n adapter.submit({ message, type });\n\n if (message.role === \"assistant\") {\n const updatedMessage: ThreadMessage = {\n ...message,\n metadata: {\n ...message.metadata,\n submittedFeedback: { type },\n },\n };\n const voiceIdx = this._voiceMessages.findIndex(\n (voiceMessage) => voiceMessage.id === messageId,\n );\n if (voiceIdx === -1) {\n this.repository.addOrUpdateMessage(parentId, updatedMessage);\n } else {\n this._voiceMessages[voiceIdx] = updatedMessage;\n if (this._currentAssistantMsg === message) {\n this._currentAssistantMsg = updatedMessage as ThreadAssistantMessage;\n }\n this._markVoiceMessagesDirty();\n }\n }\n\n this._notifySubscribers();\n }\n\n private _stopSpeaking: Unsubscribe | undefined;\n public speech: SpeechState | undefined;\n\n public speak(messageId: string) {\n const adapter = this.adapters?.speech;\n if (!adapter) throw new Error(\"Speech adapter not configured\");\n\n const entry = this.getMessageById(messageId);\n if (!entry) throw new Error(`Message not found: ${messageId}`);\n const { message } = entry;\n\n const previousStop = this._stopSpeaking;\n let utterance: SpeechSynthesisAdapter.Utterance;\n try {\n previousStop?.();\n utterance = adapter.speak(getThreadMessageText(message));\n } catch (error) {\n if (previousStop && !this._stopSpeaking) {\n try {\n this._notifySubscribers();\n } catch (notificationError) {\n console.error(\n \"[assistant-ui] Speech rollback notification threw\",\n notificationError,\n );\n }\n }\n throw error;\n }\n let unsub: Unsubscribe | undefined;\n const clear = () => {\n this._stopSpeaking = undefined;\n this.speech = undefined;\n const cleanup = unsub;\n unsub = undefined;\n cleanup?.();\n };\n const stop = () => {\n if (this._stopSpeaking !== stop) return;\n try {\n clear();\n } finally {\n utterance.cancel();\n }\n };\n const update = () => {\n if (this._stopSpeaking !== stop) return;\n if (utterance.status.type === \"ended\") {\n notifySubscribers([clear, () => this._notifySubscribers()]);\n } else {\n this.speech = { messageId, status: utterance.status };\n this._notifySubscribers();\n }\n };\n\n this._stopSpeaking = stop;\n try {\n unsub = utterance.subscribe(update);\n if (this._stopSpeaking !== stop) {\n unsub();\n return;\n }\n update();\n } catch (error) {\n if (this._stopSpeaking === stop) {\n try {\n notifySubscribers([stop, () => this._notifySubscribers()]);\n } catch (cleanupError) {\n console.error(\n \"[assistant-ui] Speech rollback cleanup threw\",\n cleanupError,\n );\n }\n }\n throw error;\n }\n }\n\n public stopSpeaking() {\n if (!this._stopSpeaking) throw new Error(\"No message is being spoken\");\n notifySubscribers([this._stopSpeaking, () => this._notifySubscribers()]);\n }\n\n private _voiceSession: RealtimeVoiceAdapter.Session | undefined;\n private _voiceUnsubs: Array<() => void> = [];\n public voice: VoiceSessionState | undefined;\n\n private _voiceVolume = 0;\n private _voiceVolumeSubscribers = new Set<() => void>();\n\n public getVoiceVolume = () => this._voiceVolume;\n\n public subscribeVoiceVolume = (callback: () => void): Unsubscribe => {\n this._voiceVolumeSubscribers.add(callback);\n return () => this._voiceVolumeSubscribers.delete(callback);\n };\n\n public connectVoice() {\n const adapter = this.adapters?.voice;\n if (!adapter) throw new Error(\"Voice adapter not configured\");\n\n try {\n this.disconnectVoice();\n } catch (error) {\n console.error(\n \"[assistant-ui] Voice cleanup threw before reconnect\",\n error,\n );\n }\n\n const session = adapter.connect({});\n this._voiceSession = session;\n const unsubs: Array<() => void> = [];\n this._voiceUnsubs = unsubs;\n\n // The cleanup-list identity preserves ownership after an ended status clears the session.\n const finishDetachedSetup = () => {\n if (this._voiceSession === session && this._voiceUnsubs === unsubs) {\n return false;\n }\n\n try {\n notifySubscribers(unsubs.splice(0));\n } catch (error) {\n console.error(\n \"[assistant-ui] Detached voice setup cleanup threw\",\n error,\n );\n }\n return true;\n };\n\n try {\n let currentMode: RealtimeVoiceAdapter.Mode = \"listening\";\n\n this.voice = {\n status: session.status,\n isMuted: session.isMuted,\n mode: currentMode,\n };\n this._voiceVolume = 0;\n this._notifySubscribers();\n if (finishDetachedSetup()) return;\n\n unsubs.push(\n session.onStatusChange((status) => {\n if (status.type === \"ended\") {\n this._finishVoiceAssistantMessage();\n this._voiceSession = undefined;\n this.voice = undefined;\n } else {\n this.voice = {\n status,\n isMuted: session.isMuted,\n mode: currentMode,\n };\n }\n this._notifySubscribers();\n }),\n );\n if (finishDetachedSetup()) return;\n\n unsubs.push(\n session.onModeChange((mode) => {\n currentMode = mode;\n if (this.voice) {\n this.voice = { ...this.voice, mode };\n this._notifySubscribers();\n }\n }),\n );\n if (finishDetachedSetup()) return;\n\n unsubs.push(\n session.onVolumeChange((volume) => {\n this._voiceVolume = volume;\n notifyEventListeners(\n this._voiceVolumeSubscribers,\n undefined,\n \"Voice volume\",\n );\n }),\n );\n if (finishDetachedSetup()) return;\n\n unsubs.push(\n session.onTranscript((transcript) => {\n this._handleVoiceTranscript(transcript);\n }),\n );\n finishDetachedSetup();\n } catch (error) {\n if (this._voiceSession === session && this._voiceUnsubs === unsubs) {\n try {\n this.disconnectVoice();\n } catch (cleanupError) {\n console.error(\n \"[assistant-ui] Voice rollback cleanup threw\",\n cleanupError,\n );\n }\n } else {\n finishDetachedSetup();\n }\n throw error;\n }\n }\n\n private _currentAssistantMsg: ThreadAssistantMessage | null = null;\n\n private _handleVoiceTranscript(\n transcript: RealtimeVoiceAdapter.TranscriptItem,\n ) {\n this.ensureInitialized();\n\n if (transcript.role === \"user\") {\n this._finishVoiceAssistantMessage();\n this._currentAssistantMsg = null;\n\n if (transcript.isFinal) {\n this._voiceMessages.push({\n id: generateId(),\n role: \"user\",\n content: [{ type: \"text\", text: transcript.text }],\n metadata: { modality: \"voice\", custom: {} },\n createdAt: new Date(),\n status: { type: \"complete\", reason: \"unknown\" },\n attachments: [],\n });\n this._markVoiceMessagesDirty();\n this._notifySubscribers();\n }\n } else {\n const status: ThreadAssistantMessage[\"status\"] = transcript.isFinal\n ? { type: \"complete\", reason: \"stop\" }\n : { type: \"running\" };\n\n if (!this._currentAssistantMsg) {\n this._currentAssistantMsg = {\n id: generateId(),\n role: \"assistant\",\n content: [{ type: \"text\", text: transcript.text }],\n metadata: {\n unstable_state: this.state,\n unstable_annotations: [],\n unstable_data: [],\n steps: [],\n modality: \"voice\",\n custom: {},\n },\n status,\n createdAt: new Date(),\n };\n this._voiceMessages.push(this._currentAssistantMsg);\n } else {\n const idx = this._voiceMessages.indexOf(this._currentAssistantMsg);\n if (idx === -1) return;\n const updated: ThreadAssistantMessage = {\n ...this._currentAssistantMsg,\n content: [{ type: \"text\", text: transcript.text }],\n status,\n };\n this._voiceMessages[idx] = updated;\n this._currentAssistantMsg = updated;\n }\n\n if (transcript.isFinal) {\n this._currentAssistantMsg = null;\n }\n\n this._markVoiceMessagesDirty();\n this._notifySubscribers();\n }\n }\n\n private _finishVoiceAssistantMessage() {\n const last = this._voiceMessages.at(-1);\n if (last?.role === \"assistant\" && last.status.type === \"running\") {\n const idx = this._voiceMessages.length - 1;\n this._voiceMessages[idx] = {\n ...(last as ThreadAssistantMessage),\n status: { type: \"complete\", reason: \"stop\" },\n };\n this._markVoiceMessagesDirty();\n this._notifySubscribers();\n }\n }\n\n public disconnectVoice() {\n this._currentAssistantMsg = null;\n // Drain the shared list in place so reentrant setup cannot release the same handles again.\n const unsubs = this._voiceUnsubs.splice(0);\n this._voiceUnsubs = [];\n const session = this._voiceSession;\n this._voiceSession = undefined;\n this.voice = undefined;\n this._voiceVolume = 0;\n const stopSpeaking =\n this.speech && this._isVoiceMessage(this.speech.messageId)\n ? this._stopSpeaking\n : undefined;\n this._voiceMessages = [];\n this._markVoiceMessagesDirty();\n\n notifySubscribers([\n ...unsubs,\n ...(stopSpeaking ? [stopSpeaking] : []),\n ...(session ? [() => session.disconnect()] : []),\n () =>\n notifyEventListeners(\n this._voiceVolumeSubscribers,\n undefined,\n \"Voice volume\",\n ),\n () => this._notifySubscribers(),\n ]);\n }\n\n public muteVoice() {\n if (!this._voiceSession) throw new Error(\"No active voice session\");\n this._voiceSession.mute();\n this.voice = {\n ...this.voice!,\n isMuted: true,\n };\n this._notifySubscribers();\n }\n\n public unmuteVoice() {\n if (!this._voiceSession) throw new Error(\"No active voice session\");\n this._voiceSession.unmute();\n this.voice = {\n ...this.voice!,\n isMuted: false,\n };\n this._notifySubscribers();\n }\n\n protected ensureInitialized() {\n if (!this._isInitialized) {\n this._isInitialized = true;\n this._notifyEventSubscribers(\"initialize\", {});\n }\n }\n\n public export() {\n return this.repository.export();\n }\n\n public import(data: ExportedMessageRepository) {\n this.ensureInitialized();\n this.repository.clear();\n this.repository.import(data);\n this._notifySubscribers();\n }\n\n public reset(initialMessages?: readonly ThreadMessageLike[]) {\n this.import(ExportedMessageRepository.fromArray(initialMessages ?? []));\n }\n\n private _eventSubscribers = new Map<\n ThreadRuntimeEventType,\n Set<(payload?: unknown) => void>\n >();\n\n public unstable_on<E extends ThreadRuntimeEventType>(\n event: E,\n callback: ThreadRuntimeEventCallback<E>,\n ) {\n const wrapped = callback as (payload?: unknown) => void;\n if (event === \"modelContextUpdate\") {\n // provider.subscribe is `() => void`; pump the typed empty payload to the user callback.\n return (\n this._contextProvider.subscribe?.(() =>\n notifyEventListeners([wrapped], {}, `Thread runtime \"${event}\"`),\n ) ?? (() => {})\n );\n }\n\n let subscribers = this._eventSubscribers.get(event);\n if (!subscribers) {\n subscribers = new Set();\n this._eventSubscribers.set(event, subscribers);\n }\n subscribers.add(wrapped);\n\n // `initialize` latches: replay it (deferred) to subscribers that attach\n // after the thread already initialized, mirroring a BehaviorSubject.\n if (event === \"initialize\" && this._isInitialized) {\n queueMicrotask(() => {\n if (subscribers.has(wrapped)) {\n notifyEventListeners([wrapped], {}, `Thread runtime \"${event}\"`);\n }\n });\n }\n\n return () => {\n this._eventSubscribers.get(event)?.delete(wrapped);\n };\n }\n}\n"],"mappings":"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"}
@@ -82,6 +82,12 @@ type SubmittedFeedback = {
82
82
  readonly type: "negative" | "positive";
83
83
  };
84
84
  type ThreadRuntimeEventPayload = {
85
+ toolApprovalAnswered: {
86
+ messageId: string;
87
+ toolCallId: string;
88
+ toolName: string;
89
+ approved: boolean;
90
+ };
85
91
  /**
86
92
  * @deprecated State-derivable. Observe `state.isRunning` flipping to `true`
87
93
  * via `subscribe` + `getState` instead. Note: this event fires at the
@@ -1 +1 @@
1
- {"version":3,"file":"thread-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/interfaces/thread-runtime-core.ts"],"mappings":";;;;;;;;;;;;;;KAqBY;WACD;WACA;WACA;WACA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;KAGC;EACV;EACA;EACA;EACA,QAAQ;EACR;EACA,WAAW;;;;;;;EAOX,wBAAwB;;KAGd;EACV;EACA;;KAGU;EACV;EACA;;EAEA;;EAEA;EACA;;KAGU;EACV;EACA;;KAGU;;EAEV;;EAEA;;EAEA;;KAGU;WACD;WACA,QAAQ,uBAAuB;;KAG9B;WACD,QAAQ,qBAAqB;WAC7B;WACA,MAAM,qBAAqB;;KAG1B;WACD;;KAGC;;;;;;;EAOV,UAAU;;;;;;;EAOV,QAAQ;;;;;;;;;EASR,YAAY;;;;;EAKZ,oBAAoB;;KAGV,+BAA+B;KAE/B,2BAA2B,UAAU,2BAC/C,SAAS,0BAA0B;KAGzB;EACV;EACA;EACA,WAAW;;KAGD,kBAAkB;EAC5B,UACE,SAAS,wBACN,eAAe;;KAGV,oBAAoB;EAC9B,iBAAiB;IAEX;IACA,SAAS;IACT;;EAIN,cAAc;EACd,iBAAiB;EAEjB,SAAS,SAAS;EAClB,gBAAgB,6BAA6B;EAC7C,WAAW,QAAQ;EACnB,YAAY,QAAQ;EACpB;EACA;EAEA,gBAAgB,SAAS;EACzB,iBAAiB,SAAS;;;;;;;;;;;;;EAa1B,wBACE,SAAS,iCACN;EAEL,QAAQ;EACR;EAEA;EACA;EACA;EACA;EAEA,iBAAiB,UAAU;EAE3B,uBAAuB;EAEvB,UAAU;EACV,kBAAkB,sBAAsB;EACxC,YAAY;EAEZ,+BAA+B;EAC/B,oCAAoC;EACpC,iBAAiB,qBAAqB,WAAW;EACjD,mBAAmB;EAEnB,QAAQ;EACR,OAAO;EAEP,cAAc,SAAS;EACvB;;;;;;EAMA;EACA;;;;;;;EAOA;EACA,mBAAmB;EACnB,OAAO;EACP,sBAAsB;EAEtB;EAEA,YAAY,yBAAyB;EAErC;EACA,uBAAuB,yBAAyB;EAEhD,OAAO,YAAY;EACnB,UAAU;EAEV;EACA,oBAAoB;EAEpB,MAAM,2BAA2B;;;;;;;;;;;;EAajC,gCAAgC;;;;;;EAOhC,YAAY,UAAU,wBACpB,OAAO,GACP,UAAU,2BAA2B,KACpC"}
1
+ {"version":3,"file":"thread-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/interfaces/thread-runtime-core.ts"],"mappings":";;;;;;;;;;;;;;KAqBY;WACD;WACA;WACA;WACA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;KAGC;EACV;EACA;EACA;EACA,QAAQ;EACR;EACA,WAAW;;;;;;;EAOX,wBAAwB;;KAGd;EACV;EACA;;KAGU;EACV;EACA;;EAEA;;EAEA;EACA;;KAGU;EACV;EACA;;KAGU;;EAEV;;EAEA;;EAEA;;KAGU;WACD;WACA,QAAQ,uBAAuB;;KAG9B;WACD,QAAQ,qBAAqB;WAC7B;WACA,MAAM,qBAAqB;;KAG1B;WACD;;KAGC;EACV;IACE;IACA;IACA;IACA;;;;;;;;EAQF,UAAU;;;;;;;EAOV,QAAQ;;;;;;;;;EASR,YAAY;;;;;EAKZ,oBAAoB;;KAGV,+BAA+B;KAE/B,2BAA2B,UAAU,2BAC/C,SAAS,0BAA0B;KAGzB;EACV;EACA;EACA,WAAW;;KAGD,kBAAkB;EAC5B,UACE,SAAS,wBACN,eAAe;;KAGV,oBAAoB;EAC9B,iBAAiB;IAEX;IACA,SAAS;IACT;;EAIN,cAAc;EACd,iBAAiB;EAEjB,SAAS,SAAS;EAClB,gBAAgB,6BAA6B;EAC7C,WAAW,QAAQ;EACnB,YAAY,QAAQ;EACpB;EACA;EAEA,gBAAgB,SAAS;EACzB,iBAAiB,SAAS;;;;;;;;;;;;;EAa1B,wBACE,SAAS,iCACN;EAEL,QAAQ;EACR;EAEA;EACA;EACA;EACA;EAEA,iBAAiB,UAAU;EAE3B,uBAAuB;EAEvB,UAAU;EACV,kBAAkB,sBAAsB;EACxC,YAAY;EAEZ,+BAA+B;EAC/B,oCAAoC;EACpC,iBAAiB,qBAAqB,WAAW;EACjD,mBAAmB;EAEnB,QAAQ;EACR,OAAO;EAEP,cAAc,SAAS;EACvB;;;;;;EAMA;EACA;;;;;;;EAOA;EACA,mBAAmB;EACnB,OAAO;EACP,sBAAsB;EAEtB;EAEA,YAAY,yBAAyB;EAErC;EACA,uBAAuB,yBAAyB;EAEhD,OAAO,YAAY;EACnB,UAAU;EAEV;EACA,oBAAoB;EAEpB,MAAM,2BAA2B;;;;;;;;;;;;EAajC,gCAAgC;;;;;;EAOhC,YAAY,UAAU,wBACpB,OAAO,GACP,UAAU,2BAA2B,KACpC"}
@@ -2,6 +2,11 @@ import { AppendMessage } from "../../types/message.js";
2
2
  import { ExternalThreadQueueAdapter } from "./external-thread-queue-adapter.js";
3
3
  //#region src/runtime/queue/message-queue.d.ts
4
4
  type MessageQueueDriver = {
5
+ /**
6
+ * A synchronous throw is treated as a run that never started and restores
7
+ * the message. A driver that already started work must call `notifyBusy`
8
+ * before throwing.
9
+ */
5
10
  run: (message: AppendMessage, options: {
6
11
  steer: boolean;
7
12
  }) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"message-queue.d.ts","names":[],"sources":["../../../src/runtime/queue/message-queue.ts"],"mappings":";;;KAcY;EACV,MAAM,SAAS,eAAe;IAAW;;;EAEzC;;KAGU;WACD,SAAS;;EAElB;;EAEA;;;;;;;EAOA;;EAEA;EACA,YAAY;;cAgCD,qBACX,QAAQ,uBACP"}
1
+ {"version":3,"file":"message-queue.d.ts","names":[],"sources":["../../../src/runtime/queue/message-queue.ts"],"mappings":";;;KAcY;;;;;;EAMV,MAAM,SAAS,eAAe;IAAW;;;EAEzC;;KAGU;WACD,SAAS;;EAElB;;EAEA;;;;;;;EAOA;;EAEA;EACA,YAAY;;cAsCD,qBACX,QAAQ,uBACP"}
@@ -28,6 +28,7 @@ const createMessageQueue = (driver) => {
28
28
  let suppressIdle = 0;
29
29
  let cancelSettles = 0;
30
30
  let interrupting = false;
31
+ let busyEdges = 0;
31
32
  const notify = () => {
32
33
  notifyEventListeners(subscribers, void 0, "Message queue");
33
34
  };
@@ -42,6 +43,18 @@ const createMessageQueue = (driver) => {
42
43
  prompt: getThreadMessageText(message),
43
44
  parts: getQueueItemParts(message)
44
45
  });
46
+ const restore = (lane, dispatch, index = 0) => {
47
+ paused = true;
48
+ messages.set(dispatch.id, dispatch.message);
49
+ setLanes({
50
+ ...lanes,
51
+ [lane]: [
52
+ ...lanes[lane].slice(0, index),
53
+ dispatch.item,
54
+ ...lanes[lane].slice(index)
55
+ ]
56
+ });
57
+ };
45
58
  const laneOf = (queueItemId) => {
46
59
  if (lanes.steer.some((item) => item.id === queueItemId)) return "steer";
47
60
  if (lanes.queue.some((item) => item.id === queueItemId)) return "queue";
@@ -58,21 +71,52 @@ const createMessageQueue = (driver) => {
58
71
  [lane]: lanes[lane].slice(1)
59
72
  });
60
73
  if (!message) return;
74
+ const dispatch = {
75
+ id: head.id,
76
+ item: head,
77
+ message
78
+ };
61
79
  running = true;
62
- driver.run(dispatchTransform(message), { steer: false });
80
+ const busyEdgesBeforeRun = busyEdges;
81
+ try {
82
+ driver.run(dispatchTransform(message), { steer: false });
83
+ } catch (error) {
84
+ if (busyEdges === busyEdgesBeforeRun) {
85
+ running = false;
86
+ restore(lane, dispatch);
87
+ }
88
+ throw error;
89
+ }
63
90
  };
64
- const interrupt = (message) => {
91
+ const interrupt = (dispatch, restoreLane = "steer", restoreIndex = 0) => {
65
92
  paused = false;
66
93
  suppressIdle += Math.max(cancelSettles, 1);
67
94
  cancelSettles = 0;
95
+ const restoreInterrupted = (replacementStarted = false) => {
96
+ if (replacementStarted) return;
97
+ const pendingSettles = suppressIdle;
98
+ suppressIdle = Math.max(pendingSettles - 1, 0);
99
+ cancelSettles = pendingSettles > 0 ? 1 : 0;
100
+ running = pendingSettles > 0;
101
+ restore(restoreLane, dispatch, restoreIndex);
102
+ };
68
103
  interrupting = true;
69
104
  try {
70
105
  driver.cancel();
106
+ } catch (error) {
107
+ restoreInterrupted();
108
+ throw error;
71
109
  } finally {
72
110
  interrupting = false;
73
111
  }
74
112
  running = true;
75
- driver.run(dispatchTransform(message), { steer: true });
113
+ const busyEdgesBeforeRun = busyEdges;
114
+ try {
115
+ driver.run(dispatchTransform(dispatch.message), { steer: true });
116
+ } catch (error) {
117
+ restoreInterrupted(busyEdges !== busyEdgesBeforeRun);
118
+ throw error;
119
+ }
76
120
  };
77
121
  const push = (lane, message) => {
78
122
  paused = false;
@@ -89,7 +133,12 @@ const createMessageQueue = (driver) => {
89
133
  };
90
134
  const steer = (message) => {
91
135
  if (running && driver.cancel) {
92
- interrupt(message);
136
+ const id = generateId();
137
+ interrupt({
138
+ id,
139
+ item: toItem(id, message),
140
+ message
141
+ });
93
142
  return;
94
143
  }
95
144
  push("steer", message);
@@ -98,7 +147,8 @@ const createMessageQueue = (driver) => {
98
147
  const fromLane = laneOf(queueItemId);
99
148
  if (!fromLane) throw new Error(`Unknown queue item "${queueItemId}".`);
100
149
  const toLane = placement.lane ?? fromLane;
101
- const item = lanes[fromLane].find((i) => i.id === queueItemId);
150
+ const fromIndex = lanes[fromLane].findIndex((i) => i.id === queueItemId);
151
+ const item = lanes[fromLane][fromIndex];
102
152
  const dest = (toLane === fromLane ? lanes[fromLane] : lanes[toLane]).filter((i) => i.id !== queueItemId);
103
153
  const anchorIndex = (anchor) => {
104
154
  if (anchor === queueItemId) throw new Error(`Queue item "${queueItemId}" cannot anchor itself.`);
@@ -122,7 +172,11 @@ const createMessageQueue = (driver) => {
122
172
  queue: lanes.queue.filter((i) => i.id !== queueItemId),
123
173
  steer: lanes.steer
124
174
  });
125
- interrupt(message);
175
+ interrupt({
176
+ id: queueItemId,
177
+ item,
178
+ message
179
+ }, fromLane, fromIndex);
126
180
  return;
127
181
  }
128
182
  const nextDest = [
@@ -181,6 +235,7 @@ const createMessageQueue = (driver) => {
181
235
  suppressIdle += cancelSettles;
182
236
  cancelSettles = 0;
183
237
  running = true;
238
+ busyEdges++;
184
239
  },
185
240
  notifyIdle: () => {
186
241
  if (suppressIdle > 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"message-queue.js","names":["AppendMessage","FileMessagePart","TextMessagePart","EMPTY_QUEUE_ITEMS","QueueItemState","generateId","notifyEventListeners","getThreadMessageText","ExternalThreadQueueAdapter","QueuePlacement","MessageQueueDriver","run","message","options","steer","cancel","MessageQueueController","adapter","notifyBusy","notifyIdle","notifyCancelled","clear","subscribe","callback","Lane","getQueueItemParts","source","content","attachments","flatMap","attachment","filter","part","type","parts","push","data","image","mimeType","filename","undefined","createMessageQueue","driver","lanes","Record","queue","messages","Map","subscribers","Set","running","paused","dispatchTransform","m","suppressIdle","cancelSettles","interrupting","notify","setLanes","next","items","steerItems","toItem","id","prompt","laneOf","queueItemId","some","item","advance","lane","length","head","get","delete","slice","interrupt","Math","max","set","enqueue","move","placement","fromLane","Error","toLane","find","i","dest","anchorIndex","anchor","index","findIndex","insertAfter","insertBefore","after","before","nextDest","edit","map","remove","__internal_setDispatchTransform","transform","__internal_notifyCancelled","add"],"sources":["../../../src/runtime/queue/message-queue.ts"],"sourcesContent":["import type {\n AppendMessage,\n FileMessagePart,\n TextMessagePart,\n} from \"../../types/message\";\nimport { EMPTY_QUEUE_ITEMS, type QueueItemState } from \"./queue-item\";\nimport { generateId } from \"../../utils/id\";\nimport { notifyEventListeners } from \"../../utils/notify-event-listeners\";\nimport { getThreadMessageText } from \"../../utils/text\";\nimport type {\n ExternalThreadQueueAdapter,\n QueuePlacement,\n} from \"./external-thread-queue-adapter\";\n\nexport type MessageQueueDriver = {\n run: (message: AppendMessage, options: { steer: boolean }) => void;\n /** When omitted, steering degrades to \"process next\" instead of interrupting. */\n cancel?: (() => void) | undefined;\n};\n\nexport type MessageQueueController = {\n readonly adapter: ExternalThreadQueueAdapter;\n /** Mark a run as in flight so concurrent sends buffer; call on the rising edge. */\n notifyBusy: () => void;\n /** Advances to the next pending message; call on the run's falling edge. */\n notifyIdle: () => void;\n /**\n * Pauses queue advance for a user-initiated cancel, so the cancelled run's\n * settle keeps the pending items instead of dispatching the next one; the\n * next explicit send or run start re-arms draining. Call before aborting\n * the run.\n */\n notifyCancelled: () => void;\n /** Empties both lanes without dispatching. */\n clear: () => void;\n subscribe: (callback: () => void) => () => void;\n};\n\ntype Lane = \"queue\" | \"steer\";\n\nconst getQueueItemParts = (\n message: AppendMessage,\n): readonly (FileMessagePart | TextMessagePart)[] => {\n // attachment-derived text is the file body, not user-authored prose;\n // project only the file/image content of attachments\n const source = [\n ...message.content,\n ...(message.attachments ?? []).flatMap((attachment) =>\n (attachment.content ?? []).filter((part) => part.type !== \"text\"),\n ),\n ];\n const parts: (FileMessagePart | TextMessagePart)[] = [];\n for (const part of source) {\n if (part.type === \"file\" || part.type === \"text\") {\n parts.push(part);\n } else if (part.type === \"image\") {\n parts.push({\n type: \"file\",\n data: part.image,\n mimeType: \"image/*\",\n ...(part.filename !== undefined && { filename: part.filename }),\n });\n }\n }\n return parts;\n};\n\nexport const createMessageQueue = (\n driver: MessageQueueDriver,\n): MessageQueueController => {\n let lanes: Record<Lane, readonly QueueItemState[]> = {\n queue: EMPTY_QUEUE_ITEMS,\n steer: EMPTY_QUEUE_ITEMS,\n };\n const messages = new Map<string, AppendMessage>();\n const subscribers = new Set<() => void>();\n\n let running = false;\n let paused = false;\n let dispatchTransform: (message: AppendMessage) => AppendMessage = (m) => m;\n // swallow the cancelled run's settle when steering so it does not double-advance\n let suppressIdle = 0;\n // settles from cancelled runs that must drop `running` without advancing\n let cancelSettles = 0;\n let interrupting = false;\n\n const notify = () => {\n notifyEventListeners(subscribers, undefined, \"Message queue\");\n };\n\n const setLanes = (next: Record<Lane, readonly QueueItemState[]>) => {\n lanes = next;\n adapter.items = next.queue;\n adapter.steerItems = next.steer;\n notify();\n };\n\n const toItem = (id: string, message: AppendMessage): QueueItemState => ({\n id,\n prompt: getThreadMessageText(message),\n parts: getQueueItemParts(message),\n });\n\n const laneOf = (queueItemId: string): Lane | undefined => {\n if (lanes.steer.some((item) => item.id === queueItemId)) return \"steer\";\n if (lanes.queue.some((item) => item.id === queueItemId)) return \"queue\";\n return undefined;\n };\n\n const advance = () => {\n if (running || paused) return;\n const lane: Lane = lanes.steer.length > 0 ? \"steer\" : \"queue\";\n const head = lanes[lane][0];\n if (!head) return;\n const message = messages.get(head.id);\n messages.delete(head.id);\n setLanes({ ...lanes, [lane]: lanes[lane].slice(1) });\n if (!message) return;\n running = true;\n driver.run(dispatchTransform(message), { steer: false });\n };\n\n const interrupt = (message: AppendMessage) => {\n paused = false;\n // the interrupted run settles exactly once, whether or not it was\n // already cancel-notified\n suppressIdle += Math.max(cancelSettles, 1);\n cancelSettles = 0;\n // a driver whose cancel routes through the runtime notifies this queue\n // back; the interrupt already accounted for that settle and is dispatching\n // in its place\n interrupting = true;\n try {\n driver.cancel!();\n } finally {\n interrupting = false;\n }\n running = true;\n driver.run(dispatchTransform(message), { steer: true });\n };\n\n const push = (lane: Lane, message: AppendMessage) => {\n paused = false;\n const id = generateId();\n messages.set(id, message);\n setLanes({ ...lanes, [lane]: [...lanes[lane], toItem(id, message)] });\n advance();\n };\n\n const enqueue = (message: AppendMessage) => {\n push(\"queue\", message);\n };\n\n const steer = (message: AppendMessage) => {\n if (running && driver.cancel) {\n interrupt(message);\n return;\n }\n push(\"steer\", message);\n };\n\n const move = (queueItemId: string, placement: QueuePlacement) => {\n const fromLane = laneOf(queueItemId);\n if (!fromLane) throw new Error(`Unknown queue item \"${queueItemId}\".`);\n const toLane = placement.lane ?? fromLane;\n\n const item = lanes[fromLane].find((i) => i.id === queueItemId)!;\n const dest = (toLane === fromLane ? lanes[fromLane] : lanes[toLane]).filter(\n (i) => i.id !== queueItemId,\n );\n\n const anchorIndex = (anchor: string) => {\n if (anchor === queueItemId)\n throw new Error(`Queue item \"${queueItemId}\" cannot anchor itself.`);\n const index = dest.findIndex((i) => i.id === anchor);\n if (index === -1)\n throw new Error(`Unknown anchor \"${anchor}\" in lane \"${toLane}\".`);\n return index;\n };\n\n const { insertAfter, insertBefore } = placement;\n let index: number;\n if (insertAfter === undefined && insertBefore === undefined) {\n index =\n toLane === fromLane\n ? lanes[fromLane].findIndex((i) => i.id === queueItemId)\n : dest.length;\n } else if (insertAfter !== undefined && insertBefore !== undefined) {\n const after = insertAfter === null ? -1 : anchorIndex(insertAfter);\n const before =\n insertBefore === null ? dest.length : anchorIndex(insertBefore);\n if (before !== after + 1)\n throw new Error(\n `insertAfter \"${insertAfter}\" and insertBefore \"${insertBefore}\" are not adjacent in lane \"${toLane}\".`,\n );\n index = after + 1;\n } else if (insertAfter !== undefined) {\n index = insertAfter === null ? 0 : anchorIndex(insertAfter) + 1;\n } else {\n index = insertBefore === null ? dest.length : anchorIndex(insertBefore!);\n }\n\n // placement and immediate dispatch cannot coexist: an anchored move into\n // the steer lane places without interrupting; only an unanchored one\n // cancels the live run and dispatches\n if (\n insertAfter === undefined &&\n insertBefore === undefined &&\n toLane === \"steer\" &&\n fromLane !== \"steer\" &&\n running &&\n driver.cancel\n ) {\n const message = messages.get(queueItemId)!;\n messages.delete(queueItemId);\n setLanes({\n queue: lanes.queue.filter((i) => i.id !== queueItemId),\n steer: lanes.steer,\n });\n interrupt(message);\n return;\n }\n\n const nextDest = [...dest.slice(0, index), item, ...dest.slice(index)];\n const next = { ...lanes, [toLane]: nextDest };\n if (toLane !== fromLane)\n next[fromLane] = lanes[fromLane].filter((i) => i.id !== queueItemId);\n setLanes(next);\n advance();\n };\n\n const edit = (queueItemId: string, message: AppendMessage) => {\n const lane = laneOf(queueItemId);\n if (!lane) throw new Error(`Unknown queue item \"${queueItemId}\".`);\n messages.set(queueItemId, message);\n setLanes({\n ...lanes,\n [lane]: lanes[lane].map((item) =>\n item.id === queueItemId ? toItem(queueItemId, message) : item,\n ),\n });\n };\n\n const remove = (queueItemId: string) => {\n if (!messages.delete(queueItemId)) return;\n setLanes({\n queue: lanes.queue.filter((item) => item.id !== queueItemId),\n steer: lanes.steer.filter((item) => item.id !== queueItemId),\n });\n };\n\n const notifyCancelled = () => {\n if (interrupting) return;\n if (running && cancelSettles === 0) {\n paused = true;\n cancelSettles = 1;\n }\n };\n\n const adapter: ExternalThreadQueueAdapter = {\n items: lanes.queue,\n steerItems: lanes.steer,\n enqueue,\n steer,\n move,\n edit,\n remove,\n __internal_setDispatchTransform: (transform) => {\n dispatchTransform = transform;\n },\n __internal_notifyCancelled: notifyCancelled,\n };\n\n return {\n adapter,\n notifyBusy: () => {\n paused = false;\n // a cancelled run's settle that is still outstanding belongs to a run\n // this new one replaces; swallow it entirely\n suppressIdle += cancelSettles;\n cancelSettles = 0;\n running = true;\n },\n notifyIdle: () => {\n if (suppressIdle > 0) {\n suppressIdle--;\n return;\n }\n if (cancelSettles > 0) cancelSettles--;\n running = false;\n advance();\n },\n notifyCancelled,\n clear: () => {\n messages.clear();\n setLanes({ queue: EMPTY_QUEUE_ITEMS, steer: EMPTY_QUEUE_ITEMS });\n },\n subscribe: (callback) => {\n subscribers.add(callback);\n return () => {\n subscribers.delete(callback);\n };\n },\n };\n};\n"],"mappings":";;;;;AAwCA,MAAMyB,qBACJb,YACmD;CAGnD,MAAMc,SAAS,CACb,GAAGd,QAAQe,SACX,IAAIf,QAAQgB,eAAe,CAAA,EAAA,CAAIC,SAASC,gBACrCA,WAAWH,WAAW,CAAA,EAAA,CAAII,QAAQC,SAASA,KAAKC,SAAS,MAAM,CAClE,CAAC;CAEH,MAAMC,QAA+C,CAAA;CACrD,KAAK,MAAMF,QAAQN,QACjB,IAAIM,KAAKC,SAAS,UAAUD,KAAKC,SAAS,QACxCC,MAAMC,KAAKH,IAAI;MACV,IAAIA,KAAKC,SAAS,SACvBC,MAAMC,KAAK;EACTF,MAAM;EACNG,MAAMJ,KAAKK;EACXC,UAAU;EACV,GAAIN,KAAKO,aAAaC,KAAAA,KAAa,EAAED,UAAUP,KAAKO,SAAS;CAC/D,CAAC;CAGL,OAAOL;AACT;AAEA,MAAaO,sBACXC,WAC2B;CAC3B,IAAIC,QAAiD;EACnDE,OAAO1C;EACPW,OAAOX;CACT;CACA,MAAM2C,2BAAW,IAAIC,IAA2B;CAChD,MAAMC,8BAAc,IAAIC,IAAgB;CAExC,IAAIC,UAAU;CACd,IAAIC,SAAS;CACb,IAAIC,qBAAgEC,MAAMA;CAE1E,IAAIC,eAAe;CAEnB,IAAIC,gBAAgB;CACpB,IAAIC,eAAe;CAEnB,MAAMC,eAAe;EACnBnD,qBAAqB0C,aAAaR,KAAAA,GAAW,eAAe;CAC9D;CAEA,MAAMkB,YAAYC,SAAkD;EAClEhB,QAAQgB;EACR1C,QAAQ2C,QAAQD,KAAKd;EACrB5B,QAAQ4C,aAAaF,KAAK7C;EAC1B2C,OAAO;CACT;CAEA,MAAMK,UAAUC,IAAYnD,aAA4C;EACtEmD;EACAC,QAAQzD,qBAAqBK,OAAO;EACpCsB,OAAOT,kBAAkBb,OAAO;CAClC;CAEA,MAAMqD,UAAUC,gBAA0C;EACxD,IAAIvB,MAAM7B,MAAMqD,MAAMC,SAASA,KAAKL,OAAOG,WAAW,GAAG,OAAO;EAChE,IAAIvB,MAAME,MAAMsB,MAAMC,SAASA,KAAKL,OAAOG,WAAW,GAAG,OAAO;CAElE;CAEA,MAAMG,gBAAgB;EACpB,IAAInB,WAAWC,QAAQ;EACvB,MAAMmB,OAAa3B,MAAM7B,MAAMyD,SAAS,IAAI,UAAU;EACtD,MAAMC,OAAO7B,MAAM2B,KAAK,CAAC;EACzB,IAAI,CAACE,MAAM;EACX,MAAM5D,UAAUkC,SAAS2B,IAAID,KAAKT,EAAE;EACpCjB,SAAS4B,OAAOF,KAAKT,EAAE;EACvBL,SAAS;GAAE,GAAGf;IAAQ2B,OAAO3B,MAAM2B,KAAK,CAACK,MAAM,CAAC;EAAE,CAAC;EACnD,IAAI,CAAC/D,SAAS;EACdsC,UAAU;EACVR,OAAO/B,IAAIyC,kBAAkBxC,OAAO,GAAG,EAAEE,OAAO,MAAM,CAAC;CACzD;CAEA,MAAM8D,aAAahE,YAA2B;EAC5CuC,SAAS;EAGTG,gBAAgBuB,KAAKC,IAAIvB,eAAe,CAAC;EACzCA,gBAAgB;EAIhBC,eAAe;EACf,IAAI;GACFd,OAAO3B,OAAQ;EACjB,UAAU;GACRyC,eAAe;EACjB;EACAN,UAAU;EACVR,OAAO/B,IAAIyC,kBAAkBxC,OAAO,GAAG,EAAEE,OAAO,KAAK,CAAC;CACxD;CAEA,MAAMqB,QAAQmC,MAAY1D,YAA2B;EACnDuC,SAAS;EACT,MAAMY,KAAK1D,WAAW;EACtByC,SAASiC,IAAIhB,IAAInD,OAAO;EACxB8C,SAAS;GAAE,GAAGf;IAAQ2B,OAAO,CAAC,GAAG3B,MAAM2B,OAAOR,OAAOC,IAAInD,OAAO,CAAC;EAAE,CAAC;EACpEyD,QAAQ;CACV;CAEA,MAAMW,WAAWpE,YAA2B;EAC1CuB,KAAK,SAASvB,OAAO;CACvB;CAEA,MAAME,SAASF,YAA2B;EACxC,IAAIsC,WAAWR,OAAO3B,QAAQ;GAC5B6D,UAAUhE,OAAO;GACjB;EACF;EACAuB,KAAK,SAASvB,OAAO;CACvB;CAEA,MAAMqE,QAAQf,aAAqBgB,cAA8B;EAC/D,MAAMC,WAAWlB,OAAOC,WAAW;EACnC,IAAI,CAACiB,UAAU,MAAM,IAAIC,MAAM,uBAAuBlB,YAAW,GAAI;EACrE,MAAMmB,SAASH,UAAUZ,QAAQa;EAEjC,MAAMf,OAAOzB,MAAMwC,SAAS,CAACG,MAAMC,MAAMA,EAAExB,OAAOG,WAAW;EAC7D,MAAMsB,QAAQH,WAAWF,WAAWxC,MAAMwC,YAAYxC,MAAM0C,QAAAA,CAAStD,QAClEwD,MAAMA,EAAExB,OAAOG,WAClB;EAEA,MAAMuB,eAAeC,WAAmB;GACtC,IAAIA,WAAWxB,aACb,MAAM,IAAIkB,MAAM,eAAelB,YAAW,wBAAyB;GACrE,MAAMyB,QAAQH,KAAKI,WAAWL,MAAMA,EAAExB,OAAO2B,MAAM;GACnD,IAAIC,UAAU,IACZ,MAAM,IAAIP,MAAM,mBAAmBM,OAAM,aAAcL,OAAM,GAAI;GACnE,OAAOM;EACT;EAEA,MAAM,EAAEE,aAAaC,iBAAiBZ;EACtC,IAAIS;EACJ,IAAIE,gBAAgBrD,KAAAA,KAAasD,iBAAiBtD,KAAAA,GAChDmD,QACEN,WAAWF,WACPxC,MAAMwC,SAAS,CAACS,WAAWL,MAAMA,EAAExB,OAAOG,WAAW,IACrDsB,KAAKjB;OACN,IAAIsB,gBAAgBrD,KAAAA,KAAasD,iBAAiBtD,KAAAA,GAAW;GAClE,MAAMuD,QAAQF,gBAAgB,OAAO,KAAKJ,YAAYI,WAAW;GAGjE,KADEC,iBAAiB,OAAON,KAAKjB,SAASkB,YAAYK,YAAY,OACjDC,QAAQ,GACrB,MAAM,IAAIX,MACR,gBAAgBS,YAAW,sBAAuBC,aAAY,8BAA+BT,OAAM,GACrG;GACFM,QAAQI,QAAQ;EAClB,OAAO,IAAIF,gBAAgBrD,KAAAA,GACzBmD,QAAQE,gBAAgB,OAAO,IAAIJ,YAAYI,WAAW,IAAI;OAE9DF,QAAQG,iBAAiB,OAAON,KAAKjB,SAASkB,YAAYK,YAAa;EAMzE,IACED,gBAAgBrD,KAAAA,KAChBsD,iBAAiBtD,KAAAA,KACjB6C,WAAW,WACXF,aAAa,WACbjC,WACAR,OAAO3B,QACP;GACA,MAAMH,UAAUkC,SAAS2B,IAAIP,WAAW;GACxCpB,SAAS4B,OAAOR,WAAW;GAC3BR,SAAS;IACPb,OAAOF,MAAME,MAAMd,QAAQwD,MAAMA,EAAExB,OAAOG,WAAW;IACrDpD,OAAO6B,MAAM7B;GACf,CAAC;GACD8D,UAAUhE,OAAO;GACjB;EACF;EAEA,MAAMqF,WAAW;GAAC,GAAGT,KAAKb,MAAM,GAAGgB,KAAK;GAAGvB;GAAM,GAAGoB,KAAKb,MAAMgB,KAAK;EAAC;EACrE,MAAMhC,OAAO;GAAE,GAAGhB;IAAQ0C,SAASY;EAAS;EAC5C,IAAIZ,WAAWF,UACbxB,KAAKwB,YAAYxC,MAAMwC,SAAS,CAACpD,QAAQwD,MAAMA,EAAExB,OAAOG,WAAW;EACrER,SAASC,IAAI;EACbU,QAAQ;CACV;CAEA,MAAM6B,QAAQhC,aAAqBtD,YAA2B;EAC5D,MAAM0D,OAAOL,OAAOC,WAAW;EAC/B,IAAI,CAACI,MAAM,MAAM,IAAIc,MAAM,uBAAuBlB,YAAW,GAAI;EACjEpB,SAASiC,IAAIb,aAAatD,OAAO;EACjC8C,SAAS;GACP,GAAGf;IACF2B,OAAO3B,MAAM2B,KAAK,CAAC6B,KAAK/B,SACvBA,KAAKL,OAAOG,cAAcJ,OAAOI,aAAatD,OAAO,IAAIwD,IAC3D;EACF,CAAC;CACH;CAEA,MAAMgC,UAAUlC,gBAAwB;EACtC,IAAI,CAACpB,SAAS4B,OAAOR,WAAW,GAAG;EACnCR,SAAS;GACPb,OAAOF,MAAME,MAAMd,QAAQqC,SAASA,KAAKL,OAAOG,WAAW;GAC3DpD,OAAO6B,MAAM7B,MAAMiB,QAAQqC,SAASA,KAAKL,OAAOG,WAAW;EAC7D,CAAC;CACH;CAEA,MAAM9C,wBAAwB;EAC5B,IAAIoC,cAAc;EAClB,IAAIN,WAAWK,kBAAkB,GAAG;GAClCJ,SAAS;GACTI,gBAAgB;EAClB;CACF;CAEA,MAAMtC,UAAsC;EAC1C2C,OAAOjB,MAAME;EACbgB,YAAYlB,MAAM7B;EAClBkE;EACAlE;EACAmE;EACAiB;EACAE;EACAC,kCAAkCC,cAAc;GAC9ClD,oBAAoBkD;EACtB;EACAC,4BAA4BnF;CAC9B;CAEA,OAAO;EACLH;EACAC,kBAAkB;GAChBiC,SAAS;GAGTG,gBAAgBC;GAChBA,gBAAgB;GAChBL,UAAU;EACZ;EACA/B,kBAAkB;GAChB,IAAImC,eAAe,GAAG;IACpBA;IACA;GACF;GACA,IAAIC,gBAAgB,GAAGA;GACvBL,UAAU;GACVmB,QAAQ;EACV;EACAjD;EACAC,aAAa;GACXyB,SAASzB,MAAM;GACfqC,SAAS;IAAEb,OAAO1C;IAAmBW,OAAOX;GAAkB,CAAC;EACjE;EACAmB,YAAYC,aAAa;GACvByB,YAAYwD,IAAIjF,QAAQ;GACxB,aAAa;IACXyB,YAAY0B,OAAOnD,QAAQ;GAC7B;EACF;CACF;AACF"}
1
+ {"version":3,"file":"message-queue.js","names":["AppendMessage","FileMessagePart","TextMessagePart","EMPTY_QUEUE_ITEMS","QueueItemState","generateId","notifyEventListeners","getThreadMessageText","ExternalThreadQueueAdapter","QueuePlacement","MessageQueueDriver","run","message","options","steer","cancel","MessageQueueController","adapter","notifyBusy","notifyIdle","notifyCancelled","clear","subscribe","callback","Lane","DispatchItem","id","item","getQueueItemParts","source","content","attachments","flatMap","attachment","filter","part","type","parts","push","data","image","mimeType","filename","undefined","createMessageQueue","driver","lanes","Record","queue","messages","Map","subscribers","Set","running","paused","dispatchTransform","m","suppressIdle","cancelSettles","interrupting","busyEdges","notify","setLanes","next","items","steerItems","toItem","prompt","restore","lane","dispatch","index","set","slice","laneOf","queueItemId","some","advance","length","head","get","delete","busyEdgesBeforeRun","error","interrupt","restoreLane","restoreIndex","Math","max","restoreInterrupted","replacementStarted","pendingSettles","enqueue","move","placement","fromLane","Error","toLane","fromIndex","findIndex","i","dest","anchorIndex","anchor","insertAfter","insertBefore","after","before","nextDest","edit","map","remove","__internal_setDispatchTransform","transform","__internal_notifyCancelled","add"],"sources":["../../../src/runtime/queue/message-queue.ts"],"sourcesContent":["import type {\n AppendMessage,\n FileMessagePart,\n TextMessagePart,\n} from \"../../types/message\";\nimport { EMPTY_QUEUE_ITEMS, type QueueItemState } from \"./queue-item\";\nimport { generateId } from \"../../utils/id\";\nimport { notifyEventListeners } from \"../../utils/notify-event-listeners\";\nimport { getThreadMessageText } from \"../../utils/text\";\nimport type {\n ExternalThreadQueueAdapter,\n QueuePlacement,\n} from \"./external-thread-queue-adapter\";\n\nexport type MessageQueueDriver = {\n /**\n * A synchronous throw is treated as a run that never started and restores\n * the message. A driver that already started work must call `notifyBusy`\n * before throwing.\n */\n run: (message: AppendMessage, options: { steer: boolean }) => void;\n /** When omitted, steering degrades to \"process next\" instead of interrupting. */\n cancel?: (() => void) | undefined;\n};\n\nexport type MessageQueueController = {\n readonly adapter: ExternalThreadQueueAdapter;\n /** Mark a run as in flight so concurrent sends buffer; call on the rising edge. */\n notifyBusy: () => void;\n /** Advances to the next pending message; call on the run's falling edge. */\n notifyIdle: () => void;\n /**\n * Pauses queue advance for a user-initiated cancel, so the cancelled run's\n * settle keeps the pending items instead of dispatching the next one; the\n * next explicit send or run start re-arms draining. Call before aborting\n * the run.\n */\n notifyCancelled: () => void;\n /** Empties both lanes without dispatching. */\n clear: () => void;\n subscribe: (callback: () => void) => () => void;\n};\n\ntype Lane = \"queue\" | \"steer\";\n\ntype DispatchItem = {\n id: string;\n item: QueueItemState;\n message: AppendMessage;\n};\n\nconst getQueueItemParts = (\n message: AppendMessage,\n): readonly (FileMessagePart | TextMessagePart)[] => {\n // attachment-derived text is the file body, not user-authored prose;\n // project only the file/image content of attachments\n const source = [\n ...message.content,\n ...(message.attachments ?? []).flatMap((attachment) =>\n (attachment.content ?? []).filter((part) => part.type !== \"text\"),\n ),\n ];\n const parts: (FileMessagePart | TextMessagePart)[] = [];\n for (const part of source) {\n if (part.type === \"file\" || part.type === \"text\") {\n parts.push(part);\n } else if (part.type === \"image\") {\n parts.push({\n type: \"file\",\n data: part.image,\n mimeType: \"image/*\",\n ...(part.filename !== undefined && { filename: part.filename }),\n });\n }\n }\n return parts;\n};\n\nexport const createMessageQueue = (\n driver: MessageQueueDriver,\n): MessageQueueController => {\n let lanes: Record<Lane, readonly QueueItemState[]> = {\n queue: EMPTY_QUEUE_ITEMS,\n steer: EMPTY_QUEUE_ITEMS,\n };\n const messages = new Map<string, AppendMessage>();\n const subscribers = new Set<() => void>();\n\n let running = false;\n let paused = false;\n let dispatchTransform: (message: AppendMessage) => AppendMessage = (m) => m;\n // swallow the cancelled run's settle when steering so it does not double-advance\n let suppressIdle = 0;\n // settles from cancelled runs that must drop `running` without advancing\n let cancelSettles = 0;\n let interrupting = false;\n let busyEdges = 0;\n\n const notify = () => {\n notifyEventListeners(subscribers, undefined, \"Message queue\");\n };\n\n const setLanes = (next: Record<Lane, readonly QueueItemState[]>) => {\n lanes = next;\n adapter.items = next.queue;\n adapter.steerItems = next.steer;\n notify();\n };\n\n const toItem = (id: string, message: AppendMessage): QueueItemState => ({\n id,\n prompt: getThreadMessageText(message),\n parts: getQueueItemParts(message),\n });\n\n const restore = (lane: Lane, dispatch: DispatchItem, index = 0) => {\n paused = true;\n messages.set(dispatch.id, dispatch.message);\n setLanes({\n ...lanes,\n [lane]: [\n ...lanes[lane].slice(0, index),\n dispatch.item,\n ...lanes[lane].slice(index),\n ],\n });\n };\n\n const laneOf = (queueItemId: string): Lane | undefined => {\n if (lanes.steer.some((item) => item.id === queueItemId)) return \"steer\";\n if (lanes.queue.some((item) => item.id === queueItemId)) return \"queue\";\n return undefined;\n };\n\n const advance = () => {\n if (running || paused) return;\n const lane: Lane = lanes.steer.length > 0 ? \"steer\" : \"queue\";\n const head = lanes[lane][0];\n if (!head) return;\n const message = messages.get(head.id);\n messages.delete(head.id);\n setLanes({ ...lanes, [lane]: lanes[lane].slice(1) });\n if (!message) return;\n const dispatch = { id: head.id, item: head, message };\n running = true;\n const busyEdgesBeforeRun = busyEdges;\n try {\n driver.run(dispatchTransform(message), { steer: false });\n } catch (error) {\n if (busyEdges === busyEdgesBeforeRun) {\n running = false;\n restore(lane, dispatch);\n }\n throw error;\n }\n };\n\n const interrupt = (\n dispatch: DispatchItem,\n restoreLane: Lane = \"steer\",\n restoreIndex = 0,\n ) => {\n paused = false;\n // the interrupted run settles exactly once, whether or not it was\n // already cancel-notified\n suppressIdle += Math.max(cancelSettles, 1);\n cancelSettles = 0;\n const restoreInterrupted = (replacementStarted = false) => {\n if (replacementStarted) return;\n // The live count distinguishes an outstanding cancellation settle\n // from one delivered synchronously by cancel().\n const pendingSettles = suppressIdle;\n suppressIdle = Math.max(pendingSettles - 1, 0);\n cancelSettles = pendingSettles > 0 ? 1 : 0;\n running = pendingSettles > 0;\n restore(restoreLane, dispatch, restoreIndex);\n };\n // a driver whose cancel routes through the runtime notifies this queue\n // back; the interrupt already accounted for that settle and is dispatching\n // in its place\n interrupting = true;\n try {\n driver.cancel!();\n } catch (error) {\n restoreInterrupted();\n throw error;\n } finally {\n interrupting = false;\n }\n running = true;\n const busyEdgesBeforeRun = busyEdges;\n try {\n driver.run(dispatchTransform(dispatch.message), { steer: true });\n } catch (error) {\n const replacementStarted = busyEdges !== busyEdgesBeforeRun;\n restoreInterrupted(replacementStarted);\n throw error;\n }\n };\n\n const push = (lane: Lane, message: AppendMessage) => {\n paused = false;\n const id = generateId();\n messages.set(id, message);\n setLanes({ ...lanes, [lane]: [...lanes[lane], toItem(id, message)] });\n advance();\n };\n\n const enqueue = (message: AppendMessage) => {\n push(\"queue\", message);\n };\n\n const steer = (message: AppendMessage) => {\n if (running && driver.cancel) {\n const id = generateId();\n interrupt({ id, item: toItem(id, message), message });\n return;\n }\n push(\"steer\", message);\n };\n\n const move = (queueItemId: string, placement: QueuePlacement) => {\n const fromLane = laneOf(queueItemId);\n if (!fromLane) throw new Error(`Unknown queue item \"${queueItemId}\".`);\n const toLane = placement.lane ?? fromLane;\n\n const fromIndex = lanes[fromLane].findIndex((i) => i.id === queueItemId);\n const item = lanes[fromLane][fromIndex]!;\n const dest = (toLane === fromLane ? lanes[fromLane] : lanes[toLane]).filter(\n (i) => i.id !== queueItemId,\n );\n\n const anchorIndex = (anchor: string) => {\n if (anchor === queueItemId)\n throw new Error(`Queue item \"${queueItemId}\" cannot anchor itself.`);\n const index = dest.findIndex((i) => i.id === anchor);\n if (index === -1)\n throw new Error(`Unknown anchor \"${anchor}\" in lane \"${toLane}\".`);\n return index;\n };\n\n const { insertAfter, insertBefore } = placement;\n let index: number;\n if (insertAfter === undefined && insertBefore === undefined) {\n index =\n toLane === fromLane\n ? lanes[fromLane].findIndex((i) => i.id === queueItemId)\n : dest.length;\n } else if (insertAfter !== undefined && insertBefore !== undefined) {\n const after = insertAfter === null ? -1 : anchorIndex(insertAfter);\n const before =\n insertBefore === null ? dest.length : anchorIndex(insertBefore);\n if (before !== after + 1)\n throw new Error(\n `insertAfter \"${insertAfter}\" and insertBefore \"${insertBefore}\" are not adjacent in lane \"${toLane}\".`,\n );\n index = after + 1;\n } else if (insertAfter !== undefined) {\n index = insertAfter === null ? 0 : anchorIndex(insertAfter) + 1;\n } else {\n index = insertBefore === null ? dest.length : anchorIndex(insertBefore!);\n }\n\n // placement and immediate dispatch cannot coexist: an anchored move into\n // the steer lane places without interrupting; only an unanchored one\n // cancels the live run and dispatches\n if (\n insertAfter === undefined &&\n insertBefore === undefined &&\n toLane === \"steer\" &&\n fromLane !== \"steer\" &&\n running &&\n driver.cancel\n ) {\n const message = messages.get(queueItemId)!;\n messages.delete(queueItemId);\n setLanes({\n queue: lanes.queue.filter((i) => i.id !== queueItemId),\n steer: lanes.steer,\n });\n interrupt({ id: queueItemId, item, message }, fromLane, fromIndex);\n return;\n }\n\n const nextDest = [...dest.slice(0, index), item, ...dest.slice(index)];\n const next = { ...lanes, [toLane]: nextDest };\n if (toLane !== fromLane)\n next[fromLane] = lanes[fromLane].filter((i) => i.id !== queueItemId);\n setLanes(next);\n advance();\n };\n\n const edit = (queueItemId: string, message: AppendMessage) => {\n const lane = laneOf(queueItemId);\n if (!lane) throw new Error(`Unknown queue item \"${queueItemId}\".`);\n messages.set(queueItemId, message);\n setLanes({\n ...lanes,\n [lane]: lanes[lane].map((item) =>\n item.id === queueItemId ? toItem(queueItemId, message) : item,\n ),\n });\n };\n\n const remove = (queueItemId: string) => {\n if (!messages.delete(queueItemId)) return;\n setLanes({\n queue: lanes.queue.filter((item) => item.id !== queueItemId),\n steer: lanes.steer.filter((item) => item.id !== queueItemId),\n });\n };\n\n const notifyCancelled = () => {\n if (interrupting) return;\n if (running && cancelSettles === 0) {\n paused = true;\n cancelSettles = 1;\n }\n };\n\n const adapter: ExternalThreadQueueAdapter = {\n items: lanes.queue,\n steerItems: lanes.steer,\n enqueue,\n steer,\n move,\n edit,\n remove,\n __internal_setDispatchTransform: (transform) => {\n dispatchTransform = transform;\n },\n __internal_notifyCancelled: notifyCancelled,\n };\n\n return {\n adapter,\n notifyBusy: () => {\n paused = false;\n // a cancelled run's settle that is still outstanding belongs to a run\n // this new one replaces; swallow it entirely\n suppressIdle += cancelSettles;\n cancelSettles = 0;\n running = true;\n busyEdges++;\n },\n notifyIdle: () => {\n if (suppressIdle > 0) {\n suppressIdle--;\n return;\n }\n if (cancelSettles > 0) cancelSettles--;\n running = false;\n advance();\n },\n notifyCancelled,\n clear: () => {\n messages.clear();\n setLanes({ queue: EMPTY_QUEUE_ITEMS, steer: EMPTY_QUEUE_ITEMS });\n },\n subscribe: (callback) => {\n subscribers.add(callback);\n return () => {\n subscribers.delete(callback);\n };\n },\n };\n};\n"],"mappings":"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"}
@@ -4,10 +4,14 @@ import { ReadonlyJSONValue } from "assistant-stream/utils";
4
4
  //#region src/runtime/utils/auto-status.d.ts
5
5
  type ThreadMessageLikeContentItem = Exclude<ThreadMessageLike["content"], string>[number];
6
6
  declare const isPendingToolCall: (c: ThreadMessageLikeContentItem) => boolean;
7
+ /** A pending tool call whose nested conversation is still streaming; the outer message stays running until the nested run settles. */
8
+ declare const isBackgroundToolCall: (c: ThreadMessageLikeContentItem) => boolean;
7
9
  declare const isInterruptedToolCall: (c: ThreadMessageLikeContentItem) => boolean;
8
10
  declare const isAutoStatus: (status: MessageStatus) => boolean;
9
- declare const getAutoStatus: (isLast: boolean, isRunning: boolean, hasInterruptedToolCalls: boolean, hasPendingToolCalls: boolean, error?: ReadonlyJSONValue, isCancelled?: boolean) => MessageStatus;
11
+ declare const getAutoStatus: (isLast: boolean, isRunning: boolean, hasInterruptedToolCalls: boolean, hasPendingToolCalls: boolean, error?: ReadonlyJSONValue, isCancelled?: boolean, hasBackgroundToolCalls?: boolean) => MessageStatus;
12
+ /** Status for a message entering the repository: the nested conversation is not being fed here, so it never keeps the message running. */
13
+ declare const getRepositoryContentAutoStatus: (content: ThreadMessageLike["content"]) => MessageStatus;
10
14
  declare const getContentAutoStatus: (content: ThreadMessageLike["content"], isLast: boolean, isRunning: boolean) => MessageStatus;
11
15
  //#endregion
12
- export { getAutoStatus, getContentAutoStatus, isAutoStatus, isInterruptedToolCall, isPendingToolCall };
16
+ export { getAutoStatus, getContentAutoStatus, getRepositoryContentAutoStatus, isAutoStatus, isBackgroundToolCall, isInterruptedToolCall, isPendingToolCall };
13
17
  //# sourceMappingURL=auto-status.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auto-status.d.ts","names":[],"sources":["../../../src/runtime/utils/auto-status.ts"],"mappings":";;;;KAIK,+BAA+B,QAClC;cAIW,oBAAqB,GAAG;cAGxB,wBACX,GAAG;cAuDQ,eAAgB,QAAQ;cAGxB,gBACX,iBACA,oBACA,kCACA,8BACA,QAAQ,mBACR,0BACC;cAuBU,uBACX,SAAS,8BACT,iBACA,uBACC"}
1
+ {"version":3,"file":"auto-status.d.ts","names":[],"sources":["../../../src/runtime/utils/auto-status.ts"],"mappings":";;;;KAIK,+BAA+B,QAClC;cAIW,oBAAqB,GAAG;;cAIxB,uBACX,GAAG;cAOQ,wBACX,GAAG;cAuDQ,eAAgB,QAAQ;cAGxB,gBACX,iBACA,oBACA,kCACA,8BACA,QAAQ,mBACR,uBACA,qCACC;;cA0BU,iCACX,SAAS,iCACR;cAQU,uBACX,SAAS,8BACT,iBACA,uBACC"}
@@ -1,5 +1,11 @@
1
1
  //#region src/runtime/utils/auto-status.ts
2
2
  const isPendingToolCall = (c) => c.type === "tool-call" && c.result === void 0;
3
+ /** A pending tool call whose nested conversation is still streaming; the outer message stays running until the nested run settles. */
4
+ const isBackgroundToolCall = (c) => {
5
+ if (c.type !== "tool-call" || c.result !== void 0) return false;
6
+ const last = c.messages?.at(-1);
7
+ return last?.role === "assistant" && last.status.type === "running";
8
+ };
3
9
  const isInterruptedToolCall = (c) => {
4
10
  if (c.type !== "tool-call" || c.result !== void 0) return false;
5
11
  return c.interrupt != null || c.approval != null && c.approval.approved === void 0 && c.approval.resolution === void 0;
@@ -23,16 +29,18 @@ const AUTO_STATUS_INTERRUPT = Object.freeze(Object.assign({
23
29
  reason: "interrupt"
24
30
  }, { [symbolAutoStatus]: true }));
25
31
  const isAutoStatus = (status) => status[symbolAutoStatus] === true;
26
- const getAutoStatus = (isLast, isRunning, hasInterruptedToolCalls, hasPendingToolCalls, error, isCancelled) => {
32
+ const getAutoStatus = (isLast, isRunning, hasInterruptedToolCalls, hasPendingToolCalls, error, isCancelled, hasBackgroundToolCalls) => {
27
33
  if (isLast && error) return Object.assign({
28
34
  type: "incomplete",
29
35
  reason: "error",
30
36
  error
31
37
  }, { [symbolAutoStatus]: true });
32
- return isLast && isRunning ? AUTO_STATUS_RUNNING : hasInterruptedToolCalls ? AUTO_STATUS_INTERRUPT : hasPendingToolCalls ? AUTO_STATUS_PENDING : isCancelled ? AUTO_STATUS_CANCELLED : AUTO_STATUS_COMPLETE;
38
+ return isLast && isRunning ? AUTO_STATUS_RUNNING : hasInterruptedToolCalls ? AUTO_STATUS_INTERRUPT : hasBackgroundToolCalls && !isCancelled ? AUTO_STATUS_RUNNING : hasPendingToolCalls ? AUTO_STATUS_PENDING : isCancelled ? AUTO_STATUS_CANCELLED : AUTO_STATUS_COMPLETE;
33
39
  };
34
- const getContentAutoStatus = (content, isLast, isRunning) => getAutoStatus(isLast, isRunning, typeof content !== "string" && content.some(isInterruptedToolCall), typeof content !== "string" && content.some(isPendingToolCall));
40
+ /** Status for a message entering the repository: the nested conversation is not being fed here, so it never keeps the message running. */
41
+ const getRepositoryContentAutoStatus = (content) => getAutoStatus(false, false, typeof content !== "string" && content.some(isInterruptedToolCall), typeof content !== "string" && content.some(isPendingToolCall));
42
+ const getContentAutoStatus = (content, isLast, isRunning) => getAutoStatus(isLast, isRunning, typeof content !== "string" && content.some(isInterruptedToolCall), typeof content !== "string" && content.some(isPendingToolCall), void 0, void 0, typeof content !== "string" && content.some(isBackgroundToolCall));
35
43
  //#endregion
36
- export { getAutoStatus, getContentAutoStatus, isAutoStatus, isInterruptedToolCall, isPendingToolCall };
44
+ export { getAutoStatus, getContentAutoStatus, getRepositoryContentAutoStatus, isAutoStatus, isBackgroundToolCall, isInterruptedToolCall, isPendingToolCall };
37
45
 
38
46
  //# sourceMappingURL=auto-status.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auto-status.js","names":["MessageStatus","ReadonlyJSONValue","ThreadMessageLike","ThreadMessageLikeContentItem","Exclude","isPendingToolCall","c","type","result","undefined","isInterruptedToolCall","interrupt","approval","approved","resolution","symbolAutoStatus","Symbol","AUTO_STATUS_RUNNING","Object","freeze","assign","const","AUTO_STATUS_COMPLETE","reason","AUTO_STATUS_CANCELLED","AUTO_STATUS_PENDING","AUTO_STATUS_INTERRUPT","isAutoStatus","status","getAutoStatus","isLast","isRunning","hasInterruptedToolCalls","hasPendingToolCalls","error","isCancelled","getContentAutoStatus","content","some"],"sources":["../../../src/runtime/utils/auto-status.ts"],"sourcesContent":["import type { MessageStatus } from \"../../types/message\";\nimport type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport type { ThreadMessageLike } from \"./thread-message-like\";\n\ntype ThreadMessageLikeContentItem = Exclude<\n ThreadMessageLike[\"content\"],\n string\n>[number];\n\nexport const isPendingToolCall = (c: ThreadMessageLikeContentItem): boolean =>\n c.type === \"tool-call\" && c.result === undefined;\n\nexport const isInterruptedToolCall = (\n c: ThreadMessageLikeContentItem,\n): boolean => {\n if (c.type !== \"tool-call\" || c.result !== undefined) return false;\n return (\n c.interrupt != null ||\n (c.approval != null &&\n c.approval.approved === undefined &&\n c.approval.resolution === undefined)\n );\n};\n\nconst symbolAutoStatus = Symbol(\"autoStatus\");\n\nconst AUTO_STATUS_RUNNING = Object.freeze(\n Object.assign({ type: \"running\" as const }, { [symbolAutoStatus]: true }),\n);\nconst AUTO_STATUS_COMPLETE = Object.freeze(\n Object.assign(\n {\n type: \"complete\" as const,\n reason: \"unknown\" as const,\n },\n { [symbolAutoStatus]: true },\n ),\n);\nconst AUTO_STATUS_CANCELLED = Object.freeze(\n Object.assign(\n {\n type: \"incomplete\" as const,\n reason: \"cancelled\" as const,\n },\n { [symbolAutoStatus]: true },\n ),\n);\n\nconst AUTO_STATUS_PENDING = Object.freeze(\n Object.assign(\n {\n type: \"requires-action\" as const,\n reason: \"tool-calls\" as const,\n },\n { [symbolAutoStatus]: true },\n ),\n);\n\nconst AUTO_STATUS_INTERRUPT = Object.freeze(\n Object.assign(\n {\n type: \"requires-action\" as const,\n reason: \"interrupt\" as const,\n },\n { [symbolAutoStatus]: true },\n ),\n);\n\nexport const isAutoStatus = (status: MessageStatus) =>\n (status as any)[symbolAutoStatus] === true;\n\nexport const getAutoStatus = (\n isLast: boolean,\n isRunning: boolean,\n hasInterruptedToolCalls: boolean,\n hasPendingToolCalls: boolean,\n error?: ReadonlyJSONValue,\n isCancelled?: boolean,\n): MessageStatus => {\n if (isLast && error) {\n return Object.assign(\n {\n type: \"incomplete\" as const,\n reason: \"error\" as const,\n error: error,\n },\n { [symbolAutoStatus]: true },\n );\n }\n\n return isLast && isRunning\n ? AUTO_STATUS_RUNNING\n : hasInterruptedToolCalls\n ? AUTO_STATUS_INTERRUPT\n : hasPendingToolCalls\n ? AUTO_STATUS_PENDING\n : isCancelled\n ? AUTO_STATUS_CANCELLED\n : AUTO_STATUS_COMPLETE;\n};\n\nexport const getContentAutoStatus = (\n content: ThreadMessageLike[\"content\"],\n isLast: boolean,\n isRunning: boolean,\n): MessageStatus =>\n getAutoStatus(\n isLast,\n isRunning,\n typeof content !== \"string\" && content.some(isInterruptedToolCall),\n typeof content !== \"string\" && content.some(isPendingToolCall),\n );\n"],"mappings":";AASA,MAAaK,qBAAqBC,MAChCA,EAAEC,SAAS,eAAeD,EAAEE,WAAWC,KAAAA;AAEzC,MAAaC,yBACXJ,MACY;CACZ,IAAIA,EAAEC,SAAS,eAAeD,EAAEE,WAAWC,KAAAA,GAAW,OAAO;CAC7D,OACEH,EAAEK,aAAa,QACdL,EAAEM,YAAY,QACbN,EAAEM,SAASC,aAAaJ,KAAAA,KACxBH,EAAEM,SAASE,eAAeL,KAAAA;AAEhC;AAEA,MAAMM,mBAAmBC,OAAO,YAAY;AAE5C,MAAMC,sBAAsBC,OAAOC,OACjCD,OAAOE,OAAO,EAAEb,MAAM,UAAmB,GAAG,GAAGQ,mBAAmB,KAAK,CAAC,CAC1E;AACA,MAAMO,uBAAuBJ,OAAOC,OAClCD,OAAOE,OACL;CACEb,MAAM;CACNgB,QAAQ;AACV,GACA,GAAGR,mBAAmB,KAAK,CAC7B,CACF;AACA,MAAMS,wBAAwBN,OAAOC,OACnCD,OAAOE,OACL;CACEb,MAAM;CACNgB,QAAQ;AACV,GACA,GAAGR,mBAAmB,KAAK,CAC7B,CACF;AAEA,MAAMU,sBAAsBP,OAAOC,OACjCD,OAAOE,OACL;CACEb,MAAM;CACNgB,QAAQ;AACV,GACA,GAAGR,mBAAmB,KAAK,CAC7B,CACF;AAEA,MAAMW,wBAAwBR,OAAOC,OACnCD,OAAOE,OACL;CACEb,MAAM;CACNgB,QAAQ;AACV,GACA,GAAGR,mBAAmB,KAAK,CAC7B,CACF;AAEA,MAAaY,gBAAgBC,WAC1BA,OAAeb,sBAAsB;AAExC,MAAac,iBACXC,QACAC,WACAC,yBACAC,qBACAC,OACAC,gBACkB;CAClB,IAAIL,UAAUI,OACZ,OAAOhB,OAAOE,OACZ;EACEb,MAAM;EACNgB,QAAQ;EACDW;CACT,GACA,GAAGnB,mBAAmB,KAAK,CAC7B;CAGF,OAAOe,UAAUC,YACbd,sBACAe,0BACEN,wBACAO,sBACER,sBACAU,cACEX,wBACAF;AACZ;AAEA,MAAac,wBACXC,SACAP,QACAC,cAEAF,cACEC,QACAC,WACA,OAAOM,YAAY,YAAYA,QAAQC,KAAK5B,qBAAqB,GACjE,OAAO2B,YAAY,YAAYA,QAAQC,KAAKjC,iBAAiB,CAC/D"}
1
+ {"version":3,"file":"auto-status.js","names":["MessageStatus","ReadonlyJSONValue","ThreadMessageLike","ThreadMessageLikeContentItem","Exclude","isPendingToolCall","c","type","result","undefined","isBackgroundToolCall","last","messages","at","role","status","isInterruptedToolCall","interrupt","approval","approved","resolution","symbolAutoStatus","Symbol","AUTO_STATUS_RUNNING","Object","freeze","assign","const","AUTO_STATUS_COMPLETE","reason","AUTO_STATUS_CANCELLED","AUTO_STATUS_PENDING","AUTO_STATUS_INTERRUPT","isAutoStatus","getAutoStatus","isLast","isRunning","hasInterruptedToolCalls","hasPendingToolCalls","error","isCancelled","hasBackgroundToolCalls","getRepositoryContentAutoStatus","content","some","getContentAutoStatus"],"sources":["../../../src/runtime/utils/auto-status.ts"],"sourcesContent":["import type { MessageStatus } from \"../../types/message\";\nimport type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport type { ThreadMessageLike } from \"./thread-message-like\";\n\ntype ThreadMessageLikeContentItem = Exclude<\n ThreadMessageLike[\"content\"],\n string\n>[number];\n\nexport const isPendingToolCall = (c: ThreadMessageLikeContentItem): boolean =>\n c.type === \"tool-call\" && c.result === undefined;\n\n/** A pending tool call whose nested conversation is still streaming; the outer message stays running until the nested run settles. */\nexport const isBackgroundToolCall = (\n c: ThreadMessageLikeContentItem,\n): boolean => {\n if (c.type !== \"tool-call\" || c.result !== undefined) return false;\n const last = c.messages?.at(-1);\n return last?.role === \"assistant\" && last.status.type === \"running\";\n};\n\nexport const isInterruptedToolCall = (\n c: ThreadMessageLikeContentItem,\n): boolean => {\n if (c.type !== \"tool-call\" || c.result !== undefined) return false;\n return (\n c.interrupt != null ||\n (c.approval != null &&\n c.approval.approved === undefined &&\n c.approval.resolution === undefined)\n );\n};\n\nconst symbolAutoStatus = Symbol(\"autoStatus\");\n\nconst AUTO_STATUS_RUNNING = Object.freeze(\n Object.assign({ type: \"running\" as const }, { [symbolAutoStatus]: true }),\n);\nconst AUTO_STATUS_COMPLETE = Object.freeze(\n Object.assign(\n {\n type: \"complete\" as const,\n reason: \"unknown\" as const,\n },\n { [symbolAutoStatus]: true },\n ),\n);\nconst AUTO_STATUS_CANCELLED = Object.freeze(\n Object.assign(\n {\n type: \"incomplete\" as const,\n reason: \"cancelled\" as const,\n },\n { [symbolAutoStatus]: true },\n ),\n);\n\nconst AUTO_STATUS_PENDING = Object.freeze(\n Object.assign(\n {\n type: \"requires-action\" as const,\n reason: \"tool-calls\" as const,\n },\n { [symbolAutoStatus]: true },\n ),\n);\n\nconst AUTO_STATUS_INTERRUPT = Object.freeze(\n Object.assign(\n {\n type: \"requires-action\" as const,\n reason: \"interrupt\" as const,\n },\n { [symbolAutoStatus]: true },\n ),\n);\n\nexport const isAutoStatus = (status: MessageStatus) =>\n (status as any)[symbolAutoStatus] === true;\n\nexport const getAutoStatus = (\n isLast: boolean,\n isRunning: boolean,\n hasInterruptedToolCalls: boolean,\n hasPendingToolCalls: boolean,\n error?: ReadonlyJSONValue,\n isCancelled?: boolean,\n hasBackgroundToolCalls?: boolean,\n): MessageStatus => {\n if (isLast && error) {\n return Object.assign(\n {\n type: \"incomplete\" as const,\n reason: \"error\" as const,\n error: error,\n },\n { [symbolAutoStatus]: true },\n );\n }\n\n return isLast && isRunning\n ? AUTO_STATUS_RUNNING\n : hasInterruptedToolCalls\n ? AUTO_STATUS_INTERRUPT\n : hasBackgroundToolCalls && !isCancelled\n ? AUTO_STATUS_RUNNING\n : hasPendingToolCalls\n ? AUTO_STATUS_PENDING\n : isCancelled\n ? AUTO_STATUS_CANCELLED\n : AUTO_STATUS_COMPLETE;\n};\n\n/** Status for a message entering the repository: the nested conversation is not being fed here, so it never keeps the message running. */\nexport const getRepositoryContentAutoStatus = (\n content: ThreadMessageLike[\"content\"],\n): MessageStatus =>\n getAutoStatus(\n false,\n false,\n typeof content !== \"string\" && content.some(isInterruptedToolCall),\n typeof content !== \"string\" && content.some(isPendingToolCall),\n );\n\nexport const getContentAutoStatus = (\n content: ThreadMessageLike[\"content\"],\n isLast: boolean,\n isRunning: boolean,\n): MessageStatus =>\n getAutoStatus(\n isLast,\n isRunning,\n typeof content !== \"string\" && content.some(isInterruptedToolCall),\n typeof content !== \"string\" && content.some(isPendingToolCall),\n undefined,\n undefined,\n typeof content !== \"string\" && content.some(isBackgroundToolCall),\n );\n"],"mappings":";AASA,MAAaK,qBAAqBC,MAChCA,EAAEC,SAAS,eAAeD,EAAEE,WAAWC,KAAAA;;AAGzC,MAAaC,wBACXJ,MACY;CACZ,IAAIA,EAAEC,SAAS,eAAeD,EAAEE,WAAWC,KAAAA,GAAW,OAAO;CAC7D,MAAME,OAAOL,EAAEM,UAAUC,GAAG,EAAE;CAC9B,OAAOF,MAAMG,SAAS,eAAeH,KAAKI,OAAOR,SAAS;AAC5D;AAEA,MAAaS,yBACXV,MACY;CACZ,IAAIA,EAAEC,SAAS,eAAeD,EAAEE,WAAWC,KAAAA,GAAW,OAAO;CAC7D,OACEH,EAAEW,aAAa,QACdX,EAAEY,YAAY,QACbZ,EAAEY,SAASC,aAAaV,KAAAA,KACxBH,EAAEY,SAASE,eAAeX,KAAAA;AAEhC;AAEA,MAAMY,mBAAmBC,OAAO,YAAY;AAE5C,MAAMC,sBAAsBC,OAAOC,OACjCD,OAAOE,OAAO,EAAEnB,MAAM,UAAmB,GAAG,GAAGc,mBAAmB,KAAK,CAAC,CAC1E;AACA,MAAMO,uBAAuBJ,OAAOC,OAClCD,OAAOE,OACL;CACEnB,MAAM;CACNsB,QAAQ;AACV,GACA,GAAGR,mBAAmB,KAAK,CAC7B,CACF;AACA,MAAMS,wBAAwBN,OAAOC,OACnCD,OAAOE,OACL;CACEnB,MAAM;CACNsB,QAAQ;AACV,GACA,GAAGR,mBAAmB,KAAK,CAC7B,CACF;AAEA,MAAMU,sBAAsBP,OAAOC,OACjCD,OAAOE,OACL;CACEnB,MAAM;CACNsB,QAAQ;AACV,GACA,GAAGR,mBAAmB,KAAK,CAC7B,CACF;AAEA,MAAMW,wBAAwBR,OAAOC,OACnCD,OAAOE,OACL;CACEnB,MAAM;CACNsB,QAAQ;AACV,GACA,GAAGR,mBAAmB,KAAK,CAC7B,CACF;AAEA,MAAaY,gBAAgBlB,WAC1BA,OAAeM,sBAAsB;AAExC,MAAaa,iBACXC,QACAC,WACAC,yBACAC,qBACAC,OACAC,aACAC,2BACkB;CAClB,IAAIN,UAAUI,OACZ,OAAOf,OAAOE,OACZ;EACEnB,MAAM;EACNsB,QAAQ;EACDU;CACT,GACA,GAAGlB,mBAAmB,KAAK,CAC7B;CAGF,OAAOc,UAAUC,YACbb,sBACAc,0BACEL,wBACAS,0BAA0B,CAACD,cACzBjB,sBACAe,sBACEP,sBACAS,cACEV,wBACAF;AACd;;AAGA,MAAac,kCACXC,YAEAT,cACE,OACA,OACA,OAAOS,YAAY,YAAYA,QAAQC,KAAK5B,qBAAqB,GACjE,OAAO2B,YAAY,YAAYA,QAAQC,KAAKvC,iBAAiB,CAC/D;AAEF,MAAawC,wBACXF,SACAR,QACAC,cAEAF,cACEC,QACAC,WACA,OAAOO,YAAY,YAAYA,QAAQC,KAAK5B,qBAAqB,GACjE,OAAO2B,YAAY,YAAYA,QAAQC,KAAKvC,iBAAiB,GAC7DI,KAAAA,GACAA,KAAAA,GACA,OAAOkC,YAAY,YAAYA,QAAQC,KAAKlC,oBAAoB,CAClE"}
@@ -1,6 +1,7 @@
1
1
  import { MessageTiming, ThreadMessage } from "../../types/message.js";
2
2
  import { ThreadMessageLike } from "./thread-message-like.js";
3
3
  import { ToolExecutionStatus } from "../../runtimes/tool-invocations/ToolInvocationTracker.js";
4
+ import { ThreadMessageConverter } from "../../runtimes/external-store/thread-message-converter.js";
4
5
  import { ReadonlyJSONValue } from "assistant-stream/utils";
5
6
  //#region src/runtime/utils/external-message-conversion.d.ts
6
7
  type JoinStrategy = "concat-content" | "none";
@@ -36,13 +37,24 @@ declare const convertExternalMessageCallback: <T>(input: T, callback: ExternalMe
36
37
  declare const joinExternalMessages: (messages: readonly ExternalMessageConverterMessage[]) => ThreadMessageLike;
37
38
  declare const chunkExternalMessages: <T>(callbackResults: ExternalMessageConverterCallbackResult<T>[], joinStrategy?: JoinStrategy) => ExternalMessageConverterChunk<T>[];
38
39
  declare const shallowArrayEqual: (a: readonly unknown[], b: readonly unknown[]) => boolean;
39
- type ExternalMessageConversionCache = {
40
+ type ExternalMessageChunkConversionCache = {
40
41
  message: ThreadMessage | undefined;
41
42
  generatedFallbackMessages: WeakSet<object>;
42
43
  };
43
- declare const convertExternalMessageChunk: <T>(message: ExternalMessageConverterChunk<T>, idx: number, chunkCount: number, isRunning: boolean, error: ReadonlyJSONValue | undefined, cache?: ExternalMessageConversionCache, cancelledMessageIds?: ReadonlySet<string>) => ThreadMessage;
44
+ type ExternalMessageConversionCallbackCacheEntry<T> = ExternalMessageConverterCallbackResult<T> & {
45
+ metadata: ExternalMessageConverterMetadata;
46
+ callback: ExternalMessageConverterCallback<T>;
47
+ };
48
+ type InternalExternalMessageConversionCache<T extends WeakKey = WeakKey> = {
49
+ callbackCache: WeakMap<T, ExternalMessageConversionCallbackCacheEntry<T>>;
50
+ chunkCache: WeakMap<ExternalMessageConverterMessage, ExternalMessageConverterChunk<T>>;
51
+ converterCache: ThreadMessageConverter;
52
+ generatedFallbackMessages: WeakSet<object>;
53
+ };
54
+ declare const createExternalMessageConversionCache: <T extends WeakKey = WeakKey>() => InternalExternalMessageConversionCache<T>;
55
+ declare const convertExternalMessageChunk: <T>(message: ExternalMessageConverterChunk<T>, idx: number, chunkCount: number, isRunning: boolean, error: ReadonlyJSONValue | undefined, cache?: ExternalMessageChunkConversionCache, cancelledMessageIds?: ReadonlySet<string>) => ThreadMessage;
44
56
  declare const completeExternalMessageConversion: (messages: ThreadMessage[], error: ReadonlyJSONValue | undefined) => ThreadMessage[];
45
- declare const convertExternalMessages: <T extends WeakKey>(messages: T[], callback: ExternalMessageConverterCallback<T>, isRunning: boolean, metadata: ExternalMessageConverterMetadata) => ThreadMessage[];
57
+ declare const convertExternalMessages: <T extends WeakKey>(messages: T[], callback: ExternalMessageConverterCallback<T>, isRunning: boolean, metadata: ExternalMessageConverterMetadata, joinStrategy?: JoinStrategy, cache?: InternalExternalMessageConversionCache<T>) => ThreadMessage[];
46
58
  //#endregion
47
- export { ExternalMessageConverterCallback, ExternalMessageConverterCallbackResult, ExternalMessageConverterChunk, ExternalMessageConverterMessage, ExternalMessageConverterMetadata, JoinStrategy, chunkExternalMessages, completeExternalMessageConversion, convertExternalMessageCallback, convertExternalMessageChunk, convertExternalMessages, joinExternalMessages, shallowArrayEqual };
59
+ export { ExternalMessageConverterCallback, ExternalMessageConverterCallbackResult, ExternalMessageConverterChunk, ExternalMessageConverterMessage, ExternalMessageConverterMetadata, InternalExternalMessageConversionCache, JoinStrategy, chunkExternalMessages, completeExternalMessageConversion, convertExternalMessageCallback, convertExternalMessageChunk, convertExternalMessages, createExternalMessageConversionCache, joinExternalMessages, shallowArrayEqual };
48
60
  //# sourceMappingURL=external-message-conversion.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"external-message-conversion.d.ts","names":[],"sources":["../../../src/runtime/utils/external-message-conversion.ts"],"mappings":";;;;;KA2BY;KAEA,mCACP;WACU;aACE,eAAe;;;EAI1B;EACA;EACA;EACA;EACA;EACA;EACA,oBAAoB;;KAGd;WACD,eAAe,eAAe;WAC9B,QAAQ;WACR,sBAAsB;WACtB,gBAAgB,eAAe;;KAG9B,iCAAiC,MAC3C,SAAS,GACT,UAAU,qCACP,kCAAkC;KAE3B,uCAAuC;EACjD,OAAO;EACP,SAAS;;KAGC,8BAA8B;EACxC,QAAQ;EACR,SAAS;;cAsDE,iCAAkC,GAC7C,OAAO,GACP,UAAU,iCAAiC,IAC3C,UAAU,qCACT,uCAAuC;cAY7B,uBACX,mBAAmB,sCAClB;cA4KU,wBAAyB,GACpC,iBAAiB,uCAAuC,MACxD,eAAe,iBAAY,8BAAA;cAmDhB,oBACX,uBACA;KASG;EACH,SAAS;EACT,2BAA2B;;cAGhB,8BAA+B,GAC1C,SAAS,8BAA8B,IACvC,aACA,oBACA,oBACA,OAAO,+BACP,QAAQ,gCACR,sBAAsB,wBAAmB;cA0F9B,oCACX,UAAU,iBACV,OAAO,kCAA6B;cAWzB,0BAA2B,UAAU,SAChD,UAAU,KACV,UAAU,iCAAiC,IAC3C,oBACA,UAAU,qCAAgC"}
1
+ {"version":3,"file":"external-message-conversion.d.ts","names":[],"sources":["../../../src/runtime/utils/external-message-conversion.ts"],"mappings":";;;;;;KA6BY;KAEA,mCACP;WACU;aACE,eAAe;;;EAI1B;EACA;EACA;EACA;EACA;EACA;EACA,oBAAoB;;KAGd;WACD,eAAe,eAAe;WAC9B,QAAQ;WACR,sBAAsB;WACtB,gBAAgB,eAAe;;KAG9B,iCAAiC,MAC3C,SAAS,GACT,UAAU,qCACP,kCAAkC;KAE3B,uCAAuC;EACjD,OAAO;EACP,SAAS;;KAGC,8BAA8B;EACxC,QAAQ;EACR,SAAS;;cAsDE,iCAAkC,GAC7C,OAAO,GACP,UAAU,iCAAiC,IAC3C,UAAU,qCACT,uCAAuC;cAe7B,uBACX,mBAAmB,sCAClB;cAwLU,wBAAyB,GACpC,iBAAiB,uCAAuC,MACxD,eAAe,iBAAY,8BAAA;cAmDhB,oBACX,uBACA;KASG;EACH,SAAS;EACT,2BAA2B;;KAGxB,4CAA4C,KAC/C,uCAAuC;EACrC,UAAU;EACV,UAAU,iCAAiC;;KAGnC,uCACV,UAAU,UAAU;EAEpB,eAAe,QAAQ,GAAG,4CAA4C;EACtE,YAAY,QACV,iCACA,8BAA8B;EAEhC,gBAAgB;EAEhB,2BAA2B;;cAGhB,uCACX,UAAU,UAAU,cACjB,uCAAuC;cAO/B,8BAA+B,GAC1C,SAAS,8BAA8B,IACvC,aACA,oBACA,oBACA,OAAO,+BACP,QAAQ,qCACR,sBAAsB,wBAAmB;cA8F9B,oCACX,UAAU,iBACV,OAAO,kCAA6B;cAWzB,0BAA2B,UAAU,SAChD,UAAU,KACV,UAAU,iCAAiC,IAC3C,oBACA,UAAU,kCACV,eAAe,cACf,QAAQ,uCAAuC,OAAE"}