UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

115 lines (114 loc) • 5.63 kB
import { t as formatErrorMessage } from "./errors-BvOkmQM5.mjs"; import { t as createSubsystemLogger } from "./subsystem-4NzR43uz.mjs"; import { w as runWithGatewayDetachedWorkContinuation } from "./gateway-work-admission-DAV5kkgV.mjs"; import { a as execRequestAbortSignal, l as withExecRequestOwners, u as withExecRequestTurn } from "./exec-request-context-u4rNuPjF.mjs"; import { r as runOutsidePreparedModelRuntimePluginGenerationScope } from "./prepared-model-runtime-generation-scope-Ck1wk1tN.mjs"; import { n as ToolInputError } from "./tool-input-error-mjW74R8m.mjs"; import { t as GatewayClientRequestError } from "./request-error-DgMXHa-w.mjs"; import { o as getGatewayToolCallerIdentity } from "./gateway-caller-context-CU8n6n_e.mjs"; import { t as jsonResult } from "./tool-results-BCM3fdVS.mjs"; import "./common-BkU19q6Q.mjs"; import { o as prepareSessionEventTargetForHost, r as captureSessionEventTargetForHost, t as enqueueSessionEventForHost } from "./session-event-handoff-BkyE9Uzx.mjs"; import { R as resolveReplyRunForCurrentSessionId } from "./reply-run-registry.state-BgHFgrrj.mjs"; import "./reply-run-registry-1HN3_KMU.mjs"; import { n as getAgentToolExecutionContext } from "./tool-execution-context-BwYF5HLu.mjs"; import { o as captureOperatorToolGatewayContinuationContext } from "./server-plugin-in-process-dispatch-CHKjkAiH.mjs"; import { n as callAgentToolGatewayRequest } from "./in-process-gateway-BYRZzLBf.mjs"; import { randomUUID } from "node:crypto"; //#region src/agents/tools/plugins-reload-handoff.ts const log = createSubsystemLogger("plugins/reload-handoff"); const pending = /* @__PURE__ */ new WeakSet(); /** The reply owner releases the turn; the ordinary reload owner still drains physical leases. */ async function handoffPluginReload(params) { if (getAgentToolExecutionContext()?.hasUnobservedAsyncToolResults) return jsonResult({ status: "deferred", message: "Read earlier async results before handing off the reload." }); const caller = getGatewayToolCallerIdentity(); const operation = params.sessionId ? resolveReplyRunForCurrentSessionId(params.sessionId) : void 0; if (!caller || !params.onYield || !operation?.ownerSettlement) throw new ToolInputError("reloadAndResume requires an active Gateway conversation with turn yielding."); if (pending.has(operation)) throw new ToolInputError("This turn already handed off a plugin reload."); pending.add(operation); let continuation = void 0; try { continuation = await captureOperatorToolGatewayContinuationContext({ agentId: caller.agentId, sessionKey: caller.sessionKey }); if (!continuation) throw new ToolInputError("reloadAndResume requires its admitted Gateway."); const target = await captureSessionEventTargetForHost(caller.agentId, caller.sessionKey); if (target.sessionId !== params.sessionId) throw new ToolInputError("The reload requester session changed before handoff."); continuation.assertCurrent(); operation.abortSignal.throwIfAborted(); params.signal?.throwIfAborted(); await params.onYield("Plugin reload handed off; resume with its result in this same conversation."); const retained = continuation; runOutsidePreparedModelRuntimePluginGenerationScope(() => runWithGatewayDetachedWorkContinuation(() => withExecRequestTurn({ identity: { runId: params.runId, sessionId: params.sessionId, sessionKey: caller.sessionKey, agentId: caller.agentId }, owners: params.requestOwners }, async () => { const signal = execRequestAbortSignal(params.requestOwners, operation.abortSignal) ?? operation.abortSignal; try { await operation.ownerSettlement; if (signal.aborted) return; let result; try { const destination = await prepareSessionEventTargetForHost(target); try { result = await retained.run(() => callAgentToolGatewayRequest({ method: "plugins.reload", params: params.request, sessionMutationCommitGuard: destination.assertCurrent, signal: AbortSignal.any([retained.signal, signal]), timeoutMs: null })); } finally { destination.release(); } } catch (error) { result = { ok: false, error: formatErrorMessage(error), ...error instanceof GatewayClientRequestError ? { code: error.gatewayCode, details: error.details } : {} }; } if (signal.aborted) return; const receipt = enqueueSessionEventForHost("Plugin reload result: " + params.formatResult(result) + "\nContinue the original task in this conversation. Do not repeat a completed reload.", withExecRequestOwners({ agentId: caller.agentId, sessionKey: caller.sessionKey, source: "plugin", contextKey: "plugin-reload:" + randomUUID(), expectedTarget: target, assertCurrent: retained.assertCurrent, abortSignal: signal }, params.requestOwners)); const accepted = await receipt.accepted; if (!accepted.ok) throw new Error(accepted.error); const outcome = await receipt.settled; if (outcome.status === "failed") throw new Error(outcome.error ?? "Plugin reload resume failed"); } finally { retained.release(); } }), "plugins:reload-handoff")).catch((error) => log.error("Plugin reload handoff failed: " + formatErrorMessage(error))).finally(() => retained.release()); return jsonResult({ status: "started", async: true, yielded: true, message: "Reload will run after turn cleanup; its result will resume this session." }); } catch (error) { pending.delete(operation); continuation?.release(); throw error; } } //#endregion export { handoffPluginReload };