chore: recover wellington workspace state

This commit is contained in:
Nathan Flurry 2026-03-09 19:59:55 -07:00
parent 5d65013aa5
commit c294ca85be
366 changed files with 1265 additions and 53395 deletions

View file

@ -1,5 +1,5 @@
FROM node:22-bookworm-slim
RUN apt-get update && apt-get install -y curl ca-certificates && rm -rf /var/lib/apt/lists/*
RUN curl -fsSL https://releases.rivet.dev/sandbox-agent/0.3.x/install.sh | sh
RUN curl -fsSL https://releases.rivet.dev/sandbox-agent/0.2.x/install.sh | sh
RUN sandbox-agent install-agent claude
RUN sandbox-agent install-agent codex

View file

@ -1,5 +1,5 @@
FROM node:22-bookworm-slim
RUN apt-get update && apt-get install -y curl ca-certificates && rm -rf /var/lib/apt/lists/*
RUN curl -fsSL https://releases.rivet.dev/sandbox-agent/0.3.x/install.sh | sh
RUN curl -fsSL https://releases.rivet.dev/sandbox-agent/0.2.x/install.sh | sh
RUN sandbox-agent install-agent claude
RUN sandbox-agent install-agent codex

View file

@ -1,6 +1,6 @@
import { SimpleBox } from "@boxlite-ai/boxlite";
import { SandboxAgent } from "sandbox-agent";
import { detectAgent, buildInspectorUrl } from "@sandbox-agent/example-shared";
import { detectAgent, buildInspectorUrl, waitForHealth } from "@sandbox-agent/example-shared";
import { setupImage, OCI_DIR } from "./setup-image.ts";
const env: Record<string, string> = {};
@ -26,7 +26,9 @@ if (result.exitCode !== 0) throw new Error(`Failed to start server: ${result.std
const baseUrl = "http://localhost:3000";
console.log("Connecting to server...");
console.log("Waiting for server...");
await waitForHealth({ baseUrl });
const client = await SandboxAgent.connect({ baseUrl });
const session = await client.createSession({ agent: detectAgent(), sessionInit: { cwd: "/root", mcpServers: [] } });
const sessionId = session.id;

View file

@ -1,7 +1,7 @@
FROM cloudflare/sandbox:0.7.0
# Install sandbox-agent
RUN curl -fsSL https://releases.rivet.dev/sandbox-agent/0.3.x/install.sh | sh
RUN curl -fsSL https://releases.rivet.dev/sandbox-agent/0.2.x/install.sh | sh
# Pre-install agents
RUN sandbox-agent install-agent claude && \

View file

@ -10,7 +10,7 @@ import {
type ProviderName,
} from "computesdk";
import { SandboxAgent } from "sandbox-agent";
import { detectAgent, buildInspectorUrl } from "@sandbox-agent/example-shared";
import { detectAgent, buildInspectorUrl, waitForHealth } from "@sandbox-agent/example-shared";
import { fileURLToPath } from "node:url";
import { resolve } from "node:path";
@ -116,6 +116,9 @@ export async function setupComputeSdkSandboxAgent(): Promise<{
const baseUrl = await sandbox.getUrl({ port: PORT });
console.log("Waiting for server...");
await waitForHealth({ baseUrl });
const cleanup = async () => {
try {
await sandbox.destroy();

View file

@ -1,6 +1,6 @@
import { Daytona, Image } from "@daytonaio/sdk";
import { SandboxAgent } from "sandbox-agent";
import { detectAgent, buildInspectorUrl } from "@sandbox-agent/example-shared";
import { detectAgent, buildInspectorUrl, waitForHealth } from "@sandbox-agent/example-shared";
const daytona = new Daytona();
@ -13,7 +13,7 @@ if (process.env.OPENAI_API_KEY)
// Build a custom image with sandbox-agent pre-installed (slower first run, faster subsequent runs)
const image = Image.base("ubuntu:22.04").runCommands(
"apt-get update && apt-get install -y curl ca-certificates",
"curl -fsSL https://releases.rivet.dev/sandbox-agent/0.3.x/install.sh | sh",
"curl -fsSL https://releases.rivet.dev/sandbox-agent/0.2.x/install.sh | sh",
);
console.log("Creating Daytona sandbox (first run builds the base image and may take a few minutes, subsequent runs are fast)...");
@ -25,7 +25,9 @@ await sandbox.process.executeCommand(
const baseUrl = (await sandbox.getSignedPreviewUrl(3000, 4 * 60 * 60)).url;
console.log("Connecting to server...");
console.log("Waiting for server...");
await waitForHealth({ baseUrl });
const client = await SandboxAgent.connect({ baseUrl });
const session = await client.createSession({ agent: detectAgent(), sessionInit: { cwd: "/home/daytona", mcpServers: [] } });
const sessionId = session.id;

View file

@ -1,6 +1,6 @@
import { Daytona } from "@daytonaio/sdk";
import { SandboxAgent } from "sandbox-agent";
import { detectAgent, buildInspectorUrl } from "@sandbox-agent/example-shared";
import { detectAgent, buildInspectorUrl, waitForHealth } from "@sandbox-agent/example-shared";
const daytona = new Daytona();
@ -17,7 +17,7 @@ const sandbox = await daytona.create({ envVars, autoStopInterval: 0 });
// Install sandbox-agent and start server
console.log("Installing sandbox-agent...");
await sandbox.process.executeCommand(
"curl -fsSL https://releases.rivet.dev/sandbox-agent/0.3.x/install.sh | sh",
"curl -fsSL https://releases.rivet.dev/sandbox-agent/0.2.x/install.sh | sh",
);
console.log("Installing agents...");
@ -30,7 +30,9 @@ await sandbox.process.executeCommand(
const baseUrl = (await sandbox.getSignedPreviewUrl(3000, 4 * 60 * 60)).url;
console.log("Connecting to server...");
console.log("Waiting for server...");
await waitForHealth({ baseUrl });
const client = await SandboxAgent.connect({ baseUrl });
const session = await client.createSession({ agent: detectAgent(), sessionInit: { cwd: "/home/daytona", mcpServers: [] } });
const sessionId = session.id;

View file

@ -1,16 +1,9 @@
import Docker from "dockerode";
import fs from "node:fs";
import path from "node:path";
import { SandboxAgent } from "sandbox-agent";
import { detectAgent, buildInspectorUrl } from "@sandbox-agent/example-shared";
import { detectAgent, buildInspectorUrl, waitForHealth } from "@sandbox-agent/example-shared";
const IMAGE = "node:22-bookworm-slim";
const IMAGE = "alpine:latest";
const PORT = 3000;
const agent = detectAgent();
const codexAuthPath = process.env.HOME ? path.join(process.env.HOME, ".codex", "auth.json") : null;
const bindMounts = codexAuthPath && fs.existsSync(codexAuthPath)
? [`${codexAuthPath}:/root/.codex/auth.json:ro`]
: [];
const docker = new Docker({ socketPath: "/var/run/docker.sock" });
@ -31,30 +24,29 @@ console.log("Starting container...");
const container = await docker.createContainer({
Image: IMAGE,
Cmd: ["sh", "-c", [
"apt-get update",
"DEBIAN_FRONTEND=noninteractive apt-get install -y curl ca-certificates bash libstdc++6",
"rm -rf /var/lib/apt/lists/*",
"curl -fsSL https://releases.rivet.dev/sandbox-agent/0.3.x/install.sh | sh",
"apk add --no-cache curl ca-certificates libstdc++ libgcc bash",
"curl -fsSL https://releases.rivet.dev/sandbox-agent/0.2.x/install.sh | sh",
"sandbox-agent install-agent claude",
"sandbox-agent install-agent codex",
`sandbox-agent server --no-token --host 0.0.0.0 --port ${PORT}`,
].join(" && ")],
Env: [
process.env.ANTHROPIC_API_KEY ? `ANTHROPIC_API_KEY=${process.env.ANTHROPIC_API_KEY}` : "",
process.env.OPENAI_API_KEY ? `OPENAI_API_KEY=${process.env.OPENAI_API_KEY}` : "",
process.env.CODEX_API_KEY ? `CODEX_API_KEY=${process.env.CODEX_API_KEY}` : "",
].filter(Boolean),
ExposedPorts: { [`${PORT}/tcp`]: {} },
HostConfig: {
AutoRemove: true,
PortBindings: { [`${PORT}/tcp`]: [{ HostPort: `${PORT}` }] },
Binds: bindMounts,
},
});
await container.start();
const baseUrl = `http://127.0.0.1:${PORT}`;
await waitForHealth({ baseUrl });
const client = await SandboxAgent.connect({ baseUrl });
const session = await client.createSession({ agent, sessionInit: { cwd: "/root", mcpServers: [] } });
const session = await client.createSession({ agent: detectAgent(), sessionInit: { cwd: "/root", mcpServers: [] } });
const sessionId = session.id;
console.log(` UI: ${buildInspectorUrl({ baseUrl, sessionId })}`);

View file

@ -1,6 +1,6 @@
import { Sandbox } from "@e2b/code-interpreter";
import { SandboxAgent } from "sandbox-agent";
import { detectAgent, buildInspectorUrl } from "@sandbox-agent/example-shared";
import { detectAgent, buildInspectorUrl, waitForHealth } from "@sandbox-agent/example-shared";
const envs: Record<string, string> = {};
if (process.env.ANTHROPIC_API_KEY) envs.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;
@ -16,7 +16,7 @@ const run = async (cmd: string) => {
};
console.log("Installing sandbox-agent...");
await run("curl -fsSL https://releases.rivet.dev/sandbox-agent/0.3.x/install.sh | sh");
await run("curl -fsSL https://releases.rivet.dev/sandbox-agent/0.2.x/install.sh | sh");
console.log("Installing agents...");
await run("sandbox-agent install-agent claude");
@ -27,7 +27,9 @@ await sandbox.commands.run("sandbox-agent server --no-token --host 0.0.0.0 --por
const baseUrl = `https://${sandbox.getHost(3000)}`;
console.log("Connecting to server...");
console.log("Waiting for server...");
await waitForHealth({ baseUrl });
const client = await SandboxAgent.connect({ baseUrl });
const session = await client.createSession({ agent: detectAgent(), sessionInit: { cwd: "/home/user", mcpServers: [] } });
const sessionId = session.id;

View file

@ -11,7 +11,6 @@ COPY sdks/typescript/ sdks/typescript/
COPY sdks/acp-http-client/ sdks/acp-http-client/
COPY sdks/cli-shared/ sdks/cli-shared/
COPY sdks/persist-indexeddb/ sdks/persist-indexeddb/
COPY sdks/react/ sdks/react/
COPY frontend/packages/inspector/ frontend/packages/inspector/
COPY docs/openapi.json docs/

View file

@ -4,6 +4,7 @@ import fs from "node:fs";
import path from "node:path";
import { PassThrough } from "node:stream";
import { fileURLToPath } from "node:url";
import { waitForHealth } from "./sandbox-agent-client.ts";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const EXAMPLE_IMAGE = "sandbox-agent-examples:latest";
@ -172,7 +173,7 @@ async function ensureExampleImage(_docker: Docker): Promise<string> {
}
/**
* Start a Docker container running sandbox-agent.
* Start a Docker container running sandbox-agent and wait for it to be healthy.
* Registers SIGINT/SIGTERM handlers for cleanup.
*/
export async function startDockerSandbox(opts: DockerSandboxOptions): Promise<DockerSandbox> {
@ -274,8 +275,18 @@ export async function startDockerSandbox(opts: DockerSandboxOptions): Promise<Do
}
const baseUrl = `http://127.0.0.1:${mappedHostPort}`;
try {
await waitForHealth({ baseUrl });
} catch (err) {
stopStartupLogs();
console.error(" Container logs:");
for (const chunk of logChunks) {
process.stderr.write(` ${chunk}`);
}
throw err;
}
stopStartupLogs();
console.log(` Started (${baseUrl})`);
console.log(` Ready (${baseUrl})`);
const cleanup = async () => {
stopStartupLogs();

View file

@ -3,6 +3,8 @@
* Provides minimal helpers for connecting to and interacting with sandbox-agent servers.
*/
import { setTimeout as delay } from "node:timers/promises";
function normalizeBaseUrl(baseUrl: string): string {
return baseUrl.replace(/\/+$/, "");
}
@ -72,6 +74,41 @@ export function buildHeaders({
return headers;
}
export async function waitForHealth({
baseUrl,
token,
extraHeaders,
timeoutMs = 120_000,
}: {
baseUrl: string;
token?: string;
extraHeaders?: Record<string, string>;
timeoutMs?: number;
}): Promise<void> {
const normalized = normalizeBaseUrl(baseUrl);
const deadline = Date.now() + timeoutMs;
let lastError: unknown;
while (Date.now() < deadline) {
try {
const headers = buildHeaders({ token, extraHeaders });
const response = await fetch(`${normalized}/v1/health`, { headers });
if (response.ok) {
const data = await response.json();
if (data?.status === "ok") {
return;
}
lastError = new Error(`Unexpected health response: ${JSON.stringify(data)}`);
} else {
lastError = new Error(`Health check failed: ${response.status}`);
}
} catch (error) {
lastError = error;
}
await delay(500);
}
throw (lastError ?? new Error("Timed out waiting for /v1/health")) as Error;
}
export function generateSessionId(): string {
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
let id = "session-";
@ -107,3 +144,4 @@ export function detectAgent(): string {
}
return "claude";
}

View file

@ -1,6 +1,6 @@
import { Sandbox } from "@vercel/sandbox";
import { SandboxAgent } from "sandbox-agent";
import { detectAgent, buildInspectorUrl } from "@sandbox-agent/example-shared";
import { detectAgent, buildInspectorUrl, waitForHealth } from "@sandbox-agent/example-shared";
const envs: Record<string, string> = {};
if (process.env.ANTHROPIC_API_KEY) envs.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;
@ -22,7 +22,7 @@ const run = async (cmd: string, args: string[] = []) => {
};
console.log("Installing sandbox-agent...");
await run("sh", ["-c", "curl -fsSL https://releases.rivet.dev/sandbox-agent/0.3.x/install.sh | sh"]);
await run("sh", ["-c", "curl -fsSL https://releases.rivet.dev/sandbox-agent/0.2.x/install.sh | sh"]);
console.log("Installing agents...");
await run("sandbox-agent", ["install-agent", "claude"]);
@ -38,7 +38,9 @@ await sandbox.runCommand({
const baseUrl = sandbox.domain(3000);
console.log("Connecting to server...");
console.log("Waiting for server...");
await waitForHealth({ baseUrl });
const client = await SandboxAgent.connect({ baseUrl });
const session = await client.createSession({ agent: detectAgent(), sessionInit: { cwd: "/home/vercel-sandbox", mcpServers: [] } });
const sessionId = session.id;