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.
- package/README.md +7 -2
- package/dist/{cli-T-Z-9x6a.js → cli-BGYGVo3b.js} +35 -10
- package/dist/cli-BGYGVo3b.js.map +1 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +204 -19
- package/dist/cli.js.map +1 -1
- package/dist/{client-COPilhO_.d.ts → client-FzXPdgP7.d.ts} +7 -3
- package/dist/client-FzXPdgP7.d.ts.map +1 -0
- package/dist/{flags-Dj-IXgo9.js → flags-D706STfk.js} +46 -6
- package/dist/flags-D706STfk.js.map +1 -0
- package/dist/{flows-CF8w1rPI.js → flows-hcjHmU7P.js} +8 -5
- package/dist/flows-hcjHmU7P.js.map +1 -0
- package/dist/flows.d.ts +3 -2
- package/dist/flows.d.ts.map +1 -1
- package/dist/flows.js +1 -1
- package/dist/{prompt-turn-CVPMWdj1.js → live-checkpoint-B9ctAuqV.js} +1301 -78
- package/dist/live-checkpoint-B9ctAuqV.js.map +1 -0
- package/dist/output-BL9XRWzS.js +3712 -0
- package/dist/output-BL9XRWzS.js.map +1 -0
- package/dist/runtime.d.ts +28 -4
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +153 -24
- package/dist/runtime.js.map +1 -1
- package/dist/{types-CVBeQyi3.d.ts → session-options-BJyG6zEH.d.ts} +56 -3
- package/dist/session-options-BJyG6zEH.d.ts.map +1 -0
- package/package.json +23 -21
- package/skills/acpx/SKILL.md +200 -10
- package/dist/cli-T-Z-9x6a.js.map +0 -1
- package/dist/client-COPilhO_.d.ts.map +0 -1
- package/dist/flags-Dj-IXgo9.js.map +0 -1
- package/dist/flows-CF8w1rPI.js.map +0 -1
- package/dist/ipc-ABXlXzGP.js +0 -1290
- package/dist/ipc-ABXlXzGP.js.map +0 -1
- package/dist/jsonrpc-DSxh2w5R.js +0 -68
- package/dist/jsonrpc-DSxh2w5R.js.map +0 -1
- package/dist/output-DmHvT8vm.js +0 -807
- package/dist/output-DmHvT8vm.js.map +0 -1
- package/dist/perf-metrics-C2pXfxvR.js +0 -598
- package/dist/perf-metrics-C2pXfxvR.js.map +0 -1
- package/dist/prompt-turn-CVPMWdj1.js.map +0 -1
- package/dist/render-N5YwotCy.js +0 -172
- package/dist/render-N5YwotCy.js.map +0 -1
- package/dist/rolldown-runtime-CiIaOW0V.js +0 -13
- package/dist/session-CDaQe6BH.js +0 -1538
- package/dist/session-CDaQe6BH.js.map +0 -1
- package/dist/session-options-pCbHn_n7.d.ts +0 -13
- package/dist/session-options-pCbHn_n7.d.ts.map +0 -1
- 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.
|
|
90
|
-
|
|
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 {
|
|
2
|
-
import { _ as
|
|
3
|
-
import { c as validateFlowDefinition, h as isDefinedFlow, o as FlowRunner } from "./flows-
|
|
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
|
-
|
|
102
|
-
if (selfPath.endsWith(`${path.sep}src${path.sep}flows${path.sep}cli.
|
|
103
|
-
|
|
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 === ".
|
|
107
|
-
const {
|
|
108
|
-
|
|
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-
|
|
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
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":";;;;
|
|
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 {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
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("./
|
|
75
|
+
sessionModulePromise ??= import("./output-BL9XRWzS.js").then((n) => n.i);
|
|
73
76
|
return sessionModulePromise;
|
|
74
77
|
}
|
|
75
78
|
function loadOutputModule() {
|
|
76
|
-
outputModulePromise ??= import("./output-
|
|
79
|
+
outputModulePromise ??= import("./output-BL9XRWzS.js").then((n) => n.r);
|
|
77
80
|
return outputModulePromise;
|
|
78
81
|
}
|
|
79
82
|
function loadOutputRenderModule() {
|
|
80
|
-
outputRenderModulePromise ??=
|
|
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-
|
|
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) {
|