UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

100 lines (99 loc) • 4.04 kB
import { o as extractToolCallsFromAssistant } from "./tool-result-pairing-DxxMHOQj.mjs"; import { d as withOwnedSessionTranscriptWrites, i as captureOwnedTranscriptWriteAssertion, u as withOwnedSessionTranscriptWriterFence } from "./transcript-write-context-m7NE2aEm.mjs"; import "./tool-call-id-CutFFA5a.mjs"; import { l as makeZeroUsageSnapshot } from "./usage-XmAH1cfG.mjs"; import { r as readAssistantDisplayContent, t as ASSISTANT_DISPLAY_CONTENT_FIELD } from "./assistant-display-content-mzartsGP.mjs"; import { n as appendExactAssistantMessageToSessionTranscript } from "./transcript-DCh7fycW.mjs"; import { a as hasAssistantDisplayableNonTextContent, l as isAssistantTextContentType } from "./chat-display-projection.helpers-pbUdgTgb.mjs"; import { n as hasPersistedMedia } from "./user-turn-media-DxovqnvB.mjs"; //#region src/agents/assistant-error-transcript.ts /** Holds attempt failures until the logical run decides whether recovery succeeded. */ function createAssistantErrorTranscript(params) { const streamOutputs = /* @__PURE__ */ new WeakMap(); let pending; const clear = () => { const failure = pending; pending = void 0; failure?.replaceStream?.(false); }; return { clear, bindStream(source, replaceStream) { if (pending?.source === source) pending.replaceStream = replaceStream; else streamOutputs.set(source, replaceStream); }, snapshot() { return pending; }, restore(snapshot) { clear(); pending = snapshot; pending?.replaceStream?.(true); }, record(message, target, source = message) { pending = { message, source, target: withOwnedSessionTranscriptWriterFence(target), assertActive: captureOwnedTranscriptWriteAssertion(target), replaceStream: streamOutputs.get(source) }; streamOutputs.delete(source); const displayContent = readAssistantDisplayContent(message); if (!hasAssistantDisplayableNonTextContent(message) && !hasAssistantDisplayableNonTextContent({ content: displayContent }) && !hasPersistedMedia(message) && !message.openclawDelivery?.mediaUrls?.length) return; const text = message.content.filter((block) => isAssistantTextContentType(block.type)); const hasDisplayOverride = ASSISTANT_DISPLAY_CONTENT_FIELD in message; const { errorMessage, errorCode, errorType, errorBody, diagnostics, ...replayMessage } = message; pending.message = { role: "assistant", api: message.api, provider: message.provider, model: message.model, content: text, ...hasDisplayOverride ? { [ASSISTANT_DISPLAY_CONTENT_FIELD]: displayContent.filter((block) => isAssistantTextContentType(block.type)) } : {}, usage: makeZeroUsageSnapshot(), stopReason: "error", errorMessage, errorCode, errorType, errorBody, diagnostics, timestamp: message.timestamp }; return { ...replayMessage, content: message.content.filter((block) => !isAssistantTextContentType(block.type)), ...hasDisplayOverride ? { [ASSISTANT_DISPLAY_CONTENT_FIELD]: displayContent.filter((block) => !isAssistantTextContentType(block.type)) } : {}, stopReason: extractToolCallsFromAssistant(message).length > 0 ? "toolUse" : "stop" }; }, async settle(failed) { if (!failed) { clear(); return; } const failure = pending; pending = void 0; if (!failure) return; const { message, target, assertActive } = failure; await withOwnedSessionTranscriptWrites({ sessionTarget: target, assertCommitAllowed: assertActive, withTranscriptWrite: async (operation) => await operation() }, async () => { assertActive(); const result = await appendExactAssistantMessageToSessionTranscript({ ...target, expectedSessionId: target.sessionId, message, runId: params.runId, idempotencyKey: `${params.runId}:terminal-error`, config: params.config }); if (!result.ok) throw new Error(`Failed to persist terminal assistant error: ${result.reason}`); }); } }; } //#endregion export { createAssistantErrorTranscript as t };