acpx 0.13.0 → 0.13.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 +64 -382
- package/dist/{cli-D52eGvxU.js → cli-DJT3MRRI.js} +6 -5
- package/dist/{cli-D52eGvxU.js.map → cli-DJT3MRRI.js.map} +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +20 -13
- package/dist/cli.js.map +1 -1
- package/dist/{client-BeKvumq9.d.ts → client-CxNllqui.d.ts} +15 -3
- package/dist/client-CxNllqui.d.ts.map +1 -0
- package/dist/{flags---9OR06b.js → flags-CM2rAdBo.js} +3 -3
- package/dist/{flags---9OR06b.js.map → flags-CM2rAdBo.js.map} +1 -1
- package/dist/{flows-CYfjwbn2.js → flows-BiRKgCnW.js} +4 -4
- package/dist/{flows-CYfjwbn2.js.map → flows-BiRKgCnW.js.map} +1 -1
- package/dist/flows.d.ts +2 -2
- package/dist/flows.js +1 -1
- package/dist/{live-checkpoint-CBecfnSH.js → live-checkpoint-Gw2oGjhe.js} +445 -252
- package/dist/live-checkpoint-Gw2oGjhe.js.map +1 -0
- package/dist/{output-CzN8vLdE.js → output-DiPPprGk.js} +40 -84
- package/dist/output-DiPPprGk.js.map +1 -0
- package/dist/runtime.d.ts +107 -23
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +600 -202
- package/dist/runtime.js.map +1 -1
- package/dist/{session-options-CTdZvr68.d.ts → session-options-DwRDODlr.d.ts} +25 -3
- package/dist/session-options-DwRDODlr.d.ts.map +1 -0
- package/package.json +15 -15
- package/skills/acpx/SKILL.md +5 -1
- package/dist/client-BeKvumq9.d.ts.map +0 -1
- package/dist/live-checkpoint-CBecfnSH.js.map +0 -1
- package/dist/output-CzN8vLdE.js.map +0 -1
- package/dist/session-options-CTdZvr68.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,432 +1,114 @@
|
|
|
1
|
+
# acpx 🤝 — Agents talking to agents, minus the terminal séance
|
|
2
|
+
|
|
1
3
|
<p align="center">
|
|
2
4
|
<img src="acpx_banner.svg" alt="acpx banner" width="100%" />
|
|
3
5
|
</p>
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
[](https://opensource.org/licenses/MIT)
|
|
11
|
-
[](https://nodejs.org)
|
|
12
|
-
|
|
13
|
-
> ⚠️ `acpx` is in alpha and the CLI/runtime interfaces are likely to change. Anything you build downstream of this might break until it stabilizes.
|
|
14
|
-
|
|
15
|
-
> ACP coverage status: see [ACP Spec Coverage Roadmap](docs/2026-02-19-acp-coverage-roadmap.md).
|
|
16
|
-
|
|
17
|
-
Your agents love acpx! 🤖❤️ They hate having to scrape characters from a PTY session 😤
|
|
18
|
-
|
|
19
|
-
`acpx` is a headless CLI client for the [Agent Client Protocol (ACP)](https://agentclientprotocol.com), so AI agents and orchestrators can talk to coding agents over a structured protocol instead of PTY scraping.
|
|
20
|
-
|
|
21
|
-
One command surface for Pi, OpenClaw ACP, Codex, Claude, and other ACP-compatible agents. Built for agent-to-agent communication over the command line.
|
|
22
|
-
|
|
23
|
-
- **Persistent sessions**: multi-turn conversations that survive across invocations, scoped per repo
|
|
24
|
-
- **Named sessions**: run parallel workstreams in the same repo (`-s backend`, `-s frontend`)
|
|
25
|
-
- **Prompt queueing**: submit prompts while one is already running, they execute in order
|
|
26
|
-
- **Cooperative cancel command**: `cancel` sends ACP `session/cancel` via queue IPC without tearing down session state
|
|
27
|
-
- **Soft-close lifecycle**: close sessions without deleting history from disk
|
|
28
|
-
- **Queue owner TTL**: keep queue owners alive briefly for follow-up prompts (`--ttl`)
|
|
29
|
-
- **Fire-and-forget**: `--no-wait` queues a prompt and returns immediately
|
|
30
|
-
- **Graceful cancel**: `Ctrl+C` sends ACP `session/cancel` before force-kill fallback
|
|
31
|
-
- **Session controls**: `set-mode` and `set <key> <value>` for `session/set_mode` and `session/set_config_option`
|
|
32
|
-
- **Crash reconnect**: dead agent processes are detected and sessions are resumed or reloaded automatically
|
|
33
|
-
- **Prompt from file/stdin**: `--file <path>` or piped stdin for prompt content
|
|
34
|
-
- **Config files**: global + project JSON config with `acpx config show|init`
|
|
35
|
-
- **Session inspect/history**: `sessions show` and `sessions history --limit <n>`
|
|
36
|
-
- **Session export/import**: move portable session archives between machines
|
|
37
|
-
- **Local status checks**: `status` reports running/idle/dead/no-session, pid, uptime, last prompt
|
|
38
|
-
- **Client methods**: stable `fs/*` and `terminal/*` handlers with permission controls and cwd sandboxing
|
|
39
|
-
- **Capability opt-outs**: let adapters use their native filesystem or terminal tools with `--no-fs` and `--no-terminal`
|
|
40
|
-
- **Auth handshake**: stable `authenticate` support via env/config credentials
|
|
41
|
-
- **Structured output**: typed ACP messages (thinking, tool calls, diffs) instead of ANSI scraping
|
|
42
|
-
- **Any ACP agent**: built-in registry + `--agent` escape hatch for custom servers
|
|
43
|
-
- **One-shot mode**: `exec` for stateless fire-and-forget tasks
|
|
44
|
-
- **Compare across agents**: `acpx compare pi openclaw codex 'fix the bug'` runs the same one-shot prompt against multiple ACP-compatible agents and summarizes timing, token usage, permissions, and final output side by side
|
|
45
|
-
- **Experimental flows**: `flow run <file>` for TypeScript workflow modules over multiple prompts
|
|
46
|
-
- **Runtime-owned flow actions**: shell-backed action steps can prepare workspaces and other deterministic mechanics outside the agent turn
|
|
47
|
-
- **Flow workspace isolation**: `acp` nodes can target an explicit per-step cwd, so flows can keep agent work inside disposable worktrees
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
$ acpx codex sessions new
|
|
51
|
-
$ acpx codex "find the flaky test and fix it"
|
|
52
|
-
|
|
53
|
-
[thinking] Investigating test suite for flaky failures
|
|
54
|
-
|
|
55
|
-
[tool] Run npm test -- --reporter=verbose (running)
|
|
56
|
-
[tool] Run npm test -- --reporter=verbose (completed)
|
|
57
|
-
output:
|
|
58
|
-
✓ auth.login (0.8s)
|
|
59
|
-
✗ checkout.submit (timed out after 5000ms)
|
|
60
|
-
✓ cart.add (0.3s)
|
|
61
|
-
|
|
62
|
-
[thinking] Found it — checkout.submit has a race condition in the async setup
|
|
63
|
-
|
|
64
|
-
[tool] Edit src/checkout.test.ts (completed)
|
|
65
|
-
output:
|
|
66
|
-
Success. Updated 1 file.
|
|
7
|
+
[](https://github.com/openclaw/acpx/actions/workflows/ci.yml)
|
|
8
|
+
[](https://www.npmjs.com/package/acpx)
|
|
9
|
+
[](https://nodejs.org/)
|
|
10
|
+
[](LICENSE)
|
|
11
|
+
[](https://www.npmjs.com/package/acpx)
|
|
67
12
|
|
|
68
|
-
[
|
|
69
|
-
output:
|
|
70
|
-
✓ checkout.submit (0.4s)
|
|
71
|
-
|
|
72
|
-
Fixed: added `await` to the setup hook in checkout.submit. The test was
|
|
73
|
-
reading stale state from the previous run.
|
|
13
|
+
`acpx` is a headless command-line client for the [Agent Client Protocol (ACP)](https://agentclientprotocol.com). It gives agents, orchestrators, and developers one structured interface for persistent sessions, one-shot runs, permissions, and machine-readable output across ACP-compatible coding agents.
|
|
74
14
|
|
|
15
|
+
```console
|
|
16
|
+
$ acpx codex sessions new
|
|
17
|
+
<session-id>
|
|
18
|
+
$ acpx codex "summarize this repository"
|
|
19
|
+
[tool] Read README.md (completed)
|
|
20
|
+
This repository contains ...
|
|
75
21
|
[done] end_turn
|
|
76
22
|
```
|
|
77
23
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
Copy the block below and paste it into your Pi, OpenClaw, Claude Code, or similar agent harness. It will install acpx, read the skill reference, and know how to use ACP for all future coding agent tasks.
|
|
81
|
-
|
|
82
|
-
```text
|
|
83
|
-
I want you to use acpx to run coding agents over the Agent Client Protocol
|
|
84
|
-
(ACP) instead of scraping PTY sessions. Please do the following:
|
|
85
|
-
|
|
86
|
-
1. Install acpx globally (recommended) or use npx:
|
|
87
|
-
npm install -g acpx@latest
|
|
88
|
-
|
|
89
|
-
Or without installing:
|
|
90
|
-
npx acpx@latest
|
|
91
|
-
|
|
92
|
-
2. For Pi or OpenClaw, use the reference URL below. For Codex-style skill
|
|
93
|
-
installation, install the acpx skill so you have the full reference
|
|
94
|
-
available:
|
|
95
|
-
npx acpx@latest --skill install acpx --agent codex --scope user
|
|
96
|
-
Use --agent claude for Claude Code. For another harness not listed by
|
|
97
|
-
--skill install --help, use the reference URL below instead.
|
|
98
|
-
|
|
99
|
-
3. Read the acpx skill reference so you know every command, flag, and
|
|
100
|
-
workflow pattern:
|
|
101
|
-
https://raw.githubusercontent.com/openclaw/acpx/main/skills/acpx/SKILL.md
|
|
102
|
-
|
|
103
|
-
4. If you need the full CLI reference with all options and examples:
|
|
104
|
-
https://raw.githubusercontent.com/openclaw/acpx/main/docs/CLI.md
|
|
105
|
-
|
|
106
|
-
From now on, when you need to delegate work to a coding agent, use acpx
|
|
107
|
-
instead of spawning raw terminal sessions. For example:
|
|
108
|
-
npx acpx@latest codex "fix the failing tests"
|
|
109
|
-
npx acpx@latest claude "refactor the auth module"
|
|
110
|
-
npx acpx@latest codex exec "one-shot: summarize this repo"
|
|
111
|
-
```
|
|
24
|
+
> [!NOTE]
|
|
25
|
+
> `acpx` is pre-1.0. Treat its CLI and runtime interfaces as evolving.
|
|
112
26
|
|
|
113
27
|
## Install
|
|
114
28
|
|
|
115
|
-
|
|
116
|
-
npm install -g acpx@latest
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
Or run without installing:
|
|
29
|
+
Install the published npm package globally:
|
|
120
30
|
|
|
121
31
|
```bash
|
|
122
|
-
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
Session state lives in `~/.acpx/` either way. Global install is a little faster, but `npx acpx@latest` works fine.
|
|
126
|
-
|
|
127
|
-
## Agent prerequisites
|
|
128
|
-
|
|
129
|
-
`acpx` auto-downloads ACP adapters with `npx` on first use. You do not need to install adapter packages manually.
|
|
130
|
-
|
|
131
|
-
The only prerequisite is the underlying coding agent you want to use:
|
|
132
|
-
|
|
133
|
-
- `acpx pi` -> Pi Coding Agent: https://github.com/mariozechner/pi
|
|
134
|
-
- `acpx openclaw` -> OpenClaw ACP bridge: https://github.com/openclaw/openclaw
|
|
135
|
-
- `acpx codex` -> Codex CLI: https://codex.openai.com
|
|
136
|
-
- `acpx claude` -> Claude Code: https://claude.ai/code
|
|
137
|
-
|
|
138
|
-
Additional built-in agent docs live in [agents/README.md](agents/README.md).
|
|
139
|
-
|
|
140
|
-
## Usage examples
|
|
141
|
-
|
|
142
|
-
```bash
|
|
143
|
-
acpx codex sessions new # create a session (explicit) for this project dir
|
|
144
|
-
acpx codex 'fix the tests' # implicit prompt (routes via directory-walk)
|
|
145
|
-
acpx codex prompt 'fix the tests' # explicit prompt subcommand
|
|
146
|
-
echo 'fix flaky tests' | acpx codex # prompt from stdin
|
|
147
|
-
acpx codex --file prompt.md # prompt from file
|
|
148
|
-
acpx codex --file - "extra context" # explicit stdin + appended args
|
|
149
|
-
acpx codex --no-wait 'draft test migration plan' # enqueue without waiting if session is busy
|
|
150
|
-
acpx codex cancel # cooperative cancel of in-flight prompt
|
|
151
|
-
acpx codex set-mode auto # session/set_mode (adapter-defined mode id)
|
|
152
|
-
acpx codex set model gpt-5.6-sol # select the advertised base model
|
|
153
|
-
acpx codex set reasoning_effort max # set the advertised reasoning effort
|
|
154
|
-
acpx exec 'summarize this repo' # default agent shortcut (codex)
|
|
155
|
-
acpx codex exec 'what does this repo do?' # one-shot, no saved session
|
|
156
|
-
|
|
157
|
-
acpx codex sessions new --name api # create named session
|
|
158
|
-
acpx codex -s api 'implement token pagination' # prompt in named session
|
|
159
|
-
acpx codex sessions new --name docs # create another named session
|
|
160
|
-
acpx codex -s docs 'rewrite API docs' # parallel work in another named session
|
|
161
|
-
|
|
162
|
-
acpx codex sessions # list sessions for codex command
|
|
163
|
-
acpx codex sessions list # explicit list
|
|
164
|
-
acpx codex sessions show # inspect cwd session metadata
|
|
165
|
-
acpx codex sessions history # show recent turn history
|
|
166
|
-
acpx codex sessions new # create fresh cwd-scoped default session
|
|
167
|
-
acpx codex sessions new --name api # create fresh named session
|
|
168
|
-
acpx codex sessions ensure # return existing scoped session or create one
|
|
169
|
-
acpx codex sessions ensure --name api # ensure named scoped session
|
|
170
|
-
acpx codex sessions close # close cwd-scoped default session
|
|
171
|
-
acpx codex sessions close api # close cwd-scoped named session
|
|
172
|
-
acpx codex status # local process status for current session
|
|
173
|
-
|
|
174
|
-
acpx config show # show resolved config (global + project)
|
|
175
|
-
acpx config init # create ~/.acpx/config.json template
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
Main landing harness examples:
|
|
179
|
-
|
|
180
|
-
```bash
|
|
181
|
-
acpx pi 'review recent changes'
|
|
182
|
-
acpx openclaw exec 'summarize active session state' # built-in OpenClaw ACP bridge
|
|
183
|
-
acpx codex 'fix the failing typecheck'
|
|
184
|
-
acpx claude 'refactor auth middleware' # built-in claude agent
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
Additional supported harnesses and their specific notes are documented in [agents/README.md](agents/README.md).
|
|
188
|
-
|
|
189
|
-
```bash
|
|
190
|
-
acpx my-agent 'review this patch' # unknown name -> raw command
|
|
191
|
-
acpx --agent './bin/dev-acp --profile ci' 'run checks' # --agent escape hatch
|
|
32
|
+
npm install -g acpx@latest
|
|
192
33
|
```
|
|
193
34
|
|
|
194
|
-
|
|
35
|
+
`acpx` requires Node.js 22.13 or newer. To try it without a global install, prefix a command with `npx acpx@latest` instead. See the [install guide](docs/install.md) for adapter prerequisites, updates, and source builds.
|
|
195
36
|
|
|
196
|
-
|
|
197
|
-
# Review a PR in a dedicated session and auto-approve permissions
|
|
198
|
-
acpx --cwd ~/repos/shop --approve-all codex -s pr-842 \
|
|
199
|
-
'Review PR #842 for regressions and propose a minimal fix'
|
|
200
|
-
|
|
201
|
-
# Keep parallel streams for the same repo
|
|
202
|
-
acpx codex -s bugfix 'isolate flaky checkout test'
|
|
203
|
-
acpx codex -s release 'draft release notes from recent commits'
|
|
204
|
-
```
|
|
37
|
+
## Quick start
|
|
205
38
|
|
|
206
|
-
|
|
39
|
+
Install and authenticate the coding agent you want to use, then create a session in your project and send it a prompt:
|
|
207
40
|
|
|
208
41
|
```bash
|
|
209
|
-
acpx
|
|
210
|
-
acpx
|
|
211
|
-
acpx --deny-all codex 'explain what you can do without tool access'
|
|
212
|
-
acpx --non-interactive-permissions fail codex 'fail instead of deny in non-TTY'
|
|
213
|
-
acpx --policy '{"escalate":["execute"],"defaultAction":"deny"}' --format json codex exec 'ask before shell'
|
|
214
|
-
|
|
215
|
-
acpx --cwd ~/repos/backend codex 'review recent auth changes'
|
|
216
|
-
acpx --format text codex 'summarize your findings'
|
|
217
|
-
acpx --format json codex exec 'review changed files'
|
|
218
|
-
acpx --format json --json-strict codex exec 'machine-safe JSON only'
|
|
219
|
-
acpx flow run ./my-flow.ts --input-file ./flow-input.json
|
|
220
|
-
acpx --timeout 1800 flow run ./my-flow.ts
|
|
221
|
-
acpx --format quiet codex 'final recommendation only'
|
|
222
|
-
acpx --suppress-reads codex exec 'show tool activity without dumping file bodies'
|
|
223
|
-
acpx --no-fs codex exec 'read files without ACP client filesystem delegation'
|
|
224
|
-
|
|
225
|
-
acpx --timeout 90 codex 'investigate intermittent test timeout'
|
|
226
|
-
acpx --ttl 30 codex 'keep queue owner alive for quick follow-ups'
|
|
227
|
-
acpx --verbose codex 'debug why adapter startup is failing'
|
|
42
|
+
acpx codex sessions new
|
|
43
|
+
acpx codex "find the slowest test and explain why"
|
|
228
44
|
```
|
|
229
45
|
|
|
230
|
-
|
|
46
|
+
The session is scoped to the current repository and persists across invocations. Creating sessions explicitly prevents automation from starting an unexpected conversation. The [quickstart](docs/quickstart.md) continues with named sessions, one-shot runs, history, and JSON output.
|
|
231
47
|
|
|
232
|
-
|
|
233
|
-
runtime and persists run state under `~/.acpx/flows/runs/`.
|
|
48
|
+
## Choose an agent
|
|
234
49
|
|
|
235
|
-
|
|
50
|
+
Use the same command shape with the built-in launch profiles:
|
|
236
51
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
52
|
+
| Agent | Command |
|
|
53
|
+
| ----------------- | ---------------------------- |
|
|
54
|
+
| Codex | `acpx codex …` |
|
|
55
|
+
| Claude Code | `acpx claude …` |
|
|
56
|
+
| Gemini CLI | `acpx gemini …` |
|
|
57
|
+
| OpenClaw | `acpx openclaw …` |
|
|
58
|
+
| Custom ACP server | `acpx --agent '<command>' …` |
|
|
242
59
|
|
|
243
|
-
The
|
|
60
|
+
The upstream agent must be installed and authenticated when its adapter does not provide that itself. See [built-in agents](docs/agents.md) for every supported profile and [custom agents](docs/custom-agents.md) for registry configuration.
|
|
244
61
|
|
|
245
|
-
|
|
246
|
-
- a larger PR-triage example under [examples/flows/pr-triage/README.md](examples/flows/pr-triage/README.md)
|
|
247
|
-
- a replay viewer under [examples/flows/replay-viewer/README.md](examples/flows/replay-viewer/README.md) for inspecting saved run bundles in the browser
|
|
62
|
+
## Sessions and one-shot runs
|
|
248
63
|
|
|
249
|
-
|
|
64
|
+
Persistent sessions keep context between prompts, support parallel named workstreams, and queue follow-up prompts when a turn is already running. Use `exec` when you want a stateless run with no saved session.
|
|
250
65
|
|
|
251
66
|
```bash
|
|
252
|
-
acpx
|
|
253
|
-
|
|
254
|
-
acpx
|
|
255
|
-
--input-json '{"task":"FIX: add a regression test for the reconnect bug"}'
|
|
256
|
-
|
|
257
|
-
acpx flow run examples/flows/pr-triage/pr-triage.flow.ts \
|
|
258
|
-
--input-json '{"repo":"openclaw/acpx","prNumber":150}'
|
|
67
|
+
acpx codex sessions new --name backend
|
|
68
|
+
acpx codex -s backend "trace the checkout timeout"
|
|
69
|
+
acpx codex exec "summarize this repository"
|
|
259
70
|
```
|
|
260
71
|
|
|
261
|
-
|
|
262
|
-
real GitHub PRs if you run it against a live repository.
|
|
263
|
-
|
|
264
|
-
## Configuration files
|
|
265
|
-
|
|
266
|
-
`acpx` reads config in this order (later wins):
|
|
267
|
-
|
|
268
|
-
1. global: `~/.acpx/config.json`
|
|
269
|
-
2. project: `<cwd>/.acpxrc.json`
|
|
270
|
-
|
|
271
|
-
CLI flags always win over config values.
|
|
272
|
-
|
|
273
|
-
Use `--mcp-config <path>` to load only the `mcpServers` array from an external JSON file without
|
|
274
|
-
writing a project config file. Relative paths resolve from `--cwd`.
|
|
72
|
+
Session state lives under `~/.acpx/`. The [sessions guide](docs/sessions.md) covers scope, queue ownership, reconnects, export/import, cancellation, and cleanup.
|
|
275
73
|
|
|
276
|
-
|
|
74
|
+
## Automation and permissions
|
|
277
75
|
|
|
278
|
-
|
|
279
|
-
{
|
|
280
|
-
"defaultAgent": "codex",
|
|
281
|
-
"defaultPermissions": "approve-all",
|
|
282
|
-
"nonInteractivePermissions": "deny",
|
|
283
|
-
"authPolicy": "skip",
|
|
284
|
-
"ttl": 300,
|
|
285
|
-
"timeout": null,
|
|
286
|
-
"format": "text",
|
|
287
|
-
"agents": {
|
|
288
|
-
"my-custom": { "argv": ["./bin/my-acp-server", "acp"] }
|
|
289
|
-
},
|
|
290
|
-
"auth": {
|
|
291
|
-
"my_auth_method_id": "credential-value"
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
```
|
|
76
|
+
Text output is the default. `--format json` emits NDJSON ACP events for automation, while `--format quiet` prints only the final assistant text. Output events retain structured thinking, tool calls, diffs, and completion state instead of terminal escape sequences.
|
|
295
77
|
|
|
296
|
-
|
|
297
|
-
Use structured `agents.<name>.argv` for custom launches; it is required on Windows. Legacy
|
|
298
|
-
`command` plus `args` entries migrate when `command` is an unquoted executable with no whitespace,
|
|
299
|
-
while raw command strings remain Unix-only.
|
|
78
|
+
Permission modes range from read approval to explicit deny or approve-all policies. Use `--cwd` to set the session scope and filesystem boundary. Global and project JSON configuration can provide defaults; command-line flags take precedence.
|
|
300
79
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
80
|
+
- [Output formats](docs/output-formats.md)
|
|
81
|
+
- [Permissions](docs/permissions.md)
|
|
82
|
+
- [Configuration](docs/config.md)
|
|
83
|
+
- [Exit codes](docs/exit-codes.md)
|
|
305
84
|
|
|
306
|
-
##
|
|
85
|
+
## Flows and embedding
|
|
307
86
|
|
|
308
|
-
|
|
309
|
-
# text (default): human-readable stream with tool updates
|
|
310
|
-
acpx codex 'review this PR'
|
|
87
|
+
For multi-step work, `acpx flow run` executes TypeScript workflows that combine ACP turns with deterministic actions, decisions, computation, and checkpoints. The package also exports `acpx/runtime` and `acpx/flows` for applications that need session and workflow primitives without shelling out.
|
|
311
88
|
|
|
312
|
-
|
|
313
|
-
acpx --format json codex exec 'review this PR' \
|
|
314
|
-
| jq -r 'select(.type=="tool_call") | [.status, .title] | @tsv'
|
|
89
|
+
Start with the [flows guide](docs/flows.md), then use the [examples](examples/flows/README.md) and [architecture notes](docs/2026-03-25-acpx-flows-architecture.md) for deeper integrations.
|
|
315
90
|
|
|
316
|
-
|
|
317
|
-
acpx --format json --json-strict codex exec 'review this PR'
|
|
91
|
+
## Documentation
|
|
318
92
|
|
|
319
|
-
|
|
320
|
-
|
|
93
|
+
- [CLI reference](docs/CLI.md) — commands, flags, and behavior
|
|
94
|
+
- [Prompting](docs/prompting.md) — arguments, stdin, files, and queueing
|
|
95
|
+
- [Session controls](docs/session-control.md) — cancel, modes, options, and status
|
|
96
|
+
- [Compare agents](docs/compare.md) — run one prompt across multiple agents
|
|
97
|
+
- [ACP coverage](docs/2026-02-19-acp-coverage-roadmap.md) — implemented protocol methods
|
|
98
|
+
- [Vision](VISION.md) — project scope and design principles
|
|
321
99
|
|
|
322
|
-
|
|
323
|
-
acpx --suppress-reads codex exec 'inspect the repo and report tool usage'
|
|
324
|
-
```
|
|
100
|
+
The full documentation is also available at [acpx.sh](https://acpx.sh/).
|
|
325
101
|
|
|
326
|
-
|
|
327
|
-
- `json`: raw ACP NDJSON stream for automation
|
|
328
|
-
- `quiet`: final assistant text on stdout; failed prompts emit one structured `[acpx] error:` line on stderr
|
|
329
|
-
- `--suppress-reads`: replace raw read-file contents with `[read output suppressed]` in `text` and `json` output
|
|
330
|
-
|
|
331
|
-
JSON events include a stable envelope for correlation:
|
|
332
|
-
|
|
333
|
-
```json
|
|
334
|
-
{
|
|
335
|
-
"eventVersion": 1,
|
|
336
|
-
"sessionId": "abc123",
|
|
337
|
-
"requestId": "req-42",
|
|
338
|
-
"seq": 7,
|
|
339
|
-
"stream": "prompt",
|
|
340
|
-
"type": "tool_call"
|
|
341
|
-
}
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
Session-control JSON payloads (`sessions new|ensure`, `status`) always include
|
|
345
|
-
`acpxRecordId` and `acpxSessionId`. They include `agentSessionId` only when the
|
|
346
|
-
adapter exposes a provider-native session ID. The text/quiet session id is the
|
|
347
|
-
local acpx record id; do not assume it can be passed to the native provider CLI
|
|
348
|
-
unless `agentSessionId` is present.
|
|
349
|
-
|
|
350
|
-
## Built-in agents and custom servers
|
|
351
|
-
|
|
352
|
-
Built-ins:
|
|
353
|
-
|
|
354
|
-
| Agent | Adapter | Wraps |
|
|
355
|
-
| ------------ | --------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
356
|
-
| `pi` | [pi-acp](https://github.com/svkozak/pi-acp) | [Pi Coding Agent](https://github.com/mariozechner/pi) |
|
|
357
|
-
| `openclaw` | native (`openclaw acp`) | [OpenClaw ACP bridge](https://github.com/openclaw/openclaw) |
|
|
358
|
-
| `codex` | [codex-acp](https://github.com/agentclientprotocol/codex-acp) | [Codex CLI](https://codex.openai.com) |
|
|
359
|
-
| `claude` | [claude-agent-acp](https://github.com/agentclientprotocol/claude-agent-acp) | [Claude Code](https://claude.ai/code) |
|
|
360
|
-
| `gemini` | native (`gemini --acp`) | [Gemini CLI](https://github.com/google/gemini-cli) |
|
|
361
|
-
| `cursor` | native (`cursor-agent acp`) | [Cursor CLI](https://cursor.com/docs/cli/acp) |
|
|
362
|
-
| `copilot` | native (`copilot --acp --stdio`) | [GitHub Copilot CLI](https://docs.github.com/copilot/how-tos/copilot-chat/use-copilot-chat-in-the-command-line) |
|
|
363
|
-
| `droid` | native (`droid exec --output-format acp`) | [Factory Droid](https://www.factory.ai) |
|
|
364
|
-
| `fast-agent` | `uvx fast-agent-mcp acp` | [fast-agent](https://fast-agent.ai) |
|
|
365
|
-
| `grok-build` | native (`grok agent stdio`) | [Grok Build](https://docs.x.ai/build/overview) |
|
|
366
|
-
| `iflow` | native (`iflow --experimental-acp`) | [iFlow CLI](https://github.com/iflow-ai/iflow-cli) |
|
|
367
|
-
| `kilocode` | `npx -y @kilocode/cli acp` | [Kilocode](https://kilocode.ai) |
|
|
368
|
-
| `kimi` | native (`kimi acp`) | [Kimi CLI](https://github.com/MoonshotAI/kimi-cli) |
|
|
369
|
-
| `kiro` | native (`kiro-cli-chat acp`) | [Kiro CLI](https://kiro.dev) |
|
|
370
|
-
| `mux` | `mux acp` via an ACPX-owned npm range | [Mux](https://mux.coder.com) |
|
|
371
|
-
| `opencode` | `npx -y opencode-ai acp` | [OpenCode](https://opencode.ai) |
|
|
372
|
-
| `pool` | native (`pool acp`) | [Poolside](https://poolside.ai) |
|
|
373
|
-
| `qoder` | native (`qodercli --acp`) | [Qoder CLI](https://docs.qoder.com/cli/acp) |
|
|
374
|
-
| `qwen` | native (`qwen --acp`) | [Qwen Code](https://github.com/QwenLM/qwen-code) |
|
|
375
|
-
| `trae` | native (`traecli acp serve`) | [Trae CLI](https://docs.trae.cn/cli) |
|
|
376
|
-
| `zeroclaw` | native (`zeroclaw acp`) | [ZeroClaw](https://github.com/zeroclaw-labs/zeroclaw) |
|
|
377
|
-
|
|
378
|
-
`factory-droid` and `factorydroid` also resolve to the built-in `droid` adapter.
|
|
379
|
-
|
|
380
|
-
Additional built-in agent docs live in [agents/README.md](agents/README.md).
|
|
381
|
-
|
|
382
|
-
Use `--agent` as an escape hatch for custom ACP servers:
|
|
102
|
+
## Development
|
|
383
103
|
|
|
384
104
|
```bash
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
For repo-local OpenClaw checkouts, override the built-in command in config so `acpx openclaw ...`
|
|
389
|
-
spawns the ACP bridge directly without `pnpm` wrapper noise:
|
|
390
|
-
|
|
391
|
-
```json
|
|
392
|
-
{
|
|
393
|
-
"agents": {
|
|
394
|
-
"openclaw": {
|
|
395
|
-
"command": "env OPENCLAW_HIDE_BANNER=1 OPENCLAW_SUPPRESS_NOTES=1 node scripts/run-node.mjs acp --url ws://127.0.0.1:18789 --token-file ~/.openclaw/gateway.token --session agent:main:main"
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
}
|
|
105
|
+
pnpm install --frozen-lockfile
|
|
106
|
+
pnpm run check
|
|
107
|
+
pnpm run check:docs
|
|
399
108
|
```
|
|
400
109
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
- Prompt commands require an existing saved session record (created via `sessions new` or `sessions ensure`).
|
|
404
|
-
- Prompts route by walking up from `cwd` (or `--cwd`) to the nearest git root (inclusive) and selecting the nearest active session matching `(agent command, dir, optional name)`.
|
|
405
|
-
- If no git root is found, prompts only match an exact `cwd` session (no parent-directory walk).
|
|
406
|
-
- `-s <name>` selects a parallel named session during that directory walk.
|
|
407
|
-
- `sessions new [--name <name>]` creates a fresh session for that scope and soft-closes the prior one.
|
|
408
|
-
- `sessions ensure [--name <name>]` is idempotent: it returns an existing scoped session or creates one when missing.
|
|
409
|
-
- `sessions close [name]` soft-closes the session: queue owner/processes are terminated, record is kept with `closed: true`.
|
|
410
|
-
- `sessions list` uses agent-side ACP `session/list` when available; use
|
|
411
|
-
`--cursor`, `--filter-cwd`, or `--local` for pagination, cwd filtering, or
|
|
412
|
-
saved-record inspection.
|
|
413
|
-
- Auto-resume for cwd scope skips sessions marked closed.
|
|
414
|
-
- Prompt submissions are queue-aware per session. If a prompt is already running, new prompts are queued and drained by the running `acpx` process.
|
|
415
|
-
- Queue owners use an idle TTL (default 300s). `--ttl <seconds>` overrides it; `--ttl 0` keeps owners alive indefinitely.
|
|
416
|
-
- `--no-wait` submits to that queue and returns immediately.
|
|
417
|
-
- `cancel` sends cooperative `session/cancel` to the running queue owner process and returns success when no prompt is running (`nothing to cancel`).
|
|
418
|
-
- `set-mode` and `set` route through queue-owner IPC when active, otherwise they reconnect directly to apply `session/set_mode` and `session/set_config_option`.
|
|
419
|
-
- `<mode>` values for `set-mode` are adapter-defined; unsupported values are rejected by the adapter (commonly `Invalid params`).
|
|
420
|
-
- `exec` is always one-shot and does not reuse saved sessions.
|
|
421
|
-
- Session metadata is stored under `~/.acpx/sessions/`.
|
|
422
|
-
- Each successful prompt appends lightweight turn history previews (`role`, `timestamp`, `textPreview`) to session metadata.
|
|
423
|
-
- `Ctrl+C` during a running turn sends ACP `session/cancel` and waits briefly for `stopReason=cancelled` before force-killing if needed.
|
|
424
|
-
- If a saved session pid is dead on the next prompt, `acpx` respawns the agent, attempts `session/resume` when advertised or `session/load` otherwise, and transparently falls back to `session/new` if reconnecting fails.
|
|
425
|
-
|
|
426
|
-
## Full CLI reference
|
|
427
|
-
|
|
428
|
-
See [docs/CLI.md](docs/CLI.md).
|
|
110
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution and review guidance.
|
|
429
111
|
|
|
430
112
|
## License
|
|
431
113
|
|
|
432
|
-
MIT
|
|
114
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { S as loadPermissionPolicySpec, _ as resolveGlobalFlags, a as hasExplicitPermissionModeFlag, g as resolveAgentInvocation, v as resolveOutputPolicy, 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-Gw2oGjhe.js";
|
|
2
|
+
import { S as loadPermissionPolicySpec, _ as resolveGlobalFlags, a as hasExplicitPermissionModeFlag, g as resolveAgentInvocation, v as resolveOutputPolicy, y as resolvePermissionMode } from "./flags-CM2rAdBo.js";
|
|
3
|
+
import { c as validateFlowDefinition, h as isDefinedFlow, o as FlowRunner } from "./flows-BiRKgCnW.js";
|
|
4
4
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { InvalidArgumentError } from "commander";
|
|
@@ -52,7 +52,8 @@ async function resolveFlowPermissionPolicy(globalFlags) {
|
|
|
52
52
|
try {
|
|
53
53
|
return await loadPermissionPolicySpec(globalFlags.permissionPolicy, globalFlags.cwd);
|
|
54
54
|
} catch (error) {
|
|
55
|
-
|
|
55
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
56
|
+
throw new InvalidArgumentError(`Invalid permission policy: ${message}`);
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
function assertFlowPermissionRequirements(flow, permissionMode, globalFlags) {
|
|
@@ -195,4 +196,4 @@ function printFlowRunResult(result, globalFlags) {
|
|
|
195
196
|
//#endregion
|
|
196
197
|
export { handleFlowRun };
|
|
197
198
|
|
|
198
|
-
//# sourceMappingURL=cli-
|
|
199
|
+
//# sourceMappingURL=cli-DJT3MRRI.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-D52eGvxU.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 fs: globalFlags.fs,\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);\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-DJT3MRRI.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 fs: globalFlags.fs,\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);\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