openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
214 lines (213 loc) • 9.4 kB
JavaScript
import { t as createLazyImportLoader } from "./lazy-promise-DGqyc4Y4.js";
import { u as resolveAgentDir } from "./agent-scope-config-DcbEhP0R.js";
import { S as isAcpSessionKey } from "./session-key-BnWWjqNc.js";
import { _ as resolveSessionAgentId } from "./agent-scope-DbtJyKUL.js";
import { r as logVerbose } from "./globals-CTaGxEqj.js";
import { a as isInternalMessageChannel } from "./message-channel-BQrhwUEA.js";
import { n as isResetAuthorizedForContext } from "./command-auth-DRYzLgCh.js";
import { i as copyReplyPayloadMetadata } from "./reply-payload-DahKk-7n.js";
import { xt as updateSessionEntry } from "./session-accessor-YsytfDtG.js";
import { t as clearAllCliSessions } from "./cli-session-binding-Aa6nlDa8.js";
import { t as clearBootstrapSnapshot } from "./bootstrap-cache-Bpsy6pH_.js";
import "./cli-session-pAa_-y_N.js";
import { n as shouldHandleTextCommands } from "./commands-text-routing-sBs1BOcS.js";
import "./commands-registry-zRoXYk7P.js";
import { t as parseSoftResetCommand } from "./commands-reset-mode-CPsoHzU1.js";
import { t as applyCommandTextToContext } from "./command-context-rewrite-DyA5NUca.js";
import { n as commandReply } from "./command-gates-B4tlStPI.js";
import "./commands-context-CzCiQCus.js";
import { t as emitResetCommandHooks } from "./commands-reset-hooks-Dqv5kTUZ.js";
import { n as resetConfiguredBindingTargetInPlace } from "./binding-targets-C2dEPPXN.js";
import { n as resolveBoundAcpThreadSessionKey } from "./targets-CwA8rh58.js";
import { n as buildStatusReply } from "./commands-status-B9u_tnV2.js";
//#region src/auto-reply/reply/commands-reset.ts
/** Handles /new and /reset command flows, including soft reset and ACP-bound sessions. */
function applyAcpResetTailContext(ctx, resetTail) {
applyCommandTextToContext(ctx, resetTail);
ctx.AcpDispatchTailAfterReset = true;
}
function isResetAuthorized(params) {
return isResetAuthorizedForContext({
ctx: params.ctx,
cfg: params.cfg,
commandAuthorized: params.command.isAuthorizedSender || params.ctx.CommandAuthorized === true
});
}
/** Handles reset/new commands or returns null when another command handler should continue. */
async function maybeHandleResetCommand(params) {
const resetMatch = params.command.commandBodyNormalized.match(/^\/(new|reset)(?:\s|$)/i);
if (!resetMatch) return null;
if (!isResetAuthorized(params)) {
logVerbose(`Ignoring /${resetMatch[1]} from unauthorized sender: ${params.command.senderId || "<unknown>"}`);
return isInternalMessageChannel(params.ctx.Provider || params.ctx.Surface) && isInternalMessageChannel(params.command.channel) ? commandReply("⚠️ You are not authorized to reset this session. Gateway resets require operator.admin and command access. Ask your administrator to reset it, or send your message without the command.") : { shouldContinue: false };
}
const softReset = parseSoftResetCommand(params.command.commandBodyNormalized);
if (softReset.matched) {
const boundAcpSessionKey = resolveBoundAcpThreadSessionKey(params);
if (boundAcpSessionKey && isAcpSessionKey(boundAcpSessionKey) ? boundAcpSessionKey.trim() : void 0) return {
shouldContinue: false,
reply: { text: "Usage: /reset soft is not available for ACP-bound sessions yet." }
};
const targetSessionEntry = params.sessionStore?.[params.sessionKey] ?? params.sessionEntry;
const previousSessionEntry = params.previousSessionEntry ?? (targetSessionEntry ? { ...targetSessionEntry } : void 0);
if (targetSessionEntry) {
const now = Date.now();
clearAllCliSessions(targetSessionEntry);
if (params.sessionEntry && params.sessionEntry !== targetSessionEntry) {
clearAllCliSessions(params.sessionEntry);
params.sessionEntry.updatedAt = now;
params.sessionEntry.lastInteractionAt = now;
}
if (params.sessionKey) clearBootstrapSnapshot(params.sessionKey);
targetSessionEntry.updatedAt = now;
targetSessionEntry.lastInteractionAt = now;
if (params.sessionStore && params.sessionKey) params.sessionStore[params.sessionKey] = targetSessionEntry;
if (params.storePath && params.sessionKey) await updateSessionEntry({
storePath: params.storePath,
sessionKey: params.sessionKey
}, async (entry) => {
const next = { ...entry };
clearAllCliSessions(next);
return {
cliSessionBindings: next.cliSessionBindings,
cliSessionIds: next.cliSessionIds,
claudeCliSessionId: next.claudeCliSessionId,
updatedAt: now,
lastInteractionAt: now
};
}, { consumePendingReset: true });
}
await emitResetCommandHooks({
action: "reset",
agentId: params.agentId,
ctx: params.ctx,
cfg: params.cfg,
command: params.command,
sessionKey: params.sessionKey,
storePath: params.storePath,
sessionEntry: targetSessionEntry,
previousSessionEntry,
previousSessionMemory: params.previousSessionMemory,
previousSessionResetMessages: params.previousSessionResetMessages,
onObservedReplyDelivery: params.opts?.onObservedReplyDelivery,
workspaceDir: params.workspaceDir
});
params.command.softResetTriggered = true;
params.command.softResetTail = softReset.tail;
return null;
}
const commandAction = resetMatch[1]?.toLowerCase() === "reset" ? "reset" : "new";
const resetTail = params.command.commandBodyNormalized.slice(resetMatch[0].length).trimStart();
const boundAcpSessionKey = resolveBoundAcpThreadSessionKey(params);
const boundAcpKey = boundAcpSessionKey && isAcpSessionKey(boundAcpSessionKey) ? boundAcpSessionKey.trim() : void 0;
if (boundAcpKey) {
const resetResult = await resetConfiguredBindingTargetInPlace({
cfg: params.cfg,
sessionKey: boundAcpKey,
reason: commandAction,
commandSource: `${params.command.surface}:${params.ctx.CommandSource ?? "text"}`
});
if (!resetResult.ok) logVerbose(`acp reset failed for ${boundAcpKey}: ${resetResult.error ?? "unknown error"}`);
if (resetResult.ok) {
if (resetResult.sessionId) params.opts?.onSessionPrepared?.({
sessionKey: resetResult.sessionKey ?? boundAcpKey,
sessionId: resetResult.sessionId,
storePath: resetResult.storePath
});
params.command.resetHookTriggered = true;
if (resetTail) {
applyAcpResetTailContext(params.ctx, resetTail);
if (params.rootCtx && params.rootCtx !== params.ctx) applyAcpResetTailContext(params.rootCtx, resetTail);
return { shouldContinue: false };
}
return {
shouldContinue: false,
reply: {
text: "✅ ACP session reset in place.",
isStatusNotice: true
}
};
}
return {
shouldContinue: false,
reply: {
text: "⚠️ ACP session reset failed. Check /acp status and try again.",
isStatusNotice: true
}
};
}
const targetSessionEntry = params.sessionStore?.[params.sessionKey] ?? params.sessionEntry;
const hookResult = await emitResetCommandHooks({
action: commandAction,
agentId: params.agentId,
ctx: params.ctx,
cfg: params.cfg,
command: params.command,
sessionKey: params.sessionKey,
storePath: params.storePath,
sessionEntry: targetSessionEntry,
previousSessionEntry: params.previousSessionEntry,
previousSessionMemory: params.previousSessionMemory,
previousSessionResetMessages: params.previousSessionResetMessages,
onObservedReplyDelivery: params.opts?.onObservedReplyDelivery,
workspaceDir: params.workspaceDir
});
if (!resetTail) return {
shouldContinue: false,
...hookResult.routedReply ? {} : { reply: {
text: commandAction === "reset" ? "✅ Session reset." : "✅ New session started.",
isStatusNotice: true
} }
};
return null;
}
//#endregion
//#region src/auto-reply/reply/commands-core.ts
const commandHandlersRuntimeLoader = createLazyImportLoader(() => import("./commands-handlers.runtime.js"));
function loadCommandHandlersRuntime() {
return commandHandlersRuntimeLoader.load();
}
let HANDLERS = null;
function normalizeCommandHandlerResult(result) {
if (!result.reply) return result;
return {
...result,
reply: copyReplyPayloadMetadata(result.reply, {
...result.reply,
replyToId: void 0,
replyToCurrent: false
})
};
}
async function handleCommands(params) {
if (params.ctx.CommandInterpretationSuppressed === true) return { shouldContinue: true };
if (HANDLERS === null) HANDLERS = (await loadCommandHandlersRuntime()).loadCommandHandlers();
const allowCreateSessionEntry = params.allowCreateSessionEntry === true;
const initialSessionEntry = params.initialSessionEntry ?? (allowCreateSessionEntry ? void 0 : params.sessionEntry ? { ...params.sessionEntry } : void 0);
const agentId = resolveSessionAgentId({
sessionKey: params.sessionKey,
config: params.cfg,
fallbackAgentId: params.agentId
});
const commandParams = {
...params,
agentId,
agentDir: agentId === params.agentId ? params.agentDir : resolveAgentDir(params.cfg, agentId),
initialSessionEntry,
allowCreateSessionEntry
};
const resetResult = await maybeHandleResetCommand(commandParams);
if (resetResult) return normalizeCommandHandlerResult(resetResult);
const allowTextCommands = shouldHandleTextCommands({
cfg: params.cfg,
surface: params.command.surface,
commandSource: params.ctx.CommandSource
});
for (const handler of HANDLERS) {
const result = await handler(commandParams, allowTextCommands);
if (result) return normalizeCommandHandlerResult(result);
}
return { shouldContinue: true };
}
//#endregion
export { buildStatusReply, handleCommands };