From f1fb38227d9ae13d938be510c2c7b0b1ddb93239 Mon Sep 17 00:00:00 2001 From: Charles Packer Date: Wed, 31 Dec 2025 15:58:26 -0800 Subject: [PATCH] feat: prefer bun runtime (#435) --- scripts/postinstall-patches.js | 33 ++++++++++++++++++++++++++++++++- src/settings-manager.ts | 12 ++++++------ 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/scripts/postinstall-patches.js b/scripts/postinstall-patches.js index 5d355cc..cc94729 100644 --- a/scripts/postinstall-patches.js +++ b/scripts/postinstall-patches.js @@ -1,7 +1,14 @@ // Postinstall patcher for vendoring our Ink modifications without patch-package. // Copies patched runtime files from ./src/vendor into node_modules. -import { copyFileSync, existsSync, mkdirSync } from "node:fs"; +import { execSync } from "node:child_process"; +import { + copyFileSync, + existsSync, + mkdirSync, + readFileSync, + writeFileSync, +} from "node:fs"; import { createRequire } from "node:module"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; @@ -101,3 +108,27 @@ await copyToResolved( ); console.log("[patch] Ink runtime patched"); + +// On Unix with Bun available, use polyglot shebang to prefer Bun runtime. +// This enables Bun.secrets for secure keychain storage instead of fallback. +// Windows always uses #!/usr/bin/env node (polyglot shebang breaks npm wrappers). +if (process.platform !== "win32") { + try { + execSync("bun --version", { stdio: "ignore" }); + const lettaPath = join(pkgRoot, "letta.js"); + if (existsSync(lettaPath)) { + let content = readFileSync(lettaPath, "utf-8"); + if (content.startsWith("#!/usr/bin/env node")) { + content = content.replace( + "#!/usr/bin/env node", + `#!/bin/sh +":" //#; exec /usr/bin/env sh -c 'command -v bun >/dev/null && exec bun "$0" "$@" || exec node "$0" "$@"' "$0" "$@"`, + ); + writeFileSync(lettaPath, content); + console.log("[patch] Configured letta to prefer Bun runtime"); + } + } + } catch { + // Bun not available, keep node shebang + } +} diff --git a/src/settings-manager.ts b/src/settings-manager.ts index cef3f40..c5e0a61 100644 --- a/src/settings-manager.ts +++ b/src/settings-manager.ts @@ -4,6 +4,7 @@ import { homedir } from "node:os"; import { join } from "node:path"; import type { PermissionRules } from "./permissions/types"; +import { debugWarn } from "./utils/debug.js"; import { exists, mkdir, readFile, writeFile } from "./utils/fs.js"; import { deleteSecureTokens, @@ -131,15 +132,14 @@ class SettingsManager { try { const available = await this.isKeychainAvailable(); if (!available) { - console.warn( - "⚠️ System secrets are not available - using fallback storage", - ); - console.warn( - " This may occur when running in Node.js or restricted environments", + // Only show warning in debug mode - fallback storage is expected for npm users + debugWarn( + "secrets", + "System secrets not available - using fallback storage", ); } } catch (error) { - console.warn("⚠️ Could not check secrets availability:", error); + debugWarn("secrets", `Could not check secrets availability: ${error}`); } }