UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

158 lines (157 loc) 7.3 kB
import { n as resolveGlobalMap } from "./global-singleton-Dc_stLtU.js"; import { T as validateAgentRunDelegatedAuthority, s as getActiveAgentRunDelegatedAuthority } from "./agent-run-registry-CKYKdfNd.js"; import { i as captureGatewayRootWorkAdmissionContinuationScope } from "./gateway-work-admission-R1IpuDim.js"; import { t as extractAssistantPhaseText } from "./chat-message-content-Dws_XUEQ.js"; //#region src/gateway/worker-environments/placement-turn-claim-events.ts const turnClaimReleaseWaiters = resolveGlobalMap(Symbol.for("openclaw.turnClaimReleaseWaiters"), (waitersByPath) => { const error = /* @__PURE__ */ new Error("Gateway lifecycle ended while waiting for turn claim release"); for (const bySession of waitersByPath.values()) for (const waiters of bySession.values()) for (const reject of waiters) reject(error); waitersByPath.clear(); }); const workerTurnClaimClosedHandlers = resolveGlobalMap(Symbol.for("openclaw.workerTurnClaimClosedHandlers"), (handlersByPath) => { handlersByPath.clear(); }); const workerTurnOwners = resolveGlobalMap(Symbol.for("openclaw.workerTurnExecutionIdentities"), (ownersByPath) => { for (const owners of ownersByPath.values()) for (const owner of owners.values()) owner.runtime?.scope?.release(); ownersByPath.clear(); }); const WORKER_TURN_EXECUTION_IDENTITY_PATH = Symbol("workerTurnExecutionIdentityPath"); function claimKey(claim) { return JSON.stringify([ claim.claimId, claim.runId, claim.placementGeneration, claim.owner.kind, claim.owner.kind === "worker" ? claim.owner.environmentId : null, claim.owner.kind === "worker" ? claim.owner.ownerEpoch : null ]); } /** Bind every worker to its live run; diagnostic provenance remains optional. */ function bindWorkerTurnOwner(store, claim, token, operationalRunInstance, source, assertRunActive, prepareAssistantTranscriptMessage) { const scope = captureGatewayRootWorkAdmissionContinuationScope(); const path = store[WORKER_TURN_EXECUTION_IDENTITY_PATH]; const delegatedAuthority = getActiveAgentRunDelegatedAuthority(operationalRunInstance); if (!path || !store.validateTurnClaim(claim) || !delegatedAuthority) { scope?.release(); throw new Error(`Session ${claim.sessionId} worker turn authority changed`); } const owners = workerTurnOwners.get(path) ?? /* @__PURE__ */ new Map(); const assertActive = () => { assertRunActive(); if (owners.get(claim.sessionId) !== owner || !store.validateTurnClaim(claim) || !validateAgentRunDelegatedAuthority(delegatedAuthority)) throw new Error(`Session ${claim.sessionId} worker turn authority changed`); }; const identity = Object.freeze({ agentId: source.agentId, delegatedAuthority, ...token ? { executionIdentityToken: token } : {}, operationalRunInstance, receiptAuthority: assertActive, sessionKey: source.sessionKey, turnClaim: claim }); const capability = Object.freeze({ async run(callback) { assertActive(); const result = await callback(identity); assertActive(); return result; } }); const existing = owners.get(claim.sessionId); const currentClaimKey = claimKey(claim); existing?.runtime.scope?.release(); const owner = { capability, claim, claimKey: currentClaimKey, runtime: { delegatedAuthority, prepareAssistantTranscriptMessage, scope: scope ?? void 0, store } }; owners.set(claim.sessionId, owner); workerTurnOwners.set(path, owners); } function getWorkerTurnExecutionIdentityCapability(store, claim) { const path = store[WORKER_TURN_EXECUTION_IDENTITY_PATH]; const bound = path ? workerTurnOwners.get(path)?.get(claim.sessionId) : void 0; return bound && bound.claimKey === claimKey(claim) && store.validateTurnClaim(claim) ? bound.capability : void 0; } function resolveWorkerTurnRuntime(identity) { const claim = identity.turnClaim; if (!claim || claim.owner.kind !== "worker" || identity.sessionId !== claim.sessionId || identity.runId !== claim.runId || identity.environmentId !== claim.owner.environmentId || identity.ownerEpoch !== claim.owner.ownerEpoch) return; const currentClaimKey = claimKey(claim); let owner; for (const owners of workerTurnOwners.values()) { const candidate = owners.get(claim.sessionId); if (candidate?.claimKey !== currentClaimKey) continue; if (owner) return; owner = candidate; } const runtime = owner?.runtime; if (!owner || !runtime || !runtime.store.validateTurnClaim(owner.claim) || !validateAgentRunDelegatedAuthority(runtime.delegatedAuthority)) return; return runtime; } function runWorkerTurnAdmissionContinuation(identity, run) { return resolveWorkerTurnRuntime(identity)?.scope?.run(run) ?? null; } /** Host-owned preparation runs at append time, after any awaited transcript admission. */ function prepareWorkerTurnTranscriptMessage(identity, message) { return resolveWorkerTurnRuntime(identity)?.prepareAssistantTranscriptMessage?.(message, extractAssistantPhaseText(message)) ?? message; } function attachWorkerTurnExecutionIdentityStore(store, path) { Object.defineProperty(store, WORKER_TURN_EXECUTION_IDENTITY_PATH, { value: path }); } function waitersFor(path, sessionId) { let bySession = turnClaimReleaseWaiters.get(path); if (!bySession) { bySession = /* @__PURE__ */ new Map(); turnClaimReleaseWaiters.set(path, bySession); } let waiters = bySession.get(sessionId); if (!waiters) { waiters = /* @__PURE__ */ new Set(); bySession.set(sessionId, waiters); } return waiters; } function signalTurnClaimRelease(path, sessionId) { const bySession = turnClaimReleaseWaiters.get(path); const waiters = bySession?.get(sessionId); if (!bySession || !waiters) return; bySession.delete(sessionId); if (bySession.size === 0) turnClaimReleaseWaiters.delete(path); for (const resolve of waiters) resolve(); } function removeTurnClaimReleaseWaiter(path, sessionId, waiter) { const bySession = turnClaimReleaseWaiters.get(path); const waiters = bySession?.get(sessionId); if (!bySession || !waiters) return; waiters.delete(waiter); if (waiters.size === 0) bySession.delete(sessionId); if (bySession.size === 0) turnClaimReleaseWaiters.delete(path); } function registerWorkerTurnClaimClosedHandler(path, handler) { const handlers = workerTurnClaimClosedHandlers.get(path) ?? /* @__PURE__ */ new Set(); handlers.add(handler); workerTurnClaimClosedHandlers.set(path, handlers); return () => { handlers.delete(handler); if (handlers.size === 0) workerTurnClaimClosedHandlers.delete(path); }; } function signalWorkerTurnClaimClosed(path, claim) { signalTurnClaimRelease(path, claim.sessionId); const owners = workerTurnOwners.get(path); const owner = owners?.get(claim.sessionId); if (owner?.claimKey === claimKey(claim)) { owner.runtime?.scope?.release(); owners?.delete(claim.sessionId); if (owners?.size === 0) workerTurnOwners.delete(path); } for (const handler of workerTurnClaimClosedHandlers.get(path) ?? []) try { handler(claim); } catch {} } //#endregion export { registerWorkerTurnClaimClosedHandler as a, signalTurnClaimRelease as c, prepareWorkerTurnTranscriptMessage as i, signalWorkerTurnClaimClosed as l, bindWorkerTurnOwner as n, removeTurnClaimReleaseWaiter as o, getWorkerTurnExecutionIdentityCapability as r, runWorkerTurnAdmissionContinuation as s, attachWorkerTurnExecutionIdentityStore as t, waitersFor as u };