acpx 0.10.0 → 0.11.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 (33) hide show
  1. package/README.md +22 -19
  2. package/dist/{cli-8dP_TqBp.js → cli-CC2w0U-A.js} +4 -4
  3. package/dist/{cli-8dP_TqBp.js.map → cli-CC2w0U-A.js.map} +1 -1
  4. package/dist/cli.d.ts +1 -1
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +299 -61
  7. package/dist/cli.js.map +1 -1
  8. package/dist/{client-C4iJBO0j.d.ts → client-j3sLnpcM.d.ts} +27 -4
  9. package/dist/client-j3sLnpcM.d.ts.map +1 -0
  10. package/dist/{flags--2oX_ubW.js → flags-BKjjl3tF.js} +4 -4
  11. package/dist/flags-BKjjl3tF.js.map +1 -0
  12. package/dist/{flows-e4umXVbY.js → flows-BabqiU0u.js} +4 -3
  13. package/dist/flows-BabqiU0u.js.map +1 -0
  14. package/dist/flows.d.ts +1 -1
  15. package/dist/flows.d.ts.map +1 -1
  16. package/dist/flows.js +1 -1
  17. package/dist/{live-checkpoint-CuFft_Nd.js → live-checkpoint-BZrk9Mjz.js} +646 -164
  18. package/dist/live-checkpoint-BZrk9Mjz.js.map +1 -0
  19. package/dist/{output-Di77Yugq.js → output-D_BGt1YI.js} +170 -88
  20. package/dist/output-D_BGt1YI.js.map +1 -0
  21. package/dist/runtime.d.ts +71 -5
  22. package/dist/runtime.d.ts.map +1 -1
  23. package/dist/runtime.js +188 -32
  24. package/dist/runtime.js.map +1 -1
  25. package/dist/{session-options-Bh1bIqQ2.d.ts → session-options-Co1oGEK8.d.ts} +15 -2
  26. package/dist/{session-options-Bh1bIqQ2.d.ts.map → session-options-Co1oGEK8.d.ts.map} +1 -1
  27. package/package.json +17 -17
  28. package/skills/acpx/SKILL.md +55 -3
  29. package/dist/client-C4iJBO0j.d.ts.map +0 -1
  30. package/dist/flags--2oX_ubW.js.map +0 -1
  31. package/dist/flows-e4umXVbY.js.map +0 -1
  32. package/dist/live-checkpoint-CuFft_Nd.js.map +0 -1
  33. package/dist/output-Di77Yugq.js.map +0 -1
package/dist/cli.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { a as runSessionQueueOwner, c as buildQueueOwnerArgOverride, g as __exportAll, h as isProcessAlive, l as flushPerfMetricsCapture, n as getTextErrorRemediationHints, p as probeQueueOwnerHealth, t as createOutputFormatter, u as installPerfMetricsCapture } from "./output-Di77Yugq.js";
3
- import { $ as defaultSessionEventLog, A as findGitRepositoryRoot, At as EXIT_CODES, I as normalizeName, M as findSessionByDirectoryWalk, P as listSessions, Pt as OUTPUT_FORMATS, Rt as AcpxOperationalError, St as exitCodeForOutputErrorCode, Tt as normalizeOutputError, X as serializeSessionRecordForDisk, Y as parseSessionRecord, Z as normalizeRuntimeSessionId, at as isAcpJsonRpcMessage, bt as normalizeAgentName$1, ct as PromptInputValidationError, dt as parsePromptSource, j as findSession, mt as InterruptedError, nt as sessionEventLockPath, pt as textPrompt, rt as sessionEventSegmentPath, tt as sessionEventActivePath, ut as mergePromptSourceWithText, vt as DEFAULT_AGENT_NAME, yt as listBuiltInAgents, z as writeSessionRecord, zt as AgentSpawnError } from "./live-checkpoint-CuFft_Nd.js";
4
- import { _ as resolveOutputPolicy, b as loadPermissionPolicySpec, c as parseHistoryLimit, d as parseOutputFormat$1, f as parsePruneBeforeDate, g as resolveGlobalFlags, h as resolveAgentInvocation, i as addSessionOption, l as parseMaxTurns, m as parseTtlSeconds, n as addPromptInputOption, o as parseAllowedTools, p as parseSessionName, r as addSessionNameOption, s as parseDaysOlderThan, t as addGlobalFlags, u as parseNonEmptyValue, v as resolvePermissionMode, y as resolveSessionNameFromFlags } from "./flags--2oX_ubW.js";
5
- import { readFileSync, realpathSync } from "node:fs";
2
+ import { a as runSessionQueueOwner, c as buildQueueOwnerArgOverride, g as __exportAll, h as isProcessAlive, l as flushPerfMetricsCapture, n as getTextErrorRemediationHints, o as runOnce, p as probeQueueOwnerHealth, t as createOutputFormatter, u as installPerfMetricsCapture } from "./output-D_BGt1YI.js";
3
+ import { B as listSessions, Bt as OUTPUT_FORMATS, Et as normalizeAgentName$1, G as writeSessionRecord, Gt as AgentSpawnError, H as normalizeName, I as findGitRepositoryRoot, It as EXIT_CODES, L as findSession, M as getAcpxVersion, Ot as exitCodeForOutputErrorCode, R as findSessionByDirectoryWalk, Tt as listBuiltInAgents, Wt as AcpxOperationalError, _t as parsePromptSource, at as defaultSessionEventLog, bt as InterruptedError, ct as sessionEventLockPath, dt as isAcpJsonRpcMessage, gt as mergePromptSourceWithText, jt as normalizeOutputError, lt as sessionEventSegmentPath, mt as PromptInputValidationError, nt as serializeSessionRecordForDisk, rt as normalizeRuntimeSessionId, st as sessionEventActivePath, tt as parseSessionRecord, wt as DEFAULT_AGENT_NAME, xt as TimeoutError, yt as textPrompt } from "./live-checkpoint-BZrk9Mjz.js";
4
+ import { _ as resolveGlobalFlags, b as resolveSessionNameFromFlags, c as parseHistoryLimit, d as parseOutputFormat$1, f as parsePruneBeforeDate, g as resolveAgentInvocation, h as parseTtlSeconds, i as addSessionOption, l as parseMaxTurns, m as parseTimeoutSeconds, n as addPromptInputOption, o as parseAllowedTools, p as parseSessionName, r as addSessionNameOption, s as parseDaysOlderThan, t as addGlobalFlags, u as parseNonEmptyValue, v as resolveOutputPolicy, x as loadPermissionPolicySpec, y as resolvePermissionMode } from "./flags-BKjjl3tF.js";
5
+ import { realpathSync } from "node:fs";
6
6
  import { fileURLToPath, pathToFileURL } from "node:url";
7
7
  import path from "node:path";
8
8
  import { Command, CommanderError, InvalidArgumentError, Option } from "commander";
@@ -10,6 +10,7 @@ import fs$1 from "node:fs/promises";
10
10
  import os from "node:os";
11
11
  import { randomUUID } from "node:crypto";
12
12
  import { ZodError, z } from "zod";
13
+ import { performance } from "node:perf_hooks";
13
14
  //#region src/cli-public.ts
14
15
  function configurePublicCli(options) {
15
16
  const builtInAgents = options.listBuiltInAgents(options.config.agents);
@@ -386,11 +387,11 @@ let sessionModulePromise;
386
387
  let outputModulePromise;
387
388
  let outputRenderModulePromise;
388
389
  function loadSessionModule() {
389
- sessionModulePromise ??= import("./output-Di77Yugq.js").then((n) => n.i);
390
+ sessionModulePromise ??= import("./output-D_BGt1YI.js").then((n) => n.i);
390
391
  return sessionModulePromise;
391
392
  }
392
393
  function loadOutputModule() {
393
- outputModulePromise ??= import("./output-Di77Yugq.js").then((n) => n.r);
394
+ outputModulePromise ??= import("./output-D_BGt1YI.js").then((n) => n.r);
394
395
  return outputModulePromise;
395
396
  }
396
397
  function loadOutputRenderModule() {
@@ -436,7 +437,7 @@ function resolveRequestedOutputPolicy(globalFlags) {
436
437
  suppressReads: globalFlags.suppressReads === true
437
438
  };
438
439
  }
439
- function sessionOptionsFromGlobalFlags(globalFlags) {
440
+ function sessionOptionsFromGlobalFlags$1(globalFlags) {
440
441
  return {
441
442
  model: globalFlags.model,
442
443
  allowedTools: globalFlags.allowedTools,
@@ -444,7 +445,7 @@ function sessionOptionsFromGlobalFlags(globalFlags) {
444
445
  systemPrompt: globalFlags.systemPrompt
445
446
  };
446
447
  }
447
- async function resolvePermissionPolicyFromFlags(globalFlags) {
448
+ async function resolvePermissionPolicyFromFlags$1(globalFlags) {
448
449
  try {
449
450
  return await loadPermissionPolicySpec(globalFlags.permissionPolicy, globalFlags.cwd);
450
451
  } catch (error) {
@@ -466,7 +467,8 @@ function buildSessionStartOptions(params) {
466
467
  terminal: params.globalFlags.terminal,
467
468
  timeoutMs: params.globalFlags.timeout,
468
469
  verbose: params.globalFlags.verbose,
469
- sessionOptions: sessionOptionsFromGlobalFlags(params.globalFlags)
470
+ sessionOptions: sessionOptionsFromGlobalFlags$1(params.globalFlags),
471
+ onModelWarning: params.globalFlags.jsonStrict ? void 0 : (message) => process.stderr.write(`[acpx] warning: ${message}\n`)
470
472
  };
471
473
  }
472
474
  function resolveSessionListFilterCwd(flags, agentCwd) {
@@ -505,7 +507,7 @@ async function handlePrompt(explicitAgentName, promptParts, flags, command, conf
505
507
  const globalFlags = resolveGlobalFlags(command, config);
506
508
  const outputPolicy = resolveRequestedOutputPolicy(globalFlags);
507
509
  const permissionMode = resolvePermissionMode(globalFlags, config.defaultPermissions);
508
- const permissionPolicy = await resolvePermissionPolicyFromFlags(globalFlags);
510
+ const permissionPolicy = await resolvePermissionPolicyFromFlags$1(globalFlags);
509
511
  const prompt = await readPrompt(promptParts, flags.file, globalFlags.cwd);
510
512
  const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
511
513
  const [{ createOutputFormatter }, { printPromptSessionBanner, printQueuedPromptByFormat }, { sendSession }] = await Promise.all([
@@ -513,7 +515,7 @@ async function handlePrompt(explicitAgentName, promptParts, flags, command, conf
513
515
  loadOutputRenderModule(),
514
516
  loadSessionModule()
515
517
  ]);
516
- const record = await findRoutedSessionOrThrow(agent.agentCommand, agent.agentName, agent.cwd, flags.session);
518
+ const record = await findRoutedSessionOrThrow(agent.agentCommand, agent.agentName, agent.cwd, resolveSessionNameFromFlags(flags, command));
517
519
  const outputFormatter = createOutputFormatter(outputPolicy.format, {
518
520
  jsonContext: { sessionId: record.acpxRecordId },
519
521
  suppressReads: outputPolicy.suppressReads
@@ -569,7 +571,7 @@ async function handleExec(explicitAgentName, promptParts, flags, command, config
569
571
  const globalFlags = resolveGlobalFlags(command, config);
570
572
  const outputPolicy = resolveRequestedOutputPolicy(globalFlags);
571
573
  const permissionMode = resolvePermissionMode(globalFlags, config.defaultPermissions);
572
- const permissionPolicy = await resolvePermissionPolicyFromFlags(globalFlags);
574
+ const permissionPolicy = await resolvePermissionPolicyFromFlags$1(globalFlags);
573
575
  const prompt = await readPrompt(promptParts, flags.file, globalFlags.cwd);
574
576
  const [{ createOutputFormatter }, { runOnce }] = await Promise.all([loadOutputModule(), loadSessionModule()]);
575
577
  const outputFormatter = createOutputFormatter(outputPolicy.format, { suppressReads: outputPolicy.suppressReads });
@@ -726,7 +728,7 @@ async function handleSetConfigOption(explicitAgentName, configId, value, flags,
726
728
  }
727
729
  async function tryListAgentSessions(agent, flags, globalFlags, config) {
728
730
  const permissionMode = resolvePermissionMode(globalFlags, config.defaultPermissions);
729
- const permissionPolicy = await resolvePermissionPolicyFromFlags(globalFlags);
731
+ const permissionPolicy = await resolvePermissionPolicyFromFlags$1(globalFlags);
730
732
  const { listAgentSessions } = await loadSessionModule();
731
733
  try {
732
734
  return await listAgentSessions({
@@ -781,7 +783,7 @@ async function handleSessionsClose(explicitAgentName, sessionName, command, conf
781
783
  async function handleSessionsNew(explicitAgentName, flags, command, config) {
782
784
  const globalFlags = resolveGlobalFlags(command, config);
783
785
  const permissionMode = resolvePermissionMode(globalFlags, config.defaultPermissions);
784
- const permissionPolicy = await resolvePermissionPolicyFromFlags(globalFlags);
786
+ const permissionPolicy = await resolvePermissionPolicyFromFlags$1(globalFlags);
785
787
  const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
786
788
  const [{ createSession, closeSession }, { printCreatedSessionBanner, printNewSessionByFormat }] = await Promise.all([loadSessionModule(), loadOutputRenderModule()]);
787
789
  const replaced = await findSession({
@@ -811,7 +813,7 @@ async function handleSessionsNew(explicitAgentName, flags, command, config) {
811
813
  async function handleSessionsEnsure(explicitAgentName, flags, command, config) {
812
814
  const globalFlags = resolveGlobalFlags(command, config);
813
815
  const permissionMode = resolvePermissionMode(globalFlags, config.defaultPermissions);
814
- const permissionPolicy = await resolvePermissionPolicyFromFlags(globalFlags);
816
+ const permissionPolicy = await resolvePermissionPolicyFromFlags$1(globalFlags);
815
817
  const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
816
818
  const [{ ensureSession }, { printCreatedSessionBanner, printEnsuredSessionByFormat }] = await Promise.all([loadSessionModule(), loadOutputRenderModule()]);
817
819
  const result = await ensureSession(buildSessionStartOptions({
@@ -987,6 +989,285 @@ async function handleSessionsPrune(explicitAgentName, flags, command, config) {
987
989
  }), globalFlags.format);
988
990
  }
989
991
  //#endregion
992
+ //#region src/cli/compare-command.ts
993
+ const DEFAULT_COMPARE_TIMEOUT_MS = 3e5;
994
+ const FINAL_MESSAGE_PREVIEW_CHARS = 200;
995
+ var CaptureFormatter = class {
996
+ setContext(_context) {}
997
+ onAcpMessage(_message) {}
998
+ onError(params) {}
999
+ onPermissionEscalation(_event) {}
1000
+ flush() {}
1001
+ };
1002
+ function asRecord$2(value) {
1003
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value) ? value : void 0;
1004
+ }
1005
+ function numberField(source, keys) {
1006
+ if (!source) return null;
1007
+ for (const key of keys) {
1008
+ const value = source[key];
1009
+ if (typeof value === "number" && Number.isFinite(value)) return value;
1010
+ }
1011
+ return null;
1012
+ }
1013
+ function collapseWhitespace(value) {
1014
+ return value.replace(/\s+/g, " ").trim();
1015
+ }
1016
+ function truncate(value, maxChars) {
1017
+ if (value.length <= maxChars) return value;
1018
+ return `${value.slice(0, Math.max(0, maxChars - 3))}...`;
1019
+ }
1020
+ async function readStdin() {
1021
+ let data = "";
1022
+ for await (const chunk of process.stdin) data += String(chunk);
1023
+ return data;
1024
+ }
1025
+ async function readPromptFile(filePath, promptText, cwd) {
1026
+ const prompt = mergePromptSourceWithText(filePath === "-" ? await readStdin() : await fs$1.readFile(path.resolve(cwd, filePath), "utf8"), promptText);
1027
+ if (prompt.length === 0) throw new InvalidArgumentError("Prompt from --file is empty");
1028
+ return prompt;
1029
+ }
1030
+ async function readPromptFromStdin() {
1031
+ if (process.stdin.isTTY) throw new InvalidArgumentError("Prompt is required (pass as final argument, --file, or pipe via stdin)");
1032
+ const prompt = parsePromptSource(await readStdin());
1033
+ if (prompt.length === 0) throw new InvalidArgumentError("Prompt from stdin is empty");
1034
+ return prompt;
1035
+ }
1036
+ async function readPromptInput(filePath, promptText, cwd) {
1037
+ try {
1038
+ if (filePath) return await readPromptFile(filePath, promptText, cwd);
1039
+ const joined = promptText.trim();
1040
+ if (joined.length > 0) return textPrompt(joined);
1041
+ return await readPromptFromStdin();
1042
+ } catch (error) {
1043
+ if (error instanceof PromptInputValidationError) throw new InvalidArgumentError(error.message);
1044
+ throw error;
1045
+ }
1046
+ }
1047
+ function promptTokensAfterDoubleDash(command) {
1048
+ const commandName = command.name();
1049
+ const commandIndex = process.argv.findIndex((token, index) => index >= 2 && token === commandName);
1050
+ if (commandIndex < 0) return [];
1051
+ const delimiterIndex = process.argv.findIndex((token, index) => index > commandIndex && token === "--");
1052
+ return delimiterIndex < 0 ? [] : process.argv.slice(delimiterIndex + 1);
1053
+ }
1054
+ function splitCompareArgs(args, filePath, command) {
1055
+ if (filePath) {
1056
+ if (args.length === 0) throw new InvalidArgumentError("At least one agent is required");
1057
+ return {
1058
+ agents: args,
1059
+ promptText: ""
1060
+ };
1061
+ }
1062
+ const promptTokens = promptTokensAfterDoubleDash(command);
1063
+ if (promptTokens.length > 0) {
1064
+ const agents = args.slice(0, -promptTokens.length);
1065
+ if (agents.length === 0) throw new InvalidArgumentError("At least one agent is required");
1066
+ return {
1067
+ agents,
1068
+ promptText: promptTokens.join(" ")
1069
+ };
1070
+ }
1071
+ if (args.length < 2) throw new InvalidArgumentError("Usage: acpx compare <agent>... '<prompt>'");
1072
+ return {
1073
+ agents: args.slice(0, -1),
1074
+ promptText: args[args.length - 1] ?? ""
1075
+ };
1076
+ }
1077
+ function captureUsage(update, capture) {
1078
+ const source = asRecord$2(asRecord$2(update._meta)?.usage) ?? update;
1079
+ capture.usage = {
1080
+ input_tokens: numberField(source, ["input_tokens", "inputTokens"]) ?? void 0,
1081
+ output_tokens: numberField(source, ["output_tokens", "outputTokens"]) ?? void 0,
1082
+ total_tokens: numberField(source, [
1083
+ "total_tokens",
1084
+ "totalTokens",
1085
+ "size",
1086
+ "used"
1087
+ ]) ?? void 0
1088
+ };
1089
+ }
1090
+ function captureSessionUpdate(notification, capture) {
1091
+ const update = asRecord$2(notification.update);
1092
+ if (!update) return;
1093
+ if (update.sessionUpdate === "agent_message_chunk") {
1094
+ const content = asRecord$2(update.content);
1095
+ if (content?.type === "text" && typeof content.text === "string") capture.finalMessage += content.text;
1096
+ return;
1097
+ }
1098
+ if (update.sessionUpdate === "usage_update") captureUsage(update, capture);
1099
+ }
1100
+ function rowStatusFromPermissionStats(stats) {
1101
+ return stats.denied + stats.cancelled > 0 ? "permission_denied" : "ok";
1102
+ }
1103
+ function sessionOptionsFromGlobalFlags(globalFlags) {
1104
+ return {
1105
+ model: globalFlags.model,
1106
+ allowedTools: globalFlags.allowedTools,
1107
+ maxTurns: globalFlags.maxTurns,
1108
+ systemPrompt: globalFlags.systemPrompt
1109
+ };
1110
+ }
1111
+ async function resolvePermissionPolicyFromFlags(globalFlags) {
1112
+ try {
1113
+ return await loadPermissionPolicySpec(globalFlags.permissionPolicy, globalFlags.cwd);
1114
+ } catch (error) {
1115
+ throw new InvalidArgumentError(`Invalid permission policy: ${error instanceof Error ? error.message : String(error)}`);
1116
+ }
1117
+ }
1118
+ function buildSuccessRow(agentName, result, capture, startedAt) {
1119
+ const permissionStats = result.permissionStats;
1120
+ return {
1121
+ agent: agentName,
1122
+ status: result.stopReason === "cancelled" ? "cancelled" : rowStatusFromPermissionStats(permissionStats),
1123
+ stop_reason: result.stopReason,
1124
+ wall_ms: Math.round(performance.now() - startedAt),
1125
+ input_tokens: capture.usage.input_tokens ?? null,
1126
+ output_tokens: capture.usage.output_tokens ?? null,
1127
+ total_tokens: capture.usage.total_tokens ?? null,
1128
+ final_message: truncate(collapseWhitespace(capture.finalMessage), FINAL_MESSAGE_PREVIEW_CHARS),
1129
+ error: null,
1130
+ permission_requests: permissionStats.requested,
1131
+ permission_denied: permissionStats.denied + permissionStats.cancelled
1132
+ };
1133
+ }
1134
+ function buildErrorRow(agentName, caught, capture, startedAt) {
1135
+ return {
1136
+ agent: agentName,
1137
+ status: caught instanceof TimeoutError ? "cancelled" : "error",
1138
+ stop_reason: null,
1139
+ wall_ms: Math.round(performance.now() - startedAt),
1140
+ input_tokens: capture.usage.input_tokens ?? null,
1141
+ output_tokens: capture.usage.output_tokens ?? null,
1142
+ total_tokens: capture.usage.total_tokens ?? null,
1143
+ final_message: truncate(collapseWhitespace(capture.finalMessage), FINAL_MESSAGE_PREVIEW_CHARS),
1144
+ error: truncate(collapseWhitespace(caught instanceof Error ? caught.message : String(caught)), FINAL_MESSAGE_PREVIEW_CHARS),
1145
+ permission_requests: 0,
1146
+ permission_denied: 0
1147
+ };
1148
+ }
1149
+ async function runAgentForCompare(params) {
1150
+ const capture = {
1151
+ finalMessage: "",
1152
+ usage: {},
1153
+ errors: []
1154
+ };
1155
+ const formatter = new CaptureFormatter();
1156
+ const t0 = performance.now();
1157
+ try {
1158
+ const agent = resolveAgentInvocation(params.agentName, params.globalFlags, params.config);
1159
+ const result = await runOnce({
1160
+ agentCommand: agent.agentCommand,
1161
+ cwd: agent.cwd,
1162
+ prompt: params.prompt,
1163
+ mcpServers: params.config.mcpServers,
1164
+ permissionMode: resolvePermissionMode(params.globalFlags, params.config.defaultPermissions),
1165
+ nonInteractivePermissions: params.globalFlags.nonInteractivePermissions,
1166
+ permissionPolicy: params.permissionPolicy,
1167
+ authCredentials: params.config.auth,
1168
+ authPolicy: params.globalFlags.authPolicy,
1169
+ terminal: params.globalFlags.terminal,
1170
+ outputFormatter: formatter,
1171
+ suppressSdkConsoleErrors: true,
1172
+ timeoutMs: params.globalFlags.timeout ?? DEFAULT_COMPARE_TIMEOUT_MS,
1173
+ verbose: params.globalFlags.verbose,
1174
+ promptRetries: params.globalFlags.promptRetries,
1175
+ sessionOptions: sessionOptionsFromGlobalFlags(params.globalFlags),
1176
+ onSessionUpdate: (notification) => captureSessionUpdate(notification, capture)
1177
+ });
1178
+ return buildSuccessRow(params.agentName, result, capture, t0);
1179
+ } catch (caught) {
1180
+ return buildErrorRow(params.agentName, caught, capture, t0);
1181
+ }
1182
+ }
1183
+ function formatCell(value) {
1184
+ if (value == null || value === "") return "-";
1185
+ if (typeof value === "string") return collapseWhitespace(value);
1186
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
1187
+ return collapseWhitespace(JSON.stringify(value));
1188
+ }
1189
+ function renderTable(rows) {
1190
+ const headers = [
1191
+ "agent",
1192
+ "status",
1193
+ "wall_ms",
1194
+ "input",
1195
+ "output",
1196
+ "total",
1197
+ "permissions",
1198
+ "stop_reason",
1199
+ "final_message",
1200
+ "error"
1201
+ ];
1202
+ const body = rows.map((row) => [
1203
+ row.agent,
1204
+ row.status,
1205
+ row.wall_ms,
1206
+ row.input_tokens,
1207
+ row.output_tokens,
1208
+ row.total_tokens,
1209
+ `${row.permission_denied}/${row.permission_requests}`,
1210
+ row.stop_reason,
1211
+ row.final_message,
1212
+ row.error
1213
+ ]);
1214
+ const widths = headers.map((header, index) => Math.max(header.length, ...body.map((cells) => formatCell(cells[index]).length)));
1215
+ const formatRow = (cells) => cells.map((cell, index) => truncate(formatCell(cell), widths[index] ?? 24).padEnd(widths[index] ?? 24)).join(" ").trimEnd();
1216
+ return [
1217
+ formatRow(headers),
1218
+ widths.map((width) => "-".repeat(width)).join(" "),
1219
+ ...body.map(formatRow)
1220
+ ].join("\n");
1221
+ }
1222
+ function printRows(rows, format) {
1223
+ if (format === "json") {
1224
+ process.stdout.write(`${JSON.stringify(rows)}\n`);
1225
+ return;
1226
+ }
1227
+ if (format === "quiet") {
1228
+ for (const row of rows) process.stdout.write(`${row.agent}\t${row.status}\n`);
1229
+ return;
1230
+ }
1231
+ process.stdout.write(`${renderTable(rows)}\n`);
1232
+ }
1233
+ function updateCompareExitCode(rows) {
1234
+ if (rows.some((row) => row.status === "error")) {
1235
+ process.exitCode = EXIT_CODES.ERROR;
1236
+ return;
1237
+ }
1238
+ if (rows.some((row) => row.status === "permission_denied")) {
1239
+ process.exitCode = EXIT_CODES.PERMISSION_DENIED;
1240
+ return;
1241
+ }
1242
+ if (rows.some((row) => row.status === "cancelled")) process.exitCode = EXIT_CODES.TIMEOUT;
1243
+ }
1244
+ function resolvePromptFile(flags) {
1245
+ if (flags.file && flags.promptFile && flags.file !== flags.promptFile) throw new InvalidArgumentError("Use only one prompt file flag: --file or --prompt-file");
1246
+ return flags.file ?? flags.promptFile;
1247
+ }
1248
+ function registerCompareCommand(program, config) {
1249
+ 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) {
1250
+ if (config.disableExec) throw new Error("compare subcommand is disabled by configuration (disableExec: true)");
1251
+ const globalFlags = resolveGlobalFlags(this, config);
1252
+ if (globalFlags.agent) throw new InvalidArgumentError("Do not combine compare with --agent; pass agent names");
1253
+ const outputPolicy = resolveOutputPolicy(flags.json === true ? "json" : globalFlags.format, globalFlags.jsonStrict === true);
1254
+ const promptFile = resolvePromptFile(flags);
1255
+ const { agents, promptText } = splitCompareArgs(args, promptFile, this);
1256
+ const prompt = await readPromptInput(promptFile, promptText, globalFlags.cwd);
1257
+ const permissionPolicy = await resolvePermissionPolicyFromFlags(globalFlags);
1258
+ const rows = [];
1259
+ for (const agentName of agents) rows.push(await runAgentForCompare({
1260
+ agentName,
1261
+ prompt,
1262
+ config,
1263
+ globalFlags,
1264
+ permissionPolicy
1265
+ }));
1266
+ printRows(rows, outputPolicy.format);
1267
+ updateCompareExitCode(rows);
1268
+ });
1269
+ }
1270
+ //#endregion
990
1271
  //#region src/mcp-servers.ts
991
1272
  function asRecord$1(value) {
992
1273
  if (!value || typeof value !== "object" || Array.isArray(value)) return;
@@ -1090,7 +1371,6 @@ function parseOptionalMcpServers(value, sourcePath, fieldName = "mcpServers") {
1090
1371
  }
1091
1372
  //#endregion
1092
1373
  //#region src/cli/config.ts
1093
- const DEFAULT_TIMEOUT_MS = void 0;
1094
1374
  const DEFAULT_TTL_MS = 3e5;
1095
1375
  const DEFAULT_PERMISSION_MODE = "approve-reads";
1096
1376
  const DEFAULT_NON_INTERACTIVE_PERMISSION_POLICY = "deny";
@@ -1292,7 +1572,6 @@ function hasConfigKey(config, key) {
1292
1572
  function resolveTimeoutMs(projectConfig, projectPath, globalConfig, globalPath) {
1293
1573
  if (hasConfigKey(projectConfig, "timeout")) return parseTimeoutMs(projectConfig?.timeout, projectPath);
1294
1574
  if (hasConfigKey(globalConfig, "timeout")) return parseTimeoutMs(globalConfig?.timeout, globalPath);
1295
- return DEFAULT_TIMEOUT_MS;
1296
1575
  }
1297
1576
  function resolveMcpServers(projectConfig, projectPath, globalConfig, globalPath) {
1298
1577
  if (hasConfigKey(projectConfig, "mcpServers")) return parseMcpServers(projectConfig?.mcpServers, projectPath);
@@ -1862,7 +2141,7 @@ function registerAgentCommand(program, agentName, config) {
1862
2141
  }
1863
2142
  function registerFlowCommand(program, config) {
1864
2143
  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) {
1865
- const { handleFlowRun } = await import("./cli-8dP_TqBp.js");
2144
+ const { handleFlowRun } = await import("./cli-CC2w0U-A.js");
1866
2145
  await handleFlowRun(file, flags, this, config);
1867
2146
  });
1868
2147
  }
@@ -1877,6 +2156,7 @@ function registerDefaultCommands(program, config) {
1877
2156
  });
1878
2157
  registerSessionsCommand(program, void 0, config);
1879
2158
  registerConfigCommand(program, config);
2159
+ registerCompareCommand(program, config);
1880
2160
  registerFlowCommand(program, config);
1881
2161
  }
1882
2162
  //#endregion
@@ -1958,54 +2238,12 @@ async function runQueueOwnerFromEnv(env) {
1958
2238
  await runSessionQueueOwner(parseQueueOwnerPayload(payload));
1959
2239
  }
1960
2240
  //#endregion
1961
- //#region src/version.ts
1962
- const UNKNOWN_VERSION = "0.0.0-unknown";
1963
- const MODULE_DIR = path.dirname(fileURLToPath(import.meta.url));
1964
- let cachedVersion = null;
1965
- function parseVersion(value) {
1966
- if (typeof value !== "string") return null;
1967
- const trimmed = value.trim();
1968
- return trimmed.length > 0 ? trimmed : null;
1969
- }
1970
- function readPackageVersion(packageJsonPath) {
1971
- try {
1972
- return parseVersion(JSON.parse(readFileSync(packageJsonPath, "utf8")).version);
1973
- } catch {
1974
- return null;
1975
- }
1976
- }
1977
- function resolveVersionFromAncestors(startDir) {
1978
- let current = startDir;
1979
- while (true) {
1980
- const packageVersion = readPackageVersion(path.join(current, "package.json"));
1981
- if (packageVersion) return packageVersion;
1982
- const parent = path.dirname(current);
1983
- if (parent === current) return null;
1984
- current = parent;
1985
- }
1986
- }
1987
- function resolveAcpxVersion(params) {
1988
- const envVersion = resolvePackageEnvVersion(params?.env ?? process.env);
1989
- if (envVersion) return envVersion;
1990
- if (params?.packageJsonPath) return readPackageVersion(params.packageJsonPath) ?? UNKNOWN_VERSION;
1991
- return resolveVersionFromAncestors(MODULE_DIR) ?? UNKNOWN_VERSION;
1992
- }
1993
- function resolvePackageEnvVersion(env) {
1994
- const envPackageName = parseVersion(env.npm_package_name);
1995
- const envVersion = parseVersion(env.npm_package_version);
1996
- return envPackageName === "acpx" ? envVersion : null;
1997
- }
1998
- function getAcpxVersion() {
1999
- if (cachedVersion) return cachedVersion;
2000
- cachedVersion = resolveAcpxVersion();
2001
- return cachedVersion;
2002
- }
2003
- //#endregion
2004
2241
  //#region src/cli-core.ts
2005
2242
  const TOP_LEVEL_VERBS = new Set([
2006
2243
  "prompt",
2007
2244
  "exec",
2008
2245
  "cancel",
2246
+ "compare",
2009
2247
  "flow",
2010
2248
  "set-mode",
2011
2249
  "set",