mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-07 06:51:36 +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" };
|
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 {
|
function formatCliError(err: unknown): string {
|
||||||
const msg = describeUnknownError(err);
|
const msg = describeUnknownError(err);
|
||||||
return msg.includes("\n") ? msg.split("\n")[0] : msg;
|
return msg.includes("\n") ? msg.split("\n")[0] : msg;
|
||||||
@@ -268,45 +313,21 @@ export function registerExecApprovalsCli(program: Command) {
|
|||||||
.action(async (opts: ExecApprovalsCliOpts) => {
|
.action(async (opts: ExecApprovalsCliOpts) => {
|
||||||
try {
|
try {
|
||||||
if (!opts.file && !opts.stdin) {
|
if (!opts.file && !opts.stdin) {
|
||||||
defaultRuntime.error("Provide --file or --stdin.");
|
exitWithError("Provide --file or --stdin.");
|
||||||
defaultRuntime.exit(1);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (opts.file && opts.stdin) {
|
if (opts.file && opts.stdin) {
|
||||||
defaultRuntime.error("Use either --file or --stdin (not both).");
|
exitWithError("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;
|
|
||||||
}
|
}
|
||||||
|
const { source, nodeId, targetLabel, baseHash } = await loadWritableSnapshotTarget(opts);
|
||||||
const raw = opts.stdin ? await readStdin() : await fs.readFile(String(opts.file), "utf8");
|
const raw = opts.stdin ? await readStdin() : await fs.readFile(String(opts.file), "utf8");
|
||||||
let file: ExecApprovalsFile;
|
let file: ExecApprovalsFile;
|
||||||
try {
|
try {
|
||||||
file = JSON5.parse(raw);
|
file = JSON5.parse(raw);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
defaultRuntime.error(`Failed to parse approvals JSON: ${String(err)}`);
|
exitWithError(`Failed to parse approvals JSON: ${String(err)}`);
|
||||||
defaultRuntime.exit(1);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
file.version = 1;
|
file.version = 1;
|
||||||
const next =
|
await saveSnapshotTargeted({ opts, source, nodeId, file, baseHash, targetLabel });
|
||||||
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);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
defaultRuntime.error(formatCliError(err));
|
defaultRuntime.error(formatCliError(err));
|
||||||
defaultRuntime.exit(1);
|
defaultRuntime.exit(1);
|
||||||
@@ -345,20 +366,10 @@ export function registerExecApprovalsCli(program: Command) {
|
|||||||
try {
|
try {
|
||||||
const trimmed = pattern.trim();
|
const trimmed = pattern.trim();
|
||||||
if (!trimmed) {
|
if (!trimmed) {
|
||||||
defaultRuntime.error("Pattern required.");
|
exitWithError("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;
|
|
||||||
}
|
}
|
||||||
|
const { snapshot, nodeId, source, targetLabel, baseHash } =
|
||||||
|
await loadWritableSnapshotTarget(opts);
|
||||||
const file = snapshot.file ?? { version: 1 };
|
const file = snapshot.file ?? { version: 1 };
|
||||||
file.version = 1;
|
file.version = 1;
|
||||||
const agentKey = resolveAgentKey(opts.agent);
|
const agentKey = resolveAgentKey(opts.agent);
|
||||||
@@ -371,16 +382,7 @@ export function registerExecApprovalsCli(program: Command) {
|
|||||||
allowlistEntries.push({ pattern: trimmed, lastUsedAt: Date.now() });
|
allowlistEntries.push({ pattern: trimmed, lastUsedAt: Date.now() });
|
||||||
agent.allowlist = allowlistEntries;
|
agent.allowlist = allowlistEntries;
|
||||||
file.agents = { ...file.agents, [agentKey]: agent };
|
file.agents = { ...file.agents, [agentKey]: agent };
|
||||||
const next =
|
await saveSnapshotTargeted({ opts, source, nodeId, file, baseHash, targetLabel });
|
||||||
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);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
defaultRuntime.error(formatCliError(err));
|
defaultRuntime.error(formatCliError(err));
|
||||||
defaultRuntime.exit(1);
|
defaultRuntime.exit(1);
|
||||||
@@ -398,20 +400,10 @@ export function registerExecApprovalsCli(program: Command) {
|
|||||||
try {
|
try {
|
||||||
const trimmed = pattern.trim();
|
const trimmed = pattern.trim();
|
||||||
if (!trimmed) {
|
if (!trimmed) {
|
||||||
defaultRuntime.error("Pattern required.");
|
exitWithError("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;
|
|
||||||
}
|
}
|
||||||
|
const { snapshot, nodeId, source, targetLabel, baseHash } =
|
||||||
|
await loadWritableSnapshotTarget(opts);
|
||||||
const file = snapshot.file ?? { version: 1 };
|
const file = snapshot.file ?? { version: 1 };
|
||||||
file.version = 1;
|
file.version = 1;
|
||||||
const agentKey = resolveAgentKey(opts.agent);
|
const agentKey = resolveAgentKey(opts.agent);
|
||||||
@@ -436,16 +428,7 @@ export function registerExecApprovalsCli(program: Command) {
|
|||||||
} else {
|
} else {
|
||||||
file.agents = { ...file.agents, [agentKey]: agent };
|
file.agents = { ...file.agents, [agentKey]: agent };
|
||||||
}
|
}
|
||||||
const next =
|
await saveSnapshotTargeted({ opts, source, nodeId, file, baseHash, targetLabel });
|
||||||
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);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
defaultRuntime.error(formatCliError(err));
|
defaultRuntime.error(formatCliError(err));
|
||||||
defaultRuntime.exit(1);
|
defaultRuntime.exit(1);
|
||||||
|
|||||||
Reference in New Issue
Block a user