zcode-acp-server 0.18.2 → 0.19.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/dist/handlers/sandbox-allow.d.ts +67 -5
- package/dist/handlers/sandbox-allow.d.ts.map +1 -1
- package/dist/handlers/sandbox-allow.js +136 -29
- package/dist/handlers/sandbox-allow.js.map +1 -1
- package/dist/handlers/session.d.ts.map +1 -1
- package/dist/handlers/session.js +28 -8
- package/dist/handlers/session.js.map +1 -1
- package/dist/i18n.d.ts +3 -2
- package/dist/i18n.d.ts.map +1 -1
- package/dist/i18n.js +4 -4
- package/dist/i18n.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -4
- package/dist/index.js.map +1 -1
- package/dist/remote/config.d.ts +18 -0
- package/dist/remote/config.d.ts.map +1 -1
- package/dist/remote/config.js +13 -1
- package/dist/remote/config.js.map +1 -1
- package/dist/remote/endpoint.d.ts.map +1 -1
- package/dist/remote/endpoint.js +4 -0
- package/dist/remote/endpoint.js.map +1 -1
- package/dist/remote/hub-server.d.ts +49 -3
- package/dist/remote/hub-server.d.ts.map +1 -1
- package/dist/remote/hub-server.js +381 -44
- package/dist/remote/hub-server.js.map +1 -1
- package/dist/remote/session-list-endpoint.d.ts +51 -0
- package/dist/remote/session-list-endpoint.d.ts.map +1 -0
- package/dist/remote/session-list-endpoint.js +153 -0
- package/dist/remote/session-list-endpoint.js.map +1 -0
- package/dist/server.d.ts +15 -3
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +14 -2
- package/dist/server.js.map +1 -1
- package/docs/REMOTE-CLIENTS.md +88 -26
- package/docs/REMOTE.md +30 -8
- package/docs/SANDBOX.md +3 -1
- package/package.json +1 -1
package/docs/REMOTE-CLIENTS.md
CHANGED
|
@@ -46,17 +46,18 @@ ACP editor ────── stdio ──────────┘
|
|
|
46
46
|
|
|
47
47
|
## Discovery API
|
|
48
48
|
|
|
49
|
-
| Endpoint
|
|
50
|
-
|
|
|
51
|
-
| `GET /api/health`
|
|
52
|
-
| `GET /api/instances`
|
|
53
|
-
| `GET /api/instances/{id}/status`
|
|
54
|
-
| `POST /api/instances/{id}/sessions/{sessionId}/close`
|
|
55
|
-
| `POST /api/instances/{id}/sessions/{sessionId}/rename` | required | Rename a session — see [Renaming a session](#renaming-a-session).
|
|
56
|
-
| `GET /api/quota`
|
|
57
|
-
| `POST /api/upgrade`
|
|
58
|
-
| `GET /api/projects`
|
|
59
|
-
| `
|
|
49
|
+
| Endpoint | Auth | Purpose |
|
|
50
|
+
| ------------------------------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------- |
|
|
51
|
+
| `GET /api/health` | none | Liveness probe; `200` body `ok`. |
|
|
52
|
+
| `GET /api/instances` | required | Registered bridge instances. Add `?probe=1` to verify first. |
|
|
53
|
+
| `GET /api/instances/{id}/status` | required | Real-time per-session running status of one bridge. |
|
|
54
|
+
| `POST /api/instances/{id}/sessions/{sessionId}/close` | required | Retire a session from remote discovery — see [Closing a session](#closing-a-session). |
|
|
55
|
+
| `POST /api/instances/{id}/sessions/{sessionId}/rename` | required | Rename a session — see [Renaming a session](#renaming-a-session). |
|
|
56
|
+
| `GET /api/quota` | required | Account-level usage stats — same payload as `account/usage_stats`, no ACP connection needed. |
|
|
57
|
+
| `POST /api/upgrade` | required | Trigger the hub's own staleness check — see [Hub self-upgrade](#hub-self-upgrade). |
|
|
58
|
+
| `GET /api/projects` | required | Known-project list (remote session-create whitelist) — see below. |
|
|
59
|
+
| `GET /api/projects/sessions?workspacePath=` | required | A project's full session store incl. closed ones — see [Resuming a closed session](#resuming-a-closed-session). |
|
|
60
|
+
| `POST /api/instances {workspacePath}` | required | Create (or reuse) a headless serve bridge for one known project — see below. |
|
|
60
61
|
|
|
61
62
|
HTTP auth: `Authorization: Bearer <token>` or `?token=<token>`.
|
|
62
63
|
|
|
@@ -149,7 +150,8 @@ GET {hub}/api/projects
|
|
|
149
150
|
POST {hub}/api/instances body {"workspacePath":"/Users/me/proj"}
|
|
150
151
|
→ 200 {"id":"47073","reused":false}
|
|
151
152
|
→ 403 "unknown project" (path not on the known-project list)
|
|
152
|
-
→ 502 (spawn failed / bridge died during startup / never registered
|
|
153
|
+
→ 502 (spawn failed / bridge died during startup / never registered;
|
|
154
|
+
~10s headless, ~20s when a terminal window is opened)
|
|
153
155
|
```
|
|
154
156
|
|
|
155
157
|
- `GET /api/projects` aggregates the App's tasks index: every workspace that
|
|
@@ -159,20 +161,80 @@ POST {hub}/api/instances body {"workspacePath":"/Users/me/proj"}
|
|
|
159
161
|
bound, not a security boundary: a token holder can already run any
|
|
160
162
|
editor-bridge session in an arbitrary cwd; the trust boundary is the
|
|
161
163
|
token itself.
|
|
162
|
-
- On create the hub
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
`
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
164
|
+
- On create the hub incubates a VISIBLE interactive REPL in the machine's
|
|
165
|
+
terminal (ADR-0016, macOS): the project's owner gets a real local CLI
|
|
166
|
+
window, and its bridge registers with the hub like any serve instance (it
|
|
167
|
+
appears in `/api/instances` with `origin:"serve"` — allow up to ~20s for
|
|
168
|
+
the GUI round-trip). Headless machines, SSH sessions, or
|
|
169
|
+
`ZCODE_ACP_HUB_TERMINAL=0` fall back to the detached `zcode-acp serve`
|
|
170
|
+
bridge of the original design. Connect with the normal
|
|
171
|
+
`WS /acp?instance=<id>` and drive it like any instance; the new
|
|
172
|
+
conversation's cwd is the project directory regardless of what
|
|
173
|
+
`session/new` sends (session roots are pinned in both surfaces).
|
|
174
|
+
- **Which terminal opens** (nothing is auto-detected — the hub is a
|
|
175
|
+
background process and macOS has no default-terminal setting):
|
|
176
|
+
`ZCODE_ACP_HUB_TERMINAL_COMMAND` (a shell command; `{script}` is replaced
|
|
177
|
+
by the quoted script path) wins over `ZCODE_ACP_HUB_TERMINAL_APP`, which
|
|
178
|
+
is matched against built-in launch recipes: Terminal and iTerm run the
|
|
179
|
+
script via `open -a` (both execute `.command`); WezTerm, kitty, Alacritty,
|
|
180
|
+
and Ghostty are driven by their own CLI (`open -na <app> --args … -e …`);
|
|
181
|
+
any other name passes through to `open -a` as-is. Default: Terminal.app.
|
|
182
|
+
Warp cannot execute scripts or commands programmatically at all
|
|
183
|
+
(warpdotdev/warp#1917, #3959, #9083) — naming it warns, and the flow
|
|
184
|
+
degrades to the headless bridge after the register timeout.
|
|
185
|
+
- A live serve-origin instance for the same workspace is reused
|
|
186
|
+
(`reused:true`) instead of spawning a second one; concurrent creates join
|
|
187
|
+
the same in-flight spawn instead of racing a duplicate.
|
|
188
|
+
- Lifetime depends on the surface: a terminal-REPL instance lives while its
|
|
189
|
+
window lives (the owner closing it retires the bridge — re-create on
|
|
190
|
+
demand); the headless fallback exists for remote interest only and exits
|
|
191
|
+
~10 minutes after the last client detaches AND the last running turn
|
|
192
|
+
finishes. Treat any vanished instance like a dead bridge.
|
|
193
|
+
|
|
194
|
+
## Resuming a closed session
|
|
195
|
+
|
|
196
|
+
Discovery lists only currently-running conversations. To find and reopen a
|
|
197
|
+
PREVIOUS one — including conversations no bridge currently holds — use the
|
|
198
|
+
per-project history listing (ADR-0015):
|
|
199
|
+
|
|
200
|
+
```text
|
|
201
|
+
GET {hub}/api/projects/sessions?workspacePath=/Users/me/proj
|
|
202
|
+
→ 200 {"workspacePath":"/Users/me/proj",
|
|
203
|
+
"instance":{"id":"47073","origin":"serve"},
|
|
204
|
+
"sessions":[
|
|
205
|
+
{"sessionId":"sess_9f2…","title":"Fix login bug",
|
|
206
|
+
"cwd":"/Users/me/proj","updatedAt":"2026-09-01T10:00:00.000Z",
|
|
207
|
+
"live":false,"running":false}, …],
|
|
208
|
+
"nextCursor":{"before":1723800000000,"beforeId":"sess_9f2…"}}
|
|
209
|
+
→ 400 "workspacePath required" / "invalid limit/before …"
|
|
210
|
+
→ 403 "unknown project" (path not on the known-project list)
|
|
211
|
+
→ 502 (spawn failed / bridge unreachable / broken list)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
- The listing is the project's backend session store — closed conversations
|
|
215
|
+
included. `live` marks conversations currently advertised by a bridge (the
|
|
216
|
+
same membership as discovery); `running` marks an in-flight turn. Titles
|
|
217
|
+
are the store's authoritative ones.
|
|
218
|
+
- **Pagination** (projects can hold dozens of sessions): rows come
|
|
219
|
+
newest-first (`updatedAt` descending). `?limit=<n>` sets the page size
|
|
220
|
+
(default 20, max 200); the previous response's `nextCursor` splits into
|
|
221
|
+
`?before=<ms-epoch>&beforeId=<sessionId>` for the next older page — the
|
|
222
|
+
composite cursor names the exact last row, so timestamps tied across a
|
|
223
|
+
page boundary are never skipped or repeated. `nextCursor: null` means
|
|
224
|
+
there are no older sessions. Order is total (id tiebreak), so
|
|
225
|
+
paging never repeats or skips rows.
|
|
226
|
+
- The first listing of a cold project incubates its serve bridge (the same
|
|
227
|
+
machinery as remote session-create; budget ~12s) — later listings and the
|
|
228
|
+
follow-up load reuse it.
|
|
229
|
+
- Resume with the existing flow: `POST /api/instances` (answers
|
|
230
|
+
`reused:true` with the listing's instance), attach
|
|
231
|
+
`WS /acp?instance=<id>`, then
|
|
232
|
+
`session/load {"sessionId":"<the listed id>"}` — history replays and the
|
|
233
|
+
conversation continues with `session/prompt`.
|
|
234
|
+
- `sessionId` here is the backend store id (`sess_…`), which `session/load`
|
|
235
|
+
accepts as-is (pass-through resume). The same conversation may also appear
|
|
236
|
+
in discovery under a different (ACP) id — treat discovery as the
|
|
237
|
+
live-attention surface and this listing as the browse/resume surface.
|
|
176
238
|
|
|
177
239
|
## Connecting
|
|
178
240
|
|
package/docs/REMOTE.md
CHANGED
|
@@ -68,14 +68,36 @@ ran a session (system temp trees, `~/.zcode` itself, and vanished
|
|
|
68
68
|
directories filtered out), newest activity first. The list gates the POST —
|
|
69
69
|
paths outside it get 403 (a convenience bound, not a security boundary: a
|
|
70
70
|
token holder can already drive an editor-bridge session in any cwd; the
|
|
71
|
-
trust boundary is the token). On create the hub
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
71
|
+
trust boundary is the token). On create the hub incubates a VISIBLE
|
|
72
|
+
interactive REPL in the machine's terminal (ADR-0016, macOS; headless/SSH or
|
|
73
|
+
`ZCODE_ACP_HUB_TERMINAL=0` falls back to the detached headless
|
|
74
|
+
`zcode-acp serve`); its bridge registers back within seconds (budget ~20s)
|
|
75
|
+
and is reachable like any other instance. The hub itself is a background
|
|
76
|
+
process with no terminal, so nothing is auto-detected: the target terminal
|
|
77
|
+
resolves as `ZCODE_ACP_HUB_TERMINAL_COMMAND` → `ZCODE_ACP_HUB_TERMINAL_APP`
|
|
78
|
+
(built-in launch recipes for Terminal, iTerm, WezTerm, kitty, Alacritty,
|
|
79
|
+
Ghostty; other names pass through to `open -a`) → plain Terminal.app. Warp
|
|
80
|
+
cannot execute scripts or commands programmatically (warpdotdev/warp#1917,
|
|
81
|
+
#3959) and is deliberately unsupported — it degrades to the headless bridge.
|
|
82
|
+
A live serve-origin instance for
|
|
83
|
+
the same workspace is reused instead of re-spawned (`reused:true`). A
|
|
84
|
+
terminal-REPL instance lives while its window lives; the headless fallback
|
|
85
|
+
exits ~10 minutes after the last client detaches and the last turn
|
|
86
|
+
finishes. Session roots are pinned to the project cwd in both surfaces
|
|
87
|
+
regardless of what a client sends.
|
|
88
|
+
|
|
89
|
+
**Remote session-resume** (ADR-0015). Remote clients can also reopen a
|
|
90
|
+
PREVIOUS conversation of a project — including closed ones no bridge
|
|
91
|
+
currently advertises (discovery lists only running conversations):
|
|
92
|
+
|
|
93
|
+
```text
|
|
94
|
+
GET /api/projects/sessions?workspacePath=… → {workspacePath, instance, sessions}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The listing is the project's full backend session store; the hub incubates
|
|
98
|
+
the project's serve bridge on first listing and reuses it after. Resume is
|
|
99
|
+
the normal attach flow with `session/load` on a listed backend id. See
|
|
100
|
+
`docs/REMOTE-CLIENTS.md` ("Resuming a closed session") for the client contract.
|
|
79
101
|
|
|
80
102
|
`sessions` lists the project's **currently running** conversations (live
|
|
81
103
|
editor tabs and remote attachments) under the same ACP session ids the
|
package/docs/SANDBOX.md
CHANGED
|
@@ -42,7 +42,9 @@ that file — the sandbox denies
|
|
|
42
42
|
writes to `.zcode/acp/` inside the workspace while the bridge (outside the
|
|
43
43
|
sandbox) writes it on your behalf. After an allow, the backend restarts with
|
|
44
44
|
the widened profile (a few seconds; the bridge auto-continues the interrupted
|
|
45
|
-
task).
|
|
45
|
+
task). Approvals are batched for a short window, so several pending popups
|
|
46
|
+
granted in a row share ONE restart instead of each killing the others. Set
|
|
47
|
+
`"strictGit": true` in the config to also put `.git` behind the
|
|
46
48
|
popup.
|
|
47
49
|
|
|
48
50
|
Ordinary filesystem permission failures (`Permission denied`, EACCES — a
|