@raysonmeng/agentbridge 0.1.0 → 0.1.1
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.
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
{
|
|
13
13
|
"name": "agentbridge",
|
|
14
14
|
"description": "Bridge Claude Code and Codex through a shared daemon, push channel delivery, and reply/get_messages tools.",
|
|
15
|
-
"version": "0.1.
|
|
15
|
+
"version": "0.1.1",
|
|
16
16
|
"author": {
|
|
17
17
|
"name": "AgentBridge Contributors",
|
|
18
18
|
"email": "raysonmeng@qq.com"
|
package/README.md
CHANGED
package/README.zh-CN.md
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1012,7 +1012,7 @@ var init_kill = __esm(() => {
|
|
|
1012
1012
|
var require_package = __commonJS((exports, module) => {
|
|
1013
1013
|
module.exports = {
|
|
1014
1014
|
name: "@raysonmeng/agentbridge",
|
|
1015
|
-
version: "0.1.
|
|
1015
|
+
version: "0.1.1",
|
|
1016
1016
|
description: "Bridge between Claude Code and Codex \u2014 bidirectional agent communication via MCP Channel + JSON-RPC",
|
|
1017
1017
|
type: "module",
|
|
1018
1018
|
bin: {
|
package/package.json
CHANGED
|
@@ -29,6 +29,9 @@ class CodexAdapter extends EventEmitter {
|
|
|
29
29
|
turnInProgress = false;
|
|
30
30
|
nextProxyId = 1e5;
|
|
31
31
|
upstreamToClient = new Map;
|
|
32
|
+
serverRequestToProxy = new Map;
|
|
33
|
+
serverRequestTtlTimers = new Map;
|
|
34
|
+
pendingServerRequests = [];
|
|
32
35
|
staleProxyIds = new Map;
|
|
33
36
|
bridgeRequestIds = new Map;
|
|
34
37
|
intentionalDisconnect = false;
|
|
@@ -225,6 +228,26 @@ class CodexAdapter extends EventEmitter {
|
|
|
225
228
|
this.tuiWs = ws;
|
|
226
229
|
this.log(`TUI connected (conn #${this.tuiConnId})`);
|
|
227
230
|
this.emit("tuiConnected", this.tuiConnId);
|
|
231
|
+
const remaining = [];
|
|
232
|
+
for (const buffered of this.pendingServerRequests) {
|
|
233
|
+
const proxyId = this.nextProxyId++;
|
|
234
|
+
try {
|
|
235
|
+
const parsed = JSON.parse(buffered.raw);
|
|
236
|
+
parsed.id = proxyId;
|
|
237
|
+
ws.send(JSON.stringify(parsed));
|
|
238
|
+
this.serverRequestToProxy.set(proxyId, {
|
|
239
|
+
serverId: buffered.serverId,
|
|
240
|
+
connId: this.tuiConnId,
|
|
241
|
+
method: buffered.method,
|
|
242
|
+
timestamp: Date.now()
|
|
243
|
+
});
|
|
244
|
+
this.log(`Replayed buffered server request: ${buffered.method} (server id=${buffered.serverId} \u2192 proxy id=${proxyId})`);
|
|
245
|
+
} catch (e) {
|
|
246
|
+
this.log(`Failed to replay buffered server request: ${buffered.method} (server id=${buffered.serverId}): ${e.message}`);
|
|
247
|
+
remaining.push(buffered);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
this.pendingServerRequests = remaining;
|
|
228
251
|
}
|
|
229
252
|
onTuiDisconnect(ws) {
|
|
230
253
|
const connId = ws.data.connId;
|
|
@@ -244,6 +267,33 @@ class CodexAdapter extends EventEmitter {
|
|
|
244
267
|
this.log(`Dropping message from stale TUI conn #${connId} (current is #${this.tuiConnId})`);
|
|
245
268
|
return;
|
|
246
269
|
}
|
|
270
|
+
try {
|
|
271
|
+
const parsed = JSON.parse(data);
|
|
272
|
+
if (parsed.id !== undefined && !parsed.method) {
|
|
273
|
+
const normalizedId = this.normalizeNumericId(parsed.id);
|
|
274
|
+
const pending = !isNaN(normalizedId) ? this.serverRequestToProxy.get(normalizedId) : undefined;
|
|
275
|
+
if (pending !== undefined) {
|
|
276
|
+
if (pending.connId !== connId) {
|
|
277
|
+
this.log(`Dropping stale server request response (proxy id=${normalizedId}, expected conn #${pending.connId}, got #${connId})`);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
if (!this.appServerWs || this.appServerWs.readyState !== WebSocket.OPEN) {
|
|
281
|
+
this.log(`Cannot forward approval response: app-server disconnected (proxy id=${normalizedId})`);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
parsed.id = pending.serverId;
|
|
285
|
+
try {
|
|
286
|
+
this.appServerWs.send(JSON.stringify(parsed));
|
|
287
|
+
this.serverRequestToProxy.delete(normalizedId);
|
|
288
|
+
this.log(`TUI \u2192 app-server: ${pending.method} response (proxy id=${normalizedId} \u2192 server id=${pending.serverId})`);
|
|
289
|
+
} catch (e) {
|
|
290
|
+
parsed.id = normalizedId;
|
|
291
|
+
this.log(`Failed to forward approval response (proxy id=${normalizedId}): ${e.message}`);
|
|
292
|
+
}
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
} catch {}
|
|
247
297
|
let forwarded = data;
|
|
248
298
|
try {
|
|
249
299
|
const parsed = JSON.parse(data);
|
|
@@ -275,14 +325,45 @@ class CodexAdapter extends EventEmitter {
|
|
|
275
325
|
this.interceptServerMessage(parsed);
|
|
276
326
|
return forwarded;
|
|
277
327
|
}
|
|
328
|
+
if (parsed.method !== undefined) {
|
|
329
|
+
this.handleServerRequest(parsed, raw);
|
|
330
|
+
return null;
|
|
331
|
+
}
|
|
278
332
|
return this.handleAppServerResponse(parsed, raw);
|
|
279
333
|
} catch {
|
|
280
334
|
return raw;
|
|
281
335
|
}
|
|
282
336
|
}
|
|
337
|
+
handleServerRequest(parsed, raw) {
|
|
338
|
+
const serverId = parsed.id;
|
|
339
|
+
const method = parsed.method;
|
|
340
|
+
if (!this.tuiWs) {
|
|
341
|
+
this.pendingServerRequests.push({ raw, serverId, method });
|
|
342
|
+
this.log(`Server request buffered (no TUI): ${method} (server id=${serverId})`);
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
const proxyId = this.nextProxyId++;
|
|
346
|
+
parsed.id = proxyId;
|
|
347
|
+
try {
|
|
348
|
+
this.tuiWs.send(JSON.stringify(parsed));
|
|
349
|
+
} catch (e) {
|
|
350
|
+
this.log(`Server request send failed, buffering: ${method} (server id=${serverId}): ${e.message}`);
|
|
351
|
+
this.pendingServerRequests.push({ raw, serverId, method });
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
this.serverRequestToProxy.set(proxyId, { serverId, connId: this.tuiConnId, method, timestamp: Date.now() });
|
|
355
|
+
this.log(`Server request: ${method} (server id=${serverId} \u2192 proxy id=${proxyId}, conn #${this.tuiConnId})`);
|
|
356
|
+
}
|
|
357
|
+
normalizeNumericId(id) {
|
|
358
|
+
if (typeof id === "number")
|
|
359
|
+
return id;
|
|
360
|
+
if (typeof id === "string" && /^-?\d+$/.test(id))
|
|
361
|
+
return Number(id);
|
|
362
|
+
return NaN;
|
|
363
|
+
}
|
|
283
364
|
handleAppServerResponse(parsed, raw) {
|
|
284
365
|
const responseId = parsed.id;
|
|
285
|
-
const numericId =
|
|
366
|
+
const numericId = this.normalizeNumericId(responseId);
|
|
286
367
|
const mapping = !isNaN(numericId) ? this.upstreamToClient.get(numericId) : undefined;
|
|
287
368
|
if (mapping) {
|
|
288
369
|
this.upstreamToClient.delete(numericId);
|
|
@@ -511,6 +592,20 @@ class CodexAdapter extends EventEmitter {
|
|
|
511
592
|
this.upstreamToClient.delete(upId);
|
|
512
593
|
this.trackStaleProxyId(upId);
|
|
513
594
|
}
|
|
595
|
+
for (const [proxyId, pending] of this.serverRequestToProxy.entries()) {
|
|
596
|
+
if (pending.connId === connId) {
|
|
597
|
+
this.clearTrackedId(this.serverRequestTtlTimers, proxyId);
|
|
598
|
+
const timer = setTimeout(() => {
|
|
599
|
+
this.serverRequestTtlTimers.delete(proxyId);
|
|
600
|
+
if (this.serverRequestToProxy.get(proxyId)?.connId === connId) {
|
|
601
|
+
this.serverRequestToProxy.delete(proxyId);
|
|
602
|
+
this.log(`Expired stale server request mapping (proxy id=${proxyId}, method=${pending.method})`);
|
|
603
|
+
}
|
|
604
|
+
}, CodexAdapter.RESPONSE_TRACKING_TTL_MS);
|
|
605
|
+
timer.unref?.();
|
|
606
|
+
this.serverRequestTtlTimers.set(proxyId, timer);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
514
609
|
}
|
|
515
610
|
trackStaleProxyId(proxyId) {
|
|
516
611
|
this.clearTrackedId(this.staleProxyIds, proxyId);
|
|
@@ -556,6 +651,12 @@ class CodexAdapter extends EventEmitter {
|
|
|
556
651
|
clearTimeout(timer);
|
|
557
652
|
}
|
|
558
653
|
this.bridgeRequestIds.clear();
|
|
654
|
+
for (const timer of this.serverRequestTtlTimers.values()) {
|
|
655
|
+
clearTimeout(timer);
|
|
656
|
+
}
|
|
657
|
+
this.serverRequestTtlTimers.clear();
|
|
658
|
+
this.serverRequestToProxy.clear();
|
|
659
|
+
this.pendingServerRequests = [];
|
|
559
660
|
}
|
|
560
661
|
async checkPorts() {
|
|
561
662
|
for (const port of [this.appPort, this.proxyPort]) {
|