acpx 0.7.0 → 0.8.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 (49) hide show
  1. package/README.md +7 -2
  2. package/dist/{cli-T-Z-9x6a.js → cli-BGYGVo3b.js} +35 -10
  3. package/dist/cli-BGYGVo3b.js.map +1 -0
  4. package/dist/cli.d.ts +1 -1
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +204 -19
  7. package/dist/cli.js.map +1 -1
  8. package/dist/{client-COPilhO_.d.ts → client-FzXPdgP7.d.ts} +7 -3
  9. package/dist/client-FzXPdgP7.d.ts.map +1 -0
  10. package/dist/{flags-Dj-IXgo9.js → flags-D706STfk.js} +46 -6
  11. package/dist/flags-D706STfk.js.map +1 -0
  12. package/dist/{flows-CF8w1rPI.js → flows-hcjHmU7P.js} +8 -5
  13. package/dist/flows-hcjHmU7P.js.map +1 -0
  14. package/dist/flows.d.ts +3 -2
  15. package/dist/flows.d.ts.map +1 -1
  16. package/dist/flows.js +1 -1
  17. package/dist/{prompt-turn-CVPMWdj1.js → live-checkpoint-B9ctAuqV.js} +1301 -78
  18. package/dist/live-checkpoint-B9ctAuqV.js.map +1 -0
  19. package/dist/output-BL9XRWzS.js +3712 -0
  20. package/dist/output-BL9XRWzS.js.map +1 -0
  21. package/dist/runtime.d.ts +28 -4
  22. package/dist/runtime.d.ts.map +1 -1
  23. package/dist/runtime.js +153 -24
  24. package/dist/runtime.js.map +1 -1
  25. package/dist/{types-CVBeQyi3.d.ts → session-options-BJyG6zEH.d.ts} +56 -3
  26. package/dist/session-options-BJyG6zEH.d.ts.map +1 -0
  27. package/package.json +23 -21
  28. package/skills/acpx/SKILL.md +200 -10
  29. package/dist/cli-T-Z-9x6a.js.map +0 -1
  30. package/dist/client-COPilhO_.d.ts.map +0 -1
  31. package/dist/flags-Dj-IXgo9.js.map +0 -1
  32. package/dist/flows-CF8w1rPI.js.map +0 -1
  33. package/dist/ipc-ABXlXzGP.js +0 -1290
  34. package/dist/ipc-ABXlXzGP.js.map +0 -1
  35. package/dist/jsonrpc-DSxh2w5R.js +0 -68
  36. package/dist/jsonrpc-DSxh2w5R.js.map +0 -1
  37. package/dist/output-DmHvT8vm.js +0 -807
  38. package/dist/output-DmHvT8vm.js.map +0 -1
  39. package/dist/perf-metrics-C2pXfxvR.js +0 -598
  40. package/dist/perf-metrics-C2pXfxvR.js.map +0 -1
  41. package/dist/prompt-turn-CVPMWdj1.js.map +0 -1
  42. package/dist/render-N5YwotCy.js +0 -172
  43. package/dist/render-N5YwotCy.js.map +0 -1
  44. package/dist/rolldown-runtime-CiIaOW0V.js +0 -13
  45. package/dist/session-CDaQe6BH.js +0 -1538
  46. package/dist/session-CDaQe6BH.js.map +0 -1
  47. package/dist/session-options-pCbHn_n7.d.ts +0 -13
  48. package/dist/session-options-pCbHn_n7.d.ts.map +0 -1
  49. package/dist/types-CVBeQyi3.d.ts.map +0 -1
package/README.md CHANGED
@@ -86,8 +86,12 @@ I want you to use acpx to run coding agents over the Agent Client Protocol
86
86
  Or without installing:
87
87
  npx acpx@latest
88
88
 
89
- 2. Install the acpx skill so you have the full reference available:
90
- npx acpx@latest --skill install acpx
89
+ 2. For Pi or OpenClaw, use the reference URL below. For Codex-style skill
90
+ installation, install the acpx skill so you have the full reference
91
+ available:
92
+ npx acpx@latest --skill install acpx --agent codex --scope user
93
+ Use --agent claude for Claude Code. For another harness not listed by
94
+ --skill install --help, use the reference URL below instead.
91
95
 
92
96
  3. Read the acpx skill reference so you know every command, flag, and
93
97
  workflow pattern:
@@ -202,6 +206,7 @@ acpx --approve-all codex 'apply the patch and run tests'
202
206
  acpx --approve-reads codex 'inspect repo structure and suggest plan' # default mode
203
207
  acpx --deny-all codex 'explain what you can do without tool access'
204
208
  acpx --non-interactive-permissions fail codex 'fail instead of deny in non-TTY'
209
+ acpx --policy '{"escalate":["execute"],"defaultAction":"deny"}' --format json codex exec 'ask before shell'
205
210
 
206
211
  acpx --cwd ~/repos/backend codex 'review recent auth changes'
207
212
  acpx --format text codex 'summarize your findings'
@@ -1,6 +1,6 @@
1
- import { w as permissionModeSatisfies } from "./prompt-turn-CVPMWdj1.js";
2
- import { _ as resolvePermissionMode, a as hasExplicitPermissionModeFlag, g as resolveOutputPolicy, h as resolveGlobalFlags, m as resolveAgentInvocation } from "./flags-Dj-IXgo9.js";
3
- import { c as validateFlowDefinition, h as isDefinedFlow, o as FlowRunner } from "./flows-CF8w1rPI.js";
1
+ import { j as permissionModeSatisfies } from "./live-checkpoint-B9ctAuqV.js";
2
+ import { _ as resolveOutputPolicy, a as hasExplicitPermissionModeFlag, b as loadPermissionPolicySpec, g as resolveGlobalFlags, h as resolveAgentInvocation, v as resolvePermissionMode } from "./flags-D706STfk.js";
3
+ import { c as validateFlowDefinition, h as isDefinedFlow, o as FlowRunner } from "./flows-hcjHmU7P.js";
4
4
  import { fileURLToPath, pathToFileURL } from "node:url";
5
5
  import path from "node:path";
6
6
  import { InvalidArgumentError } from "commander";
@@ -20,6 +20,7 @@ const TEXT_MODULE_EXTENSIONS = new Set([
20
20
  async function handleFlowRun(flowFile, flags, command, config) {
21
21
  const globalFlags = resolveGlobalFlags(command, config);
22
22
  const permissionMode = resolvePermissionMode(globalFlags, config.defaultPermissions);
23
+ const permissionPolicy = await resolveFlowPermissionPolicy(globalFlags);
23
24
  const outputPolicy = resolveOutputPolicy(globalFlags.format, globalFlags.jsonStrict === true);
24
25
  const input = await readFlowInput(flags);
25
26
  const flowPath = path.resolve(flowFile);
@@ -32,6 +33,7 @@ async function handleFlowRun(flowFile, flags, command, config) {
32
33
  permissionMode,
33
34
  mcpServers: config.mcpServers,
34
35
  nonInteractivePermissions: globalFlags.nonInteractivePermissions,
36
+ permissionPolicy,
35
37
  authCredentials: config.auth,
36
38
  authPolicy: globalFlags.authPolicy,
37
39
  timeoutMs: globalFlags.timeout,
@@ -45,6 +47,13 @@ async function handleFlowRun(flowFile, flags, command, config) {
45
47
  }
46
48
  }).run(flow, input, { flowPath }), globalFlags);
47
49
  }
50
+ async function resolveFlowPermissionPolicy(globalFlags) {
51
+ try {
52
+ return await loadPermissionPolicySpec(globalFlags.permissionPolicy, globalFlags.cwd);
53
+ } catch (error) {
54
+ throw new InvalidArgumentError(`Invalid permission policy: ${error instanceof Error ? error.message : String(error)}`);
55
+ }
56
+ }
48
57
  function assertFlowPermissionRequirements(flow, permissionMode, globalFlags) {
49
58
  const permissions = flow.permissions;
50
59
  if (!permissions) return;
@@ -98,14 +107,30 @@ async function prepareFlowModuleImport(flowPath, extension) {
98
107
  }
99
108
  function resolveFlowRuntimeImportSpecifier() {
100
109
  const selfPath = fileURLToPath(import.meta.url);
101
- if (selfPath.endsWith(`${path.sep}src${path.sep}flows${path.sep}cli.ts`)) return new URL("../flows.ts", import.meta.url).href;
102
- if (selfPath.endsWith(`${path.sep}src${path.sep}flows${path.sep}cli.js`)) return new URL("../flows.js", import.meta.url).href;
103
- return new URL("./flows.js", import.meta.url).href;
110
+ let runtimePath;
111
+ if (selfPath.endsWith(`${path.sep}src${path.sep}flows${path.sep}cli.ts`)) runtimePath = fileURLToPath(new URL("../flows.ts", import.meta.url));
112
+ else if (selfPath.endsWith(`${path.sep}src${path.sep}flows${path.sep}cli.js`)) runtimePath = fileURLToPath(new URL("../flows.js", import.meta.url));
113
+ else runtimePath = fileURLToPath(new URL("./flows.js", import.meta.url));
114
+ return runtimePath.replaceAll(path.sep, "/");
104
115
  }
105
116
  async function loadFlowRuntimeModule(flowUrl, extension) {
106
- if (extension === ".ts" || extension === ".tsx" || extension === ".mts" || extension === ".cts") {
107
- const { tsImport } = await import("tsx/esm/api");
108
- return await tsImport(flowUrl, import.meta.url);
117
+ if (extension === ".ts" || extension === ".tsx" || extension === ".cts") {
118
+ const { register } = await import("tsx/cjs/api");
119
+ const loader = register({ namespace: randomUUID() });
120
+ try {
121
+ return loader.require(flowUrl, import.meta.url);
122
+ } finally {
123
+ loader.unregister();
124
+ }
125
+ }
126
+ if (extension === ".mts") {
127
+ const { register } = await import("tsx/esm/api");
128
+ const loader = register({ namespace: randomUUID() });
129
+ try {
130
+ return await loader.import(flowUrl, import.meta.url);
131
+ } finally {
132
+ await loader.unregister();
133
+ }
109
134
  }
110
135
  return await import(flowUrl);
111
136
  }
@@ -169,4 +194,4 @@ function printFlowRunResult(result, globalFlags) {
169
194
  //#endregion
170
195
  export { handleFlowRun };
171
196
 
172
- //# sourceMappingURL=cli-T-Z-9x6a.js.map
197
+ //# sourceMappingURL=cli-BGYGVo3b.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-BGYGVo3b.js","names":[],"sources":["../src/flows/cli.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { InvalidArgumentError, type Command } from \"commander\";\nimport type { ResolvedAcpxConfig } from \"../cli/config.js\";\nimport {\n hasExplicitPermissionModeFlag,\n resolveAgentInvocation,\n resolveGlobalFlags,\n resolveOutputPolicy,\n resolvePermissionMode,\n type GlobalFlags,\n} from \"../cli/flags.js\";\nimport { type FlowDefinition, FlowRunner } from \"../flows.js\";\nimport { loadPermissionPolicySpec } from \"../permission-policy.js\";\nimport { permissionModeSatisfies } from \"../permissions.js\";\nimport type { PermissionMode } from \"../types.js\";\nimport { isDefinedFlow } from \"./authoring.js\";\nimport { validateFlowDefinition } from \"./graph.js\";\n\ntype FlowRunFlags = {\n inputJson?: string;\n inputFile?: string;\n defaultAgent?: string;\n};\n\nconst FLOW_RUNTIME_SPECIFIER = \"acpx/flows\";\nconst TEXT_MODULE_EXTENSIONS = new Set([\".js\", \".mjs\", \".cjs\", \".ts\", \".tsx\", \".mts\", \".cts\"]);\n\nexport async function handleFlowRun(\n flowFile: string,\n flags: FlowRunFlags,\n command: Command,\n config: ResolvedAcpxConfig,\n): Promise<void> {\n const globalFlags = resolveGlobalFlags(command, config);\n const permissionMode = resolvePermissionMode(globalFlags, config.defaultPermissions);\n const permissionPolicy = await resolveFlowPermissionPolicy(globalFlags);\n const outputPolicy = resolveOutputPolicy(globalFlags.format, globalFlags.jsonStrict === true);\n const input = await readFlowInput(flags);\n const flowPath = path.resolve(flowFile);\n const flow = await loadFlowModule(flowPath);\n assertFlowPermissionRequirements(flow, permissionMode, globalFlags);\n\n const runner = new FlowRunner({\n resolveAgent: (profile?: string) => {\n return resolveAgentInvocation(profile ?? flags.defaultAgent, globalFlags, config);\n },\n permissionMode,\n mcpServers: config.mcpServers,\n nonInteractivePermissions: globalFlags.nonInteractivePermissions,\n permissionPolicy,\n authCredentials: config.auth,\n authPolicy: globalFlags.authPolicy,\n timeoutMs: globalFlags.timeout,\n ttlMs: globalFlags.ttl,\n verbose: globalFlags.verbose,\n suppressSdkConsoleErrors: outputPolicy.suppressSdkConsoleErrors,\n sessionOptions: {\n model: globalFlags.model,\n allowedTools: globalFlags.allowedTools,\n maxTurns: globalFlags.maxTurns,\n },\n });\n\n const result = await runner.run(flow, input, {\n flowPath,\n });\n\n printFlowRunResult(result, globalFlags);\n}\n\nasync function resolveFlowPermissionPolicy(globalFlags: GlobalFlags) {\n try {\n return await loadPermissionPolicySpec(globalFlags.permissionPolicy, globalFlags.cwd);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new InvalidArgumentError(`Invalid permission policy: ${message}`);\n }\n}\n\nfunction assertFlowPermissionRequirements(\n flow: FlowDefinition,\n permissionMode: PermissionMode,\n globalFlags: GlobalFlags,\n): void {\n const permissions = flow.permissions;\n if (!permissions) {\n return;\n }\n\n if (permissions.requireExplicitGrant && !hasExplicitPermissionModeFlag(globalFlags)) {\n throw new InvalidArgumentError(\n buildFlowPermissionFailureMessage(flow, permissions.requiredMode, permissions.reason, true),\n );\n }\n\n if (!permissionModeSatisfies(permissionMode, permissions.requiredMode)) {\n throw new InvalidArgumentError(\n buildFlowPermissionFailureMessage(flow, permissions.requiredMode, permissions.reason, false),\n );\n }\n}\n\nfunction buildFlowPermissionFailureMessage(\n flow: FlowDefinition,\n requiredMode: PermissionMode,\n reason?: string,\n explicit = false,\n): string {\n return [\n explicit\n ? `Flow \"${flow.name}\" requires an explicit ${requiredMode} grant.`\n : `Flow \"${flow.name}\" requires permission mode ${requiredMode}.`,\n `Rerun with --${requiredMode}.`,\n ...(reason ? [`Reason: ${reason}`] : []),\n ].join(\" \");\n}\n\nasync function readFlowInput(flags: FlowRunFlags): Promise<unknown> {\n if (flags.inputJson && flags.inputFile) {\n throw new InvalidArgumentError(\"Use only one of --input-json or --input-file\");\n }\n\n if (flags.inputJson) {\n return parseJsonInput(flags.inputJson, \"--input-json\");\n }\n\n if (flags.inputFile) {\n const inputPath = path.resolve(flags.inputFile);\n const payload = await fs.readFile(inputPath, \"utf8\");\n return parseJsonInput(payload, \"--input-file\");\n }\n\n return {};\n}\n\nasync function loadFlowModule(flowPath: string): Promise<FlowDefinition> {\n const extension = path.extname(flowPath).toLowerCase();\n const prepared = await prepareFlowModuleImport(flowPath, extension);\n try {\n const module = await loadFlowRuntimeModule(prepared.flowUrl, extension);\n\n const candidate = findFlowDefinition(module);\n if (!candidate) {\n throw new Error(\n `Flow module must export default defineFlow({...}) from \"acpx/flows\": ${flowPath}`,\n );\n }\n validateFlowDefinition(candidate);\n return candidate;\n } finally {\n await prepared.cleanup?.();\n }\n}\n\nasync function prepareFlowModuleImport(\n flowPath: string,\n extension: string,\n): Promise<{\n flowUrl: string;\n cleanup?: () => Promise<void>;\n}> {\n const flowUrl = pathToFileURL(flowPath).href;\n if (!TEXT_MODULE_EXTENSIONS.has(extension)) {\n return { flowUrl };\n }\n\n const source = await fs.readFile(flowPath, \"utf8\");\n if (!source.includes(FLOW_RUNTIME_SPECIFIER)) {\n return { flowUrl };\n }\n\n const runtimeSpecifier = resolveFlowRuntimeImportSpecifier();\n const rewritten = source.replaceAll(\n /([\"'])acpx\\/flows\\1/g,\n (_match, quote: string) => `${quote}${runtimeSpecifier}${quote}`,\n );\n if (rewritten === source) {\n return { flowUrl };\n }\n\n const tempPath = path.join(path.dirname(flowPath), `.acpx-flow-load-${randomUUID()}${extension}`);\n await fs.writeFile(tempPath, rewritten, \"utf8\");\n return {\n flowUrl: pathToFileURL(tempPath).href,\n cleanup: async () => {\n await fs.rm(tempPath, { force: true });\n },\n };\n}\n\nfunction resolveFlowRuntimeImportSpecifier(): string {\n const selfPath = fileURLToPath(import.meta.url);\n let runtimePath: string;\n\n if (selfPath.endsWith(`${path.sep}src${path.sep}flows${path.sep}cli.ts`)) {\n runtimePath = fileURLToPath(new URL(\"../flows.ts\", import.meta.url));\n } else if (selfPath.endsWith(`${path.sep}src${path.sep}flows${path.sep}cli.js`)) {\n runtimePath = fileURLToPath(new URL(\"../flows.js\", import.meta.url));\n } else {\n runtimePath = fileURLToPath(new URL(\"./flows.js\", import.meta.url));\n }\n return runtimePath.replaceAll(path.sep, \"/\");\n}\n\nasync function loadFlowRuntimeModule(\n flowUrl: string,\n extension: string,\n): Promise<{\n default?: unknown;\n \"module.exports\"?: unknown;\n}> {\n if (extension === \".ts\" || extension === \".tsx\" || extension === \".cts\") {\n const { register } = (await import(\"tsx/cjs/api\")) as {\n register: (options: { namespace: string }) => {\n require: (\n specifier: string,\n parentURL: string,\n ) => {\n default?: unknown;\n \"module.exports\"?: unknown;\n };\n unregister: () => void;\n };\n };\n const loader = register({ namespace: randomUUID() });\n try {\n return loader.require(flowUrl, import.meta.url);\n } finally {\n loader.unregister();\n }\n }\n\n if (extension === \".mts\") {\n const { register } = (await import(\"tsx/esm/api\")) as {\n register: (options: { namespace: string }) => {\n import: (\n specifier: string,\n parentURL: string,\n ) => Promise<{\n default?: unknown;\n \"module.exports\"?: unknown;\n }>;\n unregister: () => Promise<void>;\n };\n };\n const loader = register({ namespace: randomUUID() });\n try {\n return (await loader.import(flowUrl, import.meta.url)) as {\n default?: unknown;\n \"module.exports\"?: unknown;\n };\n } finally {\n await loader.unregister();\n }\n }\n\n return (await import(flowUrl)) as {\n default?: unknown;\n \"module.exports\"?: unknown;\n };\n}\n\nfunction findFlowDefinition(module: {\n default?: unknown;\n \"module.exports\"?: unknown;\n}): FlowDefinition | null {\n const candidates = [\n module.default,\n module[\"module.exports\"],\n getNestedDefault(module.default),\n getNestedDefault(module[\"module.exports\"]),\n ];\n\n for (const candidate of candidates) {\n if (isDefinedFlow(candidate)) {\n return candidate;\n }\n }\n\n return null;\n}\n\nfunction getNestedDefault(value: unknown): unknown {\n if (!value || typeof value !== \"object\" || !(\"default\" in value)) {\n return null;\n }\n return (value as { default?: unknown }).default ?? null;\n}\n\nfunction parseJsonInput(raw: string, label: string): unknown {\n try {\n return JSON.parse(raw);\n } catch (error) {\n throw new InvalidArgumentError(\n `${label} must contain valid JSON: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n}\n\nfunction printFlowRunResult(\n result: Awaited<ReturnType<FlowRunner[\"run\"]>>,\n globalFlags: GlobalFlags,\n): void {\n const payload = {\n action: \"flow_run_result\",\n runId: result.state.runId,\n flowName: result.state.flowName,\n runTitle: result.state.runTitle,\n flowPath: result.state.flowPath,\n status: result.state.status,\n currentNode: result.state.currentNode,\n currentNodeType: result.state.currentNodeType,\n currentNodeStartedAt: result.state.currentNodeStartedAt,\n lastHeartbeatAt: result.state.lastHeartbeatAt,\n statusDetail: result.state.statusDetail,\n waitingOn: result.state.waitingOn,\n runDir: result.runDir,\n outputs: result.state.outputs,\n sessionBindings: result.state.sessionBindings,\n };\n\n if (globalFlags.format === \"json\") {\n process.stdout.write(`${JSON.stringify(payload)}\\n`);\n return;\n }\n\n if (globalFlags.format === \"quiet\") {\n process.stdout.write(`${result.state.runId}\\n`);\n return;\n }\n\n process.stdout.write(`runId: ${payload.runId}\\n`);\n process.stdout.write(`flow: ${payload.flowName}\\n`);\n if (payload.runTitle) {\n process.stdout.write(`title: ${payload.runTitle}\\n`);\n }\n process.stdout.write(`status: ${payload.status}\\n`);\n process.stdout.write(`runDir: ${payload.runDir}\\n`);\n if (payload.currentNode) {\n process.stdout.write(`currentNode: ${payload.currentNode}\\n`);\n }\n if (payload.statusDetail) {\n process.stdout.write(`statusDetail: ${payload.statusDetail}\\n`);\n }\n if (payload.waitingOn) {\n process.stdout.write(`waitingOn: ${payload.waitingOn}\\n`);\n }\n process.stdout.write(`${JSON.stringify(payload.outputs, null, 2)}\\n`);\n}\n"],"mappings":"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"}
package/dist/cli.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { s as SessionRecord } from "./types-CVBeQyi3.js";
1
+ import { f as SessionRecord } from "./session-options-BJyG6zEH.js";
2
2
  import { Command } from "commander";
3
3
 
4
4
  //#region src/cli/flags.d.ts
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","names":[],"sources":["../src/cli/flags.ts","../src/cli/output/render.ts"],"mappings":";;;;iBAmHgB,eAAA,CAAgB,KAAA;AAAA,iBAkDhB,iBAAA,CAAkB,KAAA;AAAA,iBAgBlB,aAAA,CAAc,KAAA;;;KCnKzB,uBAAA;AAAA,iBA0IW,6BAAA,CACd,MAAA,EAAQ,aAAA,EACR,UAAA,UACA,gBAAA,GAAkB,uBAAA"}
1
+ {"version":3,"file":"cli.d.ts","names":[],"sources":["../src/cli/flags.ts","../src/cli/output/render.ts"],"mappings":";;;;iBAoHgB,eAAA,CAAgB,KAAa;AAAA,iBAkD7B,iBAAA,CAAkB,KAAa;AAAA,iBAgB/B,aAAA,CAAc,KAAa;;;KCpKtC,uBAAA;AAAA,iBA0IW,6BAAA,CACd,MAAA,EAAQ,aAAA,EACR,UAAA,UACA,gBAAA,GAAkB,uBAA2C"}
package/dist/cli.js CHANGED
@@ -1,11 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { A as OUTPUT_FORMATS, E as EXIT_CODES, _ as exitCodeForOutputErrorCode, d as PromptInputValidationError, g as textPrompt, m as parsePromptSource, p as mergePromptSourceWithText, x as normalizeOutputError } from "./perf-metrics-C2pXfxvR.js";
3
- import { D as findGitRepositoryRoot, K as InterruptedError, O as findSession, Q as normalizeAgentName, X as DEFAULT_AGENT_NAME, Z as listBuiltInAgents, k as findSessionByDirectoryWalk } from "./prompt-turn-CVPMWdj1.js";
4
- import { a as buildQueueOwnerArgOverride, n as runSessionQueueOwner, o as flushPerfMetricsCapture, s as installPerfMetricsCapture } from "./session-CDaQe6BH.js";
5
- import { c as probeQueueOwnerHealth } from "./ipc-ABXlXzGP.js";
6
- import { _ as resolvePermissionMode, c as parseHistoryLimit, d as parsePruneBeforeDate, f as parseSessionName, g as resolveOutputPolicy, h as resolveGlobalFlags, i as addSessionOption, l as parseMaxTurns, m as resolveAgentInvocation, n as addPromptInputOption, o as parseAllowedTools, p as parseTtlSeconds, r as addSessionNameOption, s as parseDaysOlderThan, t as addGlobalFlags, u as parseNonEmptyValue, v as resolveSessionNameFromFlags } from "./flags-Dj-IXgo9.js";
7
- import { i as emitJsonResult, n as formatPromptSessionBannerLine, t as agentSessionIdPayload } from "./render-N5YwotCy.js";
8
- import { n as getTextErrorRemediationHints, t as createOutputFormatter } from "./output-DmHvT8vm.js";
2
+ import { a as runSessionQueueOwner, c as buildQueueOwnerArgOverride, h as __exportAll, l as flushPerfMetricsCapture, n as getTextErrorRemediationHints, p as probeQueueOwnerHealth, t as createOutputFormatter, u as installPerfMetricsCapture } from "./output-BL9XRWzS.js";
3
+ import { At as EXIT_CODES, F as findSession, I as findSessionByDirectoryWalk, P as findGitRepositoryRoot, Pt as OUTPUT_FORMATS, St as exitCodeForOutputErrorCode, Tt as normalizeOutputError, bt as normalizeAgentName, ct as PromptInputValidationError, dt as parsePromptSource, mt as InterruptedError, pt as textPrompt, st as normalizeRuntimeSessionId, ut as mergePromptSourceWithText, vt as DEFAULT_AGENT_NAME, yt as listBuiltInAgents } from "./live-checkpoint-B9ctAuqV.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-D706STfk.js";
9
5
  import { readFileSync, realpathSync } from "node:fs";
10
6
  import { fileURLToPath, pathToFileURL } from "node:url";
11
7
  import path from "node:path";
@@ -58,6 +54,13 @@ function isCodexInvocation(agentName, agentCommand) {
58
54
  return /\bcodex-acp\b/u.test(agentCommand);
59
55
  }
60
56
  //#endregion
57
+ //#region src/cli/output/json-output.ts
58
+ function emitJsonResult(format, payload) {
59
+ if (format !== "json") return false;
60
+ process.stdout.write(`${JSON.stringify(payload)}\n`);
61
+ return true;
62
+ }
63
+ //#endregion
61
64
  //#region src/cli/command-handlers.ts
62
65
  var NoSessionError = class extends Error {
63
66
  constructor(message) {
@@ -69,15 +72,15 @@ let sessionModulePromise;
69
72
  let outputModulePromise;
70
73
  let outputRenderModulePromise;
71
74
  function loadSessionModule() {
72
- sessionModulePromise ??= import("./session-CDaQe6BH.js").then((n) => n.t);
75
+ sessionModulePromise ??= import("./output-BL9XRWzS.js").then((n) => n.i);
73
76
  return sessionModulePromise;
74
77
  }
75
78
  function loadOutputModule() {
76
- outputModulePromise ??= import("./output-DmHvT8vm.js").then((n) => n.r);
79
+ outputModulePromise ??= import("./output-BL9XRWzS.js").then((n) => n.r);
77
80
  return outputModulePromise;
78
81
  }
79
82
  function loadOutputRenderModule() {
80
- outputRenderModulePromise ??= import("./render-N5YwotCy.js").then((n) => n.r);
83
+ outputRenderModulePromise ??= Promise.resolve().then(() => render_exports);
81
84
  return outputRenderModulePromise;
82
85
  }
83
86
  async function readPromptInputFromStdin() {
@@ -126,6 +129,13 @@ function sessionOptionsFromGlobalFlags(globalFlags) {
126
129
  systemPrompt: globalFlags.systemPrompt
127
130
  };
128
131
  }
132
+ async function resolvePermissionPolicyFromFlags(globalFlags) {
133
+ try {
134
+ return await loadPermissionPolicySpec(globalFlags.permissionPolicy, globalFlags.cwd);
135
+ } catch (error) {
136
+ throw new InvalidArgumentError(`Invalid permission policy: ${error instanceof Error ? error.message : String(error)}`);
137
+ }
138
+ }
129
139
  function buildSessionStartOptions(params) {
130
140
  return {
131
141
  agentCommand: params.agent.agentCommand,
@@ -135,6 +145,7 @@ function buildSessionStartOptions(params) {
135
145
  mcpServers: params.config.mcpServers,
136
146
  permissionMode: params.permissionMode,
137
147
  nonInteractivePermissions: params.globalFlags.nonInteractivePermissions,
148
+ permissionPolicy: params.permissionPolicy,
138
149
  authCredentials: params.config.auth,
139
150
  authPolicy: params.globalFlags.authPolicy,
140
151
  terminal: params.globalFlags.terminal,
@@ -171,6 +182,7 @@ async function handlePrompt(explicitAgentName, promptParts, flags, command, conf
171
182
  const globalFlags = resolveGlobalFlags(command, config);
172
183
  const outputPolicy = resolveRequestedOutputPolicy(globalFlags);
173
184
  const permissionMode = resolvePermissionMode(globalFlags, config.defaultPermissions);
185
+ const permissionPolicy = await resolvePermissionPolicyFromFlags(globalFlags);
174
186
  const prompt = await readPrompt(promptParts, flags.file, globalFlags.cwd);
175
187
  const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
176
188
  const [{ createOutputFormatter }, { printPromptSessionBanner, printQueuedPromptByFormat }, { sendSession }] = await Promise.all([
@@ -190,6 +202,7 @@ async function handlePrompt(explicitAgentName, promptParts, flags, command, conf
190
202
  mcpServers: config.mcpServers,
191
203
  permissionMode,
192
204
  nonInteractivePermissions: globalFlags.nonInteractivePermissions,
205
+ permissionPolicy,
193
206
  authCredentials: config.auth,
194
207
  authPolicy: globalFlags.authPolicy,
195
208
  terminal: globalFlags.terminal,
@@ -233,6 +246,7 @@ async function handleExec(explicitAgentName, promptParts, flags, command, config
233
246
  const globalFlags = resolveGlobalFlags(command, config);
234
247
  const outputPolicy = resolveRequestedOutputPolicy(globalFlags);
235
248
  const permissionMode = resolvePermissionMode(globalFlags, config.defaultPermissions);
249
+ const permissionPolicy = await resolvePermissionPolicyFromFlags(globalFlags);
236
250
  const prompt = await readPrompt(promptParts, flags.file, globalFlags.cwd);
237
251
  const [{ createOutputFormatter }, { runOnce }] = await Promise.all([loadOutputModule(), loadSessionModule()]);
238
252
  const outputFormatter = createOutputFormatter(outputPolicy.format, { suppressReads: outputPolicy.suppressReads });
@@ -244,6 +258,7 @@ async function handleExec(explicitAgentName, promptParts, flags, command, config
244
258
  mcpServers: config.mcpServers,
245
259
  permissionMode,
246
260
  nonInteractivePermissions: globalFlags.nonInteractivePermissions,
261
+ permissionPolicy,
247
262
  authCredentials: config.auth,
248
263
  authPolicy: globalFlags.authPolicy,
249
264
  terminal: globalFlags.terminal,
@@ -407,6 +422,7 @@ async function handleSessionsClose(explicitAgentName, sessionName, command, conf
407
422
  async function handleSessionsNew(explicitAgentName, flags, command, config) {
408
423
  const globalFlags = resolveGlobalFlags(command, config);
409
424
  const permissionMode = resolvePermissionMode(globalFlags, config.defaultPermissions);
425
+ const permissionPolicy = await resolvePermissionPolicyFromFlags(globalFlags);
410
426
  const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
411
427
  const [{ createSession, closeSession }, { printCreatedSessionBanner, printNewSessionByFormat }] = await Promise.all([loadSessionModule(), loadOutputRenderModule()]);
412
428
  const replaced = await findSession({
@@ -423,7 +439,8 @@ async function handleSessionsNew(explicitAgentName, flags, command, config) {
423
439
  flags,
424
440
  globalFlags,
425
441
  config,
426
- permissionMode
442
+ permissionMode,
443
+ permissionPolicy
427
444
  }));
428
445
  printCreatedSessionBanner(created, agent.agentName, globalFlags.format, globalFlags.jsonStrict);
429
446
  if (globalFlags.verbose) {
@@ -435,6 +452,7 @@ async function handleSessionsNew(explicitAgentName, flags, command, config) {
435
452
  async function handleSessionsEnsure(explicitAgentName, flags, command, config) {
436
453
  const globalFlags = resolveGlobalFlags(command, config);
437
454
  const permissionMode = resolvePermissionMode(globalFlags, config.defaultPermissions);
455
+ const permissionPolicy = await resolvePermissionPolicyFromFlags(globalFlags);
438
456
  const agent = resolveAgentInvocation(explicitAgentName, globalFlags, config);
439
457
  const [{ ensureSession }, { printCreatedSessionBanner, printEnsuredSessionByFormat }] = await Promise.all([loadSessionModule(), loadOutputRenderModule()]);
440
458
  const result = await ensureSession(buildSessionStartOptions({
@@ -442,7 +460,8 @@ async function handleSessionsEnsure(explicitAgentName, flags, command, config) {
442
460
  flags,
443
461
  globalFlags,
444
462
  config,
445
- permissionMode
463
+ permissionMode,
464
+ permissionPolicy
446
465
  }));
447
466
  if (result.created) printCreatedSessionBanner(result.record, agent.agentName, globalFlags.format, globalFlags.jsonStrict);
448
467
  printEnsuredSessionByFormat(result.record, result.created, globalFlags.format);
@@ -936,10 +955,10 @@ async function handleConfigInit(command, config) {
936
955
  }
937
956
  function registerConfigCommand(program, config) {
938
957
  const configCommand = program.command("config").description("Inspect and initialize acpx configuration");
939
- configCommand.command("show").description("Show resolved config").action(async function() {
958
+ configCommand.command("show").description("Show resolved config").option("--format <fmt>", "Output format: text, json, quiet", parseOutputFormat$1).action(async function() {
940
959
  await handleConfigShow(this, config);
941
960
  });
942
- configCommand.command("init").description("Create global config template").action(async function() {
961
+ configCommand.command("init").description("Create global config template").option("--format <fmt>", "Output format: text, json, quiet", parseOutputFormat$1).action(async function() {
943
962
  await handleConfigInit(this, config);
944
963
  });
945
964
  configCommand.action(async function() {
@@ -947,6 +966,164 @@ function registerConfigCommand(program, config) {
947
966
  });
948
967
  }
949
968
  //#endregion
969
+ //#region src/cli/output/render.ts
970
+ var render_exports = /* @__PURE__ */ __exportAll({
971
+ agentSessionIdPayload: () => agentSessionIdPayload,
972
+ formatPromptSessionBannerLine: () => formatPromptSessionBannerLine,
973
+ printClosedSessionByFormat: () => printClosedSessionByFormat,
974
+ printCreatedSessionBanner: () => printCreatedSessionBanner,
975
+ printEnsuredSessionByFormat: () => printEnsuredSessionByFormat,
976
+ printNewSessionByFormat: () => printNewSessionByFormat,
977
+ printPromptSessionBanner: () => printPromptSessionBanner,
978
+ printPruneResultByFormat: () => printPruneResultByFormat,
979
+ printQueuedPromptByFormat: () => printQueuedPromptByFormat,
980
+ printSessionsByFormat: () => printSessionsByFormat
981
+ });
982
+ function formatSessionLabel(record) {
983
+ return record.name ?? "cwd";
984
+ }
985
+ function formatRoutedFrom(sessionCwd, currentCwd) {
986
+ const relative = path.relative(sessionCwd, currentCwd);
987
+ if (!relative || relative === ".") return;
988
+ return relative.startsWith(".") ? relative : `.${path.sep}${relative}`;
989
+ }
990
+ async function resolveSessionConnectionStatus(record) {
991
+ return (await probeQueueOwnerHealth(record.acpxRecordId)).healthy ? "connected" : "needs reconnect";
992
+ }
993
+ function printSessionsByFormat(sessions, format) {
994
+ if (format === "json") {
995
+ process.stdout.write(`${JSON.stringify(sessions)}\n`);
996
+ return;
997
+ }
998
+ if (format === "quiet") {
999
+ for (const session of sessions) {
1000
+ const closedMarker = session.closed ? " [closed]" : "";
1001
+ process.stdout.write(`${session.acpxRecordId}${closedMarker}\n`);
1002
+ }
1003
+ return;
1004
+ }
1005
+ if (sessions.length === 0) {
1006
+ process.stdout.write("No sessions\n");
1007
+ return;
1008
+ }
1009
+ for (const session of sessions) {
1010
+ const closedMarker = session.closed ? " [closed]" : "";
1011
+ process.stdout.write(`${session.acpxRecordId}${closedMarker}\t${session.name ?? "-"}\t${session.cwd}\t${session.lastUsedAt}\n`);
1012
+ }
1013
+ }
1014
+ function printClosedSessionByFormat(record, format) {
1015
+ if (emitJsonResult(format, {
1016
+ action: "session_closed",
1017
+ acpxRecordId: record.acpxRecordId,
1018
+ acpxSessionId: record.acpSessionId,
1019
+ agentSessionId: record.agentSessionId
1020
+ })) return;
1021
+ if (format === "quiet") return;
1022
+ process.stdout.write(`${record.acpxRecordId}\n`);
1023
+ }
1024
+ function printNewSessionByFormat(record, replaced, format) {
1025
+ if (emitJsonResult(format, {
1026
+ action: "session_ensured",
1027
+ created: true,
1028
+ acpxRecordId: record.acpxRecordId,
1029
+ acpxSessionId: record.acpSessionId,
1030
+ agentSessionId: record.agentSessionId,
1031
+ name: record.name,
1032
+ replacedSessionId: replaced?.acpxRecordId
1033
+ })) return;
1034
+ if (format === "quiet") {
1035
+ process.stdout.write(`${record.acpxRecordId}\n`);
1036
+ return;
1037
+ }
1038
+ if (replaced) {
1039
+ process.stdout.write(`${record.acpxRecordId}\t(replaced ${replaced.acpxRecordId})\n`);
1040
+ return;
1041
+ }
1042
+ process.stdout.write(`${record.acpxRecordId}\n`);
1043
+ }
1044
+ function printEnsuredSessionByFormat(record, created, format) {
1045
+ if (emitJsonResult(format, {
1046
+ action: "session_ensured",
1047
+ created,
1048
+ acpxRecordId: record.acpxRecordId,
1049
+ acpxSessionId: record.acpSessionId,
1050
+ agentSessionId: record.agentSessionId,
1051
+ name: record.name
1052
+ })) return;
1053
+ if (format === "quiet") {
1054
+ process.stdout.write(`${record.acpxRecordId}\n`);
1055
+ return;
1056
+ }
1057
+ const action = created ? "created" : "existing";
1058
+ process.stdout.write(`${record.acpxRecordId}\t(${action})\n`);
1059
+ }
1060
+ function printQueuedPromptByFormat(result, format) {
1061
+ if (emitJsonResult(format, {
1062
+ action: "prompt_queued",
1063
+ acpxRecordId: result.sessionId,
1064
+ requestId: result.requestId
1065
+ })) return;
1066
+ if (format === "quiet") return;
1067
+ process.stdout.write(`[queued] ${result.requestId}\n`);
1068
+ }
1069
+ function formatPromptSessionBannerLine(record, currentCwd, connectionStatus = "needs reconnect") {
1070
+ const label = formatSessionLabel(record);
1071
+ const normalizedSessionCwd = path.resolve(record.cwd);
1072
+ const normalizedCurrentCwd = path.resolve(currentCwd);
1073
+ const routedFrom = normalizedSessionCwd === normalizedCurrentCwd ? void 0 : formatRoutedFrom(normalizedSessionCwd, normalizedCurrentCwd);
1074
+ const status = connectionStatus;
1075
+ if (routedFrom) return `[acpx] session ${label} (${record.acpxRecordId}) · ${normalizedSessionCwd} (routed from ${routedFrom}) · agent ${status}`;
1076
+ return `[acpx] session ${label} (${record.acpxRecordId}) · ${normalizedSessionCwd} · agent ${status}`;
1077
+ }
1078
+ async function printPromptSessionBanner(record, currentCwd, format, jsonStrict = false) {
1079
+ if (format === "quiet" || jsonStrict && format === "json") return;
1080
+ const status = await resolveSessionConnectionStatus(record);
1081
+ process.stderr.write(`${formatPromptSessionBannerLine(record, currentCwd, status)}\n`);
1082
+ }
1083
+ function printCreatedSessionBanner(record, agentName, format, jsonStrict = false) {
1084
+ if (format === "quiet" || jsonStrict && format === "json") return;
1085
+ const label = formatSessionLabel(record);
1086
+ process.stderr.write(`[acpx] created session ${label} (${record.acpxRecordId})\n`);
1087
+ process.stderr.write(`[acpx] agent: ${agentName}\n`);
1088
+ process.stderr.write(`[acpx] cwd: ${record.cwd}\n`);
1089
+ }
1090
+ function formatBytes(bytes) {
1091
+ if (bytes >= 1073741824) return `${(bytes / 1073741824).toFixed(1)} GB`;
1092
+ if (bytes >= 1048576) return `${(bytes / 1048576).toFixed(1)} MB`;
1093
+ if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)} KB`;
1094
+ return `${bytes} B`;
1095
+ }
1096
+ function printPruneResultByFormat(result, format) {
1097
+ const count = result.pruned.length;
1098
+ if (emitJsonResult(format, {
1099
+ action: result.dryRun ? "sessions_prune_dry_run" : "sessions_pruned",
1100
+ dryRun: result.dryRun,
1101
+ count,
1102
+ bytesFreed: result.bytesFreed,
1103
+ pruned: result.pruned.map((r) => r.acpxRecordId)
1104
+ })) return;
1105
+ if (format === "quiet") {
1106
+ for (const record of result.pruned) process.stdout.write(`${record.acpxRecordId}\n`);
1107
+ return;
1108
+ }
1109
+ if (count === 0) {
1110
+ process.stdout.write(result.dryRun ? "[DRY RUN] No sessions to prune\n" : "No sessions pruned\n");
1111
+ return;
1112
+ }
1113
+ const prefix = result.dryRun ? "[DRY RUN] Would prune" : "Pruned";
1114
+ const bytesSuffix = !result.dryRun && result.bytesFreed > 0 ? `, freed ${formatBytes(result.bytesFreed)}` : "";
1115
+ process.stdout.write(`${prefix} ${count} session${count === 1 ? "" : "s"}${bytesSuffix}\n`);
1116
+ for (const record of result.pruned) {
1117
+ const label = record.name ? ` (${record.name})` : "";
1118
+ process.stdout.write(` ${record.acpxRecordId}${label}\t${record.closedAt ?? record.lastUsedAt}\n`);
1119
+ }
1120
+ }
1121
+ function agentSessionIdPayload(agentSessionId) {
1122
+ const normalized = normalizeRuntimeSessionId(agentSessionId);
1123
+ if (!normalized) return {};
1124
+ return { agentSessionId: normalized };
1125
+ }
1126
+ //#endregion
950
1127
  //#region src/cli/status-command.ts
951
1128
  function formatUptime(startedAt) {
952
1129
  if (!startedAt) return;
@@ -1070,10 +1247,10 @@ function registerSessionsCommand(parent, explicitAgentName, config) {
1070
1247
  sessionsCommand.command("list").description("List sessions").action(async function() {
1071
1248
  await handleSessionsList(explicitAgentName, this, config);
1072
1249
  });
1073
- sessionsCommand.command("new").description("Create a fresh session for current cwd").option("--name <name>", "Session name", parseSessionName).option("--resume-session <id>", "Resume existing ACP session id", (value) => parseNonEmptyValue("Resume session id", value)).action(async function(flags) {
1250
+ sessionsCommand.command("new").description("Create a fresh session for current cwd").option("-s, --name <name>", "Session name", parseSessionName).option("--resume-session <id>", "Resume existing ACP session id", (value) => parseNonEmptyValue("Resume session id", value)).action(async function(flags) {
1074
1251
  await handleSessionsNew(explicitAgentName, flags, this, config);
1075
1252
  });
1076
- sessionsCommand.command("ensure").description("Ensure a session exists for current cwd or ancestor").option("--name <name>", "Session name", parseSessionName).option("--resume-session <id>", "Resume existing ACP session id", (value) => parseNonEmptyValue("Resume session id", value)).action(async function(flags) {
1253
+ sessionsCommand.command("ensure").description("Ensure a session exists for current cwd or ancestor").option("-s, --name <name>", "Session name", parseSessionName).option("--resume-session <id>", "Resume existing ACP session id", (value) => parseNonEmptyValue("Resume session id", value)).action(async function(flags) {
1077
1254
  await handleSessionsEnsure(explicitAgentName, flags, this, config);
1078
1255
  });
1079
1256
  sessionsCommand.command("close").description("Close session for current cwd").argument("[name]", "Session name", parseSessionName).action(async function(name) {
@@ -1140,7 +1317,7 @@ function registerAgentCommand(program, agentName, config) {
1140
1317
  }
1141
1318
  function registerFlowCommand(program, config) {
1142
1319
  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) {
1143
- const { handleFlowRun } = await import("./cli-T-Z-9x6a.js");
1320
+ const { handleFlowRun } = await import("./cli-BGYGVo3b.js");
1144
1321
  await handleFlowRun(file, flags, this, config);
1145
1322
  });
1146
1323
  }
@@ -1285,11 +1462,11 @@ function detectAgentToken(argv) {
1285
1462
  hasAgentOverride = true;
1286
1463
  continue;
1287
1464
  }
1288
- if (token === "--cwd" || token === "--auth-policy" || token === "--non-interactive-permissions" || token === "--format" || token === "--model" || token === "--allowed-tools" || token === "--max-turns" || token === "--timeout" || token === "--ttl" || token === "--file") {
1465
+ if (token === "--cwd" || token === "--auth-policy" || token === "--non-interactive-permissions" || token === "--permission-policy" || token === "--policy" || token === "--format" || token === "--model" || token === "--allowed-tools" || token === "--max-turns" || token === "--timeout" || token === "--ttl" || token === "--file") {
1289
1466
  index += 1;
1290
1467
  continue;
1291
1468
  }
1292
- if (token.startsWith("--cwd=") || token.startsWith("--auth-policy=") || token.startsWith("--non-interactive-permissions=") || token.startsWith("--format=") || token.startsWith("--model=") || token.startsWith("--allowed-tools=") || token.startsWith("--max-turns=") || token.startsWith("--json-strict=") || token.startsWith("--timeout=") || token.startsWith("--ttl=") || token.startsWith("--file=")) continue;
1469
+ if (token.startsWith("--cwd=") || token.startsWith("--auth-policy=") || token.startsWith("--non-interactive-permissions=") || token.startsWith("--permission-policy=") || token.startsWith("--policy=") || token.startsWith("--format=") || token.startsWith("--model=") || token.startsWith("--allowed-tools=") || token.startsWith("--max-turns=") || token.startsWith("--json-strict=") || token.startsWith("--timeout=") || token.startsWith("--ttl=") || token.startsWith("--file=")) continue;
1293
1470
  if (token === "--approve-all" || token === "--approve-reads" || token === "--deny-all" || token === "--json-strict" || token === "--verbose" || token === "--suppress-reads") continue;
1294
1471
  return { hasAgentOverride };
1295
1472
  }
@@ -1445,6 +1622,14 @@ async function main(argv = process.argv) {
1445
1622
  }
1446
1623
  //#endregion
1447
1624
  //#region src/cli.ts
1625
+ function installBrokenPipeHandler(stream) {
1626
+ stream.on("error", (error) => {
1627
+ if (error.code === "EPIPE") process.exit(0);
1628
+ throw error;
1629
+ });
1630
+ }
1631
+ installBrokenPipeHandler(process.stdout);
1632
+ installBrokenPipeHandler(process.stderr);
1448
1633
  const queueOwnerArgOverride = buildQueueOwnerArgOverride(fileURLToPath(import.meta.url));
1449
1634
  if (queueOwnerArgOverride) process.env.ACPX_QUEUE_OWNER_ARGS ??= queueOwnerArgOverride;
1450
1635
  function isCliEntrypoint(argv) {