fix(ai-sandbox): pass deterministic id into provider.create#889
Conversation
SandboxCreateInput gains an optional `id`, and ensure() passes the computed compound sandbox key into provider.create(). Cloudflare honors it (`input.id ?? crypto.randomUUID()`) so its DO id is reconstructable from run context. Previously create() minted a random id recoverable only from the sandbox store, so out-of-band consumers (e.g. a preview iframe) could address a different sandbox than the one the agent edits.
🚀 Changeset Version Preview6 package(s) bumped directly, 20 bumped as dependents. 🟨 Minor bumps
🟩 Patch bumps
|
📝 WalkthroughWalkthroughIntroduces an optional ChangesDeterministic sandbox id support
Estimated code review effort: 2 (Simple) | ~12 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant ensure
participant Provider
Caller->>ensure: ensure(ctx)
ensure->>ensure: compute deterministic key from ctx
ensure->>Provider: create({ id: key })
alt provider supports named addressing
Provider-->>ensure: handle with id = key
else provider ignores input id
Provider-->>ensure: handle with self-generated id
end
ensure-->>Caller: sandbox handle
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
View your CI Pipeline Execution ↗ for commit f7e2c1b
☁️ Nx Cloud last updated this comment at |
@tanstack/ai
@tanstack/ai-acp
@tanstack/ai-angular
@tanstack/ai-anthropic
@tanstack/ai-bedrock
@tanstack/ai-claude-code
@tanstack/ai-client
@tanstack/ai-code-mode
@tanstack/ai-code-mode-skills
@tanstack/ai-codex
@tanstack/ai-devtools-core
@tanstack/ai-elevenlabs
@tanstack/ai-event-client
@tanstack/ai-fal
@tanstack/ai-gemini
@tanstack/ai-grok
@tanstack/ai-grok-build
@tanstack/ai-groq
@tanstack/ai-isolate-cloudflare
@tanstack/ai-isolate-node
@tanstack/ai-isolate-quickjs
@tanstack/ai-mcp
@tanstack/ai-mistral
@tanstack/ai-ollama
@tanstack/ai-openai
@tanstack/ai-opencode
@tanstack/ai-openrouter
@tanstack/ai-preact
@tanstack/ai-react
@tanstack/ai-react-ui
@tanstack/ai-sandbox
@tanstack/ai-sandbox-cloudflare
@tanstack/ai-sandbox-daytona
@tanstack/ai-sandbox-docker
@tanstack/ai-sandbox-local-process
@tanstack/ai-sandbox-sprites
@tanstack/ai-sandbox-vercel
@tanstack/ai-solid
@tanstack/ai-solid-ui
@tanstack/ai-svelte
@tanstack/ai-utils
@tanstack/ai-vue
@tanstack/ai-vue-ui
@tanstack/openai-base
@tanstack/preact-ai-devtools
@tanstack/react-ai-devtools
@tanstack/solid-ai-devtools
commit: |
Sprites is the same class as Cloudflare — the sprite's preview URL is keyed by its name, so a random name stranded out-of-band reconnects. Honor `input.id ?? <random>` so preview consumers can reconstruct the sprite address.
Problem
@tanstack/ai-sandboxcomputes a stable compound sandbox key, butSandboxCreateInputcarried no deterministic id intoprovider.create(). Providers then minted a random id (Cloudflarecrypto.randomUUID(), Spritestanstack-ai-<random>), so the provider-assigned id was recoverable only from the sandbox store.Out-of-band consumers that reconnect without reading the store — e.g. Forge attaching a preview iframe — had no way to reconstruct that random id. The result: the agent (Codex) edited one sandbox while the iframe watched another.
Fix
SandboxCreateInputgains an optionalid.ensure()passes the computed compound key (not rawdefineSandbox({ id })) intoprovider.create({ id, ... }). The computed key already folds in threadId / runId (forreuse: 'none') / provider / workspace / tenant, so it can't collide across threads or runs.input.id ?? <random>): Cloudflare (DO id) and Sprites (sprite name). Consumers can now recomputedefinition.key(ctx)and address the exact sandbox the agent edits.Which providers honor it — and why the rest don't
id?getSandbox(binding, name)— caller-namedcreateSprite(name)— caller-namedcreateContainer(could name)daytona.create()mints opaque idSandbox.create()server-assigns nameSo the two providers with the exact "caller-named + URL-addressable preview" shape are fixed; Docker/local-process could honor it but have no out-of-band reconnect problem (their store record already covers resume); Daytona/Vercel physically can't, since the backend owns the id.
Tests
ai-sandbox/tests/ensure.test.ts: asserts the provider id equalsdef.key(ctx).ai-sandbox-cloudflare/tests/provider.test.ts(new):getSandboxcalled withinput.id, random fallback otherwise.ai-sandbox-sprites/tests/provider.test.ts: create usesinput.idas the sprite name when provided.Unit tests, typecheck, and lint pass for all three packages. (One pre-existing, unrelated Windows path-separator failure in
harness-cwd.test.tsis untouched by this change.)🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes