acpx 0.6.1 → 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 +8 -2
  2. package/dist/{cli-Ddxpnz9X.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-2fTFutRH.d.ts → client-FzXPdgP7.d.ts} +10 -4
  9. package/dist/client-FzXPdgP7.d.ts.map +1 -0
  10. package/dist/{flags-yXzUm7Aq.js → flags-D706STfk.js} +46 -6
  11. package/dist/flags-D706STfk.js.map +1 -0
  12. package/dist/{flows-CDsfbaA2.js → flows-hcjHmU7P.js} +117 -11
  13. package/dist/flows-hcjHmU7P.js.map +1 -0
  14. package/dist/flows.d.ts +19 -3
  15. package/dist/flows.d.ts.map +1 -1
  16. package/dist/flows.js +2 -2
  17. package/dist/{prompt-turn-BY5SwU1F.js → live-checkpoint-B9ctAuqV.js} +1335 -82
  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 +32 -6
  22. package/dist/runtime.d.ts.map +1 -1
  23. package/dist/runtime.js +169 -32
  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 +27 -25
  28. package/skills/acpx/SKILL.md +200 -9
  29. package/dist/cli-Ddxpnz9X.js.map +0 -1
  30. package/dist/client-2fTFutRH.d.ts.map +0 -1
  31. package/dist/flags-yXzUm7Aq.js.map +0 -1
  32. package/dist/flows-CDsfbaA2.js.map +0 -1
  33. package/dist/ipc-BruTG5Fb.js +0 -1241
  34. package/dist/ipc-BruTG5Fb.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-BY5SwU1F.js.map +0 -1
  42. package/dist/render-yqwtaOX4.js +0 -172
  43. package/dist/render-yqwtaOX4.js.map +0 -1
  44. package/dist/rolldown-runtime-CiIaOW0V.js +0 -13
  45. package/dist/session-BwgaPK8-.js +0 -1526
  46. package/dist/session-BwgaPK8-.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
@@ -1,5 +1,5 @@
1
- import { a as PermissionMode, c as PromptInput, i as NonInteractivePermissionPolicy, o as PermissionStats, t as AcpClientOptions } from "./types-CVBeQyi3.js";
2
- import { InitializeResponse, PromptResponse, SessionModelState, SetSessionConfigOptionResponse } from "@agentclientprotocol/sdk";
1
+ import { c as NonInteractivePermissionPolicy, d as PermissionStats, l as PermissionMode, p as PromptInput, r as AcpClientOptions } from "./session-options-BJyG6zEH.js";
2
+ import { InitializeResponse, PromptResponse, SessionConfigOption, SessionModelState, SetSessionConfigOptionResponse } from "@agentclientprotocol/sdk";
3
3
 
4
4
  //#region src/acp/client.d.ts
5
5
  type LoadSessionOptions = {
@@ -10,10 +10,12 @@ type LoadSessionOptions = {
10
10
  type SessionCreateResult = {
11
11
  sessionId: string;
12
12
  agentSessionId?: string;
13
+ configOptions?: SessionConfigOption[];
13
14
  models?: SessionModelState;
14
15
  };
15
16
  type SessionLoadResult = {
16
17
  agentSessionId?: string;
18
+ configOptions?: SessionConfigOption[];
17
19
  models?: SessionModelState;
18
20
  };
19
21
  type AgentDisconnectReason = "process_exit" | "process_close" | "pipe_close" | "connection_close";
@@ -47,6 +49,7 @@ declare class AcpClient {
47
49
  private suppressReplaySessionUpdateMessages;
48
50
  private activePrompt?;
49
51
  private readonly cancellingSessionIds;
52
+ private readonly permissionAbortControllers;
50
53
  private closing;
51
54
  private agentStartedAt?;
52
55
  private lastAgentExit?;
@@ -60,11 +63,12 @@ declare class AcpClient {
60
63
  getAgentLifecycleSnapshot(): AgentLifecycleSnapshot;
61
64
  supportsLoadSession(): boolean;
62
65
  supportsCloseSession(): boolean;
63
- setEventHandlers(handlers: Pick<AcpClientOptions, "onAcpMessage" | "onAcpOutputMessage" | "onSessionUpdate" | "onClientOperation">): void;
66
+ setEventHandlers(handlers: Pick<AcpClientOptions, "onAcpMessage" | "onAcpOutputMessage" | "onSessionUpdate" | "onClientOperation" | "onPermissionEscalation">): void;
64
67
  clearEventHandlers(): void;
65
68
  updateRuntimeOptions(options: {
66
69
  permissionMode?: PermissionMode;
67
70
  nonInteractivePermissions?: NonInteractivePermissionPolicy;
71
+ permissionPolicy?: AcpClientOptions["permissionPolicy"];
68
72
  terminal?: boolean;
69
73
  suppressSdkConsoleErrors?: boolean;
70
74
  verbose?: boolean;
@@ -109,6 +113,8 @@ declare class AcpClient {
109
113
  private handleWaitForTerminalExit;
110
114
  private handleKillTerminal;
111
115
  private handleReleaseTerminal;
116
+ private cancellationSignalForSession;
117
+ private abortAndDropPermissionSignal;
112
118
  private recordPermissionDecision;
113
119
  private recordPermissionError;
114
120
  private handleSessionUpdate;
@@ -120,4 +126,4 @@ declare class AcpClient {
120
126
  }
121
127
  //#endregion
122
128
  export { AcpClient as t };
123
- //# sourceMappingURL=client-2fTFutRH.d.ts.map
129
+ //# sourceMappingURL=client-FzXPdgP7.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-FzXPdgP7.d.ts","names":[],"sources":["../src/acp/client.ts"],"mappings":"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"}
@@ -1,8 +1,45 @@
1
- import { A as OUTPUT_FORMATS, D as NON_INTERACTIVE_PERMISSION_POLICIES, T as AUTH_POLICIES } from "./perf-metrics-C2pXfxvR.js";
2
- import { Q as resolveAgentCommand } from "./prompt-turn-BY5SwU1F.js";
3
- import "./session-BwgaPK8-.js";
1
+ import "./output-BL9XRWzS.js";
2
+ import { It as PERMISSION_POLICY_ACTIONS, Pt as OUTPUT_FORMATS, jt as NON_INTERACTIVE_PERMISSION_POLICIES, kt as AUTH_POLICIES, xt as resolveAgentCommand } from "./live-checkpoint-B9ctAuqV.js";
4
3
  import path from "node:path";
5
4
  import { InvalidArgumentError } from "commander";
5
+ import fs from "node:fs/promises";
6
+ //#region src/permission-policy.ts
7
+ function asRecord(value) {
8
+ if (!value || typeof value !== "object" || Array.isArray(value)) return;
9
+ return value;
10
+ }
11
+ function parseRuleList(value, key, source) {
12
+ if (value == null) return;
13
+ if (!Array.isArray(value)) throw new Error(`${source}: permission policy ${key} must be an array of strings`);
14
+ return value.map((entry) => {
15
+ if (typeof entry !== "string" || entry.trim().length === 0) throw new Error(`${source}: permission policy ${key} must contain only non-empty strings`);
16
+ return entry.trim();
17
+ });
18
+ }
19
+ function parsePermissionPolicy(value, source = "permission policy") {
20
+ const record = asRecord(value);
21
+ if (!record) throw new Error(`${source}: permission policy must be a JSON object`);
22
+ const defaultAction = record.defaultAction;
23
+ if (defaultAction != null && (typeof defaultAction !== "string" || !PERMISSION_POLICY_ACTIONS.includes(defaultAction))) throw new Error(`${source}: permission policy defaultAction must be one of ${PERMISSION_POLICY_ACTIONS.join(", ")}`);
24
+ const policy = {};
25
+ const autoApprove = parseRuleList(record.autoApprove, "autoApprove", source);
26
+ const autoDeny = parseRuleList(record.autoDeny, "autoDeny", source);
27
+ const escalate = parseRuleList(record.escalate, "escalate", source);
28
+ if (autoApprove) policy.autoApprove = autoApprove;
29
+ if (autoDeny) policy.autoDeny = autoDeny;
30
+ if (escalate) policy.escalate = escalate;
31
+ if (typeof defaultAction === "string") policy.defaultAction = defaultAction;
32
+ return policy;
33
+ }
34
+ async function loadPermissionPolicySpec(spec, cwd) {
35
+ const trimmed = spec?.trim();
36
+ if (!trimmed) return;
37
+ if (trimmed.startsWith("{")) return parsePermissionPolicy(JSON.parse(trimmed), "--permission-policy");
38
+ const policyPath = path.resolve(cwd, trimmed);
39
+ const raw = await fs.readFile(policyPath, "utf8");
40
+ return parsePermissionPolicy(JSON.parse(raw), policyPath);
41
+ }
42
+ //#endregion
6
43
  //#region src/cli/flags.ts
7
44
  function hasExplicitPermissionModeFlag(flags) {
8
45
  return flags.approveAll === true || flags.approveReads === true || flags.denyAll === true;
@@ -90,7 +127,7 @@ function resolvePermissionMode(flags, defaultMode) {
90
127
  return defaultMode;
91
128
  }
92
129
  function addGlobalFlags(command) {
93
- 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).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).option("--format <fmt>", "Output format: text, json, quiet", parseOutputFormat).option("--suppress-reads", "Suppress raw read-file contents in output").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("--system-prompt <text>", "Replace the agent system prompt (claude-agent-acp via ACP _meta.systemPrompt)", (value) => parseNonEmptyValue("System prompt", value)).option("--append-system-prompt <text>", "Append text to the agent system prompt (claude-agent-acp via ACP _meta.systemPrompt.append)", (value) => parseNonEmptyValue("Append system prompt", value)).option("--prompt-retries <count>", "Retry failed prompt turns on transient errors (default: 0)", parsePromptRetries).option("--json-strict", "Strict JSON mode: requires --format json and suppresses non-JSON stderr output").option("--no-terminal", "Do not advertise ACP terminal capability").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");
130
+ 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).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).option("--permission-policy <json-or-file>", "Permission policy JSON or path (autoApprove, autoDeny, escalate, defaultAction)").option("--policy <json-or-file>", "Alias for --permission-policy").option("--format <fmt>", "Output format: text, json, quiet", parseOutputFormat).option("--suppress-reads", "Suppress raw read-file contents in output").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("--system-prompt <text>", "Replace the agent system prompt (claude-agent-acp via ACP _meta.systemPrompt)", (value) => parseNonEmptyValue("System prompt", value)).option("--append-system-prompt <text>", "Append text to the agent system prompt (claude-agent-acp via ACP _meta.systemPrompt.append)", (value) => parseNonEmptyValue("Append system prompt", value)).option("--prompt-retries <count>", "Retry failed prompt turns on transient errors (default: 0)", parsePromptRetries).option("--json-strict", "Strict JSON mode: requires --format json and suppresses non-JSON stderr output").option("--no-terminal", "Do not advertise ACP terminal capability").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");
94
131
  }
95
132
  function addSessionOption(command) {
96
133
  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");
@@ -113,13 +150,16 @@ function resolveGlobalFlags(command, config) {
113
150
  const format = opts.format ?? config.format ?? "text";
114
151
  const jsonStrict = opts.jsonStrict === true;
115
152
  const verbose = opts.verbose === true;
153
+ const permissionPolicy = typeof opts.permissionPolicy === "string" ? opts.permissionPolicy : typeof opts.policy === "string" ? opts.policy : void 0;
116
154
  if (jsonStrict && format !== "json") throw new InvalidArgumentError("--json-strict requires --format json");
117
155
  if (jsonStrict && verbose) throw new InvalidArgumentError("--json-strict cannot be combined with --verbose");
156
+ if (typeof opts.permissionPolicy === "string" && typeof opts.policy === "string" && opts.permissionPolicy !== opts.policy) throw new InvalidArgumentError("Use only one permission policy flag: --permission-policy or --policy");
118
157
  return {
119
158
  agent: opts.agent,
120
159
  cwd: opts.cwd ?? process.cwd(),
121
160
  authPolicy: opts.authPolicy ?? config.authPolicy,
122
161
  nonInteractivePermissions: opts.nonInteractivePermissions ?? config.nonInteractivePermissions,
162
+ permissionPolicy,
123
163
  jsonStrict,
124
164
  suppressReads: opts.suppressReads === true,
125
165
  terminal: opts.terminal === false ? false : void 0,
@@ -158,6 +198,6 @@ function resolveAgentInvocation(explicitAgentName, globalFlags, config) {
158
198
  };
159
199
  }
160
200
  //#endregion
161
- export { resolvePermissionMode as _, hasExplicitPermissionModeFlag as a, parseHistoryLimit as c, parsePruneBeforeDate as d, parseSessionName as f, resolveOutputPolicy as g, resolveGlobalFlags as h, addSessionOption as i, parseMaxTurns as l, resolveAgentInvocation as m, addPromptInputOption as n, parseAllowedTools as o, parseTtlSeconds as p, addSessionNameOption as r, parseDaysOlderThan as s, addGlobalFlags as t, parseNonEmptyValue as u, resolveSessionNameFromFlags as v };
201
+ export { resolveOutputPolicy as _, hasExplicitPermissionModeFlag as a, loadPermissionPolicySpec as b, parseHistoryLimit as c, parseOutputFormat as d, parsePruneBeforeDate as f, resolveGlobalFlags as g, resolveAgentInvocation as h, addSessionOption as i, parseMaxTurns as l, parseTtlSeconds as m, addPromptInputOption as n, parseAllowedTools as o, parseSessionName as p, addSessionNameOption as r, parseDaysOlderThan as s, addGlobalFlags as t, parseNonEmptyValue as u, resolvePermissionMode as v, resolveSessionNameFromFlags as y };
162
202
 
163
- //# sourceMappingURL=flags-yXzUm7Aq.js.map
203
+ //# sourceMappingURL=flags-D706STfk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flags-D706STfk.js","names":["resolveAgentCommandFromRegistry"],"sources":["../src/permission-policy.ts","../src/cli/flags.ts"],"sourcesContent":["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n PERMISSION_POLICY_ACTIONS,\n type PermissionPolicy,\n type PermissionPolicyAction,\n} from \"./types.js\";\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return undefined;\n }\n return value as Record<string, unknown>;\n}\n\nfunction parseRuleList(value: unknown, key: string, source: string): string[] | undefined {\n if (value == null) {\n return undefined;\n }\n if (!Array.isArray(value)) {\n throw new Error(`${source}: permission policy ${key} must be an array of strings`);\n }\n\n const parsed = value.map((entry) => {\n if (typeof entry !== \"string\" || entry.trim().length === 0) {\n throw new Error(`${source}: permission policy ${key} must contain only non-empty strings`);\n }\n return entry.trim();\n });\n\n return parsed;\n}\n\nexport function parsePermissionPolicy(\n value: unknown,\n source = \"permission policy\",\n): PermissionPolicy {\n const record = asRecord(value);\n if (!record) {\n throw new Error(`${source}: permission policy must be a JSON object`);\n }\n\n const defaultAction = record.defaultAction;\n if (\n defaultAction != null &&\n (typeof defaultAction !== \"string\" ||\n !PERMISSION_POLICY_ACTIONS.includes(defaultAction as PermissionPolicyAction))\n ) {\n throw new Error(\n `${source}: permission policy defaultAction must be one of ${PERMISSION_POLICY_ACTIONS.join(\", \")}`,\n );\n }\n\n const policy: PermissionPolicy = {};\n const autoApprove = parseRuleList(record.autoApprove, \"autoApprove\", source);\n const autoDeny = parseRuleList(record.autoDeny, \"autoDeny\", source);\n const escalate = parseRuleList(record.escalate, \"escalate\", source);\n\n if (autoApprove) {\n policy.autoApprove = autoApprove;\n }\n if (autoDeny) {\n policy.autoDeny = autoDeny;\n }\n if (escalate) {\n policy.escalate = escalate;\n }\n if (typeof defaultAction === \"string\") {\n policy.defaultAction = defaultAction as PermissionPolicy[\"defaultAction\"];\n }\n\n return policy;\n}\n\nexport async function loadPermissionPolicySpec(\n spec: string | undefined,\n cwd: string,\n): Promise<PermissionPolicy | undefined> {\n const trimmed = spec?.trim();\n if (!trimmed) {\n return undefined;\n }\n\n if (trimmed.startsWith(\"{\")) {\n return parsePermissionPolicy(JSON.parse(trimmed), \"--permission-policy\");\n }\n\n const policyPath = path.resolve(cwd, trimmed);\n const raw = await fs.readFile(policyPath, \"utf8\");\n return parsePermissionPolicy(JSON.parse(raw), policyPath);\n}\n","import path from \"node:path\";\nimport { InvalidArgumentError } from \"commander\";\nimport type { Command } from \"commander\";\nimport {\n DEFAULT_AGENT_NAME,\n resolveAgentCommand as resolveAgentCommandFromRegistry,\n} from \"../agent-registry.js\";\nimport type { SystemPromptOption } from \"../runtime/engine/session-options.js\";\nimport { DEFAULT_QUEUE_OWNER_TTL_MS } from \"../session/session.js\";\nimport {\n AUTH_POLICIES,\n NON_INTERACTIVE_PERMISSION_POLICIES,\n OUTPUT_FORMATS,\n type AuthPolicy,\n type NonInteractivePermissionPolicy,\n type OutputFormat,\n type OutputPolicy,\n type PermissionMode,\n} from \"../types.js\";\nimport type { ResolvedAcpxConfig } from \"./config.js\";\n\nexport type PermissionFlags = {\n approveAll?: boolean;\n approveReads?: boolean;\n denyAll?: boolean;\n};\n\nexport function hasExplicitPermissionModeFlag(flags: PermissionFlags): boolean {\n return flags.approveAll === true || flags.approveReads === true || flags.denyAll === true;\n}\n\nexport type GlobalFlags = PermissionFlags & {\n agent?: string;\n cwd: string;\n authPolicy?: AuthPolicy;\n nonInteractivePermissions: NonInteractivePermissionPolicy;\n jsonStrict?: boolean;\n suppressReads?: boolean;\n terminal?: boolean;\n timeout?: number;\n ttl: number;\n verbose?: boolean;\n format: OutputFormat;\n model?: string;\n allowedTools?: string[];\n maxTurns?: number;\n systemPrompt?: SystemPromptOption;\n promptRetries?: number;\n permissionPolicy?: string;\n};\n\nexport type PromptFlags = {\n session?: string;\n wait?: boolean;\n file?: string;\n};\n\nexport type ExecFlags = {\n file?: string;\n};\n\nexport type SessionsNewFlags = {\n name?: string;\n resumeSession?: string;\n};\n\nexport type SessionsHistoryFlags = {\n limit: number;\n};\n\nexport type StatusFlags = {\n session?: string;\n};\n\nexport type SessionsPruneFlags = {\n dryRun?: boolean;\n before?: Date;\n olderThan?: number;\n includeHistory?: boolean;\n};\n\nexport function parseOutputFormat(value: string): OutputFormat {\n if (!OUTPUT_FORMATS.includes(value as OutputFormat)) {\n throw new InvalidArgumentError(\n `Invalid format \"${value}\". Expected one of: ${OUTPUT_FORMATS.join(\", \")}`,\n );\n }\n return value as OutputFormat;\n}\n\nexport function parseAuthPolicy(value: string): AuthPolicy {\n if (!AUTH_POLICIES.includes(value as AuthPolicy)) {\n throw new InvalidArgumentError(\n `Invalid auth policy \"${value}\". Expected one of: ${AUTH_POLICIES.join(\", \")}`,\n );\n }\n return value as AuthPolicy;\n}\n\nexport function parseNonInteractivePermissionPolicy(value: string): NonInteractivePermissionPolicy {\n if (!NON_INTERACTIVE_PERMISSION_POLICIES.includes(value as NonInteractivePermissionPolicy)) {\n throw new InvalidArgumentError(\n `Invalid non-interactive permission policy \"${value}\". Expected one of: ${NON_INTERACTIVE_PERMISSION_POLICIES.join(\", \")}`,\n );\n }\n return value as NonInteractivePermissionPolicy;\n}\n\nexport function parseTimeoutSeconds(value: string): number {\n const parsed = Number(value);\n if (!Number.isFinite(parsed) || parsed <= 0) {\n throw new InvalidArgumentError(\"Timeout must be a positive number of seconds\");\n }\n return Math.round(parsed * 1000);\n}\n\nexport function parseTtlSeconds(value: string): number {\n const parsed = Number(value);\n if (!Number.isFinite(parsed) || parsed < 0) {\n throw new InvalidArgumentError(\"TTL must be a non-negative number of seconds\");\n }\n return Math.round(parsed * 1000);\n}\n\nexport function parseSessionName(value: string): string {\n const trimmed = value.trim();\n if (trimmed.length === 0) {\n throw new InvalidArgumentError(\"Session name must not be empty\");\n }\n return trimmed;\n}\n\nexport function parseNonEmptyValue(label: string, value: string): string {\n const trimmed = value.trim();\n if (trimmed.length === 0) {\n throw new InvalidArgumentError(`${label} must not be empty`);\n }\n return trimmed;\n}\n\nexport function parseHistoryLimit(value: string): number {\n const parsed = Number(value);\n if (!Number.isInteger(parsed) || parsed <= 0) {\n throw new InvalidArgumentError(\"Limit must be a positive integer\");\n }\n return parsed;\n}\n\nexport function parseDaysOlderThan(value: string): number {\n const parsed = Number(value);\n if (!Number.isInteger(parsed) || parsed <= 0) {\n throw new InvalidArgumentError(\"--older-than must be a positive integer number of days\");\n }\n return parsed;\n}\n\nexport function parsePruneBeforeDate(value: string): Date {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) {\n throw new InvalidArgumentError(\n `--before must be a valid date (e.g. 2026-01-01 or 2026-01-01T00:00:00Z)`,\n );\n }\n return date;\n}\n\nexport function parseAllowedTools(value: string): string[] {\n const trimmed = value.trim();\n if (trimmed.length === 0) {\n return [];\n }\n\n const items = trimmed.split(\",\").map((item) => item.trim());\n if (items.some((item) => item.length === 0)) {\n throw new InvalidArgumentError(\n \"Allowed tools must be a comma-separated list without empty entries\",\n );\n }\n\n return items;\n}\n\nexport function parseMaxTurns(value: string): number {\n const parsed = Number(value);\n if (!Number.isInteger(parsed) || parsed <= 0) {\n throw new InvalidArgumentError(\"Max turns must be a positive integer\");\n }\n return parsed;\n}\n\nexport function resolveSystemPromptFlag(opts: {\n systemPrompt?: unknown;\n appendSystemPrompt?: unknown;\n}): SystemPromptOption | undefined {\n const replace =\n typeof opts.systemPrompt === \"string\" && opts.systemPrompt.length > 0\n ? opts.systemPrompt\n : undefined;\n const append =\n typeof opts.appendSystemPrompt === \"string\" && opts.appendSystemPrompt.length > 0\n ? opts.appendSystemPrompt\n : undefined;\n\n if (replace !== undefined && append !== undefined) {\n throw new InvalidArgumentError(\"Use only one of --system-prompt or --append-system-prompt\");\n }\n if (replace !== undefined) {\n return replace;\n }\n if (append !== undefined) {\n return { append };\n }\n return undefined;\n}\n\nexport function parsePromptRetries(value: string): number {\n const parsed = Number(value);\n if (!Number.isInteger(parsed) || parsed < 0) {\n throw new InvalidArgumentError(\"Prompt retries must be a non-negative integer\");\n }\n return parsed;\n}\n\nexport function resolvePermissionMode(\n flags: PermissionFlags,\n defaultMode: PermissionMode,\n): PermissionMode {\n const selected = [flags.approveAll, flags.approveReads, flags.denyAll].filter(Boolean).length;\n\n if (selected > 1) {\n throw new InvalidArgumentError(\n \"Use only one permission mode: --approve-all, --approve-reads, or --deny-all\",\n );\n }\n\n if (flags.approveAll) {\n return \"approve-all\";\n }\n if (flags.approveReads) {\n return \"approve-reads\";\n }\n if (flags.denyAll) {\n return \"deny-all\";\n }\n\n return defaultMode;\n}\n\nexport function addGlobalFlags(command: Command): Command {\n return command\n .option(\"--agent <command>\", \"Raw ACP agent command (escape hatch)\")\n .option(\"--cwd <dir>\", \"Working directory\", process.cwd())\n .option(\n \"--auth-policy <policy>\",\n \"Authentication policy: skip or fail when auth is required\",\n parseAuthPolicy,\n )\n .option(\"--approve-all\", \"Auto-approve all permission requests\")\n .option(\"--approve-reads\", \"Auto-approve read/search requests and prompt for writes\")\n .option(\"--deny-all\", \"Deny all permission requests\")\n .option(\n \"--non-interactive-permissions <policy>\",\n \"When prompting is unavailable: deny or fail\",\n parseNonInteractivePermissionPolicy,\n )\n .option(\n \"--permission-policy <json-or-file>\",\n \"Permission policy JSON or path (autoApprove, autoDeny, escalate, defaultAction)\",\n )\n .option(\"--policy <json-or-file>\", \"Alias for --permission-policy\")\n .option(\"--format <fmt>\", \"Output format: text, json, quiet\", parseOutputFormat)\n .option(\"--suppress-reads\", \"Suppress raw read-file contents in output\")\n .option(\"--model <id>\", \"Agent model id\")\n .option(\n \"--allowed-tools <list>\",\n 'Allowed tool names as a comma-separated list (use \"\" for no tools)',\n parseAllowedTools,\n )\n .option(\"--max-turns <count>\", \"Maximum turns for the session\", parseMaxTurns)\n .option(\n \"--system-prompt <text>\",\n \"Replace the agent system prompt (claude-agent-acp via ACP _meta.systemPrompt)\",\n (value: string) => parseNonEmptyValue(\"System prompt\", value),\n )\n .option(\n \"--append-system-prompt <text>\",\n \"Append text to the agent system prompt (claude-agent-acp via ACP _meta.systemPrompt.append)\",\n (value: string) => parseNonEmptyValue(\"Append system prompt\", value),\n )\n .option(\n \"--prompt-retries <count>\",\n \"Retry failed prompt turns on transient errors (default: 0)\",\n parsePromptRetries,\n )\n .option(\n \"--json-strict\",\n \"Strict JSON mode: requires --format json and suppresses non-JSON stderr output\",\n )\n .option(\"--no-terminal\", \"Do not advertise ACP terminal capability\")\n .option(\"--timeout <seconds>\", \"Maximum time to wait for agent response\", parseTimeoutSeconds)\n .option(\n \"--ttl <seconds>\",\n \"Queue owner idle TTL before shutdown (0 = keep alive forever) (default: 300)\",\n parseTtlSeconds,\n )\n .option(\"--verbose\", \"Enable verbose debug logs\");\n}\n\nexport function addSessionOption(command: Command): Command {\n return command\n .option(\"-s, --session <name>\", \"Use named session instead of cwd default\", parseSessionName)\n .option(\n \"--no-wait\",\n \"Queue prompt and return immediately when another prompt is already running\",\n );\n}\n\nexport function addSessionNameOption(command: Command): Command {\n return command.option(\n \"-s, --session <name>\",\n \"Use named session instead of cwd default\",\n parseSessionName,\n );\n}\n\nexport function resolveSessionNameFromFlags(\n flags: StatusFlags,\n command: Command,\n): string | undefined {\n if (flags.session) {\n return flags.session;\n }\n\n // Commander parses options on the parent command when flags appear before the\n // subcommand (e.g. `acpx codex -s foo cancel`). Use optsWithGlobals() so\n // subcommands can still access those values.\n const allOpts = (command as unknown as { optsWithGlobals?: () => unknown }).optsWithGlobals?.();\n if (allOpts && typeof (allOpts as { session?: unknown }).session === \"string\") {\n return parseSessionName((allOpts as { session: string }).session);\n }\n\n const parentOpts = command.parent?.opts?.();\n if (parentOpts && typeof (parentOpts as { session?: unknown }).session === \"string\") {\n return parseSessionName((parentOpts as { session: string }).session);\n }\n\n return undefined;\n}\n\nexport function addPromptInputOption(command: Command): Command {\n return command.option(\"-f, --file <path>\", \"Read prompt text from file path (use - for stdin)\");\n}\n\nexport function resolveGlobalFlags(command: Command, config: ResolvedAcpxConfig): GlobalFlags {\n const opts = command.optsWithGlobals();\n const format = opts.format ?? config.format ?? \"text\";\n const jsonStrict = opts.jsonStrict === true;\n const verbose = opts.verbose === true;\n const permissionPolicy =\n typeof opts.permissionPolicy === \"string\"\n ? opts.permissionPolicy\n : typeof opts.policy === \"string\"\n ? opts.policy\n : undefined;\n\n if (jsonStrict && format !== \"json\") {\n throw new InvalidArgumentError(\"--json-strict requires --format json\");\n }\n\n if (jsonStrict && verbose) {\n throw new InvalidArgumentError(\"--json-strict cannot be combined with --verbose\");\n }\n\n if (\n typeof opts.permissionPolicy === \"string\" &&\n typeof opts.policy === \"string\" &&\n opts.permissionPolicy !== opts.policy\n ) {\n throw new InvalidArgumentError(\n \"Use only one permission policy flag: --permission-policy or --policy\",\n );\n }\n\n return {\n agent: opts.agent,\n cwd: opts.cwd ?? process.cwd(),\n authPolicy: opts.authPolicy ?? config.authPolicy,\n nonInteractivePermissions: opts.nonInteractivePermissions ?? config.nonInteractivePermissions,\n permissionPolicy,\n jsonStrict,\n suppressReads: opts.suppressReads === true,\n terminal: opts.terminal === false ? false : undefined,\n timeout: opts.timeout ?? config.timeoutMs,\n ttl: opts.ttl ?? config.ttlMs ?? DEFAULT_QUEUE_OWNER_TTL_MS,\n verbose,\n format,\n model: typeof opts.model === \"string\" ? parseNonEmptyValue(\"Model\", opts.model) : undefined,\n allowedTools: Array.isArray(opts.allowedTools) ? opts.allowedTools : undefined,\n maxTurns: typeof opts.maxTurns === \"number\" ? opts.maxTurns : undefined,\n systemPrompt: resolveSystemPromptFlag(opts),\n promptRetries: typeof opts.promptRetries === \"number\" ? opts.promptRetries : undefined,\n approveAll: opts.approveAll ? true : undefined,\n approveReads: opts.approveReads ? true : undefined,\n denyAll: opts.denyAll ? true : undefined,\n };\n}\n\nexport function resolveOutputPolicy(format: OutputFormat, jsonStrict: boolean): OutputPolicy {\n return {\n format,\n jsonStrict,\n suppressReads: false,\n suppressNonJsonStderr: jsonStrict,\n queueErrorAlreadyEmitted: format !== \"quiet\",\n suppressSdkConsoleErrors: jsonStrict,\n };\n}\n\nexport function resolveAgentInvocation(\n explicitAgentName: string | undefined,\n globalFlags: GlobalFlags,\n config: ResolvedAcpxConfig,\n): {\n agentName: string;\n agentCommand: string;\n cwd: string;\n} {\n const override = globalFlags.agent?.trim();\n if (override && explicitAgentName) {\n throw new InvalidArgumentError(\"Do not combine positional agent with --agent override\");\n }\n\n const agentName = explicitAgentName ?? config.defaultAgent ?? DEFAULT_AGENT_NAME;\n const agentCommand =\n override && override.length > 0\n ? override\n : resolveAgentCommandFromRegistry(agentName, config.agents);\n\n return {\n agentName,\n agentCommand,\n cwd: path.resolve(globalFlags.cwd),\n };\n}\n"],"mappings":"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"}
@@ -1,7 +1,5 @@
1
- import { M as SESSION_RECORD_SCHEMA, g as textPrompt, h as promptToDisplayText, j as PERMISSION_MODES } from "./perf-metrics-C2pXfxvR.js";
2
- import { G as InterruptedError, J as withTimeout, K as TimeoutError, P as resolveSessionRecord, R as defaultSessionEventLog, _ as createSessionConversation, b as recordSessionUpdate, h as cloneSessionAcpxState, q as withInterrupt, v as recordClientOperation, y as recordPromptSubmission } from "./prompt-turn-BY5SwU1F.js";
3
- import { c as createSessionWithClient, i as sendSessionDirect, l as cancelSessionPrompt, r as runOnce } from "./session-BwgaPK8-.js";
4
- import { t as createOutputFormatter } from "./output-DmHvT8vm.js";
1
+ import { d as createSessionWithClient, f as cancelSessionPrompt, o as runOnce, s as sendSessionDirect, t as createOutputFormatter } from "./output-BL9XRWzS.js";
2
+ import { Ft as PERMISSION_MODES, H as resolveSessionRecord, K as defaultSessionEventLog, Lt as SESSION_RECORD_SCHEMA, _t as withTimeout, b as recordPromptSubmission, ft as promptToDisplayText, g as cloneSessionAcpxState, gt as withInterrupt, ht as TimeoutError, mt as InterruptedError, pt as textPrompt, v as createSessionConversation, x as recordSessionUpdate, y as recordClientOperation } from "./live-checkpoint-B9ctAuqV.js";
5
3
  import path from "node:path";
6
4
  import fs from "node:fs/promises";
7
5
  import os from "node:os";
@@ -465,7 +463,7 @@ function normalizeFlowRunTitle(value) {
465
463
  return trimmed ? trimmed : void 0;
466
464
  }
467
465
  function createRunId(flowName) {
468
- return `${isoNow$1().replaceAll(":", "").replaceAll(".", "")}-${flowName.replace(/[^a-z0-9]+/gi, "-").replace(/^-+|-+$/g, "").toLowerCase()}-${randomUUID().slice(0, 8)}`;
466
+ return `${isoNow$1().replaceAll(":", "").replaceAll(".", "")}-${slugifyAsciiIdPart(flowName)}-${randomUUID().slice(0, 8)}`;
469
467
  }
470
468
  function createSessionBindingKey(agentCommand, cwd, handle) {
471
469
  return `${agentCommand}::${cwd}::${handle}`;
@@ -474,7 +472,31 @@ function createSessionName(flowName, handle, cwd, runId) {
474
472
  return `${flowName}-${handle}-${stableShortHash(cwd)}-${runId.slice(-8)}`;
475
473
  }
476
474
  function createSessionBundleId(handle, key) {
477
- return `${handle.replace(/[^a-z0-9]+/gi, "-").replace(/^-+|-+$/g, "").toLowerCase() || "session"}-${stableShortHash(key)}`;
475
+ return `${slugifyAsciiIdPart(handle) || "session"}-${stableShortHash(key)}`;
476
+ }
477
+ function slugifyAsciiIdPart(value) {
478
+ let slug = "";
479
+ let lastWasSeparator = false;
480
+ for (const char of value) {
481
+ const safeChar = toLowerAsciiAlphaNumeric(char);
482
+ if (safeChar) {
483
+ slug += safeChar;
484
+ lastWasSeparator = false;
485
+ continue;
486
+ }
487
+ if (slug.length > 0 && !lastWasSeparator) {
488
+ slug += "-";
489
+ lastWasSeparator = true;
490
+ }
491
+ }
492
+ return lastWasSeparator ? slug.slice(0, -1) : slug;
493
+ }
494
+ function toLowerAsciiAlphaNumeric(char) {
495
+ const code = char.charCodeAt(0);
496
+ if (code >= 48 && code <= 57) return char;
497
+ if (code >= 65 && code <= 90) return String.fromCharCode(code + 32);
498
+ if (code >= 97 && code <= 122) return char;
499
+ return null;
478
500
  }
479
501
  function createIsolatedSessionBinding(flowName, runId, attemptId, profile, agent) {
480
502
  const key = `isolated::${attemptId}`;
@@ -965,6 +987,7 @@ var FlowRunner = class {
965
987
  permissionMode;
966
988
  mcpServers;
967
989
  nonInteractivePermissions;
990
+ permissionPolicy;
968
991
  authCredentials;
969
992
  authPolicy;
970
993
  timeoutMs;
@@ -981,6 +1004,7 @@ var FlowRunner = class {
981
1004
  this.permissionMode = options.permissionMode;
982
1005
  this.mcpServers = options.mcpServers;
983
1006
  this.nonInteractivePermissions = options.nonInteractivePermissions;
1007
+ this.permissionPolicy = options.permissionPolicy;
984
1008
  this.authCredentials = options.authCredentials;
985
1009
  this.authPolicy = options.authPolicy;
986
1010
  this.timeoutMs = options.timeoutMs;
@@ -1497,6 +1521,7 @@ var FlowRunner = class {
1497
1521
  mcpServers: this.mcpServers,
1498
1522
  permissionMode: this.permissionMode,
1499
1523
  nonInteractivePermissions: this.nonInteractivePermissions,
1524
+ permissionPolicy: this.permissionPolicy,
1500
1525
  authCredentials: this.authCredentials,
1501
1526
  authPolicy: this.authPolicy,
1502
1527
  timeoutMs,
@@ -1545,6 +1570,7 @@ var FlowRunner = class {
1545
1570
  mcpServers: this.mcpServers,
1546
1571
  permissionMode: this.permissionMode,
1547
1572
  nonInteractivePermissions: this.nonInteractivePermissions,
1573
+ permissionPolicy: this.permissionPolicy,
1548
1574
  authCredentials: this.authCredentials,
1549
1575
  authPolicy: this.authPolicy,
1550
1576
  outputFormatter: capture.formatter,
@@ -1608,6 +1634,7 @@ var FlowRunner = class {
1608
1634
  mcpServers: this.mcpServers,
1609
1635
  permissionMode: this.permissionMode,
1610
1636
  nonInteractivePermissions: this.nonInteractivePermissions,
1637
+ permissionPolicy: this.permissionPolicy,
1611
1638
  authCredentials: this.authCredentials,
1612
1639
  authPolicy: this.authPolicy,
1613
1640
  outputFormatter: capture.formatter,
@@ -1677,9 +1704,9 @@ function parseJsonObject(text, options = {}) {
1677
1704
  const direct = tryParse(trimmed);
1678
1705
  if (direct.ok) return direct.value;
1679
1706
  if (mode === "fenced" || mode === "compat") {
1680
- const fencedMatch = trimmed.match(/```(?:json)?\s*([\s\S]*?)```/i);
1681
- if (fencedMatch) {
1682
- const fenced = tryParse(fencedMatch[1].trim());
1707
+ const fencedText = extractFencedJsonText(trimmed);
1708
+ if (fencedText !== null) {
1709
+ const fenced = tryParse(fencedText);
1683
1710
  if (fenced.ok) return fenced.value;
1684
1711
  }
1685
1712
  }
@@ -1705,6 +1732,19 @@ function tryParse(text) {
1705
1732
  return { ok: false };
1706
1733
  }
1707
1734
  }
1735
+ function extractFencedJsonText(text) {
1736
+ const openingFenceIndex = text.indexOf("```");
1737
+ if (openingFenceIndex === -1) return null;
1738
+ let contentStart = openingFenceIndex + 3;
1739
+ if (text.slice(contentStart, contentStart + 4).toLowerCase() === "json" && isFenceWhitespace(text[contentStart + 4])) contentStart += 4;
1740
+ while (isFenceWhitespace(text[contentStart])) contentStart += 1;
1741
+ const closingFenceIndex = text.indexOf("```", contentStart);
1742
+ if (closingFenceIndex === -1) return null;
1743
+ return text.slice(contentStart, closingFenceIndex).trim();
1744
+ }
1745
+ function isFenceWhitespace(char) {
1746
+ return char === " " || char === "\n" || char === "\r" || char === " ";
1747
+ }
1708
1748
  function extractBalancedJsonCandidates(text) {
1709
1749
  const candidates = [];
1710
1750
  for (let index = 0; index < text.length; index += 1) {
@@ -1743,6 +1783,72 @@ function scanBalanced(text, startIndex) {
1743
1783
  return null;
1744
1784
  }
1745
1785
  //#endregion
1746
- export { flowRunsBaseDir as a, action as c, defineFlow as d, shell as f, FlowRunner as i, checkpoint as l, parseJsonObject as n, validateFlowDefinition as o, isDefinedFlow as p, parseStrictJsonObject as r, acp as s, extractJsonObject as t, compute as u };
1786
+ //#region src/flows/decision.ts
1787
+ const DEFAULT_FIELD = "route";
1788
+ const SIMPLE_FIELD_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
1789
+ function decision(definition) {
1790
+ const { question, choices, field: fieldOverride, ...acpOptions } = definition;
1791
+ const field = normalizeField(fieldOverride);
1792
+ assertValidChoices(choices);
1793
+ const allowed = new Set(choices);
1794
+ return acp({
1795
+ ...acpOptions,
1796
+ async prompt(context) {
1797
+ return formatDecisionPrompt(typeof question === "function" ? await question(context) : question, choices, field);
1798
+ },
1799
+ parse(text) {
1800
+ const raw = extractJsonObject(text);
1801
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) throw new Error(`Decision response must be a JSON object, got ${typeof raw}`);
1802
+ const value = raw[field];
1803
+ if (typeof value !== "string" || !allowed.has(value)) {
1804
+ const allowedLabels = choices.map((choice) => JSON.stringify(choice)).join(", ");
1805
+ throw new Error(`Decision returned invalid ${field}=${JSON.stringify(value)}; expected one of ${allowedLabels}`);
1806
+ }
1807
+ return raw;
1808
+ }
1809
+ });
1810
+ }
1811
+ function decisionEdge(args) {
1812
+ const field = normalizeField(args.field);
1813
+ assertValidChoices(args.choices);
1814
+ for (const choice of args.choices) if (!Object.hasOwn(args.cases, choice)) throw new Error(`Decision edge is missing case for choice ${JSON.stringify(choice)}`);
1815
+ return {
1816
+ from: args.from,
1817
+ switch: {
1818
+ on: `$.${field}`,
1819
+ cases: args.cases
1820
+ }
1821
+ };
1822
+ }
1823
+ function assertValidChoices(choices) {
1824
+ if (choices.length === 0) throw new Error("Decision choices must include at least one value");
1825
+ const seen = /* @__PURE__ */ new Set();
1826
+ for (const choice of choices) {
1827
+ if (typeof choice !== "string" || choice.length === 0) throw new Error("Decision choices must be non-empty strings");
1828
+ if (seen.has(choice)) throw new Error(`Decision choices must be unique; duplicate ${JSON.stringify(choice)}`);
1829
+ seen.add(choice);
1830
+ }
1831
+ }
1832
+ function normalizeField(fieldOverride) {
1833
+ const field = fieldOverride ?? DEFAULT_FIELD;
1834
+ if (!SIMPLE_FIELD_PATTERN.test(field)) throw new Error(`Decision field must be a simple JSON key matching ${SIMPLE_FIELD_PATTERN.source}`);
1835
+ return field;
1836
+ }
1837
+ function formatDecisionPrompt(question, choices, field) {
1838
+ const allowed = choices.map((choice) => JSON.stringify(choice)).join(" | ");
1839
+ return [
1840
+ question,
1841
+ "",
1842
+ "Return exactly one JSON object with this shape:",
1843
+ "{",
1844
+ ` ${JSON.stringify(field)}: ${allowed},`,
1845
+ " \"reason\": \"short justification\"",
1846
+ "}",
1847
+ "",
1848
+ "Do not include any other text outside the JSON object."
1849
+ ].join("\n");
1850
+ }
1851
+ //#endregion
1852
+ export { parseStrictJsonObject as a, validateFlowDefinition as c, checkpoint as d, compute as f, isDefinedFlow as h, parseJsonObject as i, acp as l, shell as m, decisionEdge as n, FlowRunner as o, defineFlow as p, extractJsonObject as r, flowRunsBaseDir as s, decision as t, action as u };
1747
1853
 
1748
- //# sourceMappingURL=flows-CDsfbaA2.js.map
1854
+ //# sourceMappingURL=flows-hcjHmU7P.js.map