From 266b3a356d322631509dc9be5d82fe2dde639e7f Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 21 Feb 2026 21:45:50 +0000 Subject: [PATCH] refactor(cli): dedupe allowlist command wiring --- src/cli/exec-approvals-cli.ts | 120 ++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 58 deletions(-) diff --git a/src/cli/exec-approvals-cli.ts b/src/cli/exec-approvals-cli.ts index 291617df74b..07fe5a462a6 100644 --- a/src/cli/exec-approvals-cli.ts +++ b/src/cli/exec-approvals-cli.ts @@ -295,11 +295,12 @@ async function loadWritableAllowlistAgent(opts: ExecApprovalsCliOpts): Promise<{ type WritableAllowlistAgentContext = Awaited> & { trimmedPattern: string; }; +type AllowlistMutation = (context: WritableAllowlistAgentContext) => boolean | Promise; async function runAllowlistMutation( pattern: string, opts: ExecApprovalsCliOpts, - mutate: (context: WritableAllowlistAgentContext) => boolean | Promise, + mutate: AllowlistMutation, ): Promise { try { const trimmedPattern = requireTrimmedNonEmpty(pattern, "Pattern required."); @@ -322,6 +323,25 @@ async function runAllowlistMutation( } } +function registerAllowlistMutationCommand(params: { + allowlist: Command; + name: "add" | "remove"; + description: string; + mutate: AllowlistMutation; +}): Command { + const command = params.allowlist + .command(`${params.name} `) + .description(params.description) + .option("--node ", "Target node id/name/IP") + .option("--gateway", "Force gateway approvals", false) + .option("--agent ", 'Agent id (defaults to "*")') + .action(async (pattern: string, opts: ExecApprovalsCliOpts) => { + await runAllowlistMutation(pattern, opts, params.mutate); + }); + nodesCallOpts(command); + return command; +} + export function registerExecApprovalsCli(program: Command) { const formatExample = (cmd: string, desc: string) => ` ${theme.command(cmd)}\n ${theme.muted(desc)}`; @@ -416,63 +436,47 @@ export function registerExecApprovalsCli(program: Command) { )}\n\n${theme.muted("Docs:")} ${formatDocsLink("/cli/approvals", "docs.openclaw.ai/cli/approvals")}\n`, ); - const allowlistAdd = allowlist - .command("add ") - .description("Add a glob pattern to an allowlist") - .option("--node ", "Target node id/name/IP") - .option("--gateway", "Force gateway approvals", false) - .option("--agent ", 'Agent id (defaults to "*")') - .action(async (pattern: string, opts: ExecApprovalsCliOpts) => { - await runAllowlistMutation( - pattern, - opts, - ({ trimmedPattern, file, agent, agentKey, allowlistEntries }) => { - if (allowlistEntries.some((entry) => normalizeAllowlistEntry(entry) === trimmedPattern)) { - defaultRuntime.log("Already allowlisted."); - return false; - } - allowlistEntries.push({ pattern: trimmedPattern, lastUsedAt: Date.now() }); - agent.allowlist = allowlistEntries; - file.agents = { ...file.agents, [agentKey]: agent }; - return true; - }, - ); - }); - nodesCallOpts(allowlistAdd); + registerAllowlistMutationCommand({ + allowlist, + name: "add", + description: "Add a glob pattern to an allowlist", + mutate: ({ trimmedPattern, file, agent, agentKey, allowlistEntries }) => { + if (allowlistEntries.some((entry) => normalizeAllowlistEntry(entry) === trimmedPattern)) { + defaultRuntime.log("Already allowlisted."); + return false; + } + allowlistEntries.push({ pattern: trimmedPattern, lastUsedAt: Date.now() }); + agent.allowlist = allowlistEntries; + file.agents = { ...file.agents, [agentKey]: agent }; + return true; + }, + }); - const allowlistRemove = allowlist - .command("remove ") - .description("Remove a glob pattern from an allowlist") - .option("--node ", "Target node id/name/IP") - .option("--gateway", "Force gateway approvals", false) - .option("--agent ", 'Agent id (defaults to "*")') - .action(async (pattern: string, opts: ExecApprovalsCliOpts) => { - await runAllowlistMutation( - pattern, - opts, - ({ trimmedPattern, file, agent, agentKey, allowlistEntries }) => { - const nextEntries = allowlistEntries.filter( - (entry) => normalizeAllowlistEntry(entry) !== trimmedPattern, - ); - if (nextEntries.length === allowlistEntries.length) { - defaultRuntime.log("Pattern not found."); - return false; - } - if (nextEntries.length === 0) { - delete agent.allowlist; - } else { - agent.allowlist = nextEntries; - } - if (isEmptyAgent(agent)) { - const agents = { ...file.agents }; - delete agents[agentKey]; - file.agents = Object.keys(agents).length > 0 ? agents : undefined; - } else { - file.agents = { ...file.agents, [agentKey]: agent }; - } - return true; - }, + registerAllowlistMutationCommand({ + allowlist, + name: "remove", + description: "Remove a glob pattern from an allowlist", + mutate: ({ trimmedPattern, file, agent, agentKey, allowlistEntries }) => { + const nextEntries = allowlistEntries.filter( + (entry) => normalizeAllowlistEntry(entry) !== trimmedPattern, ); - }); - nodesCallOpts(allowlistRemove); + if (nextEntries.length === allowlistEntries.length) { + defaultRuntime.log("Pattern not found."); + return false; + } + if (nextEntries.length === 0) { + delete agent.allowlist; + } else { + agent.allowlist = nextEntries; + } + if (isEmptyAgent(agent)) { + const agents = { ...file.agents }; + delete agents[agentKey]; + file.agents = Object.keys(agents).length > 0 ? agents : undefined; + } else { + file.agents = { ...file.agents, [agentKey]: agent }; + } + return true; + }, + }); }