mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-15 06:04:43 +00:00
feat(cloudflare): add React frontend and improve deployment docs
- Add React + Vite frontend for Cloudflare example with sandbox-agent SDK - Update ensureRunning to poll health endpoint instead of fixed wait - Fix SDK fetch binding issue (globalThis.fetch.bind) - Update docs with .dev.vars format warning and container caching tip - Use containerFetch proxy pattern for reliable local dev
This commit is contained in:
parent
44382d2c12
commit
3576b7fcca
12 changed files with 619 additions and 425 deletions
|
|
@ -22,10 +22,69 @@ npm create cloudflare@latest -- my-sandbox --template=cloudflare/sandbox-sdk/exa
|
|||
cd my-sandbox
|
||||
```
|
||||
|
||||
## Dockerfile
|
||||
|
||||
Create a `Dockerfile` with sandbox-agent and agents pre-installed:
|
||||
|
||||
```dockerfile
|
||||
FROM cloudflare/sandbox:0.7.0
|
||||
|
||||
# Install sandbox-agent
|
||||
RUN curl -fsSL https://releases.rivet.dev/sandbox-agent/latest/install.sh | sh
|
||||
|
||||
# Pre-install agents
|
||||
RUN sandbox-agent install-agent claude && \
|
||||
sandbox-agent install-agent codex
|
||||
|
||||
# Required for local development with wrangler dev
|
||||
EXPOSE 8000
|
||||
```
|
||||
|
||||
<Note>
|
||||
The `EXPOSE 8000` directive is required for `wrangler dev` to proxy requests to the container. Port 3000 is reserved for the Cloudflare control plane.
|
||||
</Note>
|
||||
|
||||
## Wrangler Configuration
|
||||
|
||||
Update `wrangler.jsonc` to use your Dockerfile:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"name": "my-sandbox-agent",
|
||||
"main": "src/index.ts",
|
||||
"compatibility_date": "2025-01-01",
|
||||
"compatibility_flags": ["nodejs_compat"],
|
||||
"containers": [
|
||||
{
|
||||
"class_name": "Sandbox",
|
||||
"image": "./Dockerfile",
|
||||
"instance_type": "lite",
|
||||
"max_instances": 1
|
||||
}
|
||||
],
|
||||
"durable_objects": {
|
||||
"bindings": [
|
||||
{
|
||||
"class_name": "Sandbox",
|
||||
"name": "Sandbox"
|
||||
}
|
||||
]
|
||||
},
|
||||
"migrations": [
|
||||
{
|
||||
"new_sqlite_classes": ["Sandbox"],
|
||||
"tag": "v1"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## TypeScript Example
|
||||
|
||||
This example proxies requests to sandbox-agent via `containerFetch`, which works reliably in both local development and production:
|
||||
|
||||
```typescript
|
||||
import { getSandbox, proxyToSandbox, type Sandbox } from "@cloudflare/sandbox";
|
||||
import { getSandbox, type Sandbox } from "@cloudflare/sandbox";
|
||||
export { Sandbox } from "@cloudflare/sandbox";
|
||||
|
||||
type Env = {
|
||||
|
|
@ -34,62 +93,60 @@ type Env = {
|
|||
OPENAI_API_KEY?: string;
|
||||
};
|
||||
|
||||
/** Check if sandbox-agent is already running by probing its health endpoint */
|
||||
const PORT = 8000;
|
||||
|
||||
/** Check if sandbox-agent is already running */
|
||||
async function isServerRunning(sandbox: Sandbox): Promise<boolean> {
|
||||
try {
|
||||
const result = await sandbox.exec("curl -sf http://localhost:8000/v1/health");
|
||||
const result = await sandbox.exec(`curl -sf http://localhost:${PORT}/v1/health`);
|
||||
return result.success;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Ensure sandbox-agent is running in the container */
|
||||
async function ensureRunning(sandbox: Sandbox, env: Env): Promise<void> {
|
||||
if (await isServerRunning(sandbox)) return;
|
||||
|
||||
// Set environment variables for agents
|
||||
const envVars: Record<string, string> = {};
|
||||
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);
|
||||
|
||||
// Start sandbox-agent server
|
||||
await sandbox.startProcess(
|
||||
`sandbox-agent server --no-token --host 0.0.0.0 --port ${PORT}`
|
||||
);
|
||||
|
||||
// Poll health endpoint until server is ready
|
||||
for (let i = 0; i < 30; i++) {
|
||||
if (await isServerRunning(sandbox)) return;
|
||||
await new Promise((r) => setTimeout(r, 200));
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
async fetch(request: Request, env: Env): Promise<Response> {
|
||||
// Proxy requests to exposed ports first
|
||||
const proxyResponse = await proxyToSandbox(request, env);
|
||||
if (proxyResponse) return proxyResponse;
|
||||
const url = new URL(request.url);
|
||||
|
||||
const { hostname } = new URL(request.url);
|
||||
const sandbox = getSandbox(env.Sandbox, "sandbox-agent");
|
||||
// Proxy requests: /sandbox/:name/v1/...
|
||||
const match = url.pathname.match(/^\/sandbox\/([^/]+)(\/.*)?$/);
|
||||
if (match) {
|
||||
const [, name, path = "/"] = match;
|
||||
const sandbox = getSandbox(env.Sandbox, name);
|
||||
|
||||
// Check if server is already running to avoid port conflicts
|
||||
const alreadyRunning = await isServerRunning(sandbox);
|
||||
await ensureRunning(sandbox, env);
|
||||
|
||||
if (!alreadyRunning) {
|
||||
// Install sandbox-agent
|
||||
await sandbox.exec(
|
||||
"curl -fsSL https://releases.rivet.dev/sandbox-agent/latest/install.sh | sh"
|
||||
// Proxy request to container
|
||||
return sandbox.containerFetch(
|
||||
new Request(`http://localhost${path}${url.search}`, request),
|
||||
PORT
|
||||
);
|
||||
|
||||
// Install agents
|
||||
await sandbox.exec("sandbox-agent install-agent claude");
|
||||
await sandbox.exec("sandbox-agent install-agent codex");
|
||||
|
||||
// Set environment variables for agents
|
||||
const envVars: Record<string, string> = {};
|
||||
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);
|
||||
|
||||
// Start sandbox-agent server as background process
|
||||
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
|
||||
const exposed = await sandbox.exposePort(8000, { hostname });
|
||||
|
||||
return Response.json({
|
||||
endpoint: exposed.url,
|
||||
message: alreadyRunning
|
||||
? "sandbox-agent server was already running"
|
||||
: "sandbox-agent server started",
|
||||
});
|
||||
return new Response("Not found", { status: 404 });
|
||||
},
|
||||
};
|
||||
```
|
||||
|
|
@ -99,11 +156,10 @@ export default {
|
|||
```typescript
|
||||
import { SandboxAgent } from "sandbox-agent";
|
||||
|
||||
// Get the endpoint from the Worker
|
||||
const { endpoint } = await fetch("http://localhost:8787").then((r) => r.json());
|
||||
|
||||
// Connect to sandbox-agent
|
||||
const client = await SandboxAgent.connect({ baseUrl: endpoint });
|
||||
// Connect via the proxy endpoint
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8787/sandbox/my-sandbox",
|
||||
});
|
||||
|
||||
// Wait for server to be ready
|
||||
for (let i = 0; i < 30; i++) {
|
||||
|
|
@ -116,42 +172,49 @@ for (let i = 0; i < 30; i++) {
|
|||
}
|
||||
|
||||
// Create a session and start coding
|
||||
await client.createSession("my-session", {
|
||||
agent: "claude",
|
||||
permissionMode: "default",
|
||||
});
|
||||
await client.createSession("my-session", { agent: "claude" });
|
||||
|
||||
await client.postMessage("my-session", {
|
||||
message: "Summarize this repository",
|
||||
});
|
||||
|
||||
for await (const event of client.streamEvents("my-session")) {
|
||||
console.log(event.type, event.data);
|
||||
}
|
||||
```
|
||||
// Auto-approve permissions
|
||||
if (event.type === "permission.requested") {
|
||||
await client.replyPermission("my-session", event.data.permission_id, {
|
||||
reply: "once",
|
||||
});
|
||||
}
|
||||
|
||||
## Configuration
|
||||
|
||||
Update `wrangler.jsonc` to add environment variables:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"vars": {
|
||||
"ANTHROPIC_API_KEY": "your-api-key"
|
||||
// Handle text output
|
||||
if (event.type === "item.delta" && event.data?.delta) {
|
||||
process.stdout.write(event.data.delta);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Or use `.dev.vars` for local development:
|
||||
## Environment Variables
|
||||
|
||||
Use `.dev.vars` for local development:
|
||||
|
||||
```bash
|
||||
echo "ANTHROPIC_API_KEY=your-api-key" > .dev.vars
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Use plain `KEY=value` format in `.dev.vars`. Do not use `export KEY=value` - wrangler won't parse the bash syntax.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
The `.dev.vars` file is automatically gitignored and only used during local development with `npm run dev`.
|
||||
</Note>
|
||||
|
||||
For production, set secrets via wrangler:
|
||||
|
||||
```bash
|
||||
wrangler secret put ANTHROPIC_API_KEY
|
||||
```
|
||||
|
||||
## Local Development
|
||||
|
||||
Start the development server:
|
||||
|
|
@ -167,40 +230,22 @@ First run builds the Docker container (2-3 minutes). Subsequent runs are much fa
|
|||
Test with curl:
|
||||
|
||||
```bash
|
||||
curl http://localhost:8787
|
||||
curl http://localhost:8787/sandbox/demo/v1/health
|
||||
```
|
||||
|
||||
<Tip>
|
||||
Containers cache environment variables. If you change `.dev.vars`, either use a new sandbox name or clear existing containers:
|
||||
```bash
|
||||
docker ps -a | grep sandbox | awk '{print $1}' | xargs -r docker rm -f
|
||||
```
|
||||
</Tip>
|
||||
|
||||
## Production Deployment
|
||||
|
||||
For production, preview URLs require a custom domain with wildcard DNS routing.
|
||||
Deploy to Cloudflare:
|
||||
|
||||
See [Cloudflare Production Deployment](https://developers.cloudflare.com/sandbox/guides/production-deployment/) for setup instructions.
|
||||
|
||||
## Faster Cold Starts
|
||||
|
||||
To speed up cold starts, you can:
|
||||
|
||||
1. Create a custom Dockerfile with sandbox-agent pre-installed
|
||||
2. Pre-install agents in the Docker image
|
||||
|
||||
Example `Dockerfile`:
|
||||
|
||||
```dockerfile
|
||||
FROM docker.io/cloudflare/sandbox:0.7.0
|
||||
|
||||
RUN curl -fsSL https://releases.rivet.dev/sandbox-agent/latest/install.sh | sh && \
|
||||
sandbox-agent install-agent claude && \
|
||||
sandbox-agent install-agent codex
|
||||
```bash
|
||||
wrangler deploy
|
||||
```
|
||||
|
||||
Then update `wrangler.jsonc`:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"containers": {
|
||||
"sandbox": {
|
||||
"image": "./Dockerfile"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
For production with preview URLs (direct container access), you'll need a custom domain with wildcard DNS routing. See [Cloudflare Production Deployment](https://developers.cloudflare.com/sandbox/guides/production-deployment/) for setup instructions.
|
||||
|
|
|
|||
|
|
@ -49,9 +49,9 @@
|
|||
"deploy/index",
|
||||
"deploy/local",
|
||||
"deploy/e2b",
|
||||
"deploy/daytona",
|
||||
"deploy/vercel",
|
||||
"deploy/cloudflare",
|
||||
"deploy/daytona",
|
||||
"deploy/docker"
|
||||
]
|
||||
},
|
||||
|
|
|
|||
11
examples/cloudflare/Dockerfile
Normal file
11
examples/cloudflare/Dockerfile
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
FROM cloudflare/sandbox:0.7.0
|
||||
|
||||
# Install sandbox-agent
|
||||
RUN curl -fsSL https://releases.rivet.dev/sandbox-agent/latest/install.sh | sh
|
||||
|
||||
# Pre-install agents
|
||||
RUN sandbox-agent install-agent claude && \
|
||||
sandbox-agent install-agent codex
|
||||
|
||||
# Expose port for local dev (wrangler dev requires EXPOSE directives)
|
||||
EXPOSE 8000
|
||||
272
examples/cloudflare/frontend/App.tsx
Normal file
272
examples/cloudflare/frontend/App.tsx
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
import { useState, useRef, useEffect, useCallback } from "react";
|
||||
import { SandboxAgent } from "sandbox-agent";
|
||||
import type { PermissionEventData, QuestionEventData } from "sandbox-agent";
|
||||
|
||||
export function App() {
|
||||
const [sandboxName, setSandboxName] = useState("demo");
|
||||
const [prompt, setPrompt] = useState("");
|
||||
const [output, setOutput] = useState("");
|
||||
const [status, setStatus] = useState<"idle" | "connecting" | "ready" | "thinking">("idle");
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const clientRef = useRef<SandboxAgent | null>(null);
|
||||
const sessionIdRef = useRef<string>(`session-${Date.now()}`);
|
||||
const abortRef = useRef<AbortController | null>(null);
|
||||
const isThinkingRef = useRef(false);
|
||||
|
||||
const log = useCallback((msg: string) => {
|
||||
setOutput((prev) => prev + msg + "\n");
|
||||
}, []);
|
||||
|
||||
const connect = useCallback(async () => {
|
||||
setStatus("connecting");
|
||||
setError(null);
|
||||
setOutput("");
|
||||
|
||||
try {
|
||||
// Connect via proxy endpoint (need full URL for SDK)
|
||||
const baseUrl = `${window.location.origin}/sandbox/${encodeURIComponent(sandboxName)}`;
|
||||
log(`Connecting to sandbox: ${sandboxName}`);
|
||||
|
||||
const client = await SandboxAgent.connect({ baseUrl });
|
||||
clientRef.current = client;
|
||||
|
||||
// Wait for health (this also ensures the container is started)
|
||||
log("Waiting for sandbox-agent to be ready...");
|
||||
for (let i = 0; i < 30; i++) {
|
||||
try {
|
||||
await client.getHealth();
|
||||
break;
|
||||
} catch {
|
||||
if (i === 29) throw new Error("Timeout waiting for sandbox-agent");
|
||||
await new Promise((r) => setTimeout(r, 1000));
|
||||
}
|
||||
}
|
||||
|
||||
// Create session
|
||||
await client.createSession(sessionIdRef.current, { agent: "claude" });
|
||||
log("Session created. Ready to chat.\n");
|
||||
|
||||
setStatus("ready");
|
||||
|
||||
// Start listening for events
|
||||
startEventStream(client);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : String(err));
|
||||
setStatus("idle");
|
||||
}
|
||||
}, [sandboxName, log]);
|
||||
|
||||
const startEventStream = useCallback(
|
||||
async (client: SandboxAgent) => {
|
||||
abortRef.current?.abort();
|
||||
const controller = new AbortController();
|
||||
abortRef.current = controller;
|
||||
|
||||
try {
|
||||
for await (const event of client.streamEvents(sessionIdRef.current, undefined, controller.signal)) {
|
||||
console.log("Event:", event.type, event.data);
|
||||
|
||||
// Auto-approve permissions
|
||||
if (event.type === "permission.requested") {
|
||||
const data = event.data as PermissionEventData;
|
||||
log(`[Auto-approved] ${data.action}`);
|
||||
await client.replyPermission(sessionIdRef.current, data.permission_id, { reply: "once" });
|
||||
}
|
||||
|
||||
// Reject questions (don't support interactive input)
|
||||
if (event.type === "question.requested") {
|
||||
const data = event.data as QuestionEventData;
|
||||
log(`[Question rejected] ${data.prompt}`);
|
||||
await client.rejectQuestion(sessionIdRef.current, data.question_id);
|
||||
}
|
||||
|
||||
// Track when assistant starts thinking
|
||||
if (event.type === "item.started") {
|
||||
const item = (event.data as any)?.item;
|
||||
if (item?.role === "assistant") {
|
||||
isThinkingRef.current = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Show deltas while assistant is thinking
|
||||
if (event.type === "item.delta" && isThinkingRef.current) {
|
||||
const delta = (event.data as any)?.delta;
|
||||
if (delta) {
|
||||
const text = typeof delta === "string" ? delta : delta.type === "text" ? delta.text || "" : "";
|
||||
if (text) {
|
||||
setOutput((prev) => prev + text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Track assistant turn completion
|
||||
if (event.type === "item.completed") {
|
||||
const item = (event.data as any)?.item;
|
||||
if (item?.role === "assistant") {
|
||||
isThinkingRef.current = false;
|
||||
setOutput((prev) => prev + "\n\n");
|
||||
setStatus("ready");
|
||||
}
|
||||
}
|
||||
|
||||
// Handle errors
|
||||
if (event.type === "error") {
|
||||
const data = event.data as any;
|
||||
log(`Error: ${data?.message || JSON.stringify(data)}`);
|
||||
}
|
||||
|
||||
// Handle session end
|
||||
if (event.type === "session.ended") {
|
||||
const data = event.data as any;
|
||||
log(`Session ended: ${data?.reason || "unknown"}`);
|
||||
setStatus("idle");
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if (controller.signal.aborted) return;
|
||||
console.error("Event stream error:", err);
|
||||
}
|
||||
},
|
||||
[log]
|
||||
);
|
||||
|
||||
const send = useCallback(async () => {
|
||||
if (!clientRef.current || !prompt.trim() || status !== "ready") return;
|
||||
|
||||
const message = prompt.trim();
|
||||
setPrompt("");
|
||||
setOutput((prev) => prev + `user: ${message}\n\nassistant: `);
|
||||
setStatus("thinking");
|
||||
|
||||
try {
|
||||
await clientRef.current.postMessage(sessionIdRef.current, { message });
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : String(err));
|
||||
setStatus("ready");
|
||||
}
|
||||
}, [prompt, status]);
|
||||
|
||||
// Cleanup on unmount
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
abortRef.current?.abort();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div style={styles.container}>
|
||||
<h1 style={styles.title}>Sandbox Agent</h1>
|
||||
|
||||
{status === "idle" && (
|
||||
<div style={styles.connectForm}>
|
||||
<label style={styles.label}>
|
||||
Sandbox name:
|
||||
<input
|
||||
style={styles.input}
|
||||
value={sandboxName}
|
||||
onChange={(e) => setSandboxName(e.target.value)}
|
||||
placeholder="demo"
|
||||
/>
|
||||
</label>
|
||||
<button style={styles.button} onClick={connect}>
|
||||
Connect
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{status === "connecting" && <div style={styles.status}>Connecting to sandbox...</div>}
|
||||
|
||||
{error && <div style={styles.error}>{error}</div>}
|
||||
|
||||
{(status === "ready" || status === "thinking") && (
|
||||
<>
|
||||
<div style={styles.output}>{output}</div>
|
||||
<div style={styles.inputRow}>
|
||||
<input
|
||||
style={styles.promptInput}
|
||||
value={prompt}
|
||||
onChange={(e) => setPrompt(e.target.value)}
|
||||
onKeyDown={(e) => e.key === "Enter" && send()}
|
||||
placeholder="Enter prompt..."
|
||||
disabled={status === "thinking"}
|
||||
/>
|
||||
<button style={styles.button} onClick={send} disabled={status === "thinking"}>
|
||||
{status === "thinking" ? "..." : "Send"}
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const styles: Record<string, React.CSSProperties> = {
|
||||
container: {
|
||||
fontFamily: "system-ui, sans-serif",
|
||||
maxWidth: 800,
|
||||
margin: "2rem auto",
|
||||
padding: "1rem",
|
||||
},
|
||||
title: {
|
||||
marginBottom: "1rem",
|
||||
},
|
||||
connectForm: {
|
||||
display: "flex",
|
||||
gap: "1rem",
|
||||
alignItems: "flex-end",
|
||||
},
|
||||
label: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "0.25rem",
|
||||
fontSize: "0.875rem",
|
||||
color: "#666",
|
||||
},
|
||||
input: {
|
||||
padding: "0.5rem",
|
||||
fontSize: "1rem",
|
||||
width: 200,
|
||||
},
|
||||
button: {
|
||||
padding: "0.5rem 1rem",
|
||||
fontSize: "1rem",
|
||||
cursor: "pointer",
|
||||
backgroundColor: "#0066cc",
|
||||
color: "white",
|
||||
border: "none",
|
||||
borderRadius: 4,
|
||||
},
|
||||
status: {
|
||||
color: "#666",
|
||||
fontStyle: "italic",
|
||||
},
|
||||
error: {
|
||||
color: "#cc0000",
|
||||
padding: "0.5rem",
|
||||
backgroundColor: "#fff0f0",
|
||||
borderRadius: 4,
|
||||
marginBottom: "1rem",
|
||||
},
|
||||
output: {
|
||||
whiteSpace: "pre-wrap",
|
||||
background: "#1e1e1e",
|
||||
color: "#d4d4d4",
|
||||
padding: "1rem",
|
||||
minHeight: 300,
|
||||
fontFamily: "monospace",
|
||||
fontSize: 14,
|
||||
overflow: "auto",
|
||||
borderRadius: 4,
|
||||
},
|
||||
inputRow: {
|
||||
display: "flex",
|
||||
gap: "0.5rem",
|
||||
marginTop: "1rem",
|
||||
},
|
||||
promptInput: {
|
||||
flex: 1,
|
||||
padding: "0.5rem",
|
||||
fontSize: "1rem",
|
||||
},
|
||||
};
|
||||
12
examples/cloudflare/frontend/index.html
Normal file
12
examples/cloudflare/frontend/index.html
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Sandbox Agent</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
9
examples/cloudflare/frontend/main.tsx
Normal file
9
examples/cloudflare/frontend/main.tsx
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { App } from "./App";
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>
|
||||
);
|
||||
|
|
@ -3,17 +3,25 @@
|
|||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "wrangler dev",
|
||||
"deploy": "wrangler deploy",
|
||||
"dev": "vite build --watch & wrangler dev",
|
||||
"build": "vite build",
|
||||
"deploy": "vite build && wrangler deploy",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cloudflare/sandbox": "latest"
|
||||
"@cloudflare/sandbox": "latest",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"sandbox-agent": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cloudflare/workers-types": "latest",
|
||||
"@types/node": "latest",
|
||||
"@types/react": "^19.1.0",
|
||||
"@types/react-dom": "^19.1.0",
|
||||
"@vitejs/plugin-react": "^4.5.0",
|
||||
"typescript": "latest",
|
||||
"vite": "^6.2.0",
|
||||
"vitest": "^3.0.0",
|
||||
"wrangler": "latest"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,69 +1,76 @@
|
|||
import { getSandbox, proxyToSandbox, type Sandbox } from "@cloudflare/sandbox";
|
||||
import { getSandbox, type Sandbox } from "@cloudflare/sandbox";
|
||||
|
||||
export { Sandbox } from "@cloudflare/sandbox";
|
||||
|
||||
type Env = {
|
||||
Sandbox: DurableObjectNamespace<Sandbox>;
|
||||
ANTHROPIC_API_KEY?: string;
|
||||
OPENAI_API_KEY?: string;
|
||||
Bindings: {
|
||||
Sandbox: DurableObjectNamespace<Sandbox>;
|
||||
ASSETS: Fetcher;
|
||||
ANTHROPIC_API_KEY?: string;
|
||||
OPENAI_API_KEY?: string;
|
||||
};
|
||||
};
|
||||
|
||||
const PORT = 8000;
|
||||
|
||||
/** 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");
|
||||
const result = await sandbox.exec(`curl -sf http://localhost:${PORT}/v1/health`);
|
||||
return result.success;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Ensure sandbox-agent is running in the container */
|
||||
async function ensureRunning(sandbox: Sandbox, env: Env["Bindings"]): Promise<void> {
|
||||
if (await isServerRunning(sandbox)) return;
|
||||
|
||||
// Set environment variables for agents
|
||||
const envVars: Record<string, string> = {};
|
||||
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);
|
||||
|
||||
// Start sandbox-agent server as background process
|
||||
await sandbox.startProcess(`sandbox-agent server --no-token --host 0.0.0.0 --port ${PORT}`);
|
||||
|
||||
// Poll health endpoint until server is ready (max ~6 seconds)
|
||||
for (let i = 0; i < 30; i++) {
|
||||
if (await isServerRunning(sandbox)) return;
|
||||
await new Promise((r) => setTimeout(r, 200));
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
async fetch(request: Request, env: Env): Promise<Response> {
|
||||
// Proxy requests to exposed ports first
|
||||
const proxyResponse = await proxyToSandbox(request, env);
|
||||
if (proxyResponse) return proxyResponse;
|
||||
async fetch(request: Request, env: Env["Bindings"]): Promise<Response> {
|
||||
const url = new URL(request.url);
|
||||
|
||||
const { hostname } = new URL(request.url);
|
||||
const sandbox = getSandbox(env.Sandbox, "sandbox-agent");
|
||||
// Proxy requests to sandbox-agent: /sandbox/:name/v1/...
|
||||
const match = url.pathname.match(/^\/sandbox\/([^/]+)(\/.*)?$/);
|
||||
if (match) {
|
||||
if (!env.ANTHROPIC_API_KEY && !env.OPENAI_API_KEY) {
|
||||
return Response.json(
|
||||
{ error: "ANTHROPIC_API_KEY or OPENAI_API_KEY must be set" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
|
||||
// Check if server is already running to avoid port conflicts
|
||||
const alreadyRunning = await isServerRunning(sandbox);
|
||||
const name = match[1];
|
||||
const path = match[2] || "/";
|
||||
const sandbox = getSandbox(env.Sandbox, name);
|
||||
|
||||
if (!alreadyRunning) {
|
||||
console.log("Installing sandbox-agent...");
|
||||
await sandbox.exec(
|
||||
"curl -fsSL https://releases.rivet.dev/sandbox-agent/latest/install.sh | sh"
|
||||
await ensureRunning(sandbox, env);
|
||||
|
||||
// Proxy request to container
|
||||
return sandbox.containerFetch(
|
||||
new Request(`http://localhost${path}${url.search}`, request),
|
||||
PORT
|
||||
);
|
||||
|
||||
console.log("Installing agents...");
|
||||
await sandbox.exec("sandbox-agent install-agent claude");
|
||||
await sandbox.exec("sandbox-agent install-agent codex");
|
||||
|
||||
// Set environment variables for agents
|
||||
const envVars: Record<string, string> = {};
|
||||
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);
|
||||
|
||||
console.log("Starting sandbox-agent server...");
|
||||
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
|
||||
const exposed = await sandbox.exposePort(8000, { hostname });
|
||||
|
||||
console.log("Server accessible at:", exposed.url);
|
||||
|
||||
return Response.json({
|
||||
endpoint: exposed.url,
|
||||
message: alreadyRunning
|
||||
? "sandbox-agent server was already running"
|
||||
: "sandbox-agent server started",
|
||||
});
|
||||
// Serve frontend assets
|
||||
return env.ASSETS.fetch(request);
|
||||
},
|
||||
};
|
||||
} satisfies ExportedHandler<Env["Bindings"]>;
|
||||
|
|
|
|||
11
examples/cloudflare/vite.config.ts
Normal file
11
examples/cloudflare/vite.config.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { defineConfig } from "vite";
|
||||
import react from "@vitejs/plugin-react";
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
root: "frontend",
|
||||
build: {
|
||||
outDir: "../dist",
|
||||
emptyOutDir: true,
|
||||
},
|
||||
});
|
||||
|
|
@ -4,10 +4,14 @@
|
|||
"main": "src/cloudflare.ts",
|
||||
"compatibility_date": "2025-01-01",
|
||||
"compatibility_flags": ["nodejs_compat"],
|
||||
"assets": {
|
||||
"directory": "./dist",
|
||||
"binding": "ASSETS"
|
||||
},
|
||||
"containers": [
|
||||
{
|
||||
"class_name": "Sandbox",
|
||||
"image": "docker.io/cloudflare/sandbox:0.7.0",
|
||||
"image": "./Dockerfile",
|
||||
"instance_type": "lite",
|
||||
"max_instances": 1
|
||||
}
|
||||
|
|
|
|||
375
pnpm-lock.yaml
generated
375
pnpm-lock.yaml
generated
|
|
@ -13,13 +13,22 @@ importers:
|
|||
version: 2.7.6
|
||||
vitest:
|
||||
specifier: ^3.0.0
|
||||
version: 3.2.4(@types/debug@4.1.12)(@types/node@25.2.0)
|
||||
version: 3.2.4(@types/debug@4.1.12)(@types/node@25.2.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2)
|
||||
|
||||
examples/cloudflare:
|
||||
dependencies:
|
||||
'@cloudflare/sandbox':
|
||||
specifier: latest
|
||||
version: 0.7.0
|
||||
react:
|
||||
specifier: ^19.1.0
|
||||
version: 19.2.4
|
||||
react-dom:
|
||||
specifier: ^19.1.0
|
||||
version: 19.2.4(react@19.2.4)
|
||||
sandbox-agent:
|
||||
specifier: workspace:*
|
||||
version: link:../../sdks/typescript
|
||||
devDependencies:
|
||||
'@cloudflare/workers-types':
|
||||
specifier: latest
|
||||
|
|
@ -27,12 +36,24 @@ importers:
|
|||
'@types/node':
|
||||
specifier: latest
|
||||
version: 25.2.0
|
||||
'@types/react':
|
||||
specifier: ^19.1.0
|
||||
version: 19.2.10
|
||||
'@types/react-dom':
|
||||
specifier: ^19.1.0
|
||||
version: 19.2.3(@types/react@19.2.10)
|
||||
'@vitejs/plugin-react':
|
||||
specifier: ^4.5.0
|
||||
version: 4.7.0(vite@6.4.1(@types/node@25.2.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2))
|
||||
typescript:
|
||||
specifier: latest
|
||||
version: 5.9.3
|
||||
vite:
|
||||
specifier: ^6.2.0
|
||||
version: 6.4.1(@types/node@25.2.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2)
|
||||
vitest:
|
||||
specifier: ^3.0.0
|
||||
version: 3.2.4(@types/debug@4.1.12)(@types/node@25.2.0)
|
||||
version: 3.2.4(@types/debug@4.1.12)(@types/node@25.2.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2)
|
||||
wrangler:
|
||||
specifier: latest
|
||||
version: 4.61.1(@cloudflare/workers-types@4.20260131.0)
|
||||
|
|
@ -41,14 +62,14 @@ importers:
|
|||
dependencies:
|
||||
'@daytonaio/sdk':
|
||||
specifier: latest
|
||||
version: 0.135.0(ws@8.19.0)
|
||||
version: 0.138.0(ws@8.19.0)
|
||||
'@sandbox-agent/example-shared':
|
||||
specifier: workspace:*
|
||||
version: link:../shared
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: latest
|
||||
version: 25.0.10
|
||||
version: 25.2.0
|
||||
tsx:
|
||||
specifier: latest
|
||||
version: 4.21.0
|
||||
|
|
@ -70,7 +91,7 @@ importers:
|
|||
version: 4.0.1
|
||||
'@types/node':
|
||||
specifier: latest
|
||||
version: 25.0.10
|
||||
version: 25.2.0
|
||||
tsx:
|
||||
specifier: latest
|
||||
version: 4.21.0
|
||||
|
|
@ -79,7 +100,7 @@ importers:
|
|||
version: 5.9.3
|
||||
vitest:
|
||||
specifier: ^3.0.0
|
||||
version: 3.2.4(@types/debug@4.1.12)(@types/node@25.0.10)
|
||||
version: 3.2.4(@types/debug@4.1.12)(@types/node@25.2.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2)
|
||||
|
||||
examples/e2b:
|
||||
dependencies:
|
||||
|
|
@ -95,7 +116,7 @@ importers:
|
|||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: latest
|
||||
version: 25.0.10
|
||||
version: 25.2.0
|
||||
tsx:
|
||||
specifier: latest
|
||||
version: 4.21.0
|
||||
|
|
@ -104,7 +125,7 @@ importers:
|
|||
version: 5.9.3
|
||||
vitest:
|
||||
specifier: ^3.0.0
|
||||
version: 3.2.4(@types/debug@4.1.12)(@types/node@25.0.10)
|
||||
version: 3.2.4(@types/debug@4.1.12)(@types/node@25.2.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2)
|
||||
|
||||
examples/shared:
|
||||
dependencies:
|
||||
|
|
@ -114,7 +135,7 @@ importers:
|
|||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: latest
|
||||
version: 25.0.10
|
||||
version: 25.2.0
|
||||
typescript:
|
||||
specifier: latest
|
||||
version: 5.9.3
|
||||
|
|
@ -133,7 +154,7 @@ importers:
|
|||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: latest
|
||||
version: 25.1.0
|
||||
version: 25.2.0
|
||||
tsx:
|
||||
specifier: latest
|
||||
version: 4.21.0
|
||||
|
|
@ -142,7 +163,7 @@ importers:
|
|||
version: 5.9.3
|
||||
vitest:
|
||||
specifier: ^3.0.0
|
||||
version: 3.2.4(@types/debug@4.1.12)(@types/node@25.1.0)
|
||||
version: 3.2.4(@types/debug@4.1.12)(@types/node@25.2.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2)
|
||||
|
||||
frontend/packages/inspector:
|
||||
dependencies:
|
||||
|
|
@ -216,10 +237,10 @@ importers:
|
|||
dependencies:
|
||||
'@anthropic-ai/claude-code':
|
||||
specifier: latest
|
||||
version: 2.1.22
|
||||
version: 2.1.29
|
||||
'@openai/codex':
|
||||
specifier: latest
|
||||
version: 0.92.0
|
||||
version: 0.94.0
|
||||
cheerio:
|
||||
specifier: ^1.0.0
|
||||
version: 1.2.0
|
||||
|
|
@ -294,14 +315,14 @@ importers:
|
|||
dependencies:
|
||||
'@daytonaio/sdk':
|
||||
specifier: latest
|
||||
version: 0.135.0(ws@8.19.0)
|
||||
version: 0.138.0(ws@8.19.0)
|
||||
'@e2b/code-interpreter':
|
||||
specifier: latest
|
||||
version: 2.3.3
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: latest
|
||||
version: 25.0.10
|
||||
version: 25.2.0
|
||||
tsx:
|
||||
specifier: latest
|
||||
version: 4.21.0
|
||||
|
|
@ -326,7 +347,7 @@ importers:
|
|||
devDependencies:
|
||||
vitest:
|
||||
specifier: ^3.0.0
|
||||
version: 3.2.4(@types/debug@4.1.12)(@types/node@25.2.0)
|
||||
version: 3.2.4(@types/debug@4.1.12)(@types/node@25.2.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2)
|
||||
|
||||
sdks/cli/platforms/darwin-arm64: {}
|
||||
|
||||
|
|
@ -352,7 +373,7 @@ importers:
|
|||
version: 5.9.3
|
||||
vitest:
|
||||
specifier: ^3.0.0
|
||||
version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)
|
||||
version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2)
|
||||
|
||||
packages:
|
||||
|
||||
|
|
@ -360,8 +381,8 @@ packages:
|
|||
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
'@anthropic-ai/claude-code@2.1.22':
|
||||
resolution: {integrity: sha512-WMwUUC/Ux87LqBDBC4KI/uYE0L/jcro3XcBzyd4a/YCkGVRyruyhypeeyHqAW7bUxm72xxWaPoy0keBkxpgIpQ==}
|
||||
'@anthropic-ai/claude-code@2.1.29':
|
||||
resolution: {integrity: sha512-vMHTOXrYdnreGtKUsWdd3Bwx5fKprTyNG7shrvbx3L2/jU9jexkOJrEKmN5loeR5jrE54LSB38QpaIj8pVM6eQ==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
hasBin: true
|
||||
|
||||
|
|
@ -754,14 +775,14 @@ packages:
|
|||
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
'@daytonaio/api-client@0.135.0':
|
||||
resolution: {integrity: sha512-7/gY3FimUXtgQvyUzEnxlr6ztET7G7bG0whdc4HRmeoWIZhNX+Fr2L2IpOH55UvFkb0CY7p60Ecubx2IltlMJA==}
|
||||
'@daytonaio/api-client@0.138.0':
|
||||
resolution: {integrity: sha512-mKO3Aqk2aCnOw4ej+UxvKE+Z1ixmo9OKTAFElkvRb6UOwb5zioudqTyqEfijkA2tXUXO8yPGhQDPaICLgpPopA==}
|
||||
|
||||
'@daytonaio/sdk@0.135.0':
|
||||
resolution: {integrity: sha512-bJBBpLvFAfpcGlI2rg5xe2lKf0P5RWmt2OSL73mRyWJBQ1m2NRPijnmnE//sf62YoOOZpwL2Ykq3DkT8fczrew==}
|
||||
'@daytonaio/sdk@0.138.0':
|
||||
resolution: {integrity: sha512-cnbsflZYJ1NA4pQ2uX2lLN4w4ZQsO/xqdGDnpmwSu/LIW5F+O5gA8z4mfuWdIRcFFT4UhIpTzMuh3zRwxH7dIw==}
|
||||
|
||||
'@daytonaio/toolbox-api-client@0.135.0':
|
||||
resolution: {integrity: sha512-XkaFm3nKF9PlOJi/qZS8pXpKjDn00X/lFvtpwUwCzIZSe0sC68uJZfp7/+DNgIVU1927kBOKgiyb6OMp4MCLDw==}
|
||||
'@daytonaio/toolbox-api-client@0.138.0':
|
||||
resolution: {integrity: sha512-unM9e7MOQiyDXdY8hCW1uTctYbxpo/TGZ6L71ZXyS/j2Cnz9/ud4VWBLcQP2VzlC+lrBP2YMrhT90zSSvcNfmA==}
|
||||
|
||||
'@e2b/code-interpreter@2.3.3':
|
||||
resolution: {integrity: sha512-WOpSwc1WpvxyOijf6WMbR76BUuvd2O9ddXgCHHi65lkuy6YgQGq7oyd8PNsT331O9Tqbccjy6uF4xanSdLX1UA==}
|
||||
|
|
@ -1667,8 +1688,8 @@ packages:
|
|||
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
'@openai/codex@0.92.0':
|
||||
resolution: {integrity: sha512-DR9A2QlJDtEpMwqUGMIztTCzzCYTVrM7rqG3XuMVURnQ4b7XrScmY5RnSUuUZ/ga7wDTqw0BTmVzPurm4NX3Tw==}
|
||||
'@openai/codex@0.94.0':
|
||||
resolution: {integrity: sha512-GKOU2ty3NXls2aeiFSCnSSB6zQBtENqC5OnPa8s79Z576YP1r2DIfUrhQZzVDKmFei852E1SG4TNljFL/081gg==}
|
||||
engines: {node: '>=16'}
|
||||
hasBin: true
|
||||
|
||||
|
|
@ -2153,12 +2174,6 @@ packages:
|
|||
'@types/node@24.10.9':
|
||||
resolution: {integrity: sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==}
|
||||
|
||||
'@types/node@25.0.10':
|
||||
resolution: {integrity: sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg==}
|
||||
|
||||
'@types/node@25.1.0':
|
||||
resolution: {integrity: sha512-t7frlewr6+cbx+9Ohpl0NOTKXZNV9xHRmNOvql47BFJKcEG1CxtxlPEEe+gR9uhVWM4DwhnvTF110mIL4yP9RA==}
|
||||
|
||||
'@types/node@25.2.0':
|
||||
resolution: {integrity: sha512-DZ8VwRFUNzuqJ5khrvwMXHmvPe+zGayJhr2CDNiKB1WBE1ST8Djl00D0IC4vvNmHMdj6DlbYRIaFE7WHjlDl5w==}
|
||||
|
||||
|
|
@ -2467,10 +2482,6 @@ packages:
|
|||
chownr@1.1.4:
|
||||
resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
|
||||
|
||||
chownr@2.0.0:
|
||||
resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
chownr@3.0.0:
|
||||
resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==}
|
||||
engines: {node: '>=18'}
|
||||
|
|
@ -2868,10 +2879,6 @@ packages:
|
|||
fs-constants@1.0.0:
|
||||
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
|
||||
|
||||
fs-minipass@2.1.0:
|
||||
resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
fsevents@2.3.3:
|
||||
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||
|
|
@ -3332,22 +3339,10 @@ packages:
|
|||
resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
|
||||
minipass@3.3.6:
|
||||
resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
minipass@5.0.0:
|
||||
resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
minipass@7.1.2:
|
||||
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
|
||||
minizlib@2.1.2:
|
||||
resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
minizlib@3.1.0:
|
||||
resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==}
|
||||
engines: {node: '>= 18'}
|
||||
|
|
@ -3355,11 +3350,6 @@ packages:
|
|||
mkdirp-classic@0.5.3:
|
||||
resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
|
||||
|
||||
mkdirp@1.0.4:
|
||||
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
mlly@1.8.0:
|
||||
resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==}
|
||||
|
||||
|
|
@ -3923,11 +3913,6 @@ packages:
|
|||
tar-stream@3.1.7:
|
||||
resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==}
|
||||
|
||||
tar@6.2.1:
|
||||
resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
|
||||
engines: {node: '>=10'}
|
||||
deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me
|
||||
|
||||
tar@7.5.6:
|
||||
resolution: {integrity: sha512-xqUeu2JAIJpXyvskvU3uvQW8PAmHrtXp2KDuMJwQqW8Sqq0CaZBAQ+dKS3RBXVhU4wC5NjAdKrmh84241gO9cA==}
|
||||
engines: {node: '>=18'}
|
||||
|
|
@ -4447,9 +4432,6 @@ packages:
|
|||
yallist@3.1.1:
|
||||
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
|
||||
|
||||
yallist@4.0.0:
|
||||
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
|
||||
|
||||
yallist@5.0.0:
|
||||
resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
|
||||
engines: {node: '>=18'}
|
||||
|
|
@ -4509,7 +4491,7 @@ snapshots:
|
|||
|
||||
'@alloc/quick-lru@5.2.0': {}
|
||||
|
||||
'@anthropic-ai/claude-code@2.1.22':
|
||||
'@anthropic-ai/claude-code@2.1.29':
|
||||
optionalDependencies:
|
||||
'@img/sharp-darwin-arm64': 0.33.5
|
||||
'@img/sharp-darwin-x64': 0.33.5
|
||||
|
|
@ -5307,18 +5289,18 @@ snapshots:
|
|||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.9
|
||||
|
||||
'@daytonaio/api-client@0.135.0':
|
||||
'@daytonaio/api-client@0.138.0':
|
||||
dependencies:
|
||||
axios: 1.13.4
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
|
||||
'@daytonaio/sdk@0.135.0(ws@8.19.0)':
|
||||
'@daytonaio/sdk@0.138.0(ws@8.19.0)':
|
||||
dependencies:
|
||||
'@aws-sdk/client-s3': 3.975.0
|
||||
'@aws-sdk/lib-storage': 3.975.0(@aws-sdk/client-s3@3.975.0)
|
||||
'@daytonaio/api-client': 0.135.0
|
||||
'@daytonaio/toolbox-api-client': 0.135.0
|
||||
'@daytonaio/api-client': 0.138.0
|
||||
'@daytonaio/toolbox-api-client': 0.138.0
|
||||
'@iarna/toml': 2.2.5
|
||||
axios: 1.13.4
|
||||
busboy: 1.6.0
|
||||
|
|
@ -5329,13 +5311,13 @@ snapshots:
|
|||
isomorphic-ws: 5.0.0(ws@8.19.0)
|
||||
pathe: 2.0.3
|
||||
shell-quote: 1.8.3
|
||||
tar: 6.2.1
|
||||
tar: 7.5.6
|
||||
transitivePeerDependencies:
|
||||
- aws-crt
|
||||
- debug
|
||||
- ws
|
||||
|
||||
'@daytonaio/toolbox-api-client@0.135.0':
|
||||
'@daytonaio/toolbox-api-client@0.138.0':
|
||||
dependencies:
|
||||
axios: 1.13.4
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -5888,7 +5870,7 @@ snapshots:
|
|||
'@nodelib/fs.scandir': 2.1.5
|
||||
fastq: 1.20.1
|
||||
|
||||
'@openai/codex@0.92.0': {}
|
||||
'@openai/codex@0.94.0': {}
|
||||
|
||||
'@oslojs/encoding@1.1.0': {}
|
||||
|
||||
|
|
@ -6424,13 +6406,13 @@ snapshots:
|
|||
|
||||
'@types/docker-modem@3.0.6':
|
||||
dependencies:
|
||||
'@types/node': 24.10.9
|
||||
'@types/node': 25.2.0
|
||||
'@types/ssh2': 1.15.5
|
||||
|
||||
'@types/dockerode@4.0.1':
|
||||
dependencies:
|
||||
'@types/docker-modem': 3.0.6
|
||||
'@types/node': 24.10.9
|
||||
'@types/node': 25.2.0
|
||||
'@types/ssh2': 1.15.5
|
||||
|
||||
'@types/estree@1.0.8': {}
|
||||
|
|
@ -6463,14 +6445,6 @@ snapshots:
|
|||
dependencies:
|
||||
undici-types: 7.16.0
|
||||
|
||||
'@types/node@25.0.10':
|
||||
dependencies:
|
||||
undici-types: 7.16.0
|
||||
|
||||
'@types/node@25.1.0':
|
||||
dependencies:
|
||||
undici-types: 7.16.0
|
||||
|
||||
'@types/node@25.2.0':
|
||||
dependencies:
|
||||
undici-types: 7.16.0
|
||||
|
|
@ -6553,30 +6527,6 @@ snapshots:
|
|||
chai: 5.3.3
|
||||
tinyrainbow: 2.0.0
|
||||
|
||||
'@vitest/mocker@3.2.4(vite@5.4.21(@types/node@22.19.7))':
|
||||
dependencies:
|
||||
'@vitest/spy': 3.2.4
|
||||
estree-walker: 3.0.3
|
||||
magic-string: 0.30.21
|
||||
optionalDependencies:
|
||||
vite: 5.4.21(@types/node@22.19.7)
|
||||
|
||||
'@vitest/mocker@3.2.4(vite@5.4.21(@types/node@25.0.10))':
|
||||
dependencies:
|
||||
'@vitest/spy': 3.2.4
|
||||
estree-walker: 3.0.3
|
||||
magic-string: 0.30.21
|
||||
optionalDependencies:
|
||||
vite: 5.4.21(@types/node@25.0.10)
|
||||
|
||||
'@vitest/mocker@3.2.4(vite@5.4.21(@types/node@25.1.0))':
|
||||
dependencies:
|
||||
'@vitest/spy': 3.2.4
|
||||
estree-walker: 3.0.3
|
||||
magic-string: 0.30.21
|
||||
optionalDependencies:
|
||||
vite: 5.4.21(@types/node@25.1.0)
|
||||
|
||||
'@vitest/mocker@3.2.4(vite@5.4.21(@types/node@25.2.0))':
|
||||
dependencies:
|
||||
'@vitest/spy': 3.2.4
|
||||
|
|
@ -6936,8 +6886,6 @@ snapshots:
|
|||
|
||||
chownr@1.1.4: {}
|
||||
|
||||
chownr@2.0.0: {}
|
||||
|
||||
chownr@3.0.0: {}
|
||||
|
||||
ci-info@4.3.1: {}
|
||||
|
|
@ -7400,10 +7348,6 @@ snapshots:
|
|||
|
||||
fs-constants@1.0.0: {}
|
||||
|
||||
fs-minipass@2.1.0:
|
||||
dependencies:
|
||||
minipass: 3.3.6
|
||||
|
||||
fsevents@2.3.3:
|
||||
optional: true
|
||||
|
||||
|
|
@ -8079,27 +8023,14 @@ snapshots:
|
|||
dependencies:
|
||||
brace-expansion: 2.0.2
|
||||
|
||||
minipass@3.3.6:
|
||||
dependencies:
|
||||
yallist: 4.0.0
|
||||
|
||||
minipass@5.0.0: {}
|
||||
|
||||
minipass@7.1.2: {}
|
||||
|
||||
minizlib@2.1.2:
|
||||
dependencies:
|
||||
minipass: 3.3.6
|
||||
yallist: 4.0.0
|
||||
|
||||
minizlib@3.1.0:
|
||||
dependencies:
|
||||
minipass: 7.1.2
|
||||
|
||||
mkdirp-classic@0.5.3: {}
|
||||
|
||||
mkdirp@1.0.4: {}
|
||||
|
||||
mlly@1.8.0:
|
||||
dependencies:
|
||||
acorn: 8.15.0
|
||||
|
|
@ -8343,7 +8274,7 @@ snapshots:
|
|||
'@protobufjs/path': 1.1.2
|
||||
'@protobufjs/pool': 1.1.0
|
||||
'@protobufjs/utf8': 1.1.0
|
||||
'@types/node': 24.10.9
|
||||
'@types/node': 25.2.0
|
||||
long: 5.3.2
|
||||
|
||||
proxy-from-env@1.1.0: {}
|
||||
|
|
@ -8779,15 +8710,6 @@ snapshots:
|
|||
- bare-abort-controller
|
||||
- react-native-b4a
|
||||
|
||||
tar@6.2.1:
|
||||
dependencies:
|
||||
chownr: 2.0.0
|
||||
fs-minipass: 2.1.0
|
||||
minipass: 5.0.0
|
||||
minizlib: 2.1.2
|
||||
mkdirp: 1.0.4
|
||||
yallist: 4.0.0
|
||||
|
||||
tar@7.5.6:
|
||||
dependencies:
|
||||
'@isaacs/fs-minipass': 4.0.1
|
||||
|
|
@ -9044,15 +8966,16 @@ snapshots:
|
|||
'@types/unist': 3.0.3
|
||||
vfile-message: 4.0.3
|
||||
|
||||
vite-node@3.2.4(@types/node@22.19.7):
|
||||
vite-node@3.2.4(@types/node@22.19.7)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2):
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
debug: 4.4.3
|
||||
es-module-lexer: 1.7.0
|
||||
pathe: 2.0.3
|
||||
vite: 5.4.21(@types/node@22.19.7)
|
||||
vite: 6.4.1(@types/node@22.19.7)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- jiti
|
||||
- less
|
||||
- lightningcss
|
||||
- sass
|
||||
|
|
@ -9061,52 +8984,19 @@ snapshots:
|
|||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
- tsx
|
||||
- yaml
|
||||
|
||||
vite-node@3.2.4(@types/node@25.0.10):
|
||||
vite-node@3.2.4(@types/node@25.2.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2):
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
debug: 4.4.3
|
||||
es-module-lexer: 1.7.0
|
||||
pathe: 2.0.3
|
||||
vite: 5.4.21(@types/node@25.0.10)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- less
|
||||
- lightningcss
|
||||
- sass
|
||||
- sass-embedded
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
|
||||
vite-node@3.2.4(@types/node@25.1.0):
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
debug: 4.4.3
|
||||
es-module-lexer: 1.7.0
|
||||
pathe: 2.0.3
|
||||
vite: 5.4.21(@types/node@25.1.0)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- less
|
||||
- lightningcss
|
||||
- sass
|
||||
- sass-embedded
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
|
||||
vite-node@3.2.4(@types/node@25.2.0):
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
debug: 4.4.3
|
||||
es-module-lexer: 1.7.0
|
||||
pathe: 2.0.3
|
||||
vite: 5.4.21(@types/node@25.2.0)
|
||||
vite: 6.4.1(@types/node@25.2.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- jiti
|
||||
- less
|
||||
- lightningcss
|
||||
- sass
|
||||
|
|
@ -9115,6 +9005,8 @@ snapshots:
|
|||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
- tsx
|
||||
- yaml
|
||||
|
||||
vite@5.4.21(@types/node@22.19.7):
|
||||
dependencies:
|
||||
|
|
@ -9125,24 +9017,6 @@ snapshots:
|
|||
'@types/node': 22.19.7
|
||||
fsevents: 2.3.3
|
||||
|
||||
vite@5.4.21(@types/node@25.0.10):
|
||||
dependencies:
|
||||
esbuild: 0.21.5
|
||||
postcss: 8.5.6
|
||||
rollup: 4.56.0
|
||||
optionalDependencies:
|
||||
'@types/node': 25.0.10
|
||||
fsevents: 2.3.3
|
||||
|
||||
vite@5.4.21(@types/node@25.1.0):
|
||||
dependencies:
|
||||
esbuild: 0.21.5
|
||||
postcss: 8.5.6
|
||||
rollup: 4.56.0
|
||||
optionalDependencies:
|
||||
'@types/node': 25.1.0
|
||||
fsevents: 2.3.3
|
||||
|
||||
vite@5.4.21(@types/node@25.2.0):
|
||||
dependencies:
|
||||
esbuild: 0.21.5
|
||||
|
|
@ -9152,6 +9026,21 @@ snapshots:
|
|||
'@types/node': 25.2.0
|
||||
fsevents: 2.3.3
|
||||
|
||||
vite@6.4.1(@types/node@22.19.7)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2):
|
||||
dependencies:
|
||||
esbuild: 0.25.12
|
||||
fdir: 6.5.0(picomatch@4.0.3)
|
||||
picomatch: 4.0.3
|
||||
postcss: 8.5.6
|
||||
rollup: 4.56.0
|
||||
tinyglobby: 0.2.15
|
||||
optionalDependencies:
|
||||
'@types/node': 22.19.7
|
||||
fsevents: 2.3.3
|
||||
jiti: 1.21.7
|
||||
tsx: 4.21.0
|
||||
yaml: 2.8.2
|
||||
|
||||
vite@6.4.1(@types/node@25.2.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2):
|
||||
dependencies:
|
||||
esbuild: 0.25.12
|
||||
|
|
@ -9171,11 +9060,11 @@ snapshots:
|
|||
optionalDependencies:
|
||||
vite: 6.4.1(@types/node@25.2.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2)
|
||||
|
||||
vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.19.7):
|
||||
vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2):
|
||||
dependencies:
|
||||
'@types/chai': 5.2.3
|
||||
'@vitest/expect': 3.2.4
|
||||
'@vitest/mocker': 3.2.4(vite@5.4.21(@types/node@22.19.7))
|
||||
'@vitest/mocker': 3.2.4(vite@5.4.21(@types/node@25.2.0))
|
||||
'@vitest/pretty-format': 3.2.4
|
||||
'@vitest/runner': 3.2.4
|
||||
'@vitest/snapshot': 3.2.4
|
||||
|
|
@ -9194,12 +9083,13 @@ snapshots:
|
|||
tinypool: 1.1.1
|
||||
tinyrainbow: 2.0.0
|
||||
vite: 5.4.21(@types/node@22.19.7)
|
||||
vite-node: 3.2.4(@types/node@22.19.7)
|
||||
vite-node: 3.2.4(@types/node@22.19.7)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2)
|
||||
why-is-node-running: 2.3.0
|
||||
optionalDependencies:
|
||||
'@types/debug': 4.1.12
|
||||
'@types/node': 22.19.7
|
||||
transitivePeerDependencies:
|
||||
- jiti
|
||||
- less
|
||||
- lightningcss
|
||||
- msw
|
||||
|
|
@ -9209,86 +9099,10 @@ snapshots:
|
|||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
- tsx
|
||||
- yaml
|
||||
|
||||
vitest@3.2.4(@types/debug@4.1.12)(@types/node@25.0.10):
|
||||
dependencies:
|
||||
'@types/chai': 5.2.3
|
||||
'@vitest/expect': 3.2.4
|
||||
'@vitest/mocker': 3.2.4(vite@5.4.21(@types/node@25.0.10))
|
||||
'@vitest/pretty-format': 3.2.4
|
||||
'@vitest/runner': 3.2.4
|
||||
'@vitest/snapshot': 3.2.4
|
||||
'@vitest/spy': 3.2.4
|
||||
'@vitest/utils': 3.2.4
|
||||
chai: 5.3.3
|
||||
debug: 4.4.3
|
||||
expect-type: 1.3.0
|
||||
magic-string: 0.30.21
|
||||
pathe: 2.0.3
|
||||
picomatch: 4.0.3
|
||||
std-env: 3.10.0
|
||||
tinybench: 2.9.0
|
||||
tinyexec: 0.3.2
|
||||
tinyglobby: 0.2.15
|
||||
tinypool: 1.1.1
|
||||
tinyrainbow: 2.0.0
|
||||
vite: 5.4.21(@types/node@25.0.10)
|
||||
vite-node: 3.2.4(@types/node@25.0.10)
|
||||
why-is-node-running: 2.3.0
|
||||
optionalDependencies:
|
||||
'@types/debug': 4.1.12
|
||||
'@types/node': 25.0.10
|
||||
transitivePeerDependencies:
|
||||
- less
|
||||
- lightningcss
|
||||
- msw
|
||||
- sass
|
||||
- sass-embedded
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
|
||||
vitest@3.2.4(@types/debug@4.1.12)(@types/node@25.1.0):
|
||||
dependencies:
|
||||
'@types/chai': 5.2.3
|
||||
'@vitest/expect': 3.2.4
|
||||
'@vitest/mocker': 3.2.4(vite@5.4.21(@types/node@25.1.0))
|
||||
'@vitest/pretty-format': 3.2.4
|
||||
'@vitest/runner': 3.2.4
|
||||
'@vitest/snapshot': 3.2.4
|
||||
'@vitest/spy': 3.2.4
|
||||
'@vitest/utils': 3.2.4
|
||||
chai: 5.3.3
|
||||
debug: 4.4.3
|
||||
expect-type: 1.3.0
|
||||
magic-string: 0.30.21
|
||||
pathe: 2.0.3
|
||||
picomatch: 4.0.3
|
||||
std-env: 3.10.0
|
||||
tinybench: 2.9.0
|
||||
tinyexec: 0.3.2
|
||||
tinyglobby: 0.2.15
|
||||
tinypool: 1.1.1
|
||||
tinyrainbow: 2.0.0
|
||||
vite: 5.4.21(@types/node@25.1.0)
|
||||
vite-node: 3.2.4(@types/node@25.1.0)
|
||||
why-is-node-running: 2.3.0
|
||||
optionalDependencies:
|
||||
'@types/debug': 4.1.12
|
||||
'@types/node': 25.1.0
|
||||
transitivePeerDependencies:
|
||||
- less
|
||||
- lightningcss
|
||||
- msw
|
||||
- sass
|
||||
- sass-embedded
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
|
||||
vitest@3.2.4(@types/debug@4.1.12)(@types/node@25.2.0):
|
||||
vitest@3.2.4(@types/debug@4.1.12)(@types/node@25.2.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2):
|
||||
dependencies:
|
||||
'@types/chai': 5.2.3
|
||||
'@vitest/expect': 3.2.4
|
||||
|
|
@ -9311,12 +9125,13 @@ snapshots:
|
|||
tinypool: 1.1.1
|
||||
tinyrainbow: 2.0.0
|
||||
vite: 5.4.21(@types/node@25.2.0)
|
||||
vite-node: 3.2.4(@types/node@25.2.0)
|
||||
vite-node: 3.2.4(@types/node@25.2.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2)
|
||||
why-is-node-running: 2.3.0
|
||||
optionalDependencies:
|
||||
'@types/debug': 4.1.12
|
||||
'@types/node': 25.2.0
|
||||
transitivePeerDependencies:
|
||||
- jiti
|
||||
- less
|
||||
- lightningcss
|
||||
- msw
|
||||
|
|
@ -9326,6 +9141,8 @@ snapshots:
|
|||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
- tsx
|
||||
- yaml
|
||||
|
||||
vscode-languageserver-textdocument@1.0.12: {}
|
||||
|
||||
|
|
@ -9417,8 +9234,6 @@ snapshots:
|
|||
|
||||
yallist@3.1.1: {}
|
||||
|
||||
yallist@4.0.0: {}
|
||||
|
||||
yallist@5.0.0: {}
|
||||
|
||||
yaml@2.8.2: {}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ export class SandboxAgent {
|
|||
private constructor(options: SandboxAgentConnectOptions) {
|
||||
this.baseUrl = options.baseUrl.replace(/\/$/, "");
|
||||
this.token = options.token;
|
||||
this.fetcher = options.fetch ?? globalThis.fetch;
|
||||
this.fetcher = options.fetch ?? globalThis.fetch.bind(globalThis);
|
||||
this.defaultHeaders = options.headers;
|
||||
|
||||
if (!this.fetcher) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue