@jobshimo/browser-link 0.7.9 → 0.7.13

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.
@@ -1,470 +0,0 @@
1
- import { connect } from 'node:net';
2
- import { createInterface } from 'node:readline';
3
- import { IPC_HOST, IPC_PORT, IPC_PROTOCOL_VERSION, encodeFrame, parseFrame, } from './protocol.js';
4
- import { readToken } from './token.js';
5
- /**
6
- * Proxy's side of the IPC bridge. The proxy is a thin browser-link process
7
- * spawned by an MCP client (Claude / Copilot / OpenCode) that finds the WS
8
- * port already taken — it forwards every MCP frame it gets on stdin to the
9
- * primary via the IPC socket, and pipes responses back to stdout.
10
- *
11
- * Two flavours:
12
- * - IpcClient is the bare connection (used by tests and re-election).
13
- * - runProxy() wires IpcClient to stdin/stdout so the MCP client thinks
14
- * it is talking to a real server.
15
- */
16
- function log(msg) {
17
- console.error(`[browser-link proxy] ${msg}`);
18
- }
19
- /** Raised when the proxy cannot complete the IPC handshake. */
20
- export class HandshakeError extends Error {
21
- constructor(message) {
22
- super(message);
23
- this.name = 'HandshakeError';
24
- }
25
- }
26
- /** Minimal IPC client. Owns the TCP socket, handles framing, runs the
27
- * handshake, dispatches mcp.response frames back to whoever sent the
28
- * matching mcp.request. */
29
- export class IpcClient {
30
- socket = null;
31
- buffer = '';
32
- nextRequestId = 1;
33
- pendingRequests = new Map();
34
- closeListeners = [];
35
- notificationListeners = [];
36
- closed = false;
37
- /** Open the TCP connection, perform the handshake, and resolve with the
38
- * session info from the primary's hello-ack. On any handshake failure,
39
- * rejects with HandshakeError and tears down the socket. */
40
- async connect(token, opts = {}) {
41
- const host = opts.host ?? IPC_HOST;
42
- const port = opts.port ?? IPC_PORT;
43
- const handshakeTimeoutMs = opts.handshakeTimeoutMs ?? 4000;
44
- const socket = await new Promise((resolve, reject) => {
45
- const s = connect({ host, port });
46
- s.once('connect', () => {
47
- resolve(s);
48
- });
49
- s.once('error', (err) => {
50
- reject(err);
51
- });
52
- });
53
- this.socket = socket;
54
- socket.on('data', (chunk) => {
55
- this.ingest(chunk);
56
- });
57
- socket.on('close', () => {
58
- this.onSocketClose('remote');
59
- });
60
- socket.on('error', (err) => {
61
- log(`Socket error: ${err.message}`);
62
- });
63
- // Send hello, wait for ack or reject or timeout.
64
- const ack = await new Promise((resolve, reject) => {
65
- const timer = setTimeout(() => {
66
- reject(new HandshakeError('Handshake timed out — primary did not reply.'));
67
- }, handshakeTimeoutMs);
68
- const onFirstFrame = (frame) => {
69
- clearTimeout(timer);
70
- if (frame.kind === 'hello-ack') {
71
- resolve({ sessionId: frame.sessionId, version: frame.version });
72
- return;
73
- }
74
- if (frame.kind === 'hello-reject') {
75
- reject(new HandshakeError(`Primary rejected: ${frame.reason}`));
76
- return;
77
- }
78
- reject(new HandshakeError(`Unexpected first frame: ${frame.kind}`));
79
- };
80
- this.handshakeReceiver = onFirstFrame;
81
- try {
82
- socket.write(encodeFrame({ kind: 'hello', version: IPC_PROTOCOL_VERSION, token }));
83
- }
84
- catch (err) {
85
- clearTimeout(timer);
86
- reject(err instanceof Error ? err : new Error(String(err)));
87
- }
88
- }).catch((err) => {
89
- void this.disconnect().catch(() => {
90
- /* ignore */
91
- });
92
- throw err;
93
- });
94
- this.handshakeReceiver = null;
95
- log(`Handshake ok — session=${ack.sessionId}`);
96
- return ack;
97
- }
98
- handshakeReceiver = null;
99
- /** Forward a JSON-RPC request as an mcp.request frame. Resolves with the
100
- * primary's JSON-RPC response payload. Rejects if the socket closes. */
101
- sendMcpRequest(jsonRpcPayload) {
102
- const socket = this.socket;
103
- if (!socket || this.closed) {
104
- return Promise.reject(new Error('Proxy is not connected.'));
105
- }
106
- const requestId = this.nextRequestId++;
107
- return new Promise((resolve, reject) => {
108
- this.pendingRequests.set(requestId, resolve);
109
- const onCloseHandler = () => {
110
- if (this.pendingRequests.delete(requestId)) {
111
- reject(new Error('Primary connection closed while a request was in flight.'));
112
- }
113
- };
114
- this.onClose(onCloseHandler);
115
- try {
116
- socket.write(encodeFrame({ kind: 'mcp.request', requestId, payload: jsonRpcPayload }));
117
- }
118
- catch (err) {
119
- this.pendingRequests.delete(requestId);
120
- reject(err instanceof Error ? err : new Error(String(err)));
121
- }
122
- });
123
- }
124
- /** Forward a JSON-RPC notification as an mcp.notification frame. Fire-
125
- * and-forget — notifications have no response in JSON-RPC. */
126
- sendMcpNotification(jsonRpcPayload) {
127
- if (!this.socket || this.closed)
128
- return;
129
- try {
130
- this.socket.write(encodeFrame({ kind: 'mcp.notification', payload: jsonRpcPayload }));
131
- }
132
- catch {
133
- /* socket gone; close handler will fire */
134
- }
135
- }
136
- /** Register a callback invoked when the IPC connection drops. The
137
- * `reason` argument distinguishes a primary-closing broadcast from a
138
- * plain remote close so callers can decide to re-elect vs exit. */
139
- onClose(cb) {
140
- this.closeListeners.push(cb);
141
- }
142
- /** Register a callback for unsolicited notifications from the primary
143
- * (e.g. tools/list_changed in the future). */
144
- onNotification(cb) {
145
- this.notificationListeners.push(cb);
146
- }
147
- /** Close the IPC connection. */
148
- disconnect() {
149
- if (this.closed)
150
- return Promise.resolve();
151
- this.closed = true;
152
- if (this.socket) {
153
- const s = this.socket;
154
- this.socket = null;
155
- try {
156
- s.end();
157
- }
158
- catch {
159
- /* ignore */
160
- }
161
- s.destroy();
162
- // Fire close listeners with reason=local (we initiated it).
163
- this.notifyClose('local');
164
- }
165
- return Promise.resolve();
166
- }
167
- ingest(chunk) {
168
- this.buffer += chunk.toString('utf8');
169
- let nl;
170
- while ((nl = this.buffer.indexOf('\n')) >= 0) {
171
- const line = this.buffer.slice(0, nl);
172
- this.buffer = this.buffer.slice(nl + 1);
173
- if (line.length === 0)
174
- continue;
175
- const frame = parseFrame(line);
176
- if (!frame) {
177
- log('Invalid frame from primary; dropping.');
178
- continue;
179
- }
180
- this.handleFrame(frame);
181
- }
182
- }
183
- handleFrame(frame) {
184
- if (this.handshakeReceiver) {
185
- this.handshakeReceiver(frame);
186
- return;
187
- }
188
- switch (frame.kind) {
189
- case 'mcp.response': {
190
- const resolve = this.pendingRequests.get(frame.requestId);
191
- if (resolve) {
192
- this.pendingRequests.delete(frame.requestId);
193
- resolve(frame.payload);
194
- }
195
- return;
196
- }
197
- case 'mcp.notification': {
198
- for (const cb of this.notificationListeners)
199
- cb(frame.payload);
200
- return;
201
- }
202
- case 'ping': {
203
- try {
204
- this.socket?.write(encodeFrame({ kind: 'pong' }));
205
- }
206
- catch {
207
- /* socket gone */
208
- }
209
- return;
210
- }
211
- case 'pong': {
212
- // Future: we can send our own pings if needed. Today the primary
213
- // initiates the heartbeat; pong from us → primary.
214
- return;
215
- }
216
- case 'primary-closing': {
217
- log(`Primary signalled close (${frame.reason ?? 'no reason'}).`);
218
- this.notifyClose('primary-closing');
219
- return;
220
- }
221
- default:
222
- return;
223
- }
224
- }
225
- onSocketClose(reason) {
226
- if (this.closed)
227
- return;
228
- this.closed = true;
229
- log('Socket closed by primary.');
230
- this.notifyClose(reason);
231
- }
232
- notifyClose(reason) {
233
- // Reject every in-flight request first so callers don't hang.
234
- for (const resolve of this.pendingRequests.values()) {
235
- // We resolve with a JSON-RPC error envelope so the MCP client gets
236
- // a tool error instead of a stuck promise.
237
- resolve({
238
- jsonrpc: '2.0',
239
- id: null,
240
- error: { code: -32000, message: 'browser-link primary disconnected.' },
241
- });
242
- }
243
- this.pendingRequests.clear();
244
- for (const cb of this.closeListeners.splice(0)) {
245
- try {
246
- cb(reason);
247
- }
248
- catch (err) {
249
- log(`Close listener threw: ${err instanceof Error ? err.message : String(err)}`);
250
- }
251
- }
252
- }
253
- }
254
- /** Read the token from disk and connect to the running primary, then plug
255
- * stdin → IPC mcp.request and IPC mcp.response → stdout.
256
- *
257
- * When `autoReelect: true` is passed, the proxy survives IPC drops by
258
- * waiting for a fresh primary to appear at the same port. During the
259
- * wait, incoming JSON-RPC requests get an immediate error response so
260
- * the MCP client never hangs on a missing reply. */
261
- export async function runProxy(opts = {}) {
262
- const input = opts.input ?? process.stdin;
263
- const output = opts.output ?? process.stdout;
264
- const autoReelect = opts.autoReelect === true;
265
- const reelectTimeoutMs = opts.reelectTimeoutMs ?? 5000;
266
- const reelectIntervalMs = opts.reelectIntervalMs ?? 200;
267
- const initialToken = opts.token ?? readToken();
268
- if (!initialToken) {
269
- throw new Error('Multi-agent token not found. The primary browser-link instance is not running with multi-agent enabled.');
270
- }
271
- let client = new IpcClient();
272
- await client.connect(initialToken, { host: opts.host, port: opts.port });
273
- /* When the IPC drops AND autoReelect is on, we enter "reconnecting"
274
- * mode. While reconnecting, the data pipe stays attached but requests
275
- * are answered immediately with an error envelope so the MCP client
276
- * does not stall on a missing reply.
277
- *
278
- * The flags live behind a getter pair on purpose: any read pattern
279
- * TS can statically narrow (let-binding, object literal property)
280
- * gets refined after the first `if (flag) return` and stays narrowed
281
- * across the subsequent `await reconnectLoop(...)`, even though
282
- * `stop()` can flip the value concurrently. TS does NOT narrow the
283
- * return type of a function call, which is exactly the safety net
284
- * we need for the post-await re-check. */
285
- const flags = { stopped: false, reconnecting: false };
286
- const isStopped = () => flags.stopped;
287
- const isReconnecting = () => flags.reconnecting;
288
- let closedResolve = () => {
289
- /* replaced synchronously in the Promise executor below */
290
- };
291
- const closed = new Promise((resolve) => {
292
- closedResolve = resolve;
293
- });
294
- const fail = (reason) => {
295
- if (isStopped())
296
- return;
297
- flags.stopped = true;
298
- input.off('data', onData);
299
- if (opts.onClose) {
300
- try {
301
- opts.onClose(reason);
302
- }
303
- catch (err) {
304
- log(`onClose handler threw: ${err instanceof Error ? err.message : String(err)}`);
305
- }
306
- }
307
- closedResolve();
308
- };
309
- // Set up the input pipe. We can't use readline.createInterface on a raw
310
- // stream that has already been data-event-attached, but we can use a
311
- // simple line buffer like the server side.
312
- let lineBuffer = '';
313
- const onData = (chunk) => {
314
- const text = typeof chunk === 'string' ? chunk : chunk.toString('utf8');
315
- lineBuffer += text;
316
- let nl;
317
- while ((nl = lineBuffer.indexOf('\n')) >= 0) {
318
- const line = lineBuffer.slice(0, nl).replace(/\r$/, '');
319
- lineBuffer = lineBuffer.slice(nl + 1);
320
- if (line.length === 0)
321
- continue;
322
- handleLine(line);
323
- }
324
- };
325
- const handleLine = (line) => {
326
- let msg;
327
- try {
328
- msg = JSON.parse(line);
329
- }
330
- catch {
331
- output.write(JSON.stringify({
332
- jsonrpc: '2.0',
333
- id: null,
334
- error: { code: -32700, message: 'Parse error in proxy input.' },
335
- }) + '\n');
336
- return;
337
- }
338
- if (typeof msg !== 'object')
339
- return;
340
- if (msg.id === undefined || msg.id === null) {
341
- // Notification — fire and forget when connected; drop during reconnect.
342
- if (!isReconnecting())
343
- client.sendMcpNotification(msg);
344
- return;
345
- }
346
- if (isReconnecting()) {
347
- // Fail fast so the MCP client can decide to retry.
348
- output.write(JSON.stringify({
349
- jsonrpc: '2.0',
350
- id: msg.id,
351
- error: {
352
- code: -32001,
353
- message: 'browser-link bridge temporarily unavailable (primary just closed; reconnecting).',
354
- },
355
- }) + '\n');
356
- return;
357
- }
358
- // Capture the id NOW; by the time the catch fires the closure scope
359
- // still has `msg`, but TS narrowing of `msg` inside the catch is
360
- // weaker than reading the field upfront.
361
- const incomingId = msg.id;
362
- client
363
- .sendMcpRequest(msg)
364
- .then((responsePayload) => {
365
- output.write(JSON.stringify(responsePayload) + '\n');
366
- })
367
- .catch((err) => {
368
- output.write(JSON.stringify({
369
- jsonrpc: '2.0',
370
- id: incomingId,
371
- error: { code: -32000, message: err instanceof Error ? err.message : String(err) },
372
- }) + '\n');
373
- });
374
- };
375
- input.on('data', onData);
376
- const wireCloseHandler = (c) => {
377
- // The onClose contract is sync (returns void). The body needs awaits
378
- // for the reconnect loop, so we kick off an async IIFE inside.
379
- c.onClose((reason) => {
380
- void (async () => {
381
- if (isStopped())
382
- return;
383
- if (!autoReelect) {
384
- fail(reason);
385
- return;
386
- }
387
- // Enter reconnect mode and try to find a new primary.
388
- flags.reconnecting = true;
389
- opts.onReelectStart?.();
390
- log(`Primary closed (${reason}); reelect window opened for ${reelectTimeoutMs}ms.`);
391
- const newClient = await reconnectLoop(opts.host, opts.port, reelectTimeoutMs, reelectIntervalMs);
392
- // `stop()` may have run during the await above and flipped
393
- // `flags.stopped`. The `isStopped()` call dodges TS narrowing
394
- // from the check at the top of this IIFE so the runtime guard
395
- // stays real.
396
- if (isStopped()) {
397
- if (newClient)
398
- await newClient.disconnect();
399
- return;
400
- }
401
- if (!newClient) {
402
- log('Reelect window exhausted; closing proxy.');
403
- opts.onReelectExhausted?.();
404
- flags.reconnecting = false;
405
- fail(reason);
406
- return;
407
- }
408
- // Hot-swap clients. The old one is already torn down by its close
409
- // handler chain; we just install the new one and wire it up.
410
- log('Reconnected to new primary.');
411
- opts.onReelectSuccess?.();
412
- client = newClient;
413
- flags.reconnecting = false;
414
- wireCloseHandler(client);
415
- })();
416
- });
417
- };
418
- wireCloseHandler(client);
419
- const stop = async () => {
420
- flags.stopped = true;
421
- input.off('data', onData);
422
- await client.disconnect();
423
- closedResolve();
424
- };
425
- return {
426
- get client() {
427
- return client;
428
- },
429
- stop,
430
- closed,
431
- };
432
- }
433
- /** Repeatedly try to connect to the IPC port until success or budget
434
- * expires. Re-reads the token on every attempt because a new primary
435
- * rotates it on startup. Returns the connected client, or null on
436
- * timeout. */
437
- async function reconnectLoop(host, port, totalBudgetMs, intervalMs) {
438
- const deadline = Date.now() + totalBudgetMs;
439
- // Generous handshake budget — Windows under load can take >200ms for a
440
- // local socket round-trip and a too-tight ceiling makes reconnects flap.
441
- const handshakeTimeoutMs = Math.min(1500, Math.max(800, intervalMs * 4));
442
- while (Date.now() < deadline) {
443
- await new Promise((r) => setTimeout(r, intervalMs));
444
- const token = readToken();
445
- if (!token)
446
- continue;
447
- const c = new IpcClient();
448
- try {
449
- await c.connect(token, { host, port, handshakeTimeoutMs });
450
- return c;
451
- }
452
- catch {
453
- try {
454
- await c.disconnect();
455
- }
456
- catch {
457
- /* ignore */
458
- }
459
- // Retry until deadline.
460
- }
461
- }
462
- return null;
463
- }
464
- /** Convenience: open a readline-style line iterator over a stream. Currently
465
- * unused (we use a hand-rolled line buffer for symmetry with the server)
466
- * but exported for future tooling. */
467
- export function readlines(stream) {
468
- return createInterface({ input: stream, crlfDelay: Infinity });
469
- }
470
- //# sourceMappingURL=client.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/bridge/client.ts"],"names":[],"mappings":"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"}