UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

166 lines (165 loc) 7.37 kB
import { i as asOptionalRecord } from "./record-coerce-DHZ4bFlT.js"; import { s as asFiniteNumber } from "./number-coercion-CJQ8TR--.js"; import { t as setSafeTimeout } from "./timer-delay-T0mHtzex.js"; import { i as mergeAgentRunTerminalOutcome, l as normalizeBlockedLivenessWaitStatus, r as isStickyAgentRunTerminalOutcome, t as buildAgentRunTerminalOutcome } from "./agent-run-terminal-outcome-wSgVLvyR.js"; import { m as isNonTerminalAgentRunStatus } from "./subagent-announce-delivery-B2BgoPnM.js"; //#region src/gateway/server-methods/agent-wait-dedupe.ts const AGENT_WAITERS_BY_RUN_ID = /* @__PURE__ */ new Map(); function normalizeTerminalOutcomeForWaitSnapshot(outcome) { if (outcome.reason === "hard_timeout") return { status: outcome.status, error: outcome.error }; return normalizeBlockedLivenessWaitStatus(outcome); } function parseRunIdFromDedupeKey(key) { if (key.startsWith("agent:")) return key.slice(6) || null; if (key.startsWith("chat:")) return key.slice(5) || null; return null; } function asString(value) { return typeof value === "string" && value.trim() ? value : void 0; } function buildDedupeTerminalSnapshot(params) { const terminalOutcome = buildAgentRunTerminalOutcome({ status: params.status, livenessState: params.livenessState, error: params.error, stopReason: params.stopReason, timeoutPhase: params.timeoutPhase, providerStarted: params.providerStarted, startedAt: params.startedAt, endedAt: params.endedAt }); const normalized = normalizeTerminalOutcomeForWaitSnapshot(terminalOutcome); return { status: normalized.status, startedAt: params.startedAt, endedAt: params.endedAt, error: normalized.status === "error" ? normalized.error : normalized.status === "timeout" ? terminalOutcome.error : void 0, stopReason: params.stopReason, livenessState: params.livenessState, ...params.yielded ? { yielded: params.yielded } : {}, ...terminalOutcome.timeoutPhase ? { timeoutPhase: terminalOutcome.timeoutPhase } : {}, ...terminalOutcome.providerStarted !== void 0 ? { providerStarted: terminalOutcome.providerStarted } : {} }; } function removeWaiter(runId, waiter) { const waiters = AGENT_WAITERS_BY_RUN_ID.get(runId); if (!waiters) return; waiters.delete(waiter); if (waiters.size === 0) AGENT_WAITERS_BY_RUN_ID.delete(runId); } function addWaiter(runId, waiter) { const normalizedRunId = runId.trim(); if (!normalizedRunId) return () => {}; const existing = AGENT_WAITERS_BY_RUN_ID.get(normalizedRunId); if (existing) { existing.add(waiter); return () => removeWaiter(normalizedRunId, waiter); } AGENT_WAITERS_BY_RUN_ID.set(normalizedRunId, new Set([waiter])); return () => removeWaiter(normalizedRunId, waiter); } function notifyWaiters(runId) { const normalizedRunId = runId.trim(); if (!normalizedRunId) return; const waiters = AGENT_WAITERS_BY_RUN_ID.get(normalizedRunId); if (!waiters || waiters.size === 0) return; for (const waiter of waiters) waiter(); } function readTerminalSnapshotFromDedupeEntry(entry) { const payload = entry.payload; const status = typeof payload?.status === "string" ? payload.status : void 0; if (isNonTerminalAgentRunStatus(status)) return null; const startedAt = asFiniteNumber(payload?.startedAt); const endedAt = asFiniteNumber(payload?.endedAt) ?? entry.ts; const resultMeta = asOptionalRecord(asOptionalRecord(payload?.result)?.meta); const stopReason = asString(payload?.stopReason) ?? asString(resultMeta?.stopReason); const livenessState = asString(payload?.livenessState) ?? asString(resultMeta?.livenessState); const yielded = payload?.yielded === true || resultMeta?.yielded === true; const timeoutPhase = payload?.timeoutPhase ?? resultMeta?.timeoutPhase; const providerStarted = payload?.providerStarted ?? resultMeta?.providerStarted; const errorMessage = typeof payload?.error === "string" ? payload.error : typeof payload?.summary === "string" ? payload.summary : entry.error?.message; const terminalStatus = status === "ok" || status === "timeout" || status === "error" ? status : entry.ok ? null : "error"; if (!terminalStatus) return null; return buildDedupeTerminalSnapshot({ status: terminalStatus, startedAt, endedAt, error: errorMessage, stopReason, livenessState, yielded, timeoutPhase, providerStarted }); } function terminalOutcomeFromWaitSnapshot(snapshot) { if (snapshot.pendingError) return; return buildAgentRunTerminalOutcome(snapshot); } function readTerminalSnapshotFromGatewayDedupe(params) { if (params.ignoreAgentTerminalSnapshot) { const chatEntry = params.dedupe.get(`chat:${params.runId}`); if (!chatEntry) return null; return readTerminalSnapshotFromDedupeEntry(chatEntry); } const chatEntry = params.dedupe.get(`chat:${params.runId}`); const chatSnapshot = chatEntry ? readTerminalSnapshotFromDedupeEntry(chatEntry) : null; const agentEntry = params.dedupe.get(`agent:${params.runId}`); const agentSnapshot = agentEntry ? readTerminalSnapshotFromDedupeEntry(agentEntry) : null; if (agentEntry) { if (!agentSnapshot) { if (chatSnapshot && chatEntry && chatEntry.ts > agentEntry.ts) return chatSnapshot; return null; } } if (agentSnapshot && chatSnapshot && agentEntry && chatEntry) return chatEntry.ts > agentEntry.ts ? chatSnapshot : agentSnapshot; return agentSnapshot ?? chatSnapshot; } async function waitForTerminalGatewayDedupe(params) { const initial = readTerminalSnapshotFromGatewayDedupe(params); if (initial) return initial; if (params.timeoutMs <= 0 || params.signal?.aborted) return null; return await new Promise((resolve) => { let settled = false; const finish = (snapshot) => { if (settled) return; settled = true; if (timeoutHandle) clearTimeout(timeoutHandle); if (onAbort) params.signal?.removeEventListener("abort", onAbort); removeWaiterLocal?.(); resolve(snapshot); }; const onWake = () => { const snapshot = readTerminalSnapshotFromGatewayDedupe(params); if (snapshot) finish(snapshot); }; const removeWaiterLocal = addWaiter(params.runId, onWake); onWake(); if (settled) return; const timeoutHandle = setSafeTimeout(() => finish(null), params.timeoutMs); timeoutHandle.unref?.(); const onAbort = () => finish(null); params.signal?.addEventListener("abort", onAbort, { once: true }); }); } function setGatewayDedupeEntry(params) { const existing = params.dedupe.get(params.key); const existingSnapshot = existing ? readTerminalSnapshotFromDedupeEntry(existing) : null; const incomingSnapshot = readTerminalSnapshotFromDedupeEntry(params.entry); const existingOutcome = existingSnapshot ? terminalOutcomeFromWaitSnapshot(existingSnapshot) : void 0; const incomingOutcome = incomingSnapshot ? terminalOutcomeFromWaitSnapshot(incomingSnapshot) : void 0; if (existingOutcome && isStickyAgentRunTerminalOutcome(existingOutcome) && !incomingOutcome) return; if (existingOutcome && incomingOutcome && isStickyAgentRunTerminalOutcome(existingOutcome)) { if (mergeAgentRunTerminalOutcome(existingOutcome, incomingOutcome) === existingOutcome) return; } params.dedupe.set(params.key, params.entry); const runId = parseRunIdFromDedupeKey(params.key); if (!runId) return; if (!incomingSnapshot) return; notifyWaiters(runId); } //#endregion export { setGatewayDedupeEntry as n, waitForTerminalGatewayDedupe as r, readTerminalSnapshotFromGatewayDedupe as t };