diff --git a/packages/coding-agent/src/cli/args.ts b/packages/coding-agent/src/cli/args.ts index bfb0ff6e2..5f111812b 100644 --- a/packages/coding-agent/src/cli/args.ts +++ b/packages/coding-agent/src/cli/args.ts @@ -79,7 +79,16 @@ export function parseArgs(args: string[]): Args { for (let i = 0; i < args.length; i++) { const arg = args[i]; - if (arg === "--help" || arg === "-h") { + if (arg === "--") { + for (const positionalArg of args.slice(i + 1)) { + if (positionalArg.startsWith("@")) { + result.fileArgs.push(positionalArg.slice(1)); + } else { + result.messages.push(positionalArg); + } + } + break; + } else if (arg === "--help" || arg === "-h") { result.help = true; } else if (arg === "--version" || arg === "-v") { result.version = true; diff --git a/packages/coding-agent/test/suite/regressions/7269-cli-end-of-options.test.ts b/packages/coding-agent/test/suite/regressions/7269-cli-end-of-options.test.ts new file mode 100644 index 000000000..cd012c280 --- /dev/null +++ b/packages/coding-agent/test/suite/regressions/7269-cli-end-of-options.test.ts @@ -0,0 +1,39 @@ +import { fauxAssistantMessage } from "@earendil-works/pi-ai"; +import { afterEach, describe, expect, it } from "vitest"; +import { parseArgs } from "../../../src/cli/args.ts"; +import { createHarness, getUserTexts, type Harness } from "../harness.ts"; + +describe("issue #7269 CLI end-of-options delimiter", () => { + let harness: Harness | undefined; + + afterEach(() => { + harness?.cleanup(); + harness = undefined; + }); + + it.each(["- summarize the following points for me", "--answer my question briefly"])( + "passes %j as a prompt after --", + async (prompt) => { + const parsed = parseArgs(["-ne", "--no-session", "-p", "--", prompt]); + expect(parsed.messages).toEqual([prompt]); + expect(parsed.unknownFlags.size).toBe(0); + expect(parsed.diagnostics).toEqual([]); + + harness = await createHarness(); + harness.setResponses([fauxAssistantMessage("ok")]); + await harness.session.prompt(parsed.messages[0]); + expect(getUserTexts(harness)).toEqual([prompt]); + }, + ); + + it("stops parsing options while retaining @file handling", () => { + const parsed = parseArgs(["--unknown-flag", "value", "--", "--provider", "openai", "-c", "@prompt.md"]); + + expect(parsed.unknownFlags.get("unknown-flag")).toBe("value"); + expect(parsed.provider).toBeUndefined(); + expect(parsed.continue).toBeUndefined(); + expect(parsed.messages).toEqual(["--provider", "openai", "-c"]); + expect(parsed.fileArgs).toEqual(["prompt.md"]); + expect(parsed.diagnostics).toEqual([]); + }); +});