@minhspark/codex-mcp-bridge 1.15.1 → 1.15.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/CHANGELOG.md CHANGED
@@ -4,6 +4,13 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and [SemVer](ht
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.15.2] - 2026-09-14
8
+
9
+ ### Fixed
10
+
11
+ - Restore Codex-to-Claude Desktop messaging on Windows with Claude Code 2.1.270, which advertises its process FILETIME as `procStart` instead of `procStartFt`. Normalize both fields in session records and authentication keys, retain live process verification, and reject malformed or conflicting identities.
12
+ - Advertise both Windows identity fields on bridge peer records and authentication keys so current Claude sessions and older peers can validate the same endpoint without restarting Desktop.
13
+
7
14
  ## [1.15.1] - 2026-09-14
8
15
 
9
16
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minhspark/codex-mcp-bridge",
3
- "version": "1.15.1",
3
+ "version": "1.15.2",
4
4
  "description": "Two-way MCP bridge between Claude and Codex: prompts into a live Codex thread, messages into a running Claude Code session.",
5
5
  "keywords": [
6
6
  "mcp",
@@ -22,7 +22,7 @@ import { createReleaseSnapshot, snapshotRoot } from "../src/release-snapshot.mjs
22
22
 
23
23
  exitForVersionRequest(import.meta.url);
24
24
 
25
- const VERSION = "1.15.1";
25
+ const VERSION = "1.15.2";
26
26
  const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
27
27
  const entry = path.join(root, "src", "mcp-supervisor.mjs");
28
28
  const entryArgs = ["native-relay-companion.mjs"];
@@ -22,7 +22,7 @@ import { resolveClaudeDesktopSession } from "./claude-session-router.mjs";
22
22
 
23
23
  exitForVersionRequest(import.meta.url);
24
24
 
25
- const VERSION = "1.15.1";
25
+ const VERSION = "1.15.2";
26
26
  const FORWARD_MIN_INTERVAL_MS = 5000;
27
27
  const FORWARD_MAX_PER_SESSION = 50;
28
28
 
package/src/index.mjs CHANGED
@@ -33,7 +33,7 @@ import { assertClaudeSenderContext, readClaudeSenderContext, requireClaudeSender
33
33
 
34
34
  exitForVersionRequest(import.meta.url);
35
35
 
36
- const VERSION = "1.15.1";
36
+ const VERSION = "1.15.2";
37
37
  const log = (msg) => process.stderr.write(`[codex-mcp-bridge] ${msg}\n`);
38
38
 
39
39
  /**
@@ -30,7 +30,7 @@ import { createRuntimeState } from "./runtime-state.mjs";
30
30
 
31
31
  exitForVersionRequest(import.meta.url);
32
32
 
33
- const VERSION = "1.15.1";
33
+ const VERSION = "1.15.2";
34
34
  const log = (msg) => process.stderr.write(`[native-relay] ${msg}\n`);
35
35
 
36
36
  function errorResponse(code, message, sent) {
@@ -99,7 +99,7 @@ function readPeerToken(socket) {
99
99
  try {
100
100
  const key = JSON.parse(fs.readFileSync(peerKeyPath(candidates[0].pid, socket), "utf8"));
101
101
  if (typeof key.peerToken !== "string" || !/^[0-9a-f]{32}$/i.test(key.peerToken)) throw new Error("Invalid peer key");
102
- const identity = IS_WINDOWS ? key.procStartFt : key.procStart;
102
+ const identity = readPeerProcessIdentity(key);
103
103
  if (identity && identity !== readProcessStart(candidates[0].pid)) throw new Error("Peer process identity changed");
104
104
  return key.peerToken;
105
105
  } catch {
@@ -108,6 +108,17 @@ function readPeerToken(socket) {
108
108
  }
109
109
  }
110
110
 
111
+ export function readPeerProcessIdentity(entry, platform = process.platform) {
112
+ if (platform !== "win32") return entry.procStart ?? null;
113
+ const values = ["procStart", "procStartFt"].filter((field) => Object.hasOwn(entry, field)).map((field) => entry[field]);
114
+ if (!values.length) return null;
115
+ if (values.some((value) => typeof value !== "string" || !/^[1-9]\d{0,19}$/.test(value) || BigInt(value) > 18446744073709551615n)
116
+ || values.some((value) => value !== values[0])) {
117
+ throw new Error("Invalid or conflicting Windows peer process identity");
118
+ }
119
+ return values[0];
120
+ }
121
+
111
122
  /**
112
123
  * MCP servers are spawned with an empty PATH, so `ps` must be addressed by its
113
124
  * absolute path - a bare lookup throws ENOENT and takes the whole server down
@@ -173,6 +184,9 @@ export function listClaudeSessions({ includeDead = false, includeBridges = false
173
184
  if (entry.entrypoint === BRIDGE_ENTRYPOINT && !includeBridges) continue;
174
185
  const alive = isProcessAlive(entry.pid) && hasMessagingEndpoint(entry);
175
186
  if (!alive && !includeDead) continue;
187
+ let processStart;
188
+ try { processStart = readPeerProcessIdentity(entry); }
189
+ catch { continue; }
176
190
  rows.push({
177
191
  pid: entry.pid,
178
192
  name: entry.name ?? null,
@@ -182,7 +196,7 @@ export function listClaudeSessions({ includeDead = false, includeBridges = false
182
196
  kind: entry.kind ?? null,
183
197
  entrypoint: entry.entrypoint ?? null,
184
198
  startedAt: entry.startedAt ?? null,
185
- processStart: (IS_WINDOWS ? entry.procStartFt : entry.procStart) ?? null,
199
+ processStart,
186
200
  socket: entry.messagingSocketPath,
187
201
  alive,
188
202
  });
@@ -420,7 +434,7 @@ export class PeerEndpoint {
420
434
  });
421
435
  if (!IS_WINDOWS) fs.chmodSync(this.socketPath, 0o600);
422
436
 
423
- const processIdentity = procStart ? (IS_WINDOWS ? { procStartFt: procStart } : { procStart }) : {};
437
+ const processIdentity = procStart ? (IS_WINDOWS ? { procStart, procStartFt: procStart } : { procStart }) : {};
424
438
  this.registry = {
425
439
  pid: this.pid,
426
440
  sessionId: crypto.randomUUID(),