@raysonmeng/agentbridge 0.1.0 → 0.1.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.
@@ -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.0",
15
+ "version": "0.1.2",
16
16
  "author": {
17
17
  "name": "AgentBridge Contributors",
18
18
  "email": "raysonmeng@qq.com"
package/README.md CHANGED
@@ -93,7 +93,7 @@ Then install the CLI tool:
93
93
 
94
94
  ```bash
95
95
  # 4. Install the CLI globally
96
- npm install -g agentbridge
96
+ npm install -g @raysonmeng/agentbridge
97
97
 
98
98
  # 5. Generate project config (optional)
99
99
  abg init
package/README.zh-CN.md CHANGED
@@ -93,7 +93,7 @@ AgentBridge 采用两层进程结构:
93
93
 
94
94
  ```bash
95
95
  # 4. 全局安装 CLI
96
- npm install -g agentbridge
96
+ npm install -g @raysonmeng/agentbridge
97
97
 
98
98
  # 5. 生成项目配置(可选)
99
99
  abg init
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.0",
1015
+ version: "0.1.2",
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raysonmeng/agentbridge",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Bridge between Claude Code and Codex — bidirectional agent communication via MCP Channel + JSON-RPC",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentbridge",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Bridge Claude Code and Codex with a shared daemon, push channel delivery, and bidirectional reply tooling.",
5
5
  "author": {
6
6
  "name": "AgentBridge Contributors",
@@ -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 = typeof responseId === "number" ? responseId : typeof responseId === "string" && /^-?\d+$/.test(responseId) ? Number(responseId) : NaN;
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]) {