UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

161 lines (160 loc) • 10.2 kB
import { l as normalizeOptionalString } from "./string-coerce-1VuiLaaR.mjs"; import { a as resolveGlobalSingleton } from "./global-singleton-0m-JziJW.mjs"; import { a as asOptionalRecord } from "./record-coerce-TIsquoVR.mjs"; import { M as parseAgentSessionKey } from "./session-key-C09ow4h0.mjs"; import { t as bindGatewayContextResolver } from "./gateway-context-binding-VqB7gkMe.mjs"; import "./gateway-request-scope-BSmCVVpP.mjs"; import { s as normalizeDeliveryContext } from "./delivery-context.shared-PF5njaoI.mjs"; import { s as createSessionWorkStartChangedError } from "./work-start-error-Dh9d0ImY.mjs"; import { n as loadExactSessionEntry } from "./session-accessor.sqlite-exact-read-JW6IveXD.mjs"; import { h as normalizeInputProvenance } from "./input-provenance-D1LHo5Qj.mjs"; import { t as everySessionTranscriptUserInputFrom } from "./session-accessor.sqlite-active-events-g60ynzeU.mjs"; import "./session-accessor-BDmTPdtx.mjs"; import "./lifecycle-BU4MFl1q.mjs"; import { n as sourceDeliveryTargetsMatch } from "./source-delivery-plan-B_VDfdVc.mjs"; import { AsyncLocalStorage } from "node:async_hooks"; //#region src/agents/agent-harness-completion-scope.ts const scopeRegistry = resolveGlobalSingleton(Symbol.for("openclaw.agentHarnessCompletionScope.registry"), () => ({ hostIssuedScopes: /* @__PURE__ */ new WeakSet() })); /** Creates a host-issued requester scope for agent harness completion. */ function createAgentHarnessCompletionScope(params) { const requesterSessionKey = params.requesterSessionKey.trim(); if (!requesterSessionKey) throw new Error("Harness completion scope requires requesterSessionKey"); const requesterAgentId = params.requesterAgentId?.trim() || parseAgentSessionKey(requesterSessionKey)?.agentId; if (!requesterAgentId) throw new Error("Harness completion scope requires an exact requester agent"); const requesterOrigin = normalizeDeliveryContext(params.requesterOrigin); const scope = { requesterSessionKey, requesterAgentId, ...requesterOrigin ? { requesterOrigin } : {} }; scopeRegistry.hostIssuedScopes.add(scope); bindGatewayContextResolver(scope, params.gatewayContextResolver); return scope; } function assertAgentHarnessCompletionScope(scope) { if (!scopeRegistry.hostIssuedScopes.has(scope)) throw new Error("Harness completion requires a host-issued scope"); return scope; } const sourceAdmissions = resolveGlobalSingleton(Symbol.for("openclaw.harnessCompletionSourceAdmission"), () => new AsyncLocalStorage()); /** The native source owner admits delivery; the requester receipt owns accepted recovery thereafter. */ async function withAgentHarnessCompletionAdmission(params, operation) { const scope = assertAgentHarnessCompletionScope(params.scope); let active = true; const assertCurrent = () => { if (!active || !params.isSourceCurrent()) throw new Error("Harness completion source owner retired"); }; assertCurrent(); try { return await sourceAdmissions.run({ ...params, scope, assertCurrent }, operation); } finally { active = false; } } function assertHarnessCompletionSourceAdmission(params) { const admission = sourceAdmissions.getStore(); if (!admission || admission.scope.requesterSessionKey !== params.requesterSessionKey || admission.scope.requesterAgentId !== params.requesterAgentId || admission.requesterSessionId !== params.requesterSessionId || admission.requesterLifecycleRevision !== params.requesterLifecycleRevision || admission.sourceSessionKey !== params.sourceSessionKey || admission.sourceRunId !== params.sourceRunId) throw new Error("Harness completion requires exact host-issued source admission"); admission.assertCurrent(); return admission.assertCurrent; } //#endregion //#region src/agents/agent-harness-completion-recovery.ts /** These receipts are stricter than legacy live-return classification: omission is not success. */ function hasHarnessCompletionFinalReceipt(receipt) { const target = receipt.deliveryContext; if (!target?.channel || !target.to || receipt.payloadsTruncated || receipt.messagingToolSentTargetsTruncated || receipt.messagingToolAggregateEvidenceUnaccounted) return false; const requiredProvider = normalizeOptionalString(target.channel)?.toLowerCase(); if (!requiredProvider) return false; if (receipt.messagingToolSentTargets?.some((sent) => normalizeOptionalString(sent.provider)?.toLowerCase() === requiredProvider && normalizeOptionalString(sent.accountId) === normalizeOptionalString(target.accountId) && sent.sourceReplyFinal === true && sent.visible === true && sourceDeliveryTargetsMatch(sent, target))) return true; return receipt.deliveryStatus?.status === "sent" && (receipt.deliveryStatus.resultCount ?? 0) > 0 && receipt.payloads?.some((payload) => payload.visible === true) === true; } const admittedClaims = /* @__PURE__ */ new WeakMap(); function sameCompletionClaim(left, right) { return Boolean(left && left.taskId === right.taskId && left.taskRunId === right.taskRunId && left.sourceRunId === right.sourceRunId && left.requesterSessionKey === right.requesterSessionKey && left.requesterAgentId === right.requesterAgentId && left.sessionId === right.sessionId && left.lifecycleRevision === right.lifecycleRevision); } function captureHarnessCompletionRecovery(params) { const provenance = normalizeInputProvenance(params.inputProvenance); if (!params.runId.startsWith("announce:") || provenance?.kind !== "inter_session" || !["agent_harness_task", "agent_harness_completion"].includes(provenance.sourceTool ?? "") || provenance.sourceChannel !== "internal" || !provenance.sourceSessionKey) return; const assertSourceCurrent = assertHarnessCompletionSourceAdmission({ requesterSessionKey: params.sessionKey, requesterAgentId: params.agentId, requesterSessionId: params.entry.sessionId, requesterLifecycleRevision: params.entry.lifecycleRevision, sourceSessionKey: provenance.sourceSessionKey, sourceRunId: params.runId }); const claim = { taskId: provenance.sourceSessionKey, taskRunId: provenance.sourceSessionKey, taskStatus: "succeeded", sourceRunId: params.runId, requesterSessionKey: params.sessionKey, requesterAgentId: params.agentId, sessionId: params.entry.sessionId, ...params.entry.lifecycleRevision ? { lifecycleRevision: params.entry.lifecycleRevision } : {} }; admittedClaims.set(claim, assertSourceCurrent); return claim; } /** A current session incarnation and its exact admitted completion receipt own further effects. */ function getOwedHarnessCompletionTask(claim, entry) { if (entry.sessionId !== claim.sessionId || entry.lifecycleRevision !== claim.lifecycleRevision) return; if (entry.restartRecoveryTerminalDeliveryEvidence?.some((receipt) => sameCompletionClaim(receipt.harnessCompletion, claim) && hasHarnessCompletionFinalReceipt(receipt))) return; if (sameCompletionClaim(entry.restartRecoveryHarnessCompletion, claim) || entry.restartRecoveryTerminalDeliveryEvidence?.some((receipt) => sameCompletionClaim(receipt.harnessCompletion, claim))) return claim; const assertSourceCurrent = admittedClaims.get(claim); if (!assertSourceCurrent) return; try { assertSourceCurrent(); return claim; } catch { return; } } /** Exact source lookup is independent of the display tail used to choose recovery policy. */ function readAdmittedHarnessCompletionInput(params) { const scope = { agentId: params.claim.requesterAgentId, sessionKey: params.claim.requesterSessionKey, sessionId: params.entry.sessionId, storePath: params.storePath }; const priorRunIds = (params.entry.restartRecoveryRuns ?? []).filter((run) => Boolean(run.lifecycleGeneration)).map((run) => run.runId); const claim = params.claim; const allowedRunIds = new Set([params.operationalRunId, ...priorRunIds].filter(Boolean)); let sourceChecked = false; return everySessionTranscriptUserInputFrom(scope, `${params.claim.sourceRunId}:user`, (message) => { const record = asOptionalRecord(message); const provenance = normalizeInputProvenance(record?.provenance); const annotatedRunId = asOptionalRecord(record?.["__openclaw"])?.runId; if (!sourceChecked) { sourceChecked = true; return record?.role === "user" && record.idempotencyKey === `${claim.sourceRunId}:user` && annotatedRunId === claim.sourceRunId && provenance?.kind === "inter_session" && provenance.sourceChannel === "internal" && ["agent_harness_task", "agent_harness_completion"].includes(provenance.sourceTool ?? "") && provenance.sourceSessionKey === claim.taskRunId; } if (record?.role !== "user") return true; const runId = typeof record.idempotencyKey === "string" ? [...allowedRunIds].find((id) => record.idempotencyKey === `${id}:user`) : annotatedRunId; return typeof runId === "string" && allowedRunIds.has(runId) && (annotatedRunId == null || annotatedRunId === runId) && provenance?.kind === "internal_system" && provenance.sourceTool === "main_session_restart_recovery" && provenance.sourceSessionKey === claim.requesterSessionKey; }); } /** The existing admitted execution guard rechecks this before execution and delegated effects. */ function createHarnessCompletionSourceAssertion(params) { return () => { params.priorAssertion?.(); const current = loadExactSessionEntry({ agentId: params.claim.requesterAgentId, sessionKey: params.claim.requesterSessionKey, storePath: params.storePath, readConsistency: "latest" }); if (!current || current.sessionKey !== params.claim.requesterSessionKey || !getOwedHarnessCompletionTask(params.claim, current.entry) || current.entry.restartRecoveryDeliveryRunId !== params.claim.sourceRunId && !readAdmittedHarnessCompletionInput({ claim: params.claim, entry: current.entry, storePath: params.storePath, operationalRunId: current.entry.restartRecoveryDeliveryRunId })) throw createSessionWorkStartChangedError(params.claim.requesterSessionKey); }; } //#endregion export { readAdmittedHarnessCompletionInput as a, withAgentHarnessCompletionAdmission as c, hasHarnessCompletionFinalReceipt as i, createHarnessCompletionSourceAssertion as n, assertAgentHarnessCompletionScope as o, getOwedHarnessCompletionTask as r, createAgentHarnessCompletionScope as s, captureHarnessCompletionRecovery as t };