From babb51ba94e4635330a9dd57ed367856b18b8127 Mon Sep 17 00:00:00 2001 From: Ordinary Date: Wed, 24 Dec 2025 14:01:53 +0800 Subject: [PATCH] fix: use runtime execPath for MCP bridge --- src/codex/runCodex.ts | 7 ++++--- src/gemini/runGemini.ts | 7 ++++--- src/utils/spawnHappyCLI.ts | 16 ++++++++++------ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/codex/runCodex.ts b/src/codex/runCodex.ts index d789bb19..0f5c43b2 100644 --- a/src/codex/runCodex.ts +++ b/src/codex/runCodex.ts @@ -536,11 +536,12 @@ export async function runCodex(opts: { // Start Happy MCP server (HTTP) and prepare STDIO bridge config for Codex const happyServer = await startHappyServer(session); - const bridgeCommand = join(projectPath(), 'bin', 'happy-mcp.mjs'); + const bridgeScript = join(projectPath(), 'bin', 'happy-mcp.mjs'); + // Use process.execPath (bun or node) as command to support both runtimes const mcpServers = { happy: { - command: bridgeCommand, - args: ['--url', happyServer.url] + command: process.execPath, + args: [bridgeScript, '--url', happyServer.url] } } as const; let first = true; diff --git a/src/gemini/runGemini.ts b/src/gemini/runGemini.ts index b89554bf..08a73a7c 100644 --- a/src/gemini/runGemini.ts +++ b/src/gemini/runGemini.ts @@ -421,11 +421,12 @@ export async function runGemini(opts: { // const happyServer = await startHappyServer(session); - const bridgeCommand = join(projectPath(), 'bin', 'happy-mcp.mjs'); + const bridgeScript = join(projectPath(), 'bin', 'happy-mcp.mjs'); + // Use process.execPath (bun or node) as command to support both runtimes const mcpServers = { happy: { - command: bridgeCommand, - args: ['--url', happyServer.url] + command: process.execPath, + args: [bridgeScript, '--url', happyServer.url] } }; diff --git a/src/utils/spawnHappyCLI.ts b/src/utils/spawnHappyCLI.ts index 1ed7d2d7..29db7b42 100644 --- a/src/utils/spawnHappyCLI.ts +++ b/src/utils/spawnHappyCLI.ts @@ -50,7 +50,7 @@ */ import { spawn, SpawnOptions, type ChildProcess } from 'child_process'; -import { join } from 'node:path'; +import { join, basename } from 'node:path'; import { projectPath } from '@/projectPath'; import { logger } from '@/ui/logger'; import { existsSync } from 'node:fs'; @@ -69,6 +69,10 @@ import { existsSync } from 'node:fs'; export function spawnHappyCLI(args: string[], options: SpawnOptions = {}): ChildProcess { const projectRoot = projectPath(); const entrypoint = join(projectRoot, 'dist', 'index.mjs'); + const overrideRuntime = process.env.HAPPY_NODE_BIN; + const runtimePath = overrideRuntime || process.execPath || 'node'; + const isBunRuntime = typeof (process as any).versions?.bun === 'string' + || basename(runtimePath).toLowerCase().includes('bun'); let directory: string | URL | undefined; if ('cwd' in options) { @@ -84,10 +88,9 @@ export function spawnHappyCLI(args: string[], options: SpawnOptions = {}): Child const fullCommand = `happy ${args.join(' ')}`; logger.debug(`[SPAWN HAPPY CLI] Spawning: ${fullCommand} in ${directory}`); - // Use the same Node.js flags that the wrapper script uses - const nodeArgs = [ - '--no-warnings', - '--no-deprecation', + // Use the same Node.js flags that the wrapper script uses (Bun doesn't support these) + const runtimeArgs = [ + ...(isBunRuntime ? [] : ['--no-warnings', '--no-deprecation']), entrypoint, ...args ]; @@ -99,5 +102,6 @@ export function spawnHappyCLI(args: string[], options: SpawnOptions = {}): Child throw new Error(errorMessage); } - return spawn('node', nodeArgs, options); + logger.debug(`[SPAWN HAPPY CLI] Runtime: ${runtimePath} (bun=${isBunRuntime})`); + return spawn(runtimePath, runtimeArgs, options); }