fix: use process.execPath and probe ~/.bun/bin for snap/PATH-limited envs#190
Conversation
|
I'll re-check those failures. |
…envs In snap Node.js environments, spawning `node` as a child process invokes the snap wrapper again which exits 0 with no output, causing the server test and all JS execution to silently fail. Fix by storing process.execPath as the javascript runtime so the actual binary is used directly. Also probe ~/.bun/bin/bun as a fallback when bun is not in PATH, which happens in MCP server environments that inherit a stripped PATH and miss the fish/shell profile additions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Keep original "bun or node" test alongside new stricter check - Add test asserting javascript runtime is never bare "node" string - Add test for full-path bun runtime using "run" subcommand - Fix PATH-dependent shell test to use process.execPath instead of "node" Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3081bd5 to
cc2060d
Compare
Architecture Review — 3 Specialist AgentsThanks @luispabon — this is a valuable fix for snap Node.js users and PATH-limited environments. The architecture is sound: Bug Found:
|
Additional Finding: Electron
|
PR #183: Restrict sessionKey regex to [a-zA-Z0-9_-]+ and add startsWith containment check to prevent path traversal in writeRoutingInstructions workspace derivation. PR #190: Fix getRuntimeSummary() bun detection — use endsWith("bun") instead of === "bun" to handle full paths like ~/.bun/bin/bun. PR #192: Remove trailing whitespace from AGENTS.md blank separator lines. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Merged and post-merge fix applied: Fixed the - const bunPreferred = runtimes.javascript === "bun";
+ const bunPreferred = runtimes.javascript?.endsWith("bun") ?? false;This ensures the lightning bolt indicator and "Performance: FAST (Bun)" message work correctly when bun is detected via Note: I reviewed the Electron Once the next version ships, can you test on your Ubuntu snap setup? Both the snap Node.js fix and bun detection should work correctly now. Thanks for the valuable fix @luispabon. |
|
Thank you @mksglu |
#731) ctx_execute(language: "javascript") failed when context-mode runs in-process inside a bun-compiled self-contained binary host (OpenCode opencode.exe / Kilo). PolyglotExecutor spawned the host binary itself with a script.js argument, triggering yargs's "Failed to change directory" error and a silent exit 0 with no stdout. Root cause: detectRuntimes() returned `bun ?? process.execPath` for the javascript runtime (src/runtime.ts:253). PR #190 (f69b0d2) introduced the execPath default to avoid the snap-Node wrapper re-invocation problem, but assumed execPath always points at a JS runtime — false for in-process plugin hosts whose execPath is the host binary itself. Fix: extract resolveJavascriptRuntime() helper that gates execPath on the existing JS_RUNTIMES allowlist (src/adapters/types.ts:421 — the same single-source-of-truth set PR #708 introduced for buildNodeCommand). When execPath basename is not in {node, bun, deno}, fall back to commandExists("node") ? "node" : null. The allowlist is cross-OS by design — strips optional .exe and splits on both separators, so the bug reproduces and fixes identically on macOS, Linux, and Windows (the reporter only saw the Windows shape but the cross-OS check is correct). Preserves PR #190 snap-Node behavior: snap wrapper's binary is literally named `node` → in JS_RUNTIMES → execPath returned verbatim. Covered by regression test "snap-node host". When neither bun nor PATH node is reachable, runtimes.javascript is null. RuntimeMap.javascript is widened to string | null; getRuntimeSummary surfaces an actionable "not available" line instead of literal "null", and buildCommand throws a clear error before spawning the wrong binary. server.ts:3895 jsRuntime forwarding is null-guarded (downstream buildNodeCommand already defaults to "node" when jsRuntime is omitted). Tests added (tests/runtime.test.ts): - Windows opencode.exe host falls back to PATH node - POSIX opencode binary host falls back to PATH node (cross-OS) - null when host is non-JS and node missing - snap-node host preserves execPath (regression for #190) - bun host preserves execPath - doctor summary surfaces actionable error when javascript is null Archaeology: - f69b0d2 (#190) — introduced bun ?? process.execPath default - PR #708 — added JS_RUNTIMES + IN_PROCESS_PLUGIN_PLATFORMS
…brew Cellar ENOENT (#800) (#803) * fix(runtime): add liveness guard to resolveJavascriptRuntime for Homebrew Cellar ENOENT (#800) When process.execPath is a Homebrew Cellar path (/opt/homebrew/Cellar/node/VERSION/bin/node), brew upgrade plus brew cleanup deletes the old Cellar directory, leaving the in-process execPath dangling. The liveness guard falls back to PATH-resolved node when the execPath no longer exists on disk. Preserves the snap-node fix (#190): the snap wrapper binary literally exists at its execPath, so the guard passes and the path is returned verbatim (not collapsed to bare node). - Add existsSync(execPath) check before returning execPath - Existing snap-node + bun regression tests updated to mock existsSync returning true for their respective exec paths - Two new tests covering: 1. Stale Cellar path falls back to PATH node 2. Stale Cellar + no PATH node returns null * fix(test): cross-platform bun path mock in #800 Cellar ENOENT test The existsSync mock only blocked Unix-style bun paths (/.bun/bin/bun), but on Windows bunFallbackPaths returns paths with backslashes (C:\Users\...\.bun\bin\bun.exe). This caused bunExists() to find a real bun on the Windows CI runner, making resolveJavascriptRuntime return the bun path instead of 'node'. Replace the single-platform .includes() check with a cross-platform regex that matches both file separators and the optional dot prefix on ~/.bun.
tl;dr
This fixes execution on Ubuntu systems where Node is installed as a snap, and also access to bun when the user is using a different shell than bash (fish in my case).
Before
After
Summary
nodeas a child process re-invokes the snap wrapper, which exits 0 with no output — causing all JS execution (including the doctor server test) to silently fail. Fixed by usingprocess.execPathas the javascript runtime so the actual binary path is passed directly tospawn().~/.bun/bin(added by fish/shell profile scripts). Fixed by probing~/.bun/bin/bunas a fallback inbunExists().Test plan
/ctx-doctorwith snap Node.js — server test should PASS/ctx-doctorwith bun installed via its installer (not in system PATH) — bun should be detected and performance warning should clear🤖 Generated with Claude Code