From ab731e64d2ad1f670030725639ddc8160f2c94ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Fri, 17 Apr 2026 20:15:40 -0400 Subject: [PATCH] fix(onboarding): actually probe shell PATH for node; stop returning Electron's bundled version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `checkNodeInstalled` IPC handler was hardcoded to `{ installed: true, version: process.version }`. That meant: 1. The NodeCheckStep in onboarding ALWAYS passed, regardless of what was actually on the user's machine. 2. The "Node.js vX.Y installed" success banner showed the **Electron runtime's** bundled Node version, not the one the agent's bash tool will invoke. A user with no shell Node saw "Node.js v22.x installed" and moved on, then every agent bash call that executed `node -e 'fetch(...)'` (the pattern the API prompt-builder strongly recommends in `api-docs/header.en.md`) crashed at runtime. Replaced the stub with an `execFile("node", ["--version"])` probe that runs in the same PATH the bash tool will later inherit. Added a 3s timeout so a hung PATH entry doesn't stall onboarding. On failure the handler returns `{ installed: false, version: null }` — the existing NodeCheckStep already renders the platform-specific install instructions (brew / winget / nvm) in that case. No UI change; the fake-pass was the bug. Covers the onboarding audit item about misleading health checks. --- src/main/ipc-core-admin-handlers.ts | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/main/ipc-core-admin-handlers.ts b/src/main/ipc-core-admin-handlers.ts index 48c74a01..7f917a58 100644 --- a/src/main/ipc-core-admin-handlers.ts +++ b/src/main/ipc-core-admin-handlers.ts @@ -1,3 +1,4 @@ +import { execFile } from "node:child_process"; import { IPC_CHANNELS, companyInputSchema, @@ -11,6 +12,27 @@ import { validateConnectorConfigurationModel, validateConnectorModelSelection } import { reconcileExecutionModeChange } from "./execution-mode-reconciler"; import { fail, ok, type RegisterCoreHandlersDependencies } from "./ipc-core-common"; +/** + * Probe the user's shell PATH for a `node` binary. The onboarding Node + * check uses this to decide whether agents will be able to run the + * "Node.js fetch()" snippets the API prompt-builder emits. Returns the + * shell `node --version` output on success; never surfaces the raw + * `process.version` (that is Electron's bundled Node, not what the + * agent's bash tool will actually invoke). + */ +function probeShellNode(timeoutMs = 3000): Promise<{ installed: boolean; version: string | null }> { + return new Promise((resolve) => { + execFile("node", ["--version"], { timeout: timeoutMs }, (error, stdout) => { + if (error) { + resolve({ installed: false, version: null }); + return; + } + const version = stdout.trim(); + resolve({ installed: version.length > 0, version: version.length > 0 ? version : null }); + }); + }); +} + export function registerCoreAdminHandlers({ registerHandle, db, @@ -108,7 +130,7 @@ export function registerCoreAdminHandlers({ }); registerHandle(IPC_CHANNELS.checkNodeInstalled, async () => { - return ok({ installed: true, version: process.version }); + return ok(await probeShellNode()); }); registerHandle(IPC_CHANNELS.openTerminalCommand, async (_event, payload) => {