openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
209 lines (208 loc) • 7.74 kB
JavaScript
import "./src-vebZIeLe.js";
import { t as expectDefined } from "./expect-CyE8FADM.js";
import { l as normalizeOptionalString } from "./string-coerce-CIXf7egm.js";
import { O as parseAgentSessionKey } from "./session-key-BnWWjqNc.js";
import { t as ErrorCodes } from "./gateway-error-details-w0nAGBBp.js";
import { Li as validateSessionsSendParams } from "./src-BiL5aQto.js";
import { d as errorShape } from "./error-codes-Bo8q2D1o.js";
import "./sessions-9nxpeTwt.js";
import { f as resolveSessionWorkStartError } from "./lifecycle-BaroCBMc.js";
import { g as terminateAcceptedCollectorRun } from "./subagent-announce-output-Cy2Rx3_K.js";
import { n as resolveRequestedSessionAgentId } from "./session-request-agent-CCRSEGCB.js";
import { i as loadGatewaySessionEntryReadOnly, l as resolveDeletedAgentIdFromSessionKey, r as loadGatewaySessionEntry } from "./session-utils-store-CInT2loy.js";
import "./session-utils-Cai0_C6U.js";
import { n as handleDirectExternalChatSend, t as chatHandlers } from "./chat-IsrqkYID.js";
import { t as assertValidParams } from "./validation-pzrlzFvo.js";
import { n as emitSessionsChanged } from "./session-change-event-DzmH4zlz.js";
import { t as reactivateCompletedSubagentSession } from "./session-subagent-reactivation-D4NwQBzD.js";
import { n as isAgentMainSessionKey, s as requireSessionKey } from "./sessions-shared-D_lV07q2.js";
import { n as isFreshChatSendStarted, t as sessionCreateHandlers } from "./sessions-create-BSGvT-wJ.js";
import { randomUUID } from "node:crypto";
//#region src/gateway/server-methods/sessions-messaging.ts
async function createAgentMainSessionForSend(params) {
const agentId = parseAgentSessionKey(params.canonicalKey)?.agentId;
if (!agentId) return {
ok: false,
error: errorShape(ErrorCodes.INVALID_REQUEST, `session not found: ${params.canonicalKey}`)
};
let createResult;
await expectDefined(sessionCreateHandlers["sessions.create"], "sessions.create handler")({
req: params.req,
params: {
key: params.canonicalKey,
agentId
},
respond: (ok, payload, error) => {
createResult = {
ok,
payload: payload && typeof payload === "object" ? payload : void 0,
error
};
},
context: params.context,
client: params.client,
isWebchatConnect: params.isWebchatConnect
});
if (!createResult) return {
ok: false,
error: errorShape(ErrorCodes.UNAVAILABLE, "sessions.create did not respond")
};
if (!createResult.ok) return {
ok: false,
error: createResult.error ?? errorShape(ErrorCodes.UNAVAILABLE, "failed to create session")
};
const createdKey = normalizeOptionalString(createResult.payload?.key) ?? params.canonicalKey;
const loaded = loadGatewaySessionEntryReadOnly(createdKey, { agentId });
if (!loaded.entry?.sessionId) return {
ok: false,
error: errorShape(ErrorCodes.UNAVAILABLE, `session not created: ${createdKey}`)
};
return {
ok: true,
entry: loaded.entry,
canonicalKey: loaded.canonicalKey
};
}
async function handleSessionSend(params) {
if (!assertValidParams(params.params, validateSessionsSendParams, params.method, params.respond)) return;
const p = params.params;
const key = requireSessionKey(p.key, params.respond);
if (!key) return;
const cfg = params.context.getRuntimeConfig();
const requestedAgent = resolveRequestedSessionAgentId(cfg, key, p.agentId);
if (!requestedAgent.ok) {
params.respond(false, void 0, requestedAgent.error);
return;
}
const requestedAgentId = requestedAgent.agentId;
const loaded = loadGatewaySessionEntry(key, { agentId: requestedAgentId });
const { legacyKey } = loaded;
let { entry, canonicalKey } = loaded;
const deletedAgentId = resolveDeletedAgentIdFromSessionKey(cfg, canonicalKey, entry, { acpMetadataSessionKey: legacyKey ?? canonicalKey });
if (deletedAgentId !== null) {
params.respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, `Agent "${deletedAgentId}" no longer exists in configuration`));
return;
}
const rawIdempotencyKey = p.idempotencyKey;
const explicitIdempotencyKey = typeof rawIdempotencyKey === "string" && rawIdempotencyKey.trim() ? rawIdempotencyKey.trim() : void 0;
const idempotencyKey = explicitIdempotencyKey ?? randomUUID();
const respond = params.respond;
const dispatchChatSend = async (dispatchRespond) => {
const options = {
req: params.req,
params: {
sessionKey: canonicalKey,
...requestedAgentId ? { agentId: requestedAgentId } : {},
message: p.message,
...p.mentions ? { mentions: p.mentions } : {},
thinking: p.thinking,
attachments: p.attachments,
timeoutMs: p.timeoutMs,
idempotencyKey,
...params.queueMode ? { queueMode: params.queueMode } : {}
},
respond: dispatchRespond,
context: params.context,
client: params.client,
isWebchatConnect: params.isWebchatConnect
};
if (params.queueMode === "interrupt") {
await handleDirectExternalChatSend(options);
return;
}
await expectDefined(chatHandlers["chat.send"], "chat.send handler")(options);
};
const archivedSessionError = resolveSessionWorkStartError(canonicalKey, entry, { allowPendingWorkspace: true });
if (archivedSessionError) {
if (explicitIdempotencyKey) {
await dispatchChatSend(respond);
return;
}
respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, archivedSessionError));
return;
}
if (!entry?.sessionId && params.queueMode !== "interrupt" && isAgentMainSessionKey(cfg, canonicalKey)) {
const created = await createAgentMainSessionForSend({
req: params.req,
canonicalKey,
context: params.context,
client: params.client,
isWebchatConnect: params.isWebchatConnect
});
if (!created.ok) {
respond(false, void 0, created.error);
return;
}
entry = created.entry;
canonicalKey = created.canonicalKey;
}
if (!entry?.sessionId) {
respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, `session not found: ${key}`));
return;
}
let sendAcked = false;
let sendPayload;
let sendCached = false;
let startedRunId;
let interruptedActiveRun = false;
await dispatchChatSend((ok, payload, error, meta) => {
sendAcked = ok;
sendPayload = payload;
sendCached = meta?.cached === true;
startedRunId = payload && typeof payload === "object" && typeof payload.runId === "string" ? payload.runId : void 0;
interruptedActiveRun = ok && payload !== null && typeof payload === "object" && "interruptedActiveRun" in payload && payload.interruptedActiveRun === true;
respond(ok, payload, error, meta);
});
if (sendAcked) {
if (isFreshChatSendStarted({
payload: sendPayload,
cached: sendCached
})) try {
await reactivateCompletedSubagentSession({
sessionKey: canonicalKey,
runId: startedRunId,
task: p.message,
gatewayContextResolver: params.context.resolveGatewayContext
});
} catch (error) {
if (startedRunId) await terminateAcceptedCollectorRun({
childSessionKey: canonicalKey,
gatewayRunId: startedRunId,
sessionCleanup: "preserve"
});
throw error;
}
emitSessionsChanged(params.context, {
sessionKey: canonicalKey,
...requestedAgentId ? { agentId: requestedAgentId } : {},
reason: interruptedActiveRun ? "steer" : "send"
});
}
}
const sessionMessagingHandlers = {
"sessions.send": async ({ req, params, respond, context, client, isWebchatConnect }) => {
await handleSessionSend({
method: "sessions.send",
req,
params,
respond,
context,
client,
isWebchatConnect
});
},
"sessions.steer": async ({ req, params, respond, context, client, isWebchatConnect }) => {
await handleSessionSend({
method: "sessions.steer",
req,
params,
respond,
context,
client,
isWebchatConnect,
queueMode: "interrupt"
});
}
};
//#endregion
export { sessionMessagingHandlers };