acpx 0.17.1 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/{agent-registry-evUoJINz.js → agent-registry-Ct2yWPW7.js} +18 -18
  2. package/dist/agent-registry-Ct2yWPW7.js.map +1 -0
  3. package/dist/agent-registry.d.ts.map +1 -1
  4. package/dist/agent-registry.js +1 -1
  5. package/dist/{cli-B2ycKzaO.js → cli-Bmki9cj5.js} +5 -5
  6. package/dist/{cli-B2ycKzaO.js.map → cli-Bmki9cj5.js.map} +1 -1
  7. package/dist/cli.js +167 -131
  8. package/dist/cli.js.map +1 -1
  9. package/dist/{client-CkbBoSGd.d.ts → client-DzaUKazo.d.ts} +23 -15
  10. package/dist/client-DzaUKazo.d.ts.map +1 -0
  11. package/dist/{flows-xGyhmoHO.js → flows--Ewxn_fQ.js} +665 -460
  12. package/dist/flows--Ewxn_fQ.js.map +1 -0
  13. package/dist/flows.d.ts +19 -7
  14. package/dist/flows.d.ts.map +1 -1
  15. package/dist/flows.js +1 -1
  16. package/dist/{invocation-options-eZEBh4vd.js → invocation-options-DRzxHZmr.js} +34 -12
  17. package/dist/invocation-options-DRzxHZmr.js.map +1 -0
  18. package/dist/{ipc-D2rstexT.js → ipc-fMgj5vrO.js} +818 -302
  19. package/dist/ipc-fMgj5vrO.js.map +1 -0
  20. package/dist/{output-D2xL6wdp.js → output-D6kDs8BN.js} +30 -14
  21. package/dist/output-D6kDs8BN.js.map +1 -0
  22. package/dist/{queue-owner-runtime-Dgv3e2Tp.js → queue-owner-runtime-CLwjMYNL.js} +1448 -717
  23. package/dist/queue-owner-runtime-CLwjMYNL.js.map +1 -0
  24. package/dist/runtime.d.ts +57 -3
  25. package/dist/runtime.d.ts.map +1 -1
  26. package/dist/runtime.js +303 -166
  27. package/dist/runtime.js.map +1 -1
  28. package/dist/session-options-Dp6mzNSy.d.ts.map +1 -1
  29. package/dist/{session-watch-CTe9Bnbc.js → session-watch-BfdIo-n4.js} +5 -5
  30. package/dist/session-watch-BfdIo-n4.js.map +1 -0
  31. package/dist/{watch-DxuXEc8n.js → watch-DH-zXQH2.js} +2 -2
  32. package/dist/{watch-DxuXEc8n.js.map → watch-DH-zXQH2.js.map} +1 -1
  33. package/package.json +1 -1
  34. package/skills/acpx/SKILL.md +69 -30
  35. package/dist/agent-registry-evUoJINz.js.map +0 -1
  36. package/dist/client-CkbBoSGd.d.ts.map +0 -1
  37. package/dist/flows-xGyhmoHO.js.map +0 -1
  38. package/dist/invocation-options-eZEBh4vd.js.map +0 -1
  39. package/dist/ipc-D2rstexT.js.map +0 -1
  40. package/dist/output-D2xL6wdp.js.map +0 -1
  41. package/dist/queue-owner-runtime-Dgv3e2Tp.js.map +0 -1
  42. package/dist/session-watch-CTe9Bnbc.js.map +0 -1
package/dist/cli.js CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import { n as getTextErrorRemediationHints, o as __exportAll, t as createOutputFormatter } from "./output-D2xL6wdp.js";
3
- import { A as listSessions, At as AgentSpawnError, C as textPrompt, D as findSession, E as findGitRepositoryRoot, I as writeSessionRecord, M as normalizeName, O as findSessionByDirectoryWalk, Ot as AcpxOperationalError, R as parseSessionRecord, V as normalizeAgentSessionId, b as mergePromptSourceWithText, bt as EXIT_CODES, ct as defaultSessionEventLog, dt as sessionEventLockPath, ht as isProcessAlive, pt as writePrivateFile, u as probeQueueOwnerHealth, ut as sessionEventActivePath, v as PromptInputValidationError, wt as OUTPUT_FORMATS, x as parsePromptSource, z as serializeSessionRecordForDisk } from "./ipc-D2rstexT.js";
4
- import { X as getAcpxVersion, ct as normalizeOutputError, d as flushPerfMetricsCapture, et as listSessionEvents, f as installPerfMetricsCapture, i as runOnce, n as runSessionQueueOwner, nt as InterruptedError, rt as TimeoutError, s as DISCARD_OUTPUT_FORMATTER, st as exitCodeForOutputErrorCode, tt as isLegacyZedCodexAcpInvocation, u as buildQueueOwnerArgOverride } from "./queue-owner-runtime-Dgv3e2Tp.js";
5
- import { O as renderArgvIdentity, i as DEFAULT_AGENT_NAME, l as normalizeAgentName$1, s as listBuiltInAgents } from "./agent-registry-evUoJINz.js";
6
- import { C as resolvePermissionMode, S as resolveOutputPolicy, T as toTimerMilliseconds, _ as parseSessionName, a as addGlobalFlags, b as resolveAgentInvocation, c as addSessionOption, d as parseDaysOlderThan, f as parseHistoryLimit, g as parsePruneBeforeDate, h as parseOutputFormat$1, i as addExecConfigOption, m as parseNonEmptyValue, n as sessionConnectionOptions, o as addPromptInputOption, p as parseMaxTurns, r as sessionOptionsFromGlobalFlags, s as addSessionNameOption, t as resolvePermissionPolicyFromFlags, u as parseAllowedTools, v as parseTimeoutSeconds, w as resolveSessionNameFromFlags, x as resolveGlobalFlags, y as parseTtlSeconds } from "./invocation-options-eZEBh4vd.js";
2
+ import { n as getTextErrorRemediationHints, o as __exportAll, t as createOutputFormatter } from "./output-D6kDs8BN.js";
3
+ import { A as findGitRepositoryRoot, B as writeSessionRecord, D as textPrompt, G as normalizeAgentSessionId, H as parseSessionRecord, I as normalizeName, M as findSessionByDirectoryWalk, Mt as AcpxOperationalError, Ot as OUTPUT_FORMATS, P as listSessions, Pt as AgentSpawnError, S as PromptInputValidationError, T as parsePromptSource, U as serializeSessionRecordForDisk, _t as writePrivateFile, ft as defaultSessionEventLog, ht as sessionEventLockPath, j as findSession, mt as sessionEventActivePath, u as probeQueueOwnerHealth, w as mergePromptSourceWithText, wt as EXIT_CODES, yt as isProcessAlive } from "./ipc-fMgj5vrO.js";
4
+ import { $ as getAcpxVersion, at as InterruptedError, d as flushPerfMetricsCapture, dt as normalizeOutputError, f as installPerfMetricsCapture, i as runOnce, it as isLegacyZedCodexAcpInvocation, n as runSessionQueueOwner, ot as TimeoutError, rt as listSessionEvents, s as DISCARD_OUTPUT_FORMATTER, u as buildQueueOwnerArgOverride, ut as exitCodeForOutputErrorCode } from "./queue-owner-runtime-CLwjMYNL.js";
5
+ import { O as renderArgvIdentity, i as DEFAULT_AGENT_NAME, l as normalizeAgentName$1, s as listBuiltInAgents } from "./agent-registry-Ct2yWPW7.js";
6
+ import { C as resolvePermissionMode, D as toTimerMilliseconds, E as resolveSessionsListFlags, S as resolveOutputPolicy, T as resolveSessionNameFromFlags, _ as parseSessionName, a as addGlobalFlags, b as resolveAgentInvocation, c as addSessionOption, d as parseDaysOlderThan, f as parseHistoryLimit, g as parsePruneBeforeDate, h as parseOutputFormat$1, i as addExecConfigOption, m as parseNonEmptyValue, n as sessionConnectionOptions, o as addPromptInputOption, p as parseMaxTurns, r as sessionOptionsFromGlobalFlags, s as addSessionNameOption, t as resolvePermissionPolicyFromFlags, u as parseAllowedTools, v as parseTimeoutSeconds, w as resolvePromptFlags, x as resolveGlobalFlags, y as parseTtlSeconds } from "./invocation-options-DRzxHZmr.js";
7
7
  import { realpathSync } from "node:fs";
8
8
  import { fileURLToPath, pathToFileURL } from "node:url";
9
9
  import path from "node:path";
@@ -402,11 +402,11 @@ let sessionModulePromise;
402
402
  let outputModulePromise;
403
403
  let outputRenderModulePromise;
404
404
  function loadSessionModule() {
405
- sessionModulePromise ??= import("./output-D2xL6wdp.js").then((n) => n.a);
405
+ sessionModulePromise ??= import("./output-D6kDs8BN.js").then((n) => n.a);
406
406
  return sessionModulePromise;
407
407
  }
408
408
  function loadOutputModule() {
409
- outputModulePromise ??= import("./output-D2xL6wdp.js").then((n) => n.r);
409
+ outputModulePromise ??= import("./output-D6kDs8BN.js").then((n) => n.r);
410
410
  return outputModulePromise;
411
411
  }
412
412
  function loadOutputRenderModule() {
@@ -483,11 +483,12 @@ async function findRoutedSessionOrThrow(agentCommand, agentName, cwd, sessionNam
483
483
  throw new NoSessionError(`⚠ No acpx session found (searched up to ${walkBoundary}).\nCreate one: ${sessionName ? `acpx ${agentName} sessions new --name ${sessionName}` : `acpx ${agentName} sessions new`}`);
484
484
  }
485
485
  async function handlePrompt(explicitAgentName, promptParts, flags, command, config) {
486
+ const promptFlags = resolvePromptFlags(flags, command);
486
487
  const globalFlags = resolveGlobalFlags(command, config);
487
488
  const outputPolicy = resolveRequestedOutputPolicy(globalFlags);
488
489
  const permissionMode = resolvePermissionMode(globalFlags, config.defaultPermissions);
489
490
  const permissionPolicy = await resolvePermissionPolicyFromFlags(globalFlags);
490
- const prompt = await readPromptInput(flags.file, promptParts.join(" "), globalFlags.cwd);
491
+ const prompt = await readPromptInput(promptFlags.file, promptParts.join(" "), globalFlags.cwd);
491
492
  const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
492
493
  const [{ createOutputFormatter }, { printPromptSessionBanner, printQueuedPromptByFormat }, { sendSession }] = await Promise.all([
493
494
  loadOutputModule(),
@@ -514,7 +515,7 @@ async function handlePrompt(explicitAgentName, promptParts, flags, command, conf
514
515
  ttlMs: globalFlags.ttl,
515
516
  maxQueueDepth: config.queueMaxDepth,
516
517
  promptRetries: globalFlags.promptRetries,
517
- waitForCompletion: flags.wait !== false,
518
+ waitForCompletion: promptFlags.wait,
518
519
  sessionOptions: sessionOptionsFromGlobalFlags(globalFlags)
519
520
  });
520
521
  if ("queued" in result) {
@@ -525,24 +526,15 @@ async function handlePrompt(explicitAgentName, promptParts, flags, command, conf
525
526
  if (globalFlags.verbose && result.loadError) process.stderr.write(`[acpx] session reconnect failed, started fresh session: ${result.loadError}\n`);
526
527
  }
527
528
  async function handleExec(explicitAgentName, promptParts, flags, command, config) {
528
- if (config.disableExec) {
529
- if (resolveRequestedOutputPolicy(resolveGlobalFlags(command, config)).format === "json") process.stdout.write(`${JSON.stringify({
530
- jsonrpc: "2.0",
531
- error: {
532
- code: -32603,
533
- message: "exec subcommand is disabled by configuration (disableExec: true)",
534
- data: { acpxCode: "EXEC_DISABLED" }
535
- }
536
- })}\n`);
537
- else process.stderr.write("Error: exec subcommand is disabled by configuration (disableExec: true)\n");
538
- process.exitCode = 1;
539
- return;
540
- }
541
529
  const globalFlags = resolveGlobalFlags(command, config);
530
+ if (config.disableExec) throw new AcpxOperationalError("exec subcommand is disabled by configuration (disableExec: true)", {
531
+ outputCode: "EXEC_DISABLED",
532
+ origin: "cli"
533
+ });
542
534
  const outputPolicy = resolveRequestedOutputPolicy(globalFlags);
543
535
  const permissionMode = resolvePermissionMode(globalFlags, config.defaultPermissions);
544
536
  const permissionPolicy = await resolvePermissionPolicyFromFlags(globalFlags);
545
- const prompt = await readPromptInput(flags.file, promptParts.join(" "), globalFlags.cwd);
537
+ const prompt = await readPromptInput(resolvePromptFlags(flags, command).file, promptParts.join(" "), globalFlags.cwd);
546
538
  const [{ createOutputFormatter }, { runOnce }] = await Promise.all([loadOutputModule(), loadSessionModule()]);
547
539
  const outputFormatter = createOutputFormatter(outputPolicy.format, { suppressReads: outputPolicy.suppressReads });
548
540
  const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
@@ -694,17 +686,18 @@ async function tryListAgentSessions(agent, flags, globalFlags, config) {
694
686
  }
695
687
  }
696
688
  async function handleSessionsList(explicitAgentName, flags, command, config) {
689
+ const listFlags = resolveSessionsListFlags(flags, command);
697
690
  const globalFlags = resolveGlobalFlags(command, config);
698
691
  const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
699
- const filterCwd = resolveSessionListFilterCwd(flags, agent.cwd);
700
- if (flags.local) {
701
- if (flags.cursor) throw new InvalidArgumentError("--cursor cannot be combined with --local");
692
+ const filterCwd = resolveSessionListFilterCwd(listFlags, agent.cwd);
693
+ if (listFlags.local) {
694
+ if (listFlags.cursor) throw new InvalidArgumentError("--cursor cannot be combined with --local");
702
695
  await printLocalSessionsList(agent.agentCommand, filterCwd, globalFlags.format);
703
696
  return;
704
697
  }
705
- const [result, { printAgentSessionsByFormat }] = await Promise.all([tryListAgentSessions(agent, flags, globalFlags, config), loadOutputRenderModule()]);
698
+ const [result, { printAgentSessionsByFormat }] = await Promise.all([tryListAgentSessions(agent, listFlags, globalFlags, config), loadOutputRenderModule()]);
706
699
  if (!result || result === "spawn-failed") {
707
- if (result !== "spawn-failed" && (flags.cursor || flags.filterCwd)) throw new Error(`Agent command "${agent.agentCommand}" does not advertise sessionCapabilities.list; cannot use agent-side session/list filters`);
700
+ if (result !== "spawn-failed" && (listFlags.cursor || listFlags.filterCwd)) throw new Error(`Agent command "${agent.agentCommand}" does not advertise sessionCapabilities.list; cannot use agent-side session/list filters`);
708
701
  await printLocalSessionsList(agent.agentCommand, void 0, globalFlags.format);
709
702
  return;
710
703
  }
@@ -880,18 +873,19 @@ async function handleSessionsHistory(explicitAgentName, sessionName, flags, comm
880
873
  async function handleSessionsWatch(explicitAgentName, flags, command, config) {
881
874
  const globalFlags = resolveGlobalFlags(command, config);
882
875
  const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
876
+ const sessionName = resolveSessionNameFromFlags({ session: flags.name }, command);
883
877
  const scope = {
884
878
  agentCommand: agent.agentCommand,
885
879
  cwd: agent.cwd,
886
- name: flags.name,
880
+ name: sessionName,
887
881
  readOnly: true
888
882
  };
889
883
  const record = await findSession(scope) ?? await findSession({
890
884
  ...scope,
891
885
  includeClosed: true
892
886
  });
893
- if (!record) throw new Error(missingScopedSessionMessage(agent, flags.name));
894
- const { runSessionWatch } = await import("./session-watch-CTe9Bnbc.js");
887
+ if (!record) throw new Error(missingScopedSessionMessage(agent, sessionName));
888
+ const { runSessionWatch } = await import("./session-watch-BfdIo-n4.js");
895
889
  await runSessionWatch(record, {
896
890
  cursor: flags.cursor,
897
891
  policy: resolveRequestedOutputPolicy(globalFlags)
@@ -951,6 +945,37 @@ async function handleSessionsPrune(explicitAgentName, flags, command, config) {
951
945
  }), globalFlags.format);
952
946
  }
953
947
  //#endregion
948
+ //#region src/cli/compare-args.ts
949
+ function addCompareOptions(command) {
950
+ return command.option("--cwd <dir>", "Target workspace").option("--approve-all", "Auto-approve all permission requests").option("--approve-reads", "Auto-approve read/search requests and prompt for writes").option("--deny-all", "Deny all permission requests").option("--timeout <seconds>", "Per-agent timeout in seconds", parseTimeoutSeconds).option("--format <fmt>", "Output format: text, json, quiet", parseOutputFormat$1).option("--json", "Alias for --format json").option("-f, --file <path>", "Read prompt text from file path (use - for stdin)", (value) => parseNonEmptyValue("Prompt file", value)).option("--prompt-file <path>", "Alias for --file", (value) => parseNonEmptyValue("Prompt file", value));
951
+ }
952
+ const VALUE_FLAGS = new Set(addCompareOptions(new Command()).options.filter((option) => option.required).flatMap((option) => [option.long, option.short].filter((flag) => flag !== void 0)));
953
+ function captureCompareOutputFlag(output, token, nextToken) {
954
+ if (token === "--json") output.json = true;
955
+ else if (token === "--format") output.format = nextToken;
956
+ else if (token.startsWith("--format=")) output.format = token.slice(9);
957
+ }
958
+ function scanCompareArgs(argv) {
959
+ let cwd;
960
+ const output = {};
961
+ for (let index = 0; index < argv.length; index += 1) {
962
+ const token = argv[index];
963
+ if (token === "--") return {
964
+ cwd,
965
+ ...output,
966
+ promptTokens: argv.slice(index + 1)
967
+ };
968
+ if (token === "--cwd") cwd = argv[index + 1];
969
+ else if (token.startsWith("--cwd=")) cwd = token.slice(6);
970
+ captureCompareOutputFlag(output, token, argv[index + 1]);
971
+ if (VALUE_FLAGS.has(token)) index += 1;
972
+ }
973
+ return {
974
+ cwd,
975
+ ...output
976
+ };
977
+ }
978
+ //#endregion
954
979
  //#region src/cli/compare-command.ts
955
980
  const DEFAULT_COMPARE_TIMEOUT_MS = 3e5;
956
981
  const FINAL_MESSAGE_PREVIEW_CHARS = 200;
@@ -972,14 +997,15 @@ function truncate(value, maxChars) {
972
997
  if (value.length <= maxChars) return value;
973
998
  return `${value.slice(0, Math.max(0, maxChars - 3))}...`;
974
999
  }
975
- function promptTokensAfterDoubleDash(command) {
976
- const commandName = command.name();
977
- const commandIndex = process.argv.findIndex((token, index) => index >= 2 && token === commandName);
978
- if (commandIndex < 0) return [];
979
- const delimiterIndex = process.argv.findIndex((token, index) => index > commandIndex && token === "--");
980
- return delimiterIndex < 0 ? [] : process.argv.slice(delimiterIndex + 1);
981
- }
982
- function splitCompareArgs(args, filePath, command) {
1000
+ function splitCompareArgs(args, filePath, promptTokens) {
1001
+ if (promptTokens !== void 0) {
1002
+ const agents = args.slice(0, args.length - promptTokens.length);
1003
+ if (agents.length === 0) throw new InvalidArgumentError("At least one agent is required");
1004
+ return {
1005
+ agents,
1006
+ promptText: promptTokens.join(" ")
1007
+ };
1008
+ }
983
1009
  if (filePath) {
984
1010
  if (args.length === 0) throw new InvalidArgumentError("At least one agent is required");
985
1011
  return {
@@ -987,15 +1013,6 @@ function splitCompareArgs(args, filePath, command) {
987
1013
  promptText: ""
988
1014
  };
989
1015
  }
990
- const promptTokens = promptTokensAfterDoubleDash(command);
991
- if (promptTokens.length > 0) {
992
- const agents = args.slice(0, -promptTokens.length);
993
- if (agents.length === 0) throw new InvalidArgumentError("At least one agent is required");
994
- return {
995
- agents,
996
- promptText: promptTokens.join(" ")
997
- };
998
- }
999
1016
  if (args.length < 2) throw new InvalidArgumentError("Usage: acpx compare <agent>... '<prompt>'");
1000
1017
  return {
1001
1018
  agents: args.slice(0, -1),
@@ -1007,12 +1024,7 @@ function captureUsage(update, capture) {
1007
1024
  capture.usage = {
1008
1025
  input_tokens: numberField(source, ["input_tokens", "inputTokens"]) ?? void 0,
1009
1026
  output_tokens: numberField(source, ["output_tokens", "outputTokens"]) ?? void 0,
1010
- total_tokens: numberField(source, [
1011
- "total_tokens",
1012
- "totalTokens",
1013
- "size",
1014
- "used"
1015
- ]) ?? void 0
1027
+ total_tokens: numberField(source, ["total_tokens", "totalTokens"]) ?? void 0
1016
1028
  };
1017
1029
  }
1018
1030
  function captureSessionUpdate(notification, capture) {
@@ -1149,22 +1161,53 @@ function updateCompareExitCode(rows) {
1149
1161
  }
1150
1162
  if (rows.some((row) => row.status === "cancelled")) process.exitCode = EXIT_CODES.TIMEOUT;
1151
1163
  }
1164
+ async function runCompareAgents(agents, run) {
1165
+ const rows = [];
1166
+ let interrupted = false;
1167
+ const onInterrupt = () => {
1168
+ interrupted = true;
1169
+ };
1170
+ const signals = [
1171
+ "SIGINT",
1172
+ "SIGTERM",
1173
+ "SIGHUP"
1174
+ ];
1175
+ for (const signal of signals) process.once(signal, onInterrupt);
1176
+ try {
1177
+ for (const agentName of agents) {
1178
+ if (interrupted) break;
1179
+ const row = await run(agentName);
1180
+ rows.push(interrupted ? {
1181
+ ...row,
1182
+ status: "cancelled",
1183
+ error: "Interrupted"
1184
+ } : row);
1185
+ }
1186
+ } finally {
1187
+ for (const signal of signals) process.off(signal, onInterrupt);
1188
+ }
1189
+ return {
1190
+ rows,
1191
+ interrupted
1192
+ };
1193
+ }
1152
1194
  function resolvePromptFile(flags) {
1153
1195
  if (flags.file && flags.promptFile && flags.file !== flags.promptFile) throw new InvalidArgumentError("Use only one prompt file flag: --file or --prompt-file");
1154
1196
  return flags.file ?? flags.promptFile;
1155
1197
  }
1156
1198
  function registerCompareCommand(program, config) {
1157
- program.command("compare").description("Run one prompt across multiple agents and summarize the results").argument("<args...>", "Agents followed by prompt text, or agents with --file").option("--cwd <dir>", "Target workspace").option("--approve-all", "Auto-approve all permission requests").option("--approve-reads", "Auto-approve read/search requests and prompt for writes").option("--deny-all", "Deny all permission requests").option("--timeout <seconds>", "Per-agent timeout in seconds", parseTimeoutSeconds).option("--format <fmt>", "Output format: text, json, quiet", parseOutputFormat$1).option("--json", "Alias for --format json").option("-f, --file <path>", "Read prompt text from file path (use - for stdin)", (value) => parseNonEmptyValue("Prompt file", value)).option("--prompt-file <path>", "Alias for --file", (value) => parseNonEmptyValue("Prompt file", value)).action(async function(args, flags) {
1199
+ addCompareOptions(program.command("compare").description("Run one prompt across multiple agents and summarize the results").argument("<args...>", "Agents followed by prompt text, or agents with --file")).action(async function(args, flags) {
1158
1200
  if (config.disableExec) throw new Error("compare subcommand is disabled by configuration (disableExec: true)");
1159
1201
  const globalFlags = resolveGlobalFlags(this, config);
1202
+ if (flags.cwd !== void 0) globalFlags.cwd = path.resolve(flags.cwd);
1160
1203
  if (globalFlags.agent) throw new InvalidArgumentError("Do not combine compare with --agent; pass agent names");
1161
- const outputPolicy = resolveOutputPolicy(flags.json === true ? "json" : globalFlags.format, globalFlags.jsonStrict === true);
1204
+ const outputPolicy = resolveOutputPolicy(globalFlags.format, globalFlags.jsonStrict === true);
1162
1205
  const promptFile = resolvePromptFile(flags);
1163
- const { agents, promptText } = splitCompareArgs(args, promptFile, this);
1206
+ const { promptTokens } = scanCompareArgs(program.args.slice(1));
1207
+ const { agents, promptText } = splitCompareArgs(args, promptFile, promptTokens);
1164
1208
  const prompt = await readPromptInput(promptFile, promptText, globalFlags.cwd, "final argument");
1165
1209
  const permissionPolicy = await resolvePermissionPolicyFromFlags(globalFlags);
1166
- const rows = [];
1167
- for (const agentName of agents) rows.push(await runAgentForCompare({
1210
+ const { rows, interrupted } = await runCompareAgents(agents, async (agentName) => await runAgentForCompare({
1168
1211
  agentName,
1169
1212
  prompt,
1170
1213
  config,
@@ -1172,7 +1215,8 @@ function registerCompareCommand(program, config) {
1172
1215
  permissionPolicy
1173
1216
  }));
1174
1217
  printRows(rows, outputPolicy.format);
1175
- updateCompareExitCode(rows);
1218
+ if (interrupted) process.exitCode = EXIT_CODES.INTERRUPTED;
1219
+ else updateCompareExitCode(rows);
1176
1220
  });
1177
1221
  }
1178
1222
  //#endregion
@@ -1185,6 +1229,10 @@ function parseNonEmptyString(value, path) {
1185
1229
  if (typeof value !== "string" || value.trim().length === 0) throw new Error(`Invalid ${path}: expected non-empty string`);
1186
1230
  return value.trim();
1187
1231
  }
1232
+ function parseString(value, path) {
1233
+ if (typeof value !== "string") throw new Error(`Invalid ${path}: expected string`);
1234
+ return value;
1235
+ }
1188
1236
  function parseNameValuePairs(value, path) {
1189
1237
  if (value == null) return [];
1190
1238
  if (!Array.isArray(value)) throw new Error(`Invalid ${path}: expected array`);
@@ -1194,7 +1242,7 @@ function parseNameValuePairs(value, path) {
1194
1242
  if (!entry) throw new Error(`Invalid ${path}[${index}]: expected object`);
1195
1243
  entries.push({
1196
1244
  name: parseNonEmptyString(entry.name, `${path}[${index}].name`),
1197
- value: parseNonEmptyString(entry.value, `${path}[${index}].value`)
1245
+ value: parseString(entry.value, `${path}[${index}].value`)
1198
1246
  });
1199
1247
  }
1200
1248
  return entries;
@@ -1203,10 +1251,7 @@ function parseArgs(value, path) {
1203
1251
  if (value == null) return [];
1204
1252
  if (!Array.isArray(value)) throw new Error(`Invalid ${path}: expected array`);
1205
1253
  const args = [];
1206
- for (const [index, rawArg] of value.entries()) {
1207
- if (typeof rawArg !== "string") throw new Error(`Invalid ${path}[${index}]: expected string`);
1208
- args.push(rawArg);
1209
- }
1254
+ for (const [index, rawArg] of value.entries()) args.push(parseString(rawArg, `${path}[${index}]`));
1210
1255
  return args;
1211
1256
  }
1212
1257
  function parseMeta(value, path) {
@@ -1336,9 +1381,7 @@ function parseDefaultAgent(value, sourcePath) {
1336
1381
  function parseAgents(value, sourcePath) {
1337
1382
  if (value == null) return;
1338
1383
  if (!isObject(value)) throw new Error(`Invalid config agents in ${sourcePath}: expected object`);
1339
- const parsed = {};
1340
- for (const [name, raw] of Object.entries(value)) parsed[normalizeAgentName$1(name)] = parseAgentEntry(raw, name, sourcePath);
1341
- return parsed;
1384
+ return Object.fromEntries(Object.entries(value).map(([name, raw]) => [normalizeAgentName$1(name), parseAgentEntry(raw, name, sourcePath)]));
1342
1385
  }
1343
1386
  function parseAgentEntry(raw, name, sourcePath) {
1344
1387
  if (!isObject(raw)) throw new Error(`Invalid config agents.${name} in ${sourcePath}: expected object with command`);
@@ -1490,8 +1533,7 @@ function resolveMcpServers(projectConfig, projectPath, globalConfig, globalPath,
1490
1533
  return [];
1491
1534
  }
1492
1535
  function toConfigDisplay(config) {
1493
- const agents = {};
1494
- for (const [name, agent] of Object.entries(config.agents)) agents[name] = agent.argv ? { argv: [...agent.argv] } : { command: agent.command };
1536
+ const agents = Object.fromEntries(Object.entries(config.agents).map(([name, agent]) => [name, agent.argv ? { argv: [...agent.argv] } : { command: agent.command }]));
1495
1537
  return {
1496
1538
  defaultAgent: config.defaultAgent,
1497
1539
  defaultPermissions: config.defaultPermissions,
@@ -2074,7 +2116,7 @@ function registerAgentCommand(program, agentName, config) {
2074
2116
  }
2075
2117
  function registerFlowCommand(program, config) {
2076
2118
  program.command("flow").description("Run multi-step ACP workflows from flow files").command("run").description("Run a flow file").argument("<file>", "Flow module path").option("--input-json <json>", "Flow input as JSON").option("--input-file <path>", "Read flow input JSON from file").option("--default-agent <name>", "Default agent profile for ACP nodes without profile", (value) => parseNonEmptyValue("Default agent", value)).action(async function(file, flags) {
2077
- const { handleFlowRun } = await import("./cli-B2ycKzaO.js");
2119
+ const { handleFlowRun } = await import("./cli-Bmki9cj5.js");
2078
2120
  await handleFlowRun(file, flags, this, config);
2079
2121
  });
2080
2122
  }
@@ -2280,57 +2322,41 @@ function detectAgentToken(argv) {
2280
2322
  for (let index = 0; index < argv.length; index += 1) {
2281
2323
  const token = argv[index];
2282
2324
  const step = scanAgentTokenStep(token, hasAgentOverride);
2283
- if (step.result) return step.result;
2325
+ if (step.result) return {
2326
+ ...step.result,
2327
+ index
2328
+ };
2284
2329
  if (step.hasAgentOverride) hasAgentOverride = true;
2285
2330
  index += step.indexDelta;
2286
2331
  }
2287
2332
  return { hasAgentOverride };
2288
2333
  }
2289
- function detectInitialCwd(argv) {
2334
+ function lastTopLevelFlagValue(argv, flag) {
2335
+ let value;
2290
2336
  for (let index = 0; index < argv.length; index += 1) {
2291
2337
  const token = argv[index];
2292
2338
  const scan = classifyTopLevelFlagScan(token);
2293
2339
  if (scan.stop) break;
2294
- const cwd = readCwdFlagValue(token, argv[index + 1]);
2295
- if (cwd) return path.resolve(cwd);
2296
- if (isCwdFlagToken(token)) break;
2340
+ if (token === flag) value = argv[index + 1];
2341
+ else if (token.startsWith(`${flag}=`)) value = token.slice(flag.length + 1);
2297
2342
  if (scan.skipNext) index += 1;
2298
2343
  }
2299
- return process.cwd();
2344
+ return value;
2300
2345
  }
2301
- function detectMcpConfigPath(argv, cwd) {
2302
- for (let index = 0; index < argv.length; index += 1) {
2303
- const scan = scanMcpConfigToken(argv[index], argv[index + 1], cwd);
2304
- if (scan.stop) return scan.path;
2305
- if (scan.skipNext) index += 1;
2346
+ function detectInitialCwd(argv) {
2347
+ const command = detectAgentToken(argv);
2348
+ if (command.token === "compare" && command.index !== void 0) {
2349
+ const { cwd } = scanCompareArgs(argv.slice(command.index + 1));
2350
+ if (cwd !== void 0) return path.resolve(cwd);
2306
2351
  }
2352
+ return path.resolve(lastTopLevelFlagValue(argv, "--cwd") ?? process.cwd());
2307
2353
  }
2308
- function scanMcpConfigToken(token, nextToken, cwd) {
2309
- if (token === "--" || !token.startsWith("-") || token === "-") return { stop: true };
2310
- if (token === "--mcp-config") return {
2311
- path: resolveMcpConfigPath(nextToken, cwd),
2312
- stop: true
2313
- };
2314
- if (token.startsWith("--mcp-config=")) return {
2315
- path: resolveMcpConfigPath(token.slice(13), cwd),
2316
- stop: true
2317
- };
2318
- return { skipNext: TOP_LEVEL_VERSION_VALUE_FLAGS.has(token) };
2319
- }
2320
- function resolveMcpConfigPath(value, cwd) {
2321
- const trimmed = value?.trim();
2322
- return trimmed && trimmed !== "--" ? path.resolve(cwd, trimmed) : void 0;
2323
- }
2324
- function isCwdFlagToken(token) {
2325
- return token === "--cwd" || token.startsWith("--cwd=");
2326
- }
2327
- function readCwdFlagValue(token, nextToken) {
2328
- const value = (token === "--cwd" ? nextToken : readInlineFlagValue(token, "--cwd"))?.trim();
2329
- if (!value || value === "--") return;
2330
- return value;
2354
+ function detectMcpConfigPath(argv, cwd) {
2355
+ const value = lastTopLevelFlagValue(argv, "--mcp-config");
2356
+ return value ? path.resolve(cwd, value) : void 0;
2331
2357
  }
2332
2358
  function detectRequestedOutputFormat(argv, fallback) {
2333
- let detectedFormat = fallback;
2359
+ let detectedFormat;
2334
2360
  for (let index = 0; index < argv.length; index += 1) {
2335
2361
  const token = argv[index];
2336
2362
  const scan = classifyTopLevelFlagScan(token);
@@ -2340,7 +2366,14 @@ function detectRequestedOutputFormat(argv, fallback) {
2340
2366
  if (format) detectedFormat = format;
2341
2367
  if (scan.skipNext) index += 1;
2342
2368
  }
2343
- return detectedFormat;
2369
+ return detectCompareOutputFormat(argv, detectedFormat, fallback);
2370
+ }
2371
+ function detectCompareOutputFormat(argv, rootFormat, fallback) {
2372
+ const command = detectAgentToken(argv);
2373
+ if (command.token !== "compare" || command.index === void 0) return rootFormat ?? fallback;
2374
+ const local = scanCompareArgs(argv.slice(command.index + 1));
2375
+ const localFormat = isOutputFormat(local.format) ? local.format : void 0;
2376
+ return local.json ? "json" : rootFormat ?? localFormat ?? fallback;
2344
2377
  }
2345
2378
  function classifyTopLevelFlagScan(token) {
2346
2379
  if (token === "--" || !token.startsWith("-") || token === "-") return {
@@ -2487,34 +2520,37 @@ async function main(argv = process.argv) {
2487
2520
  return;
2488
2521
  }
2489
2522
  await maybeHandleSkillflag(normalizedArgv);
2490
- const initialCwd = detectInitialCwd(rawArgs);
2491
- const config = await loadResolvedConfig(initialCwd, { mcpConfigPath: detectMcpConfigPath(rawArgs, initialCwd) });
2492
2523
  const requestedJsonStrict = detectJsonStrict(rawArgs);
2493
- const requestedOutputFormat = detectRequestedOutputFormat(rawArgs, config.format);
2494
- const requestedOutputPolicy = {
2495
- ...resolveOutputPolicy(requestedOutputFormat, requestedJsonStrict),
2524
+ let requestedOutputPolicy = {
2525
+ ...resolveOutputPolicy(detectRequestedOutputFormat(rawArgs, "text"), requestedJsonStrict),
2496
2526
  suppressReads: rawArgs.some((token) => token === "--suppress-reads")
2497
2527
  };
2498
- const program = createProgram(requestedJsonStrict);
2499
- addGlobalFlags(program);
2500
- configurePublicCli({
2501
- program,
2502
- argv: rawArgs,
2503
- config,
2504
- requestedJsonStrict,
2505
- topLevelVerbs: TOP_LEVEL_VERBS,
2506
- listBuiltInAgents,
2507
- detectAgentToken,
2508
- registerAgentCommand,
2509
- registerDefaultCommands,
2510
- handlePromptAction: async (command, promptParts) => {
2511
- await handlePrompt(void 0, promptParts, {}, command, config);
2512
- }
2513
- });
2514
- program.exitOverride((error) => {
2515
- throw error;
2516
- });
2517
2528
  try {
2529
+ const initialCwd = detectInitialCwd(rawArgs);
2530
+ const config = await loadResolvedConfig(initialCwd, { mcpConfigPath: detectMcpConfigPath(rawArgs, initialCwd) });
2531
+ requestedOutputPolicy = {
2532
+ ...resolveOutputPolicy(detectRequestedOutputFormat(rawArgs, config.format), requestedJsonStrict),
2533
+ suppressReads: requestedOutputPolicy.suppressReads
2534
+ };
2535
+ const program = createProgram(requestedJsonStrict);
2536
+ addGlobalFlags(program);
2537
+ configurePublicCli({
2538
+ program,
2539
+ argv: rawArgs,
2540
+ config,
2541
+ requestedJsonStrict,
2542
+ topLevelVerbs: TOP_LEVEL_VERBS,
2543
+ listBuiltInAgents,
2544
+ detectAgentToken,
2545
+ registerAgentCommand,
2546
+ registerDefaultCommands,
2547
+ handlePromptAction: async (command, promptParts) => {
2548
+ await handlePrompt(void 0, promptParts, {}, command, config);
2549
+ }
2550
+ });
2551
+ program.exitOverride((error) => {
2552
+ throw error;
2553
+ });
2518
2554
  await program.parseAsync(normalizedArgv);
2519
2555
  } catch (error) {
2520
2556
  await handleProgramParseError(error, requestedOutputPolicy);