diff --git a/src/qwen-delegate.ts b/src/qwen-delegate.ts index 04317a9..b76d63d 100644 --- a/src/qwen-delegate.ts +++ b/src/qwen-delegate.ts @@ -25,15 +25,22 @@ const DEFAULT_TIMEOUT_MS = 10 * 60 * 1000; // 10 min * qwen-code prints startup warnings (e.g. failed MCP sub-servers) to stderr; those are * ignored on success and surfaced only when the run itself fails. */ -export function delegateToQwen ( +export function delegateToQwen( prompt: string, options: DelegateOptions = {}, ): Promise { const { timeoutMs = DEFAULT_TIMEOUT_MS, spawnFn = spawn } = options; return new Promise((resolve) => { - const child: ChildProcess = spawnFn("qwen", ["-p", prompt], { - shell: true, // qwen.cmd on Windows needs a shell to resolve + // shell:true is required for qwen.cmd to resolve on Windows, but Node does NOT escape + // array args in that mode (see DEP0190) — it just space-joins them, so an unquoted + // multi-word prompt silently splits into extra positional args and confuses qwen's CLI + // parser ("Cannot use both a positional prompt and the --prompt (-p) flag together"). + // Build the command as a single, explicitly-quoted string instead. + const quoteArg = (s: string) => `"${s.replace(/"/g, '\\"')}"`; + const command = ["qwen", "-p", quoteArg(prompt)].join(" "); + const child: ChildProcess = spawnFn(command, { + shell: true, stdio: ["ignore", "pipe", "pipe"], });