openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
129 lines (128 loc) • 5.19 kB
JavaScript
import { s as normalizeOptionalLowercaseString } from "./string-coerce-mnp54Vah.js";
import { t as formatCliCommand } from "./command-format-CKGmlpAQ.js";
import { v as resolveSessionAgentId } from "./agent-scope-MrLta7Pq.js";
import { n as resolveAgentMainSessionKey, t as canonicalizeMainSessionAlias } from "./main-session-Eahn-btj.js";
import { t as auditSandboxToolPolicyBlock } from "./tool-policy-audit-C2OhYH6P.js";
import { r as resolveSandboxToolPolicyForAgent, t as classifyToolAgainstSandboxToolPolicy } from "./tool-policy-C8sIZN6J.js";
import { i as resolveSandboxConfigForAgent } from "./config-zzXWNRgc.js";
//#region src/agents/sandbox/runtime-status.ts
/**
* Sandbox runtime status and tool-policy diagnostics.
*
* Resolves whether a session is sandboxed and explains policy blocks before tool execution.
*/
function shouldSandboxSession(cfg, sessionKey, mainSessionKey) {
if (cfg.mode === "off") return false;
if (cfg.mode === "all") return true;
return sessionKey.trim() !== mainSessionKey.trim();
}
function resolveMainSessionKeyForSandbox(params) {
if (params.cfg?.session?.scope === "global") return "global";
return resolveAgentMainSessionKey({
cfg: params.cfg,
agentId: params.agentId
});
}
function resolveComparableSessionKeyForSandbox(params) {
return canonicalizeMainSessionAlias({
cfg: params.cfg,
agentId: params.agentId,
sessionKey: params.sessionKey
});
}
/** Resolves sandbox mode, effective session scope, and tool policy for a session. */
function resolveSandboxRuntimeStatus(params) {
const sessionKey = params.sessionKey?.trim() ?? "";
const agentId = resolveSessionAgentId({
sessionKey,
config: params.cfg
});
const cfg = params.cfg;
const sandboxCfg = resolveSandboxConfigForAgent(cfg, agentId);
const mainSessionKey = resolveMainSessionKeyForSandbox({
cfg,
agentId
});
const sandboxed = sessionKey ? shouldSandboxSession(sandboxCfg, resolveComparableSessionKeyForSandbox({
cfg,
agentId,
sessionKey
}), mainSessionKey) : false;
return {
agentId,
sessionKey,
mainSessionKey,
mode: sandboxCfg.mode,
sandboxed,
toolPolicy: resolveSandboxToolPolicyForAgent(cfg, agentId)
};
}
function sanitizeForSingleLineDisplay(value) {
return Array.from(value, (char) => {
if (char === "\n") return "\\n";
if (char === "\r") return "\\r";
if (char === " ") return "\\t";
const codePoint = char.codePointAt(0) ?? 0;
if (codePoint < 32 || codePoint === 127) return `\\x${codePoint.toString(16).padStart(2, "0")}`;
return char;
}).join("");
}
function hasUnsafeControlChars(value) {
return Array.from(value).some((char) => {
const codePoint = char.codePointAt(0) ?? 0;
return codePoint < 32 || codePoint === 127;
});
}
function redactSessionKey(value) {
const trimmed = value.trim();
if (!trimmed) return "(unknown)";
if (trimmed.length <= 12) return "(redacted)";
return `${sanitizeForSingleLineDisplay(trimmed.slice(0, 6))}…${sanitizeForSingleLineDisplay(trimmed.slice(-6))}`;
}
function shellEscapeSingleArg(value) {
return `'${value.replaceAll("'", `'\\''`)}'`;
}
/** Formats the user-facing denial message when sandbox tool policy blocks a tool. */
function formatSandboxToolPolicyBlockedMessage(params) {
const tool = normalizeOptionalLowercaseString(params.toolName);
if (!tool) return;
const runtime = resolveSandboxRuntimeStatus({
cfg: params.cfg,
sessionKey: params.sessionKey
});
if (!runtime.sandboxed) return;
const { blockedByDeny, blockedByAllow } = classifyToolAgainstSandboxToolPolicy(tool, runtime.toolPolicy);
if (!blockedByDeny && !blockedByAllow) return;
const blockingSource = blockedByDeny ? runtime.toolPolicy.sources.deny : runtime.toolPolicy.sources.allow;
if (params.audit === true) auditSandboxToolPolicyBlock({
toolName: tool,
ruleType: blockedByDeny ? "deny" : "allow",
ruleSource: blockingSource.source,
configKey: blockingSource.key,
policy: runtime.toolPolicy,
mode: runtime.mode
});
const reasons = [];
const fixes = [];
if (blockedByDeny) {
reasons.push("deny list");
fixes.push(`Remove "${tool}" from ${runtime.toolPolicy.sources.deny.key}.`);
}
if (blockedByAllow) {
reasons.push("allow list");
fixes.push(`Add "${tool}" to ${runtime.toolPolicy.sources.allow.key} (or set it to [] to allow all).`);
}
const lines = [];
lines.push(`Tool "${tool}" blocked by sandbox tool policy (mode=${runtime.mode}).`);
lines.push(`Session: ${redactSessionKey(runtime.sessionKey)}`);
lines.push(`Reason: ${reasons.join(" + ")}`);
lines.push("Fix:");
lines.push(`- agents.defaults.sandbox.mode=off (disable sandbox)`);
for (const fix of fixes) lines.push(`- ${fix}`);
if (runtime.mode === "non-main") lines.push("- Use the agent main session instead of a non-main session.");
const explainCommand = runtime.sessionKey ? hasUnsafeControlChars(runtime.sessionKey) ? `openclaw sandbox explain --agent ${runtime.agentId}` : `openclaw sandbox explain --session ${shellEscapeSingleArg(runtime.sessionKey)}` : "openclaw sandbox explain";
lines.push(`- See: ${formatCliCommand(explainCommand)}`);
return lines.join("\n");
}
//#endregion
export { resolveSandboxRuntimeStatus as n, formatSandboxToolPolicyBlockedMessage as t };