@peanut996/acp-router 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +350 -0
- package/dist/acp-client.d.ts +179 -0
- package/dist/acp-client.d.ts.map +1 -0
- package/dist/acp-client.js +718 -0
- package/dist/acp-client.js.map +1 -0
- package/dist/agents.d.ts +180 -0
- package/dist/agents.d.ts.map +1 -0
- package/dist/agents.js +430 -0
- package/dist/agents.js.map +1 -0
- package/dist/bin/acp-router-cli.d.ts +3 -0
- package/dist/bin/acp-router-cli.d.ts.map +1 -0
- package/dist/bin/acp-router-cli.js +252 -0
- package/dist/bin/acp-router-cli.js.map +1 -0
- package/dist/bin/acp-router.d.ts +3 -0
- package/dist/bin/acp-router.d.ts.map +1 -0
- package/dist/bin/acp-router.js +7 -0
- package/dist/bin/acp-router.js.map +1 -0
- package/dist/constants.d.ts +44 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +131 -0
- package/dist/constants.js.map +1 -0
- package/dist/jobs.d.ts +133 -0
- package/dist/jobs.d.ts.map +1 -0
- package/dist/jobs.js +716 -0
- package/dist/jobs.js.map +1 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +180 -0
- package/dist/server.js.map +1 -0
- package/dist/storage.d.ts +166 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +506 -0
- package/dist/storage.js.map +1 -0
- package/dist/utils.d.ts +31 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +78 -0
- package/dist/utils.js.map +1 -0
- package/package.json +55 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 peanut996
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# ACP Router
|
|
2
|
+
|
|
3
|
+
Generic MCP server for routing coding tasks to local ACP agents.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@peanut996/acp-router)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://nodejs.org/)
|
|
8
|
+
|
|
9
|
+
ACP Router discovers locally installed coding agents that speak the [Agent Client Protocol](https://agentclientprotocol.com/) (ACP), routes tasks to them inside isolated git worktrees, and tracks jobs, sessions, and event logs. It works with any MCP-compatible client -- Claude Desktop, Cursor, Windsurf, Codex, and others.
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
Run ACP Router directly without installing:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx @peanut996/acp-router
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or install globally and run:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install -g @peanut996/acp-router
|
|
23
|
+
acp-router
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Add ACP Router to any MCP client by pointing it at the `acp-router` command:
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"mcpServers": {
|
|
31
|
+
"acp-router": {
|
|
32
|
+
"command": "npx",
|
|
33
|
+
"args": ["@peanut996/acp-router"]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
See [MCP Client Setup](#mcp-client-setup) below for client-specific configuration examples, or the detailed guide at [docs/MCP_CLIENT_SETUP.md](docs/MCP_CLIENT_SETUP.md).
|
|
40
|
+
|
|
41
|
+
## MCP Client Setup
|
|
42
|
+
|
|
43
|
+
ACP Router is a standard stdio MCP server. Any MCP client that supports `command`-based servers can launch it. Below are config examples for common clients.
|
|
44
|
+
|
|
45
|
+
### Claude Desktop
|
|
46
|
+
|
|
47
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or the equivalent location on your platform:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"mcpServers": {
|
|
52
|
+
"acp-router": {
|
|
53
|
+
"command": "npx",
|
|
54
|
+
"args": ["@peanut996/acp-router"]
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Restart Claude Desktop after editing the config file.
|
|
61
|
+
|
|
62
|
+
### Cursor
|
|
63
|
+
|
|
64
|
+
Add to `.cursor/mcp.json` in your project root (or user-level config):
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"mcpServers": {
|
|
69
|
+
"acp-router": {
|
|
70
|
+
"command": "npx",
|
|
71
|
+
"args": ["@peanut996/acp-router"]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Windsurf
|
|
78
|
+
|
|
79
|
+
Add to your Windsurf MCP server configuration:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"mcpServers": {
|
|
84
|
+
"acp-router": {
|
|
85
|
+
"command": "npx",
|
|
86
|
+
"args": ["@peanut996/acp-router"]
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Codex
|
|
93
|
+
|
|
94
|
+
Add to `.mcp.json` in your project root:
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"mcpServers": {
|
|
99
|
+
"acp-router": {
|
|
100
|
+
"command": "npx",
|
|
101
|
+
"args": ["@peanut996/acp-router"]
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Generic MCP Client
|
|
108
|
+
|
|
109
|
+
Any client that supports stdio MCP servers can use ACP Router with the following parameters:
|
|
110
|
+
|
|
111
|
+
| Field | Value |
|
|
112
|
+
| --- | --- |
|
|
113
|
+
| Command | `npx` |
|
|
114
|
+
| Args | `["acp-router"]` |
|
|
115
|
+
| Transport | stdio |
|
|
116
|
+
|
|
117
|
+
If you installed globally, use `"command": "acp-router"` with an empty args array instead.
|
|
118
|
+
|
|
119
|
+
## CLI
|
|
120
|
+
|
|
121
|
+
ACP Router ships with a command-line interface (`acp-router-cli`) for use outside of an MCP client. Install globally to get the command on your PATH:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
npm install -g @peanut996/acp-router
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Commands
|
|
128
|
+
|
|
129
|
+
| Command | Description |
|
|
130
|
+
| --- | --- |
|
|
131
|
+
| `acp-router-cli run` | Run a coding agent in a worktree (sync, blocks until done) |
|
|
132
|
+
| `acp-router-cli agents` | List discovered agents |
|
|
133
|
+
| `acp-router-cli models <agent>` | Probe an agent for available models |
|
|
134
|
+
| `acp-router-cli jobs` | List jobs |
|
|
135
|
+
| `acp-router-cli job <id>` | Get job details |
|
|
136
|
+
| `acp-router-cli tail <id>` | Tail job events |
|
|
137
|
+
| `acp-router-cli cancel <id>` | Cancel a running job |
|
|
138
|
+
| `acp-router-cli sessions` | List sessions |
|
|
139
|
+
| `acp-router-cli config` | Get or set config |
|
|
140
|
+
|
|
141
|
+
### Examples
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# List available agents
|
|
145
|
+
acp-router-cli agents
|
|
146
|
+
|
|
147
|
+
# Probe models for OpenCode
|
|
148
|
+
acp-router-cli models opencode
|
|
149
|
+
|
|
150
|
+
# Run a job (sync, prints JSON result when done)
|
|
151
|
+
acp-router-cli run --worktree /path/to/repo --prompt "Fix the failing tests" --agent opencode
|
|
152
|
+
|
|
153
|
+
# Run with streaming events to stderr
|
|
154
|
+
acp-router-cli run --worktree /path/to/repo --prompt "Refactor utils" --stream
|
|
155
|
+
|
|
156
|
+
# Run with a specific model and permission profile
|
|
157
|
+
acp-router-cli run --worktree /path/to/repo --prompt "Add tests" --model gpt-5 --permission-profile acceptEdits
|
|
158
|
+
|
|
159
|
+
# Tail events for a running async job
|
|
160
|
+
acp-router-cli tail <job-id>
|
|
161
|
+
|
|
162
|
+
# Cancel a job
|
|
163
|
+
acp-router-cli cancel <job-id> --reason "no longer needed"
|
|
164
|
+
|
|
165
|
+
# Get current config
|
|
166
|
+
acp-router-cli config
|
|
167
|
+
|
|
168
|
+
# Set default agent
|
|
169
|
+
acp-router-cli config --set --defaultAgent opencode
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### `run` options
|
|
173
|
+
|
|
174
|
+
| Flag | Description | Default |
|
|
175
|
+
| --- | --- | --- |
|
|
176
|
+
| `--worktree <path>` | Absolute path to worktree (required) | -- |
|
|
177
|
+
| `--prompt <text>` | Task prompt (required) | -- |
|
|
178
|
+
| `--agent <id>` | Agent id | auto-select |
|
|
179
|
+
| `--mode <mode>` | Execution mode | `implementation` |
|
|
180
|
+
| `--timeout-sec <n>` | Timeout in seconds | `3600` |
|
|
181
|
+
| `--permission-profile <p>` | `plan` / `acceptEdits` / `bypassPermissions` | `bypassPermissions` |
|
|
182
|
+
| `--model <id>` | Model id to use (agent-specific) | agent default |
|
|
183
|
+
| `--collect-diff <bool>` | Collect git diff | `true` |
|
|
184
|
+
| `--session-id <id>` | Continue an existing session | -- |
|
|
185
|
+
| `--stream` | Stream events to stderr while running | off |
|
|
186
|
+
|
|
187
|
+
Run `acp-router-cli <command> --help` for command-specific options.
|
|
188
|
+
|
|
189
|
+
## Tools
|
|
190
|
+
|
|
191
|
+
ACP Router exposes 9 MCP tools:
|
|
192
|
+
|
|
193
|
+
| Tool | Description | Key Params |
|
|
194
|
+
| --- | --- | --- |
|
|
195
|
+
| `discover_agents` | Discover locally installed coding agents and their ACP adapter status. Returns transport, ACP availability, registry metadata, and install hints. | `refresh` (bool, optional), `includeNotInstalled` (bool, optional) |
|
|
196
|
+
| `get_agent_models` | Probe an ACP agent for its available model list. Starts a temporary ACP session, reads config options, and returns model choices. Use this before `run_agent` to discover valid model ids. | `agent` (string, required), `worktree` (string, optional) |
|
|
197
|
+
| `manage_config` | Get or set ACP Router configuration including default agent, per-mode defaults, disabled agents, and safety policy. | `action` ("get" \| "set"), `defaultAgent`, `disabledAgents`, `launchExternalAgents`, `inheritEnvironment`, `allowBypassPermissions`, `defaultPermissionProfile`, `registryEnabled`, `registryUrl`, `registryCacheTtlSec`, `modeDefaults` |
|
|
198
|
+
| `run_agent` | Run a coding agent in an isolated worktree. Requires an absolute worktree path. Supports sync and async execution. ACP-only -- CLI fallback is not supported. | `agent` (string, optional), `worktree` (string, required), `prompt` (string, required), `mode`, `async` (bool), `sessionId`, `timeoutSec`, `permissionProfile`, `model`, `collectDiff`, `launchExternalAgents`, `inheritEnvironment`, `metadata` |
|
|
199
|
+
| `list_jobs` | List ACP Router jobs from the local registry with optional filters. | `status`, `agent`, `worktree`, `limit` |
|
|
200
|
+
| `get_job` | Get an ACP Router job by id. | `jobId` (string, required) |
|
|
201
|
+
| `tail_job_events` | Return newly recorded job events from the JSONL event log for polling-style progress updates. Events are streamed in real-time for long-running async jobs. | `jobId` (string, required), `afterEventIndex`, `limit`, `includeLogTail`, `logTailBytes` |
|
|
202
|
+
| `cancel_job` | Cancel a job and terminate an active child process when the current MCP server owns it. | `jobId` (string, required), `reason` (string, optional) |
|
|
203
|
+
| `manage_sessions` | List, continue, or archive ACP Router sessions. | `action` ("list" \| "continue" \| "archive"), `sessionId`, `prompt`, `agent`, `worktree`, `async`, `includeArchived`, `limit`, `launchExternalAgents`, `inheritEnvironment`, `timeoutSec` |
|
|
204
|
+
|
|
205
|
+
### Permission Profiles
|
|
206
|
+
|
|
207
|
+
Permission profiles control what the spawned agent is allowed to do. They map to the ACP adapter's mode setting and follow Claude Code naming conventions:
|
|
208
|
+
|
|
209
|
+
| Profile | Description |
|
|
210
|
+
| --- | --- |
|
|
211
|
+
| `plan` | Read-only / planning mode. The agent should not modify files. ACP Router also detects `plan_mode_violation` when an agent modifies files despite this profile (guards against upstream ACP adapters that don't enforce read-only). |
|
|
212
|
+
| `acceptEdits` | The agent may edit files within the worktree. |
|
|
213
|
+
| `bypassPermissions` | The agent bypasses all permission checks (default). |
|
|
214
|
+
|
|
215
|
+
Set the default profile via `manage_config` (`defaultPermissionProfile`) or override per-job via `run_agent` (`permissionProfile`). `bypassPermissions` can be disabled globally via `safety.allowBypassPermissions`.
|
|
216
|
+
|
|
217
|
+
### Model Selection
|
|
218
|
+
|
|
219
|
+
Some ACP agents (e.g. OpenCode) support multiple models. Use `get_agent_models` to discover available model ids before launching a job, then pass the chosen id via `run_agent`'s `model` parameter:
|
|
220
|
+
|
|
221
|
+
```text
|
|
222
|
+
get_agent_models with agent "opencode"
|
|
223
|
+
run_agent with agent "opencode", model "gpt-5", worktree "/path", prompt "..."
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
This is useful when an agent's default model is unavailable (e.g. insufficient balance) and you want to switch to an alternative.
|
|
227
|
+
|
|
228
|
+
## ACP-Only Mode
|
|
229
|
+
|
|
230
|
+
ACP Router runs agents exclusively through the Agent Client Protocol (ACP). The previous CLI fallback adapters have been removed.
|
|
231
|
+
|
|
232
|
+
### How it works
|
|
233
|
+
|
|
234
|
+
1. When you call `run_agent`, ACP Router checks whether the selected agent has an available ACP adapter.
|
|
235
|
+
2. If the ACP executable is on `PATH`, it launches directly.
|
|
236
|
+
3. If the ACP executable is not on `PATH` but the ACP Registry lists an npx distribution for that agent, ACP Router automatically launches it via `npx --yes <package>`.
|
|
237
|
+
4. If no ACP adapter is available at all, the job hard-fails with an `acp_required` error and an install hint telling you how to install the adapter.
|
|
238
|
+
|
|
239
|
+
### When ACP is not available
|
|
240
|
+
|
|
241
|
+
| Scenario | Behavior |
|
|
242
|
+
| --- | --- |
|
|
243
|
+
| ACP executable on `PATH` | Launches directly |
|
|
244
|
+
| ACP executable not on `PATH`, registry has npx distribution | Auto-launches via `npx --yes <package>` |
|
|
245
|
+
| ACP executable not on `PATH`, no npx distribution | Job fails with `acp_required` error and install hint |
|
|
246
|
+
| Agent has no ACP adapter at all (e.g. Cursor Agent) | Job fails with `acp_required` error |
|
|
247
|
+
|
|
248
|
+
## Supported Agents
|
|
249
|
+
|
|
250
|
+
| Agent | ACP Support | Launch Method | Notes |
|
|
251
|
+
| --- | --- | --- | --- |
|
|
252
|
+
| OpenCode | Native ACP stdio | `opencode acp --cwd <worktree>` | Built-in ACP, no extra install needed |
|
|
253
|
+
| Claude Code | ACP via `claude-agent-acp` | `claude-agent-acp` or `npx --yes @anthropic-ai/claude-agent-acp` | ACP adapter preferred; npx fallback when not installed |
|
|
254
|
+
| Codex CLI | ACP via `codex-acp` | `codex-acp` or `npx --yes codex-acp` | ACP adapter preferred; npx fallback when not installed |
|
|
255
|
+
| Cursor Agent | No ACP adapter | Hard-fail | CLI fallback removed; install a Cursor ACP adapter or use a different agent |
|
|
256
|
+
|
|
257
|
+
## Configuration
|
|
258
|
+
|
|
259
|
+
ACP Router stores its configuration in `~/.acp-router/config.json`.
|
|
260
|
+
|
|
261
|
+
### Config fields
|
|
262
|
+
|
|
263
|
+
| Field | Type | Default | Description |
|
|
264
|
+
| --- | --- | --- | --- |
|
|
265
|
+
| `defaultAgent` | string \| null | `null` | Default agent id to use when none is explicitly requested |
|
|
266
|
+
| `modeDefaults` | object | `{}` | Per-mode default agent id mapping (e.g. `{ "planning": "opencode" }`) |
|
|
267
|
+
| `disabledAgents` | string[] | `[]` | Agent ids to exclude from automatic selection |
|
|
268
|
+
| `allowCurrentDirectory` | boolean | `false` | Allow dispatching agents in the current working directory |
|
|
269
|
+
| `registryEnabled` | boolean | `true` | Enable ACP registry lookups for agent discovery |
|
|
270
|
+
| `registryUrl` | string | `https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json` | ACP registry URL override |
|
|
271
|
+
| `registryCacheTtlSec` | number | `86400` | ACP registry cache TTL in seconds (24 hours) |
|
|
272
|
+
| `safety.launchExternalAgents` | boolean | `true` | Allow launching external agent processes |
|
|
273
|
+
| `safety.inheritEnvironment` | boolean | `true` | Inherit parent process environment for child agents |
|
|
274
|
+
| `safety.allowBypassPermissions` | boolean | `true` | Allow `bypassPermissions` permission profile |
|
|
275
|
+
| `safety.defaultPermissionProfile` | string | `"bypassPermissions"` | Default permission profile for new jobs (`plan` / `acceptEdits` / `bypassPermissions`) |
|
|
276
|
+
| `safety.requireAbsoluteWorktree` | boolean | `true` | Require an absolute worktree path |
|
|
277
|
+
|
|
278
|
+
Read or update config through the `manage_config` tool:
|
|
279
|
+
|
|
280
|
+
```text
|
|
281
|
+
manage_config with action "get"
|
|
282
|
+
manage_config with action "set", defaultAgent "opencode"
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Data Directory and Paths
|
|
286
|
+
|
|
287
|
+
ACP Router stores all data under `~/.acp-router/`:
|
|
288
|
+
|
|
289
|
+
| Path | Description |
|
|
290
|
+
| --- | --- |
|
|
291
|
+
| `~/.acp-router/config.json` | Configuration file |
|
|
292
|
+
| `~/.acp-router/registry.json` | Job and session registry |
|
|
293
|
+
| `~/.acp-router/logs/` | Per-job JSONL event logs |
|
|
294
|
+
| `~/.acp-router/acp-registry-cache.json` | ACP Registry metadata cache |
|
|
295
|
+
|
|
296
|
+
Override the data directory by setting the `ACP_ROUTER_DATA_DIR` environment variable:
|
|
297
|
+
|
|
298
|
+
```json
|
|
299
|
+
{
|
|
300
|
+
"mcpServers": {
|
|
301
|
+
"acp-router": {
|
|
302
|
+
"command": "npx",
|
|
303
|
+
"args": ["@peanut996/acp-router"],
|
|
304
|
+
"env": {
|
|
305
|
+
"ACP_ROUTER_DATA_DIR": "/custom/path/to/data"
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## Recursion Guard
|
|
313
|
+
|
|
314
|
+
ACP Router prevents infinite agent dispatch loops using the `ACP_ROUTER_DEPTH` environment variable.
|
|
315
|
+
|
|
316
|
+
- Each time ACP Router launches a child agent, it increments `ACP_ROUTER_DEPTH` by 1 in the child process environment.
|
|
317
|
+
- The maximum recursion depth is **3**.
|
|
318
|
+
- When `run_agent` is called and `ACP_ROUTER_DEPTH` is already at or above 3, the job immediately fails with a `recursion_limit` error.
|
|
319
|
+
|
|
320
|
+
This guards against scenarios where an ACP agent itself calls ACP Router to dispatch another agent, creating a loop. The depth counter propagates through the process tree so nested dispatches are tracked across the entire chain.
|
|
321
|
+
|
|
322
|
+
## Plan Mode Violation Detection
|
|
323
|
+
|
|
324
|
+
When `permissionProfile` is set to `plan`, the agent is expected to operate in read-only mode. However, some upstream ACP adapters do not enforce read-only mode. ACP Router detects this by checking for file changes in the worktree after a `plan` job completes.
|
|
325
|
+
|
|
326
|
+
If files were modified despite the `plan` profile, the job result includes a `plan_mode_violation` warning listing the changed files. This helps identify adapter bugs and prevents unintended modifications during planning.
|
|
327
|
+
|
|
328
|
+
## Development
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
git clone https://github.com/peanut996/acp-router.git
|
|
332
|
+
cd acp-router
|
|
333
|
+
npm install
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Validation
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
npm run check
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Start the server locally
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
npm start
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
## License
|
|
349
|
+
|
|
350
|
+
MIT
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { type ChildProcess } from "node:child_process";
|
|
2
|
+
import type { EnrichedAgent, WorktreeState } from "./agents.js";
|
|
3
|
+
type PermissionProfile = "bypassPermissions" | "acceptEdits" | "plan";
|
|
4
|
+
interface AcpLogEvent {
|
|
5
|
+
type: string;
|
|
6
|
+
timestamp: string;
|
|
7
|
+
message: string;
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
}
|
|
10
|
+
interface AcpClientConstructorArgs {
|
|
11
|
+
command: string;
|
|
12
|
+
args: string[];
|
|
13
|
+
cwd: string;
|
|
14
|
+
timeoutMs: number;
|
|
15
|
+
env?: NodeJS.ProcessEnv;
|
|
16
|
+
permissionProfile?: PermissionProfile;
|
|
17
|
+
onEvent?: (event: AcpLogEvent) => void;
|
|
18
|
+
onProcessStart?: (child: ChildProcess) => void | Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
interface PendingRequest {
|
|
21
|
+
method: string;
|
|
22
|
+
resolve: (value: any) => void;
|
|
23
|
+
reject: (error: Error) => void;
|
|
24
|
+
timer: NodeJS.Timeout;
|
|
25
|
+
}
|
|
26
|
+
interface AcpJsonRpcRequest {
|
|
27
|
+
jsonrpc: "2.0";
|
|
28
|
+
id: number;
|
|
29
|
+
method: string;
|
|
30
|
+
params?: any;
|
|
31
|
+
}
|
|
32
|
+
interface AcpJsonRpcResponse {
|
|
33
|
+
jsonrpc: "2.0";
|
|
34
|
+
id: number;
|
|
35
|
+
result?: any;
|
|
36
|
+
error?: {
|
|
37
|
+
code: number;
|
|
38
|
+
message: string;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
interface AcpSessionUpdate {
|
|
42
|
+
sessionUpdate?: string;
|
|
43
|
+
content?: {
|
|
44
|
+
text?: string;
|
|
45
|
+
};
|
|
46
|
+
title?: string;
|
|
47
|
+
status?: string;
|
|
48
|
+
toolCallId?: string;
|
|
49
|
+
availableCommands?: any[];
|
|
50
|
+
}
|
|
51
|
+
interface AcpConfigOption {
|
|
52
|
+
id: string | null;
|
|
53
|
+
title: string | null;
|
|
54
|
+
category: string | null;
|
|
55
|
+
type: string | null;
|
|
56
|
+
description: string | null;
|
|
57
|
+
currentValue: string | number | boolean | null;
|
|
58
|
+
options: AcpConfigChoice[];
|
|
59
|
+
}
|
|
60
|
+
interface AcpConfigChoice {
|
|
61
|
+
value: string;
|
|
62
|
+
label: string;
|
|
63
|
+
description: string | null;
|
|
64
|
+
}
|
|
65
|
+
interface AcpModelOption {
|
|
66
|
+
configId: string | null;
|
|
67
|
+
value: string;
|
|
68
|
+
label: string;
|
|
69
|
+
description: string | null;
|
|
70
|
+
}
|
|
71
|
+
interface SessionUpdateEvent {
|
|
72
|
+
type: string;
|
|
73
|
+
timestamp: string;
|
|
74
|
+
message: string;
|
|
75
|
+
params: any;
|
|
76
|
+
}
|
|
77
|
+
interface InitializeSummary {
|
|
78
|
+
protocolVersion: any;
|
|
79
|
+
agentInfo: any;
|
|
80
|
+
agentCapabilities: {
|
|
81
|
+
loadSession: boolean;
|
|
82
|
+
sessionCapabilities: string[];
|
|
83
|
+
};
|
|
84
|
+
authMethods: {
|
|
85
|
+
id: any;
|
|
86
|
+
name: any;
|
|
87
|
+
}[];
|
|
88
|
+
}
|
|
89
|
+
interface RunAcpStdioJobArgs {
|
|
90
|
+
args: {
|
|
91
|
+
worktree: string;
|
|
92
|
+
prompt: string;
|
|
93
|
+
model?: string | null;
|
|
94
|
+
collectDiff?: boolean;
|
|
95
|
+
};
|
|
96
|
+
job: {
|
|
97
|
+
jobId: string;
|
|
98
|
+
sessionId: string;
|
|
99
|
+
logPath: string;
|
|
100
|
+
permissionProfile?: PermissionProfile;
|
|
101
|
+
worktreeState: WorktreeState;
|
|
102
|
+
};
|
|
103
|
+
session: {
|
|
104
|
+
providerSessionId: string | null;
|
|
105
|
+
};
|
|
106
|
+
selectedAgent: EnrichedAgent;
|
|
107
|
+
timeoutSec: number;
|
|
108
|
+
agentEnv?: NodeJS.ProcessEnv;
|
|
109
|
+
controller?: any;
|
|
110
|
+
}
|
|
111
|
+
interface ProbeAgentModelsArgs {
|
|
112
|
+
selectedAgent: EnrichedAgent;
|
|
113
|
+
worktree?: string;
|
|
114
|
+
env?: NodeJS.ProcessEnv;
|
|
115
|
+
timeoutMs?: number;
|
|
116
|
+
}
|
|
117
|
+
interface ProbeAgentModelsResult {
|
|
118
|
+
agentId: string;
|
|
119
|
+
models: AcpModelOption[];
|
|
120
|
+
configOptions: AcpConfigOption[];
|
|
121
|
+
}
|
|
122
|
+
declare class AcpStdioClient {
|
|
123
|
+
command: string;
|
|
124
|
+
args: string[];
|
|
125
|
+
cwd: string;
|
|
126
|
+
timeoutMs: number;
|
|
127
|
+
env: NodeJS.ProcessEnv;
|
|
128
|
+
permissionProfile: PermissionProfile;
|
|
129
|
+
onEvent: (event: AcpLogEvent) => void;
|
|
130
|
+
onProcessStart: ((child: ChildProcess) => void | Promise<void>) | undefined;
|
|
131
|
+
nextId: number;
|
|
132
|
+
pending: Map<number, PendingRequest>;
|
|
133
|
+
stdoutBuffer: string;
|
|
134
|
+
logEvents: AcpLogEvent[];
|
|
135
|
+
child: ChildProcess | null;
|
|
136
|
+
startError: Error | null;
|
|
137
|
+
constructor({ command, args, cwd, timeoutMs, env, permissionProfile, onEvent, onProcessStart }: AcpClientConstructorArgs);
|
|
138
|
+
start(): Promise<void>;
|
|
139
|
+
request(method: string, params?: any): Promise<any>;
|
|
140
|
+
respond(id: number, result: any): void;
|
|
141
|
+
respondError(id: number, code: number, message: string): void;
|
|
142
|
+
write(payload: any): void;
|
|
143
|
+
handleStdout(chunk: string): void;
|
|
144
|
+
handleMessageLine(line: string): void;
|
|
145
|
+
handleClientRequest(message: any): void;
|
|
146
|
+
resolvePermissionOutcome(params: any): "approved" | "cancelled";
|
|
147
|
+
handleNotification(message: any): void;
|
|
148
|
+
handleStderr(chunk: string): void;
|
|
149
|
+
drainLogEvents(): AcpLogEvent[];
|
|
150
|
+
rejectPending(error: Error): void;
|
|
151
|
+
dispose(): void;
|
|
152
|
+
}
|
|
153
|
+
declare function normalizeAcpNotification(message: any): SessionUpdateEvent;
|
|
154
|
+
declare function describeSessionUpdate(update: AcpSessionUpdate): string;
|
|
155
|
+
declare function summarizeInitializeResult(result: any): InitializeSummary;
|
|
156
|
+
declare function summarizeAcpConfigOptions(configOptions: any): AcpConfigOption[];
|
|
157
|
+
declare function summarizeConfigChoices(choices: any): AcpConfigChoice[];
|
|
158
|
+
declare function summarizeConfigValue(value: any): string | number | boolean | null;
|
|
159
|
+
declare function extractModelOptions(configOptions: AcpConfigOption[]): AcpModelOption[];
|
|
160
|
+
declare function buildDispatchPrompt(prompt: string): string;
|
|
161
|
+
declare function extractAgentText(events: AcpLogEvent[]): string;
|
|
162
|
+
declare function extractAgentErrors(events: AcpLogEvent[]): string[];
|
|
163
|
+
declare function collectDiagnosticStrings(value: any, depth?: number): string[];
|
|
164
|
+
declare function buildFailureReason(adapterLabel: string, error: Error & {
|
|
165
|
+
code?: string;
|
|
166
|
+
}, agentErrors: string[]): string;
|
|
167
|
+
declare function diffChangedFiles(beforeState: WorktreeState | null, afterState: WorktreeState | {
|
|
168
|
+
skipped: boolean;
|
|
169
|
+
reason: string;
|
|
170
|
+
}): string[];
|
|
171
|
+
declare function runAcpStdioJob({ args, job, session, selectedAgent, timeoutSec, agentEnv, controller }: RunAcpStdioJobArgs): Promise<{
|
|
172
|
+
events: AcpLogEvent[];
|
|
173
|
+
sessionPatch: any;
|
|
174
|
+
jobPatch: any;
|
|
175
|
+
}>;
|
|
176
|
+
declare function probeAgentModels({ selectedAgent, worktree, env, timeoutMs }: ProbeAgentModelsArgs): Promise<ProbeAgentModelsResult>;
|
|
177
|
+
export { AcpStdioClient, normalizeAcpNotification, describeSessionUpdate, summarizeInitializeResult, summarizeAcpConfigOptions, summarizeConfigChoices, summarizeConfigValue, extractModelOptions, buildDispatchPrompt, extractAgentText, extractAgentErrors, collectDiagnosticStrings, buildFailureReason, diffChangedFiles, runAcpStdioJob, probeAgentModels };
|
|
178
|
+
export type { PermissionProfile, AcpLogEvent, AcpClientConstructorArgs, PendingRequest, AcpJsonRpcRequest, AcpJsonRpcResponse, AcpSessionUpdate, AcpConfigOption, AcpConfigChoice, AcpModelOption, SessionUpdateEvent, InitializeSummary, RunAcpStdioJobArgs, ProbeAgentModelsArgs, ProbeAgentModelsResult };
|
|
179
|
+
//# sourceMappingURL=acp-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acp-client.d.ts","sourceRoot":"","sources":["../src/acp-client.ts"],"names":[],"mappings":"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"}
|