openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
300 lines (299 loc) • 14.1 kB
JavaScript
import { g as readStringValue, l as normalizeOptionalString } from "./string-coerce-CIXf7egm.js";
import { n as normalizeAgentId } from "./agent-id-CeT3w4ap.js";
import { O as parseAgentSessionKey } from "./session-key-BnWWjqNc.js";
import { t as ErrorCodes } from "./gateway-error-details-w0nAGBBp.js";
import { Lr as validateSessionsAbortParams } from "./src-BiL5aQto.js";
import { d as errorShape } from "./error-codes-Bo8q2D1o.js";
import { a as resolveStoredSessionKeyForAgentStore, i as resolveSessionStoreKey, n as resolveSessionStoreAgentId, o as resolveStoredSessionOwnerAgentId } from "./session-store-key-8xEjWSNi.js";
import { l as resolveExistingAgentSessionStoreTargetsSync, t as isConfiguredSessionStoreAgentId } from "./targets-Cknmo7YZ.js";
import { C as resolveActiveEmbeddedRunOwnerByRunId, n as abortEmbeddedAgentRun } from "./runs-Cb42qain.js";
import "./sessions-9nxpeTwt.js";
import { i as tryResolveSessionCompatibilityOwnerAgentId, n as resolveRequestedSessionAgentId } from "./session-request-agent-CCRSEGCB.js";
import { r as loadGatewaySessionEntry } from "./session-utils-store-CInT2loy.js";
import "./session-utils-Cai0_C6U.js";
import { t as clearSessionQueues } from "./cleanup-DKkilV3a.js";
import { r as resolveChatRunOwnerAgentId } from "./chat-run-owner-DPtcuc7L.js";
import { t as assertValidParams } from "./validation-pzrlzFvo.js";
import { a as descendantAbortError, f as resolveChatAbortRequester, n as abortControlledSubagents, r as abortQueuedCollectorSession } from "./chat-abort-runtime-CKI3fkKr.js";
import { n as setGatewayDedupeEntry } from "./chat-abort-ops-zvMvu0-3.js";
import { n as emitSessionsChanged } from "./session-change-event-DzmH4zlz.js";
import { t as asWorkerInferenceControl } from "./inference-control-CDvM08Nt.js";
import { n as resolveSessionKeyForRun } from "./server-session-key-CesREwK4.js";
import { s as requireSessionKey } from "./sessions-shared-D_lV07q2.js";
import { n as handleChatAbortRequestWithLifecycle } from "./chat-abort-handler-Cs4t_nYG.js";
import { t as resolveWorkerSessionTarget } from "./session-target-BDNR3YFZ.js";
//#region src/gateway/server-methods/sessions-abort.ts
function resolveAbortSessionKey(params) {
if (params.activeRunSessionKey) return params.activeRunSessionKey;
const candidates = [
params.canonicalKey,
params.requestedKey,
...params.aliasKeys ?? []
];
for (const active of params.context.chatAbortControllers.values()) {
if (active.controlUiVisible === false) continue;
for (const candidate of candidates) if (active.sessionKey === candidate) {
const owner = resolveChatRunOwnerAgentId({
agentId: active.agentId,
sessionKey: active.sessionKey,
defaultAgentId: params.defaultAgentId
});
if (!params.agentId || owner === normalizeAgentId(params.agentId)) return candidate;
}
}
return params.requestedKey;
}
function resolveSessionKeyAgentId(sessionKey, cfg) {
const key = normalizeOptionalString(sessionKey);
if (!key) return;
if (!parseAgentSessionKey(key) && key.toLowerCase().startsWith("agent:")) return;
return parseAgentSessionKey(key)?.agentId ?? tryResolveSessionCompatibilityOwnerAgentId(cfg, key);
}
function sessionKeyBelongsToAgent(sessionKey, agentId, cfg) {
return resolveSessionKeyAgentId(sessionKey, cfg) === normalizeAgentId(agentId);
}
function resolveScopedAbortKey(params) {
const key = normalizeOptionalString(params.key);
if (!key) return;
const requestedAgentId = normalizeOptionalString(params.agentId);
if (!requestedAgentId) return key;
const scopedAgentId = normalizeAgentId(requestedAgentId);
const ownerAgentId = resolveStoredSessionOwnerAgentId({
cfg: params.cfg,
agentId: scopedAgentId,
sessionKey: key
});
if (ownerAgentId && ownerAgentId !== scopedAgentId) return;
return resolveStoredSessionKeyForAgentStore({
cfg: params.cfg,
agentId: scopedAgentId,
sessionKey: key
});
}
const sessionAbortHandlers = { "sessions.abort": async ({ req, params, respond, context, client, isWebchatConnect, sessionMutationAuthorization }) => {
if (!assertValidParams(params, validateSessionsAbortParams, "sessions.abort", respond)) return;
const p = params;
const cfg = context.getRuntimeConfig();
const requestedRunId = readStringValue(p.runId);
const requestedKey = normalizeOptionalString(p.key);
const requestedParamAgentId = normalizeOptionalString(p.agentId);
const clearQueued = p.clearQueued === true;
const workerRunSessionId = requestedRunId ? asWorkerInferenceControl(context.workerEnvironmentService)?.resolveInferenceSessionForRunId(requestedRunId) : void 0;
const workerRunTarget = workerRunSessionId ? resolveWorkerSessionTarget(cfg, workerRunSessionId) : void 0;
const embeddedRun = requestedRunId ? resolveActiveEmbeddedRunOwnerByRunId(requestedRunId) : void 0;
const embeddedRunSessionKey = embeddedRun?.sessionKey;
const scopedRequestedKey = resolveScopedAbortKey({
cfg,
key: requestedKey,
agentId: requestedParamAgentId
});
if (requestedKey && requestedParamAgentId && !scopedRequestedKey) {
respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "session key agent does not match agentId"));
return;
}
const requestedKeyAgentId = scopedRequestedKey ? resolveSessionKeyAgentId(scopedRequestedKey, cfg) : void 0;
const activeRun = requestedRunId ? context.chatAbortControllers.get(requestedRunId) : void 0;
const activeRunSessionKey = activeRun?.sessionKey;
const activeRunAgentId = normalizeOptionalString(activeRun?.agentId);
let inferredRunAgentId = requestedParamAgentId ?? activeRunAgentId ?? requestedKeyAgentId ?? workerRunTarget?.agentId ?? resolveSessionKeyAgentId(activeRunSessionKey, cfg) ?? resolveSessionKeyAgentId(embeddedRunSessionKey, cfg);
if (requestedRunId && !inferredRunAgentId) {
const runOwner = resolveRequestedSessionAgentId(cfg, scopedRequestedKey ?? activeRunSessionKey ?? workerRunTarget?.sessionKey ?? "main");
if (!runOwner.ok) {
respond(false, void 0, runOwner.error);
return;
}
inferredRunAgentId = runOwner.agentId;
}
const requestedRunAgentId = requestedRunId ? inferredRunAgentId ? normalizeAgentId(inferredRunAgentId) : void 0 : void 0;
const scopedActiveRunSessionKey = activeRunSessionKey ? requestedRunAgentId ? sessionKeyBelongsToAgent(activeRunSessionKey, requestedRunAgentId, cfg) ? activeRunSessionKey : void 0 : activeRunSessionKey : void 0;
const keyCandidate = scopedRequestedKey ?? scopedActiveRunSessionKey ?? (requestedRunId ? resolveSessionKeyForRun(requestedRunId, requestedRunAgentId ? { agentId: requestedRunAgentId } : void 0) : void 0) ?? workerRunTarget?.sessionKey ?? embeddedRunSessionKey;
if (!keyCandidate && requestedRunId) {
respond(true, {
ok: true,
abortedRunId: null,
status: "no-active-run"
});
return;
}
const key = requireSessionKey(keyCandidate, respond);
if (!key) return;
const requestedGlobalAgent = resolveRequestedSessionAgentId(cfg, key, requestedParamAgentId ?? requestedRunAgentId);
if (!requestedGlobalAgent.ok) {
respond(false, void 0, requestedGlobalAgent.error);
return;
}
const requestedGlobalAgentId = requestedGlobalAgent.agentId;
const targetAgentId = requestedGlobalAgentId ?? resolveSessionStoreAgentId(cfg, resolveSessionStoreKey({
cfg,
sessionKey: key
}));
const configuredTarget = isConfiguredSessionStoreAgentId(cfg, targetAgentId);
const existingTargets = configuredTarget ? [] : resolveExistingAgentSessionStoreTargetsSync(cfg, targetAgentId);
const stableTargetOwner = tryResolveSessionCompatibilityOwnerAgentId(cfg, key);
const hasExactActiveRun = requestedRunId ? scopedActiveRunSessionKey === key && resolveChatRunOwnerAgentId({
agentId: activeRunAgentId,
sessionKey: activeRunSessionKey,
defaultAgentId: stableTargetOwner
}) === normalizeAgentId(targetAgentId) || embeddedRun !== void 0 && resolveSessionKeyAgentId(embeddedRunSessionKey, cfg) === normalizeAgentId(targetAgentId) : [...context.chatAbortControllers.values()].some((entry) => entry.controlUiVisible !== false && entry.sessionKey === key && resolveChatRunOwnerAgentId({
agentId: entry.agentId,
sessionKey: entry.sessionKey,
defaultAgentId: stableTargetOwner
}) === normalizeAgentId(targetAgentId));
if (!configuredTarget && existingTargets.length === 0 && !hasExactActiveRun) {
respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, `agent "${targetAgentId}" not found`));
return;
}
const loadedSession = configuredTarget || existingTargets.length > 0 ? loadGatewaySessionEntry(key, { agentId: requestedGlobalAgentId }) : void 0;
const canonicalKey = loadedSession?.canonicalKey ?? resolveSessionStoreKey({
cfg,
sessionKey: key,
...requestedGlobalAgentId ? { storeAgentId: requestedGlobalAgentId } : {}
});
const sessionEntry = loadedSession?.entry;
const embeddedRunMatchesSession = Boolean(embeddedRun && resolveSessionKeyAgentId(embeddedRun.sessionKey, cfg) === normalizeAgentId(targetAgentId) && (embeddedRun.sessionKey === key || embeddedRun.sessionKey === canonicalKey || sessionEntry?.sessionId === embeddedRun.sessionId));
if (embeddedRun && !embeddedRunMatchesSession) {
respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "runId does not match session"));
return;
}
const requestedKeyAliases = requestedKey && requestedKey !== key && (!requestedParamAgentId || sessionKeyBelongsToAgent(requestedKey, requestedParamAgentId, cfg)) ? [requestedKey] : void 0;
const resolvedAbortSessionKey = resolveAbortSessionKey({
context,
requestedKey: key,
canonicalKey,
activeRunSessionKey: scopedActiveRunSessionKey,
aliasKeys: requestedKeyAliases,
agentId: requestedGlobalAgentId,
defaultAgentId: stableTargetOwner
});
const abortSessionKey = canonicalKey === "global" && requestedGlobalAgentId ? "global" : resolvedAbortSessionKey;
const abortAgentId = requestedGlobalAgentId ?? activeRunAgentId;
if (embeddedRun && !activeRun) {
let aborted = false;
const descendants = await abortControlledSubagents({
cfg,
sessionKey: embeddedRun.sessionKey ?? canonicalKey,
agentId: targetAgentId,
requesterTurnRunId: embeddedRun.runId,
beforeKill: () => aborted = embeddedRun.abort()
});
const error = descendantAbortError(descendants, "Parent run");
if (error) respond(false, void 0, error);
else respond(true, {
ok: true,
abortedRunId: aborted ? embeddedRun.runId : null,
status: aborted ? "aborted" : "no-active-run"
});
if (aborted) emitSessionsChanged(context, {
sessionKey: canonicalKey,
...abortAgentId ? { agentId: abortAgentId } : {},
reason: "abort"
});
return;
}
const preAbortRunKinds = /* @__PURE__ */ new Map();
if (requestedRunId) preAbortRunKinds.set(requestedRunId, activeRun?.kind);
else for (const [rid, entry] of context.chatAbortControllers) preAbortRunKinds.set(rid, entry.kind);
let abortedRunId = null;
let aborted = false;
let chatAbortSucceeded = false;
let responseMeta;
const persistedSessionId = sessionEntry?.sessionId;
const onAuthorizedAfterQueuedAbort = !requestedRunId && canonicalKey !== "global" && (clearQueued || persistedSessionId) ? () => {
let queueCleared = false;
if (clearQueued) {
const cleared = clearSessionQueues([
key,
...requestedKeyAliases ?? [],
canonicalKey,
...persistedSessionId ? [persistedSessionId] : []
]);
queueCleared = cleared.followupCleared > 0 || cleared.laneCleared > 0;
}
return (persistedSessionId ? abortEmbeddedAgentRun(persistedSessionId) : false) || queueCleared;
} : void 0;
const queuedAbort = abortQueuedCollectorSession({
context,
sessionKey: canonicalKey,
sessionKeyAliases: [key, ...requestedKeyAliases ?? []],
agentId: targetAgentId,
sessionId: persistedSessionId,
session: loadedSession ? {
ok: true,
value: loadedSession
} : void 0,
defaultAgentId: stableTargetOwner,
runId: requestedRunId,
abortOrigin: "rpc",
stopReason: "rpc",
requester: resolveChatAbortRequester(client),
assertCurrent: sessionMutationAuthorization?.assertCurrent,
onAuthorizedAfterQueuedAbort
});
if (queuedAbort) {
const result = await queuedAbort;
if (!result.ok) respond(false, void 0, result.error);
else respond(true, {
ok: true,
abortedRunId: result.value.runIds[0] ?? null,
status: result.value.aborted ? "aborted" : "no-active-run"
}, void 0, void 0);
return;
}
await handleChatAbortRequestWithLifecycle({
req,
params: {
sessionKey: abortSessionKey,
runId: requestedRunId,
...abortAgentId ? { agentId: abortAgentId } : {}
},
respond: (ok, payload, error, meta) => {
if (!ok) {
respond(ok, payload, error, meta);
return;
}
chatAbortSucceeded = true;
responseMeta = meta;
const firstAbortedRunId = (payload && typeof payload === "object" && Array.isArray(payload.runIds) ? payload.runIds.filter((value) => Boolean(normalizeOptionalString(value))) : [])[0] ?? null;
abortedRunId = firstAbortedRunId;
aborted = firstAbortedRunId !== null || payload !== null && typeof payload === "object" && payload.aborted === true;
if (firstAbortedRunId && !Boolean(workerRunSessionId && !activeRun)) {
const endedAt = Date.now();
const dedupePrefix = preAbortRunKinds.get(firstAbortedRunId) === "agent" ? "agent" : "chat";
setGatewayDedupeEntry({
dedupe: context.dedupe,
key: `${dedupePrefix}:${firstAbortedRunId}`,
entry: {
ts: endedAt,
ok: true,
payload: {
status: "timeout",
runId: firstAbortedRunId,
...abortAgentId ? { agentId: abortAgentId } : {},
stopReason: "rpc",
endedAt
}
}
});
}
},
context,
client,
isWebchatConnect
}, {
...onAuthorizedAfterQueuedAbort ? { onAuthorizedAfterQueuedAbort } : {},
...!requestedRunId ? { cascadeDescendants: true } : {}
});
if (!chatAbortSucceeded) return;
respond(true, {
ok: true,
abortedRunId,
status: aborted ? "aborted" : "no-active-run"
}, void 0, responseMeta);
if (aborted) emitSessionsChanged(context, {
sessionKey: canonicalKey,
...abortAgentId ? { agentId: abortAgentId } : {},
reason: "abort"
});
} };
//#endregion
export { sessionAbortHandlers as n, resolveAbortSessionKey as t };