acpx 0.3.0 → 0.4.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 (34) hide show
  1. package/README.md +67 -16
  2. package/dist/{acp-jsonrpc-BNHXq7qK.js → acp-jsonrpc-C7pPk9Tw.js} +1 -1
  3. package/dist/{acp-jsonrpc-BNHXq7qK.js.map → acp-jsonrpc-C7pPk9Tw.js.map} +1 -1
  4. package/dist/cli-5s-E-Y99.js +176 -0
  5. package/dist/cli-5s-E-Y99.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 -331
  9. package/dist/cli.js.map +1 -1
  10. package/dist/flags-BkWInxAq.js +194 -0
  11. package/dist/flags-BkWInxAq.js.map +1 -0
  12. package/dist/flows-DnIYoHI1.js +1551 -0
  13. package/dist/flows-DnIYoHI1.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-C58ukIo3.js} +137 -14
  18. package/dist/output-C58ukIo3.js.map +1 -0
  19. package/dist/{output-render-DEAaMxg8.js → output-render-C7w9NZ2H.js} +10 -10
  20. package/dist/output-render-C7w9NZ2H.js.map +1 -0
  21. package/dist/{queue-ipc-EQLpBMKv.js → queue-ipc-CgWf63GN.js} +258 -95
  22. package/dist/queue-ipc-CgWf63GN.js.map +1 -0
  23. package/dist/{session-C2Q8ktsN.js → session-BtpTC2pM.js} +687 -138
  24. package/dist/session-BtpTC2pM.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 +36 -16
  28. package/skills/acpx/SKILL.md +23 -6
  29. package/dist/output-BmkPP7qE.js.map +0 -1
  30. package/dist/output-render-DEAaMxg8.js.map +0 -1
  31. package/dist/queue-ipc-EQLpBMKv.js.map +0 -1
  32. package/dist/runtime-session-id-C544sPPL.js +0 -31
  33. package/dist/runtime-session-id-C544sPPL.js.map +0 -1
  34. package/dist/session-C2Q8ktsN.js.map +0 -1
package/dist/cli.js CHANGED
@@ -1,181 +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-BkWInxAq.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-CgWf63GN.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-BtpTC2pM.js";
5
+ import { i as emitJsonResult, n as formatPromptSessionBannerLine, t as agentSessionIdPayload } from "./output-render-C7w9NZ2H.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 DEFAULT_AGENT_NAME = "codex";
34
- function normalizeAgentName(value) {
35
- return value.trim().toLowerCase();
36
- }
37
- function mergeAgentRegistry(overrides) {
38
- if (!overrides) return { ...AGENT_REGISTRY };
39
- const merged = { ...AGENT_REGISTRY };
40
- for (const [name, command] of Object.entries(overrides)) {
41
- const normalized = normalizeAgentName(name);
42
- if (!normalized || !command.trim()) continue;
43
- merged[normalized] = command.trim();
44
- }
45
- return merged;
46
- }
47
- function resolveAgentCommand(agentName, overrides) {
48
- const normalized = normalizeAgentName(agentName);
49
- return mergeAgentRegistry(overrides)[normalized] ?? agentName;
50
- }
51
- function listBuiltInAgents(overrides) {
52
- return Object.keys(mergeAgentRegistry(overrides));
53
- }
54
- //#endregion
55
- //#region src/cli/flags.ts
56
- function parseOutputFormat$1(value) {
57
- if (!OUTPUT_FORMATS.includes(value)) throw new InvalidArgumentError(`Invalid format "${value}". Expected one of: ${OUTPUT_FORMATS.join(", ")}`);
58
- return value;
59
- }
60
- function parseAuthPolicy$1(value) {
61
- if (!AUTH_POLICIES.includes(value)) throw new InvalidArgumentError(`Invalid auth policy "${value}". Expected one of: ${AUTH_POLICIES.join(", ")}`);
62
- return value;
63
- }
64
- function parseNonInteractivePermissionPolicy$1(value) {
65
- if (!NON_INTERACTIVE_PERMISSION_POLICIES.includes(value)) throw new InvalidArgumentError(`Invalid non-interactive permission policy "${value}". Expected one of: ${NON_INTERACTIVE_PERMISSION_POLICIES.join(", ")}`);
66
- return value;
67
- }
68
- function parseTimeoutSeconds(value) {
69
- const parsed = Number(value);
70
- if (!Number.isFinite(parsed) || parsed <= 0) throw new InvalidArgumentError("Timeout must be a positive number of seconds");
71
- return Math.round(parsed * 1e3);
72
- }
73
- function parseTtlSeconds(value) {
74
- const parsed = Number(value);
75
- if (!Number.isFinite(parsed) || parsed < 0) throw new InvalidArgumentError("TTL must be a non-negative number of seconds");
76
- return Math.round(parsed * 1e3);
77
- }
78
- function parseSessionName(value) {
79
- const trimmed = value.trim();
80
- if (trimmed.length === 0) throw new InvalidArgumentError("Session name must not be empty");
81
- return trimmed;
82
- }
83
- function parseNonEmptyValue(label, value) {
84
- const trimmed = value.trim();
85
- if (trimmed.length === 0) throw new InvalidArgumentError(`${label} must not be empty`);
86
- return trimmed;
87
- }
88
- function parseHistoryLimit(value) {
89
- const parsed = Number(value);
90
- if (!Number.isInteger(parsed) || parsed <= 0) throw new InvalidArgumentError("Limit must be a positive integer");
91
- return parsed;
92
- }
93
- function parseAllowedTools(value) {
94
- const trimmed = value.trim();
95
- if (trimmed.length === 0) return [];
96
- const items = trimmed.split(",").map((item) => item.trim());
97
- if (items.some((item) => item.length === 0)) throw new InvalidArgumentError("Allowed tools must be a comma-separated list without empty entries");
98
- return items;
99
- }
100
- function parseMaxTurns(value) {
101
- const parsed = Number(value);
102
- if (!Number.isInteger(parsed) || parsed <= 0) throw new InvalidArgumentError("Max turns must be a positive integer");
103
- return parsed;
104
- }
105
- function resolvePermissionMode(flags, defaultMode) {
106
- if ([
107
- flags.approveAll,
108
- flags.approveReads,
109
- flags.denyAll
110
- ].filter(Boolean).length > 1) throw new InvalidArgumentError("Use only one permission mode: --approve-all, --approve-reads, or --deny-all");
111
- if (flags.approveAll) return "approve-all";
112
- if (flags.denyAll) return "deny-all";
113
- return defaultMode;
114
- }
115
- function addGlobalFlags(command) {
116
- 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");
117
- }
118
- function addSessionOption(command) {
119
- 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");
120
- }
121
- function addSessionNameOption(command) {
122
- return command.option("-s, --session <name>", "Use named session instead of cwd default", parseSessionName);
123
- }
124
- function resolveSessionNameFromFlags(flags, command) {
125
- if (flags.session) return flags.session;
126
- const allOpts = command.optsWithGlobals?.();
127
- if (allOpts && typeof allOpts.session === "string") return parseSessionName(allOpts.session);
128
- const parentOpts = command.parent?.opts?.();
129
- if (parentOpts && typeof parentOpts.session === "string") return parseSessionName(parentOpts.session);
130
- }
131
- function addPromptInputOption(command) {
132
- return command.option("-f, --file <path>", "Read prompt text from file path (use - for stdin)");
133
- }
134
- function resolveGlobalFlags(command, config) {
135
- const opts = command.optsWithGlobals();
136
- const format = opts.format ?? config.format ?? "text";
137
- const jsonStrict = opts.jsonStrict === true;
138
- const verbose = opts.verbose === true;
139
- if (jsonStrict && format !== "json") throw new InvalidArgumentError("--json-strict requires --format json");
140
- if (jsonStrict && verbose) throw new InvalidArgumentError("--json-strict cannot be combined with --verbose");
141
- return {
142
- agent: opts.agent,
143
- cwd: opts.cwd ?? process.cwd(),
144
- authPolicy: opts.authPolicy ?? config.authPolicy,
145
- nonInteractivePermissions: opts.nonInteractivePermissions ?? config.nonInteractivePermissions,
146
- jsonStrict,
147
- timeout: opts.timeout ?? config.timeoutMs,
148
- ttl: opts.ttl ?? config.ttlMs ?? 3e5,
149
- verbose,
150
- format,
151
- model: typeof opts.model === "string" ? parseNonEmptyValue("Model", opts.model) : void 0,
152
- allowedTools: Array.isArray(opts.allowedTools) ? opts.allowedTools : void 0,
153
- maxTurns: typeof opts.maxTurns === "number" ? opts.maxTurns : void 0,
154
- approveAll: opts.approveAll ? true : void 0,
155
- approveReads: opts.approveReads ? true : void 0,
156
- denyAll: opts.denyAll ? true : void 0
157
- };
158
- }
159
- function resolveOutputPolicy(format, jsonStrict) {
160
- return {
161
- format,
162
- jsonStrict,
163
- suppressNonJsonStderr: jsonStrict,
164
- queueErrorAlreadyEmitted: format !== "quiet",
165
- suppressSdkConsoleErrors: jsonStrict
166
- };
167
- }
168
- function resolveAgentInvocation(explicitAgentName, globalFlags, config) {
169
- const override = globalFlags.agent?.trim();
170
- if (override && explicitAgentName) throw new InvalidArgumentError("Do not combine positional agent with --agent override");
171
- const agentName = explicitAgentName ?? config.defaultAgent ?? "codex";
172
- return {
173
- agentName,
174
- agentCommand: override && override.length > 0 ? override : resolveAgentCommand(agentName, config.agents),
175
- cwd: path.resolve(globalFlags.cwd)
176
- };
177
- }
178
- //#endregion
179
12
  //#region src/mcp-servers.ts
180
13
  function asRecord$1(value) {
181
14
  if (!value || typeof value !== "object" || Array.isArray(value)) return;
@@ -498,6 +331,163 @@ async function initGlobalConfigFile() {
498
331
  };
499
332
  }
500
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
501
491
  //#region src/queue-owner-env.ts
502
492
  function asRecord(value) {
503
493
  if (!value || typeof value !== "object" || Array.isArray(value)) return;
@@ -524,6 +514,7 @@ function parseQueueOwnerPayload(raw) {
524
514
  if (typeof record.verbose === "boolean") options.verbose = record.verbose;
525
515
  if (typeof record.ttlMs === "number" && Number.isFinite(record.ttlMs)) options.ttlMs = record.ttlMs;
526
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));
527
518
  return options;
528
519
  }
529
520
  async function runQueueOwnerFromEnv(env) {
@@ -583,6 +574,7 @@ const TOP_LEVEL_VERBS = new Set([
583
574
  "prompt",
584
575
  "exec",
585
576
  "cancel",
577
+ "flow",
586
578
  "set-mode",
587
579
  "set",
588
580
  "sessions",
@@ -618,40 +610,32 @@ function applyPermissionExitCode(result) {
618
610
  const deniedOrCancelled = stats.denied + stats.cancelled;
619
611
  if (stats.requested > 0 && stats.approved === 0 && deniedOrCancelled > 0) process.exitCode = EXIT_CODES.PERMISSION_DENIED;
620
612
  }
621
- function emitJsonResult(format, payload) {
622
- if (format !== "json") return false;
623
- process.stdout.write(`${JSON.stringify(payload)}\n`);
624
- return true;
625
- }
626
- function isCodexAgentInvocation(agent) {
627
- if (agent.agentName === "codex") return true;
628
- return /\bcodex-acp\b/.test(agent.agentCommand);
629
- }
630
613
  function resolveCompatibleConfigId(agent, configId) {
631
- if (isCodexAgentInvocation(agent) && configId === "thought_level") return "reasoning_effort";
614
+ if (isCodexInvocation(agent.agentName, agent.agentCommand) && configId === "thought_level") return "reasoning_effort";
632
615
  return configId;
633
616
  }
617
+ function resolveRequestedOutputPolicy(globalFlags) {
618
+ return {
619
+ ...resolveOutputPolicy(globalFlags.format, globalFlags.jsonStrict === true),
620
+ suppressReads: globalFlags.suppressReads === true
621
+ };
622
+ }
634
623
  let sessionModulePromise;
635
624
  let outputModulePromise;
636
625
  let outputRenderModulePromise;
637
- let queueIpcModulePromise;
638
626
  let skillflagModulePromise;
639
627
  function loadSessionModule() {
640
- sessionModulePromise ??= import("./session-C2Q8ktsN.js").then((n) => n.t);
628
+ sessionModulePromise ??= import("./session-BtpTC2pM.js").then((n) => n.t);
641
629
  return sessionModulePromise;
642
630
  }
643
631
  function loadOutputModule() {
644
- outputModulePromise ??= import("./output-BmkPP7qE.js");
632
+ outputModulePromise ??= import("./output-C58ukIo3.js").then((n) => n.n);
645
633
  return outputModulePromise;
646
634
  }
647
635
  function loadOutputRenderModule() {
648
- outputRenderModulePromise ??= import("./output-render-DEAaMxg8.js").then((n) => n.n);
636
+ outputRenderModulePromise ??= import("./output-render-C7w9NZ2H.js").then((n) => n.r);
649
637
  return outputRenderModulePromise;
650
638
  }
651
- function loadQueueIpcModule() {
652
- queueIpcModulePromise ??= import("./queue-ipc-EQLpBMKv.js").then((n) => n.r);
653
- return queueIpcModulePromise;
654
- }
655
639
  function loadSkillflagModule() {
656
640
  skillflagModulePromise ??= import("skillflag");
657
641
  return skillflagModulePromise;
@@ -672,7 +656,7 @@ async function findRoutedSessionOrThrow(agentCommand, agentName, cwd, sessionNam
672
656
  }
673
657
  async function handlePrompt(explicitAgentName, promptParts, flags, command, config) {
674
658
  const globalFlags = resolveGlobalFlags(command, config);
675
- const outputPolicy = resolveOutputPolicy(globalFlags.format, globalFlags.jsonStrict === true);
659
+ const outputPolicy = resolveRequestedOutputPolicy(globalFlags);
676
660
  const permissionMode = resolvePermissionMode(globalFlags, config.defaultPermissions);
677
661
  const prompt = await readPrompt(promptParts, flags.file, globalFlags.cwd);
678
662
  const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
@@ -682,7 +666,10 @@ async function handlePrompt(explicitAgentName, promptParts, flags, command, conf
682
666
  loadSessionModule()
683
667
  ]);
684
668
  const record = await findRoutedSessionOrThrow(agent.agentCommand, agent.agentName, agent.cwd, flags.session);
685
- 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
+ });
686
673
  await printPromptSessionBanner(record, agent.cwd, outputPolicy.format, outputPolicy.jsonStrict);
687
674
  const result = await sendSession({
688
675
  sessionId: record.acpxRecordId,
@@ -698,6 +685,7 @@ async function handlePrompt(explicitAgentName, promptParts, flags, command, conf
698
685
  timeoutMs: globalFlags.timeout,
699
686
  ttlMs: globalFlags.ttl,
700
687
  maxQueueDepth: config.queueMaxDepth,
688
+ promptRetries: globalFlags.promptRetries,
701
689
  verbose: globalFlags.verbose,
702
690
  waitForCompletion: flags.wait !== false
703
691
  });
@@ -710,8 +698,7 @@ async function handlePrompt(explicitAgentName, promptParts, flags, command, conf
710
698
  }
711
699
  async function handleExec(explicitAgentName, promptParts, flags, command, config) {
712
700
  if (config.disableExec) {
713
- const globalFlags = resolveGlobalFlags(command, config);
714
- 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({
715
702
  jsonrpc: "2.0",
716
703
  error: {
717
704
  code: -32603,
@@ -724,11 +711,11 @@ async function handleExec(explicitAgentName, promptParts, flags, command, config
724
711
  return;
725
712
  }
726
713
  const globalFlags = resolveGlobalFlags(command, config);
727
- const outputPolicy = resolveOutputPolicy(globalFlags.format, globalFlags.jsonStrict === true);
714
+ const outputPolicy = resolveRequestedOutputPolicy(globalFlags);
728
715
  const permissionMode = resolvePermissionMode(globalFlags, config.defaultPermissions);
729
716
  const prompt = await readPrompt(promptParts, flags.file, globalFlags.cwd);
730
717
  const [{ createOutputFormatter }, { runOnce }] = await Promise.all([loadOutputModule(), loadSessionModule()]);
731
- const outputFormatter = createOutputFormatter(outputPolicy.format);
718
+ const outputFormatter = createOutputFormatter(outputPolicy.format, { suppressReads: outputPolicy.suppressReads });
732
719
  const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
733
720
  applyPermissionExitCode(await runOnce({
734
721
  agentCommand: agent.agentCommand,
@@ -743,6 +730,7 @@ async function handleExec(explicitAgentName, promptParts, flags, command, config
743
730
  suppressSdkConsoleErrors: outputPolicy.suppressSdkConsoleErrors,
744
731
  timeoutMs: globalFlags.timeout,
745
732
  verbose: globalFlags.verbose,
733
+ promptRetries: globalFlags.promptRetries,
746
734
  sessionOptions: {
747
735
  model: globalFlags.model,
748
736
  allowedTools: globalFlags.allowedTools,
@@ -777,6 +765,21 @@ function printSetModeResultByFormat(modeId, result, format) {
777
765
  }
778
766
  process.stdout.write(`mode set: ${modeId}\n`);
779
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
+ }
780
783
  function printSetConfigOptionResultByFormat(configId, value, result, format) {
781
784
  if (emitJsonResult(format, {
782
785
  action: "config_set",
@@ -834,9 +837,30 @@ async function handleSetMode(explicitAgentName, modeId, flags, command, config)
834
837
  if (globalFlags.verbose && result.loadError) process.stderr.write(`[acpx] loadSession failed, started fresh session: ${result.loadError}\n`);
835
838
  printSetModeResultByFormat(modeId, result, globalFlags.format);
836
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
+ }
837
857
  async function handleSetConfigOption(explicitAgentName, configId, value, flags, command, config) {
838
858
  const globalFlags = resolveGlobalFlags(command, config);
839
859
  const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
860
+ if (configId === "model") {
861
+ await handleSetModel(explicitAgentName, value, flags, command, config);
862
+ return;
863
+ }
840
864
  const resolvedConfigId = resolveCompatibleConfigId(agent, configId);
841
865
  const { setSessionConfigOption } = await loadSessionModule();
842
866
  const result = await setSessionConfigOption({
@@ -1054,125 +1078,6 @@ async function handleSessionsHistory(explicitAgentName, sessionName, flags, comm
1054
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}`);
1055
1079
  printSessionHistoryByFormat(record, flags.limit, globalFlags.format);
1056
1080
  }
1057
- function formatUptime(startedAt) {
1058
- if (!startedAt) return;
1059
- const startedMs = Date.parse(startedAt);
1060
- if (!Number.isFinite(startedMs)) return;
1061
- const elapsedMs = Math.max(0, Date.now() - startedMs);
1062
- const seconds = Math.floor(elapsedMs / 1e3);
1063
- const hours = Math.floor(seconds / 3600);
1064
- const minutes = Math.floor(seconds % 3600 / 60);
1065
- const remSeconds = seconds % 60;
1066
- return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}:${remSeconds.toString().padStart(2, "0")}`;
1067
- }
1068
- async function handleStatus(explicitAgentName, flags, command, config) {
1069
- const globalFlags = resolveGlobalFlags(command, config);
1070
- const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
1071
- const [{ probeQueueOwnerHealth }, { agentSessionIdPayload, emitJsonResult }] = await Promise.all([loadQueueIpcModule(), loadOutputRenderModule()]);
1072
- const record = await findSession({
1073
- agentCommand: agent.agentCommand,
1074
- cwd: agent.cwd,
1075
- name: resolveSessionNameFromFlags(flags, command)
1076
- });
1077
- if (!record) {
1078
- if (emitJsonResult(globalFlags.format, {
1079
- action: "status_snapshot",
1080
- status: "no-session",
1081
- summary: "no active session"
1082
- })) return;
1083
- if (globalFlags.format === "quiet") {
1084
- process.stdout.write("no-session\n");
1085
- return;
1086
- }
1087
- process.stdout.write(`session: -\n`);
1088
- process.stdout.write(`agent: ${agent.agentCommand}\n`);
1089
- process.stdout.write(`pid: -\n`);
1090
- process.stdout.write(`status: no-session\n`);
1091
- process.stdout.write(`uptime: -\n`);
1092
- process.stdout.write(`lastPromptTime: -\n`);
1093
- return;
1094
- }
1095
- const health = await probeQueueOwnerHealth(record.acpxRecordId);
1096
- const running = health.healthy;
1097
- const payload = {
1098
- sessionId: record.acpxRecordId,
1099
- agentCommand: record.agentCommand,
1100
- pid: health.pid ?? record.pid ?? null,
1101
- status: running ? "running" : "dead",
1102
- uptime: running ? formatUptime(record.agentStartedAt) ?? null : null,
1103
- lastPromptTime: record.lastPromptAt ?? null,
1104
- exitCode: running ? null : record.lastAgentExitCode ?? null,
1105
- signal: running ? null : record.lastAgentExitSignal ?? null,
1106
- ...agentSessionIdPayload(record.agentSessionId)
1107
- };
1108
- if (emitJsonResult(globalFlags.format, {
1109
- action: "status_snapshot",
1110
- status: running ? "alive" : "dead",
1111
- pid: payload.pid ?? void 0,
1112
- summary: running ? "queue owner healthy" : "queue owner unavailable",
1113
- uptime: payload.uptime ?? void 0,
1114
- lastPromptTime: payload.lastPromptTime ?? void 0,
1115
- exitCode: payload.exitCode ?? void 0,
1116
- signal: payload.signal ?? void 0,
1117
- acpxRecordId: record.acpxRecordId,
1118
- acpxSessionId: record.acpSessionId,
1119
- agentSessionId: record.agentSessionId
1120
- })) return;
1121
- if (globalFlags.format === "quiet") {
1122
- process.stdout.write(`${payload.status}\n`);
1123
- return;
1124
- }
1125
- process.stdout.write(`session: ${payload.sessionId}\n`);
1126
- if ("agentSessionId" in payload) process.stdout.write(`agentSessionId: ${payload.agentSessionId}\n`);
1127
- process.stdout.write(`agent: ${payload.agentCommand}\n`);
1128
- process.stdout.write(`pid: ${payload.pid ?? "-"}\n`);
1129
- process.stdout.write(`status: ${payload.status}\n`);
1130
- process.stdout.write(`uptime: ${payload.uptime ?? "-"}\n`);
1131
- process.stdout.write(`lastPromptTime: ${payload.lastPromptTime ?? "-"}\n`);
1132
- if (payload.status === "dead") {
1133
- process.stdout.write(`exitCode: ${payload.exitCode ?? "-"}\n`);
1134
- process.stdout.write(`signal: ${payload.signal ?? "-"}\n`);
1135
- }
1136
- }
1137
- async function handleConfigShow(command, config) {
1138
- const globalFlags = resolveGlobalFlags(command, config);
1139
- const payload = {
1140
- ...toConfigDisplay(config),
1141
- paths: {
1142
- global: config.globalPath,
1143
- project: config.projectPath
1144
- },
1145
- loaded: {
1146
- global: config.hasGlobalConfig,
1147
- project: config.hasProjectConfig
1148
- }
1149
- };
1150
- if (globalFlags.format === "json") {
1151
- process.stdout.write(`${JSON.stringify(payload)}\n`);
1152
- return;
1153
- }
1154
- process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
1155
- }
1156
- async function handleConfigInit(command, config) {
1157
- const globalFlags = resolveGlobalFlags(command, config);
1158
- const result = await initGlobalConfigFile();
1159
- if (globalFlags.format === "json") {
1160
- process.stdout.write(`${JSON.stringify({
1161
- path: result.path,
1162
- created: result.created
1163
- })}\n`);
1164
- return;
1165
- }
1166
- if (globalFlags.format === "quiet") {
1167
- process.stdout.write(`${result.path}\n`);
1168
- return;
1169
- }
1170
- if (result.created) {
1171
- process.stdout.write(`Created ${result.path}\n`);
1172
- return;
1173
- }
1174
- process.stdout.write(`Config already exists: ${result.path}\n`);
1175
- }
1176
1081
  function registerSessionsCommand(parent, explicitAgentName, config) {
1177
1082
  const sessionsCommand = parent.command("sessions").description("List, ensure, create, or close sessions for this agent");
1178
1083
  sessionsCommand.action(async function() {
@@ -1227,11 +1132,7 @@ function registerSharedAgentSubcommands(parent, explicitAgentName, config, descr
1227
1132
  setConfigCommand.action(async function(key, value, flags) {
1228
1133
  await handleSetConfigOption(explicitAgentName, key, value, flags, this, config);
1229
1134
  });
1230
- const statusCommand = parent.command("status").description(descriptions.status);
1231
- addSessionNameOption(statusCommand);
1232
- statusCommand.action(async function(flags) {
1233
- await handleStatus(explicitAgentName, flags, this, config);
1234
- });
1135
+ registerStatusCommand(parent, explicitAgentName, config, descriptions.status);
1235
1136
  }
1236
1137
  function registerAgentCommand(program, agentName, config) {
1237
1138
  const agentCommand = program.command(agentName).description(`Use ${agentName} agent`).argument("[prompt...]", "Prompt text").enablePositionalOptions().passThroughOptions().showHelpAfterError();
@@ -1250,16 +1151,10 @@ function registerAgentCommand(program, agentName, config) {
1250
1151
  });
1251
1152
  registerSessionsCommand(agentCommand, agentName, config);
1252
1153
  }
1253
- function registerConfigCommand(program, config) {
1254
- const configCommand = program.command("config").description("Inspect and initialize acpx configuration");
1255
- configCommand.command("show").description("Show resolved config").action(async function() {
1256
- await handleConfigShow(this, config);
1257
- });
1258
- configCommand.command("init").description("Create global config template").action(async function() {
1259
- await handleConfigInit(this, config);
1260
- });
1261
- configCommand.action(async function() {
1262
- 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-5s-E-Y99.js");
1157
+ await handleFlowRun(file, flags, this, config);
1263
1158
  });
1264
1159
  }
1265
1160
  function registerDefaultCommands(program, config) {
@@ -1273,6 +1168,7 @@ function registerDefaultCommands(program, config) {
1273
1168
  });
1274
1169
  registerSessionsCommand(program, void 0, config);
1275
1170
  registerConfigCommand(program, config);
1171
+ registerFlowCommand(program, config);
1276
1172
  }
1277
1173
  function detectAgentToken(argv) {
1278
1174
  let hasAgentOverride = false;
@@ -1348,7 +1244,10 @@ function detectJsonStrict(argv) {
1348
1244
  }
1349
1245
  async function emitJsonErrorEvent(error) {
1350
1246
  const { createOutputFormatter } = await loadOutputModule();
1351
- const formatter = createOutputFormatter("json", { jsonContext: { sessionId: "unknown" } });
1247
+ const formatter = createOutputFormatter("json", {
1248
+ jsonContext: { sessionId: "unknown" },
1249
+ suppressReads: false
1250
+ });
1352
1251
  formatter.onError(error);
1353
1252
  formatter.flush();
1354
1253
  }
@@ -1390,7 +1289,10 @@ async function main(argv = process.argv) {
1390
1289
  }
1391
1290
  const config = await loadResolvedConfig(detectInitialCwd(argv.slice(2)));
1392
1291
  const requestedJsonStrict = detectJsonStrict(argv.slice(2));
1393
- 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
+ };
1394
1296
  const builtInAgents = listBuiltInAgents(config.agents);
1395
1297
  const program = new Command();
1396
1298
  program.name("acpx").description("Headless CLI client for the Agent Client Protocol").version(getAcpxVersion()).enablePositionalOptions().showHelpAfterError();
@@ -1463,6 +1365,8 @@ Examples:
1463
1365
  }
1464
1366
  //#endregion
1465
1367
  //#region src/cli.ts
1368
+ const queueOwnerArgOverride = buildQueueOwnerArgOverride(fileURLToPath(import.meta.url));
1369
+ if (queueOwnerArgOverride) process.env.ACPX_QUEUE_OWNER_ARGS ??= queueOwnerArgOverride;
1466
1370
  function isCliEntrypoint(argv) {
1467
1371
  const entry = argv[1];
1468
1372
  if (!entry) return false;