mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
refactor(cli): share exec approvals save flow
This commit is contained in:
@@ -89,6 +89,51 @@ async function loadSnapshotTarget(opts: ExecApprovalsCliOpts): Promise<{
|
||||
return { snapshot, nodeId, source: nodeId ? "node" : "gateway" };
|
||||
}
|
||||
|
||||
function exitWithError(message: string): never {
|
||||
defaultRuntime.error(message);
|
||||
defaultRuntime.exit(1);
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
async function loadWritableSnapshotTarget(opts: ExecApprovalsCliOpts): Promise<{
|
||||
snapshot: ExecApprovalsSnapshot;
|
||||
nodeId: string | null;
|
||||
source: "gateway" | "node" | "local";
|
||||
targetLabel: string;
|
||||
baseHash: string;
|
||||
}> {
|
||||
const { snapshot, nodeId, source } = await loadSnapshotTarget(opts);
|
||||
if (source === "local") {
|
||||
defaultRuntime.log(theme.muted("Writing local approvals."));
|
||||
}
|
||||
const targetLabel = source === "local" ? "local" : nodeId ? `node:${nodeId}` : "gateway";
|
||||
const baseHash = snapshot.hash;
|
||||
if (!baseHash) {
|
||||
exitWithError("Exec approvals hash missing; reload and retry.");
|
||||
}
|
||||
return { snapshot, nodeId, source, targetLabel, baseHash };
|
||||
}
|
||||
|
||||
async function saveSnapshotTargeted(params: {
|
||||
opts: ExecApprovalsCliOpts;
|
||||
source: "gateway" | "node" | "local";
|
||||
nodeId: string | null;
|
||||
file: ExecApprovalsFile;
|
||||
baseHash: string;
|
||||
targetLabel: string;
|
||||
}): Promise<void> {
|
||||
const next =
|
||||
params.source === "local"
|
||||
? saveSnapshotLocal(params.file)
|
||||
: await saveSnapshot(params.opts, params.nodeId, params.file, params.baseHash);
|
||||
if (params.opts.json) {
|
||||
defaultRuntime.log(JSON.stringify(next));
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(theme.muted(`Target: ${params.targetLabel}`));
|
||||
renderApprovalsSnapshot(next, params.targetLabel);
|
||||
}
|
||||
|
||||
function formatCliError(err: unknown): string {
|
||||
const msg = describeUnknownError(err);
|
||||
return msg.includes("\n") ? msg.split("\n")[0] : msg;
|
||||
@@ -268,45 +313,21 @@ export function registerExecApprovalsCli(program: Command) {
|
||||
.action(async (opts: ExecApprovalsCliOpts) => {
|
||||
try {
|
||||
if (!opts.file && !opts.stdin) {
|
||||
defaultRuntime.error("Provide --file or --stdin.");
|
||||
defaultRuntime.exit(1);
|
||||
return;
|
||||
exitWithError("Provide --file or --stdin.");
|
||||
}
|
||||
if (opts.file && opts.stdin) {
|
||||
defaultRuntime.error("Use either --file or --stdin (not both).");
|
||||
defaultRuntime.exit(1);
|
||||
return;
|
||||
}
|
||||
const { snapshot, nodeId, source } = await loadSnapshotTarget(opts);
|
||||
if (source === "local") {
|
||||
defaultRuntime.log(theme.muted("Writing local approvals."));
|
||||
}
|
||||
const targetLabel = source === "local" ? "local" : nodeId ? `node:${nodeId}` : "gateway";
|
||||
if (!snapshot.hash) {
|
||||
defaultRuntime.error("Exec approvals hash missing; reload and retry.");
|
||||
defaultRuntime.exit(1);
|
||||
return;
|
||||
exitWithError("Use either --file or --stdin (not both).");
|
||||
}
|
||||
const { source, nodeId, targetLabel, baseHash } = await loadWritableSnapshotTarget(opts);
|
||||
const raw = opts.stdin ? await readStdin() : await fs.readFile(String(opts.file), "utf8");
|
||||
let file: ExecApprovalsFile;
|
||||
try {
|
||||
file = JSON5.parse(raw);
|
||||
} catch (err) {
|
||||
defaultRuntime.error(`Failed to parse approvals JSON: ${String(err)}`);
|
||||
defaultRuntime.exit(1);
|
||||
return;
|
||||
exitWithError(`Failed to parse approvals JSON: ${String(err)}`);
|
||||
}
|
||||
file.version = 1;
|
||||
const next =
|
||||
source === "local"
|
||||
? saveSnapshotLocal(file)
|
||||
: await saveSnapshot(opts, nodeId, file, snapshot.hash);
|
||||
if (opts.json) {
|
||||
defaultRuntime.log(JSON.stringify(next));
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(theme.muted(`Target: ${targetLabel}`));
|
||||
renderApprovalsSnapshot(next, targetLabel);
|
||||
await saveSnapshotTargeted({ opts, source, nodeId, file, baseHash, targetLabel });
|
||||
} catch (err) {
|
||||
defaultRuntime.error(formatCliError(err));
|
||||
defaultRuntime.exit(1);
|
||||
@@ -345,20 +366,10 @@ export function registerExecApprovalsCli(program: Command) {
|
||||
try {
|
||||
const trimmed = pattern.trim();
|
||||
if (!trimmed) {
|
||||
defaultRuntime.error("Pattern required.");
|
||||
defaultRuntime.exit(1);
|
||||
return;
|
||||
}
|
||||
const { snapshot, nodeId, source } = await loadSnapshotTarget(opts);
|
||||
if (source === "local") {
|
||||
defaultRuntime.log(theme.muted("Writing local approvals."));
|
||||
}
|
||||
const targetLabel = source === "local" ? "local" : nodeId ? `node:${nodeId}` : "gateway";
|
||||
if (!snapshot.hash) {
|
||||
defaultRuntime.error("Exec approvals hash missing; reload and retry.");
|
||||
defaultRuntime.exit(1);
|
||||
return;
|
||||
exitWithError("Pattern required.");
|
||||
}
|
||||
const { snapshot, nodeId, source, targetLabel, baseHash } =
|
||||
await loadWritableSnapshotTarget(opts);
|
||||
const file = snapshot.file ?? { version: 1 };
|
||||
file.version = 1;
|
||||
const agentKey = resolveAgentKey(opts.agent);
|
||||
@@ -371,16 +382,7 @@ export function registerExecApprovalsCli(program: Command) {
|
||||
allowlistEntries.push({ pattern: trimmed, lastUsedAt: Date.now() });
|
||||
agent.allowlist = allowlistEntries;
|
||||
file.agents = { ...file.agents, [agentKey]: agent };
|
||||
const next =
|
||||
source === "local"
|
||||
? saveSnapshotLocal(file)
|
||||
: await saveSnapshot(opts, nodeId, file, snapshot.hash);
|
||||
if (opts.json) {
|
||||
defaultRuntime.log(JSON.stringify(next));
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(theme.muted(`Target: ${targetLabel}`));
|
||||
renderApprovalsSnapshot(next, targetLabel);
|
||||
await saveSnapshotTargeted({ opts, source, nodeId, file, baseHash, targetLabel });
|
||||
} catch (err) {
|
||||
defaultRuntime.error(formatCliError(err));
|
||||
defaultRuntime.exit(1);
|
||||
@@ -398,20 +400,10 @@ export function registerExecApprovalsCli(program: Command) {
|
||||
try {
|
||||
const trimmed = pattern.trim();
|
||||
if (!trimmed) {
|
||||
defaultRuntime.error("Pattern required.");
|
||||
defaultRuntime.exit(1);
|
||||
return;
|
||||
}
|
||||
const { snapshot, nodeId, source } = await loadSnapshotTarget(opts);
|
||||
if (source === "local") {
|
||||
defaultRuntime.log(theme.muted("Writing local approvals."));
|
||||
}
|
||||
const targetLabel = source === "local" ? "local" : nodeId ? `node:${nodeId}` : "gateway";
|
||||
if (!snapshot.hash) {
|
||||
defaultRuntime.error("Exec approvals hash missing; reload and retry.");
|
||||
defaultRuntime.exit(1);
|
||||
return;
|
||||
exitWithError("Pattern required.");
|
||||
}
|
||||
const { snapshot, nodeId, source, targetLabel, baseHash } =
|
||||
await loadWritableSnapshotTarget(opts);
|
||||
const file = snapshot.file ?? { version: 1 };
|
||||
file.version = 1;
|
||||
const agentKey = resolveAgentKey(opts.agent);
|
||||
@@ -436,16 +428,7 @@ export function registerExecApprovalsCli(program: Command) {
|
||||
} else {
|
||||
file.agents = { ...file.agents, [agentKey]: agent };
|
||||
}
|
||||
const next =
|
||||
source === "local"
|
||||
? saveSnapshotLocal(file)
|
||||
: await saveSnapshot(opts, nodeId, file, snapshot.hash);
|
||||
if (opts.json) {
|
||||
defaultRuntime.log(JSON.stringify(next));
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(theme.muted(`Target: ${targetLabel}`));
|
||||
renderApprovalsSnapshot(next, targetLabel);
|
||||
await saveSnapshotTargeted({ opts, source, nodeId, file, baseHash, targetLabel });
|
||||
} catch (err) {
|
||||
defaultRuntime.error(formatCliError(err));
|
||||
defaultRuntime.exit(1);
|
||||
|
||||
Reference in New Issue
Block a user