fix: installSpawnCli fails on Sprite — bun shim doesn't work (#2993)

Sprite has a bun shim at /.sprite/bin/bun that delegates to
$HOME/.bun/bin/bun, but that binary doesn't exist on fresh VMs.
`command -v bun` returns true (finds the shim) so the install script
skips bun installation, then bun fails when actually invoked.

Fixed in two places:
- installSpawnCli: source shell profiles, test `bun --version` (not
  just existence), and install bun fresh if it doesn't work
- install.sh: replace `command -v bun` with `bun --version` to detect
  broken shims

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ahmed Abushagur 2026-03-25 17:36:12 -07:00 committed by GitHub
parent b47d6bbe1d
commit 90dde882d0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 18 additions and 9 deletions

View file

@ -1,6 +1,6 @@
{
"name": "@openrouter/spawn",
"version": "0.26.4",
"version": "0.26.5",
"type": "module",
"bin": {
"spawn": "cli.js"

View file

@ -115,13 +115,19 @@ function wrapWithRestartLoop(cmd: string): string {
/** Install the spawn CLI on a remote VM. */
export async function installSpawnCli(runner: CloudRunner): Promise<void> {
logStep("Installing spawn CLI on VM...");
// Build PATH explicitly — non-interactive bash skips .bashrc (PS1 guard),
// and some platforms (Sprite) have a broken bun shim that finds via
// `command -v` but doesn't actually work. We prepend all known bun
// locations so the real binary is found first, then test `bun --version`
// (not just existence) and install bun fresh if it doesn't work.
const installCmd = [
'export BUN_INSTALL="${BUN_INSTALL:-$HOME/.bun}"',
'export PATH="$BUN_INSTALL/bin:$HOME/.local/bin:$HOME/.npm-global/bin:/.sprite/languages/bun/bin:/usr/local/bin:$PATH"',
'if ! bun --version >/dev/null 2>&1; then curl -fsSL https://bun.sh/install | bash && export PATH="$HOME/.bun/bin:$PATH"; fi',
"curl -fsSL https://openrouter.ai/labs/spawn/cli/install.sh | bash",
].join("; ");
const result = await asyncTryCatch(() =>
withRetry(
"spawn CLI install",
() => wrapSshCall(runner.runServer("curl -fsSL https://openrouter.ai/labs/spawn/cli/install.sh | bash")),
2,
5,
),
withRetry("spawn CLI install", () => wrapSshCall(runner.runServer(installCmd)), 2, 5),
);
if (!result.ok) {
logWarn("Spawn CLI install failed — recursive spawning will not be available on this VM");

View file

@ -305,8 +305,11 @@ _SPAWN_ORIG_PATH="${PATH}"
export BUN_INSTALL="${BUN_INSTALL:-${HOME}/.bun}"
export PATH="${BUN_INSTALL}/bin:${HOME}/.local/bin:${PATH}"
if ! command -v bun &>/dev/null; then
log_step "bun not found. Installing bun..."
# Check that bun exists AND actually works. Some platforms (e.g. Sprite)
# have a bun shim that delegates to $HOME/.bun/bin/bun — if that binary
# doesn't exist, `command -v bun` returns 0 but `bun --version` fails.
if ! bun --version &>/dev/null; then
log_step "bun not found or not working. Installing bun..."
# Download the bun installer to a temp file and verify its SHA-256 hash
# before executing. This defends against a compromised bun.sh CDN or