

























@@ -136,6 +136,26 @@ const DEFAULT_REQUEST_TIMEOUT_MS = 30_000;
136136const DEFAULT_OPENCLAW_CLI_TIMEOUT_MS = 60_000;
137137const DISCORD_RESPONSE_BODY_MAX_BYTES = 1024 * 1024;
138138const WEBHOOK_CLEANUP_TIMEOUT_MS = 10_000;
139+const BOOLEAN_OPTIONS = new Set(["--help", "-h", "--json"]);
140+const VALUE_OPTIONS = new Set([
141+"--channel",
142+"--driver",
143+"--token",
144+"--token-prefix",
145+"--bot-token",
146+"--bot-token-prefix",
147+"--agent",
148+"--mention",
149+"--instruction",
150+"--timeout-ms",
151+"--poll-ms",
152+"--state-dir",
153+"--openclaw-bin",
154+]);
155+156+class CliArgumentError extends Error {
157+override name = "CliArgumentError";
158+}
139159140160function sleep(ms: number): Promise<void> {
141161return new Promise((resolve) => {
@@ -237,21 +257,48 @@ function resolveStateDir(): string {
237257return path.join(home, ".openclaw");
238258}
239259240-function resolveArg(flag: string): string | undefined {
241-const argv = process.argv.slice(2);
260+function resolveArg(flag: string, argv: string[]): string | undefined {
242261const eq = argv.find((entry) => entry.startsWith(`${flag}=`));
243262if (eq) {
244-return eq.slice(flag.length + 1);
263+const value = eq.slice(flag.length + 1);
264+if (!value) {
265+throw new CliArgumentError(`${flag} requires a value`);
266+}
267+return value;
245268}
246269const idx = argv.indexOf(flag);
247-if (idx >= 0 && idx + 1 < argv.length) {
248-return argv[idx + 1];
270+if (idx < 0) {
271+return undefined;
249272}
250-return undefined;
273+const value = argv[idx + 1];
274+if (!value || value.startsWith("--")) {
275+throw new CliArgumentError(`${flag} requires a value`);
276+}
277+return value;
278+}
279+280+function hasFlag(flag: string, argv = process.argv.slice(2)): boolean {
281+return argv.includes(flag);
251282}
252283253-function hasFlag(flag: string): boolean {
254-return process.argv.slice(2).includes(flag);
284+function validateCliArgs(argv: string[]): void {
285+for (let index = 0; index < argv.length; index += 1) {
286+const arg = argv[index] ?? "";
287+if (BOOLEAN_OPTIONS.has(arg)) {
288+continue;
289+}
290+if (arg.startsWith("--") && arg.includes("=")) {
291+const [flag] = arg.split("=", 1);
292+if (VALUE_OPTIONS.has(flag)) {
293+continue;
294+}
295+}
296+if (VALUE_OPTIONS.has(arg)) {
297+index += 1;
298+continue;
299+}
300+throw new CliArgumentError(`Unknown argument: ${arg}`);
301+}
255302}
256303257304function parseDriverMode(raw: string): DriverMode {
@@ -314,43 +361,54 @@ function usage(): string {
314361);
315362}
316363317-function parseArgs(): Args {
318-const channelId = resolveArg("--channel") || process.env.OPENCLAW_DISCORD_SMOKE_CHANNEL_ID || "";
364+function parseArgs(argv = process.argv.slice(2)): Args {
365+validateCliArgs(argv);
366+const channelId =
367+resolveArg("--channel", argv) || process.env.OPENCLAW_DISCORD_SMOKE_CHANNEL_ID || "";
319368const driverModeRaw =
320-resolveArg("--driver") || process.env.OPENCLAW_DISCORD_SMOKE_DRIVER || "token";
369+resolveArg("--driver", argv) || process.env.OPENCLAW_DISCORD_SMOKE_DRIVER || "token";
321370const driverMode = parseDriverMode(driverModeRaw);
322371const driverToken =
323-resolveArg("--token") || process.env.OPENCLAW_DISCORD_SMOKE_DRIVER_TOKEN || "";
372+resolveArg("--token", argv) || process.env.OPENCLAW_DISCORD_SMOKE_DRIVER_TOKEN || "";
324373const driverTokenPrefix =
325-resolveArg("--token-prefix") || process.env.OPENCLAW_DISCORD_SMOKE_DRIVER_TOKEN_PREFIX || "Bot";
374+resolveArg("--token-prefix", argv) ||
375+process.env.OPENCLAW_DISCORD_SMOKE_DRIVER_TOKEN_PREFIX ||
376+"Bot";
326377const botToken =
327-resolveArg("--bot-token") ||
378+resolveArg("--bot-token", argv) ||
328379process.env.OPENCLAW_DISCORD_SMOKE_BOT_TOKEN ||
329380process.env.DISCORD_BOT_TOKEN ||
330381"";
331382const botTokenPrefix =
332-resolveArg("--bot-token-prefix") ||
383+resolveArg("--bot-token-prefix", argv) ||
333384process.env.OPENCLAW_DISCORD_SMOKE_BOT_TOKEN_PREFIX ||
334385"Bot";
335-const targetAgent = resolveArg("--agent") || process.env.OPENCLAW_DISCORD_SMOKE_AGENT || "codex";
386+const targetAgent =
387+resolveArg("--agent", argv) || process.env.OPENCLAW_DISCORD_SMOKE_AGENT || "codex";
336388const mentionUserId =
337-resolveArg("--mention") || process.env.OPENCLAW_DISCORD_SMOKE_MENTION_USER_ID || undefined;
389+resolveArg("--mention", argv) ||
390+process.env.OPENCLAW_DISCORD_SMOKE_MENTION_USER_ID ||
391+undefined;
338392const instruction =
339-resolveArg("--instruction") || process.env.OPENCLAW_DISCORD_SMOKE_INSTRUCTION || undefined;
393+resolveArg("--instruction", argv) ||
394+process.env.OPENCLAW_DISCORD_SMOKE_INSTRUCTION ||
395+undefined;
340396const timeoutMs = parseNumber(
341-resolveArg("--timeout-ms") || process.env.OPENCLAW_DISCORD_SMOKE_TIMEOUT_MS,
397+resolveArg("--timeout-ms", argv) || process.env.OPENCLAW_DISCORD_SMOKE_TIMEOUT_MS,
342398240_000,
343399"--timeout-ms",
344400);
345401const pollMs = parseNumber(
346-resolveArg("--poll-ms") || process.env.OPENCLAW_DISCORD_SMOKE_POLL_MS,
402+resolveArg("--poll-ms", argv) || process.env.OPENCLAW_DISCORD_SMOKE_POLL_MS,
3474031_500,
348404"--poll-ms",
349405);
350-const stateDir = path.resolve(resolveArg("--state-dir") || resolveStateDir());
406+const stateDir = path.resolve(resolveArg("--state-dir", argv) || resolveStateDir());
351407const openclawBin =
352-resolveArg("--openclaw-bin") || process.env.OPENCLAW_DISCORD_SMOKE_OPENCLAW_BIN || "openclaw";
353-const json = hasFlag("--json");
408+resolveArg("--openclaw-bin", argv) ||
409+process.env.OPENCLAW_DISCORD_SMOKE_OPENCLAW_BIN ||
410+"openclaw";
411+const json = hasFlag("--json", argv);
354412355413if (!channelId) {
356414throw new Error(usage());
@@ -736,10 +794,10 @@ function printOutput(params: { json: boolean; payload: SuccessResult | FailureRe
736794}
737795}
738796739-async function run(): Promise<SuccessResult | FailureResult> {
797+async function run(argv = process.argv.slice(2)): Promise<SuccessResult | FailureResult> {
740798let args: Args;
741799try {
742-args = parseArgs();
800+args = parseArgs(argv);
743801} catch (err) {
744802return {
745803ok: false,
@@ -1032,12 +1090,18 @@ async function run(): Promise<SuccessResult | FailureResult> {
10321090}
10331091}
103410921035-async function main(): Promise<number> {
1036-if (hasFlag("--help") || hasFlag("-h")) {
1093+async function main(argv = process.argv.slice(2)): Promise<number> {
1094+try {
1095+validateCliArgs(argv);
1096+} catch (err) {
1097+writeStderrLine(safeErrorMessage(err));
1098+return 1;
1099+}
1100+if (hasFlag("--help", argv) || hasFlag("-h", argv)) {
10371101writeStdoutLine(usage());
10381102return 0;
10391103}
1040-const result = await run().catch(
1104+const result = await run(argv).catch(
10411105(err: unknown): FailureResult => ({
10421106ok: false,
10431107stage: "unexpected",
@@ -1046,14 +1110,15 @@ async function main(): Promise<number> {
10461110}),
10471111);
10481112printOutput({
1049-json: hasFlag("--json"),
1113+json: hasFlag("--json", argv),
10501114payload: result,
10511115});
10521116return result.ok ? 0 : 1;
10531117}
1054111810551119export const testing = {
10561120 parseDriverMode,
1121+ parseArgs,
10571122 parseNumber,
10581123DISCORD_RESPONSE_BODY_MAX_BYTES,
10591124 redactDiscordApiPath,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。