refactor(cli): share shell argument quoting · openclaw/openclaw@0111afe
vincentkoc
·
2026-06-22
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -10,6 +10,13 @@ const UPDATE_COMMAND_RE =
|
10 | 10 | /^(?:pnpm|npm|bunx|npx)\s+openclaw\b.*(?:^|\s)update(?:\s|$)|^openclaw\b.*(?:^|\s)update(?:\s|$)/; |
11 | 11 | const CONTAINER_HINT_RE = /^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$/; |
12 | 12 | |
| 13 | +export function quoteCliArg(value: string): string { |
| 14 | +if (/^[A-Za-z0-9_/:=.,@%+-]+$/.test(value)) { |
| 15 | +return value; |
| 16 | +} |
| 17 | +return `'${value.replaceAll("'", "'\\''")}'`; |
| 18 | +} |
| 19 | + |
13 | 20 | /** Add active root options to a displayed command without duplicating explicit flags. */ |
14 | 21 | export function formatCliCommand( |
15 | 22 | command: string, |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -38,7 +38,7 @@ import {
|
38 | 38 | type DevicePairingAccessSummary, |
39 | 39 | type PendingDeviceApprovalKind, |
40 | 40 | } from "../shared/device-pairing-access.js"; |
41 | | -import { formatCliCommand } from "./command-format.js"; |
| 41 | +import { formatCliCommand, quoteCliArg } from "./command-format.js"; |
42 | 42 | import { parseTimeoutMsWithFallback } from "./parse-timeout.js"; |
43 | 43 | import { withProgress } from "./progress.js"; |
44 | 44 | |
@@ -635,13 +635,6 @@ function lookupPairedDevice(
|
635 | 635 | return paired; |
636 | 636 | } |
637 | 637 | |
638 | | -function quoteCliArg(value: string): string { |
639 | | -if (/^[A-Za-z0-9_/:=.,@%+-]+$/.test(value)) { |
640 | | -return value; |
641 | | -} |
642 | | -return `'${value.replaceAll("'", "'\\''")}'`; |
643 | | -} |
644 | | - |
645 | 638 | function buildExplicitApproveCommand(opts: DevicesRpcOpts, requestId: string): string { |
646 | 639 | const args = ["openclaw", "devices", "approve", requestId]; |
647 | 640 | const url = normalizeOptionalString(opts.url); |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -11,7 +11,7 @@ import { formatErrorMessage } from "../../infra/errors.js";
|
11 | 11 | import { formatTimeAgo } from "../../infra/format-time/format-relative.ts"; |
12 | 12 | import { defaultRuntime } from "../../runtime.js"; |
13 | 13 | import { shortenHomeInString } from "../../utils.js"; |
14 | | -import { formatCliCommand } from "../command-format.js"; |
| 14 | +import { formatCliCommand, quoteCliArg } from "../command-format.js"; |
15 | 15 | import { parseDurationMs } from "../parse-duration.js"; |
16 | 16 | import { getNodesTheme, runNodesCommand } from "./cli-utils.js"; |
17 | 17 | import { formatPermissions, parseNodeList, parsePairingList } from "./format.js"; |
@@ -132,13 +132,6 @@ function isPendingApprovalState(
|
132 | 132 | return state === "pending-approval" || state === "pending-reapproval"; |
133 | 133 | } |
134 | 134 | |
135 | | -function quoteCliArg(value: string): string { |
136 | | -if (/^[A-Za-z0-9_/:=.,@%+-]+$/.test(value)) { |
137 | | -return value; |
138 | | -} |
139 | | -return `'${value.replaceAll("'", "'\\''")}'`; |
140 | | -} |
141 | | - |
142 | 135 | function formatPendingApprovalCommand(raw: unknown, opts: NodesRpcOpts): string | null { |
143 | 136 | const requestId = normalizeOptionalString(raw); |
144 | 137 | if (!requestId) { |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -3,7 +3,7 @@ import path from "node:path";
|
3 | 3 | import { normalizeUniqueSingleOrTrimmedStringList } from "@openclaw/normalization-core/string-normalization"; |
4 | 4 | import { note } from "../../packages/terminal-core/src/note.js"; |
5 | 5 | import { sanitizeTerminalText } from "../../packages/terminal-core/src/safe-text.js"; |
6 | | -import { formatCliCommand } from "../cli/command-format.js"; |
| 6 | +import { formatCliCommand, quoteCliArg } from "../cli/command-format.js"; |
7 | 7 | import { resolveStateDir } from "../config/paths.js"; |
8 | 8 | import type { OpenClawConfig } from "../config/types.openclaw.js"; |
9 | 9 | import { callGateway } from "../gateway/call.js"; |
@@ -163,13 +163,6 @@ function formatRoles(roles: string[]): string {
|
163 | 163 | return roles.length > 0 ? roles.join(", ") : "none"; |
164 | 164 | } |
165 | 165 | |
166 | | -function quoteCliArg(value: string): string { |
167 | | -if (/^[A-Za-z0-9_/:=.,@%+-]+$/.test(value)) { |
168 | | -return value; |
169 | | -} |
170 | | -return `'${value.replaceAll("'", "'\\''")}'`; |
171 | | -} |
172 | | - |
173 | 166 | function formatCliArgs(args: string[]): string { |
174 | 167 | return formatCliCommand(args.map(quoteCliArg).join(" ")); |
175 | 168 | } |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。