0f976084b8
`omp --approval-mode=yolo acp` was rewritten to `launch --approval-mode=yolo acp`, swallowing `acp` as a launch prompt so the yolo override never reached the ACP command path (the ACP permission gate from #2097 stayed in always-ask). `resolveCliArgv` only inspected `argv[0]`, so any leading global option flag hid the real subcommand. It now scans past leading flags using the launch parser's value-consumption contract (a flag's value is never mistaken for the subcommand, e.g. `--model acp`) and hoists the recognized subcommand to the front with the flags preserved as its own argv. Genuine launch prompts are untouched. The flag value-consumption rule is factored into `cli/flag-tables.ts` (`flagConsumesValue` + the shared `isUnknownLongValueCandidate`) so the resolver and the profile bootstrap share one source of truth. Fixed permission mode not respected in ACP mode ([#2970](https://github.com/can1357/oh-my-pi/issues/2970)) Fixes #2970
59 lines
2.2 KiB
TypeScript
59 lines
2.2 KiB
TypeScript
/**
|
|
* Leading global option flags must not hide a subcommand from the CLI runner.
|
|
*
|
|
* #2970: `omp --approval-mode=yolo acp` was rewritten to
|
|
* `launch --approval-mode=yolo acp`, swallowing `acp` as a launch prompt so the
|
|
* yolo override never reached the ACP command path. The resolver now skips
|
|
* leading global flags (using the launch parser's value-consumption contract)
|
|
* and hoists the real subcommand to the front so its parser still applies the
|
|
* flags.
|
|
*/
|
|
import { describe, expect, test } from "bun:test";
|
|
import { resolveCliArgv } from "@oh-my-pi/pi-coding-agent/cli-commands";
|
|
|
|
describe("resolveCliArgv routes subcommands hidden behind leading global flags", () => {
|
|
test("`--approval-mode=yolo acp` dispatches the acp subcommand with the flag preserved", () => {
|
|
expect(resolveCliArgv(["--approval-mode=yolo", "acp"])).toEqual({
|
|
argv: ["acp", "--approval-mode=yolo"],
|
|
});
|
|
});
|
|
|
|
test("space-form `--approval-mode yolo acp` keeps the flag and its value with acp", () => {
|
|
expect(resolveCliArgv(["--approval-mode", "yolo", "acp"])).toEqual({
|
|
argv: ["acp", "--approval-mode", "yolo"],
|
|
});
|
|
});
|
|
|
|
test("multiple leading flags before the subcommand are all preserved", () => {
|
|
expect(resolveCliArgv(["--approval-mode=yolo", "--model", "gpt", "acp"])).toEqual({
|
|
argv: ["acp", "--approval-mode=yolo", "--model", "gpt"],
|
|
});
|
|
});
|
|
|
|
test("a value-consuming flag does not mistake its value for a subcommand", () => {
|
|
// `acp` here is the value of `--model`, not the subcommand, so this stays a
|
|
// launch prompt exactly as the launch parser would read it.
|
|
expect(resolveCliArgv(["--model", "acp"])).toEqual({
|
|
argv: ["launch", "--model", "acp"],
|
|
});
|
|
});
|
|
|
|
test("`--` ends option scanning so a following subcommand stays a launch prompt", () => {
|
|
expect(resolveCliArgv(["--", "acp"])).toEqual({
|
|
argv: ["launch", "--", "acp"],
|
|
});
|
|
});
|
|
|
|
test("a genuine launch prompt is untouched", () => {
|
|
expect(resolveCliArgv(["--approval-mode=yolo", "fix", "the", "bug"])).toEqual({
|
|
argv: ["launch", "--approval-mode=yolo", "fix", "the", "bug"],
|
|
});
|
|
});
|
|
|
|
test("a subcommand already in front still passes through unchanged", () => {
|
|
expect(resolveCliArgv(["acp", "--approval-mode=yolo"])).toEqual({
|
|
argv: ["acp", "--approval-mode=yolo"],
|
|
});
|
|
});
|
|
});
|