acpx 0.3.1 → 0.4.1

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 (35) hide show
  1. package/README.md +65 -16
  2. package/dist/{acp-jsonrpc-BNHXq7qK.js → acp-jsonrpc-BbBgC5gO.js} +15 -2
  3. package/dist/acp-jsonrpc-BbBgC5gO.js.map +1 -0
  4. package/dist/cli-idpWyCOs.js +176 -0
  5. package/dist/cli-idpWyCOs.js.map +1 -0
  6. package/dist/cli.d.ts +1 -118
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +235 -336
  9. package/dist/cli.js.map +1 -1
  10. package/dist/flags-CCcX9fZj.js +194 -0
  11. package/dist/flags-CCcX9fZj.js.map +1 -0
  12. package/dist/flows-BL1tSvZT.js +1551 -0
  13. package/dist/flows-BL1tSvZT.js.map +1 -0
  14. package/dist/flows.d.ts +292 -0
  15. package/dist/flows.d.ts.map +1 -0
  16. package/dist/flows.js +2 -0
  17. package/dist/{output-BmkPP7qE.js → output-Du3m6oPQ.js} +139 -30
  18. package/dist/output-Du3m6oPQ.js.map +1 -0
  19. package/dist/{output-render-DEAaMxg8.js → output-render-Bz58qaQn.js} +10 -10
  20. package/dist/output-render-Bz58qaQn.js.map +1 -0
  21. package/dist/{queue-ipc-EQLpBMKv.js → queue-ipc-CE8_QGX3.js} +258 -95
  22. package/dist/queue-ipc-CE8_QGX3.js.map +1 -0
  23. package/dist/{session-C2Q8ktsN.js → session-RO_LZUnv.js} +687 -138
  24. package/dist/session-RO_LZUnv.js.map +1 -0
  25. package/dist/types-CeRKmEQ1.d.ts +137 -0
  26. package/dist/types-CeRKmEQ1.d.ts.map +1 -0
  27. package/package.json +44 -16
  28. package/skills/acpx/SKILL.md +22 -5
  29. package/dist/acp-jsonrpc-BNHXq7qK.js.map +0 -1
  30. package/dist/output-BmkPP7qE.js.map +0 -1
  31. package/dist/output-render-DEAaMxg8.js.map +0 -1
  32. package/dist/queue-ipc-EQLpBMKv.js.map +0 -1
  33. package/dist/runtime-session-id-C544sPPL.js +0 -31
  34. package/dist/runtime-session-id-C544sPPL.js.map +0 -1
  35. package/dist/session-C2Q8ktsN.js.map +0 -1
package/dist/cli.js CHANGED
@@ -1,186 +1,14 @@
1
1
  #!/usr/bin/env node
2
- import { A as OUTPUT_FORMATS, C as exitCodeForOutputErrorCode, D as AUTH_POLICIES, E as normalizeOutputError, I as textPrompt, M as PromptInputValidationError, N as mergePromptSourceWithText, O as EXIT_CODES, P as parsePromptSource, k as NON_INTERACTIVE_PERMISSION_POLICIES } from "./queue-ipc-EQLpBMKv.js";
3
- import { a as findGitRepositoryRoot, c as flushPerfMetricsCapture, l as installPerfMetricsCapture, o as findSession, r as runSessionQueueOwner, s as findSessionByDirectoryWalk, u as InterruptedError } from "./session-C2Q8ktsN.js";
4
- import { t as formatPromptSessionBannerLine } from "./output-render-DEAaMxg8.js";
2
+ import { _ as DEFAULT_AGENT_NAME, c as parseMaxTurns, d as parseTtlSeconds, f as resolveAgentInvocation, g as resolveSessionNameFromFlags, h as resolvePermissionMode, i as addSessionOption, l as parseNonEmptyValue, m as resolveOutputPolicy, n as addPromptInputOption, o as parseAllowedTools, p as resolveGlobalFlags, r as addSessionNameOption, s as parseHistoryLimit, t as addGlobalFlags, u as parseSessionName, v as listBuiltInAgents, y as normalizeAgentName } from "./flags-CCcX9fZj.js";
3
+ import { A as OUTPUT_FORMATS, E as normalizeOutputError, F as mergePromptSourceWithText, I as parsePromptSource, O as EXIT_CODES, P as PromptInputValidationError, R as textPrompt, S as exitCodeForOutputErrorCode, s as probeQueueOwnerHealth } from "./queue-ipc-CE8_QGX3.js";
4
+ import { S as InterruptedError, b as flushPerfMetricsCapture, c as buildQueueOwnerArgOverride, d as findSession, f as findSessionByDirectoryWalk, o as runSessionQueueOwner, u as findGitRepositoryRoot, x as installPerfMetricsCapture } from "./session-RO_LZUnv.js";
5
+ import { i as emitJsonResult, n as formatPromptSessionBannerLine, t as agentSessionIdPayload } from "./output-render-Bz58qaQn.js";
5
6
  import { readFileSync, realpathSync } from "node:fs";
6
7
  import { fileURLToPath, pathToFileURL } from "node:url";
7
8
  import fs$1 from "node:fs/promises";
8
9
  import path from "node:path";
9
10
  import { Command, CommanderError, InvalidArgumentError } from "commander";
10
11
  import os from "node:os";
11
- //#region src/agent-registry.ts
12
- const ACP_ADAPTER_PACKAGE_RANGES = {
13
- pi: "^0.0.22",
14
- codex: "^0.9.5",
15
- claude: "^0.21.0"
16
- };
17
- const AGENT_REGISTRY = {
18
- pi: `npx pi-acp@${ACP_ADAPTER_PACKAGE_RANGES.pi}`,
19
- openclaw: "openclaw acp",
20
- codex: `npx @zed-industries/codex-acp@${ACP_ADAPTER_PACKAGE_RANGES.codex}`,
21
- claude: `npx -y @zed-industries/claude-agent-acp@${ACP_ADAPTER_PACKAGE_RANGES.claude}`,
22
- gemini: "gemini --acp",
23
- cursor: "cursor-agent acp",
24
- copilot: "copilot --acp --stdio",
25
- droid: "droid exec --output-format acp",
26
- iflow: "iflow --experimental-acp",
27
- kilocode: "npx -y @kilocode/cli acp",
28
- kimi: "kimi acp",
29
- kiro: "kiro-cli acp",
30
- opencode: "npx -y opencode-ai acp",
31
- qwen: "qwen --acp"
32
- };
33
- const AGENT_ALIASES = {
34
- "factory-droid": "droid",
35
- factorydroid: "droid"
36
- };
37
- const DEFAULT_AGENT_NAME = "codex";
38
- function normalizeAgentName(value) {
39
- return value.trim().toLowerCase();
40
- }
41
- function mergeAgentRegistry(overrides) {
42
- if (!overrides) return { ...AGENT_REGISTRY };
43
- const merged = { ...AGENT_REGISTRY };
44
- for (const [name, command] of Object.entries(overrides)) {
45
- const normalized = normalizeAgentName(name);
46
- if (!normalized || !command.trim()) continue;
47
- merged[normalized] = command.trim();
48
- }
49
- return merged;
50
- }
51
- function resolveAgentCommand(agentName, overrides) {
52
- const normalized = normalizeAgentName(agentName);
53
- const registry = mergeAgentRegistry(overrides);
54
- return registry[normalized] ?? registry[AGENT_ALIASES[normalized] ?? normalized] ?? agentName;
55
- }
56
- function listBuiltInAgents(overrides) {
57
- return Object.keys(mergeAgentRegistry(overrides));
58
- }
59
- //#endregion
60
- //#region src/cli/flags.ts
61
- function parseOutputFormat$1(value) {
62
- if (!OUTPUT_FORMATS.includes(value)) throw new InvalidArgumentError(`Invalid format "${value}". Expected one of: ${OUTPUT_FORMATS.join(", ")}`);
63
- return value;
64
- }
65
- function parseAuthPolicy$1(value) {
66
- if (!AUTH_POLICIES.includes(value)) throw new InvalidArgumentError(`Invalid auth policy "${value}". Expected one of: ${AUTH_POLICIES.join(", ")}`);
67
- return value;
68
- }
69
- function parseNonInteractivePermissionPolicy$1(value) {
70
- if (!NON_INTERACTIVE_PERMISSION_POLICIES.includes(value)) throw new InvalidArgumentError(`Invalid non-interactive permission policy "${value}". Expected one of: ${NON_INTERACTIVE_PERMISSION_POLICIES.join(", ")}`);
71
- return value;
72
- }
73
- function parseTimeoutSeconds(value) {
74
- const parsed = Number(value);
75
- if (!Number.isFinite(parsed) || parsed <= 0) throw new InvalidArgumentError("Timeout must be a positive number of seconds");
76
- return Math.round(parsed * 1e3);
77
- }
78
- function parseTtlSeconds(value) {
79
- const parsed = Number(value);
80
- if (!Number.isFinite(parsed) || parsed < 0) throw new InvalidArgumentError("TTL must be a non-negative number of seconds");
81
- return Math.round(parsed * 1e3);
82
- }
83
- function parseSessionName(value) {
84
- const trimmed = value.trim();
85
- if (trimmed.length === 0) throw new InvalidArgumentError("Session name must not be empty");
86
- return trimmed;
87
- }
88
- function parseNonEmptyValue(label, value) {
89
- const trimmed = value.trim();
90
- if (trimmed.length === 0) throw new InvalidArgumentError(`${label} must not be empty`);
91
- return trimmed;
92
- }
93
- function parseHistoryLimit(value) {
94
- const parsed = Number(value);
95
- if (!Number.isInteger(parsed) || parsed <= 0) throw new InvalidArgumentError("Limit must be a positive integer");
96
- return parsed;
97
- }
98
- function parseAllowedTools(value) {
99
- const trimmed = value.trim();
100
- if (trimmed.length === 0) return [];
101
- const items = trimmed.split(",").map((item) => item.trim());
102
- if (items.some((item) => item.length === 0)) throw new InvalidArgumentError("Allowed tools must be a comma-separated list without empty entries");
103
- return items;
104
- }
105
- function parseMaxTurns(value) {
106
- const parsed = Number(value);
107
- if (!Number.isInteger(parsed) || parsed <= 0) throw new InvalidArgumentError("Max turns must be a positive integer");
108
- return parsed;
109
- }
110
- function resolvePermissionMode(flags, defaultMode) {
111
- if ([
112
- flags.approveAll,
113
- flags.approveReads,
114
- flags.denyAll
115
- ].filter(Boolean).length > 1) throw new InvalidArgumentError("Use only one permission mode: --approve-all, --approve-reads, or --deny-all");
116
- if (flags.approveAll) return "approve-all";
117
- if (flags.denyAll) return "deny-all";
118
- return defaultMode;
119
- }
120
- function addGlobalFlags(command) {
121
- return command.option("--agent <command>", "Raw ACP agent command (escape hatch)").option("--cwd <dir>", "Working directory", process.cwd()).option("--auth-policy <policy>", "Authentication policy: skip or fail when auth is required", parseAuthPolicy$1).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("--non-interactive-permissions <policy>", "When prompting is unavailable: deny or fail", parseNonInteractivePermissionPolicy$1).option("--format <fmt>", "Output format: text, json, quiet", parseOutputFormat$1).option("--model <id>", "Agent model id").option("--allowed-tools <list>", "Allowed tool names as a comma-separated list (use \"\" for no tools)", parseAllowedTools).option("--max-turns <count>", "Maximum turns for the session", parseMaxTurns).option("--json-strict", "Strict JSON mode: requires --format json and suppresses non-JSON stderr output").option("--timeout <seconds>", "Maximum time to wait for agent response", parseTimeoutSeconds).option("--ttl <seconds>", "Queue owner idle TTL before shutdown (0 = keep alive forever) (default: 300)", parseTtlSeconds).option("--verbose", "Enable verbose debug logs");
122
- }
123
- function addSessionOption(command) {
124
- return command.option("-s, --session <name>", "Use named session instead of cwd default", parseSessionName).option("--no-wait", "Queue prompt and return immediately when another prompt is already running");
125
- }
126
- function addSessionNameOption(command) {
127
- return command.option("-s, --session <name>", "Use named session instead of cwd default", parseSessionName);
128
- }
129
- function resolveSessionNameFromFlags(flags, command) {
130
- if (flags.session) return flags.session;
131
- const allOpts = command.optsWithGlobals?.();
132
- if (allOpts && typeof allOpts.session === "string") return parseSessionName(allOpts.session);
133
- const parentOpts = command.parent?.opts?.();
134
- if (parentOpts && typeof parentOpts.session === "string") return parseSessionName(parentOpts.session);
135
- }
136
- function addPromptInputOption(command) {
137
- return command.option("-f, --file <path>", "Read prompt text from file path (use - for stdin)");
138
- }
139
- function resolveGlobalFlags(command, config) {
140
- const opts = command.optsWithGlobals();
141
- const format = opts.format ?? config.format ?? "text";
142
- const jsonStrict = opts.jsonStrict === true;
143
- const verbose = opts.verbose === true;
144
- if (jsonStrict && format !== "json") throw new InvalidArgumentError("--json-strict requires --format json");
145
- if (jsonStrict && verbose) throw new InvalidArgumentError("--json-strict cannot be combined with --verbose");
146
- return {
147
- agent: opts.agent,
148
- cwd: opts.cwd ?? process.cwd(),
149
- authPolicy: opts.authPolicy ?? config.authPolicy,
150
- nonInteractivePermissions: opts.nonInteractivePermissions ?? config.nonInteractivePermissions,
151
- jsonStrict,
152
- timeout: opts.timeout ?? config.timeoutMs,
153
- ttl: opts.ttl ?? config.ttlMs ?? 3e5,
154
- verbose,
155
- format,
156
- model: typeof opts.model === "string" ? parseNonEmptyValue("Model", opts.model) : void 0,
157
- allowedTools: Array.isArray(opts.allowedTools) ? opts.allowedTools : void 0,
158
- maxTurns: typeof opts.maxTurns === "number" ? opts.maxTurns : void 0,
159
- approveAll: opts.approveAll ? true : void 0,
160
- approveReads: opts.approveReads ? true : void 0,
161
- denyAll: opts.denyAll ? true : void 0
162
- };
163
- }
164
- function resolveOutputPolicy(format, jsonStrict) {
165
- return {
166
- format,
167
- jsonStrict,
168
- suppressNonJsonStderr: jsonStrict,
169
- queueErrorAlreadyEmitted: format !== "quiet",
170
- suppressSdkConsoleErrors: jsonStrict
171
- };
172
- }
173
- function resolveAgentInvocation(explicitAgentName, globalFlags, config) {
174
- const override = globalFlags.agent?.trim();
175
- if (override && explicitAgentName) throw new InvalidArgumentError("Do not combine positional agent with --agent override");
176
- const agentName = explicitAgentName ?? config.defaultAgent ?? "codex";
177
- return {
178
- agentName,
179
- agentCommand: override && override.length > 0 ? override : resolveAgentCommand(agentName, config.agents),
180
- cwd: path.resolve(globalFlags.cwd)
181
- };
182
- }
183
- //#endregion
184
12
  //#region src/mcp-servers.ts
185
13
  function asRecord$1(value) {
186
14
  if (!value || typeof value !== "object" || Array.isArray(value)) return;
@@ -503,6 +331,163 @@ async function initGlobalConfigFile() {
503
331
  };
504
332
  }
505
333
  //#endregion
334
+ //#region src/cli/config-command.ts
335
+ async function handleConfigShow(command, config) {
336
+ const globalFlags = resolveGlobalFlags(command, config);
337
+ const payload = {
338
+ ...toConfigDisplay(config),
339
+ paths: {
340
+ global: config.globalPath,
341
+ project: config.projectPath
342
+ },
343
+ loaded: {
344
+ global: config.hasGlobalConfig,
345
+ project: config.hasProjectConfig
346
+ }
347
+ };
348
+ if (globalFlags.format === "json") {
349
+ process.stdout.write(`${JSON.stringify(payload)}\n`);
350
+ return;
351
+ }
352
+ process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
353
+ }
354
+ async function handleConfigInit(command, config) {
355
+ const globalFlags = resolveGlobalFlags(command, config);
356
+ const result = await initGlobalConfigFile();
357
+ if (globalFlags.format === "json") {
358
+ process.stdout.write(`${JSON.stringify({
359
+ path: result.path,
360
+ created: result.created
361
+ })}\n`);
362
+ return;
363
+ }
364
+ if (globalFlags.format === "quiet") {
365
+ process.stdout.write(`${result.path}\n`);
366
+ return;
367
+ }
368
+ if (result.created) {
369
+ process.stdout.write(`Created ${result.path}\n`);
370
+ return;
371
+ }
372
+ process.stdout.write(`Config already exists: ${result.path}\n`);
373
+ }
374
+ function registerConfigCommand(program, config) {
375
+ const configCommand = program.command("config").description("Inspect and initialize acpx configuration");
376
+ configCommand.command("show").description("Show resolved config").action(async function() {
377
+ await handleConfigShow(this, config);
378
+ });
379
+ configCommand.command("init").description("Create global config template").action(async function() {
380
+ await handleConfigInit(this, config);
381
+ });
382
+ configCommand.action(async function() {
383
+ await handleConfigShow(this, config);
384
+ });
385
+ }
386
+ //#endregion
387
+ //#region src/cli/status-command.ts
388
+ function formatUptime(startedAt) {
389
+ if (!startedAt) return;
390
+ const startedMs = Date.parse(startedAt);
391
+ if (!Number.isFinite(startedMs)) return;
392
+ const elapsedMs = Math.max(0, Date.now() - startedMs);
393
+ const seconds = Math.floor(elapsedMs / 1e3);
394
+ const hours = Math.floor(seconds / 3600);
395
+ const minutes = Math.floor(seconds % 3600 / 60);
396
+ const remSeconds = seconds % 60;
397
+ return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}:${remSeconds.toString().padStart(2, "0")}`;
398
+ }
399
+ async function handleStatus(explicitAgentName, flags, command, config) {
400
+ const globalFlags = resolveGlobalFlags(command, config);
401
+ const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
402
+ const record = await findSession({
403
+ agentCommand: agent.agentCommand,
404
+ cwd: agent.cwd,
405
+ name: resolveSessionNameFromFlags(flags, command)
406
+ });
407
+ if (!record) {
408
+ if (emitJsonResult(globalFlags.format, {
409
+ action: "status_snapshot",
410
+ status: "no-session",
411
+ summary: "no active session"
412
+ })) return;
413
+ if (globalFlags.format === "quiet") {
414
+ process.stdout.write("no-session\n");
415
+ return;
416
+ }
417
+ process.stdout.write("session: -\n");
418
+ process.stdout.write(`agent: ${agent.agentCommand}\n`);
419
+ process.stdout.write("pid: -\n");
420
+ process.stdout.write("status: no-session\n");
421
+ process.stdout.write("model: -\n");
422
+ process.stdout.write("mode: -\n");
423
+ process.stdout.write("uptime: -\n");
424
+ process.stdout.write("lastPromptTime: -\n");
425
+ return;
426
+ }
427
+ const health = await probeQueueOwnerHealth(record.acpxRecordId);
428
+ const running = health.healthy;
429
+ const payload = {
430
+ sessionId: record.acpxRecordId,
431
+ agentCommand: record.agentCommand,
432
+ pid: health.pid ?? record.pid ?? null,
433
+ status: running ? "running" : "dead",
434
+ model: record.acpx?.current_model_id ?? null,
435
+ mode: record.acpx?.current_mode_id ?? null,
436
+ availableModels: record.acpx?.available_models ?? null,
437
+ uptime: running ? formatUptime(record.agentStartedAt) ?? null : null,
438
+ lastPromptTime: record.lastPromptAt ?? null,
439
+ exitCode: running ? null : record.lastAgentExitCode ?? null,
440
+ signal: running ? null : record.lastAgentExitSignal ?? null,
441
+ ...agentSessionIdPayload(record.agentSessionId)
442
+ };
443
+ if (emitJsonResult(globalFlags.format, {
444
+ action: "status_snapshot",
445
+ status: running ? "alive" : "dead",
446
+ pid: payload.pid ?? void 0,
447
+ summary: running ? "queue owner healthy" : "queue owner unavailable",
448
+ model: payload.model ?? void 0,
449
+ mode: payload.mode ?? void 0,
450
+ availableModels: payload.availableModels ?? void 0,
451
+ uptime: payload.uptime ?? void 0,
452
+ lastPromptTime: payload.lastPromptTime ?? void 0,
453
+ exitCode: payload.exitCode ?? void 0,
454
+ signal: payload.signal ?? void 0,
455
+ acpxRecordId: record.acpxRecordId,
456
+ acpxSessionId: record.acpSessionId,
457
+ agentSessionId: record.agentSessionId
458
+ })) return;
459
+ if (globalFlags.format === "quiet") {
460
+ process.stdout.write(`${payload.status}\n`);
461
+ return;
462
+ }
463
+ process.stdout.write(`session: ${payload.sessionId}\n`);
464
+ if ("agentSessionId" in payload) process.stdout.write(`agentSessionId: ${payload.agentSessionId}\n`);
465
+ process.stdout.write(`agent: ${payload.agentCommand}\n`);
466
+ process.stdout.write(`pid: ${payload.pid ?? "-"}\n`);
467
+ process.stdout.write(`status: ${payload.status}\n`);
468
+ process.stdout.write(`model: ${payload.model ?? "-"}\n`);
469
+ process.stdout.write(`mode: ${payload.mode ?? "-"}\n`);
470
+ process.stdout.write(`uptime: ${payload.uptime ?? "-"}\n`);
471
+ process.stdout.write(`lastPromptTime: ${payload.lastPromptTime ?? "-"}\n`);
472
+ if (payload.status === "dead") {
473
+ process.stdout.write(`exitCode: ${payload.exitCode ?? "-"}\n`);
474
+ process.stdout.write(`signal: ${payload.signal ?? "-"}\n`);
475
+ }
476
+ }
477
+ function registerStatusCommand(parent, explicitAgentName, config, description) {
478
+ const statusCommand = parent.command("status").description(description);
479
+ addSessionNameOption(statusCommand);
480
+ statusCommand.action(async function(flags) {
481
+ await handleStatus(explicitAgentName, flags, this, config);
482
+ });
483
+ }
484
+ //#endregion
485
+ //#region src/codex-compat.ts
486
+ function isCodexInvocation(agentName, agentCommand) {
487
+ if (agentName === "codex") return true;
488
+ return /\bcodex-acp\b/u.test(agentCommand);
489
+ }
490
+ //#endregion
506
491
  //#region src/queue-owner-env.ts
507
492
  function asRecord(value) {
508
493
  if (!value || typeof value !== "object" || Array.isArray(value)) return;
@@ -529,6 +514,7 @@ function parseQueueOwnerPayload(raw) {
529
514
  if (typeof record.verbose === "boolean") options.verbose = record.verbose;
530
515
  if (typeof record.ttlMs === "number" && Number.isFinite(record.ttlMs)) options.ttlMs = record.ttlMs;
531
516
  if (typeof record.maxQueueDepth === "number" && Number.isFinite(record.maxQueueDepth)) options.maxQueueDepth = Math.max(1, Math.round(record.maxQueueDepth));
517
+ if (typeof record.promptRetries === "number" && Number.isFinite(record.promptRetries)) options.promptRetries = Math.max(0, Math.round(record.promptRetries));
532
518
  return options;
533
519
  }
534
520
  async function runQueueOwnerFromEnv(env) {
@@ -588,6 +574,7 @@ const TOP_LEVEL_VERBS = new Set([
588
574
  "prompt",
589
575
  "exec",
590
576
  "cancel",
577
+ "flow",
591
578
  "set-mode",
592
579
  "set",
593
580
  "sessions",
@@ -623,40 +610,32 @@ function applyPermissionExitCode(result) {
623
610
  const deniedOrCancelled = stats.denied + stats.cancelled;
624
611
  if (stats.requested > 0 && stats.approved === 0 && deniedOrCancelled > 0) process.exitCode = EXIT_CODES.PERMISSION_DENIED;
625
612
  }
626
- function emitJsonResult(format, payload) {
627
- if (format !== "json") return false;
628
- process.stdout.write(`${JSON.stringify(payload)}\n`);
629
- return true;
630
- }
631
- function isCodexAgentInvocation(agent) {
632
- if (agent.agentName === "codex") return true;
633
- return /\bcodex-acp\b/.test(agent.agentCommand);
634
- }
635
613
  function resolveCompatibleConfigId(agent, configId) {
636
- if (isCodexAgentInvocation(agent) && configId === "thought_level") return "reasoning_effort";
614
+ if (isCodexInvocation(agent.agentName, agent.agentCommand) && configId === "thought_level") return "reasoning_effort";
637
615
  return configId;
638
616
  }
617
+ function resolveRequestedOutputPolicy(globalFlags) {
618
+ return {
619
+ ...resolveOutputPolicy(globalFlags.format, globalFlags.jsonStrict === true),
620
+ suppressReads: globalFlags.suppressReads === true
621
+ };
622
+ }
639
623
  let sessionModulePromise;
640
624
  let outputModulePromise;
641
625
  let outputRenderModulePromise;
642
- let queueIpcModulePromise;
643
626
  let skillflagModulePromise;
644
627
  function loadSessionModule() {
645
- sessionModulePromise ??= import("./session-C2Q8ktsN.js").then((n) => n.t);
628
+ sessionModulePromise ??= import("./session-RO_LZUnv.js").then((n) => n.t);
646
629
  return sessionModulePromise;
647
630
  }
648
631
  function loadOutputModule() {
649
- outputModulePromise ??= import("./output-BmkPP7qE.js");
632
+ outputModulePromise ??= import("./output-Du3m6oPQ.js").then((n) => n.n);
650
633
  return outputModulePromise;
651
634
  }
652
635
  function loadOutputRenderModule() {
653
- outputRenderModulePromise ??= import("./output-render-DEAaMxg8.js").then((n) => n.n);
636
+ outputRenderModulePromise ??= import("./output-render-Bz58qaQn.js").then((n) => n.r);
654
637
  return outputRenderModulePromise;
655
638
  }
656
- function loadQueueIpcModule() {
657
- queueIpcModulePromise ??= import("./queue-ipc-EQLpBMKv.js").then((n) => n.r);
658
- return queueIpcModulePromise;
659
- }
660
639
  function loadSkillflagModule() {
661
640
  skillflagModulePromise ??= import("skillflag");
662
641
  return skillflagModulePromise;
@@ -677,7 +656,7 @@ async function findRoutedSessionOrThrow(agentCommand, agentName, cwd, sessionNam
677
656
  }
678
657
  async function handlePrompt(explicitAgentName, promptParts, flags, command, config) {
679
658
  const globalFlags = resolveGlobalFlags(command, config);
680
- const outputPolicy = resolveOutputPolicy(globalFlags.format, globalFlags.jsonStrict === true);
659
+ const outputPolicy = resolveRequestedOutputPolicy(globalFlags);
681
660
  const permissionMode = resolvePermissionMode(globalFlags, config.defaultPermissions);
682
661
  const prompt = await readPrompt(promptParts, flags.file, globalFlags.cwd);
683
662
  const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
@@ -687,7 +666,10 @@ async function handlePrompt(explicitAgentName, promptParts, flags, command, conf
687
666
  loadSessionModule()
688
667
  ]);
689
668
  const record = await findRoutedSessionOrThrow(agent.agentCommand, agent.agentName, agent.cwd, flags.session);
690
- const outputFormatter = createOutputFormatter(outputPolicy.format, { jsonContext: { sessionId: record.acpxRecordId } });
669
+ const outputFormatter = createOutputFormatter(outputPolicy.format, {
670
+ jsonContext: { sessionId: record.acpxRecordId },
671
+ suppressReads: outputPolicy.suppressReads
672
+ });
691
673
  await printPromptSessionBanner(record, agent.cwd, outputPolicy.format, outputPolicy.jsonStrict);
692
674
  const result = await sendSession({
693
675
  sessionId: record.acpxRecordId,
@@ -703,6 +685,7 @@ async function handlePrompt(explicitAgentName, promptParts, flags, command, conf
703
685
  timeoutMs: globalFlags.timeout,
704
686
  ttlMs: globalFlags.ttl,
705
687
  maxQueueDepth: config.queueMaxDepth,
688
+ promptRetries: globalFlags.promptRetries,
706
689
  verbose: globalFlags.verbose,
707
690
  waitForCompletion: flags.wait !== false
708
691
  });
@@ -715,8 +698,7 @@ async function handlePrompt(explicitAgentName, promptParts, flags, command, conf
715
698
  }
716
699
  async function handleExec(explicitAgentName, promptParts, flags, command, config) {
717
700
  if (config.disableExec) {
718
- const globalFlags = resolveGlobalFlags(command, config);
719
- if (resolveOutputPolicy(globalFlags.format, globalFlags.jsonStrict === true).format === "json") process.stdout.write(`${JSON.stringify({
701
+ if (resolveRequestedOutputPolicy(resolveGlobalFlags(command, config)).format === "json") process.stdout.write(`${JSON.stringify({
720
702
  jsonrpc: "2.0",
721
703
  error: {
722
704
  code: -32603,
@@ -729,11 +711,11 @@ async function handleExec(explicitAgentName, promptParts, flags, command, config
729
711
  return;
730
712
  }
731
713
  const globalFlags = resolveGlobalFlags(command, config);
732
- const outputPolicy = resolveOutputPolicy(globalFlags.format, globalFlags.jsonStrict === true);
714
+ const outputPolicy = resolveRequestedOutputPolicy(globalFlags);
733
715
  const permissionMode = resolvePermissionMode(globalFlags, config.defaultPermissions);
734
716
  const prompt = await readPrompt(promptParts, flags.file, globalFlags.cwd);
735
717
  const [{ createOutputFormatter }, { runOnce }] = await Promise.all([loadOutputModule(), loadSessionModule()]);
736
- const outputFormatter = createOutputFormatter(outputPolicy.format);
718
+ const outputFormatter = createOutputFormatter(outputPolicy.format, { suppressReads: outputPolicy.suppressReads });
737
719
  const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
738
720
  applyPermissionExitCode(await runOnce({
739
721
  agentCommand: agent.agentCommand,
@@ -748,6 +730,7 @@ async function handleExec(explicitAgentName, promptParts, flags, command, config
748
730
  suppressSdkConsoleErrors: outputPolicy.suppressSdkConsoleErrors,
749
731
  timeoutMs: globalFlags.timeout,
750
732
  verbose: globalFlags.verbose,
733
+ promptRetries: globalFlags.promptRetries,
751
734
  sessionOptions: {
752
735
  model: globalFlags.model,
753
736
  allowedTools: globalFlags.allowedTools,
@@ -782,6 +765,21 @@ function printSetModeResultByFormat(modeId, result, format) {
782
765
  }
783
766
  process.stdout.write(`mode set: ${modeId}\n`);
784
767
  }
768
+ function printSetModelResultByFormat(modelId, result, format) {
769
+ if (emitJsonResult(format, {
770
+ action: "model_set",
771
+ modelId,
772
+ resumed: result.resumed,
773
+ acpxRecordId: result.record.acpxRecordId,
774
+ acpxSessionId: result.record.acpSessionId,
775
+ agentSessionId: result.record.agentSessionId
776
+ })) return;
777
+ if (format === "quiet") {
778
+ process.stdout.write(`${modelId}\n`);
779
+ return;
780
+ }
781
+ process.stdout.write(`model set: ${modelId}\n`);
782
+ }
785
783
  function printSetConfigOptionResultByFormat(configId, value, result, format) {
786
784
  if (emitJsonResult(format, {
787
785
  action: "config_set",
@@ -839,9 +837,30 @@ async function handleSetMode(explicitAgentName, modeId, flags, command, config)
839
837
  if (globalFlags.verbose && result.loadError) process.stderr.write(`[acpx] loadSession failed, started fresh session: ${result.loadError}\n`);
840
838
  printSetModeResultByFormat(modeId, result, globalFlags.format);
841
839
  }
840
+ async function handleSetModel(explicitAgentName, modelId, flags, command, config) {
841
+ const globalFlags = resolveGlobalFlags(command, config);
842
+ const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
843
+ const { setSessionModel } = await loadSessionModule();
844
+ const result = await setSessionModel({
845
+ sessionId: (await findRoutedSessionOrThrow(agent.agentCommand, agent.agentName, agent.cwd, resolveSessionNameFromFlags(flags, command))).acpxRecordId,
846
+ modelId,
847
+ mcpServers: config.mcpServers,
848
+ nonInteractivePermissions: globalFlags.nonInteractivePermissions,
849
+ authCredentials: config.auth,
850
+ authPolicy: globalFlags.authPolicy,
851
+ timeoutMs: globalFlags.timeout,
852
+ verbose: globalFlags.verbose
853
+ });
854
+ if (globalFlags.verbose && result.loadError) process.stderr.write(`[acpx] loadSession failed, started fresh session: ${result.loadError}\n`);
855
+ printSetModelResultByFormat(modelId, result, globalFlags.format);
856
+ }
842
857
  async function handleSetConfigOption(explicitAgentName, configId, value, flags, command, config) {
843
858
  const globalFlags = resolveGlobalFlags(command, config);
844
859
  const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
860
+ if (configId === "model") {
861
+ await handleSetModel(explicitAgentName, value, flags, command, config);
862
+ return;
863
+ }
845
864
  const resolvedConfigId = resolveCompatibleConfigId(agent, configId);
846
865
  const { setSessionConfigOption } = await loadSessionModule();
847
866
  const result = await setSessionConfigOption({
@@ -1059,125 +1078,6 @@ async function handleSessionsHistory(explicitAgentName, sessionName, flags, comm
1059
1078
  if (!record) throw new Error(sessionName ? `No named session "${sessionName}" for cwd ${agent.cwd} and agent ${agent.agentName}` : `No cwd session for ${agent.cwd} and agent ${agent.agentName}`);
1060
1079
  printSessionHistoryByFormat(record, flags.limit, globalFlags.format);
1061
1080
  }
1062
- function formatUptime(startedAt) {
1063
- if (!startedAt) return;
1064
- const startedMs = Date.parse(startedAt);
1065
- if (!Number.isFinite(startedMs)) return;
1066
- const elapsedMs = Math.max(0, Date.now() - startedMs);
1067
- const seconds = Math.floor(elapsedMs / 1e3);
1068
- const hours = Math.floor(seconds / 3600);
1069
- const minutes = Math.floor(seconds % 3600 / 60);
1070
- const remSeconds = seconds % 60;
1071
- return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}:${remSeconds.toString().padStart(2, "0")}`;
1072
- }
1073
- async function handleStatus(explicitAgentName, flags, command, config) {
1074
- const globalFlags = resolveGlobalFlags(command, config);
1075
- const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
1076
- const [{ probeQueueOwnerHealth }, { agentSessionIdPayload, emitJsonResult }] = await Promise.all([loadQueueIpcModule(), loadOutputRenderModule()]);
1077
- const record = await findSession({
1078
- agentCommand: agent.agentCommand,
1079
- cwd: agent.cwd,
1080
- name: resolveSessionNameFromFlags(flags, command)
1081
- });
1082
- if (!record) {
1083
- if (emitJsonResult(globalFlags.format, {
1084
- action: "status_snapshot",
1085
- status: "no-session",
1086
- summary: "no active session"
1087
- })) return;
1088
- if (globalFlags.format === "quiet") {
1089
- process.stdout.write("no-session\n");
1090
- return;
1091
- }
1092
- process.stdout.write(`session: -\n`);
1093
- process.stdout.write(`agent: ${agent.agentCommand}\n`);
1094
- process.stdout.write(`pid: -\n`);
1095
- process.stdout.write(`status: no-session\n`);
1096
- process.stdout.write(`uptime: -\n`);
1097
- process.stdout.write(`lastPromptTime: -\n`);
1098
- return;
1099
- }
1100
- const health = await probeQueueOwnerHealth(record.acpxRecordId);
1101
- const running = health.healthy;
1102
- const payload = {
1103
- sessionId: record.acpxRecordId,
1104
- agentCommand: record.agentCommand,
1105
- pid: health.pid ?? record.pid ?? null,
1106
- status: running ? "running" : "dead",
1107
- uptime: running ? formatUptime(record.agentStartedAt) ?? null : null,
1108
- lastPromptTime: record.lastPromptAt ?? null,
1109
- exitCode: running ? null : record.lastAgentExitCode ?? null,
1110
- signal: running ? null : record.lastAgentExitSignal ?? null,
1111
- ...agentSessionIdPayload(record.agentSessionId)
1112
- };
1113
- if (emitJsonResult(globalFlags.format, {
1114
- action: "status_snapshot",
1115
- status: running ? "alive" : "dead",
1116
- pid: payload.pid ?? void 0,
1117
- summary: running ? "queue owner healthy" : "queue owner unavailable",
1118
- uptime: payload.uptime ?? void 0,
1119
- lastPromptTime: payload.lastPromptTime ?? void 0,
1120
- exitCode: payload.exitCode ?? void 0,
1121
- signal: payload.signal ?? void 0,
1122
- acpxRecordId: record.acpxRecordId,
1123
- acpxSessionId: record.acpSessionId,
1124
- agentSessionId: record.agentSessionId
1125
- })) return;
1126
- if (globalFlags.format === "quiet") {
1127
- process.stdout.write(`${payload.status}\n`);
1128
- return;
1129
- }
1130
- process.stdout.write(`session: ${payload.sessionId}\n`);
1131
- if ("agentSessionId" in payload) process.stdout.write(`agentSessionId: ${payload.agentSessionId}\n`);
1132
- process.stdout.write(`agent: ${payload.agentCommand}\n`);
1133
- process.stdout.write(`pid: ${payload.pid ?? "-"}\n`);
1134
- process.stdout.write(`status: ${payload.status}\n`);
1135
- process.stdout.write(`uptime: ${payload.uptime ?? "-"}\n`);
1136
- process.stdout.write(`lastPromptTime: ${payload.lastPromptTime ?? "-"}\n`);
1137
- if (payload.status === "dead") {
1138
- process.stdout.write(`exitCode: ${payload.exitCode ?? "-"}\n`);
1139
- process.stdout.write(`signal: ${payload.signal ?? "-"}\n`);
1140
- }
1141
- }
1142
- async function handleConfigShow(command, config) {
1143
- const globalFlags = resolveGlobalFlags(command, config);
1144
- const payload = {
1145
- ...toConfigDisplay(config),
1146
- paths: {
1147
- global: config.globalPath,
1148
- project: config.projectPath
1149
- },
1150
- loaded: {
1151
- global: config.hasGlobalConfig,
1152
- project: config.hasProjectConfig
1153
- }
1154
- };
1155
- if (globalFlags.format === "json") {
1156
- process.stdout.write(`${JSON.stringify(payload)}\n`);
1157
- return;
1158
- }
1159
- process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
1160
- }
1161
- async function handleConfigInit(command, config) {
1162
- const globalFlags = resolveGlobalFlags(command, config);
1163
- const result = await initGlobalConfigFile();
1164
- if (globalFlags.format === "json") {
1165
- process.stdout.write(`${JSON.stringify({
1166
- path: result.path,
1167
- created: result.created
1168
- })}\n`);
1169
- return;
1170
- }
1171
- if (globalFlags.format === "quiet") {
1172
- process.stdout.write(`${result.path}\n`);
1173
- return;
1174
- }
1175
- if (result.created) {
1176
- process.stdout.write(`Created ${result.path}\n`);
1177
- return;
1178
- }
1179
- process.stdout.write(`Config already exists: ${result.path}\n`);
1180
- }
1181
1081
  function registerSessionsCommand(parent, explicitAgentName, config) {
1182
1082
  const sessionsCommand = parent.command("sessions").description("List, ensure, create, or close sessions for this agent");
1183
1083
  sessionsCommand.action(async function() {
@@ -1232,11 +1132,7 @@ function registerSharedAgentSubcommands(parent, explicitAgentName, config, descr
1232
1132
  setConfigCommand.action(async function(key, value, flags) {
1233
1133
  await handleSetConfigOption(explicitAgentName, key, value, flags, this, config);
1234
1134
  });
1235
- const statusCommand = parent.command("status").description(descriptions.status);
1236
- addSessionNameOption(statusCommand);
1237
- statusCommand.action(async function(flags) {
1238
- await handleStatus(explicitAgentName, flags, this, config);
1239
- });
1135
+ registerStatusCommand(parent, explicitAgentName, config, descriptions.status);
1240
1136
  }
1241
1137
  function registerAgentCommand(program, agentName, config) {
1242
1138
  const agentCommand = program.command(agentName).description(`Use ${agentName} agent`).argument("[prompt...]", "Prompt text").enablePositionalOptions().passThroughOptions().showHelpAfterError();
@@ -1255,16 +1151,10 @@ function registerAgentCommand(program, agentName, config) {
1255
1151
  });
1256
1152
  registerSessionsCommand(agentCommand, agentName, config);
1257
1153
  }
1258
- function registerConfigCommand(program, config) {
1259
- const configCommand = program.command("config").description("Inspect and initialize acpx configuration");
1260
- configCommand.command("show").description("Show resolved config").action(async function() {
1261
- await handleConfigShow(this, config);
1262
- });
1263
- configCommand.command("init").description("Create global config template").action(async function() {
1264
- await handleConfigInit(this, config);
1265
- });
1266
- configCommand.action(async function() {
1267
- await handleConfigShow(this, config);
1154
+ function registerFlowCommand(program, config) {
1155
+ 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) {
1156
+ const { handleFlowRun } = await import("./cli-idpWyCOs.js");
1157
+ await handleFlowRun(file, flags, this, config);
1268
1158
  });
1269
1159
  }
1270
1160
  function registerDefaultCommands(program, config) {
@@ -1278,6 +1168,7 @@ function registerDefaultCommands(program, config) {
1278
1168
  });
1279
1169
  registerSessionsCommand(program, void 0, config);
1280
1170
  registerConfigCommand(program, config);
1171
+ registerFlowCommand(program, config);
1281
1172
  }
1282
1173
  function detectAgentToken(argv) {
1283
1174
  let hasAgentOverride = false;
@@ -1353,7 +1244,10 @@ function detectJsonStrict(argv) {
1353
1244
  }
1354
1245
  async function emitJsonErrorEvent(error) {
1355
1246
  const { createOutputFormatter } = await loadOutputModule();
1356
- const formatter = createOutputFormatter("json", { jsonContext: { sessionId: "unknown" } });
1247
+ const formatter = createOutputFormatter("json", {
1248
+ jsonContext: { sessionId: "unknown" },
1249
+ suppressReads: false
1250
+ });
1357
1251
  formatter.onError(error);
1358
1252
  formatter.flush();
1359
1253
  }
@@ -1395,7 +1289,10 @@ async function main(argv = process.argv) {
1395
1289
  }
1396
1290
  const config = await loadResolvedConfig(detectInitialCwd(argv.slice(2)));
1397
1291
  const requestedJsonStrict = detectJsonStrict(argv.slice(2));
1398
- const requestedOutputPolicy = resolveOutputPolicy(detectRequestedOutputFormat(argv.slice(2), config.format), requestedJsonStrict);
1292
+ const requestedOutputPolicy = {
1293
+ ...resolveOutputPolicy(detectRequestedOutputFormat(argv.slice(2), config.format), requestedJsonStrict),
1294
+ suppressReads: argv.slice(2).some((token) => token === "--suppress-reads")
1295
+ };
1399
1296
  const builtInAgents = listBuiltInAgents(config.agents);
1400
1297
  const program = new Command();
1401
1298
  program.name("acpx").description("Headless CLI client for the Agent Client Protocol").version(getAcpxVersion()).enablePositionalOptions().showHelpAfterError();
@@ -1468,6 +1365,8 @@ Examples:
1468
1365
  }
1469
1366
  //#endregion
1470
1367
  //#region src/cli.ts
1368
+ const queueOwnerArgOverride = buildQueueOwnerArgOverride(fileURLToPath(import.meta.url));
1369
+ if (queueOwnerArgOverride) process.env.ACPX_QUEUE_OWNER_ARGS ??= queueOwnerArgOverride;
1471
1370
  function isCliEntrypoint(argv) {
1472
1371
  const entry = argv[1];
1473
1372
  if (!entry) return false;