openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
369 lines (368 loc) • 15.2 kB
JavaScript
import { l as normalizeOptionalString } from "./string-coerce-1VuiLaaR.mjs";
import { t as formatErrorMessage } from "./errors-BvOkmQM5.mjs";
import { n as normalizeAgentId } from "./agent-id-D1-Q6vR4.mjs";
import "./session-key-DY3MOX4N.mjs";
import { h as parseAgentSessionKey, r as isAcpSessionKey, s as isSubagentSessionKey } from "./session-key-utils-CDyBC9Gn.mjs";
import { c as resolveSessionStorePathCore } from "./paths-Bonddxfk.mjs";
import { h as resolveSessionAgentId } from "./agent-scope-bJOokm5r.mjs";
import { l as getActiveAgentRunDelegatedAuthority } from "./agent-run-registry-Cm8FlLIi.mjs";
import { l as retireSessionMcpRuntime } from "./agent-bundle-mcp-manager-api-B24ukpdI.mjs";
import { r as logVerbose } from "./globals-yEiTitH8.mjs";
import { i as resolveCommandAuthorization } from "./command-auth-BHrKDij6.mjs";
import { o as loadSessionEntry } from "./session-accessor.sqlite-entry-DLa7_9ui.mjs";
import "./session-accessor-C3ljJ974.mjs";
import { c as resolveSessionAbortTarget, i as markSessionAbortTarget } from "./session-accessor.entry-mutation-telsi3Ig.mjs";
import { a as ACTIVE_EMBEDDED_RUNS_BY_RUN_ID, i as ACTIVE_EMBEDDED_RUNS, o as ACTIVE_EMBEDDED_RUN_REGISTRATIONS } from "./run-state-D054QiMr.mjs";
import { n as getAcpSessionManager } from "./manager-sn_kcSXp.mjs";
import { y as resolveReplyOperationsForSession } from "./reply-run-registry.registry-ICalZVvY.mjs";
import "./reply-run-registry-1HN3_KMU.mjs";
import { n as abortEmbeddedAgentRun } from "./runs-Qhulcs4s.mjs";
import { i as resolveActiveEmbeddedRunSessionId } from "./active-run-projections-TAxZeJ_S.mjs";
import "./sessions-CRUJeu5H.mjs";
import { t as resolveEffectiveResetTargetSessionKey } from "./acp-reset-target-j7GMtDbc.mjs";
import { s as resolveSessionConversationBindingContext } from "./session-conversation-binding-Ct7uOkBw.mjs";
import { o as resolveInternalSessionKey, s as resolveMainSessionAlias } from "./sessions-resolution-DvbCWXwD.mjs";
import "./sessions-helpers-CA0CJ1ys.mjs";
import { r as captureExecRequestSubagentSelection } from "./subagent-control-scope-BK6Z23s2.mjs";
import { n as captureExecRequestCancellation } from "./bash-process-control-CcTL6Huf.mjs";
import { t as killAllControlledSubagentRuns } from "./subagent-control-kill-BF4IB_0r.mjs";
import { a as prepareSessionLifecycleQueueCleanup } from "./cleanup-BBmMSpbZ.mjs";
import "./subagent-control-CpvtvvWe.mjs";
import { a as shouldPersistAbortCutoff, i as resolveAbortCutoffFromContext } from "./abort-cutoff-Cy_3zrWp.mjs";
import { r as setAbortMemory } from "./abort-primitives-BWGbzk7d.mjs";
//#region src/agents/embedded-agent-runner/runs.abort-target.ts
/** Follow admitted retries while keeping legacy compaction bound to its exact handle. */
function prepareEmbeddedAgentRunAbort(sessionId) {
const handle = ACTIVE_EMBEDDED_RUNS.get(sessionId);
const registration = handle && ACTIVE_EMBEDDED_RUN_REGISTRATIONS.get(handle);
const instance = registration?.operationalRunInstance;
const authority = registration?.delegatedAuthority;
const agentId = registration?.agentId;
const sessionKey = registration?.sessionKey;
const resolveCurrent = () => {
if (!handle || !registration) return;
if (!instance || !authority) return ACTIVE_EMBEDDED_RUNS.get(sessionId) === handle && ACTIVE_EMBEDDED_RUN_REGISTRATIONS.get(handle) === registration ? registration : void 0;
if (getActiveAgentRunDelegatedAuthority(instance) !== authority) return;
const successor = ACTIVE_EMBEDDED_RUNS_BY_RUN_ID.get(instance.runId);
const current = successor && ACTIVE_EMBEDDED_RUN_REGISTRATIONS.get(successor);
return current && current.operationalRunInstance?.instanceId === instance.instanceId && current.operationalRunInstance.runId === instance.runId && current.delegatedAuthority === authority && current.agentId === agentId && current.sessionKey === sessionKey && ACTIVE_EMBEDDED_RUNS.get(current.sessionId) === successor ? current : void 0;
};
return () => {
const current = resolveCurrent();
return current ? {
active: true,
aborted: abortEmbeddedAgentRun(current.sessionId),
sessionId: current.sessionId
} : {
active: false,
aborted: false
};
};
}
//#endregion
//#region src/auto-reply/reply/abort-operation.ts
function prepareSessionRunTargetAbort(params) {
const key = normalizeOptionalString(params.key);
const operations = resolveReplyOperationsForSession({
...params,
sessionKeys: key ? [key] : []
});
const sessionIds = new Set(operations.map((operation) => operation.sessionId));
const explicitSessionId = normalizeOptionalString(params.sessionId);
const commands = key || explicitSessionId ? captureExecRequestCancellation({
sessionKey: key,
sessionId: explicitSessionId,
agentId: params.agentId
}) : void 0;
if (explicitSessionId) sessionIds.add(explicitSessionId);
if (key) {
const activeSessionId = resolveActiveEmbeddedRunSessionId(key);
if (activeSessionId && (sessionIds.has(activeSessionId) || parseAgentSessionKey(key)?.agentId === normalizeAgentId(params.agentId))) sessionIds.add(activeSessionId);
}
const runs = [...sessionIds].map(prepareEmbeddedAgentRunAbort);
return () => {
let active = operations.some((operation) => !operation.result);
const failures = [];
let aborted = commands?.cancel() === true;
for (const operation of operations) {
for (const sessionId of operation.captureOwnedSessionIds()) sessionIds.add(sessionId);
try {
aborted = operation.abortByUser() || aborted;
} catch (error) {
failures.push(error);
}
}
for (const run of runs) try {
const outcome = run();
active ||= outcome.active;
aborted ||= outcome.aborted;
if (outcome.sessionId) sessionIds.add(outcome.sessionId);
} catch (error) {
failures.push(error);
}
const retirement = !active || aborted || failures.length > 0 ? Promise.allSettled([...[...sessionIds].map((sessionId) => retireSessionMcpRuntime({
sessionId,
reason: "session-stop",
preserveActiveLeases: true
})), commands?.settle()]).then((results) => {
for (const result of results) if (result.status === "rejected") failures.push(result.reason);
if (failures.length === 1) throw failures[0];
if (failures.length > 1) throw new AggregateError(failures, failures.map(formatErrorMessage).join("; "));
}) : void 0;
return {
active,
aborted,
retirement
};
};
}
function resolveStoredSessionId(params) {
const storePath = resolveSessionStorePathCore(params.cfg.session?.store, { agentId: params.agentId });
try {
return loadSessionEntry({
agentId: params.agentId,
clone: false,
sessionKey: params.sessionKey,
storePath
})?.sessionId;
} catch {
return;
}
}
async function stopSubagentsForRequester(params) {
const cleaned = normalizeOptionalString(params.requesterSessionKey);
if (!cleaned) {
await params.beforeKill?.(() => {});
return {
stopped: 0,
failed: 0
};
}
const { alias } = resolveMainSessionAlias(params.cfg);
const requesterKey = resolveInternalSessionKey({
key: cleaned,
alias
});
const controllerAgentId = resolveSessionAgentId({
config: params.cfg,
sessionKey: requesterKey,
fallbackAgentId: params.requesterAgentId
});
const controller = {
controllerSessionKey: requesterKey,
controllerAgentId,
callerSessionKey: requesterKey,
callerIsSubagent: isSubagentSessionKey(requesterKey),
controlScope: "children"
};
const commands = captureExecRequestCancellation({
sessionKey: requesterKey,
agentId: controllerAgentId
});
const requestSelection = captureExecRequestSubagentSelection({
cfg: params.cfg,
controller,
owners: commands.owners,
sessionOrigin: params.requesterSession ? {
target: {
...params.requesterSession,
sessionKey: requesterKey,
agentId: controllerAgentId
},
acceptsRequest: () => true
} : void 0
});
const result = await killAllControlledSubagentRuns({
cfg: params.cfg,
controller,
runs: requestSelection.runs,
requestSelection,
assertCurrent: params.assertCurrent,
suppressTaskDelivery: true,
beforeKill: params.beforeKill
});
if (result.status === "error") logVerbose(`abort: failed to stop subagents for ${requesterKey}: ${result.error}`);
if (result.killed > 0) logVerbose(`abort: stopped ${result.killed} subagent run(s) for ${requesterKey}`);
return {
stopped: result.killed,
failed: result.status === "error" ? result.failed : 0,
...result.execAborted ? { execAborted: true } : {}
};
}
async function executeFastAbortRequest(params, request) {
const { ctx, cfg } = params;
const { commandSessionKey, targetKey, resolveTargetAgentId } = request;
const auth = resolveCommandAuthorization({
ctx,
cfg,
commandAuthorized: ctx.CommandAuthorized
});
if (!auth.isAuthorizedSender) return {
handled: false,
aborted: false
};
const agentId = resolveTargetAgentId();
const abortKey = targetKey ?? auth.from ?? auth.to;
const requesterSessionKey = targetKey ?? ctx.SessionKey ?? abortKey;
if (targetKey) {
const storePath = resolveSessionStorePathCore(cfg.session?.store, { agentId });
const abortCutoffForTarget = (target) => shouldPersistAbortCutoff({
commandSessionKey,
targetSessionKey: target.sessionKey
}) ? resolveAbortCutoffFromContext(ctx) : void 0;
let resolvedAbortTarget = null;
try {
resolvedAbortTarget = resolveSessionAbortTarget({
agentId,
sessionKey: targetKey,
storePath
});
} catch (error) {
logVerbose(`abort: failed to resolve abort metadata for ${targetKey}: ${formatErrorMessage(error)}`);
}
const resolvedTargetKey = resolvedAbortTarget?.sessionKey ?? targetKey;
const assertCurrent = () => {
if (params.isCommandTargetCurrent?.() === false) throw new Error("The selected session changed before it could be stopped.");
};
const prepareTarget = (key) => {
const targetAgentId = key === resolvedTargetKey ? agentId : resolveSessionAgentId({
config: cfg,
sessionKey: key,
fallbackAgentId: ctx.AgentId ?? agentId
});
const sessionId = resolveReplyOperationsForSession({
sessionKeys: [key],
agentId: targetAgentId
})[0]?.sessionId ?? (key === resolvedTargetKey ? resolvedAbortTarget?.sessionId : resolveStoredSessionId({
cfg,
sessionKey: key,
agentId: targetAgentId
}));
const target = {
key,
agentId: targetAgentId,
sessionId
};
return {
abort: prepareSessionRunTargetAbort(target),
clearQueues: prepareSessionLifecycleQueueCleanup({
...target,
keys: [key, sessionId],
sessionKey: key,
assertCurrent
})
};
};
const preparedTargets = new Map([resolvedTargetKey, ...commandSessionKey ? [commandSessionKey] : []].map((key) => [key, prepareTarget(key)]));
let aborted = false;
let activeAbortRejected = false;
const acpCancellations = [];
try {
const { stopped, failed, execAborted } = await stopSubagentsForRequester({
cfg,
requesterSessionKey,
requesterAgentId: agentId,
requesterSession: resolvedAbortTarget?.sessionId ? {
storePath,
sessionId: resolvedAbortTarget.sessionId,
lifecycleRevision: resolvedAbortTarget.entry.lifecycleRevision ?? null
} : void 0,
assertCurrent,
beforeKill: async (sealRootSelection) => {
assertCurrent();
const bindingContext = commandSessionKey ? resolveSessionConversationBindingContext(cfg, ctx) : void 0;
const conversationBoundAcpTargetKey = commandSessionKey ? await (bindingContext ? resolveEffectiveResetTargetSessionKey({
cfg,
...bindingContext,
activeSessionKey: commandSessionKey,
skipConfiguredFallbackWhenActiveSessionNonAcp: false,
fallbackToActiveAcpWhenUnbound: false
}) : void 0) : void 0;
const boundAcpTargetKey = !isAcpSessionKey(resolvedTargetKey) ? conversationBoundAcpTargetKey : void 0;
const abortTargetKeys = [resolvedTargetKey];
if (boundAcpTargetKey && boundAcpTargetKey !== resolvedTargetKey) abortTargetKeys.push(boundAcpTargetKey);
const sourceAbortKey = commandSessionKey && !abortTargetKeys.includes(commandSessionKey) && conversationBoundAcpTargetKey && abortTargetKeys.includes(conversationBoundAcpTargetKey) ? commandSessionKey : void 0;
const targets = [...abortTargetKeys, ...sourceAbortKey ? [sourceAbortKey] : []].map((key) => preparedTargets.get(key) ?? prepareTarget(key));
assertCurrent();
sealRootSelection();
try {
for (const target of targets) {
const cleared = target.clearQueues();
if (cleared.followupCleared > 0 || cleared.laneCleared > 0) logVerbose(`abort: cleared followups=${cleared.followupCleared} lane=${cleared.laneCleared} keys=${cleared.keys.join(",")}`);
}
for (const target of targets) {
const outcome = target.abort();
if (outcome.retirement) {
outcome.retirement.catch(() => {});
acpCancellations.push(outcome.retirement);
}
activeAbortRejected ||= outcome.active && !outcome.aborted;
aborted = outcome.aborted || aborted;
}
} finally {
const acpManager = getAcpSessionManager();
for (const acpTargetKey of abortTargetKeys) {
const resolution = acpManager.resolveSession({
cfg,
sessionKey: acpTargetKey,
agentId: acpTargetKey === resolvedTargetKey ? agentId : void 0
});
if (resolution.kind === "none") continue;
acpCancellations.push(acpManager.cancelSession({
cfg,
sessionKey: resolution.sessionKey,
agentId: resolution.agentId,
reason: "fast-abort"
}).catch((error) => {
logVerbose(`abort: ACP cancel failed for ${acpTargetKey}: ${formatErrorMessage(error)}`);
}));
}
}
return true;
}
});
aborted ||= execAborted === true;
const rejectionReason = activeAbortRejected && !aborted ? "finalizing" : void 0;
if (!rejectionReason) {
let persistedAbortTarget = null;
try {
persistedAbortTarget = await markSessionAbortTarget({
isCurrent: params.isCommandTargetCurrent,
expectedTarget: resolvedAbortTarget?.entry ?? null,
scope: {
agentId,
sessionKey: targetKey,
storePath
},
resolveAbortCutoff: abortCutoffForTarget
});
} catch (error) {
logVerbose(`abort: failed to persist abort metadata for ${targetKey}: ${formatErrorMessage(error)}`);
}
if (persistedAbortTarget?.persisted === false) logVerbose(`abort: failed to persist abort metadata for ${targetKey}: ${persistedAbortTarget.persistenceError ?? "unknown error"}`);
}
return {
handled: true,
aborted,
...rejectionReason ? { rejectionReason } : {},
stoppedSubagents: stopped,
failedSubagents: failed
};
} finally {
await Promise.all(acpCancellations);
}
}
if (abortKey) setAbortMemory(abortKey, true);
const { stopped, failed, execAborted } = await stopSubagentsForRequester({
cfg,
requesterSessionKey
});
return {
handled: true,
aborted: execAborted === true,
stoppedSubagents: stopped,
failedSubagents: failed
};
}
//#endregion
export { prepareSessionRunTargetAbort as n, stopSubagentsForRequester as r, executeFastAbortRequest as t };