Files
openclaw/src/infra/system-run-approval-context.ts
2026-03-11 01:25:31 +00:00

129 lines
3.9 KiB
TypeScript

import type { SystemRunApprovalPlan } from "./exec-approvals.js";
import { normalizeSystemRunApprovalPlan } from "./system-run-approval-binding.js";
import { formatExecCommand, resolveSystemRunCommand } from "./system-run-command.js";
import { normalizeNonEmptyString, normalizeStringArray } from "./system-run-normalize.js";
type PreparedRunPayload = {
cmdText: string;
plan: SystemRunApprovalPlan;
};
type SystemRunApprovalRequestContext = {
plan: SystemRunApprovalPlan | null;
commandArgv: string[] | undefined;
commandText: string;
commandPreview: string | null;
cwd: string | null;
agentId: string | null;
sessionKey: string | null;
};
type SystemRunApprovalRuntimeContext =
| {
ok: true;
plan: SystemRunApprovalPlan | null;
argv: string[];
cwd: string | null;
agentId: string | null;
sessionKey: string | null;
rawCommand: string | null;
}
| {
ok: false;
message: string;
details?: Record<string, unknown>;
};
function normalizeCommandText(value: unknown): string {
return typeof value === "string" ? value : "";
}
function normalizeCommandPreview(
value: string | null | undefined,
authoritative: string,
): string | null {
const preview = normalizeNonEmptyString(value);
if (!preview || preview === authoritative) {
return null;
}
return preview;
}
export function parsePreparedSystemRunPayload(payload: unknown): PreparedRunPayload | null {
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
return null;
}
const raw = payload as { cmdText?: unknown; plan?: unknown };
const cmdText = normalizeNonEmptyString(raw.cmdText);
const plan = normalizeSystemRunApprovalPlan(raw.plan);
if (!cmdText || !plan) {
return null;
}
return { cmdText, plan };
}
export function resolveSystemRunApprovalRequestContext(params: {
host?: unknown;
command?: unknown;
commandArgv?: unknown;
systemRunPlan?: unknown;
cwd?: unknown;
agentId?: unknown;
sessionKey?: unknown;
}): SystemRunApprovalRequestContext {
const host = normalizeNonEmptyString(params.host) ?? "";
const plan = host === "node" ? normalizeSystemRunApprovalPlan(params.systemRunPlan) : null;
const fallbackArgv = normalizeStringArray(params.commandArgv);
const fallbackCommand = normalizeCommandText(params.command);
const commandText = plan ? (plan.rawCommand ?? formatExecCommand(plan.argv)) : fallbackCommand;
return {
plan,
commandArgv: plan?.argv ?? (fallbackArgv.length > 0 ? fallbackArgv : undefined),
commandText,
commandPreview: plan
? normalizeCommandPreview(plan.commandPreview ?? fallbackCommand, commandText)
: null,
cwd: plan?.cwd ?? normalizeNonEmptyString(params.cwd),
agentId: plan?.agentId ?? normalizeNonEmptyString(params.agentId),
sessionKey: plan?.sessionKey ?? normalizeNonEmptyString(params.sessionKey),
};
}
export function resolveSystemRunApprovalRuntimeContext(params: {
plan?: unknown;
command?: unknown;
rawCommand?: unknown;
cwd?: unknown;
agentId?: unknown;
sessionKey?: unknown;
}): SystemRunApprovalRuntimeContext {
const normalizedPlan = normalizeSystemRunApprovalPlan(params.plan ?? null);
if (normalizedPlan) {
return {
ok: true,
plan: normalizedPlan,
argv: [...normalizedPlan.argv],
cwd: normalizedPlan.cwd,
agentId: normalizedPlan.agentId,
sessionKey: normalizedPlan.sessionKey,
rawCommand: normalizedPlan.rawCommand,
};
}
const command = resolveSystemRunCommand({
command: params.command,
rawCommand: params.rawCommand,
});
if (!command.ok) {
return { ok: false, message: command.message, details: command.details };
}
return {
ok: true,
plan: null,
argv: command.argv,
cwd: normalizeNonEmptyString(params.cwd),
agentId: normalizeNonEmptyString(params.agentId),
sessionKey: normalizeNonEmptyString(params.sessionKey),
rawCommand: normalizeNonEmptyString(params.rawCommand),
};
}