@assistant-ui/core 0.3.11 → 0.3.13

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 (132) hide show
  1. package/dist/index.d.ts +6 -5
  2. package/dist/index.js +2 -2
  3. package/dist/index.js.map +1 -1
  4. package/dist/internal.d.ts +6 -5
  5. package/dist/internal.js +5 -4
  6. package/dist/react/client/interactable-model-context.d.ts.map +1 -1
  7. package/dist/react/client/interactable-model-context.js +5 -1
  8. package/dist/react/client/interactable-model-context.js.map +1 -1
  9. package/dist/runtime/api/message-runtime.d.ts +2 -3
  10. package/dist/runtime/api/message-runtime.d.ts.map +1 -1
  11. package/dist/runtime/api/message-runtime.js +2 -16
  12. package/dist/runtime/api/message-runtime.js.map +1 -1
  13. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  14. package/dist/runtime/api/thread-runtime.js +5 -1
  15. package/dist/runtime/api/thread-runtime.js.map +1 -1
  16. package/dist/runtime/base/base-composer-runtime-core.d.ts +25 -0
  17. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  18. package/dist/runtime/base/base-composer-runtime-core.js +64 -11
  19. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  20. package/dist/runtime/base/base-thread-runtime-core.d.ts +14 -0
  21. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  22. package/dist/runtime/base/base-thread-runtime-core.js +31 -0
  23. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  24. package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
  25. package/dist/runtime/base/default-edit-composer-runtime-core.js +1 -6
  26. package/dist/runtime/base/default-edit-composer-runtime-core.js.map +1 -1
  27. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
  28. package/dist/runtime/base/default-thread-composer-runtime-core.js +1 -4
  29. package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
  30. package/dist/runtime/internal.d.ts +4 -4
  31. package/dist/runtime/internal.js +4 -4
  32. package/dist/runtime/queue/external-thread-queue-adapter.d.ts +15 -0
  33. package/dist/runtime/queue/external-thread-queue-adapter.d.ts.map +1 -1
  34. package/dist/runtime/queue/message-queue.js +23 -10
  35. package/dist/runtime/queue/message-queue.js.map +1 -1
  36. package/dist/runtimes/external-store/external-store-adapter.d.ts +7 -0
  37. package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
  38. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +3 -1
  39. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  40. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +49 -13
  41. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  42. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  43. package/dist/runtimes/local/local-thread-runtime-core.js +2 -1
  44. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  45. package/dist/store/clients/external-thread.d.ts +61 -0
  46. package/dist/store/clients/external-thread.d.ts.map +1 -0
  47. package/dist/store/clients/external-thread.js +1445 -0
  48. package/dist/store/clients/external-thread.js.map +1 -0
  49. package/dist/store/clients/runtime-adapter.d.ts.map +1 -1
  50. package/dist/store/clients/runtime-adapter.js +5 -2
  51. package/dist/store/clients/runtime-adapter.js.map +1 -1
  52. package/dist/store/clients/single-thread-list.d.ts +9 -0
  53. package/dist/store/clients/single-thread-list.d.ts.map +1 -0
  54. package/dist/store/clients/single-thread-list.js +175 -0
  55. package/dist/store/clients/single-thread-list.js.map +1 -0
  56. package/dist/store/clients/suggestions.d.ts +3 -1
  57. package/dist/store/clients/suggestions.d.ts.map +1 -1
  58. package/dist/store/clients/suggestions.js +65 -37
  59. package/dist/store/clients/suggestions.js.map +1 -1
  60. package/dist/store/index.d.ts +5 -3
  61. package/dist/store/index.js +4 -2
  62. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  63. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +64 -50
  64. package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
  65. package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
  66. package/dist/store/runtime-clients/thread-runtime-client.js +98 -82
  67. package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
  68. package/dist/store/scope-registration.d.ts +2 -2
  69. package/dist/store/scopes/suggestions.d.ts +6 -1
  70. package/dist/store/scopes/suggestions.d.ts.map +1 -1
  71. package/dist/store/scopes/thread.d.ts +17 -0
  72. package/dist/store/scopes/thread.d.ts.map +1 -1
  73. package/dist/types/augmentations.d.ts +33 -0
  74. package/dist/types/augmentations.d.ts.map +1 -0
  75. package/dist/types/augmentations.js +0 -0
  76. package/dist/types/error.d.ts +15 -1
  77. package/dist/types/error.d.ts.map +1 -1
  78. package/dist/types/error.js +18 -1
  79. package/dist/types/error.js.map +1 -1
  80. package/dist/types/message.d.ts +2 -0
  81. package/dist/types/message.d.ts.map +1 -1
  82. package/dist/types/message.js.map +1 -1
  83. package/dist/utils/normalizePartStatus.d.ts +3 -2
  84. package/dist/utils/normalizePartStatus.d.ts.map +1 -1
  85. package/dist/utils/normalizePartStatus.js +15 -1
  86. package/dist/utils/normalizePartStatus.js.map +1 -1
  87. package/package.json +5 -5
  88. package/src/index.ts +7 -0
  89. package/src/internal.ts +1 -1
  90. package/src/react/client/interactable-model-context.ts +6 -1
  91. package/src/react/runtimes/useExternalStoreRuntime.suggestions.test.tsx +114 -0
  92. package/src/runtime/api/message-runtime.test.ts +1 -1
  93. package/src/runtime/api/message-runtime.ts +2 -35
  94. package/src/runtime/api/thread-runtime.ts +8 -1
  95. package/src/runtime/base/base-composer-runtime-core.ts +100 -8
  96. package/src/runtime/base/base-thread-runtime-core.ts +36 -0
  97. package/src/runtime/base/default-edit-composer-runtime-core.ts +1 -15
  98. package/src/runtime/base/default-thread-composer-runtime-core.ts +1 -11
  99. package/src/runtime/queue/external-thread-queue-adapter.ts +17 -0
  100. package/src/runtime/queue/message-queue.ts +26 -9
  101. package/src/runtimes/external-store/external-store-adapter.ts +7 -0
  102. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +100 -26
  103. package/src/runtimes/local/local-thread-runtime-core.ts +4 -1
  104. package/src/store/clients/external-thread.ts +1255 -0
  105. package/src/store/clients/runtime-adapter.ts +5 -2
  106. package/src/store/clients/single-thread-list.ts +116 -0
  107. package/src/store/clients/suggestions.ts +39 -13
  108. package/src/store/index.ts +6 -0
  109. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +13 -28
  110. package/src/store/runtime-clients/thread-runtime-client.ts +5 -0
  111. package/src/store/scopes/suggestions.ts +6 -0
  112. package/src/store/scopes/thread.ts +17 -0
  113. package/src/tests/append-interactable-snapshots.test.ts +350 -0
  114. package/src/tests/base-composer-runtime-core-send.test.ts +126 -0
  115. package/src/tests/base-composer-runtime-core.test.ts +108 -1
  116. package/src/tests/default-edit-composer-runtime-core.test.ts +0 -68
  117. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +300 -0
  118. package/src/tests/external-thread-attachments.test.tsx +584 -0
  119. package/src/tests/external-thread-branches.test.tsx +157 -0
  120. package/src/tests/external-thread-feedback.test.tsx +204 -0
  121. package/src/tests/external-thread-parity.test.tsx +548 -0
  122. package/src/tests/external-thread-refetch.test.tsx +117 -0
  123. package/src/tests/external-thread-speech.test.tsx +328 -0
  124. package/src/tests/external-thread-suggestions.test.tsx +59 -0
  125. package/src/tests/message-queue.test.ts +26 -0
  126. package/src/tests/thread-message-like.test.ts +39 -0
  127. package/src/tests/thread-switch-events.test.tsx +136 -0
  128. package/src/types/augmentations.ts +33 -0
  129. package/src/types/error.ts +24 -0
  130. package/src/types/message.ts +2 -0
  131. package/src/utils/normalizePartStatus.ts +27 -0
  132. package/src/tests/default-thread-composer-runtime-core.test.ts +0 -82
@@ -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","BaseThreadAdapters","speech","feedback","attachments","voice","BaseThreadRuntimeCore","_subscriptions","Set","_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","_voiceMessages","_voiceGeneration","_cachedMergedMessages","_cachedVoiceGeneration","_cachedMergedBase","_markVoiceMessagesDirty","_getBaseMessages","getMessages","messages","length","base","mostRecentAssistantMessage","this","role","metadata","unstable_state","composer","_contextProvider","constructor","getModelContext","_editComposers","Map","getEditComposer","get","beginEdit","has","Error","set","delete","getMessage","_notifySubscribers","getMessageById","baseMessages","voiceIdx","findIndex","m","id","parentId","at","index","undefined","getBranches","some","switchToBranch","branchId","callback","_notifyEventSubscribers","event","E","payload","subscribers","_eventSubscribers","subscribe","add","submitFeedback","type","adapter","submit","updatedMessage","submittedFeedback","addOrUpdateMessage","_stopSpeaking","speak","utterance","unsub","status","cancel","stopSpeaking","_voiceSession","Session","_voiceUnsubs","Array","_voiceVolume","_voiceVolumeSubscribers","getVoiceVolume","subscribeVoiceVolume","connectVoice","disconnectVoice","session","connect","unsubs","currentMode","Mode","isMuted","mode","push","onStatusChange","_finishVoiceAssistantMessage","onModeChange","onVolumeChange","volume","cb","onTranscript","transcript","_handleVoiceTranscript","_currentAssistantMsg","TranscriptItem","ensureInitialized","isFinal","content","text","custom","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\";\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 implements ThreadRuntimeCore {\n private _subscriptions = new Set<() => void>();\n private _isInitialized = false;\n\n protected readonly 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 ): void;\n public abstract cancelRun(): void;\n public abstract exportExternalState(): any;\n public abstract importExternalState(state: any): 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 this._contextProvider = _contextProvider;\n }\n\n public getModelContext() {\n return this._contextProvider.getModelContext();\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 protected _notifySubscribers() {\n for (const callback of this._subscriptions) callback();\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 subscribe(callback: () => void): Unsubscribe {\n this._subscriptions.add(callback);\n return () => this._subscriptions.delete(callback);\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 for (const cb of this._voiceVolumeSubscribers) cb();\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 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: { type: \"running\" },\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 ...(transcript.isFinal\n ? { status: { type: \"complete\", reason: \"stop\" } }\n : {}),\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 for (const cb of this._voiceVolumeSubscribers) cb();\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 this._contextProvider.subscribe?.(() => wrapped({})) ?? (() => {});\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)) wrapped({});\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","BaseThreadAdapters","speech","feedback","attachments","voice","BaseThreadRuntimeCore","_subscriptions","Set","_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","_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","callback","_notifyEventSubscribers","event","E","payload","subscribers","_eventSubscribers","subscribe","add","submitFeedback","type","adapter","submit","updatedMessage","submittedFeedback","addOrUpdateMessage","_stopSpeaking","speak","utterance","unsub","status","cancel","stopSpeaking","_voiceSession","Session","_voiceUnsubs","Array","_voiceVolume","_voiceVolumeSubscribers","getVoiceVolume","subscribeVoiceVolume","connectVoice","disconnectVoice","session","connect","unsubs","currentMode","Mode","isMuted","mode","push","onStatusChange","_finishVoiceAssistantMessage","onModeChange","onVolumeChange","volume","cb","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\";\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 implements ThreadRuntimeCore {\n private _subscriptions = new Set<() => void>();\n private _isInitialized = false;\n\n protected readonly 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 ): void;\n public abstract cancelRun(): void;\n public abstract exportExternalState(): any;\n public abstract importExternalState(state: any): 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 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 protected _notifySubscribers() {\n for (const callback of this._subscriptions) callback();\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 subscribe(callback: () => void): Unsubscribe {\n this._subscriptions.add(callback);\n return () => this._subscriptions.delete(callback);\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 for (const cb of this._voiceVolumeSubscribers) cb();\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 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: { type: \"running\" },\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 ...(transcript.isFinal\n ? { status: { type: \"complete\", reason: \"stop\" } }\n : {}),\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 for (const cb of this._voiceVolumeSubscribers) cb();\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 this._contextProvider.subscribe?.(() => wrapped({})) ?? (() => {});\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)) wrapped({});\n });\n }\n\n return () => {\n this._eventSubscribers.get(event)?.delete(wrapped);\n };\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"default-edit-composer-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/base/default-edit-composer-runtime-core.ts"],"mappings":";;;;;;;cAWa,uCAAuC;MACvC;MAIA;YAID,wBAAoB;YAIpB,uBAAmB;UAIrB;UACA;UACA;UACA;UAQA;EAGN,YAAA,SAAS;IACP;MAEM,cAAc;MACd,YAAY;;KAIpB,+BACE,UAAU;IAAa;IAAyB,SAAS;;MA6BlD;MAIA;EAIE,WACX,SAAS,KAAK,yCACd,UAAU,cAAW;EAkChB"}
1
+ {"version":3,"file":"default-edit-composer-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/base/default-edit-composer-runtime-core.ts"],"mappings":";;;;;;;cAUa,uCAAuC;MACvC;MAIA;YAID,wBAAoB;YAIpB,uBAAmB;UAIrB;UACA;UACA;UACA;UAQA;EAGN,YAAA,SAAS;IACP;MAEM,cAAc;MACd,YAAY;;KAIpB,+BACE,UAAU;IAAa;IAAyB,SAAS;;MA6BlD;MAIA;EAIE,WACX,SAAS,KAAK,yCACd,UAAU,cAAW;EAqBhB"}
@@ -1,4 +1,3 @@
1
- import { gateInteractableComposerMetadata } from "../../model-context/interactable-composer-metadata.js";
2
1
  import { liftNonTextParts } from "../../adapters/attachment.js";
3
2
  import { getThreadMessageText } from "../../utils/text.js";
4
3
  import { BaseComposerRuntimeCore } from "./base-composer-runtime-core.js";
@@ -48,12 +47,8 @@ var DefaultEditComposerRuntimeCore = class extends BaseComposerRuntimeCore {
48
47
  }
49
48
  async handleSend(message, options) {
50
49
  const content = this._nonTextPassthrough.length > 0 ? [...message.content, ...this._nonTextPassthrough] : message.content;
51
- const messages = this.runtime.messages;
52
- const parentIndex = this._parentId === null ? -1 : messages.findIndex((m) => m.id === this._parentId);
53
- const composerMetadata = gateInteractableComposerMetadata(this.runtime.getModelContext().unstable_composerMetadata, messages.slice(0, parentIndex + 1));
54
- const enriched = this.enrichWithComposerMetadata(message, composerMetadata);
55
50
  const appendTask = this.runtime.append({
56
- ...enriched,
51
+ ...message,
57
52
  content,
58
53
  parentId: this._parentId,
59
54
  sourceId: this._sourceId,
@@ -1 +1 @@
1
- {"version":3,"file":"default-edit-composer-runtime-core.js","names":["AppendMessage","ThreadMessage","CompleteAttachment","getThreadMessageText","liftNonTextParts","AttachmentAdapter","DictationAdapter","SendOptions","ThreadRuntimeCore","BaseComposerRuntimeCore","gateInteractableComposerMetadata","DefaultEditComposerRuntimeCore","canCancel","canSend","isEmpty","_isSending","getAttachmentAdapter","runtime","adapters","attachments","getDictationAdapter","dictation","_nonTextPassthrough","_parentId","_sourceId","endEditCallback","constructor","parentId","message","id","setText","setRole","role","content","filter","p","type","setAttachments","setRunConfig","composer","runConfig","sourceId","handleSend","Omit","options","length","messages","parentIndex","findIndex","m","composerMetadata","getModelContext","unstable_composerMetadata","slice","enriched","enrichWithComposerMetadata","appendTask","append","startRun","handleCancel","_notifySubscribers"],"sources":["../../../src/runtime/base/default-edit-composer-runtime-core.ts"],"sourcesContent":["import type { AppendMessage, ThreadMessage } from \"../../types/message\";\nimport type { CompleteAttachment } from \"../../types/attachment\";\nimport { getThreadMessageText } from \"../../utils/text\";\nimport { liftNonTextParts } from \"../../adapters/attachment\";\nimport type { AttachmentAdapter } from \"../../adapters/attachment\";\nimport type { DictationAdapter } from \"../../adapters/speech\";\nimport type { SendOptions } from \"../interfaces/composer-runtime-core\";\nimport type { ThreadRuntimeCore } from \"../interfaces/thread-runtime-core\";\nimport { BaseComposerRuntimeCore } from \"./base-composer-runtime-core\";\nimport { gateInteractableComposerMetadata } from \"../../model-context/interactable-composer-metadata\";\n\nexport class DefaultEditComposerRuntimeCore extends BaseComposerRuntimeCore {\n public get canCancel() {\n return true;\n }\n\n public get canSend() {\n return !this.isEmpty && !this._isSending;\n }\n\n protected getAttachmentAdapter() {\n return this.runtime.adapters?.attachments;\n }\n\n protected getDictationAdapter() {\n return this.runtime.adapters?.dictation;\n }\n\n private _nonTextPassthrough: readonly ThreadMessage[\"content\"][number][];\n private _parentId: string | null;\n private _sourceId: string | null;\n private runtime: ThreadRuntimeCore & {\n adapters?:\n | {\n attachments?: AttachmentAdapter | undefined;\n dictation?: DictationAdapter | undefined;\n }\n | undefined;\n };\n private endEditCallback: () => void;\n\n constructor(\n runtime: ThreadRuntimeCore & {\n adapters?:\n | {\n attachments?: AttachmentAdapter | undefined;\n dictation?: DictationAdapter | undefined;\n }\n | undefined;\n },\n endEditCallback: () => void,\n { parentId, message }: { parentId: string | null; message: ThreadMessage },\n ) {\n super();\n this.runtime = runtime;\n this.endEditCallback = endEditCallback;\n this._parentId = parentId;\n this._sourceId = message.id;\n this.setText(getThreadMessageText(message));\n\n this.setRole(message.role);\n\n let attachments: readonly CompleteAttachment[];\n if (message.role === \"user\") {\n attachments = [\n ...(message.attachments ?? []),\n ...liftNonTextParts(message.content),\n ];\n this._nonTextPassthrough = [];\n } else {\n attachments = message.attachments ?? [];\n this._nonTextPassthrough = message.content.filter(\n (p) => p.type !== \"text\",\n );\n }\n this.setAttachments(attachments);\n\n this.setRunConfig({ ...runtime.composer.runConfig });\n }\n\n public get parentId() {\n return this._parentId;\n }\n\n public get sourceId() {\n return this._sourceId;\n }\n\n public async handleSend(\n message: Omit<AppendMessage, \"parentId\" | \"sourceId\">,\n options?: SendOptions,\n ) {\n const content =\n this._nonTextPassthrough.length > 0\n ? ([\n ...message.content,\n ...this._nonTextPassthrough,\n ] as AppendMessage[\"content\"])\n : message.content;\n // Gate live state against the new branch's prefix (messages up to the\n // parent): an unchanged interactable re-stamps the prior baseline, an\n // interactable edited since the original message stamps its newest state.\n const messages = this.runtime.messages;\n const parentIndex =\n this._parentId === null\n ? -1\n : messages.findIndex((m) => m.id === this._parentId);\n const composerMetadata = gateInteractableComposerMetadata(\n this.runtime.getModelContext().unstable_composerMetadata,\n messages.slice(0, parentIndex + 1),\n );\n const enriched = this.enrichWithComposerMetadata(message, composerMetadata);\n const appendTask = this.runtime.append({\n ...enriched,\n content,\n parentId: this._parentId,\n sourceId: this._sourceId,\n startRun: options?.startRun,\n });\n\n this.handleCancel();\n return appendTask;\n }\n\n public handleCancel() {\n this.endEditCallback();\n this._notifySubscribers();\n }\n}\n"],"mappings":";;;;;AAWA,IAAaW,iCAAb,cAAoDF,wBAAwB;CAC1E,IAAWG,YAAY;EACrB,OAAO;CACT;CAEA,IAAWC,UAAU;EACnB,OAAO,CAAC,KAAKC,WAAW,CAAC,KAAKC;CAChC;CAEA,uBAAiC;EAC/B,OAAO,KAAKE,QAAQC,UAAUC;CAChC;CAEA,sBAAgC;EAC9B,OAAO,KAAKF,QAAQC,UAAUG;CAChC;CAEA;CACA;CACA;CACA;CAQA;CAEAK,YACET,SAQAQ,iBACA,EAAEE,UAAUC,WACZ;EACA,MAAM;EACN,KAAKX,UAAUA;EACf,KAAKQ,kBAAkBA;EACvB,KAAKF,YAAYI;EACjB,KAAKH,YAAYI,QAAQC;EACzB,KAAKC,QAAQ3B,qBAAqByB,OAAO,CAAC;EAE1C,KAAKG,QAAQH,QAAQI,IAAI;EAEzB,IAAIb;EACJ,IAAIS,QAAQI,SAAS,QAAQ;GAC3Bb,cAAc,CACZ,GAAIS,QAAQT,eAAe,CAAA,GAC3B,GAAGf,iBAAiBwB,QAAQK,OAAO,CAAC;GAEtC,KAAKX,sBAAsB,CAAA;EAC7B,OAAO;GACLH,cAAcS,QAAQT,eAAe,CAAA;GACrC,KAAKG,sBAAsBM,QAAQK,QAAQC,QACxCC,MAAMA,EAAEC,SAAS,MACpB;EACF;EACA,KAAKC,eAAelB,WAAW;EAE/B,KAAKmB,aAAa,EAAE,GAAGrB,QAAQsB,SAASC,UAAU,CAAC;CACrD;CAEA,IAAWb,WAAW;EACpB,OAAO,KAAKJ;CACd;CAEA,IAAWkB,WAAW;EACpB,OAAO,KAAKjB;CACd;CAEA,MAAakB,WACXd,SACAgB,SACA;EACA,MAAMX,UACJ,KAAKX,oBAAoBuB,SAAS,IAC7B,CACC,GAAGjB,QAAQK,SACX,GAAG,KAAKX,mBAAmB,IAE7BM,QAAQK;EAId,MAAMa,WAAW,KAAK7B,QAAQ6B;EAC9B,MAAMC,cACJ,KAAKxB,cAAc,OACf,KACAuB,SAASE,WAAWC,MAAMA,EAAEpB,OAAO,KAAKN,SAAS;EACvD,MAAM2B,mBAAmBxC,iCACvB,KAAKO,QAAQkC,gBAAgB,CAAC,CAACC,2BAC/BN,SAASO,MAAM,GAAGN,cAAc,CAAC,CACnC;EACA,MAAMO,WAAW,KAAKC,2BAA2B3B,SAASsB,gBAAgB;EAC1E,MAAMM,aAAa,KAAKvC,QAAQwC,OAAO;GACrC,GAAGH;GACHrB;GACAN,UAAU,KAAKJ;GACfkB,UAAU,KAAKjB;GACfkC,UAAUd,SAASc;EACrB,CAAC;EAED,KAAKC,aAAa;EAClB,OAAOH;CACT;CAEA,eAAsB;EACpB,KAAK/B,gBAAgB;EACrB,KAAKmC,mBAAmB;CAC1B;AACF"}
1
+ {"version":3,"file":"default-edit-composer-runtime-core.js","names":["AppendMessage","ThreadMessage","CompleteAttachment","getThreadMessageText","liftNonTextParts","AttachmentAdapter","DictationAdapter","SendOptions","ThreadRuntimeCore","BaseComposerRuntimeCore","DefaultEditComposerRuntimeCore","canCancel","canSend","isEmpty","_isSending","getAttachmentAdapter","runtime","adapters","attachments","getDictationAdapter","dictation","_nonTextPassthrough","_parentId","_sourceId","endEditCallback","constructor","parentId","message","id","setText","setRole","role","content","filter","p","type","setAttachments","setRunConfig","composer","runConfig","sourceId","handleSend","Omit","options","length","appendTask","append","startRun","handleCancel","_notifySubscribers"],"sources":["../../../src/runtime/base/default-edit-composer-runtime-core.ts"],"sourcesContent":["import type { AppendMessage, ThreadMessage } from \"../../types/message\";\nimport type { CompleteAttachment } from \"../../types/attachment\";\nimport { getThreadMessageText } from \"../../utils/text\";\nimport { liftNonTextParts } from \"../../adapters/attachment\";\nimport type { AttachmentAdapter } from \"../../adapters/attachment\";\nimport type { DictationAdapter } from \"../../adapters/speech\";\nimport type { SendOptions } from \"../interfaces/composer-runtime-core\";\nimport type { ThreadRuntimeCore } from \"../interfaces/thread-runtime-core\";\nimport { BaseComposerRuntimeCore } from \"./base-composer-runtime-core\";\n\nexport class DefaultEditComposerRuntimeCore extends BaseComposerRuntimeCore {\n public get canCancel() {\n return true;\n }\n\n public get canSend() {\n return !this.isEmpty && !this._isSending;\n }\n\n protected getAttachmentAdapter() {\n return this.runtime.adapters?.attachments;\n }\n\n protected getDictationAdapter() {\n return this.runtime.adapters?.dictation;\n }\n\n private _nonTextPassthrough: readonly ThreadMessage[\"content\"][number][];\n private _parentId: string | null;\n private _sourceId: string | null;\n private runtime: ThreadRuntimeCore & {\n adapters?:\n | {\n attachments?: AttachmentAdapter | undefined;\n dictation?: DictationAdapter | undefined;\n }\n | undefined;\n };\n private endEditCallback: () => void;\n\n constructor(\n runtime: ThreadRuntimeCore & {\n adapters?:\n | {\n attachments?: AttachmentAdapter | undefined;\n dictation?: DictationAdapter | undefined;\n }\n | undefined;\n },\n endEditCallback: () => void,\n { parentId, message }: { parentId: string | null; message: ThreadMessage },\n ) {\n super();\n this.runtime = runtime;\n this.endEditCallback = endEditCallback;\n this._parentId = parentId;\n this._sourceId = message.id;\n this.setText(getThreadMessageText(message));\n\n this.setRole(message.role);\n\n let attachments: readonly CompleteAttachment[];\n if (message.role === \"user\") {\n attachments = [\n ...(message.attachments ?? []),\n ...liftNonTextParts(message.content),\n ];\n this._nonTextPassthrough = [];\n } else {\n attachments = message.attachments ?? [];\n this._nonTextPassthrough = message.content.filter(\n (p) => p.type !== \"text\",\n );\n }\n this.setAttachments(attachments);\n\n this.setRunConfig({ ...runtime.composer.runConfig });\n }\n\n public get parentId() {\n return this._parentId;\n }\n\n public get sourceId() {\n return this._sourceId;\n }\n\n public async handleSend(\n message: Omit<AppendMessage, \"parentId\" | \"sourceId\">,\n options?: SendOptions,\n ) {\n const content =\n this._nonTextPassthrough.length > 0\n ? ([\n ...message.content,\n ...this._nonTextPassthrough,\n ] as AppendMessage[\"content\"])\n : message.content;\n const appendTask = this.runtime.append({\n ...message,\n content,\n parentId: this._parentId,\n sourceId: this._sourceId,\n startRun: options?.startRun,\n });\n\n this.handleCancel();\n return appendTask;\n }\n\n public handleCancel() {\n this.endEditCallback();\n this._notifySubscribers();\n }\n}\n"],"mappings":";;;;AAUA,IAAaU,iCAAb,cAAoDD,wBAAwB;CAC1E,IAAWE,YAAY;EACrB,OAAO;CACT;CAEA,IAAWC,UAAU;EACnB,OAAO,CAAC,KAAKC,WAAW,CAAC,KAAKC;CAChC;CAEA,uBAAiC;EAC/B,OAAO,KAAKE,QAAQC,UAAUC;CAChC;CAEA,sBAAgC;EAC9B,OAAO,KAAKF,QAAQC,UAAUG;CAChC;CAEA;CACA;CACA;CACA;CAQA;CAEAK,YACET,SAQAQ,iBACA,EAAEE,UAAUC,WACZ;EACA,MAAM;EACN,KAAKX,UAAUA;EACf,KAAKQ,kBAAkBA;EACvB,KAAKF,YAAYI;EACjB,KAAKH,YAAYI,QAAQC;EACzB,KAAKC,QAAQ1B,qBAAqBwB,OAAO,CAAC;EAE1C,KAAKG,QAAQH,QAAQI,IAAI;EAEzB,IAAIb;EACJ,IAAIS,QAAQI,SAAS,QAAQ;GAC3Bb,cAAc,CACZ,GAAIS,QAAQT,eAAe,CAAA,GAC3B,GAAGd,iBAAiBuB,QAAQK,OAAO,CAAC;GAEtC,KAAKX,sBAAsB,CAAA;EAC7B,OAAO;GACLH,cAAcS,QAAQT,eAAe,CAAA;GACrC,KAAKG,sBAAsBM,QAAQK,QAAQC,QACxCC,MAAMA,EAAEC,SAAS,MACpB;EACF;EACA,KAAKC,eAAelB,WAAW;EAE/B,KAAKmB,aAAa,EAAE,GAAGrB,QAAQsB,SAASC,UAAU,CAAC;CACrD;CAEA,IAAWb,WAAW;EACpB,OAAO,KAAKJ;CACd;CAEA,IAAWkB,WAAW;EACpB,OAAO,KAAKjB;CACd;CAEA,MAAakB,WACXd,SACAgB,SACA;EACA,MAAMX,UACJ,KAAKX,oBAAoBuB,SAAS,IAC7B,CACC,GAAGjB,QAAQK,SACX,GAAG,KAAKX,mBAAmB,IAE7BM,QAAQK;EACd,MAAMa,aAAa,KAAK7B,QAAQ8B,OAAO;GACrC,GAAGnB;GACHK;GACAN,UAAU,KAAKJ;GACfkB,UAAU,KAAKjB;GACfwB,UAAUJ,SAASI;EACrB,CAAC;EAED,KAAKC,aAAa;EAClB,OAAOH;CACT;CAEA,eAAsB;EACpB,KAAKrB,gBAAgB;EACrB,KAAKyB,mBAAmB;CAC1B;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"default-thread-composer-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/base/default-thread-composer-runtime-core.ts"],"mappings":";;;;;;;;;;;cAgBa,yCACH,mCACG;UAEH;MACG;MAIA;UAIH;MAQY,kBAAkB;EAgBtB,cACd,qBACA,WAAW;EAKG,gBAAgB;YAItB,wBAAoB;YAIpB,uBAAmB;UAIrB;EAUN,YAAA,SAAS,KAAK;IACZ;MAEM,cAAc;MACd,YAAY;;;EAUf,WAVe;EA+BT,WACX,SAAS,KAAK,yCACd,UAAU,cAAW;EAoBV,gBAAY"}
1
+ {"version":3,"file":"default-thread-composer-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/base/default-thread-composer-runtime-core.ts"],"mappings":";;;;;;;;;;;cAea,yCACH,mCACG;UAEH;MACG;MAIA;UAIH;MAQY,kBAAkB;EAgBtB,cACd,qBACA,WAAW;EAKG,gBAAgB;YAItB,wBAAoB;YAIpB,uBAAmB;UAIrB;EAUN,YAAA,SAAS,KAAK;IACZ;MAEM,cAAc;MACd,YAAY;;;EAUf,WAVe;EA+BT,WACX,SAAS,KAAK,yCACd,UAAU,cAAW;EAWV,gBAAY"}
@@ -1,4 +1,3 @@
1
- import { gateInteractableComposerMetadata } from "../../model-context/interactable-composer-metadata.js";
2
1
  import { EMPTY_QUEUE_ITEMS } from "../../store/scopes/queue-item.js";
3
2
  import { BaseComposerRuntimeCore } from "./base-composer-runtime-core.js";
4
3
  //#region src/runtime/base/default-thread-composer-runtime-core.ts
@@ -63,10 +62,8 @@ var DefaultThreadComposerRuntimeCore = class extends BaseComposerRuntimeCore {
63
62
  });
64
63
  }
65
64
  async handleSend(message, options) {
66
- const composerMetadata = gateInteractableComposerMetadata(this.runtime.getModelContext().unstable_composerMetadata, this.runtime.messages);
67
- const enriched = this.enrichWithComposerMetadata(message, composerMetadata);
68
65
  return this.runtime.append({
69
- ...enriched,
66
+ ...message,
70
67
  parentId: this.runtime.messages.at(-1)?.id ?? null,
71
68
  sourceId: null,
72
69
  startRun: options?.startRun,
@@ -1 +1 @@
1
- {"version":3,"file":"default-thread-composer-runtime-core.js","names":["AppendMessage","AttachmentAdapter","DictationAdapter","SendOptions","ThreadComposerRuntimeCore","ThreadRuntimeCore","QueuePlacement","EMPTY_QUEUE_ITEMS","QueueItemState","BaseComposerRuntimeCore","gateInteractableComposerMetadata","DefaultThreadComposerRuntimeCore","_canCancel","canCancel","canSend","isEmpty","runtime","isSendDisabled","_isSending","_queueCache","steer","queue","flat","getSteerQueueItems","getQueueItems","cache","length","moveQueueItem","queueItemId","placement","removeQueueItem","getAttachmentAdapter","adapters","attachments","getDictationAdapter","dictation","Omit","constructor","connect","lastIsSendDisabled","lastQueue","subscribe","changed","capabilities","cancel","_notifySubscribers","handleSend","message","options","composerMetadata","getModelContext","unstable_composerMetadata","messages","enriched","enrichWithComposerMetadata","append","parentId","at","id","sourceId","startRun","handleCancel","cancelRun"],"sources":["../../../src/runtime/base/default-thread-composer-runtime-core.ts"],"sourcesContent":["import type { AppendMessage } from \"../../types/message\";\nimport type { AttachmentAdapter } from \"../../adapters/attachment\";\nimport type { DictationAdapter } from \"../../adapters/speech\";\nimport type {\n SendOptions,\n ThreadComposerRuntimeCore,\n} from \"../interfaces/composer-runtime-core\";\nimport type { ThreadRuntimeCore } from \"../interfaces/thread-runtime-core\";\nimport type { QueuePlacement } from \"../queue/external-thread-queue-adapter\";\nimport {\n EMPTY_QUEUE_ITEMS,\n type QueueItemState,\n} from \"../../store/scopes/queue-item\";\nimport { BaseComposerRuntimeCore } from \"./base-composer-runtime-core\";\nimport { gateInteractableComposerMetadata } from \"../../model-context/interactable-composer-metadata\";\n\nexport class DefaultThreadComposerRuntimeCore\n extends BaseComposerRuntimeCore\n implements ThreadComposerRuntimeCore\n{\n private _canCancel = false;\n public get canCancel() {\n return this._canCancel;\n }\n\n public get canSend() {\n return !this.isEmpty && !this.runtime.isSendDisabled && !this._isSending;\n }\n\n private _queueCache:\n | {\n steer: readonly QueueItemState[];\n queue: readonly QueueItemState[];\n flat: readonly QueueItemState[];\n }\n | undefined;\n\n public override get queue(): readonly QueueItemState[] {\n const steer = this.runtime.getSteerQueueItems?.() ?? EMPTY_QUEUE_ITEMS;\n const queue = this.runtime.getQueueItems?.() ?? EMPTY_QUEUE_ITEMS;\n const cache = this._queueCache;\n if (cache && cache.steer === steer && cache.queue === queue)\n return cache.flat;\n const flat =\n steer.length === 0\n ? queue\n : queue.length === 0\n ? steer\n : [...steer, ...queue];\n this._queueCache = { steer, queue, flat };\n return flat;\n }\n\n public override moveQueueItem(\n queueItemId: string,\n placement: QueuePlacement,\n ): void {\n this.runtime.moveQueueItem?.(queueItemId, placement);\n }\n\n public override removeQueueItem(queueItemId: string): void {\n this.runtime.removeQueueItem?.(queueItemId);\n }\n\n protected getAttachmentAdapter() {\n return this.runtime.adapters?.attachments;\n }\n\n protected getDictationAdapter() {\n return this.runtime.adapters?.dictation;\n }\n\n private runtime: Omit<ThreadRuntimeCore, \"composer\"> & {\n adapters?:\n | {\n attachments?: AttachmentAdapter | undefined;\n dictation?: DictationAdapter | undefined;\n }\n | undefined;\n };\n\n constructor(\n runtime: Omit<ThreadRuntimeCore, \"composer\"> & {\n adapters?:\n | {\n attachments?: AttachmentAdapter | undefined;\n dictation?: DictationAdapter | undefined;\n }\n | undefined;\n },\n ) {\n super();\n this.runtime = runtime;\n this.connect();\n }\n\n public connect() {\n let lastIsSendDisabled = this.runtime.isSendDisabled;\n let lastQueue = this.queue;\n return this.runtime.subscribe(() => {\n let changed = false;\n if (this.canCancel !== this.runtime.capabilities.cancel) {\n this._canCancel = this.runtime.capabilities.cancel;\n changed = true;\n }\n if (lastIsSendDisabled !== this.runtime.isSendDisabled) {\n lastIsSendDisabled = this.runtime.isSendDisabled;\n changed = true;\n }\n if (lastQueue !== this.queue) {\n lastQueue = this.queue;\n changed = true;\n }\n if (changed) this._notifySubscribers();\n });\n }\n\n public async handleSend(\n message: Omit<AppendMessage, \"parentId\" | \"sourceId\">,\n options?: SendOptions,\n ) {\n // Merge provider-contributed metadata onto the outgoing user message\n // (same metadata.custom append path quotes ride). The interactables gate\n // runs here because it needs thread history, unavailable to the provider.\n const composerMetadata = gateInteractableComposerMetadata(\n this.runtime.getModelContext().unstable_composerMetadata,\n this.runtime.messages,\n );\n const enriched = this.enrichWithComposerMetadata(message, composerMetadata);\n\n return this.runtime.append({\n ...(enriched as AppendMessage),\n parentId: this.runtime.messages.at(-1)?.id ?? null,\n sourceId: null,\n startRun: options?.startRun,\n steer: options?.steer,\n });\n }\n\n public async handleCancel() {\n this.runtime.cancelRun();\n }\n}\n"],"mappings":";;;;AAgBA,IAAaW,mCAAb,cACUF,wBAEV;CACE,aAAqB;CACrB,IAAWI,YAAY;EACrB,OAAO,KAAKD;CACd;CAEA,IAAWE,UAAU;EACnB,OAAO,CAAC,KAAKC,WAAW,CAAC,KAAKC,QAAQC,kBAAkB,CAAC,KAAKC;CAChE;CAEA;CAQA,IAAoBG,QAAmC;EACrD,MAAMD,QAAQ,KAAKJ,QAAQO,qBAAqB,KAAKhB;EACrD,MAAMc,QAAQ,KAAKL,QAAQQ,gBAAgB,KAAKjB;EAChD,MAAMkB,QAAQ,KAAKN;EACnB,IAAIM,SAASA,MAAML,UAAUA,SAASK,MAAMJ,UAAUA,OACpD,OAAOI,MAAMH;EACf,MAAMA,OACJF,MAAMM,WAAW,IACbL,QACAA,MAAMK,WAAW,IACfN,QACA,CAAC,GAAGA,OAAO,GAAGC,KAAK;EAC3B,KAAKF,cAAc;GAAEC;GAAOC;GAAOC;EAAK;EACxC,OAAOA;CACT;CAEA,cACEM,aACAC,WACM;EACN,KAAKb,QAAQW,gBAAgBC,aAAaC,SAAS;CACrD;CAEA,gBAAgCD,aAA2B;EACzD,KAAKZ,QAAQc,kBAAkBF,WAAW;CAC5C;CAEA,uBAAiC;EAC/B,OAAO,KAAKZ,QAAQgB,UAAUC;CAChC;CAEA,sBAAgC;EAC9B,OAAO,KAAKjB,QAAQgB,UAAUG;CAChC;CAEA;CASAE,YACErB,SAQA;EACA,MAAM;EACN,KAAKA,UAAUA;EACf,KAAKsB,QAAQ;CACf;CAEA,UAAiB;EACf,IAAIC,qBAAqB,KAAKvB,QAAQC;EACtC,IAAIuB,YAAY,KAAKnB;EACrB,OAAO,KAAKL,QAAQyB,gBAAgB;GAClC,IAAIC,UAAU;GACd,IAAI,KAAK7B,cAAc,KAAKG,QAAQ2B,aAAaC,QAAQ;IACvD,KAAKhC,aAAa,KAAKI,QAAQ2B,aAAaC;IAC5CF,UAAU;GACZ;GACA,IAAIH,uBAAuB,KAAKvB,QAAQC,gBAAgB;IACtDsB,qBAAqB,KAAKvB,QAAQC;IAClCyB,UAAU;GACZ;GACA,IAAIF,cAAc,KAAKnB,OAAO;IAC5BmB,YAAY,KAAKnB;IACjBqB,UAAU;GACZ;GACA,IAAIA,SAAS,KAAKG,mBAAmB;EACvC,CAAC;CACH;CAEA,MAAaC,WACXC,SACAC,SACA;EAIA,MAAMC,mBAAmBvC,iCACvB,KAAKM,QAAQkC,gBAAgB,CAAC,CAACC,2BAC/B,KAAKnC,QAAQoC,QACf;EACA,MAAMC,WAAW,KAAKC,2BAA2BP,SAASE,gBAAgB;EAE1E,OAAO,KAAKjC,QAAQuC,OAAO;GACzB,GAAIF;GACJG,UAAU,KAAKxC,QAAQoC,SAASK,GAAG,EAAE,CAAC,EAAEC,MAAM;GAC9CC,UAAU;GACVC,UAAUZ,SAASY;GACnBxC,OAAO4B,SAAS5B;EAClB,CAAC;CACH;CAEA,MAAayC,eAAe;EAC1B,KAAK7C,QAAQ8C,UAAU;CACzB;AACF"}
1
+ {"version":3,"file":"default-thread-composer-runtime-core.js","names":["AppendMessage","AttachmentAdapter","DictationAdapter","SendOptions","ThreadComposerRuntimeCore","ThreadRuntimeCore","QueuePlacement","EMPTY_QUEUE_ITEMS","QueueItemState","BaseComposerRuntimeCore","DefaultThreadComposerRuntimeCore","_canCancel","canCancel","canSend","isEmpty","runtime","isSendDisabled","_isSending","_queueCache","steer","queue","flat","getSteerQueueItems","getQueueItems","cache","length","moveQueueItem","queueItemId","placement","removeQueueItem","getAttachmentAdapter","adapters","attachments","getDictationAdapter","dictation","Omit","constructor","connect","lastIsSendDisabled","lastQueue","subscribe","changed","capabilities","cancel","_notifySubscribers","handleSend","message","options","append","parentId","messages","at","id","sourceId","startRun","handleCancel","cancelRun"],"sources":["../../../src/runtime/base/default-thread-composer-runtime-core.ts"],"sourcesContent":["import type { AppendMessage } from \"../../types/message\";\nimport type { AttachmentAdapter } from \"../../adapters/attachment\";\nimport type { DictationAdapter } from \"../../adapters/speech\";\nimport type {\n SendOptions,\n ThreadComposerRuntimeCore,\n} from \"../interfaces/composer-runtime-core\";\nimport type { ThreadRuntimeCore } from \"../interfaces/thread-runtime-core\";\nimport type { QueuePlacement } from \"../queue/external-thread-queue-adapter\";\nimport {\n EMPTY_QUEUE_ITEMS,\n type QueueItemState,\n} from \"../../store/scopes/queue-item\";\nimport { BaseComposerRuntimeCore } from \"./base-composer-runtime-core\";\n\nexport class DefaultThreadComposerRuntimeCore\n extends BaseComposerRuntimeCore\n implements ThreadComposerRuntimeCore\n{\n private _canCancel = false;\n public get canCancel() {\n return this._canCancel;\n }\n\n public get canSend() {\n return !this.isEmpty && !this.runtime.isSendDisabled && !this._isSending;\n }\n\n private _queueCache:\n | {\n steer: readonly QueueItemState[];\n queue: readonly QueueItemState[];\n flat: readonly QueueItemState[];\n }\n | undefined;\n\n public override get queue(): readonly QueueItemState[] {\n const steer = this.runtime.getSteerQueueItems?.() ?? EMPTY_QUEUE_ITEMS;\n const queue = this.runtime.getQueueItems?.() ?? EMPTY_QUEUE_ITEMS;\n const cache = this._queueCache;\n if (cache && cache.steer === steer && cache.queue === queue)\n return cache.flat;\n const flat =\n steer.length === 0\n ? queue\n : queue.length === 0\n ? steer\n : [...steer, ...queue];\n this._queueCache = { steer, queue, flat };\n return flat;\n }\n\n public override moveQueueItem(\n queueItemId: string,\n placement: QueuePlacement,\n ): void {\n this.runtime.moveQueueItem?.(queueItemId, placement);\n }\n\n public override removeQueueItem(queueItemId: string): void {\n this.runtime.removeQueueItem?.(queueItemId);\n }\n\n protected getAttachmentAdapter() {\n return this.runtime.adapters?.attachments;\n }\n\n protected getDictationAdapter() {\n return this.runtime.adapters?.dictation;\n }\n\n private runtime: Omit<ThreadRuntimeCore, \"composer\"> & {\n adapters?:\n | {\n attachments?: AttachmentAdapter | undefined;\n dictation?: DictationAdapter | undefined;\n }\n | undefined;\n };\n\n constructor(\n runtime: Omit<ThreadRuntimeCore, \"composer\"> & {\n adapters?:\n | {\n attachments?: AttachmentAdapter | undefined;\n dictation?: DictationAdapter | undefined;\n }\n | undefined;\n },\n ) {\n super();\n this.runtime = runtime;\n this.connect();\n }\n\n public connect() {\n let lastIsSendDisabled = this.runtime.isSendDisabled;\n let lastQueue = this.queue;\n return this.runtime.subscribe(() => {\n let changed = false;\n if (this.canCancel !== this.runtime.capabilities.cancel) {\n this._canCancel = this.runtime.capabilities.cancel;\n changed = true;\n }\n if (lastIsSendDisabled !== this.runtime.isSendDisabled) {\n lastIsSendDisabled = this.runtime.isSendDisabled;\n changed = true;\n }\n if (lastQueue !== this.queue) {\n lastQueue = this.queue;\n changed = true;\n }\n if (changed) this._notifySubscribers();\n });\n }\n\n public async handleSend(\n message: Omit<AppendMessage, \"parentId\" | \"sourceId\">,\n options?: SendOptions,\n ) {\n return this.runtime.append({\n ...(message as AppendMessage),\n parentId: this.runtime.messages.at(-1)?.id ?? null,\n sourceId: null,\n startRun: options?.startRun,\n steer: options?.steer,\n });\n }\n\n public async handleCancel() {\n this.runtime.cancelRun();\n }\n}\n"],"mappings":";;;AAeA,IAAaU,mCAAb,cACUD,wBAEV;CACE,aAAqB;CACrB,IAAWG,YAAY;EACrB,OAAO,KAAKD;CACd;CAEA,IAAWE,UAAU;EACnB,OAAO,CAAC,KAAKC,WAAW,CAAC,KAAKC,QAAQC,kBAAkB,CAAC,KAAKC;CAChE;CAEA;CAQA,IAAoBG,QAAmC;EACrD,MAAMD,QAAQ,KAAKJ,QAAQO,qBAAqB,KAAKf;EACrD,MAAMa,QAAQ,KAAKL,QAAQQ,gBAAgB,KAAKhB;EAChD,MAAMiB,QAAQ,KAAKN;EACnB,IAAIM,SAASA,MAAML,UAAUA,SAASK,MAAMJ,UAAUA,OACpD,OAAOI,MAAMH;EACf,MAAMA,OACJF,MAAMM,WAAW,IACbL,QACAA,MAAMK,WAAW,IACfN,QACA,CAAC,GAAGA,OAAO,GAAGC,KAAK;EAC3B,KAAKF,cAAc;GAAEC;GAAOC;GAAOC;EAAK;EACxC,OAAOA;CACT;CAEA,cACEM,aACAC,WACM;EACN,KAAKb,QAAQW,gBAAgBC,aAAaC,SAAS;CACrD;CAEA,gBAAgCD,aAA2B;EACzD,KAAKZ,QAAQc,kBAAkBF,WAAW;CAC5C;CAEA,uBAAiC;EAC/B,OAAO,KAAKZ,QAAQgB,UAAUC;CAChC;CAEA,sBAAgC;EAC9B,OAAO,KAAKjB,QAAQgB,UAAUG;CAChC;CAEA;CASAE,YACErB,SAQA;EACA,MAAM;EACN,KAAKA,UAAUA;EACf,KAAKsB,QAAQ;CACf;CAEA,UAAiB;EACf,IAAIC,qBAAqB,KAAKvB,QAAQC;EACtC,IAAIuB,YAAY,KAAKnB;EACrB,OAAO,KAAKL,QAAQyB,gBAAgB;GAClC,IAAIC,UAAU;GACd,IAAI,KAAK7B,cAAc,KAAKG,QAAQ2B,aAAaC,QAAQ;IACvD,KAAKhC,aAAa,KAAKI,QAAQ2B,aAAaC;IAC5CF,UAAU;GACZ;GACA,IAAIH,uBAAuB,KAAKvB,QAAQC,gBAAgB;IACtDsB,qBAAqB,KAAKvB,QAAQC;IAClCyB,UAAU;GACZ;GACA,IAAIF,cAAc,KAAKnB,OAAO;IAC5BmB,YAAY,KAAKnB;IACjBqB,UAAU;GACZ;GACA,IAAIA,SAAS,KAAKG,mBAAmB;EACvC,CAAC;CACH;CAEA,MAAaC,WACXC,SACAC,SACA;EACA,OAAO,KAAKhC,QAAQiC,OAAO;GACzB,GAAIF;GACJG,UAAU,KAAKlC,QAAQmC,SAASC,GAAG,EAAE,CAAC,EAAEC,MAAM;GAC9CC,UAAU;GACVC,UAAUP,SAASO;GACnBnC,OAAO4B,SAAS5B;EAClB,CAAC;CACH;CAEA,MAAaoC,eAAe;EAC1B,KAAKxC,QAAQyC,UAAU;CACzB;AACF"}
@@ -1,10 +1,6 @@
1
1
  import { fromThreadMessageLike } from "./utils/thread-message-like.js";
2
2
  import { ExportedMessageRepository, ExportedMessageRepositoryItem, MessageRepository } from "./utils/message-repository.js";
3
3
  import { ComposerRuntimeCoreBinding, EditComposerRuntimeCoreBinding, MessageStateBinding, ThreadComposerRuntimeCoreBinding } from "./api/bindings.js";
4
- import { AttachmentRuntimeImpl, EditComposerAttachmentRuntimeImpl, MessageAttachmentRuntimeImpl, ThreadComposerAttachmentRuntimeImpl } from "./api/attachment-runtime.js";
5
- import { ComposerRuntimeImpl, EditComposerRuntimeImpl, ThreadComposerRuntimeImpl } from "./api/composer-runtime.js";
6
- import { MessagePartRuntimeImpl } from "./api/message-part-runtime.js";
7
- import { MessageRuntimeImpl } from "./api/message-runtime.js";
8
4
  import { BaseAssistantRuntimeCore } from "./base/base-assistant-runtime-core.js";
9
5
  import { BaseComposerRuntimeCore } from "./base/base-composer-runtime-core.js";
10
6
  import { DefaultThreadComposerRuntimeCore } from "./base/default-thread-composer-runtime-core.js";
@@ -12,6 +8,10 @@ import { DefaultEditComposerRuntimeCore } from "./base/default-edit-composer-run
12
8
  import { BaseThreadRuntimeCore } from "./base/base-thread-runtime-core.js";
13
9
  import { ThreadListItemRuntimeImpl, ThreadListItemStateBinding } from "./api/thread-list-item-runtime.js";
14
10
  import { ThreadListRuntimeCoreBinding, ThreadListRuntimeImpl } from "./api/thread-list-runtime.js";
11
+ import { AttachmentRuntimeImpl, EditComposerAttachmentRuntimeImpl, MessageAttachmentRuntimeImpl, ThreadComposerAttachmentRuntimeImpl } from "./api/attachment-runtime.js";
12
+ import { ComposerRuntimeImpl, EditComposerRuntimeImpl, ThreadComposerRuntimeImpl } from "./api/composer-runtime.js";
13
+ import { MessagePartRuntimeImpl } from "./api/message-part-runtime.js";
14
+ import { MessageRuntimeImpl } from "./api/message-runtime.js";
15
15
  import { symbolInnerMessage } from "./utils/external-store-message.js";
16
16
  import { getAutoStatus, isAutoStatus } from "./utils/auto-status.js";
17
17
  import { ThreadListItemRuntimeBinding, ThreadRuntimeCoreBinding, ThreadRuntimeImpl, getThreadState } from "./api/thread-runtime.js";
@@ -2,16 +2,16 @@ import { fromThreadMessageLike } from "./utils/thread-message-like.js";
2
2
  import { symbolInnerMessage } from "./utils/external-store-message.js";
3
3
  import { getAutoStatus, isAutoStatus } from "./utils/auto-status.js";
4
4
  import { ExportedMessageRepository, MessageRepository } from "./utils/message-repository.js";
5
- import { AttachmentRuntimeImpl, EditComposerAttachmentRuntimeImpl, MessageAttachmentRuntimeImpl, ThreadComposerAttachmentRuntimeImpl } from "./api/attachment-runtime.js";
6
- import { ComposerRuntimeImpl, EditComposerRuntimeImpl, ThreadComposerRuntimeImpl } from "./api/composer-runtime.js";
7
- import { MessagePartRuntimeImpl } from "./api/message-part-runtime.js";
8
- import { MessageRuntimeImpl } from "./api/message-runtime.js";
9
5
  import { BaseAssistantRuntimeCore } from "./base/base-assistant-runtime-core.js";
10
6
  import { BaseComposerRuntimeCore } from "./base/base-composer-runtime-core.js";
11
7
  import { DefaultThreadComposerRuntimeCore } from "./base/default-thread-composer-runtime-core.js";
12
8
  import { DefaultEditComposerRuntimeCore } from "./base/default-edit-composer-runtime-core.js";
13
9
  import { BaseThreadRuntimeCore } from "./base/base-thread-runtime-core.js";
14
10
  import { ThreadListItemRuntimeImpl } from "./api/thread-list-item-runtime.js";
11
+ import { AttachmentRuntimeImpl, EditComposerAttachmentRuntimeImpl, MessageAttachmentRuntimeImpl, ThreadComposerAttachmentRuntimeImpl } from "./api/attachment-runtime.js";
12
+ import { ComposerRuntimeImpl, EditComposerRuntimeImpl, ThreadComposerRuntimeImpl } from "./api/composer-runtime.js";
13
+ import { MessagePartRuntimeImpl } from "./api/message-part-runtime.js";
14
+ import { MessageRuntimeImpl } from "./api/message-runtime.js";
15
15
  import { ThreadRuntimeImpl, getThreadState } from "./api/thread-runtime.js";
16
16
  import { ThreadListRuntimeImpl } from "./api/thread-list-runtime.js";
17
17
  import { AssistantRuntimeImpl } from "./api/assistant-runtime.js";
@@ -26,6 +26,21 @@ type ExternalThreadQueueAdapter = {
26
26
  move: (queueItemId: string, placement: QueuePlacement) => void;
27
27
  edit: (queueItemId: string, message: AppendMessage) => void;
28
28
  remove: (queueItemId: string) => void;
29
+ /**
30
+ * Installed by the owning runtime, applied to a message as it leaves a lane.
31
+ * A message can wait through an entire run, so state the runtime attaches at
32
+ * send time is recomputed against the thread it actually lands on. Adapters
33
+ * from `createMessageQueue` provide this; a hand-rolled adapter that omits
34
+ * it dispatches whatever was enqueued.
35
+ */
36
+ __internal_setDispatchTransform?: ((transform: (message: AppendMessage) => AppendMessage) => void) | undefined;
37
+ /**
38
+ * Called by the owning runtime when the user cancels the run, before the run
39
+ * is aborted. Pauses the queue so the cancelled run's settle keeps the
40
+ * pending items instead of dispatching the next one; the next send re-arms
41
+ * draining. A hand-rolled adapter that omits it drains on cancel.
42
+ */
43
+ __internal_notifyCancelled?: (() => void) | undefined;
29
44
  };
30
45
  //#endregion
31
46
  export { ExternalThreadQueueAdapter, QueuePlacement };
@@ -1 +1 @@
1
- {"version":3,"file":"external-thread-queue-adapter.d.ts","names":[],"sources":["../../../src/runtime/queue/external-thread-queue-adapter.ts"],"mappings":";;;KAGY;WACD;WACA;WACA;;;;;;KAOC;EACV,gBAAgB;EAChB,qBAAqB;;EAErB,UAAU,SAAS;;EAEnB,QAAQ,SAAS;;;;;;;EAOjB,OAAO,qBAAqB,WAAW;EACvC,OAAO,qBAAqB,SAAS;EACrC,SAAS"}
1
+ {"version":3,"file":"external-thread-queue-adapter.d.ts","names":[],"sources":["../../../src/runtime/queue/external-thread-queue-adapter.ts"],"mappings":";;;KAGY;WACD;WACA;WACA;;;;;;KAOC;EACV,gBAAgB;EAChB,qBAAqB;;EAErB,UAAU,SAAS;;EAEnB,QAAQ,SAAS;;;;;;;EAOjB,OAAO,qBAAqB,WAAW;EACvC,OAAO,qBAAqB,SAAS;EACrC,SAAS;;;;;;;;EAQT,oCACM,YAAY,SAAS,kBAAkB;;;;;;;EAQ7C"}
@@ -23,8 +23,10 @@ const createMessageQueue = (driver) => {
23
23
  const subscribers = /* @__PURE__ */ new Set();
24
24
  let running = false;
25
25
  let paused = false;
26
+ let dispatchTransform = (m) => m;
26
27
  let suppressIdle = 0;
27
28
  let cancelSettles = 0;
29
+ let interrupting = false;
28
30
  const notify = () => {
29
31
  for (const callback of subscribers) callback();
30
32
  };
@@ -56,15 +58,20 @@ const createMessageQueue = (driver) => {
56
58
  });
57
59
  if (!message) return;
58
60
  running = true;
59
- driver.run(message, { steer: false });
61
+ driver.run(dispatchTransform(message), { steer: false });
60
62
  };
61
63
  const interrupt = (message) => {
62
64
  paused = false;
63
65
  suppressIdle += Math.max(cancelSettles, 1);
64
66
  cancelSettles = 0;
65
- driver.cancel();
67
+ interrupting = true;
68
+ try {
69
+ driver.cancel();
70
+ } finally {
71
+ interrupting = false;
72
+ }
66
73
  running = true;
67
- driver.run(message, { steer: true });
74
+ driver.run(dispatchTransform(message), { steer: true });
68
75
  };
69
76
  const push = (lane, message) => {
70
77
  paused = false;
@@ -146,6 +153,13 @@ const createMessageQueue = (driver) => {
146
153
  steer: lanes.steer.filter((item) => item.id !== queueItemId)
147
154
  });
148
155
  };
156
+ const notifyCancelled = () => {
157
+ if (interrupting) return;
158
+ if (running && cancelSettles === 0) {
159
+ paused = true;
160
+ cancelSettles = 1;
161
+ }
162
+ };
149
163
  const adapter = {
150
164
  items: lanes.queue,
151
165
  steerItems: lanes.steer,
@@ -153,7 +167,11 @@ const createMessageQueue = (driver) => {
153
167
  steer,
154
168
  move,
155
169
  edit,
156
- remove
170
+ remove,
171
+ __internal_setDispatchTransform: (transform) => {
172
+ dispatchTransform = transform;
173
+ },
174
+ __internal_notifyCancelled: notifyCancelled
157
175
  };
158
176
  return {
159
177
  adapter,
@@ -172,12 +190,7 @@ const createMessageQueue = (driver) => {
172
190
  running = false;
173
191
  advance();
174
192
  },
175
- notifyCancelled: () => {
176
- if (running && cancelSettles === 0) {
177
- paused = true;
178
- cancelSettles = 1;
179
- }
180
- },
193
+ notifyCancelled,
181
194
  clear: () => {
182
195
  messages.clear();
183
196
  setLanes({
@@ -1 +1 @@
1
- {"version":3,"file":"message-queue.js","names":["AppendMessage","FileMessagePart","TextMessagePart","EMPTY_QUEUE_ITEMS","QueueItemState","generateId","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","suppressIdle","cancelSettles","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","add"],"sources":["../../../src/runtime/queue/message-queue.ts"],"sourcesContent":["import type {\n AppendMessage,\n FileMessagePart,\n TextMessagePart,\n} from \"../../types/message\";\nimport {\n EMPTY_QUEUE_ITEMS,\n type QueueItemState,\n} from \"../../store/scopes/queue-item\";\nimport { generateId } from \"../../utils/id\";\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 // 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\n const notify = () => {\n for (const callback of subscribers) callback();\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(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 driver.cancel!();\n running = true;\n driver.run(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 adapter: ExternalThreadQueueAdapter = {\n items: lanes.queue,\n steerItems: lanes.steer,\n enqueue,\n steer,\n move,\n edit,\n remove,\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 if (running && cancelSettles === 0) {\n paused = true;\n cancelSettles = 1;\n }\n },\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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"}
1
+ {"version":3,"file":"message-queue.js","names":["AppendMessage","FileMessagePart","TextMessagePart","EMPTY_QUEUE_ITEMS","QueueItemState","generateId","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 {\n EMPTY_QUEUE_ITEMS,\n type QueueItemState,\n} from \"../../store/scopes/queue-item\";\nimport { generateId } from \"../../utils/id\";\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 for (const callback of subscribers) callback();\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":"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"}
@@ -83,6 +83,13 @@ type ExternalStoreAdapterBase<T> = {
83
83
  suggestions?: readonly ThreadSuggestion[] | undefined;
84
84
  state?: ReadonlyJSONValue | undefined;
85
85
  extras?: unknown;
86
+ /**
87
+ * Applies a message list the runtime rewrote, and is what tells the runtime
88
+ * a removal it makes will survive the next snapshot. Without it, cancelling a
89
+ * run leaves a trailing user message in the thread and the composer
90
+ * untouched; an adapter that removes that message itself owns handing it
91
+ * back, because the runtime cannot see a removal it did not make.
92
+ */
86
93
  setMessages?: ((messages: readonly T[]) => void) | undefined;
87
94
  /**
88
95
  * Fires when the user explicitly switches branches via the runtime's
@@ -1 +1 @@
1
- {"version":3,"file":"external-store-adapter.d.ts","names":[],"sources":["../../../src/runtimes/external-store/external-store-adapter.ts"],"mappings":";;;;;;;;;;;;KAqBY,wBAAwB;EAClC,QAAQ;EACR;EACA;EACA;EACA;EACA,SAAS;;KAGC;;;;EAIV;EACA;EACA,mBAAmB;EACnB,2BAA2B;;;;EAI3B,6BAA6B;;;;EAI7B,qBAAqB,qBAAqB;EAC1C,YACE,kBACA,sBACI;EACN,mBAEM,kBACA,QAAQ,wCACL;EAET,cAAc,qBAAqB;EACnC,gBAAgB,qBAAqB;EACrC,aAAa,qBAAqB;;KAGxB,8BAA8B,MACxC,SAAS,GACT,gBACG;;;;KAKO;EACV;EACA;;KAGG,qCAAqC;EACxC,gBAAgB,8BAA8B;;KAG3C,yBAAyB;;;;;;;EAO5B;;;;;;;;;EASA;;;;;;;;;EASA;EACA;EACA,oBAAoB;EACpB,oBAAoB;EACpB,uBAAuB;EACvB,QAAQ;EACR;EAEA,gBAAgB,mBAAmB;;;;;;;;;;;;;;;;;;EAkBnC,4BACM,OAAO;EAEb,aAAa,mBAAmB;EAChC;EACA,wBAAwB;EACxB,QAAQ,SAAS,kBAAkB;;EAEnC,QAAQ;EACR,WAAW,SAAS,kBAAkB;EACtC,aAAa,sBAAsB;EACnC,aACM,yBAAyB,QAAQ,mBAAmB;EAE1D,aAAa,QAAQ,oBAAoB;EACzC,kBAAkB;;;;;;;;;EASlB,yBAAyB;EACzB,oBACM,SAAS,yBAAyB;EAExC,qBACM;IAAW;IAAoB;;EAErC,4BACM,SAAS,iCAAiC;EAEhD,iBAAiB,8BAA8B;EAC/C;IAEM,cAAc;IACd,SAAS;IACT,YAAY;IACZ,QAAQ;IACR,WAAW;;;;IAIX,aAAa;;EAGnB;IAEM;;;;;;;;;;;;;;;;;;;;;EAsBN;;;;;;;;;;EAUA,oBACM,UAAU,eAAe;;KAIrB,qBAAqB,IAAI,iBACnC,yBAAyB,MACtB,UAAU,yBAEP,qCAAqC"}
1
+ {"version":3,"file":"external-store-adapter.d.ts","names":[],"sources":["../../../src/runtimes/external-store/external-store-adapter.ts"],"mappings":";;;;;;;;;;;;KAqBY,wBAAwB;EAClC,QAAQ;EACR;EACA;EACA;EACA;EACA,SAAS;;KAGC;;;;EAIV;EACA;EACA,mBAAmB;EACnB,2BAA2B;;;;EAI3B,6BAA6B;;;;EAI7B,qBAAqB,qBAAqB;EAC1C,YACE,kBACA,sBACI;EACN,mBAEM,kBACA,QAAQ,wCACL;EAET,cAAc,qBAAqB;EACnC,gBAAgB,qBAAqB;EACrC,aAAa,qBAAqB;;KAGxB,8BAA8B,MACxC,SAAS,GACT,gBACG;;;;KAKO;EACV;EACA;;KAGG,qCAAqC;EACxC,gBAAgB,8BAA8B;;KAG3C,yBAAyB;;;;;;;EAO5B;;;;;;;;;EASA;;;;;;;;;EASA;EACA;EACA,oBAAoB;EACpB,oBAAoB;EACpB,uBAAuB;EACvB,QAAQ;EACR;;;;;;;;EASA,gBAAgB,mBAAmB;;;;;;;;;;;;;;;;;;EAkBnC,4BACM,OAAO;EAEb,aAAa,mBAAmB;EAChC;EACA,wBAAwB;EACxB,QAAQ,SAAS,kBAAkB;;EAEnC,QAAQ;EACR,WAAW,SAAS,kBAAkB;EACtC,aAAa,sBAAsB;EACnC,aACM,yBAAyB,QAAQ,mBAAmB;EAE1D,aAAa,QAAQ,oBAAoB;EACzC,kBAAkB;;;;;;;;;EASlB,yBAAyB;EACzB,oBACM,SAAS,yBAAyB;EAExC,qBACM;IAAW;IAAoB;;EAErC,4BACM,SAAS,iCAAiC;EAEhD,iBAAiB,8BAA8B;EAC/C;IAEM,cAAc;IACd,SAAS;IACT,YAAY;IACZ,QAAQ;IACR,WAAW;;;;IAIX,aAAa;;EAGnB;IAEM;;;;;;;;;;;;;;;;;;;;;EAsBN;;;;;;;;;;EAUA,oBACM,UAAU,eAAe;;KAIrB,qBAAqB,IAAI,iBACnC,yBAAyB,MACtB,UAAU,yBAEP,qCAAqC"}
@@ -38,6 +38,7 @@ declare class ExternalStoreThreadRuntimeCore extends BaseThreadRuntimeCore imple
38
38
  extras: unknown;
39
39
  private _converter;
40
40
  private _store;
41
+ private _transformedQueue;
41
42
  /**
42
43
  * Client-side tool-invocations pipeline. Constructed lazily on first
43
44
  * snapshot — only when `adapter.unstable_enableToolInvocations === true`.
@@ -76,7 +77,7 @@ declare class ExternalStoreThreadRuntimeCore extends BaseThreadRuntimeCore imple
76
77
  * head elsewhere in the meantime.
77
78
  */
78
79
  private _notifyBranchChange;
79
- append(message: AppendMessage): Promise<void>;
80
+ append(rawMessage: AppendMessage): Promise<void>;
80
81
  deleteMessage(messageId: string): Promise<void>;
81
82
  getQueueItems(): readonly QueueItemState[];
82
83
  getSteerQueueItems(): readonly QueueItemState[];
@@ -87,6 +88,7 @@ declare class ExternalStoreThreadRuntimeCore extends BaseThreadRuntimeCore imple
87
88
  exportExternalState(): any;
88
89
  importExternalState(state: any): void;
89
90
  cancelRun(): void;
91
+ private dropEmptyOptimisticHead;
90
92
  addToolResult(options: AddToolResultOptions): void;
91
93
  resumeToolCall(options: ResumeToolCallOptions): void;
92
94
  respondToToolApproval(options: RespondToToolApprovalOptions): void;
@@ -1 +1 @@
1
- {"version":3,"file":"external-store-thread-runtime-core.d.ts","names":[],"sources":["../../../src/runtimes/external-store/external-store-thread-runtime-core.ts"],"mappings":";;;;;;;;;;;;;;;;cAmDa,qBACX,oBACA,mBAAmB;cAKR,uCACH,iCACG;UAEH;MAiBG,gBAAY;UAIf;EACD;EACA;MACI;MAIA;YAIQ,6BAA6B;MAI5B,sEAAK,sDAAA;MAId;kBARqC;;;;;;;MAarC,iCAAiC;EAKrC,sBAAsB;EACtB;UAEC;UAEA;;;;;UAMA;EAEQ,UAAU;EAQxB,YAAA,iBAAiB,sBACjB,OAAO;EAMF,sBAAsB,OAAO;;;;;;;UA8L5B;;;;;UAmEA;UACA;;;;;;;UAQA;EAmBQ,eAAe;;;;;;;;;UA6BvB;EAaK,OAAO,SAAS,gBAAgB;EAmChC,cAAc,oBAAoB;EAoBxC,0BApBwC;EA0BxC,+BANa;EAUb,cAAc,qBAAqB,WAAW;EAI9C,gBAAgB;EAIV,SAAS,QAAQ,iBAAiB;EAYlC,UAAU,QAAQ,kBAAkB;EAO1C;EAOA,oBAAoB;EAmBpB;EAwCA,cAAc,SAAS;EAMvB,eAAe,SAAS;EAoBxB,sBAAsB,SAAS;EAMtB,MAAM,2BAA2B;EAMjC,OAAO,MAAM;UAQrB"}
1
+ {"version":3,"file":"external-store-thread-runtime-core.d.ts","names":[],"sources":["../../../src/runtimes/external-store/external-store-thread-runtime-core.ts"],"mappings":";;;;;;;;;;;;;;;;cAwDa,qBACX,oBACA,mBAAmB;cAKR,uCACH,iCACG;UAEH;MAiBG,gBAAY;UAIf;EACD;EACA;MACI;MAIA;YAIQ,6BAA6B;MAI5B,sEAAK,sDAAA;MAId;kBARqC;;;;;;;MAarC,iCAAiC;EAKrC,sBAAsB;EACtB;UAEC;UAEA;UAEA;;;;;UAMA;EAEQ,UAAU;EAQxB,YAAA,iBAAiB,sBACjB,OAAO;EAMF,sBAAsB,OAAO;;;;;;;UA2M5B;;;;;UAmEA;UACA;;;;;;;UAQA;EAmBQ,eAAe;;;;;;;;;UA6BvB;EAaK,OAAO,YAAY,gBAAgB;EA2CnC,cAAc,oBAAoB;EAoBxC,0BApBwC;EA0BxC,+BANa;EAUb,cAAc,qBAAqB,WAAW;EAI9C,gBAAgB;EAIV,SAAS,QAAQ,iBAAiB;EAYlC,UAAU,QAAQ,kBAAkB;EAO1C;EAOA,oBAAoB;EAmBpB;UA+EC;EAOD,cAAc,SAAS;EAMvB,eAAe,SAAS;EAoBxB,sBAAsB,SAAS;EAMtB,MAAM,2BAA2B;EAMjC,OAAO,MAAM;UAQrB"}