fix(cloudflare): fix streaming responses

This commit is contained in:
Nathan Flurry 2026-02-25 01:39:27 -08:00
parent e24b7cb140
commit a3fe0cc764
6 changed files with 266 additions and 124 deletions

View file

@ -75,7 +75,16 @@ app.post("/sandbox/:name/prompt", async (c) => {
const sandbox = await getReadySandbox(c.req.param("name"), c.env);
const sdk = await SandboxAgent.connect({
fetch: (input, init) => sandbox.containerFetch(input as Request | string | URL, init, PORT),
fetch: (input, init) =>
sandbox.containerFetch(
input as Request | string | URL,
{
...(init ?? {}),
// Avoid passing AbortSignal through containerFetch; it can drop streamed session updates.
signal: undefined,
},
PORT,
),
});
const session = await sdk.createSession({ agent: "codex" });
@ -103,6 +112,33 @@ export default app;
Create the SDK client inside the Worker using custom `fetch` backed by `sandbox.containerFetch(...)`.
This keeps all Sandbox Agent calls inside the Cloudflare sandbox routing path and does not require a `baseUrl`.
## Troubleshooting streaming updates
If you only receive:
- outbound `session/prompt`
- final `{ stopReason: "end_turn" }`
then the streamed update channel dropped. In Cloudflare sandbox paths, this is typically caused by forwarding `AbortSignal` from SDK fetch init into `containerFetch(...)`.
Fix:
```ts
const sdk = await SandboxAgent.connect({
fetch: (input, init) =>
sandbox.containerFetch(
input as Request | string | URL,
{
...(init ?? {}),
// Avoid passing AbortSignal through containerFetch; it can drop streamed session updates.
signal: undefined,
},
PORT,
),
});
```
This keeps prompt completion behavior the same, but restores streamed text/tool updates.
## Local development
```bash

View file

@ -39,12 +39,44 @@ curl http://localhost:8787
Test prompt routing through the SDK with a custom sandbox fetch handler:
```bash
curl -X POST "http://localhost:8787/sandbox/demo/prompt" \
curl -N -X POST "http://localhost:8787/sandbox/demo/prompt" \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{"agent":"codex","prompt":"Reply with one short sentence."}'
```
The response includes `events`, an array of all recorded session events for that prompt.
The response is an SSE stream with events:
- `session.created`
- `session.event`
- `prompt.completed`
- `done`
### Troubleshooting: only two events
If you only see:
- outbound `session/prompt`
- inbound prompt result with `stopReason: "end_turn"`
then ACP `session/update` notifications are not flowing. In Cloudflare sandbox paths this can happen if you forward `AbortSignal` from SDK fetch init into `containerFetch(...)` for long-lived ACP SSE requests.
Use:
```ts
const sdk = await SandboxAgent.connect({
fetch: (input, init) =>
sandbox.containerFetch(
input as Request | string | URL,
{
...(init ?? {}),
// Avoid passing AbortSignal through containerFetch; it can drop ACP SSE updates.
signal: undefined,
},
PORT,
),
});
```
Without `session/update` events, assistant text/tool deltas will not appear in UI streams.
## Deploy

View file

@ -1,7 +1,8 @@
import { getSandbox, type Sandbox } from "@cloudflare/sandbox";
import { Hono } from "hono";
import { HTTPException } from "hono/http-exception";
import { runPromptTest, type PromptTestRequest } from "./prompt-test";
import { streamSSE } from "hono/streaming";
import { runPromptEndpointStream, type PromptRequest } from "./prompt-endpoint";
export { Sandbox } from "@cloudflare/sandbox";
@ -49,7 +50,15 @@ async function getReadySandbox(name: string, env: Bindings): Promise<Sandbox> {
async function proxyToSandbox(sandbox: Sandbox, request: Request, path: string): Promise<Response> {
const query = new URL(request.url).search;
return sandbox.containerFetch(new Request(`http://localhost${path}${query}`, request), PORT);
return sandbox.containerFetch(
`http://localhost${path}${query}`,
{
method: request.method,
headers: request.headers,
body: request.body,
},
PORT,
);
}
const app = new Hono<AppEnv>();
@ -63,15 +72,34 @@ app.post("/sandbox/:name/prompt", async (c) => {
throw new HTTPException(400, { message: "Content-Type must be application/json" });
}
let payload: PromptTestRequest;
let payload: PromptRequest;
try {
payload = await c.req.json<PromptTestRequest>();
payload = await c.req.json<PromptRequest>();
} catch {
throw new HTTPException(400, { message: "Invalid JSON body" });
}
const sandbox = await getReadySandbox(c.req.param("name"), c.env);
return c.json(await runPromptTest(sandbox, payload, PORT));
return streamSSE(c, async (stream) => {
try {
await runPromptEndpointStream(sandbox, payload, PORT, async (event) => {
await stream.writeSSE({
event: event.type,
data: JSON.stringify(event),
});
});
await stream.writeSSE({
event: "done",
data: JSON.stringify({ ok: true }),
});
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
await stream.writeSSE({
event: "error",
data: JSON.stringify({ message }),
});
}
});
});
app.all("/sandbox/:name/proxy/*", async (c) => {

View file

@ -0,0 +1,66 @@
import type { Sandbox } from "@cloudflare/sandbox";
import { SandboxAgent } from "sandbox-agent";
export type PromptRequest = {
agent?: string;
prompt?: string;
};
export async function runPromptEndpointStream(
sandbox: Sandbox,
request: PromptRequest,
port: number,
emit: (event: { type: string; [key: string]: unknown }) => Promise<void> | void,
): Promise<void> {
const client = await SandboxAgent.connect({
fetch: (req, init) =>
sandbox.containerFetch(
req,
{
...(init ?? {}),
// Cloudflare containerFetch may drop long-lived update streams when
// a forwarded AbortSignal is cancelled; clear it for this path.
signal: undefined,
},
port,
),
});
let unsubscribe: (() => void) | undefined;
try {
const session = await client.createSession({
agent: request.agent ?? "codex",
});
const promptText =
request.prompt?.trim() || "Reply with a short confirmation.";
await emit({
type: "session.created",
sessionId: session.id,
agent: session.agent,
prompt: promptText,
});
let pendingWrites: Promise<void> = Promise.resolve();
unsubscribe = session.onEvent((event) => {
pendingWrites = pendingWrites
.then(async () => {
await emit({ type: "session.event", event });
})
.catch(() => {});
});
const response = await session.prompt([{ type: "text", text: promptText }]);
await pendingWrites;
await emit({ type: "prompt.response", response });
await emit({ type: "prompt.completed" });
} finally {
if (unsubscribe) {
unsubscribe();
}
await Promise.race([
client.dispose(),
new Promise((resolve) => setTimeout(resolve, 250)),
]);
}
}

View file

@ -1,66 +0,0 @@
import type { Sandbox } from "@cloudflare/sandbox";
import { SandboxAgent } from "sandbox-agent";
export type PromptTestRequest = {
agent?: string;
prompt?: string;
};
export type PromptTestResponse = {
sessionId: string;
agent: string;
prompt: string;
events: unknown[];
};
export async function runPromptTest(
sandbox: Sandbox,
request: PromptTestRequest,
port: number,
): Promise<PromptTestResponse> {
const client = await SandboxAgent.connect({
fetch: (req, init) =>
sandbox.containerFetch(req, init, port),
});
let sessionId: string | null = null;
try {
const session = await client.createSession({
agent: request.agent ?? "codex",
});
sessionId = session.id;
const promptText =
request.prompt?.trim() || "Reply with a short confirmation.";
await session.prompt([{ type: "text", text: promptText }]);
const events: unknown[] = [];
let cursor: string | undefined;
while (true) {
const page = await client.getEvents({
sessionId: session.id,
cursor,
limit: 200,
});
events.push(...page.items);
if (!page.nextCursor) break;
cursor = page.nextCursor;
}
return {
sessionId: session.id,
agent: session.agent,
prompt: promptText,
events,
};
} finally {
if (sessionId) {
try {
await client.destroySession(sessionId);
} catch {
// Ignore cleanup failures; session teardown is best-effort.
}
}
await client.dispose();
}
}

146
pnpm-lock.yaml generated
View file

@ -19,6 +19,28 @@ importers:
specifier: ^3.0.0
version: 3.2.4(@types/debug@4.1.12)(@types/node@25.3.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2)
examples/boxlite:
dependencies:
'@boxlite-ai/boxlite':
specifier: latest
version: 0.2.11
'@sandbox-agent/example-shared':
specifier: workspace:*
version: link:../shared
sandbox-agent:
specifier: workspace:*
version: link:../../sdks/typescript
devDependencies:
'@types/node':
specifier: latest
version: 25.3.0
tsx:
specifier: latest
version: 4.21.0
typescript:
specifier: latest
version: 5.9.3
examples/cloudflare:
dependencies:
'@cloudflare/sandbox':
@ -39,7 +61,7 @@ importers:
devDependencies:
'@cloudflare/workers-types':
specifier: latest
version: 4.20260302.0
version: 4.20260304.0
'@types/node':
specifier: latest
version: 25.3.0
@ -63,7 +85,7 @@ importers:
version: 3.2.4(@types/debug@4.1.12)(@types/node@25.3.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2)
wrangler:
specifier: latest
version: 4.67.1(@cloudflare/workers-types@4.20260302.0)
version: 4.68.1(@cloudflare/workers-types@4.20260304.0)
examples/computesdk:
dependencies:
@ -72,7 +94,7 @@ importers:
version: link:../shared
computesdk:
specifier: latest
version: 2.2.1
version: 2.3.0
sandbox-agent:
specifier: workspace:*
version: link:../../sdks/typescript
@ -94,7 +116,7 @@ importers:
dependencies:
'@daytonaio/sdk':
specifier: latest
version: 0.144.0(ws@8.19.0)
version: 0.145.0(ws@8.19.0)
'@sandbox-agent/example-shared':
specifier: workspace:*
version: link:../shared
@ -210,7 +232,7 @@ importers:
dependencies:
'@modelcontextprotocol/sdk':
specifier: latest
version: 1.26.0(zod@4.3.6)
version: 1.27.1(zod@4.3.6)
'@sandbox-agent/example-shared':
specifier: workspace:*
version: link:../shared
@ -379,7 +401,7 @@ importers:
version: link:../shared
'@vercel/sandbox':
specifier: latest
version: 1.6.0
version: 1.7.1
sandbox-agent:
specifier: workspace:*
version: link:../../sdks/typescript
@ -534,7 +556,7 @@ importers:
dependencies:
'@daytonaio/sdk':
specifier: latest
version: 0.144.0(ws@8.19.0)
version: 0.145.0(ws@8.19.0)
'@e2b/code-interpreter':
specifier: latest
version: 2.3.3
@ -1101,6 +1123,27 @@ packages:
'@balena/dockerignore@1.0.2':
resolution: {integrity: sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==}
'@boxlite-ai/boxlite-darwin-arm64@0.2.11':
resolution: {integrity: sha512-JjNf6S/+XqooWvFX2Zn9XjmeML/e6Errk0jzG77v8YV0k2nNmt8P1nMANb2kMPbsQn93ap9v74VnYesYdKRoNg==}
engines: {node: '>=18.0.0'}
cpu: [arm64]
os: [darwin]
'@boxlite-ai/boxlite-linux-x64-gnu@0.2.11':
resolution: {integrity: sha512-H3a8FMc6X4KVsmlQKs2xTIlSh4KhiI52MnXV16OwcC6OWQBBadR1N6GCCKojfwpqn6yIsZc2dxoyy25YTYYf9g==}
engines: {node: '>=18.0.0'}
cpu: [x64]
os: [linux]
'@boxlite-ai/boxlite@0.2.11':
resolution: {integrity: sha512-IJ+jyYdsc1hmZknDtqGpRyMAMxoQfF1VFDVuPhiO59fBmoDEI5u69DzoMtyax4gzL3Q46tjYkVBvJhNtSDaxBw==}
engines: {node: '>=18.0.0'}
peerDependencies:
playwright-core: '>=1.58.0'
peerDependenciesMeta:
playwright-core:
optional: true
'@bufbuild/protobuf@2.11.0':
resolution: {integrity: sha512-sBXGT13cpmPR5BMgHE6UEEfEaShh5Ror6rfN3yEK5si7QVrtZg8LEPQb0VVhiLRUslD2yLnXtnRzG035J/mZXQ==}
@ -1198,8 +1241,8 @@ packages:
cpu: [x64]
os: [win32]
'@cloudflare/workers-types@4.20260302.0':
resolution: {integrity: sha512-mbFRnlu1lNCScMpXZk/X/uBPufYx5OSbq+euGonGRcY+DgOwm2kczGdK401rUh52NB0fFMEcOy/zqwxv7CdDNA==}
'@cloudflare/workers-types@4.20260304.0':
resolution: {integrity: sha512-oQ0QJpWnCWK9tx5q/ZHQeSsf5EcQWa4KqdDMY/R5Ln0ojFzv6UYO0RWsfDPsoXUAwK671VwaXqAW0Mx0uWz7yw==}
'@computesdk/cmd@0.4.1':
resolution: {integrity: sha512-hhcYrwMnOpRSwWma3gkUeAVsDFG56nURwSaQx8vCepv0IuUv39bK4mMkgszolnUQrVjBDdW7b3lV+l5B2S8fRA==}
@ -1219,14 +1262,14 @@ packages:
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
'@daytonaio/api-client@0.144.0':
resolution: {integrity: sha512-qr9c6YLntqmxbGAwYNIvHqZxA5zWl0nGY5aH3oK++1x03uDc5YnCwfcX7M7WCemt2iBUtLjQshdRKwFv0sDYsA==}
'@daytonaio/api-client@0.145.0':
resolution: {integrity: sha512-8xLJ1G7C3QJs2KfONcGd4O4ktHtGM4qxWVAcQERHSE1w4hJVrlaUzutMm2qy+HoXtMU1L5h/eFazoxrJ0xWzPw==}
'@daytonaio/sdk@0.144.0':
resolution: {integrity: sha512-Le8auU/h4xOlcTBQZWEx8jJwDEHeyKT/7oTUzkvONCp50agcuKjd5CDf79wsR9IqMuoCtlYcvhWXCNsdEuWkYg==}
'@daytonaio/sdk@0.145.0':
resolution: {integrity: sha512-RZhe5oz9EdC9PP3g95g+jXFkCiQbPJTfSALe9wi4W5n97hA9O6rM5zYRuwB2PJbHA8YC0m2t5pyHRJA9+88r5A==}
'@daytonaio/toolbox-api-client@0.144.0':
resolution: {integrity: sha512-ll5IXlH3nzhFtN+sW5fbAvT0mculP/GZCKnhHge/UlyG0cXKvlb3aoG2xWE1qpl5xWv2aQJbVdGhyuiGG/kPsQ==}
'@daytonaio/toolbox-api-client@0.145.0':
resolution: {integrity: sha512-Twh8FIoPAen+pjFeW03Fcom0fYT+k2grw8Q18aHdMAKQtXmMvA3+Ntim5ooE8AsHHLpCL6w+9ycdsovvzZOAEg==}
'@e2b/code-interpreter@2.3.3':
resolution: {integrity: sha512-WOpSwc1WpvxyOijf6WMbR76BUuvd2O9ddXgCHHi65lkuy6YgQGq7oyd8PNsT331O9Tqbccjy6uF4xanSdLX1UA==}
@ -2062,8 +2105,8 @@ packages:
'@js-sdsl/ordered-map@4.4.2':
resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==}
'@modelcontextprotocol/sdk@1.26.0':
resolution: {integrity: sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg==}
'@modelcontextprotocol/sdk@1.27.1':
resolution: {integrity: sha512-sr6GbP+4edBwFndLbM60gf07z0FQ79gaExpnsjMGePXqFcSSb7t6iscpjk9DhFhwd+mTEQrzNafGP8/iGGFYaA==}
engines: {node: '>=18'}
peerDependencies:
'@cfworker/json-schema': ^4.1.1
@ -2818,12 +2861,12 @@ packages:
'@ungap/structured-clone@1.3.0':
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
'@vercel/oidc@3.1.0':
resolution: {integrity: sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==}
'@vercel/oidc@3.2.0':
resolution: {integrity: sha512-UycprH3T6n3jH0k44NHMa7pnFHGu/N05MjojYr+Mc6I7obkoLIJujSWwin1pCvdy/eOxrI/l3uDLQsmcrOb4ug==}
engines: {node: '>= 20'}
'@vercel/sandbox@1.6.0':
resolution: {integrity: sha512-T204S3RZIdo+BCR5gpErTQBYz+ruXjTMRiZyf+HV/UQeKjPKAVKWu27T65kahDvVvJrbadHhxR2Cds28rXXF/Q==}
'@vercel/sandbox@1.7.1':
resolution: {integrity: sha512-TI9InUQe7sqyO4/TIiGXC/3RHA0hTt5PpFaTWeWunkbKZae26nuPVsd+p10W/WN2THUKE+NPtTJ21dhp1Yw48w==}
'@vitejs/plugin-react@4.7.0':
resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==}
@ -3196,8 +3239,8 @@ packages:
compare-versions@6.1.1:
resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==}
computesdk@2.2.1:
resolution: {integrity: sha512-u4xAtvuTNTquaN57hJq030aeGJtmxQ6Pzd/8kXB7uaCgwyyePK4W0hPDeDOFzyNd9QgoDDUD9r1j1sdO+UqVXg==}
computesdk@2.3.0:
resolution: {integrity: sha512-4B7CRN2qB6XkuAnN7dZ0aMYqHaFrh2qdSuh02lM+cgMEQ7wZy9v44FAjBGfWebHXuPNA/nZRx7211U6CEiGdTw==}
confbox@0.1.8:
resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==}
@ -5446,8 +5489,8 @@ packages:
engines: {node: '>=16'}
hasBin: true
wrangler@4.67.1:
resolution: {integrity: sha512-5GXz8cQNN/2KCMQ/22oe9Vf9xwVNillOowhKq6W2+ZuveU4/IrTm61K4iIUOsBYmrhYGopSfk0GmyCTuNh2rsA==}
wrangler@4.68.1:
resolution: {integrity: sha512-G+TI3k/olEGBAVkPtUlhAX/DIbL/190fv3aK+r+45/wPclNEymjxCc35T8QGTDhc2fEMXiw51L5bH9aNsBg+yQ==}
engines: {node: '>=20.0.0'}
hasBin: true
peerDependencies:
@ -6331,6 +6374,17 @@ snapshots:
'@balena/dockerignore@1.0.2': {}
'@boxlite-ai/boxlite-darwin-arm64@0.2.11':
optional: true
'@boxlite-ai/boxlite-linux-x64-gnu@0.2.11':
optional: true
'@boxlite-ai/boxlite@0.2.11':
optionalDependencies:
'@boxlite-ai/boxlite-darwin-arm64': 0.2.11
'@boxlite-ai/boxlite-linux-x64-gnu': 0.2.11
'@bufbuild/protobuf@2.11.0': {}
'@capsizecss/unpack@4.0.0':
@ -6385,7 +6439,7 @@ snapshots:
'@cloudflare/workerd-windows-64@1.20260302.0':
optional: true
'@cloudflare/workers-types@4.20260302.0': {}
'@cloudflare/workers-types@4.20260304.0': {}
'@computesdk/cmd@0.4.1': {}
@ -6402,18 +6456,18 @@ snapshots:
dependencies:
'@jridgewell/trace-mapping': 0.3.9
'@daytonaio/api-client@0.144.0':
'@daytonaio/api-client@0.145.0':
dependencies:
axios: 1.13.5
transitivePeerDependencies:
- debug
'@daytonaio/sdk@0.144.0(ws@8.19.0)':
'@daytonaio/sdk@0.145.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.144.0
'@daytonaio/toolbox-api-client': 0.144.0
'@daytonaio/api-client': 0.145.0
'@daytonaio/toolbox-api-client': 0.145.0
'@iarna/toml': 2.2.5
'@opentelemetry/api': 1.9.0
'@opentelemetry/exporter-trace-otlp-http': 0.207.0(@opentelemetry/api@1.9.0)
@ -6439,7 +6493,7 @@ snapshots:
- supports-color
- ws
'@daytonaio/toolbox-api-client@0.144.0':
'@daytonaio/toolbox-api-client@0.145.0':
dependencies:
axios: 1.13.5
transitivePeerDependencies:
@ -6943,7 +6997,7 @@ snapshots:
'@js-sdsl/ordered-map@4.4.2': {}
'@modelcontextprotocol/sdk@1.26.0(zod@4.3.6)':
'@modelcontextprotocol/sdk@1.27.1(zod@4.3.6)':
dependencies:
'@hono/node-server': 1.19.9(hono@4.11.8)
ajv: 8.17.1
@ -7782,7 +7836,7 @@ snapshots:
'@types/better-sqlite3@7.6.13':
dependencies:
'@types/node': 24.10.9
'@types/node': 25.3.0
'@types/chai@5.2.3':
dependencies:
@ -7844,7 +7898,7 @@ snapshots:
'@types/pg@8.16.0':
dependencies:
'@types/node': 24.10.9
'@types/node': 25.3.0
pg-protocol: 1.11.0
pg-types: 2.2.0
@ -7863,7 +7917,7 @@ snapshots:
'@types/sax@1.2.7':
dependencies:
'@types/node': 24.10.9
'@types/node': 25.3.0
'@types/semver@7.7.1': {}
@ -7875,11 +7929,11 @@ snapshots:
'@ungap/structured-clone@1.3.0': {}
'@vercel/oidc@3.1.0': {}
'@vercel/oidc@3.2.0': {}
'@vercel/sandbox@1.6.0':
'@vercel/sandbox@1.7.1':
dependencies:
'@vercel/oidc': 3.1.0
'@vercel/oidc': 3.2.0
async-retry: 1.3.3
jsonlines: 0.1.1
ms: 2.1.3
@ -7924,14 +7978,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.3.0))':
dependencies:
'@vitest/spy': 3.2.4
@ -8378,7 +8424,7 @@ snapshots:
compare-versions@6.1.1: {}
computesdk@2.2.1:
computesdk@2.3.0:
dependencies:
'@computesdk/cmd': 0.4.1
@ -10971,7 +11017,7 @@ snapshots:
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.3.0))
'@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.2.4
'@vitest/snapshot': 3.2.4
@ -11080,7 +11126,7 @@ snapshots:
'@cloudflare/workerd-linux-arm64': 1.20260302.0
'@cloudflare/workerd-windows-64': 1.20260302.0
wrangler@4.67.1(@cloudflare/workers-types@4.20260302.0):
wrangler@4.68.1(@cloudflare/workers-types@4.20260304.0):
dependencies:
'@cloudflare/kv-asset-handler': 0.4.2
'@cloudflare/unenv-preset': 2.14.0(unenv@2.0.0-rc.24)(workerd@1.20260302.0)
@ -11091,7 +11137,7 @@ snapshots:
unenv: 2.0.0-rc.24
workerd: 1.20260302.0
optionalDependencies:
'@cloudflare/workers-types': 4.20260302.0
'@cloudflare/workers-types': 4.20260304.0
fsevents: 2.3.3
transitivePeerDependencies:
- bufferutil