acpx 0.11.0 → 0.11.2
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 +3 -0
- package/dist/{cli-CC2w0U-A.js → cli-CXlEcGWV.js} +5 -5
- package/dist/{cli-CC2w0U-A.js.map → cli-CXlEcGWV.js.map} +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +140 -37
- package/dist/cli.js.map +1 -1
- package/dist/{client-j3sLnpcM.d.ts → client-DIlpCkHw.d.ts} +15 -5
- package/dist/client-DIlpCkHw.d.ts.map +1 -0
- package/dist/{flags-BKjjl3tF.js → flags-Dl_mhic3.js} +4 -4
- package/dist/flags-Dl_mhic3.js.map +1 -0
- package/dist/{flows-BabqiU0u.js → flows-7OHjgEgq.js} +3 -3
- package/dist/{flows-BabqiU0u.js.map → flows-7OHjgEgq.js.map} +1 -1
- package/dist/flows.d.ts +1 -1
- package/dist/flows.js +1 -1
- package/dist/{live-checkpoint-BZrk9Mjz.js → live-checkpoint-mdAaF3qJ.js} +241 -67
- package/dist/live-checkpoint-mdAaF3qJ.js.map +1 -0
- package/dist/{output-D_BGt1YI.js → output-Smw6kFL_.js} +191 -55
- package/dist/output-Smw6kFL_.js.map +1 -0
- package/dist/runtime.d.ts +6 -7
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +5 -4
- package/dist/runtime.js.map +1 -1
- package/dist/{session-options-Co1oGEK8.d.ts → session-options-jkYbBxGE.d.ts} +13 -1
- package/dist/session-options-jkYbBxGE.d.ts.map +1 -0
- package/package.json +9 -8
- package/skills/acpx/SKILL.md +3 -0
- package/dist/client-j3sLnpcM.d.ts.map +0 -1
- package/dist/flags-BKjjl3tF.js.map +0 -1
- package/dist/live-checkpoint-BZrk9Mjz.js.map +0 -1
- package/dist/output-D_BGt1YI.js.map +0 -1
- package/dist/session-options-Co1oGEK8.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -267,6 +267,9 @@ real GitHub PRs if you run it against a live repository.
|
|
|
267
267
|
|
|
268
268
|
CLI flags always win over config values.
|
|
269
269
|
|
|
270
|
+
Use `--mcp-config <path>` to load only the `mcpServers` array from an external JSON file without
|
|
271
|
+
writing a project config file. Relative paths resolve from `--cwd`.
|
|
272
|
+
|
|
270
273
|
Supported keys:
|
|
271
274
|
|
|
272
275
|
```json
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { _ as resolveGlobalFlags, a as hasExplicitPermissionModeFlag, g as resolveAgentInvocation, v as resolveOutputPolicy, x as loadPermissionPolicySpec, y as resolvePermissionMode } from "./flags-
|
|
3
|
-
import { c as validateFlowDefinition, h as isDefinedFlow, o as FlowRunner } from "./flows-
|
|
1
|
+
import { R as permissionModeSatisfies } from "./live-checkpoint-mdAaF3qJ.js";
|
|
2
|
+
import { _ as resolveGlobalFlags, a as hasExplicitPermissionModeFlag, g as resolveAgentInvocation, v as resolveOutputPolicy, x as loadPermissionPolicySpec, y as resolvePermissionMode } from "./flags-Dl_mhic3.js";
|
|
3
|
+
import { c as validateFlowDefinition, h as isDefinedFlow, o as FlowRunner } from "./flows-7OHjgEgq.js";
|
|
4
4
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { InvalidArgumentError } from "commander";
|
|
@@ -8,7 +8,7 @@ import fs from "node:fs/promises";
|
|
|
8
8
|
import { randomUUID } from "node:crypto";
|
|
9
9
|
//#region src/flows/cli.ts
|
|
10
10
|
const FLOW_RUNTIME_SPECIFIER = "acpx/flows";
|
|
11
|
-
const TEXT_MODULE_EXTENSIONS = new Set([
|
|
11
|
+
const TEXT_MODULE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
12
12
|
".js",
|
|
13
13
|
".mjs",
|
|
14
14
|
".cjs",
|
|
@@ -194,4 +194,4 @@ function printFlowRunResult(result, globalFlags) {
|
|
|
194
194
|
//#endregion
|
|
195
195
|
export { handleFlowRun };
|
|
196
196
|
|
|
197
|
-
//# sourceMappingURL=cli-
|
|
197
|
+
//# sourceMappingURL=cli-CXlEcGWV.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-CC2w0U-A.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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"}
|
|
1
|
+
{"version":3,"file":"cli-CXlEcGWV.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.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as runSessionQueueOwner, c as buildQueueOwnerArgOverride, g as __exportAll, h as isProcessAlive, l as flushPerfMetricsCapture, n as getTextErrorRemediationHints, o as runOnce, p as probeQueueOwnerHealth, t as createOutputFormatter, u as installPerfMetricsCapture } from "./output-
|
|
3
|
-
import {
|
|
4
|
-
import { _ as resolveGlobalFlags, b as resolveSessionNameFromFlags, c as parseHistoryLimit, d as parseOutputFormat$1, f as parsePruneBeforeDate, g as resolveAgentInvocation, h as parseTtlSeconds, i as addSessionOption, l as parseMaxTurns, m as parseTimeoutSeconds, n as addPromptInputOption, o as parseAllowedTools, p as parseSessionName, r as addSessionNameOption, s as parseDaysOlderThan, t as addGlobalFlags, u as parseNonEmptyValue, v as resolveOutputPolicy, x as loadPermissionPolicySpec, y as resolvePermissionMode } from "./flags-
|
|
2
|
+
import { a as runSessionQueueOwner, c as buildQueueOwnerArgOverride, g as __exportAll, h as isProcessAlive, l as flushPerfMetricsCapture, n as getTextErrorRemediationHints, o as runOnce, p as probeQueueOwnerHealth, t as createOutputFormatter, u as installPerfMetricsCapture } from "./output-Smw6kFL_.js";
|
|
3
|
+
import { At as listBuiltInAgents, Et as TimeoutError, G as listSessions, Gt as OUTPUT_FORMATS, H as findSession, It as normalizeOutputError, L as getAcpxVersion, Nt as exitCodeForOutputErrorCode, St as parsePromptSource, Tt as InterruptedError, U as findSessionByDirectoryWalk, V as findGitRepositoryRoot, Vt as EXIT_CODES, X as writeSessionRecord, Xt as AgentSpawnError, Yt as AcpxOperationalError, ct as normalizeRuntimeSessionId, ft as sessionEventActivePath, gt as isAcpJsonRpcMessage, jt as normalizeAgentName$1, kt as DEFAULT_AGENT_NAME, mt as sessionEventSegmentPath, ot as parseSessionRecord, pt as sessionEventLockPath, q as normalizeName, st as serializeSessionRecordForDisk, ut as defaultSessionEventLog, wt as textPrompt, xt as mergePromptSourceWithText, yt as PromptInputValidationError } from "./live-checkpoint-mdAaF3qJ.js";
|
|
4
|
+
import { _ as resolveGlobalFlags, b as resolveSessionNameFromFlags, c as parseHistoryLimit, d as parseOutputFormat$1, f as parsePruneBeforeDate, g as resolveAgentInvocation, h as parseTtlSeconds, i as addSessionOption, l as parseMaxTurns, m as parseTimeoutSeconds, n as addPromptInputOption, o as parseAllowedTools, p as parseSessionName, r as addSessionNameOption, s as parseDaysOlderThan, t as addGlobalFlags, u as parseNonEmptyValue, v as resolveOutputPolicy, x as loadPermissionPolicySpec, y as resolvePermissionMode } from "./flags-Dl_mhic3.js";
|
|
5
5
|
import { realpathSync } from "node:fs";
|
|
6
6
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import { Command, CommanderError, InvalidArgumentError, Option } from "commander";
|
|
9
9
|
import fs$1 from "node:fs/promises";
|
|
10
10
|
import os from "node:os";
|
|
11
|
-
import { randomUUID } from "node:crypto";
|
|
11
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
12
12
|
import { ZodError, z } from "zod";
|
|
13
13
|
import { performance } from "node:perf_hooks";
|
|
14
14
|
//#region src/cli-public.ts
|
|
@@ -387,11 +387,11 @@ let sessionModulePromise;
|
|
|
387
387
|
let outputModulePromise;
|
|
388
388
|
let outputRenderModulePromise;
|
|
389
389
|
function loadSessionModule() {
|
|
390
|
-
sessionModulePromise ??= import("./output-
|
|
390
|
+
sessionModulePromise ??= import("./output-Smw6kFL_.js").then((n) => n.i);
|
|
391
391
|
return sessionModulePromise;
|
|
392
392
|
}
|
|
393
393
|
function loadOutputModule() {
|
|
394
|
-
outputModulePromise ??= import("./output-
|
|
394
|
+
outputModulePromise ??= import("./output-Smw6kFL_.js").then((n) => n.r);
|
|
395
395
|
return outputModulePromise;
|
|
396
396
|
}
|
|
397
397
|
function loadOutputRenderModule() {
|
|
@@ -525,6 +525,8 @@ async function handlePrompt(explicitAgentName, promptParts, flags, command, conf
|
|
|
525
525
|
sessionId: record.acpxRecordId,
|
|
526
526
|
prompt,
|
|
527
527
|
mcpServers: config.mcpServers,
|
|
528
|
+
mcpConfigPath: config.mcpConfigPath,
|
|
529
|
+
mcpConfigFingerprint: config.mcpConfigFingerprint,
|
|
528
530
|
permissionMode,
|
|
529
531
|
nonInteractivePermissions: globalFlags.nonInteractivePermissions,
|
|
530
532
|
permissionPolicy,
|
|
@@ -1378,14 +1380,14 @@ const DEFAULT_AUTH_POLICY = "skip";
|
|
|
1378
1380
|
const DEFAULT_OUTPUT_FORMAT = "text";
|
|
1379
1381
|
const DEFAULT_QUEUE_MAX_DEPTH = 16;
|
|
1380
1382
|
const DEFAULT_DISABLE_EXEC = false;
|
|
1381
|
-
const VALID_PERMISSION_MODES = new Set([
|
|
1383
|
+
const VALID_PERMISSION_MODES = /* @__PURE__ */ new Set([
|
|
1382
1384
|
"approve-all",
|
|
1383
1385
|
"approve-reads",
|
|
1384
1386
|
"deny-all"
|
|
1385
1387
|
]);
|
|
1386
|
-
const VALID_NON_INTERACTIVE_PERMISSION_POLICIES = new Set(["deny", "fail"]);
|
|
1387
|
-
const VALID_AUTH_POLICIES = new Set(["skip", "fail"]);
|
|
1388
|
-
const VALID_OUTPUT_FORMATS = new Set([
|
|
1388
|
+
const VALID_NON_INTERACTIVE_PERMISSION_POLICIES = /* @__PURE__ */ new Set(["deny", "fail"]);
|
|
1389
|
+
const VALID_AUTH_POLICIES = /* @__PURE__ */ new Set(["skip", "fail"]);
|
|
1390
|
+
const VALID_OUTPUT_FORMATS = /* @__PURE__ */ new Set([
|
|
1389
1391
|
"text",
|
|
1390
1392
|
"json",
|
|
1391
1393
|
"quiet"
|
|
@@ -1498,6 +1500,16 @@ async function readConfigFile(filePath) {
|
|
|
1498
1500
|
throw error;
|
|
1499
1501
|
}
|
|
1500
1502
|
}
|
|
1503
|
+
async function loadExplicitMcpConfig(cwd, configuredPath) {
|
|
1504
|
+
if (!configuredPath) return {};
|
|
1505
|
+
const resolvedPath = path.resolve(cwd, configuredPath);
|
|
1506
|
+
const result = await readConfigFile(resolvedPath);
|
|
1507
|
+
if (!result.exists) throw new Error(`MCP config file not found: ${resolvedPath}`);
|
|
1508
|
+
return {
|
|
1509
|
+
path: resolvedPath,
|
|
1510
|
+
config: result.config
|
|
1511
|
+
};
|
|
1512
|
+
}
|
|
1501
1513
|
function mergeAgents(globalAgents, projectAgents) {
|
|
1502
1514
|
return {
|
|
1503
1515
|
...globalAgents,
|
|
@@ -1510,16 +1522,20 @@ function mergeAuth(globalAuth, projectAuth) {
|
|
|
1510
1522
|
...projectAuth
|
|
1511
1523
|
};
|
|
1512
1524
|
}
|
|
1513
|
-
async function loadResolvedConfig(cwd) {
|
|
1525
|
+
async function loadResolvedConfig(cwd, options = {}) {
|
|
1514
1526
|
const globalPath = defaultGlobalConfigPath();
|
|
1515
1527
|
const projectPath = projectConfigPath(cwd);
|
|
1516
|
-
const [globalResult, projectResult] = await Promise.all([
|
|
1528
|
+
const [globalResult, projectResult, explicitMcp] = await Promise.all([
|
|
1529
|
+
readConfigFile(globalPath),
|
|
1530
|
+
readConfigFile(projectPath),
|
|
1531
|
+
loadExplicitMcpConfig(cwd, options.mcpConfigPath)
|
|
1532
|
+
]);
|
|
1517
1533
|
const globalConfig = globalResult.config;
|
|
1518
1534
|
const projectConfig = projectResult.config;
|
|
1519
1535
|
const scalar = resolveScalarConfigValues(projectConfig, projectPath, globalConfig, globalPath);
|
|
1520
1536
|
const agents = mergeAgents(parseAgents(globalConfig?.agents, globalPath), parseAgents(projectConfig?.agents, projectPath));
|
|
1521
1537
|
const auth = mergeAuth(parseAuth(globalConfig?.auth, globalPath), parseAuth(projectConfig?.auth, projectPath));
|
|
1522
|
-
const mcpServers = resolveMcpServers(projectConfig, projectPath, globalConfig, globalPath);
|
|
1538
|
+
const mcpServers = resolveMcpServers(projectConfig, projectPath, globalConfig, globalPath, explicitMcp.config, explicitMcp.path);
|
|
1523
1539
|
const disableExec = resolveDisableExec(projectConfig, projectPath, globalConfig, globalPath);
|
|
1524
1540
|
return {
|
|
1525
1541
|
...scalar,
|
|
@@ -1529,6 +1545,8 @@ async function loadResolvedConfig(cwd) {
|
|
|
1529
1545
|
mcpServers,
|
|
1530
1546
|
globalPath,
|
|
1531
1547
|
projectPath,
|
|
1548
|
+
mcpConfigPath: explicitMcp.path,
|
|
1549
|
+
mcpConfigFingerprint: explicitMcp.path ? createHash("sha256").update(JSON.stringify(mcpServers)).digest("hex") : void 0,
|
|
1532
1550
|
hasGlobalConfig: globalResult.exists,
|
|
1533
1551
|
hasProjectConfig: projectResult.exists
|
|
1534
1552
|
};
|
|
@@ -1573,7 +1591,8 @@ function resolveTimeoutMs(projectConfig, projectPath, globalConfig, globalPath)
|
|
|
1573
1591
|
if (hasConfigKey(projectConfig, "timeout")) return parseTimeoutMs(projectConfig?.timeout, projectPath);
|
|
1574
1592
|
if (hasConfigKey(globalConfig, "timeout")) return parseTimeoutMs(globalConfig?.timeout, globalPath);
|
|
1575
1593
|
}
|
|
1576
|
-
function resolveMcpServers(projectConfig, projectPath, globalConfig, globalPath) {
|
|
1594
|
+
function resolveMcpServers(projectConfig, projectPath, globalConfig, globalPath, mcpConfig, mcpConfigPath) {
|
|
1595
|
+
if (mcpConfigPath) return parseMcpServers(mcpConfig?.mcpServers, mcpConfigPath);
|
|
1577
1596
|
if (hasConfigKey(projectConfig, "mcpServers")) return parseMcpServers(projectConfig?.mcpServers, projectPath);
|
|
1578
1597
|
if (hasConfigKey(globalConfig, "mcpServers")) return parseMcpServers(globalConfig?.mcpServers, globalPath);
|
|
1579
1598
|
return [];
|
|
@@ -1620,7 +1639,18 @@ async function initGlobalConfigFile() {
|
|
|
1620
1639
|
agents: {},
|
|
1621
1640
|
auth: {}
|
|
1622
1641
|
};
|
|
1623
|
-
|
|
1642
|
+
try {
|
|
1643
|
+
await fs$1.writeFile(configPath, `${JSON.stringify(payload, null, 2)}\n`, {
|
|
1644
|
+
encoding: "utf8",
|
|
1645
|
+
flag: "wx"
|
|
1646
|
+
});
|
|
1647
|
+
} catch (error) {
|
|
1648
|
+
if (error.code === "EEXIST") return {
|
|
1649
|
+
path: configPath,
|
|
1650
|
+
created: false
|
|
1651
|
+
};
|
|
1652
|
+
throw error;
|
|
1653
|
+
}
|
|
1624
1654
|
return {
|
|
1625
1655
|
path: configPath,
|
|
1626
1656
|
created: true
|
|
@@ -1634,7 +1664,8 @@ async function handleConfigShow(command, config) {
|
|
|
1634
1664
|
...toConfigDisplay(config),
|
|
1635
1665
|
paths: {
|
|
1636
1666
|
global: config.globalPath,
|
|
1637
|
-
project: config.projectPath
|
|
1667
|
+
project: config.projectPath,
|
|
1668
|
+
...config.mcpConfigPath ? { mcp: config.mcpConfigPath } : {}
|
|
1638
1669
|
},
|
|
1639
1670
|
loaded: {
|
|
1640
1671
|
global: config.hasGlobalConfig,
|
|
@@ -2141,7 +2172,7 @@ function registerAgentCommand(program, agentName, config) {
|
|
|
2141
2172
|
}
|
|
2142
2173
|
function registerFlowCommand(program, config) {
|
|
2143
2174
|
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) {
|
|
2144
|
-
const { handleFlowRun } = await import("./cli-
|
|
2175
|
+
const { handleFlowRun } = await import("./cli-CXlEcGWV.js");
|
|
2145
2176
|
await handleFlowRun(file, flags, this, config);
|
|
2146
2177
|
});
|
|
2147
2178
|
}
|
|
@@ -2161,6 +2192,8 @@ function registerDefaultCommands(program, config) {
|
|
|
2161
2192
|
}
|
|
2162
2193
|
//#endregion
|
|
2163
2194
|
//#region src/cli/queue/owner-env.ts
|
|
2195
|
+
const QUEUE_OWNER_PAYLOAD_FILE_ENV = "ACPX_QUEUE_OWNER_PAYLOAD_FILE";
|
|
2196
|
+
const QUEUE_OWNER_PAYLOAD_ENV = "ACPX_QUEUE_OWNER_PAYLOAD";
|
|
2164
2197
|
function asRecord(value) {
|
|
2165
2198
|
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
2166
2199
|
return value;
|
|
@@ -2182,6 +2215,8 @@ function parseQueueOwnerPayload(raw) {
|
|
|
2182
2215
|
function assignQueueOwnerTransportOptions(options, record) {
|
|
2183
2216
|
const parsedMcpServers = parseOptionalMcpServers(record.mcpServers, "queue owner payload");
|
|
2184
2217
|
if (parsedMcpServers) options.mcpServers = parsedMcpServers;
|
|
2218
|
+
if (typeof record.mcpConfigPath === "string" && record.mcpConfigPath.length > 0) options.mcpConfigPath = record.mcpConfigPath;
|
|
2219
|
+
if (typeof record.mcpConfigFingerprint === "string" && record.mcpConfigFingerprint.length > 0) options.mcpConfigFingerprint = record.mcpConfigFingerprint;
|
|
2185
2220
|
if (record.authCredentials && typeof record.authCredentials === "object") {
|
|
2186
2221
|
const entries = Object.entries(record.authCredentials).filter(([, value]) => typeof value === "string");
|
|
2187
2222
|
options.authCredentials = Object.fromEntries(entries);
|
|
@@ -2214,6 +2249,7 @@ function assignQueueOwnerSessionOptions(options, rawSessionOptions) {
|
|
|
2214
2249
|
assignSessionAllowedTools(options.sessionOptions, sessionOpts.allowedTools);
|
|
2215
2250
|
assignSessionMaxTurns(options.sessionOptions, sessionOpts.maxTurns);
|
|
2216
2251
|
assignSessionSystemPrompt(options.sessionOptions, sessionOpts.systemPrompt);
|
|
2252
|
+
assignSessionEnv(options.sessionOptions, sessionOpts.env);
|
|
2217
2253
|
}
|
|
2218
2254
|
function assignSessionModel(options, value) {
|
|
2219
2255
|
if (typeof value === "string" && value.trim().length > 0) options.model = value;
|
|
@@ -2232,14 +2268,39 @@ function assignSessionSystemPrompt(options, value) {
|
|
|
2232
2268
|
const systemPrompt = asRecord(value);
|
|
2233
2269
|
if (typeof systemPrompt?.append === "string") options.systemPrompt = { append: systemPrompt.append };
|
|
2234
2270
|
}
|
|
2271
|
+
function assignSessionEnv(options, value) {
|
|
2272
|
+
const env = asRecord(value);
|
|
2273
|
+
if (!env) return;
|
|
2274
|
+
const entries = Object.entries(env).filter((entry) => typeof entry[1] === "string");
|
|
2275
|
+
if (entries.length > 0) options.env = Object.fromEntries(entries);
|
|
2276
|
+
}
|
|
2235
2277
|
async function runQueueOwnerFromEnv(env) {
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2278
|
+
await runSessionQueueOwner(parseQueueOwnerPayload(await readQueueOwnerPayloadFromEnv(env)));
|
|
2279
|
+
}
|
|
2280
|
+
async function readQueueOwnerPayloadFromEnv(env) {
|
|
2281
|
+
const payloadFile = env[QUEUE_OWNER_PAYLOAD_FILE_ENV];
|
|
2282
|
+
if (payloadFile) {
|
|
2283
|
+
const payload = await fs$1.readFile(payloadFile, "utf8");
|
|
2284
|
+
await cleanupQueueOwnerPayloadFile(payloadFile).catch(() => {});
|
|
2285
|
+
return payload;
|
|
2286
|
+
}
|
|
2287
|
+
const payload = env[QUEUE_OWNER_PAYLOAD_ENV];
|
|
2288
|
+
if (!payload) throw new Error(`missing ${QUEUE_OWNER_PAYLOAD_ENV}`);
|
|
2289
|
+
return payload;
|
|
2290
|
+
}
|
|
2291
|
+
async function cleanupQueueOwnerPayloadFile(payloadFile) {
|
|
2292
|
+
if (!isQueueOwnerPayloadFile(payloadFile)) return;
|
|
2293
|
+
await fs$1.unlink(payloadFile).catch(() => {});
|
|
2294
|
+
await fs$1.rmdir(path.dirname(payloadFile)).catch(() => {});
|
|
2295
|
+
}
|
|
2296
|
+
function isQueueOwnerPayloadFile(payloadFile) {
|
|
2297
|
+
const resolved = path.resolve(payloadFile);
|
|
2298
|
+
const payloadDir = path.dirname(resolved);
|
|
2299
|
+
return path.dirname(payloadDir) === path.resolve(os.tmpdir()) && path.basename(payloadDir).startsWith("acpx-queue-owner-") && path.basename(resolved) === "payload.json";
|
|
2239
2300
|
}
|
|
2240
2301
|
//#endregion
|
|
2241
2302
|
//#region src/cli-core.ts
|
|
2242
|
-
const TOP_LEVEL_VERBS = new Set([
|
|
2303
|
+
const TOP_LEVEL_VERBS = /* @__PURE__ */ new Set([
|
|
2243
2304
|
"prompt",
|
|
2244
2305
|
"exec",
|
|
2245
2306
|
"cancel",
|
|
@@ -2267,10 +2328,11 @@ const TOP_LEVEL_VERSION_VALUE_FLAG_VALUES = [
|
|
|
2267
2328
|
"--append-system-prompt",
|
|
2268
2329
|
"--prompt-retries",
|
|
2269
2330
|
"--timeout",
|
|
2270
|
-
"--ttl"
|
|
2331
|
+
"--ttl",
|
|
2332
|
+
"--mcp-config"
|
|
2271
2333
|
];
|
|
2272
2334
|
const TOP_LEVEL_VERSION_VALUE_FLAGS = new Set(TOP_LEVEL_VERSION_VALUE_FLAG_VALUES);
|
|
2273
|
-
const TOP_LEVEL_VERSION_BOOLEAN_FLAGS = new Set([
|
|
2335
|
+
const TOP_LEVEL_VERSION_BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
2274
2336
|
"--approve-all",
|
|
2275
2337
|
"--approve-reads",
|
|
2276
2338
|
"--deny-all",
|
|
@@ -2338,31 +2400,69 @@ function detectAgentToken(argv) {
|
|
|
2338
2400
|
function detectInitialCwd(argv) {
|
|
2339
2401
|
for (let index = 0; index < argv.length; index += 1) {
|
|
2340
2402
|
const token = argv[index];
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
if (
|
|
2347
|
-
const value = token.slice(6).trim();
|
|
2348
|
-
if (value.length > 0) return path.resolve(value);
|
|
2349
|
-
break;
|
|
2350
|
-
}
|
|
2351
|
-
if (token === "--") break;
|
|
2403
|
+
const scan = classifyTopLevelFlagScan(token);
|
|
2404
|
+
if (scan.stop) break;
|
|
2405
|
+
const cwd = readCwdFlagValue(token, argv[index + 1]);
|
|
2406
|
+
if (cwd) return path.resolve(cwd);
|
|
2407
|
+
if (isCwdFlagToken(token)) break;
|
|
2408
|
+
if (scan.skipNext) index += 1;
|
|
2352
2409
|
}
|
|
2353
2410
|
return process.cwd();
|
|
2354
2411
|
}
|
|
2412
|
+
function detectMcpConfigPath(argv, cwd) {
|
|
2413
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
2414
|
+
const scan = scanMcpConfigToken(argv[index], argv[index + 1], cwd);
|
|
2415
|
+
if (scan.stop) return scan.path;
|
|
2416
|
+
if (scan.skipNext) index += 1;
|
|
2417
|
+
}
|
|
2418
|
+
}
|
|
2419
|
+
function scanMcpConfigToken(token, nextToken, cwd) {
|
|
2420
|
+
if (token === "--" || !token.startsWith("-") || token === "-") return { stop: true };
|
|
2421
|
+
if (token === "--mcp-config") return {
|
|
2422
|
+
path: resolveMcpConfigPath(nextToken, cwd),
|
|
2423
|
+
stop: true
|
|
2424
|
+
};
|
|
2425
|
+
if (token.startsWith("--mcp-config=")) return {
|
|
2426
|
+
path: resolveMcpConfigPath(token.slice(13), cwd),
|
|
2427
|
+
stop: true
|
|
2428
|
+
};
|
|
2429
|
+
return { skipNext: TOP_LEVEL_VERSION_VALUE_FLAGS.has(token) };
|
|
2430
|
+
}
|
|
2431
|
+
function resolveMcpConfigPath(value, cwd) {
|
|
2432
|
+
const trimmed = value?.trim();
|
|
2433
|
+
return trimmed && trimmed !== "--" ? path.resolve(cwd, trimmed) : void 0;
|
|
2434
|
+
}
|
|
2435
|
+
function isCwdFlagToken(token) {
|
|
2436
|
+
return token === "--cwd" || token.startsWith("--cwd=");
|
|
2437
|
+
}
|
|
2438
|
+
function readCwdFlagValue(token, nextToken) {
|
|
2439
|
+
const value = (token === "--cwd" ? nextToken : readInlineFlagValue(token, "--cwd"))?.trim();
|
|
2440
|
+
if (!value || value === "--") return;
|
|
2441
|
+
return value;
|
|
2442
|
+
}
|
|
2355
2443
|
function detectRequestedOutputFormat(argv, fallback) {
|
|
2356
2444
|
let detectedFormat = fallback;
|
|
2357
2445
|
for (let index = 0; index < argv.length; index += 1) {
|
|
2358
2446
|
const token = argv[index];
|
|
2359
|
-
|
|
2447
|
+
const scan = classifyTopLevelFlagScan(token);
|
|
2448
|
+
if (scan.stop) break;
|
|
2360
2449
|
if (isJsonStrictToken(token)) return "json";
|
|
2361
2450
|
const format = readFormatFlagValue(token, argv[index + 1]);
|
|
2362
2451
|
if (format) detectedFormat = format;
|
|
2452
|
+
if (scan.skipNext) index += 1;
|
|
2363
2453
|
}
|
|
2364
2454
|
return detectedFormat;
|
|
2365
2455
|
}
|
|
2456
|
+
function classifyTopLevelFlagScan(token) {
|
|
2457
|
+
if (token === "--" || !token.startsWith("-") || token === "-") return {
|
|
2458
|
+
stop: true,
|
|
2459
|
+
skipNext: false
|
|
2460
|
+
};
|
|
2461
|
+
return {
|
|
2462
|
+
stop: false,
|
|
2463
|
+
skipNext: TOP_LEVEL_VERSION_VALUE_FLAGS.has(token)
|
|
2464
|
+
};
|
|
2465
|
+
}
|
|
2366
2466
|
function readFormatFlagValue(token, nextToken) {
|
|
2367
2467
|
const raw = token === "--format" ? nextToken : readInlineFlagValue(token, "--format");
|
|
2368
2468
|
return isOutputFormat(raw) ? raw : void 0;
|
|
@@ -2380,8 +2480,10 @@ function isJsonStrictToken(token) {
|
|
|
2380
2480
|
function detectJsonStrict(argv) {
|
|
2381
2481
|
for (let index = 0; index < argv.length; index += 1) {
|
|
2382
2482
|
const token = argv[index];
|
|
2383
|
-
|
|
2483
|
+
const scan = classifyTopLevelFlagScan(token);
|
|
2484
|
+
if (scan.stop) break;
|
|
2384
2485
|
if (isJsonStrictToken(token)) return true;
|
|
2486
|
+
if (scan.skipNext) index += 1;
|
|
2385
2487
|
}
|
|
2386
2488
|
return false;
|
|
2387
2489
|
}
|
|
@@ -2493,7 +2595,8 @@ async function main(argv = process.argv) {
|
|
|
2493
2595
|
return;
|
|
2494
2596
|
}
|
|
2495
2597
|
await maybeHandleSkillflag(normalizedArgv);
|
|
2496
|
-
const
|
|
2598
|
+
const initialCwd = detectInitialCwd(rawArgs);
|
|
2599
|
+
const config = await loadResolvedConfig(initialCwd, { mcpConfigPath: detectMcpConfigPath(rawArgs, initialCwd) });
|
|
2497
2600
|
const requestedJsonStrict = detectJsonStrict(rawArgs);
|
|
2498
2601
|
const requestedOutputPolicy = {
|
|
2499
2602
|
...resolveOutputPolicy(detectRequestedOutputFormat(rawArgs, config.format), requestedJsonStrict),
|