diff --git a/packages/cli/package.json b/packages/cli/package.json index db51b7081..5d32d887c 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@openrouter/spawn", - "version": "0.26.4", + "version": "0.26.5", "type": "module", "bin": { "spawn": "cli.js" diff --git a/packages/cli/src/shared/orchestrate.ts b/packages/cli/src/shared/orchestrate.ts index 949d6c5a2..50da47f29 100644 --- a/packages/cli/src/shared/orchestrate.ts +++ b/packages/cli/src/shared/orchestrate.ts @@ -115,13 +115,19 @@ function wrapWithRestartLoop(cmd: string): string { /** Install the spawn CLI on a remote VM. */ export async function installSpawnCli(runner: CloudRunner): Promise { 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"); diff --git a/sh/cli/install.sh b/sh/cli/install.sh index 8a804a576..dc1488c11 100755 --- a/sh/cli/install.sh +++ b/sh/cli/install.sh @@ -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