From 6e342a8875c999c8da951fefa78e8ba779f6ed52 Mon Sep 17 00:00:00 2001 From: Mikael Hugo Date: Wed, 29 Apr 2026 15:07:24 +0200 Subject: [PATCH] =?UTF-8?q?fix(sf-from-source):=20switch=20from=20bun=20to?= =?UTF-8?q?=20node=20=E2=80=94=20clean=20from-source=20path?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bun was the wrong runtime for our environment, two ways: 1. bun doesn't ship node:sqlite. sf-db.ts falls back through node:sqlite → better-sqlite3 → null. Result: 'No SQLite provider available' and degraded-mode filesystem-state derivation, even though sqlite is actually available (node:sqlite under node, bun:sqlite under bun — both valid, but our code only knows the node names). 2. bun's loader doesn't inherit the system library search path under Nix. libz.so.1 isn't found for forge_engine.node, so the native addon falls through to JS implementations (slower). Both warnings ("Native addon not available", "DB unavailable — degraded mode") were the symptom of "we're running under bun". Fix: use node + the existing src/resources/extensions/sf/tests/ resolve-ts.mjs loader hook (which already handles .js → .ts import-specifier remapping for runtime resolution) + --experimental-strip-types (node 22+, native in 24). Result: from-source via node loads cleanly. No native warning. No sqlite warning. No degraded mode. Exec: `./bin/sf-from-source --print "..."` returns the model output and nothing else. Drops the LD_LIBRARY_PATH zlib-injection hack that was added in 4912f6ea8 — that was working around the bun native-loader issue that doesn't exist under node. Co-Authored-By: Claude Sonnet 4.6 --- bin/sf-from-source | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/bin/sf-from-source b/bin/sf-from-source index 1e71b81cd..edf9e8583 100755 --- a/bin/sf-from-source +++ b/bin/sf-from-source @@ -1,19 +1,31 @@ #!/usr/bin/env bash # -# sf-from-source — run SF directly from this source checkout via bun. +# sf-from-source — run SF directly from this source checkout via node. # -# Purpose: every local commit in this repo (e.g. the #4251 fix) is live -# immediately without reinstalling the bun-packaged sf-run. Subagents can -# spawn sf by pointing SF_BIN_PATH at this script instead of dist/loader.js. +# Purpose: every local commit in this repo is live immediately without +# rebuilding dist/. Subagents can spawn sf by pointing SF_BIN_PATH at +# this script instead of dist/loader.js. +# +# Why node, not bun: +# - bun doesn't ship node:sqlite (sf-db.ts falls back to filesystem- +# derivation degraded mode under bun). +# - bun's native-addon loader doesn't inherit the system library +# search path under Nix (libz.so.1 not found for forge_engine.node). +# - node 22.5+ has node:sqlite built-in; node 24 supports +# --experimental-strip-types so .ts runs directly. +# - The src/resources/extensions/sf/tests/resolve-ts.mjs loader hook +# already handles .js → .ts import-specifier remapping for runtime +# resolution. # # Contract: -# - Executable shim spawn() / exec() can launch directly. +# - Executable shim; spawn() / exec() can launch directly. # - Exports SF_BIN_PATH before handing off to loader.ts so loader.ts's # `SF_BIN_PATH ||= process.argv[1]` branch preserves the shim path # instead of clobbering it with the .ts loader path (which is not # directly executable by child_process.spawn). # -# Requirements: bun on PATH, node_modules populated (`bun install` once). +# Requirements: node >= 22.5 on PATH (24+ recommended for strip-types), +# node_modules populated. set -euo pipefail SCRIPT_DIR=$(cd -- "$(dirname -- "$(readlink -f "${BASH_SOURCE[0]}")")" &>/dev/null && pwd) @@ -21,17 +33,8 @@ SF_SOURCE_ROOT=$(cd -- "$SCRIPT_DIR/.." &>/dev/null && pwd) export SF_BIN_PATH="$SCRIPT_DIR/sf-from-source" -# Native addon (forge_engine.node) links against libz / libstdc++ that are -# resolved automatically when run under node, but bun's loader doesn't -# inherit the same library search path under Nix. Prepend a Nix-store zlib -# (and stdc++ where present) so require('forge_engine.linux-x64.node') -# succeeds. No-op outside Nix (find returns nothing → empty prefix). -if [ -d /nix/store ]; then - _sf_libz_dir=$(find /nix/store -maxdepth 4 -path '*-zlib-*/lib/libz.so.1' -printf '%h\n' 2>/dev/null | head -1) - if [ -n "${_sf_libz_dir:-}" ]; then - export LD_LIBRARY_PATH="${_sf_libz_dir}${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" - fi - unset _sf_libz_dir -fi - -exec bun run "$SF_SOURCE_ROOT/src/loader.ts" "$@" +exec node \ + --import "$SF_SOURCE_ROOT/src/resources/extensions/sf/tests/resolve-ts.mjs" \ + --experimental-strip-types \ + --no-warnings \ + "$SF_SOURCE_ROOT/src/loader.ts" "$@"