fix: exec() node fallback + feat: includeNodeShims option (fixes #64, #63)#66
Conversation
Fixes rivet-dev#64 — exec() throws 'No shell available' when only NodeRuntime is mounted (which registers 'node', not 'sh'). Before this change: createKernel() → mount(createNodeRuntime()) kernel.exec('node -e "console.log(1)"') // throws: No shell available After this change: - If 'sh' is registered: routes through shell (existing behavior) - If only 'node' is registered: parses command string, strips 'node' prefix, spawns node directly with remaining args - If neither: throws improved error with actionable guidance Added: - #parseCommandArgs(): shell-like tokenizer (handles '...', "..." escapes) - #collectExecResult(): extracted common stdout/stderr collection logic - 3 new test cases in kernel-integration.test.ts
|
Hey! Ran into issue #64 when trying the README example — This PR adds a fallback: when Happy to iterate if you'd like a different approach — e.g. if you'd prefer to just improve the error message rather than auto-fallback. Let me know! |
…lyfills Fixes rivet-dev#63 — adds ability to disable Node.js polyfill shims (fs, http, process, Buffer, etc.) on globalThis. When includeNodeShims: false is passed to createNodeRuntime(): - globalThis.fs, globalThis.http, globalThis.process, globalThis.Buffer are NOT injected into the isolate - Useful for AI agents that need a clean globalThis scope - fs/http are still accessible via require('fs') / await import('fs') when host filesystem is permitted via permissions API: createNodeRuntime({ includeNodeShims: false }) Default: true (existing behavior unchanged). Changes: - packages/nodejs/src/kernel-runtime.ts: Added includeNodeShims to NodeRuntimeOptions - packages/nodejs/src/driver.ts: Added includeNodeShims to NodeDriverOptions, pass to runtime config - packages/nodejs/src/execution-driver.ts: buildFullBridgeCode() now keyed by includeNodeShims in a Map<boolean,string> cache; per-driver bridge code built in constructor - packages/nodejs/test/kernel-runtime.test.ts: 3 new tests for includeNodeShims=false/true
|
Hi! Just checking in — this PR is mergeable with all tests passing. Happy to address any feedback. Let me know if you'd like any changes! |
|
Fixed in v0.3, thanks for the contribution! |
|
Covered by |
Changes
fix: exec() falls back to node when sh is unavailable (fixes #64)
File: packages/core/src/kernel/kernel.ts
exec() currently throws "No shell available" when only createNodeRuntime() is mounted, because NodeRuntime registers 'node', not 'sh'. This breaks the README example immediately.
Fix: Added a fallback path — when 'sh' is not registered but 'node' is, exec() parses the command string, strips the 'node' prefix, and spawns node directly.
Now works out-of-the-box:
kernel.exec("node -e "console.log('hello')"") // ✓ instead of throwing
Changes:
feat: add includeNodeShims option (fixes #63)
Files: packages/nodejs/src/kernel-runtime.ts, packages/nodejs/src/driver.ts, packages/nodejs/src/execution-driver.ts, packages/nodejs/test/kernel-runtime.test.ts
Adds ability to disable Node.js polyfill shims (fs, http, process, Buffer, etc.) on globalThis. Useful for AI agents that need a clean global scope.
Usage:
// Clean scope: globalThis has NO injected shims
const driver = createNodeRuntime({ includeNodeShims: false });
await kernel.mount(driver);
// globalThis.fs === undefined ✓
// require('fs') still works via bridge permissions
Default: true (existing behavior unchanged).
Technical: buildFullBridgeCode() is keyed by includeNodeShims in a Map<boolean,string> cache. Each driver's bridge code is built once in the constructor.
Tests
Both changes include tests — 3 for the exec() fallback, 3 for includeNodeShims.