( socketPath: string, expectedVersion: string = CodeGraphPackageVersion, )
| 81 | * price of never silently running a stale daemon against newer client code.) |
| 82 | */ |
| 83 | export async function runProxy( |
| 84 | socketPath: string, |
| 85 | expectedVersion: string = CodeGraphPackageVersion, |
| 86 | ): Promise<ProxyResult> { |
| 87 | // POSIX: refuse to connect to a stale socket file that points at no |
| 88 | // listening process. `fs.existsSync` is a cheap pre-check; a real |
| 89 | // ECONNREFUSED below catches the rare "exists but unbound" race. |
| 90 | if (process.platform !== 'win32' && !fs.existsSync(socketPath)) { |
| 91 | return { outcome: 'fallback-needed', reason: 'socket file missing' }; |
| 92 | } |
| 93 | |
| 94 | const socket = net.createConnection(socketPath); |
| 95 | socket.setEncoding('utf8'); |
| 96 | |
| 97 | const hello = await readHelloLine(socket).catch((err) => { |
| 98 | socket.destroy(); |
| 99 | return new Error(String(err)); |
| 100 | }); |
| 101 | if (hello instanceof Error) { |
| 102 | return { outcome: 'fallback-needed', reason: hello.message }; |
| 103 | } |
| 104 | |
| 105 | if (hello.codegraph !== expectedVersion) { |
| 106 | process.stderr.write( |
| 107 | `[CodeGraph MCP] Found a daemon on ${socketPath} but version (${hello.codegraph}) ` + |
| 108 | `differs from ours (${expectedVersion}); falling back to direct mode.\n` |
| 109 | ); |
| 110 | socket.destroy(); |
| 111 | return { outcome: 'fallback-needed', reason: 'version mismatch' }; |
| 112 | } |
| 113 | |
| 114 | logAttachedDaemon(socketPath, hello); |
| 115 | |
| 116 | sendClientHello(socket); |
| 117 | startPpidWatchdog(socket); |
| 118 | await pipeUntilClose(socket); |
| 119 | // Host disconnected (or the daemon went away). The proxy's only job is the |
| 120 | // pipe; exit now so we don't linger — process.stdin's 'data' listener would |
| 121 | // otherwise keep the event loop alive and leave a zombie launcher behind. |
| 122 | process.exit(0); |
| 123 | } |
| 124 | |
| 125 | /** |
| 126 | * Connect to a daemon at `socketPath` and verify its hello (exact version match). |
nothing calls this directly
no test coverage detected