zcode-acp-server 0.14.3 → 0.17.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 +109 -9
- package/README.zh-CN.md +91 -9
- package/dist/backend/index.d.ts +1 -0
- package/dist/backend/index.d.ts.map +1 -1
- package/dist/backend/index.js +1 -0
- package/dist/backend/index.js.map +1 -1
- package/dist/backend/sandbox.d.ts +92 -23
- package/dist/backend/sandbox.d.ts.map +1 -1
- package/dist/backend/sandbox.js +265 -70
- package/dist/backend/sandbox.js.map +1 -1
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +10 -1
- package/dist/cli.js.map +1 -1
- package/dist/config/auto-compact.d.ts.map +1 -1
- package/dist/config/auto-compact.js +6 -4
- package/dist/config/auto-compact.js.map +1 -1
- package/dist/config/mcp-discovery.d.ts.map +1 -1
- package/dist/config/mcp-discovery.js +7 -5
- package/dist/config/mcp-discovery.js.map +1 -1
- package/dist/handlers/background-tasks.d.ts.map +1 -1
- package/dist/handlers/background-tasks.js +2 -2
- package/dist/handlers/background-tasks.js.map +1 -1
- package/dist/handlers/dispatch.d.ts.map +1 -1
- package/dist/handlers/dispatch.js +4 -4
- package/dist/handlers/dispatch.js.map +1 -1
- package/dist/handlers/replay.d.ts.map +1 -1
- package/dist/handlers/replay.js +11 -5
- package/dist/handlers/replay.js.map +1 -1
- package/dist/handlers/sandbox-allow.d.ts +71 -0
- package/dist/handlers/sandbox-allow.d.ts.map +1 -0
- package/dist/handlers/sandbox-allow.js +299 -0
- package/dist/handlers/sandbox-allow.js.map +1 -0
- package/dist/handlers/server-requests.d.ts.map +1 -1
- package/dist/handlers/server-requests.js +7 -5
- package/dist/handlers/server-requests.js.map +1 -1
- package/dist/handlers/session.d.ts +24 -1
- package/dist/handlers/session.d.ts.map +1 -1
- package/dist/handlers/session.js +231 -24
- package/dist/handlers/session.js.map +1 -1
- package/dist/handlers/slash.d.ts.map +1 -1
- package/dist/handlers/slash.js +15 -13
- package/dist/handlers/slash.js.map +1 -1
- package/dist/i18n.d.ts +113 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/i18n.js +224 -0
- package/dist/i18n.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +114 -15
- package/dist/index.js.map +1 -1
- package/dist/interaction/adapter.d.ts.map +1 -1
- package/dist/interaction/adapter.js +10 -7
- package/dist/interaction/adapter.js.map +1 -1
- package/dist/remote/config.d.ts +7 -0
- package/dist/remote/config.d.ts.map +1 -1
- package/dist/remote/config.js +2 -0
- package/dist/remote/config.js.map +1 -1
- package/dist/remote/endpoint.d.ts.map +1 -1
- package/dist/remote/endpoint.js +66 -11
- package/dist/remote/endpoint.js.map +1 -1
- package/dist/remote/hub-server.d.ts +15 -0
- package/dist/remote/hub-server.d.ts.map +1 -1
- package/dist/remote/hub-server.js +205 -1
- package/dist/remote/hub-server.js.map +1 -1
- package/dist/repl/App.d.ts.map +1 -1
- package/dist/repl/App.js +22 -5
- package/dist/repl/App.js.map +1 -1
- package/dist/repl/model.d.ts +21 -0
- package/dist/repl/model.d.ts.map +1 -1
- package/dist/repl/model.js +34 -1
- package/dist/repl/model.js.map +1 -1
- package/dist/repl/run.d.ts.map +1 -1
- package/dist/repl/run.js +5 -0
- package/dist/repl/run.js.map +1 -1
- package/dist/server.d.ts +78 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +114 -3
- package/dist/server.js.map +1 -1
- package/dist/tasks-index.d.ts +27 -0
- package/dist/tasks-index.d.ts.map +1 -1
- package/dist/tasks-index.js +72 -3
- package/dist/tasks-index.js.map +1 -1
- package/docs/RELEASING.md +29 -0
- package/docs/REMOTE-CLIENTS.md +43 -0
- package/docs/TROUBLESHOOTING.md +9 -3
- package/package.json +13 -12
- package/dist/remote/session-liveness.d.ts +0 -19
- package/dist/remote/session-liveness.d.ts.map +0 -1
- package/dist/remote/session-liveness.js +0 -70
- package/dist/remote/session-liveness.js.map +0 -1
- package/dist/repl/mouse.d.ts +0 -49
- package/dist/repl/mouse.d.ts.map +0 -1
- package/dist/repl/mouse.js +0 -165
- package/dist/repl/mouse.js.map +0 -1
package/dist/server.d.ts
CHANGED
|
@@ -96,6 +96,40 @@ export declare class ZcodeAcpServer {
|
|
|
96
96
|
* are deleted on first use.
|
|
97
97
|
*/
|
|
98
98
|
readonly sessionCwds: Map<string, string>;
|
|
99
|
+
/**
|
|
100
|
+
* Sandbox dynamic-allow state (ADR-0011): realpaths granted for this
|
|
101
|
+
* bridge lifetime ("仅此一次" answers) — folded into the Seatbelt profile
|
|
102
|
+
* on the next backend respawn in ensureBackend().
|
|
103
|
+
*/
|
|
104
|
+
readonly sandboxOnceAllows: Set<string>;
|
|
105
|
+
/**
|
|
106
|
+
* Deny paths already asked about, per ACP session — the debounce behind
|
|
107
|
+
* the allow popup (the model retries the same path and must not re-ask).
|
|
108
|
+
* Includes rejected/timed-out asks.
|
|
109
|
+
*/
|
|
110
|
+
readonly sandboxAskedPaths: Map<string, Set<string>>;
|
|
111
|
+
/**
|
|
112
|
+
* EACCES ("Permission denied") paths already hinted, per ACP session — the
|
|
113
|
+
* model routinely probes unreadable directories and each real path gets
|
|
114
|
+
* exactly one hint (see the filesystem-permission scan in session.ts's
|
|
115
|
+
* turn loop; kept separate from sandboxAskedPaths so one flow's debounce
|
|
116
|
+
* never silences the other).
|
|
117
|
+
*/
|
|
118
|
+
readonly fsDeniedPaths: Map<string, Set<string>>;
|
|
119
|
+
/**
|
|
120
|
+
* Continuation prompts waiting to run after a sandbox allow restart, per
|
|
121
|
+
* ACP session — set by the allow flow, consumed by prompt() after the
|
|
122
|
+
* interrupted turn unwinds (the new turn tells the model the write is now
|
|
123
|
+
* permitted and to resume the task).
|
|
124
|
+
*/
|
|
125
|
+
readonly sandboxContinuations: Map<string, string>;
|
|
126
|
+
/**
|
|
127
|
+
* Whether the current backend subprocess was spawned under sandbox-exec.
|
|
128
|
+
* Process-level fact (not config wish): EPERM in tool output can only come
|
|
129
|
+
* from a sandboxed process, and applySandboxFlip() needs to detect a
|
|
130
|
+
* config-armed sandbox facing an unsandboxed live backend.
|
|
131
|
+
*/
|
|
132
|
+
backendSandboxed: boolean;
|
|
99
133
|
/**
|
|
100
134
|
* Currently running turns, keyed by the ACP request id (JSON-RPC ids may be
|
|
101
135
|
* numbers or strings; set/delete always use the same value, so the wider
|
|
@@ -185,10 +219,53 @@ export declare class ZcodeAcpServer {
|
|
|
185
219
|
readonly terminalSentData: Map<string, string>;
|
|
186
220
|
/** Monotonic id counter; base 10_000_000 to avoid collisions with zcode-originated ids. */
|
|
187
221
|
private msgCounter;
|
|
222
|
+
/**
|
|
223
|
+
* Headless serve mode (ADR-0014): this bridge was hub-spawned for ONE known
|
|
224
|
+
* project (the process cwd). session/new then ignores client-supplied cwds
|
|
225
|
+
* and always uses the process cwd — the remote create-whitelist stays
|
|
226
|
+
* closed end to end (a client cannot steer a serve bridge into another
|
|
227
|
+
* directory).
|
|
228
|
+
*/
|
|
229
|
+
readonly serveMode: boolean;
|
|
230
|
+
constructor(opts?: {
|
|
231
|
+
serveMode?: boolean;
|
|
232
|
+
});
|
|
188
233
|
/** Next JSON-RPC id for messages we send to zcode. */
|
|
189
234
|
nextId(): number;
|
|
190
|
-
/**
|
|
235
|
+
/**
|
|
236
|
+
* Lazily spawn the zcode backend on first use (initialize doesn't need it).
|
|
237
|
+
* With the sandbox armed (ZCODE_ACP_SANDBOX=1 globally, or any live
|
|
238
|
+
* workspace's .zcode/acp/sandbox.json — ADR-0011), the spawn is wrapped in
|
|
239
|
+
* a Seatbelt profile built from the live workspace roots — session/new
|
|
240
|
+
* records cwds before any backend RPC (lazy placeholders), so the whitelist
|
|
241
|
+
* is complete by the time the backend materializes here.
|
|
242
|
+
*/
|
|
191
243
|
ensureBackend(): ZcodeBackend;
|
|
244
|
+
/**
|
|
245
|
+
* Mark every in-flight turn cancelled — used right before killing the
|
|
246
|
+
* backend WHOLESALE (sandbox arm-flip / allow restart). Those turn loops
|
|
247
|
+
* would otherwise wait on a dead reader with no stall signal (the backend
|
|
248
|
+
* is gone, so no events ever arrive) and hang until the freeze watchdog,
|
|
249
|
+
* ~10 minutes per turn. stopSent: no stop pair is needed — the entire
|
|
250
|
+
* process group dies with the backend.
|
|
251
|
+
*/
|
|
252
|
+
cancelAllPendingTurns(): void;
|
|
253
|
+
/**
|
|
254
|
+
* Workspace roots that parametrize the sandbox decision/profile: every live
|
|
255
|
+
* session's cwd, falling back to the bridge's own cwd before any session.
|
|
256
|
+
*/
|
|
257
|
+
sandboxRoots(): Set<string>;
|
|
258
|
+
/**
|
|
259
|
+
* Project-level sandbox flip (ADR-0011): flipping `enabled: true` in a live
|
|
260
|
+
* workspace's .zcode/acp/sandbox.json arms the sandbox mid-run, without a
|
|
261
|
+
* global env. If the flip happened after the current backend spawned
|
|
262
|
+
* unsandboxed, kill it — the caller's next ensureBackend() respawns under
|
|
263
|
+
* the profile, and prompt()'s subscribe recovery reloads the session. The
|
|
264
|
+
* reverse (flipping back to false) never restarts a live sandboxed backend;
|
|
265
|
+
* the next natural respawn drops the wrap. Best-effort: a failed kill
|
|
266
|
+
* leaves things as they were (the sandbox arms on a later respawn).
|
|
267
|
+
*/
|
|
268
|
+
applySandboxFlip(): Promise<void>;
|
|
192
269
|
/** Resolve the zcode session id for an ACP session id. */
|
|
193
270
|
resolveSid(acpSid: string): string | undefined;
|
|
194
271
|
/**
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,KAAK,GAAG,MAAM,0BAA0B,CAAC;AAErD,OAAO,EAIL,YAAY,EACb,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -7,10 +7,11 @@
|
|
|
7
7
|
* every handler layer can reach it without globals.
|
|
8
8
|
*/
|
|
9
9
|
import { loadZcodeCredentials, mergeEnvWithCreds, resolveZcodeCommand, ZcodeBackend, } from "./backend/index.js";
|
|
10
|
+
import { armSandboxArgv, collectSandboxWorkspaces, sandboxActive } from "./backend/sandbox.js";
|
|
10
11
|
import { BackgroundTaskListener } from "./handlers/background-tasks.js";
|
|
11
12
|
import { enqueueSessionSend } from "./handlers/io.js";
|
|
12
13
|
import { ClientRegistry } from "./remote/broadcast.js";
|
|
13
|
-
import { AGENT_INFO, PROTOCOL_VERSION, log } from "./utils.js";
|
|
14
|
+
import { AGENT_INFO, PROTOCOL_VERSION, log, warn } from "./utils.js";
|
|
14
15
|
/**
|
|
15
16
|
* How long a "loaded in backend" verification stays trusted. The backend
|
|
16
17
|
* evicts resident runtimes after ~10min idle (observed
|
|
@@ -54,6 +55,40 @@ export class ZcodeAcpServer {
|
|
|
54
55
|
* are deleted on first use.
|
|
55
56
|
*/
|
|
56
57
|
sessionCwds = new Map();
|
|
58
|
+
/**
|
|
59
|
+
* Sandbox dynamic-allow state (ADR-0011): realpaths granted for this
|
|
60
|
+
* bridge lifetime ("仅此一次" answers) — folded into the Seatbelt profile
|
|
61
|
+
* on the next backend respawn in ensureBackend().
|
|
62
|
+
*/
|
|
63
|
+
sandboxOnceAllows = new Set();
|
|
64
|
+
/**
|
|
65
|
+
* Deny paths already asked about, per ACP session — the debounce behind
|
|
66
|
+
* the allow popup (the model retries the same path and must not re-ask).
|
|
67
|
+
* Includes rejected/timed-out asks.
|
|
68
|
+
*/
|
|
69
|
+
sandboxAskedPaths = new Map();
|
|
70
|
+
/**
|
|
71
|
+
* EACCES ("Permission denied") paths already hinted, per ACP session — the
|
|
72
|
+
* model routinely probes unreadable directories and each real path gets
|
|
73
|
+
* exactly one hint (see the filesystem-permission scan in session.ts's
|
|
74
|
+
* turn loop; kept separate from sandboxAskedPaths so one flow's debounce
|
|
75
|
+
* never silences the other).
|
|
76
|
+
*/
|
|
77
|
+
fsDeniedPaths = new Map();
|
|
78
|
+
/**
|
|
79
|
+
* Continuation prompts waiting to run after a sandbox allow restart, per
|
|
80
|
+
* ACP session — set by the allow flow, consumed by prompt() after the
|
|
81
|
+
* interrupted turn unwinds (the new turn tells the model the write is now
|
|
82
|
+
* permitted and to resume the task).
|
|
83
|
+
*/
|
|
84
|
+
sandboxContinuations = new Map();
|
|
85
|
+
/**
|
|
86
|
+
* Whether the current backend subprocess was spawned under sandbox-exec.
|
|
87
|
+
* Process-level fact (not config wish): EPERM in tool output can only come
|
|
88
|
+
* from a sandboxed process, and applySandboxFlip() needs to detect a
|
|
89
|
+
* config-armed sandbox facing an unsandboxed live backend.
|
|
90
|
+
*/
|
|
91
|
+
backendSandboxed = false;
|
|
57
92
|
/**
|
|
58
93
|
* Currently running turns, keyed by the ACP request id (JSON-RPC ids may be
|
|
59
94
|
* numbers or strings; set/delete always use the same value, so the wider
|
|
@@ -139,19 +174,95 @@ export class ZcodeAcpServer {
|
|
|
139
174
|
terminalSentData = new Map();
|
|
140
175
|
/** Monotonic id counter; base 10_000_000 to avoid collisions with zcode-originated ids. */
|
|
141
176
|
msgCounter = 10_000_000;
|
|
177
|
+
/**
|
|
178
|
+
* Headless serve mode (ADR-0014): this bridge was hub-spawned for ONE known
|
|
179
|
+
* project (the process cwd). session/new then ignores client-supplied cwds
|
|
180
|
+
* and always uses the process cwd — the remote create-whitelist stays
|
|
181
|
+
* closed end to end (a client cannot steer a serve bridge into another
|
|
182
|
+
* directory).
|
|
183
|
+
*/
|
|
184
|
+
serveMode;
|
|
185
|
+
constructor(opts = {}) {
|
|
186
|
+
this.serveMode = opts.serveMode === true;
|
|
187
|
+
}
|
|
142
188
|
/** Next JSON-RPC id for messages we send to zcode. */
|
|
143
189
|
nextId() {
|
|
144
190
|
return ++this.msgCounter;
|
|
145
191
|
}
|
|
146
|
-
/**
|
|
192
|
+
/**
|
|
193
|
+
* Lazily spawn the zcode backend on first use (initialize doesn't need it).
|
|
194
|
+
* With the sandbox armed (ZCODE_ACP_SANDBOX=1 globally, or any live
|
|
195
|
+
* workspace's .zcode/acp/sandbox.json — ADR-0011), the spawn is wrapped in
|
|
196
|
+
* a Seatbelt profile built from the live workspace roots — session/new
|
|
197
|
+
* records cwds before any backend RPC (lazy placeholders), so the whitelist
|
|
198
|
+
* is complete by the time the backend materializes here.
|
|
199
|
+
*/
|
|
147
200
|
ensureBackend() {
|
|
148
201
|
if (this.backend && !this.backend.isDead)
|
|
149
202
|
return this.backend;
|
|
150
203
|
const env = mergeEnvWithCreds(loadZcodeCredentials());
|
|
151
|
-
|
|
204
|
+
let argv = resolveZcodeCommand();
|
|
205
|
+
this.backendSandboxed = sandboxActive(this.sandboxRoots());
|
|
206
|
+
if (this.backendSandboxed) {
|
|
207
|
+
const { workspaces, extraAllow } = collectSandboxWorkspaces(this.sandboxRoots());
|
|
208
|
+
argv = armSandboxArgv(argv, {
|
|
209
|
+
workspaces,
|
|
210
|
+
extraAllow: [...extraAllow, ...this.sandboxOnceAllows],
|
|
211
|
+
});
|
|
212
|
+
}
|
|
152
213
|
this.backend = new ZcodeBackend(argv, env);
|
|
153
214
|
return this.backend;
|
|
154
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* Mark every in-flight turn cancelled — used right before killing the
|
|
218
|
+
* backend WHOLESALE (sandbox arm-flip / allow restart). Those turn loops
|
|
219
|
+
* would otherwise wait on a dead reader with no stall signal (the backend
|
|
220
|
+
* is gone, so no events ever arrive) and hang until the freeze watchdog,
|
|
221
|
+
* ~10 minutes per turn. stopSent: no stop pair is needed — the entire
|
|
222
|
+
* process group dies with the backend.
|
|
223
|
+
*/
|
|
224
|
+
cancelAllPendingTurns() {
|
|
225
|
+
for (const turn of this.pendingTurns.values()) {
|
|
226
|
+
turn.cancelled = true;
|
|
227
|
+
turn.stopSent = true;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Workspace roots that parametrize the sandbox decision/profile: every live
|
|
232
|
+
* session's cwd, falling back to the bridge's own cwd before any session.
|
|
233
|
+
*/
|
|
234
|
+
sandboxRoots() {
|
|
235
|
+
const roots = new Set(this.sessionCwds.values());
|
|
236
|
+
if (roots.size === 0)
|
|
237
|
+
roots.add(process.cwd());
|
|
238
|
+
return roots;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Project-level sandbox flip (ADR-0011): flipping `enabled: true` in a live
|
|
242
|
+
* workspace's .zcode/acp/sandbox.json arms the sandbox mid-run, without a
|
|
243
|
+
* global env. If the flip happened after the current backend spawned
|
|
244
|
+
* unsandboxed, kill it — the caller's next ensureBackend() respawns under
|
|
245
|
+
* the profile, and prompt()'s subscribe recovery reloads the session. The
|
|
246
|
+
* reverse (flipping back to false) never restarts a live sandboxed backend;
|
|
247
|
+
* the next natural respawn drops the wrap. Best-effort: a failed kill
|
|
248
|
+
* leaves things as they were (the sandbox arms on a later respawn).
|
|
249
|
+
*/
|
|
250
|
+
async applySandboxFlip() {
|
|
251
|
+
if (this.backendSandboxed)
|
|
252
|
+
return;
|
|
253
|
+
if (!this.backend || this.backend.isDead)
|
|
254
|
+
return;
|
|
255
|
+
if (!sandboxActive(this.sandboxRoots()))
|
|
256
|
+
return;
|
|
257
|
+
warn("sandbox: project config armed mid-run — restarting backend under sandbox-exec");
|
|
258
|
+
this.cancelAllPendingTurns();
|
|
259
|
+
try {
|
|
260
|
+
await this.backend.close();
|
|
261
|
+
}
|
|
262
|
+
catch (e) {
|
|
263
|
+
warn(`sandbox: backend kill failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
155
266
|
/** Resolve the zcode session id for an ACP session id. */
|
|
156
267
|
resolveSid(acpSid) {
|
|
157
268
|
return this.sessionMap.get(acpSid);
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,GACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/tasks-index.d.ts
CHANGED
|
@@ -53,4 +53,31 @@ export declare function renameSessionTask(taskId: string, title: string): Promis
|
|
|
53
53
|
* matches the shape of App-created rows.
|
|
54
54
|
*/
|
|
55
55
|
export declare function updateSessionTitle(taskId: string, title: string, searchableText?: string): Promise<boolean>;
|
|
56
|
+
/** One known project workspace, as recorded by the App's tasks index. */
|
|
57
|
+
export interface KnownWorkspace {
|
|
58
|
+
workspacePath: string;
|
|
59
|
+
sessions: number;
|
|
60
|
+
lastActive: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Whether a recorded workspace path may be offered for remote session
|
|
64
|
+
* creation. Excludes: degenerate roots, system temp trees (macOS /tmp is a
|
|
65
|
+
* symlink to /private/tmp — both spellings; $TMPDIR lives under /var/folders),
|
|
66
|
+
* and ~/.zcode itself (the config home, not a project). The directory must
|
|
67
|
+
* still exist — a moved/deleted project disappears from the list.
|
|
68
|
+
*/
|
|
69
|
+
export declare function isSelectableWorkspace(p: string): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Every project workspace the tasks index has ever recorded a session for —
|
|
72
|
+
* the machine's known-projects list. Serves the hub's remote session-create
|
|
73
|
+
* API: the list gates which projects POST /api/instances accepts. A
|
|
74
|
+
* convenience bound, not a security boundary — bridge-side session
|
|
75
|
+
* materialization writes rows too, and a token holder can drive an
|
|
76
|
+
* editor-bridge session in any cwd (the real boundary is the token).
|
|
77
|
+
*
|
|
78
|
+
* Read-only and best-effort: node:sqlite unavailable → empty list; lock
|
|
79
|
+
* contention retries via withSqliteRetry; other failures warn and return
|
|
80
|
+
* empty. `dbPath` defaults to the App's index (tests inject a fixture).
|
|
81
|
+
*/
|
|
82
|
+
export declare function listKnownWorkspaces(dbPath?: string): Promise<KnownWorkspace[]>;
|
|
56
83
|
//# sourceMappingURL=tasks-index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tasks-index.d.ts","sourceRoot":"","sources":["../src/tasks-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;
|
|
1
|
+
{"version":3,"file":"tasks-index.d.ts","sourceRoot":"","sources":["../src/tasks-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA8HH;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,OAAO,CAAC,CA4DnB;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA+BvF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,OAAO,CAAC,CAqDlB;AAID,yEAAyE;AACzE,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAiBxD;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,GAAE,MAAyB,GAChC,OAAO,CAAC,cAAc,EAAE,CAAC,CA6B3B"}
|
package/dist/tasks-index.js
CHANGED
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
* Best-effort side-channel: failures (locked DB, schema drift) are logged and
|
|
16
16
|
* swallowed so they never break the session/create path.
|
|
17
17
|
*/
|
|
18
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
18
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
19
|
+
import { homedir, tmpdir } from "node:os";
|
|
19
20
|
import path from "node:path";
|
|
20
21
|
import { DEFAULT_MODEL_ID } from "./config/options.js";
|
|
21
22
|
import { warn, ZCODE_CREDS_PATH } from "./utils.js";
|
|
@@ -68,7 +69,7 @@ function sleep(ms) {
|
|
|
68
69
|
* Rethrows non-busy errors (or busy errors that exhausted retries) so the
|
|
69
70
|
* caller can classify and log them consistently.
|
|
70
71
|
*/
|
|
71
|
-
async function withSqliteRetry(fn) {
|
|
72
|
+
async function withSqliteRetry(fn, dbPath = TASKS_INDEX_PATH) {
|
|
72
73
|
const Sqlite = await loadSqlite();
|
|
73
74
|
if (!Sqlite)
|
|
74
75
|
return null; // node:sqlite unavailable (Node < 22)
|
|
@@ -77,7 +78,7 @@ async function withSqliteRetry(fn) {
|
|
|
77
78
|
// constructor itself throws (SQLITE_BUSY can surface at open time).
|
|
78
79
|
let con = null;
|
|
79
80
|
try {
|
|
80
|
-
con = new Sqlite(
|
|
81
|
+
con = new Sqlite(dbPath, { timeout: 5000 });
|
|
81
82
|
return fn(con);
|
|
82
83
|
}
|
|
83
84
|
catch (e) {
|
|
@@ -289,4 +290,72 @@ export async function updateSessionTitle(taskId, title, searchableText) {
|
|
|
289
290
|
return false;
|
|
290
291
|
}
|
|
291
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* Whether a recorded workspace path may be offered for remote session
|
|
295
|
+
* creation. Excludes: degenerate roots, system temp trees (macOS /tmp is a
|
|
296
|
+
* symlink to /private/tmp — both spellings; $TMPDIR lives under /var/folders),
|
|
297
|
+
* and ~/.zcode itself (the config home, not a project). The directory must
|
|
298
|
+
* still exist — a moved/deleted project disappears from the list.
|
|
299
|
+
*/
|
|
300
|
+
export function isSelectableWorkspace(p) {
|
|
301
|
+
if (!p || p === "/")
|
|
302
|
+
return false;
|
|
303
|
+
const excluded = [
|
|
304
|
+
"/tmp",
|
|
305
|
+
"/private/tmp",
|
|
306
|
+
"/var/folders",
|
|
307
|
+
tmpdir(),
|
|
308
|
+
path.join(homedir(), ".zcode"),
|
|
309
|
+
];
|
|
310
|
+
for (const ex of excluded) {
|
|
311
|
+
if (p === ex || p.startsWith(ex + path.sep))
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
try {
|
|
315
|
+
return statSync(p).isDirectory();
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Every project workspace the tasks index has ever recorded a session for —
|
|
323
|
+
* the machine's known-projects list. Serves the hub's remote session-create
|
|
324
|
+
* API: the list gates which projects POST /api/instances accepts. A
|
|
325
|
+
* convenience bound, not a security boundary — bridge-side session
|
|
326
|
+
* materialization writes rows too, and a token holder can drive an
|
|
327
|
+
* editor-bridge session in any cwd (the real boundary is the token).
|
|
328
|
+
*
|
|
329
|
+
* Read-only and best-effort: node:sqlite unavailable → empty list; lock
|
|
330
|
+
* contention retries via withSqliteRetry; other failures warn and return
|
|
331
|
+
* empty. `dbPath` defaults to the App's index (tests inject a fixture).
|
|
332
|
+
*/
|
|
333
|
+
export async function listKnownWorkspaces(dbPath = TASKS_INDEX_PATH) {
|
|
334
|
+
if (!existsSync(dbPath))
|
|
335
|
+
return [];
|
|
336
|
+
try {
|
|
337
|
+
const rows = await withSqliteRetry((con) => con
|
|
338
|
+
.prepare("SELECT workspace_path AS p, COUNT(*) AS n, MAX(updated_at) AS t " +
|
|
339
|
+
"FROM tasks WHERE deleted=0 GROUP BY workspace_key ORDER BY t DESC")
|
|
340
|
+
.all(), dbPath);
|
|
341
|
+
if (!rows)
|
|
342
|
+
return []; // node:sqlite unavailable (Node < 22)
|
|
343
|
+
const out = [];
|
|
344
|
+
for (const r of rows) {
|
|
345
|
+
const p = typeof r.p === "string" ? r.p : "";
|
|
346
|
+
if (!isSelectableWorkspace(p))
|
|
347
|
+
continue;
|
|
348
|
+
out.push({
|
|
349
|
+
workspacePath: p,
|
|
350
|
+
sessions: typeof r.n === "number" ? r.n : 0,
|
|
351
|
+
lastActive: typeof r.t === "number" ? r.t : 0,
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
return out;
|
|
355
|
+
}
|
|
356
|
+
catch (e) {
|
|
357
|
+
warn(`tasks-index workspace list failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
358
|
+
return [];
|
|
359
|
+
}
|
|
360
|
+
}
|
|
292
361
|
//# sourceMappingURL=tasks-index.js.map
|
package/dist/tasks-index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tasks-index.js","sourceRoot":"","sources":["../src/tasks-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"tasks-index.js","sourceRoot":"","sources":["../src/tasks-index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Releasing
|
|
2
|
+
|
|
3
|
+
Releases are fully automated: [release-please](https://github.com/googleapis/release-please)
|
|
4
|
+
turns Conventional Commits on `main` into a release PR, and merging that PR
|
|
5
|
+
tags the release, creates the GitHub Release and publishes to npm — no manual
|
|
6
|
+
version bumps, no npm token.
|
|
7
|
+
|
|
8
|
+
## How to cut a release
|
|
9
|
+
|
|
10
|
+
1. Land Conventional Commits on `main` (`feat:` → minor, `fix:`/`perf:` →
|
|
11
|
+
patch, `feat!:` or `BREAKING CHANGE:` footer → major). Squash-merge PRs
|
|
12
|
+
with a conventional title, or the change is invisible to release-please.
|
|
13
|
+
2. release-please opens or updates a `chore(main): release X.Y.Z` PR
|
|
14
|
+
(version bump in `package.json` + `CHANGELOG.md` entry). It rewrites
|
|
15
|
+
itself as more commits land.
|
|
16
|
+
3. Merge that PR. The `Release` workflow (`.github/workflows/release.yml`)
|
|
17
|
+
tags `vX.Y.Z`, creates the GitHub Release, then builds, runs the test
|
|
18
|
+
suite and publishes the package to npm. npmmirror follows on its own
|
|
19
|
+
sync schedule.
|
|
20
|
+
|
|
21
|
+
There is no manual tagging step. `package.json` version and
|
|
22
|
+
`.release-please-manifest.json` are maintained by release-please — never edit
|
|
23
|
+
them by hand.
|
|
24
|
+
|
|
25
|
+
## Registry
|
|
26
|
+
|
|
27
|
+
The ACP Registry entry (`agentclientprotocol/registry`, id `zcode-acp`) pins
|
|
28
|
+
an explicit `package@version` for first inclusion, but its sync bot follows
|
|
29
|
+
new npm versions automatically afterwards — a release needs no registry PR.
|
package/docs/REMOTE-CLIENTS.md
CHANGED
|
@@ -55,6 +55,8 @@ ACP editor ────── stdio ──────────┘
|
|
|
55
55
|
| `POST /api/instances/{id}/sessions/{sessionId}/rename` | required | Rename a session — see [Renaming a session](#renaming-a-session). |
|
|
56
56
|
| `GET /api/quota` | required | Account-level usage stats — same payload as `account/usage_stats`, no ACP connection needed. |
|
|
57
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
|
+
| `POST /api/instances {workspacePath}` | required | Create (or reuse) a headless serve bridge for one known project — see below. |
|
|
58
60
|
|
|
59
61
|
HTTP auth: `Authorization: Bearer <token>` or `?token=<token>`.
|
|
60
62
|
|
|
@@ -68,6 +70,7 @@ HTTP auth: `Authorization: Bearer <token>` or `?token=<token>`.
|
|
|
68
70
|
"pid": 72341,
|
|
69
71
|
"startedAt": 1723800000000,
|
|
70
72
|
"workspace": "/Users/me/proj",
|
|
73
|
+
"origin": "editor",
|
|
71
74
|
"sessions": [
|
|
72
75
|
{
|
|
73
76
|
"sessionId": "5f0c…",
|
|
@@ -82,6 +85,9 @@ HTTP auth: `Authorization: Bearer <token>` or `?token=<token>`.
|
|
|
82
85
|
|
|
83
86
|
- `id` is the bridge process id — stable for that editor window's lifetime,
|
|
84
87
|
unique per window.
|
|
88
|
+
- `origin` is `"editor"` (a bridge an editor spawned over stdio) or
|
|
89
|
+
`"serve"` (a headless bridge created via remote session-create — see
|
|
90
|
+
below; older bridges send no field, treat as `"editor"`).
|
|
85
91
|
- **On refresh, call `/api/instances?probe=1`**: the hub TCP-probes each
|
|
86
92
|
registered bridge's loopback port and prunes unreachable ones before
|
|
87
93
|
answering. A plain `GET` returns the heartbeat-based view, which can list a
|
|
@@ -131,6 +137,43 @@ heartbeat); an instance disappears ~30s after its heartbeats stop; the hub
|
|
|
131
137
|
exits after ~10 idle minutes with no instances and no proxies, and the next
|
|
132
138
|
bridge re-spawns it on demand.
|
|
133
139
|
|
|
140
|
+
## Remote session-create
|
|
141
|
+
|
|
142
|
+
A remote client can start a NEW agent session in any of the machine's known
|
|
143
|
+
projects — no editor required (bridge 0.17.0, ADR-0014):
|
|
144
|
+
|
|
145
|
+
```text
|
|
146
|
+
GET {hub}/api/projects
|
|
147
|
+
→ 200 [{"workspacePath":"/Users/me/proj","sessions":294,"lastActive":1723800000000}, …]
|
|
148
|
+
|
|
149
|
+
POST {hub}/api/instances body {"workspacePath":"/Users/me/proj"}
|
|
150
|
+
→ 200 {"id":"47073","reused":false}
|
|
151
|
+
→ 403 "unknown project" (path not on the known-project list)
|
|
152
|
+
→ 502 (spawn failed / bridge died during startup / never registered, 10s budget)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
- `GET /api/projects` aggregates the App's tasks index: every workspace that
|
|
156
|
+
ever ran a session, filtered (system temp trees, `~/.zcode` itself,
|
|
157
|
+
vanished directories) and sorted by last activity. The POST validates
|
|
158
|
+
against this exact list — no arbitrary paths. Note this is a convenience
|
|
159
|
+
bound, not a security boundary: a token holder can already run any
|
|
160
|
+
editor-bridge session in an arbitrary cwd; the trust boundary is the
|
|
161
|
+
token itself.
|
|
162
|
+
- On create the hub spawns `zcode-acp serve` — a headless bridge — detached
|
|
163
|
+
in the project's cwd and waits for its heartbeat registration (it appears
|
|
164
|
+
in `/api/instances` with `origin:"serve"` within seconds). Connect with
|
|
165
|
+
the normal `WS /acp?instance=<id>` and drive it like any instance; the
|
|
166
|
+
new conversation's cwd is the project directory regardless of what
|
|
167
|
+
`session/new` sends.
|
|
168
|
+
- A live serve instance for the same workspace is reused (`reused:true`)
|
|
169
|
+
instead of spawning a second one; concurrent creates join the same
|
|
170
|
+
in-flight spawn instead of racing a duplicate.
|
|
171
|
+
- Lifetime: the serve bridge exists for remote interest only. It exits ~10
|
|
172
|
+
minutes after the last client detaches AND the last running turn
|
|
173
|
+
finishes — a running turn always completes, even with all clients gone.
|
|
174
|
+
Treat a vanished serve instance like any other dead bridge: re-create it
|
|
175
|
+
on demand.
|
|
176
|
+
|
|
134
177
|
## Connecting
|
|
135
178
|
|
|
136
179
|
```text
|
package/docs/TROUBLESHOOTING.md
CHANGED
|
@@ -340,13 +340,19 @@ http://127.0.0.1:<hub-port>/api/health` fails, or `/api/*` returns 401.
|
|
|
340
340
|
|
|
341
341
|
1. 401 means a token mismatch — `ZCODE_ACP_REMOTE_TOKEN` must be identical in
|
|
342
342
|
the bridge env, the hub env (if run manually), and the client request.
|
|
343
|
-
2.
|
|
343
|
+
2. Bridges on ≥0.17.0 self-heal after 401s (e.g. the token was rotated while
|
|
344
|
+
some windows kept the old env): the bridge keeps heartbeating and spawns a
|
|
345
|
+
replacement hub carrying its own token (≤1/min). Convergence needs the
|
|
346
|
+
mismatched hub to exit — instantly when nothing else holds the port, or via
|
|
347
|
+
its 10-minute zero-instance idle-exit. On older bridges a 401 permanently
|
|
348
|
+
stopped registration: restart the affected editor windows.
|
|
349
|
+
3. A dead hub self-heals: the next bridge heartbeat (≤10s; worst ~1min under
|
|
344
350
|
the spawn throttle) re-spawns the hub daemon. Retry with backoff rather
|
|
345
351
|
than restarting anything by hand.
|
|
346
|
-
|
|
352
|
+
4. Confirm the ports match: the client must reach `ZCODE_ACP_HUB_PORT`
|
|
347
353
|
(default 8377) through the tunnel, and the tunnel maps exactly that one
|
|
348
354
|
port.
|
|
349
|
-
|
|
355
|
+
5. Remote silently disabled? `ZCODE_ACP_REMOTE=1` without a token logs a
|
|
350
356
|
warning and leaves the bridge stdio-only by design.
|
|
351
357
|
|
|
352
358
|
### Remote access: stale instance in the list / connect fails
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zcode-acp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.2",
|
|
4
4
|
"description": "Agent Client Protocol (ACP) server bridging headless ZCode to editors like Zed and JetBrains.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -34,6 +34,17 @@
|
|
|
34
34
|
"LICENSE",
|
|
35
35
|
"docs"
|
|
36
36
|
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsc",
|
|
39
|
+
"dev": "tsc --watch",
|
|
40
|
+
"typecheck": "tsc --noEmit",
|
|
41
|
+
"test": "vitest run",
|
|
42
|
+
"test:watch": "vitest",
|
|
43
|
+
"format": "prettier --write src",
|
|
44
|
+
"lint": "eslint .",
|
|
45
|
+
"smoke": "node dist/index.js < /dev/null",
|
|
46
|
+
"prepublishOnly": "pnpm run build && pnpm run test"
|
|
47
|
+
},
|
|
37
48
|
"dependencies": {
|
|
38
49
|
"@agentclientprotocol/sdk": "^1.3.0",
|
|
39
50
|
"chalk": "^6.0.0",
|
|
@@ -61,15 +72,5 @@
|
|
|
61
72
|
},
|
|
62
73
|
"engines": {
|
|
63
74
|
"node": ">=22.0.0"
|
|
64
|
-
},
|
|
65
|
-
"scripts": {
|
|
66
|
-
"build": "tsc",
|
|
67
|
-
"dev": "tsc --watch",
|
|
68
|
-
"typecheck": "tsc --noEmit",
|
|
69
|
-
"test": "vitest run",
|
|
70
|
-
"test:watch": "vitest",
|
|
71
|
-
"format": "prettier --write src",
|
|
72
|
-
"lint": "eslint .",
|
|
73
|
-
"smoke": "node dist/index.js < /dev/null"
|
|
74
75
|
}
|
|
75
|
-
}
|
|
76
|
+
}
|