@chances-ai/wire 24.0.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/rpc/acp/adapter.d.ts +32 -0
- package/dist/rpc/acp/adapter.d.ts.map +1 -0
- package/dist/rpc/acp/adapter.js +185 -0
- package/dist/rpc/acp/adapter.js.map +1 -0
- package/dist/rpc/acp/engine-driver.d.ts +128 -0
- package/dist/rpc/acp/engine-driver.d.ts.map +1 -0
- package/dist/rpc/acp/engine-driver.js +550 -0
- package/dist/rpc/acp/engine-driver.js.map +1 -0
- package/dist/rpc/acp/event-map.d.ts +22 -0
- package/dist/rpc/acp/event-map.d.ts.map +1 -0
- package/dist/rpc/acp/event-map.js +205 -0
- package/dist/rpc/acp/event-map.js.map +1 -0
- package/dist/rpc/acp/load-sdk.d.ts +3 -0
- package/dist/rpc/acp/load-sdk.d.ts.map +1 -0
- package/dist/rpc/acp/load-sdk.js +24 -0
- package/dist/rpc/acp/load-sdk.js.map +1 -0
- package/dist/rpc/acp/workspace-query.d.ts +41 -0
- package/dist/rpc/acp/workspace-query.d.ts.map +1 -0
- package/dist/rpc/acp/workspace-query.js +89 -0
- package/dist/rpc/acp/workspace-query.js.map +1 -0
- package/dist/rpc/driver.d.ts +42 -0
- package/dist/rpc/driver.d.ts.map +1 -0
- package/dist/rpc/driver.js +7 -0
- package/dist/rpc/driver.js.map +1 -0
- package/dist/rpc/event-map.d.ts +8 -0
- package/dist/rpc/event-map.d.ts.map +1 -0
- package/dist/rpc/event-map.js +91 -0
- package/dist/rpc/event-map.js.map +1 -0
- package/dist/rpc/index.d.ts +13 -0
- package/dist/rpc/index.d.ts.map +1 -0
- package/dist/rpc/index.js +18 -0
- package/dist/rpc/index.js.map +1 -0
- package/dist/rpc/lines.d.ts +2 -0
- package/dist/rpc/lines.d.ts.map +1 -0
- package/dist/rpc/lines.js +24 -0
- package/dist/rpc/lines.js.map +1 -0
- package/dist/rpc/protocol.d.ts +315 -0
- package/dist/rpc/protocol.d.ts.map +1 -0
- package/dist/rpc/protocol.js +70 -0
- package/dist/rpc/protocol.js.map +1 -0
- package/dist/rpc/rpc-server.d.ts +56 -0
- package/dist/rpc/rpc-server.d.ts.map +1 -0
- package/dist/rpc/rpc-server.js +305 -0
- package/dist/rpc/rpc-server.js.map +1 -0
- package/dist/rpc/stdout-guard.d.ts +5 -0
- package/dist/rpc/stdout-guard.d.ts.map +1 -0
- package/dist/rpc/stdout-guard.js +31 -0
- package/dist/rpc/stdout-guard.js.map +1 -0
- package/dist/rpc/writer.d.ts +34 -0
- package/dist/rpc/writer.d.ts.map +1 -0
- package/dist/rpc/writer.js +85 -0
- package/dist/rpc/writer.js.map +1 -0
- package/dist/serve/acp-session-host.d.ts +120 -0
- package/dist/serve/acp-session-host.d.ts.map +1 -0
- package/dist/serve/acp-session-host.js +276 -0
- package/dist/serve/acp-session-host.js.map +1 -0
- package/dist/serve/auth.d.ts +21 -0
- package/dist/serve/auth.d.ts.map +1 -0
- package/dist/serve/auth.js +58 -0
- package/dist/serve/auth.js.map +1 -0
- package/dist/serve/highlight.d.ts +25 -0
- package/dist/serve/highlight.d.ts.map +1 -0
- package/dist/serve/highlight.js +28 -0
- package/dist/serve/highlight.js.map +1 -0
- package/dist/serve/index.d.ts +14 -0
- package/dist/serve/index.d.ts.map +1 -0
- package/dist/serve/index.js +23 -0
- package/dist/serve/index.js.map +1 -0
- package/dist/serve/pairing.d.ts +25 -0
- package/dist/serve/pairing.d.ts.map +1 -0
- package/dist/serve/pairing.js +10 -0
- package/dist/serve/pairing.js.map +1 -0
- package/dist/serve/relay-frames.d.ts +29 -0
- package/dist/serve/relay-frames.d.ts.map +1 -0
- package/dist/serve/relay-frames.js +54 -0
- package/dist/serve/relay-frames.js.map +1 -0
- package/dist/serve/relay.d.ts +146 -0
- package/dist/serve/relay.d.ts.map +1 -0
- package/dist/serve/relay.js +475 -0
- package/dist/serve/relay.js.map +1 -0
- package/dist/serve/replay-hub.d.ts +102 -0
- package/dist/serve/replay-hub.d.ts.map +1 -0
- package/dist/serve/replay-hub.js +176 -0
- package/dist/serve/replay-hub.js.map +1 -0
- package/dist/serve/tls.d.ts +20 -0
- package/dist/serve/tls.d.ts.map +1 -0
- package/dist/serve/tls.js +64 -0
- package/dist/serve/tls.js.map +1 -0
- package/dist/serve/ws-transport.d.ts +64 -0
- package/dist/serve/ws-transport.d.ts.map +1 -0
- package/dist/serve/ws-transport.js +92 -0
- package/dist/serve/ws-transport.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
// The bespoke RPC server: a thin orchestrator over the `EngineHost` seam
|
|
2
|
+
// (codex C1). It subscribes the engine bus → outbound frames, dispatches
|
|
3
|
+
// inbound commands via a method table (C8), owns the permission round-trip
|
|
4
|
+
// (deny-on-abort/close + dedup — C7, Round-1 M2), and runs the shutdown order
|
|
5
|
+
// (cancel → deny → dispose → flush — Round-1 S4). No transport I/O lives here:
|
|
6
|
+
// `run()` consumes an async-iterable of input lines and writes through the
|
|
7
|
+
// injected `BoundedNdjsonWriter`, so the whole thing is unit-testable
|
|
8
|
+
// in-process against a MockAdapter-backed engine.
|
|
9
|
+
import { CancellationTokenSource, createId } from "@chances-ai/runtime";
|
|
10
|
+
import { mapEvent } from "./event-map.js";
|
|
11
|
+
import { CommandSchema, PROTOCOL_NAME, PROTOCOL_VERSION, } from "./protocol.js";
|
|
12
|
+
import { BoundedNdjsonWriter } from "./writer.js";
|
|
13
|
+
const KNOWN_TYPES = new Set([
|
|
14
|
+
"prompt",
|
|
15
|
+
"abort",
|
|
16
|
+
"set_model",
|
|
17
|
+
"get_state",
|
|
18
|
+
"get_models",
|
|
19
|
+
"permission_response",
|
|
20
|
+
"set_options",
|
|
21
|
+
"ping",
|
|
22
|
+
]);
|
|
23
|
+
const MAX_RESOLVED_IDS = 1024;
|
|
24
|
+
/** Bound on awaiting an in-flight turn during shutdown (Round-2 M1). Matches
|
|
25
|
+
* the CLI's other 2 s teardown deadlines. */
|
|
26
|
+
const SHUTDOWN_TURN_DEADLINE_MS = 2_000;
|
|
27
|
+
export class RpcServer {
|
|
28
|
+
host;
|
|
29
|
+
writer;
|
|
30
|
+
agent;
|
|
31
|
+
autoApprove;
|
|
32
|
+
toolChunks;
|
|
33
|
+
logSink;
|
|
34
|
+
built = null;
|
|
35
|
+
unsub = null;
|
|
36
|
+
activeTurn = null;
|
|
37
|
+
/** The in-flight `handlePrompt` promise (fire-and-forget from the read
|
|
38
|
+
* loop). Tracked so shutdown can await its terminal `result` before
|
|
39
|
+
* closing the writer (Round-2 M1). */
|
|
40
|
+
activePrompt = null;
|
|
41
|
+
pending = new Map();
|
|
42
|
+
resolvedIds = [];
|
|
43
|
+
resolvedSet = new Set();
|
|
44
|
+
shuttingDown = false;
|
|
45
|
+
constructor(opts) {
|
|
46
|
+
this.host = opts.host;
|
|
47
|
+
this.writer = opts.writer;
|
|
48
|
+
this.agent = opts.agent;
|
|
49
|
+
this.autoApprove = opts.autoApprove ?? false;
|
|
50
|
+
this.toolChunks = opts.toolChunks ?? true;
|
|
51
|
+
this.logSink = opts.logSink ?? ((line) => process.stderr.write(line));
|
|
52
|
+
}
|
|
53
|
+
/** Drive the server until `lines` ends, then shut down. Returns an exit code. */
|
|
54
|
+
async run(lines) {
|
|
55
|
+
const built = this.host.build(this.makeResolver());
|
|
56
|
+
this.built = built;
|
|
57
|
+
// Subscribe BEFORE ready so no frame is missed. `log` is routed to stderr
|
|
58
|
+
// (stdout purity); everything else maps to a wire frame or is suppressed.
|
|
59
|
+
this.unsub = built.bus.onAny((e) => {
|
|
60
|
+
if (e.type === "log") {
|
|
61
|
+
this.logSink(`[${e.level}] ${e.message}\n`);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const frame = mapEvent(e, { toolChunks: this.toolChunks });
|
|
65
|
+
if (!frame)
|
|
66
|
+
return;
|
|
67
|
+
if (frame.type === "turn_start")
|
|
68
|
+
frame.commandId = this.activeTurn?.commandId;
|
|
69
|
+
this.writer.enqueue(frame);
|
|
70
|
+
});
|
|
71
|
+
this.writer.enqueue({
|
|
72
|
+
type: "ready",
|
|
73
|
+
protocol: PROTOCOL_NAME,
|
|
74
|
+
version: PROTOCOL_VERSION,
|
|
75
|
+
agent: this.agent,
|
|
76
|
+
sessionId: built.sessionId,
|
|
77
|
+
models: this.host.listModels(),
|
|
78
|
+
capabilities: { permissionPrompt: true, toolChunks: this.toolChunks, steering: false },
|
|
79
|
+
});
|
|
80
|
+
try {
|
|
81
|
+
for await (const line of lines) {
|
|
82
|
+
const trimmed = line.trim();
|
|
83
|
+
if (trimmed === "")
|
|
84
|
+
continue;
|
|
85
|
+
await this.handleLine(trimmed);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
await this.shutdown();
|
|
90
|
+
}
|
|
91
|
+
return 0;
|
|
92
|
+
}
|
|
93
|
+
/** Idempotent shutdown. Order (Round-1 S4): cancel the turn → deny pending
|
|
94
|
+
* permissions (so a turn blocked in the resolver unwinds — M2) → dispose
|
|
95
|
+
* (disposers may emit their LAST bus frames, still subscribed) → flush →
|
|
96
|
+
* close. */
|
|
97
|
+
async shutdown() {
|
|
98
|
+
if (this.shuttingDown)
|
|
99
|
+
return;
|
|
100
|
+
this.shuttingDown = true;
|
|
101
|
+
this.activeTurn?.cts.cancel();
|
|
102
|
+
this.denyAllPending();
|
|
103
|
+
// (Round-2 M1) Await the in-flight prompt so its terminal `result` frame
|
|
104
|
+
// is enqueued before we flush + close — otherwise EOF/SIGINT could ack a
|
|
105
|
+
// prompt and then drop its completion. Cancellation above makes runTurn
|
|
106
|
+
// settle promptly; the bounded race guards a turn that ignores the token.
|
|
107
|
+
if (this.activePrompt) {
|
|
108
|
+
await Promise.race([this.activePrompt, delay(SHUTDOWN_TURN_DEADLINE_MS)]);
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
await this.host.dispose();
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// dispose is best-effort; never let it block the flush.
|
|
115
|
+
}
|
|
116
|
+
await this.writer.flush();
|
|
117
|
+
this.unsub?.();
|
|
118
|
+
this.writer.close();
|
|
119
|
+
}
|
|
120
|
+
// -- command handling ------------------------------------------------------
|
|
121
|
+
async handleLine(line) {
|
|
122
|
+
let json;
|
|
123
|
+
try {
|
|
124
|
+
json = JSON.parse(line);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
this.respondError(null, "parse", { code: "PARSE_ERROR", message: "invalid JSON line" });
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const parsed = CommandSchema.safeParse(json);
|
|
131
|
+
if (!parsed.success) {
|
|
132
|
+
const id = idOf(json);
|
|
133
|
+
const type = json?.type;
|
|
134
|
+
const unknown = typeof type !== "string" || !KNOWN_TYPES.has(type);
|
|
135
|
+
this.respondError(id, "parse", {
|
|
136
|
+
code: unknown ? "UNKNOWN_COMMAND" : "BAD_REQUEST",
|
|
137
|
+
message: parsed.error.issues[0]?.message ?? "invalid command",
|
|
138
|
+
});
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const cmd = parsed.data;
|
|
142
|
+
// `prompt` is long-running — fire-and-forget so the loop keeps reading
|
|
143
|
+
// `abort` / `permission_response` mid-turn. It emits its own `result`.
|
|
144
|
+
if (cmd.type === "prompt") {
|
|
145
|
+
// Fire-and-forget so the loop keeps reading abort/permission mid-turn,
|
|
146
|
+
// but track the promise so shutdown can await the terminal `result`
|
|
147
|
+
// (Round-2 M1). handlePrompt never rejects (it catches internally).
|
|
148
|
+
this.activePrompt = this.handlePrompt(cmd).finally(() => {
|
|
149
|
+
this.activePrompt = null;
|
|
150
|
+
});
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
await this.dispatch(cmd);
|
|
154
|
+
}
|
|
155
|
+
async dispatch(cmd) {
|
|
156
|
+
switch (cmd.type) {
|
|
157
|
+
case "abort":
|
|
158
|
+
// Deny pending permissions FIRST so a turn parked in the resolver
|
|
159
|
+
// unwinds, then cancel the token (Round-1 M2).
|
|
160
|
+
this.denyAllPending();
|
|
161
|
+
this.activeTurn?.cts.cancel();
|
|
162
|
+
this.respondOk(cmd.id, "abort");
|
|
163
|
+
return;
|
|
164
|
+
case "set_model":
|
|
165
|
+
if (this.activeTurn) {
|
|
166
|
+
this.respondError(cmd.id ?? null, "set_model", {
|
|
167
|
+
code: "AGENT_BUSY",
|
|
168
|
+
message: "cannot switch model while a turn is running",
|
|
169
|
+
});
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
this.built?.selection.set({ provider: cmd.provider, model: cmd.model });
|
|
173
|
+
this.respondOk(cmd.id, "set_model", this.built?.selection.get() ?? {});
|
|
174
|
+
return;
|
|
175
|
+
case "get_state":
|
|
176
|
+
this.respondOk(cmd.id, "get_state", {
|
|
177
|
+
model: this.built?.selection.get() ?? {},
|
|
178
|
+
busy: this.activeTurn !== null,
|
|
179
|
+
sessionId: this.built?.sessionId ?? "",
|
|
180
|
+
toolChunks: this.toolChunks,
|
|
181
|
+
});
|
|
182
|
+
return;
|
|
183
|
+
case "get_models":
|
|
184
|
+
this.respondOk(cmd.id, "get_models", { models: this.host.listModels() });
|
|
185
|
+
return;
|
|
186
|
+
case "permission_response":
|
|
187
|
+
this.resolvePermission(cmd.id, cmd.allow, cmd.remember);
|
|
188
|
+
return; // no response frame — it's a reply, not a request
|
|
189
|
+
case "set_options":
|
|
190
|
+
if (cmd.toolChunks !== undefined)
|
|
191
|
+
this.toolChunks = cmd.toolChunks;
|
|
192
|
+
this.respondOk(cmd.id, "set_options", { toolChunks: this.toolChunks });
|
|
193
|
+
return;
|
|
194
|
+
case "ping":
|
|
195
|
+
this.respondOk(cmd.id, "ping");
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
async handlePrompt(cmd) {
|
|
200
|
+
if (this.activeTurn) {
|
|
201
|
+
this.respondError(cmd.id ?? null, "prompt", {
|
|
202
|
+
code: "AGENT_BUSY",
|
|
203
|
+
message: "a turn is already running",
|
|
204
|
+
});
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
const cts = new CancellationTokenSource();
|
|
208
|
+
this.activeTurn = { cts, commandId: cmd.id };
|
|
209
|
+
this.respondOk(cmd.id, "prompt"); // ack now; completion is the `result` frame (C6)
|
|
210
|
+
let result = { text: "", inputTokens: 0, outputTokens: 0, costUsd: 0 };
|
|
211
|
+
let stopReason = "end";
|
|
212
|
+
try {
|
|
213
|
+
result = await this.built.runTurn(cmd.text, cts.token);
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
// Non-cancel engine errors already emitted an `error` bus frame before
|
|
217
|
+
// throwing; cancellation is user-initiated, not an error to re-surface.
|
|
218
|
+
stopReason = cts.token.isCancelled ? "cancelled" : "error";
|
|
219
|
+
}
|
|
220
|
+
finally {
|
|
221
|
+
this.activeTurn = null;
|
|
222
|
+
}
|
|
223
|
+
this.writer.enqueue({
|
|
224
|
+
type: "result",
|
|
225
|
+
commandId: cmd.id,
|
|
226
|
+
text: result.text,
|
|
227
|
+
usage: {
|
|
228
|
+
inputTokens: result.inputTokens,
|
|
229
|
+
outputTokens: result.outputTokens,
|
|
230
|
+
costUsd: result.costUsd,
|
|
231
|
+
},
|
|
232
|
+
stopReason,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
// -- permission round-trip -------------------------------------------------
|
|
236
|
+
makeResolver() {
|
|
237
|
+
return (req) => {
|
|
238
|
+
// (5.10b) Narrow the union before reading authorization-only fields
|
|
239
|
+
// (`summary`/`args`/`cacheKey`). No remote question UI yet — the channel
|
|
240
|
+
// is ready, the host frame is a follow-up; a question declines for now.
|
|
241
|
+
if (req.kind === "question") {
|
|
242
|
+
const declined = { kind: "question", answers: {}, declined: true };
|
|
243
|
+
return Promise.resolve(declined);
|
|
244
|
+
}
|
|
245
|
+
if (this.autoApprove)
|
|
246
|
+
return Promise.resolve({ allow: true, remember: true });
|
|
247
|
+
const id = createId("perm");
|
|
248
|
+
return new Promise((resolve) => {
|
|
249
|
+
this.pending.set(id, resolve);
|
|
250
|
+
this.writer.enqueue({
|
|
251
|
+
type: "request_permission",
|
|
252
|
+
id,
|
|
253
|
+
callId: req.callId,
|
|
254
|
+
tool: req.name,
|
|
255
|
+
category: req.category,
|
|
256
|
+
summary: req.summary,
|
|
257
|
+
args: req.args,
|
|
258
|
+
cacheKey: req.cacheKey,
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
resolvePermission(id, allow, remember) {
|
|
264
|
+
if (this.resolvedSet.has(id))
|
|
265
|
+
return; // dedup orphan/duplicate (C7)
|
|
266
|
+
const resolve = this.pending.get(id);
|
|
267
|
+
if (!resolve)
|
|
268
|
+
return; // unknown id — ignore
|
|
269
|
+
this.pending.delete(id);
|
|
270
|
+
this.markResolved(id);
|
|
271
|
+
resolve({ allow, remember });
|
|
272
|
+
}
|
|
273
|
+
/** Resolve every outstanding permission with deny — unblocks a turn parked
|
|
274
|
+
* in the resolver on `abort` / shutdown (Round-1 M2). */
|
|
275
|
+
denyAllPending() {
|
|
276
|
+
for (const [id, resolve] of this.pending) {
|
|
277
|
+
this.markResolved(id);
|
|
278
|
+
resolve({ allow: false });
|
|
279
|
+
}
|
|
280
|
+
this.pending.clear();
|
|
281
|
+
}
|
|
282
|
+
markResolved(id) {
|
|
283
|
+
this.resolvedSet.add(id);
|
|
284
|
+
this.resolvedIds.push(id);
|
|
285
|
+
if (this.resolvedIds.length > MAX_RESOLVED_IDS) {
|
|
286
|
+
const evicted = this.resolvedIds.shift();
|
|
287
|
+
this.resolvedSet.delete(evicted);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
// -- response helpers ------------------------------------------------------
|
|
291
|
+
respondOk(id, command, data) {
|
|
292
|
+
this.writer.enqueue({ type: "response", id: id ?? null, command, ok: true, data: data });
|
|
293
|
+
}
|
|
294
|
+
respondError(id, command, error) {
|
|
295
|
+
this.writer.enqueue({ type: "response", id, command, ok: false, error });
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
function idOf(json) {
|
|
299
|
+
const id = json?.id;
|
|
300
|
+
return typeof id === "string" ? id : null;
|
|
301
|
+
}
|
|
302
|
+
function delay(ms) {
|
|
303
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
304
|
+
}
|
|
305
|
+
//# sourceMappingURL=rpc-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc-server.js","sourceRoot":"","sources":["../../src/rpc/rpc-server.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,yEAAyE;AACzE,2EAA2E;AAC3E,8EAA8E;AAC9E,+EAA+E;AAC/E,2EAA2E;AAC3E,sEAAsE;AACtE,kDAAkD;AAElD,OAAO,EAAE,uBAAuB,EAAE,QAAQ,EAAiB,MAAM,qBAAqB,CAAC;AAGvF,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,EACL,aAAa,EACb,aAAa,EACb,gBAAgB,GAKjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAc;IACvC,QAAQ;IACR,OAAO;IACP,WAAW;IACX,WAAW;IACX,YAAY;IACZ,qBAAqB;IACrB,aAAa;IACb,MAAM;CACP,CAAC,CAAC;AAEH,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAC9B;6CAC6C;AAC7C,MAAM,yBAAyB,GAAG,KAAK,CAAC;AAexC,MAAM,OAAO,SAAS;IACH,IAAI,CAAa;IACjB,MAAM,CAAsB;IAC5B,KAAK,CAAoC;IACzC,WAAW,CAAU;IAC9B,UAAU,CAAU;IACX,OAAO,CAAyB;IAEzC,KAAK,GAAuB,IAAI,CAAC;IACjC,KAAK,GAAwB,IAAI,CAAC;IAClC,UAAU,GAAgE,IAAI,CAAC;IACvF;;0CAEsC;IAC9B,YAAY,GAAyB,IAAI,CAAC;IACjC,OAAO,GAAG,IAAI,GAAG,EAA2C,CAAC;IAC7D,WAAW,GAAa,EAAE,CAAC;IAC3B,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IACzC,YAAY,GAAG,KAAK,CAAC;IAE7B,YAAY,IAAsB;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC;QAC7C,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC;QAC1C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,iFAAiF;IACjF,KAAK,CAAC,GAAG,CAAC,KAA4B;QACpC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QACnD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QAEnB,0EAA0E;QAC1E,0EAA0E;QAC1E,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAW,EAAE,EAAE;YAC3C,IAAI,CAAC,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBACrB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC;gBAC5C,OAAO;YACT,CAAC;YACD,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;YAC3D,IAAI,CAAC,KAAK;gBAAE,OAAO;YACnB,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY;gBAAE,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC;YAC9E,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;YAClB,IAAI,EAAE,OAAO;YACb,QAAQ,EAAE,aAAa;YACvB,OAAO,EAAE,gBAAgB;YACzB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YAC9B,YAAY,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE;SACvF,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC5B,IAAI,OAAO,KAAK,EAAE;oBAAE,SAAS;gBAC7B,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACxB,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC;IAED;;;gBAGY;IACZ,KAAK,CAAC,QAAQ;QACZ,IAAI,IAAI,CAAC,YAAY;YAAE,OAAO;QAC9B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;QAC9B,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,yEAAyE;QACzE,yEAAyE;QACzE,wEAAwE;QACxE,0EAA0E;QAC1E,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC;QAC5E,CAAC;QACD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,wDAAwD;QAC1D,CAAC;QACD,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC1B,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;QACf,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;IAED,6EAA6E;IAErE,KAAK,CAAC,UAAU,CAAC,IAAY;QACnC,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC;YACxF,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,aAAa,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;YACtB,MAAM,IAAI,GAAI,IAA2B,EAAE,IAAI,CAAC;YAChD,MAAM,OAAO,GAAG,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAmB,CAAC,CAAC;YAClF,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,OAAO,EAAE;gBAC7B,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,aAAa;gBACjD,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,iBAAiB;aAC9D,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC;QACxB,uEAAuE;QACvE,uEAAuE;QACvE,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC1B,uEAAuE;YACvE,oEAAoE;YACpE,oEAAoE;YACpE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;gBACtD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;YAC3B,CAAC,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,GAAyC;QAC9D,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;YACjB,KAAK,OAAO;gBACV,kEAAkE;gBAClE,+CAA+C;gBAC/C,IAAI,CAAC,cAAc,EAAE,CAAC;gBACtB,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;gBAC9B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;gBAChC,OAAO;YACT,KAAK,WAAW;gBACd,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;oBACpB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,IAAI,IAAI,EAAE,WAAW,EAAE;wBAC7C,IAAI,EAAE,YAAY;wBAClB,OAAO,EAAE,6CAA6C;qBACvD,CAAC,CAAC;oBACH,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;gBACxE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;gBACvE,OAAO;YACT,KAAK,WAAW;gBACd,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,WAAW,EAAE;oBAClC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE;oBACxC,IAAI,EAAE,IAAI,CAAC,UAAU,KAAK,IAAI;oBAC9B,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE;oBACtC,UAAU,EAAE,IAAI,CAAC,UAAU;iBAC5B,CAAC,CAAC;gBACH,OAAO;YACT,KAAK,YAAY;gBACf,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;gBACzE,OAAO;YACT,KAAK,qBAAqB;gBACxB,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACxD,OAAO,CAAC,kDAAkD;YAC5D,KAAK,aAAa;gBAChB,IAAI,GAAG,CAAC,UAAU,KAAK,SAAS;oBAAE,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC;gBACnE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,aAAa,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;gBACvE,OAAO;YACT,KAAK,MAAM;gBACT,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;gBAC/B,OAAO;QACX,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,GAAyC;QAClE,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,IAAI,IAAI,EAAE,QAAQ,EAAE;gBAC1C,IAAI,EAAE,YAAY;gBAClB,OAAO,EAAE,2BAA2B;aACrC,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,uBAAuB,EAAE,CAAC;QAC1C,IAAI,CAAC,UAAU,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;QAC7C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,iDAAiD;QAEnF,IAAI,MAAM,GAAgB,EAAE,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;QACpF,IAAI,UAAU,GAAe,KAAK,CAAC;QACnC,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,IAAI,CAAC,KAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;QAC1D,CAAC;QAAC,MAAM,CAAC;YACP,uEAAuE;YACvE,wEAAwE;YACxE,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC;QAC7D,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;YAClB,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,GAAG,CAAC,EAAE;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,KAAK,EAAE;gBACL,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,YAAY,EAAE,MAAM,CAAC,YAAY;gBACjC,OAAO,EAAE,MAAM,CAAC,OAAO;aACxB;YACD,UAAU;SACX,CAAC,CAAC;IACL,CAAC;IAED,6EAA6E;IAErE,YAAY;QAClB,OAAO,CAAC,GAAG,EAAE,EAAE;YACb,oEAAoE;YACpE,yEAAyE;YACzE,wEAAwE;YACxE,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC5B,MAAM,QAAQ,GAAuB,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;gBACvF,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACnC,CAAC;YACD,IAAI,IAAI,CAAC,WAAW;gBAAE,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9E,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC5B,OAAO,IAAI,OAAO,CAAqB,CAAC,OAAO,EAAE,EAAE;gBACjD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;gBAC9B,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;oBAClB,IAAI,EAAE,oBAAoB;oBAC1B,EAAE;oBACF,MAAM,EAAE,GAAG,CAAC,MAAM;oBAClB,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,QAAQ,EAAE,GAAG,CAAC,QAAQ;oBACtB,OAAO,EAAE,GAAG,CAAC,OAAO;oBACpB,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,QAAQ,EAAE,GAAG,CAAC,QAAQ;iBACvB,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;IACJ,CAAC;IAEO,iBAAiB,CAAC,EAAU,EAAE,KAAc,EAAE,QAAkB;QACtE,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,OAAO,CAAC,8BAA8B;QACpE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrC,IAAI,CAAC,OAAO;YAAE,OAAO,CAAC,sBAAsB;QAC5C,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACxB,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACtB,OAAO,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED;6DACyD;IACjD,cAAc;QACpB,KAAK,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACzC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YACtB,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5B,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAEO,YAAY,CAAC,EAAU;QAC7B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACzB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1B,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;YAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,EAAG,CAAC;YAC1C,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,6EAA6E;IAErE,SAAS,CAAC,EAAsB,EAAE,OAAoB,EAAE,IAAc;QAC5E,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAa,EAAE,CAAC,CAAC;IACpG,CAAC;IAEO,YAAY,CAAC,EAAiB,EAAE,OAA8B,EAAE,KAAe;QACrF,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3E,CAAC;CACF;AAED,SAAS,IAAI,CAAC,IAAa;IACzB,MAAM,EAAE,GAAI,IAAyB,EAAE,EAAE,CAAC;IAC1C,OAAO,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5C,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdout-guard.d.ts","sourceRoot":"","sources":["../../src/rpc/stdout-guard.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,WAAW;IAC1B,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,wBAAgB,kBAAkB,IAAI,WAAW,CAuBhD"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// stdout purity guard (codex C5 + Round-1 S2). stdout carries ONLY protocol
|
|
2
|
+
// frames; a single stray `console.log` from a dependency would corrupt the
|
|
3
|
+
// client's NDJSON parser. Redirect the stdout-writing console methods to
|
|
4
|
+
// stderr for the server's lifetime. `restore()` is idempotent and must run in
|
|
5
|
+
// a `finally` so a thrown server (or an embedding test) can't leak the
|
|
6
|
+
// override. The bus `log` event is routed to stderr by the server, not here.
|
|
7
|
+
export function installStdoutGuard() {
|
|
8
|
+
// Save the ORIGINAL references (not `.bind` copies) so `restore()` puts the
|
|
9
|
+
// exact same functions back — identity matters for embedders/tests.
|
|
10
|
+
const saved = {
|
|
11
|
+
log: console.log,
|
|
12
|
+
info: console.info,
|
|
13
|
+
debug: console.debug,
|
|
14
|
+
};
|
|
15
|
+
const toErr = (...args) => console.error(...args);
|
|
16
|
+
console.log = toErr;
|
|
17
|
+
console.info = toErr;
|
|
18
|
+
console.debug = toErr;
|
|
19
|
+
let restored = false;
|
|
20
|
+
return {
|
|
21
|
+
restore() {
|
|
22
|
+
if (restored)
|
|
23
|
+
return;
|
|
24
|
+
restored = true;
|
|
25
|
+
console.log = saved.log;
|
|
26
|
+
console.info = saved.info;
|
|
27
|
+
console.debug = saved.debug;
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=stdout-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdout-guard.js","sourceRoot":"","sources":["../../src/rpc/stdout-guard.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,2EAA2E;AAC3E,yEAAyE;AACzE,8EAA8E;AAC9E,uEAAuE;AACvE,6EAA6E;AAQ7E,MAAM,UAAU,kBAAkB;IAChC,4EAA4E;IAC5E,oEAAoE;IACpE,MAAM,KAAK,GAAsE;QAC/E,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC;IACF,MAAM,KAAK,GAAkB,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,GAAG,KAAK,CAAC;IACpB,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC;IACrB,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;IAEtB,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,OAAO;QACL,OAAO;YACL,IAAI,QAAQ;gBAAE,OAAO;YACrB,QAAQ,GAAG,IAAI,CAAC;YAChB,OAAO,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;YACxB,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;YAC1B,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAC9B,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ServerFrame } from "./protocol.js";
|
|
2
|
+
/** The subset of a Node Writable the writer needs. `process.stdout` satisfies
|
|
3
|
+
* it; tests inject an in-memory sink. */
|
|
4
|
+
export interface ByteSink {
|
|
5
|
+
write(chunk: string): boolean;
|
|
6
|
+
once(event: "drain", listener: () => void): void;
|
|
7
|
+
}
|
|
8
|
+
export interface WriterOptions {
|
|
9
|
+
/** Frames; past this the writer warns (once per stall episode) to stderr. */
|
|
10
|
+
highWaterMark?: number;
|
|
11
|
+
/** Sink for the high-water warning (defaults to a `process.stderr` write). */
|
|
12
|
+
warn?: (message: string) => void;
|
|
13
|
+
}
|
|
14
|
+
export declare class BoundedNdjsonWriter<T = ServerFrame> {
|
|
15
|
+
private readonly sink;
|
|
16
|
+
private readonly opts;
|
|
17
|
+
private readonly queue;
|
|
18
|
+
private draining;
|
|
19
|
+
private closed;
|
|
20
|
+
private warnedHighWater;
|
|
21
|
+
private readonly flushWaiters;
|
|
22
|
+
constructor(sink: ByteSink, opts?: WriterOptions);
|
|
23
|
+
/** Serialise + enqueue a frame. Synchronous (callable from a sync bus
|
|
24
|
+
* handler); the async drain loop does the actual writing. The type param
|
|
25
|
+
* lets the bespoke transport keep `ServerFrame` (the default) while the M3
|
|
26
|
+
* ACP transport enqueues JSON-RPC messages through the SAME bounded queue. */
|
|
27
|
+
enqueue(frame: T): void;
|
|
28
|
+
private drain;
|
|
29
|
+
/** Resolves once the queue has fully drained (or the writer is closed). */
|
|
30
|
+
flush(): Promise<void>;
|
|
31
|
+
/** Stop accepting + draining frames (transport closing). */
|
|
32
|
+
close(): void;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writer.d.ts","sourceRoot":"","sources":["../../src/rpc/writer.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD;yCACyC;AACzC,MAAM,WAAW,QAAQ;IACvB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;CAClD;AAED,MAAM,WAAW,aAAa;IAC5B,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8EAA8E;IAC9E,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAID,qBAAa,mBAAmB,CAAC,CAAC,GAAG,WAAW;IAQ5C,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI;IARvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAyB;gBAGnC,IAAI,EAAE,QAAQ,EACd,IAAI,GAAE,aAAkB;IAG3C;;;kFAG8E;IAC9E,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI;YAaT,KAAK;IA2BnB,2EAA2E;IACrE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B,4DAA4D;IAC5D,KAAK,IAAI,IAAI;CAMd"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Single bounded FIFO writer (codex C4 + Round-1 S1). Every outbound frame
|
|
2
|
+
// goes through one ordered queue, so a `response` / `request_permission` can
|
|
3
|
+
// never overtake a queued `assistant_delta`, and the drain loop respects the
|
|
4
|
+
// sink's backpressure (`write()` → false → await "drain"). Fixes the
|
|
5
|
+
// sync-unawaited-write flaw in pi/oh-my-pi. Never drops a frame; a stalled
|
|
6
|
+
// client grows the in-memory queue and trips a re-armable stderr warning past
|
|
7
|
+
// a high-water mark (no silent cap).
|
|
8
|
+
const DEFAULT_HIGH_WATER = 10_000;
|
|
9
|
+
export class BoundedNdjsonWriter {
|
|
10
|
+
sink;
|
|
11
|
+
opts;
|
|
12
|
+
queue = [];
|
|
13
|
+
draining = false;
|
|
14
|
+
closed = false;
|
|
15
|
+
warnedHighWater = false;
|
|
16
|
+
flushWaiters = [];
|
|
17
|
+
constructor(sink, opts = {}) {
|
|
18
|
+
this.sink = sink;
|
|
19
|
+
this.opts = opts;
|
|
20
|
+
}
|
|
21
|
+
/** Serialise + enqueue a frame. Synchronous (callable from a sync bus
|
|
22
|
+
* handler); the async drain loop does the actual writing. The type param
|
|
23
|
+
* lets the bespoke transport keep `ServerFrame` (the default) while the M3
|
|
24
|
+
* ACP transport enqueues JSON-RPC messages through the SAME bounded queue. */
|
|
25
|
+
enqueue(frame) {
|
|
26
|
+
if (this.closed)
|
|
27
|
+
return;
|
|
28
|
+
this.queue.push(JSON.stringify(frame) + "\n");
|
|
29
|
+
const hwm = this.opts.highWaterMark ?? DEFAULT_HIGH_WATER;
|
|
30
|
+
if (this.queue.length > hwm && !this.warnedHighWater) {
|
|
31
|
+
this.warnedHighWater = true;
|
|
32
|
+
(this.opts.warn ?? defaultWarn)(`rpc: outbound queue exceeded ${hwm} frames — client may be stalled; not dropping`);
|
|
33
|
+
}
|
|
34
|
+
void this.drain();
|
|
35
|
+
}
|
|
36
|
+
async drain() {
|
|
37
|
+
if (this.draining)
|
|
38
|
+
return;
|
|
39
|
+
this.draining = true;
|
|
40
|
+
try {
|
|
41
|
+
while (this.queue.length > 0 && !this.closed) {
|
|
42
|
+
const line = this.queue.shift();
|
|
43
|
+
let ok;
|
|
44
|
+
try {
|
|
45
|
+
ok = this.sink.write(line);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// EPIPE / sink gone — stop writing, drop the rest cleanly.
|
|
49
|
+
this.closed = true;
|
|
50
|
+
this.queue.length = 0;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
if (!ok && !this.closed) {
|
|
54
|
+
await new Promise((resolve) => this.sink.once("drain", resolve));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
this.draining = false;
|
|
60
|
+
if (this.queue.length === 0)
|
|
61
|
+
this.warnedHighWater = false; // re-arm
|
|
62
|
+
const waiters = this.flushWaiters.splice(0);
|
|
63
|
+
for (const w of waiters)
|
|
64
|
+
w();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** Resolves once the queue has fully drained (or the writer is closed). */
|
|
68
|
+
async flush() {
|
|
69
|
+
if (this.closed || (this.queue.length === 0 && !this.draining))
|
|
70
|
+
return;
|
|
71
|
+
await new Promise((resolve) => this.flushWaiters.push(resolve));
|
|
72
|
+
}
|
|
73
|
+
/** Stop accepting + draining frames (transport closing). */
|
|
74
|
+
close() {
|
|
75
|
+
this.closed = true;
|
|
76
|
+
this.queue.length = 0;
|
|
77
|
+
const waiters = this.flushWaiters.splice(0);
|
|
78
|
+
for (const w of waiters)
|
|
79
|
+
w();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function defaultWarn(message) {
|
|
83
|
+
process.stderr.write(message + "\n");
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writer.js","sourceRoot":"","sources":["../../src/rpc/writer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* (v20 M3 / docs/6.4a §3; v21 M4 lease / docs/6.5 §5) `AcpSessionHost` — the ACP
|
|
3
|
+
* twin of the bespoke session host. ONE persistent engine session per process,
|
|
4
|
+
* sockets attach/detach over a seq-stamping `ReplayHub` fan-out; the inner engine
|
|
5
|
+
* is the `AcpEngineDriver` (ACP JSON-RPC wire).
|
|
6
|
+
*
|
|
7
|
+
* Two deliberate differences from the M2 design:
|
|
8
|
+
* 1. **State source.** The reconnect snapshot (`busy` / `pendingPermissionIds`)
|
|
9
|
+
* is read straight off the driver (authoritative). The `ReplayHub` stays a
|
|
10
|
+
* pure payload-agnostic seq/replay/fan-out layer — it does NOT parse the
|
|
11
|
+
* outbound bytes for session state (a byte-snoop lived there in the
|
|
12
|
+
* chances-rpc era; removed with the M3 hard cutover, since ACP frames' first
|
|
13
|
+
* key is `jsonrpc`/`rseq`, never `type`).
|
|
14
|
+
* 2. **No `ready` re-send.** ACP is client-initiated: a fresh client sends
|
|
15
|
+
* `initialize`/`session/new` and the driver replies; a cold-reloaded client
|
|
16
|
+
* re-initializes (client-core, c4).
|
|
17
|
+
*
|
|
18
|
+
* **Controller lease (v21 M4 §5).** Disabled by default ⇒ fan-out: any paired
|
|
19
|
+
* device drives, the engine serializes turns via `AGENT_BUSY` (the M2 model).
|
|
20
|
+
* When enabled, this host gates every inbound command by its source clientId —
|
|
21
|
+
* only the lease HOLDER may drive (`session/prompt`/`cancel`), answer a
|
|
22
|
+
* permission, or change the model; everyone else is a read-only VIEWER and gets a
|
|
23
|
+
* typed `not_controller`. `_chances/unstable/take_control` hands control over
|
|
24
|
+
* (any authed client may claim it — single-user multi-device) and bumps
|
|
25
|
+
* `controlEpoch`; the new holder + epoch are broadcast as a
|
|
26
|
+
* `_chances/unstable/control` notification. The gate lives HERE (it needs the
|
|
27
|
+
* socket→clientId map) so the driver stays a protocol-pure turn runner.
|
|
28
|
+
*
|
|
29
|
+
* **Threat model (codex M4-review).** The lease is COORDINATION among one user's
|
|
30
|
+
* equally-authed devices, NOT an authorization boundary. The security boundary is
|
|
31
|
+
* the pairing token (every connection is already token-authed); `clientId` is a
|
|
32
|
+
* self-reported coordination tag, not a trusted identity. A device could spoof
|
|
33
|
+
* another's clientId to "impersonate" the holder — but it gains nothing
|
|
34
|
+
* `take_control` doesn't already grant (any authed client may claim control), so
|
|
35
|
+
* there is no privilege escalation among your own devices. A truly-restricted
|
|
36
|
+
* viewer (read-only access shared with a THIRD party) needs server-issued identity
|
|
37
|
+
* and belongs to the multi-tenant Team era — out of scope here.
|
|
38
|
+
*
|
|
39
|
+
* The seq/replay layer (`ReplayHub`) is reused UNCHANGED — it stamps `rseq` on
|
|
40
|
+
* the serialized ACP JSON-RPC bytes (payload-agnostic, docs/6.2 §3.2).
|
|
41
|
+
*/
|
|
42
|
+
import { type EngineHost } from "../rpc/index.js";
|
|
43
|
+
import { type ReplayHubOptions } from "./replay-hub.js";
|
|
44
|
+
import { type ServerSocket } from "./ws-transport.js";
|
|
45
|
+
export interface AcpSessionHostOptions {
|
|
46
|
+
host: EngineHost;
|
|
47
|
+
agent: {
|
|
48
|
+
name: string;
|
|
49
|
+
version: string;
|
|
50
|
+
};
|
|
51
|
+
/** Auto-approve every tool permission (trusted automation). Default false. */
|
|
52
|
+
autoApprove?: boolean;
|
|
53
|
+
/** stderr-style sink for routed `log` events + writer diagnostics. */
|
|
54
|
+
logSink?: (line: string) => void;
|
|
55
|
+
/** Replay ring depth (frames). Default {@link ReplayHub}'s. */
|
|
56
|
+
ring?: ReplayHubOptions;
|
|
57
|
+
/** (v21 M4 §5) Enable the single-controller lease. Default false ⇒ fan-out
|
|
58
|
+
* (any paired device drives; the engine serializes turns via AGENT_BUSY). */
|
|
59
|
+
controllerLease?: boolean;
|
|
60
|
+
}
|
|
61
|
+
export interface AcpAttachment {
|
|
62
|
+
/** Per-attach fencing token (forward-compat; not enforced on the M3 WS — the
|
|
63
|
+
* fan-out has no exclusive lock to fence). */
|
|
64
|
+
epoch: number;
|
|
65
|
+
/** Remove this socket from the fan-out. Idempotent; does NOT end the session. */
|
|
66
|
+
detach(): void;
|
|
67
|
+
}
|
|
68
|
+
export declare class AcpSessionHost {
|
|
69
|
+
private readonly hub;
|
|
70
|
+
private readonly queue;
|
|
71
|
+
private readonly driver;
|
|
72
|
+
private readonly host;
|
|
73
|
+
private readonly done;
|
|
74
|
+
private epochCounter;
|
|
75
|
+
private shuttingDown;
|
|
76
|
+
private readonly leaseEnabled;
|
|
77
|
+
private holder;
|
|
78
|
+
private controlEpoch;
|
|
79
|
+
/** clientId → socket, for TARGETED lease replies (not_controller / ack). */
|
|
80
|
+
private readonly socketsByClient;
|
|
81
|
+
constructor(opts: AcpSessionHostOptions);
|
|
82
|
+
/**
|
|
83
|
+
* Attach a socket, synchronously replaying everything since `lastSeq` then
|
|
84
|
+
* going live (same disjoint-and-ordered guarantee as the M2 host). `clientId`
|
|
85
|
+
* (from the `?client_id=` connect query) attributes this socket for the lease.
|
|
86
|
+
* Wire order: `relay_welcome` → replayed gap → re-sent open permissions → [live].
|
|
87
|
+
*/
|
|
88
|
+
attach(socket: ServerSocket, lastSeq: number, clientId?: string): AcpAttachment;
|
|
89
|
+
/**
|
|
90
|
+
* One inbound text message (ACP JSON-RPC). Split LF-batched lines; each line
|
|
91
|
+
* passes the lease {@link gate} (a no-op when the lease is disabled) before
|
|
92
|
+
* reaching the ONE persistent queue. `fromClientId` (the attach's clientId)
|
|
93
|
+
* attributes the command to a client for the lease.
|
|
94
|
+
*/
|
|
95
|
+
onMessage(text: string, fromClientId?: string): void;
|
|
96
|
+
/** Answer one read-only workspace query: dispatch to the host's query
|
|
97
|
+
* primitives and `replyTo` the originating socket only (off-ring). Needs an id
|
|
98
|
+
* (to respond) and a clientId (to target); a query missing either is dropped
|
|
99
|
+
* (a conformant client always sends both). */
|
|
100
|
+
private handleQuery;
|
|
101
|
+
/**
|
|
102
|
+
* Controller-lease gate. Returns true ⇒ the line may proceed to the driver;
|
|
103
|
+
* false ⇒ the host handled it (a handoff) or rejected it (a viewer's privileged
|
|
104
|
+
* command — a `not_controller` reply was sent to the source). A no-op (always
|
|
105
|
+
* true) when the lease is disabled.
|
|
106
|
+
*/
|
|
107
|
+
private gate;
|
|
108
|
+
/** Broadcast the current lease state to every socket (stamped + fanned out). */
|
|
109
|
+
private broadcastControlState;
|
|
110
|
+
/** Send a single frame to ONE client (targeted; not fanned out, not stamped). */
|
|
111
|
+
private replyTo;
|
|
112
|
+
get headSeq(): number;
|
|
113
|
+
get socketCount(): number;
|
|
114
|
+
get busy(): boolean;
|
|
115
|
+
/** Current lease holder (clientId) or null. Exposed for tests/diagnostics. */
|
|
116
|
+
get controllerHolder(): string | null;
|
|
117
|
+
/** End the persistent queue → `run` returns → graceful driver shutdown. */
|
|
118
|
+
shutdown(): Promise<number>;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=acp-session-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acp-session-host.d.ts","sourceRoot":"","sources":["../../src/serve/acp-session-host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAKL,KAAK,UAAU,EAEhB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAWpE,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,8EAA8E;IAC9E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,sEAAsE;IACtE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,+DAA+D;IAC/D,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB;kFAC8E;IAC9E,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B;mDAC+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,MAAM,IAAI,IAAI,CAAC;CAChB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAY;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAsB;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAkB;IACvC,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,YAAY,CAAS;IAG7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;IACvC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,YAAY,CAAK;IACzB,4EAA4E;IAC5E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAmC;gBAEvD,IAAI,EAAE,qBAAqB;IAoBvC;;;;;OAKG;IACH,MAAM,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,aAAa;IAwC/E;;;;;OAKG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI;IAkBpD;;;mDAG+C;YACjC,WAAW;IASzB;;;;;OAKG;IACH,OAAO,CAAC,IAAI;IAuCZ,gFAAgF;IAChF,OAAO,CAAC,qBAAqB;IAK7B,iFAAiF;IACjF,OAAO,CAAC,OAAO;IAKf,IAAI,OAAO,IAAI,MAAM,CAEpB;IACD,IAAI,WAAW,IAAI,MAAM,CAExB;IACD,IAAI,IAAI,IAAI,OAAO,CAElB;IACD,8EAA8E;IAC9E,IAAI,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAEpC;IAED,2EAA2E;IACrE,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC;CAOlC"}
|