fix(sprite): pass timeoutSecs through to runSprite, add kill-on-timeout (#2060)

runSprite was wired as CloudRunner.runServer but silently dropped the
timeoutSecs parameter. All other clouds (Hetzner, DO, AWS, GCP, Daytona)
implement kill-on-timeout via setTimeout+killWithTimeout; Sprite had zero
timeout protection, so a hung agent install (e.g. ZeroClaw's 600s Rust
compile, Claude Code's 300s install) would hang forever on Sprite.

Matches the pattern used by every other cloud provider.

Agent: team-lead

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
A 2026-03-01 05:21:26 -08:00 committed by GitHub
parent 40e14c2b6b
commit cef14ce9ea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 6 additions and 3 deletions

View file

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

View file

@ -14,7 +14,7 @@ import {
toKebabCase,
defaultSpawnName,
} from "../shared/ui";
import { sleep, spawnInteractive } from "../shared/ssh";
import { sleep, spawnInteractive, killWithTimeout } from "../shared/ssh";
import { hasMessage } from "@openrouter/spawn-shared";
import { getSpawnDir } from "../history.js";
@ -449,7 +449,7 @@ export function saveVmConnection(): void {
/**
* Run a command on the remote sprite. Retries on transient errors.
*/
export async function runSprite(cmd: string): Promise<void> {
export async function runSprite(cmd: string, timeoutSecs?: number): Promise<void> {
const spriteCmd = getSpriteCmd()!;
await spriteRetry("sprite exec", async () => {
const proc = Bun.spawn(
@ -472,7 +472,10 @@ export async function runSprite(cmd: string): Promise<void> {
],
},
);
const timeout = (timeoutSecs || 300) * 1000;
const timer = setTimeout(() => killWithTimeout(proc), timeout);
const exitCode = await proc.exited;
clearTimeout(timer);
if (exitCode !== 0) {
throw new Error(`sprite exec failed (exit ${exitCode}): ${cmd.slice(0, 80)}`);
}