fix: guard server startup to avoid port conflicts

Add health check before starting sandbox-agent to prevent 'address already
in use' errors on subsequent requests. The isServerRunning() function probes
the health endpoint to determine if setup should be skipped.

Co-authored-by: Shelley <shelley@exe.dev>
This commit is contained in:
Shelley 2026-02-03 00:29:44 +00:00
parent 33ace91cfd
commit f547cfe7f1
2 changed files with 73 additions and 39 deletions

View file

@ -25,7 +25,7 @@ cd my-sandbox
## TypeScript Example ## TypeScript Example
```typescript ```typescript
import { getSandbox, proxyToSandbox } from "@cloudflare/sandbox"; import { getSandbox, proxyToSandbox, type Sandbox } from "@cloudflare/sandbox";
export { Sandbox } from "@cloudflare/sandbox"; export { Sandbox } from "@cloudflare/sandbox";
type Env = { type Env = {
@ -34,6 +34,16 @@ type Env = {
OPENAI_API_KEY?: string; OPENAI_API_KEY?: string;
}; };
/** Check if sandbox-agent is already running by probing its health endpoint */
async function isServerRunning(sandbox: Sandbox): Promise<boolean> {
try {
const result = await sandbox.exec("curl -sf http://localhost:8000/v1/health");
return result.success;
} catch {
return false;
}
}
export default { export default {
async fetch(request: Request, env: Env): Promise<Response> { async fetch(request: Request, env: Env): Promise<Response> {
// Proxy requests to exposed ports first // Proxy requests to exposed ports first
@ -43,35 +53,42 @@ export default {
const { hostname } = new URL(request.url); const { hostname } = new URL(request.url);
const sandbox = getSandbox(env.Sandbox, "sandbox-agent"); const sandbox = getSandbox(env.Sandbox, "sandbox-agent");
// Install sandbox-agent // Check if server is already running to avoid port conflicts
await sandbox.exec( const alreadyRunning = await isServerRunning(sandbox);
"curl -fsSL https://releases.rivet.dev/sandbox-agent/latest/install.sh | sh"
);
// Install agents if (!alreadyRunning) {
await sandbox.exec("sandbox-agent install-agent claude"); // Install sandbox-agent
await sandbox.exec("sandbox-agent install-agent codex"); await sandbox.exec(
"curl -fsSL https://releases.rivet.dev/sandbox-agent/latest/install.sh | sh"
);
// Set environment variables for agents // Install agents
const envVars: Record<string, string> = {}; await sandbox.exec("sandbox-agent install-agent claude");
if (env.ANTHROPIC_API_KEY) envVars.ANTHROPIC_API_KEY = env.ANTHROPIC_API_KEY; await sandbox.exec("sandbox-agent install-agent codex");
if (env.OPENAI_API_KEY) envVars.OPENAI_API_KEY = env.OPENAI_API_KEY;
await sandbox.setEnvVars(envVars);
// Start sandbox-agent server as background process // Set environment variables for agents
await sandbox.startProcess( const envVars: Record<string, string> = {};
"sandbox-agent server --no-token --host 0.0.0.0 --port 8000" if (env.ANTHROPIC_API_KEY) envVars.ANTHROPIC_API_KEY = env.ANTHROPIC_API_KEY;
); if (env.OPENAI_API_KEY) envVars.OPENAI_API_KEY = env.OPENAI_API_KEY;
await sandbox.setEnvVars(envVars);
// Wait for server to start // Start sandbox-agent server as background process
await new Promise((r) => setTimeout(r, 2000)); await sandbox.startProcess(
"sandbox-agent server --no-token --host 0.0.0.0 --port 8000"
);
// Wait for server to start
await new Promise((r) => setTimeout(r, 2000));
}
// Expose the port with a preview URL // Expose the port with a preview URL
const exposed = await sandbox.exposePort(8000, { hostname }); const exposed = await sandbox.exposePort(8000, { hostname });
return Response.json({ return Response.json({
endpoint: exposed.url, endpoint: exposed.url,
message: "sandbox-agent server is running", message: alreadyRunning
? "sandbox-agent server was already running"
: "sandbox-agent server started",
}); });
}, },
}; };

View file

@ -7,6 +7,16 @@ type Env = {
OPENAI_API_KEY?: string; OPENAI_API_KEY?: string;
}; };
/** Check if sandbox-agent is already running by probing its health endpoint */
async function isServerRunning(sandbox: Sandbox): Promise<boolean> {
try {
const result = await sandbox.exec("curl -sf http://localhost:8000/v1/health");
return result.success;
} catch {
return false;
}
}
export default { export default {
async fetch(request: Request, env: Env): Promise<Response> { async fetch(request: Request, env: Env): Promise<Response> {
// Proxy requests to exposed ports first // Proxy requests to exposed ports first
@ -16,28 +26,33 @@ export default {
const { hostname } = new URL(request.url); const { hostname } = new URL(request.url);
const sandbox = getSandbox(env.Sandbox, "sandbox-agent"); const sandbox = getSandbox(env.Sandbox, "sandbox-agent");
console.log("Installing sandbox-agent..."); // Check if server is already running to avoid port conflicts
await sandbox.exec( const alreadyRunning = await isServerRunning(sandbox);
"curl -fsSL https://releases.rivet.dev/sandbox-agent/latest/install.sh | sh"
);
console.log("Installing agents..."); if (!alreadyRunning) {
await sandbox.exec("sandbox-agent install-agent claude"); console.log("Installing sandbox-agent...");
await sandbox.exec("sandbox-agent install-agent codex"); await sandbox.exec(
"curl -fsSL https://releases.rivet.dev/sandbox-agent/latest/install.sh | sh"
);
// Set environment variables for agents console.log("Installing agents...");
const envVars: Record<string, string> = {}; await sandbox.exec("sandbox-agent install-agent claude");
if (env.ANTHROPIC_API_KEY) envVars.ANTHROPIC_API_KEY = env.ANTHROPIC_API_KEY; await sandbox.exec("sandbox-agent install-agent codex");
if (env.OPENAI_API_KEY) envVars.OPENAI_API_KEY = env.OPENAI_API_KEY;
await sandbox.setEnvVars(envVars);
console.log("Starting sandbox-agent server..."); // Set environment variables for agents
await sandbox.startProcess( const envVars: Record<string, string> = {};
"sandbox-agent server --no-token --host 0.0.0.0 --port 8000" if (env.ANTHROPIC_API_KEY) envVars.ANTHROPIC_API_KEY = env.ANTHROPIC_API_KEY;
); if (env.OPENAI_API_KEY) envVars.OPENAI_API_KEY = env.OPENAI_API_KEY;
await sandbox.setEnvVars(envVars);
// Wait for server to start console.log("Starting sandbox-agent server...");
await new Promise((r) => setTimeout(r, 2000)); await sandbox.startProcess(
"sandbox-agent server --no-token --host 0.0.0.0 --port 8000"
);
// Wait for server to start
await new Promise((r) => setTimeout(r, 2000));
}
// Expose the port with a preview URL // Expose the port with a preview URL
const exposed = await sandbox.exposePort(8000, { hostname }); const exposed = await sandbox.exposePort(8000, { hostname });
@ -46,7 +61,9 @@ export default {
return Response.json({ return Response.json({
endpoint: exposed.url, endpoint: exposed.url,
message: "sandbox-agent server is running", message: alreadyRunning
? "sandbox-agent server was already running"
: "sandbox-agent server started",
}); });
}, },
}; };