Files
openclaw/src/daemon/arg-split.ts
clawsweeper[bot] e427262044 [Fix] Keep node systemd tokens out of unit files (#84815)
Summary:
- This replacement PR marks the Linux node daemon gateway token as file-backed, writes it to `node.systemd.env`, sanitizes and migrates systemd env artifacts, adds regression tests, and updates the changelog.
- Reproducibility: yes. from source inspection: current `main` copies `OPENCLAW_GATEWAY_TOKEN` into the node s ... e-backed before systemd rendering. I did not run a local live systemd install during this read-only review.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(systemd): scrub single-quoted env tokens
- PR branch already contained follow-up commit before automerge: [Fix] Keep node systemd tokens out of unit files

Validation:
- ClawSweeper review passed for head f626b66c09.
- Required merge gates passed before the squash merge.

Prepared head SHA: f626b66c09
Review: https://github.com/openclaw/openclaw/pull/84815#issuecomment-4505012292

Co-authored-by: samzong <samzong.lu@gmail.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-05-21 06:48:15 +00:00

64 lines
1.6 KiB
TypeScript

type ArgSplitEscapeMode = "none" | "backslash" | "backslash-quote-only";
type ArgSplitQuoteChar = '"' | "'";
type ArgSplitQuoteStart = "anywhere" | "item-start";
export function splitArgsPreservingQuotes(
value: string,
options?: {
escapeMode?: ArgSplitEscapeMode;
quoteChars?: readonly ArgSplitQuoteChar[];
quoteStart?: ArgSplitQuoteStart;
},
): string[] {
const args: string[] = [];
let current = "";
let quoteChar: ArgSplitQuoteChar | null = null;
const escapeMode = options?.escapeMode ?? "none";
const quoteChars = new Set<ArgSplitQuoteChar>(options?.quoteChars ?? ['"']);
const quoteStart = options?.quoteStart ?? "anywhere";
for (let i = 0; i < value.length; i++) {
const char = value[i];
if (escapeMode === "backslash" && char === "\\") {
if (i + 1 < value.length) {
current += value[i + 1];
i++;
}
continue;
}
if (
escapeMode === "backslash-quote-only" &&
char === "\\" &&
i + 1 < value.length &&
value[i + 1] === '"'
) {
current += '"';
i++;
continue;
}
if (quoteChars.has(char as ArgSplitQuoteChar)) {
if (quoteChar === char) {
quoteChar = null;
continue;
}
const canOpenQuote = quoteStart === "anywhere" || current.length === 0;
if (!quoteChar && canOpenQuote) {
quoteChar = char as ArgSplitQuoteChar;
continue;
}
}
if (!quoteChar && /\s/.test(char)) {
if (current) {
args.push(current);
current = "";
}
continue;
}
current += char;
}
if (current) {
args.push(current);
}
return args;
}