Skip to content

fix(ai-sandbox): pass deterministic id into provider.create#889

Merged
AlemTuzlak merged 4 commits into
mainfrom
fix/sandbox-deterministic-create-id
Jul 3, 2026
Merged

fix(ai-sandbox): pass deterministic id into provider.create#889
AlemTuzlak merged 4 commits into
mainfrom
fix/sandbox-deterministic-create-id

Conversation

@AlemTuzlak

@AlemTuzlak AlemTuzlak commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Problem

@tanstack/ai-sandbox computes a stable compound sandbox key, but SandboxCreateInput carried no deterministic id into provider.create(). Providers then minted a random id (Cloudflare crypto.randomUUID(), Sprites tanstack-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

  • SandboxCreateInput gains an optional id.
  • ensure() passes the computed compound key (not raw defineSandbox({ id })) into provider.create({ id, ... }). The computed key already folds in threadId / runId (for reuse: 'none') / provider / workspace / tenant, so it can't collide across threads or runs.
  • Providers that are name-addressable and expose a preview URL keyed by that id honor it (input.id ?? <random>): Cloudflare (DO id) and Sprites (sprite name). Consumers can now recompute definition.key(ctx) and address the exact sandbox the agent edits.

Which providers honor it — and why the rest don't

Provider Backend id Preview reconnect Honors id?
Cloudflare getSandbox(binding, name) — caller-named DO/tunnel URL keyed by id ✅ yes
Sprites createSprite(name) — caller-named sprite URL keyed by name ✅ yes
Docker createContainer (could name) localhost host-port only — no cross-process address no (store-resume suffices)
local-process dir path (could name) none (runs on host) no
Daytona daytona.create() mints opaque id can't (no caller id)
Vercel Sandbox.create() server-assigns name can't (no caller id)

So 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 equals def.key(ctx).
  • ai-sandbox-cloudflare/tests/provider.test.ts (new): getSandbox called with input.id, random fallback otherwise.
  • ai-sandbox-sprites/tests/provider.test.ts: create uses input.id as 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.ts is untouched by this change.)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Sandbox creation now supports deterministic IDs, making it easier to reconnect to the same sandbox later.
    • Some sandbox providers now preserve a requested ID when creating a new sandbox, improving consistency across preview and reconnect flows.
  • Bug Fixes

    • Fixed mismatches where a sandbox could be created with one identifier but referenced with another.
    • Updated test coverage to verify deterministic sandbox IDs are returned and stored correctly.

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.
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

🚀 Changeset Version Preview

6 package(s) bumped directly, 20 bumped as dependents.

🟨 Minor bumps

Package Version Reason
@tanstack/ai-anthropic 0.15.13 → 0.16.0 Changeset

🟩 Patch bumps

Package Version Reason
@tanstack/ai 0.39.0 → 0.39.1 Changeset
@tanstack/ai-ollama 0.8.12 → 0.8.13 Changeset
@tanstack/ai-sandbox 0.2.0 → 0.2.1 Changeset
@tanstack/ai-sandbox-cloudflare 0.2.0 → 0.2.1 Changeset
@tanstack/ai-sandbox-sprites 0.2.0 → 0.2.1 Changeset
@tanstack/ai-angular 0.2.1 → 0.2.2 Dependent
@tanstack/ai-bedrock 0.1.0 → 0.1.1 Dependent
@tanstack/ai-client 0.19.1 → 0.19.2 Dependent
@tanstack/ai-code-mode 0.3.4 → 0.3.5 Dependent
@tanstack/ai-code-mode-skills 0.3.7 → 0.3.8 Dependent
@tanstack/ai-devtools-core 0.4.20 → 0.4.21 Dependent
@tanstack/ai-fal 0.9.8 → 0.9.9 Dependent
@tanstack/ai-isolate-cloudflare 0.2.34 → 0.2.35 Dependent
@tanstack/ai-isolate-node 0.1.43 → 0.1.44 Dependent
@tanstack/ai-isolate-quickjs 0.1.43 → 0.1.44 Dependent
@tanstack/ai-mcp 0.2.1 → 0.2.2 Dependent
@tanstack/ai-preact 0.10.1 → 0.10.2 Dependent
@tanstack/ai-react 0.16.2 → 0.16.3 Dependent
@tanstack/ai-solid 0.14.1 → 0.14.2 Dependent
@tanstack/ai-svelte 0.14.1 → 0.14.2 Dependent
@tanstack/ai-vue 0.14.1 → 0.14.2 Dependent
@tanstack/ai-vue-ui 0.2.29 → 0.2.30 Dependent
@tanstack/preact-ai-devtools 0.1.63 → 0.1.64 Dependent
@tanstack/react-ai-devtools 0.2.63 → 0.2.64 Dependent
@tanstack/solid-ai-devtools 0.2.63 → 0.2.64 Dependent

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Introduces an optional id field on SandboxCreateInput and updates ensure() to pass the computed sandbox key as a deterministic id to provider.create(). Cloudflare, Sprites, and fake providers honor the supplied id when present, falling back to previous random-generation behavior otherwise. Tests and a changeset document the change.

Changes

Deterministic sandbox id support

Layer / File(s) Summary
Contract and ensure() wiring
packages/ai-sandbox/src/contracts.ts, packages/ai-sandbox/src/sandbox.ts
SandboxCreateInput gains an optional id field, and ensure() passes the computed sandbox key as id when calling provider.create().
Provider implementations honoring deterministic id
packages/ai-sandbox-cloudflare/src/provider.ts, packages/ai-sandbox-sprites/src/provider.ts, packages/ai-sandbox/tests/fakes.ts
CloudflareProvider.create uses input.id for the Durable Object id, SpritesProvider.create uses it for the sprite name, and the fake provider uses it for the handle id, all falling back to random/counter-based generation when absent.
Tests and changeset
packages/ai-sandbox/tests/ensure.test.ts, packages/ai-sandbox-cloudflare/tests/provider.test.ts, packages/ai-sandbox-sprites/tests/provider.test.ts, .changeset/sandbox-deterministic-create-id.md
New tests verify deterministic and fallback id behavior across ensure(), Cloudflare, and Sprites providers, and a changeset documents the patch across the three packages.

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
Loading

Possibly related PRs

  • TanStack/ai#868: Introduced the Sprites provider's create() implementation, which this PR modifies to honor a deterministic id for the sprite name.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is detailed, but it does not follow the required template sections or include the checklist and release impact entries. Rewrite it to use the required headings: 🎯 Changes, ✅ Checklist, and 🚀 Release Impact, and fill in the checklist items.
✅ Passed checks (4 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The PR title is concise and accurately summarizes the main change.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/sandbox-deterministic-create-id

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@nx-cloud

nx-cloud Bot commented Jul 3, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit f7e2c1b

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ✅ Succeeded 1m 22s View ↗
nx run-many --targets=build --exclude=examples/... ✅ Succeeded 2s View ↗

☁️ Nx Cloud last updated this comment at 2026-07-03 09:55:37 UTC

@pkg-pr-new

pkg-pr-new Bot commented Jul 3, 2026

Copy link
Copy Markdown

Open in StackBlitz

@tanstack/ai

npm i https://pkg.pr.new/@tanstack/ai@889

@tanstack/ai-acp

npm i https://pkg.pr.new/@tanstack/ai-acp@889

@tanstack/ai-angular

npm i https://pkg.pr.new/@tanstack/ai-angular@889

@tanstack/ai-anthropic

npm i https://pkg.pr.new/@tanstack/ai-anthropic@889

@tanstack/ai-bedrock

npm i https://pkg.pr.new/@tanstack/ai-bedrock@889

@tanstack/ai-claude-code

npm i https://pkg.pr.new/@tanstack/ai-claude-code@889

@tanstack/ai-client

npm i https://pkg.pr.new/@tanstack/ai-client@889

@tanstack/ai-code-mode

npm i https://pkg.pr.new/@tanstack/ai-code-mode@889

@tanstack/ai-code-mode-skills

npm i https://pkg.pr.new/@tanstack/ai-code-mode-skills@889

@tanstack/ai-codex

npm i https://pkg.pr.new/@tanstack/ai-codex@889

@tanstack/ai-devtools-core

npm i https://pkg.pr.new/@tanstack/ai-devtools-core@889

@tanstack/ai-elevenlabs

npm i https://pkg.pr.new/@tanstack/ai-elevenlabs@889

@tanstack/ai-event-client

npm i https://pkg.pr.new/@tanstack/ai-event-client@889

@tanstack/ai-fal

npm i https://pkg.pr.new/@tanstack/ai-fal@889

@tanstack/ai-gemini

npm i https://pkg.pr.new/@tanstack/ai-gemini@889

@tanstack/ai-grok

npm i https://pkg.pr.new/@tanstack/ai-grok@889

@tanstack/ai-grok-build

npm i https://pkg.pr.new/@tanstack/ai-grok-build@889

@tanstack/ai-groq

npm i https://pkg.pr.new/@tanstack/ai-groq@889

@tanstack/ai-isolate-cloudflare

npm i https://pkg.pr.new/@tanstack/ai-isolate-cloudflare@889

@tanstack/ai-isolate-node

npm i https://pkg.pr.new/@tanstack/ai-isolate-node@889

@tanstack/ai-isolate-quickjs

npm i https://pkg.pr.new/@tanstack/ai-isolate-quickjs@889

@tanstack/ai-mcp

npm i https://pkg.pr.new/@tanstack/ai-mcp@889

@tanstack/ai-mistral

npm i https://pkg.pr.new/@tanstack/ai-mistral@889

@tanstack/ai-ollama

npm i https://pkg.pr.new/@tanstack/ai-ollama@889

@tanstack/ai-openai

npm i https://pkg.pr.new/@tanstack/ai-openai@889

@tanstack/ai-opencode

npm i https://pkg.pr.new/@tanstack/ai-opencode@889

@tanstack/ai-openrouter

npm i https://pkg.pr.new/@tanstack/ai-openrouter@889

@tanstack/ai-preact

npm i https://pkg.pr.new/@tanstack/ai-preact@889

@tanstack/ai-react

npm i https://pkg.pr.new/@tanstack/ai-react@889

@tanstack/ai-react-ui

npm i https://pkg.pr.new/@tanstack/ai-react-ui@889

@tanstack/ai-sandbox

npm i https://pkg.pr.new/@tanstack/ai-sandbox@889

@tanstack/ai-sandbox-cloudflare

npm i https://pkg.pr.new/@tanstack/ai-sandbox-cloudflare@889

@tanstack/ai-sandbox-daytona

npm i https://pkg.pr.new/@tanstack/ai-sandbox-daytona@889

@tanstack/ai-sandbox-docker

npm i https://pkg.pr.new/@tanstack/ai-sandbox-docker@889

@tanstack/ai-sandbox-local-process

npm i https://pkg.pr.new/@tanstack/ai-sandbox-local-process@889

@tanstack/ai-sandbox-sprites

npm i https://pkg.pr.new/@tanstack/ai-sandbox-sprites@889

@tanstack/ai-sandbox-vercel

npm i https://pkg.pr.new/@tanstack/ai-sandbox-vercel@889

@tanstack/ai-solid

npm i https://pkg.pr.new/@tanstack/ai-solid@889

@tanstack/ai-solid-ui

npm i https://pkg.pr.new/@tanstack/ai-solid-ui@889

@tanstack/ai-svelte

npm i https://pkg.pr.new/@tanstack/ai-svelte@889

@tanstack/ai-utils

npm i https://pkg.pr.new/@tanstack/ai-utils@889

@tanstack/ai-vue

npm i https://pkg.pr.new/@tanstack/ai-vue@889

@tanstack/ai-vue-ui

npm i https://pkg.pr.new/@tanstack/ai-vue-ui@889

@tanstack/openai-base

npm i https://pkg.pr.new/@tanstack/openai-base@889

@tanstack/preact-ai-devtools

npm i https://pkg.pr.new/@tanstack/preact-ai-devtools@889

@tanstack/react-ai-devtools

npm i https://pkg.pr.new/@tanstack/react-ai-devtools@889

@tanstack/solid-ai-devtools

npm i https://pkg.pr.new/@tanstack/solid-ai-devtools@889

commit: 81a7b2a

AlemTuzlak and others added 2 commits July 3, 2026 11:51
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.
@AlemTuzlak AlemTuzlak merged commit 9b58c08 into main Jul 3, 2026
10 checks passed
@AlemTuzlak AlemTuzlak deleted the fix/sandbox-deterministic-create-id branch July 3, 2026 10:04
@github-actions github-actions Bot mentioned this pull request Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant