Skip to content

feat(persistence): durable sandbox persistence (SandboxStore + shared lock)#988

Open
AlemTuzlak wants to merge 3 commits into
feat/persistence-corefrom
feat/persistence-sandbox
Open

feat(persistence): durable sandbox persistence (SandboxStore + shared lock)#988
AlemTuzlak wants to merge 3 commits into
feat/persistence-corefrom
feat/persistence-sandbox

Conversation

@AlemTuzlak

Copy link
Copy Markdown
Contributor

Summary

Stacked on #984. Lands the sandbox persistence piece #984 explicitly deferred: durable, multi-instance-correct resume for @tanstack/ai-sandbox.

withSandbox already consumes SandboxStore (which sandbox to resume) and LockStore (mutual exclusion around ensure) as optional capabilities, defaulting to in-memory (single-process). This adds the durable half — no behavioral change to the sandbox layer.

Core: one shared locks token

The 'locks' capability now lives in core @tanstack/ai (LocksCapability, LockStore, InMemoryLockStore, getLocks, provideLocks); @tanstack/ai-sandbox and @tanstack/ai-persistence re-export it. Because capability identity is by reference, one shared token means a withPersistence({ stores: { locks } }) already in the chain feeds the sandbox lock automatically — this is the "sandbox-consumer bridge" #984 noted as deferred.

@tanstack/ai-sandbox

  • withSandboxPersistence({ store, locks? }) — provides a durable SandboxStore (and optional distributed lock) to withSandbox. Compose before withSandbox.
  • SandboxStore conformance testkit exported at @tanstack/ai-sandbox/testkit (runSandboxStoreConformance).

Durable SandboxStore backends

  • @tanstack/ai-persistence-drizzlecreateDrizzleSandboxStore(db) + a new sandboxes table folded into the initial migration (regenerated; asset synced to the Cloudflare sibling).
  • @tanstack/ai-persistence-prismacreatePrismaSandboxStore(prisma) + a Sandbox model in the fragment.
  • @tanstack/ai-persistence-cloudflarecreateD1SandboxStore(d1) (delegates to Drizzle); the existing Durable-Object lock doubles as the distributed sandbox lock.

The three backends add @tanstack/ai-sandbox as an optional peer dependency. Sandboxes stays out of the chat BYO schema/model contract, so chat-only users are unaffected.

Tests / docs / skill

  • Conformance suites for the in-memory reference store and all three backends; withSandboxPersistence provide + cross-run-resume unit tests.
  • New docs/sandbox/persistence.md (+ nav, overview callout, cross-links from the persistence backend docs).
  • Updated the ai-sandbox agent skill.
  • E2E: a provider-free /api/sandbox-durability harness route + spec asserting a second run resumes the persisted sandbox (create stays 1).

Testing

Green locally (canonical nx targets, --skip-nx-cache): test:sherif, test:knip, test:docs, test:kiira, test:oxlint, test:types, and test:lib for @tanstack/ai, @tanstack/ai-sandbox, and all four persistence packages (conformance + wiring). @tanstack/ai-sandbox builds clean including the testkit + DTS.

Deferred to CI (per #984's precedent — this dev machine's nx output-materialization is unreliable here, which also blocks the Playwright dev server for every route): the full workspace build / test:build and the Playwright test:e2e run. The sandbox-durability spec is authored, registered in the route tree, and typechecks; the identical server-side-resume behavior is covered by the @tanstack/ai-sandbox persistence.test.ts unit test.

Release

Changeset: minor for @tanstack/ai, @tanstack/ai-sandbox, and the four persistence packages.

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e79b57d0-adbc-4c91-a70b-ba58dab8262f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/persistence-sandbox

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.

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

🚀 Changeset Version Preview

18 package(s) bumped directly, 35 bumped as dependents.

🟥 Major bumps

Package Version Reason
@tanstack/ai-angular 0.3.1 → 1.0.0 Changeset
@tanstack/ai-durable-stream 0.0.0 → 1.0.0 Changeset
@tanstack/ai-memory 0.0.0 → 1.0.0 Changeset
@tanstack/ai-openrouter 0.15.10 → 1.0.0 Changeset
@tanstack/ai-persistence 0.0.0 → 1.0.0 Changeset
@tanstack/ai-persistence-cloudflare 0.0.0 → 1.0.0 Changeset
@tanstack/ai-persistence-drizzle 0.0.0 → 1.0.0 Changeset
@tanstack/ai-persistence-prisma 0.0.0 → 1.0.0 Changeset
@tanstack/ai-preact 0.11.1 → 1.0.0 Changeset
@tanstack/ai-react 0.18.1 → 1.0.0 Changeset
@tanstack/ai-sandbox 0.2.4 → 1.0.0 Changeset
@tanstack/ai-solid 0.15.1 → 1.0.0 Changeset
@tanstack/ai-svelte 0.15.1 → 1.0.0 Changeset
@tanstack/ai-vue 0.15.1 → 1.0.0 Changeset
@tanstack/ai-acp 0.2.3 → 1.0.0 Dependent
@tanstack/ai-anthropic 0.16.3 → 1.0.0 Dependent
@tanstack/ai-bedrock 0.1.4 → 1.0.0 Dependent
@tanstack/ai-claude-code 0.2.3 → 1.0.0 Dependent
@tanstack/ai-code-mode 0.3.8 → 1.0.0 Dependent
@tanstack/ai-code-mode-skills 0.3.11 → 1.0.0 Dependent
@tanstack/ai-codex 0.2.3 → 1.0.0 Dependent
@tanstack/ai-elevenlabs 0.2.34 → 1.0.0 Dependent
@tanstack/ai-fal 0.9.12 → 1.0.0 Dependent
@tanstack/ai-gemini 0.20.1 → 1.0.0 Dependent
@tanstack/ai-grok 0.14.9 → 1.0.0 Dependent
@tanstack/ai-grok-build 0.2.3 → 1.0.0 Dependent
@tanstack/ai-groq 0.5.3 → 1.0.0 Dependent
@tanstack/ai-isolate-node 0.1.47 → 1.0.0 Dependent
@tanstack/ai-isolate-quickjs 0.1.47 → 1.0.0 Dependent
@tanstack/ai-mistral 0.2.3 → 1.0.0 Dependent
@tanstack/ai-ollama 0.8.16 → 1.0.0 Dependent
@tanstack/ai-openai 0.17.1 → 1.0.0 Dependent
@tanstack/ai-opencode 0.2.3 → 1.0.0 Dependent
@tanstack/ai-react-ui 0.8.15 → 1.0.0 Dependent
@tanstack/ai-sandbox-cloudflare 0.2.4 → 1.0.0 Dependent
@tanstack/ai-sandbox-daytona 0.2.0 → 1.0.0 Dependent
@tanstack/ai-sandbox-docker 0.2.0 → 1.0.0 Dependent
@tanstack/ai-sandbox-local-process 0.2.0 → 1.0.0 Dependent
@tanstack/ai-sandbox-sprites 0.2.1 → 1.0.0 Dependent
@tanstack/ai-sandbox-vercel 0.2.0 → 1.0.0 Dependent
@tanstack/ai-solid-ui 0.7.14 → 1.0.0 Dependent
@tanstack/openai-base 0.9.9 → 1.0.0 Dependent

🟨 Minor bumps

Package Version Reason
@tanstack/ai 0.42.0 → 0.43.0 Changeset
@tanstack/ai-client 0.22.1 → 0.23.0 Changeset
@tanstack/ai-devtools-core 0.4.24 → 0.5.0 Changeset
@tanstack/ai-event-client 0.6.8 → 0.7.0 Changeset

🟩 Patch bumps

Package Version Reason
@tanstack/ai-isolate-cloudflare 0.2.38 → 0.2.39 Dependent
@tanstack/ai-mcp 0.2.5 → 0.2.6 Dependent
@tanstack/ai-vue-ui 0.2.34 → 0.2.35 Dependent
@tanstack/preact-ai-devtools 0.1.67 → 0.1.68 Dependent
@tanstack/react-ai-devtools 0.2.67 → 0.2.68 Dependent
@tanstack/solid-ai-devtools 0.2.67 → 0.2.68 Dependent
ag-ui 0.0.2 → 0.0.3 Dependent

@nx-cloud

nx-cloud Bot commented Jul 23, 2026

Copy link
Copy Markdown

🤖 Nx Cloud AI Fix Eligible

An automatically generated fix could have helped fix failing tasks for this run, but Self-healing CI is disabled for this workspace. Visit workspace settings to enable it and get automatic fixes in future runs.

To disable these notifications, a workspace admin can disable them in workspace settings.


View your CI Pipeline Execution ↗ for commit 24360f7

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

☁️ Nx Cloud last updated this comment at 2026-07-25 06:02:57 UTC

@AlemTuzlak
AlemTuzlak force-pushed the feat/persistence-sandbox branch 2 times, most recently from 4b2e68a to e1e51d0 Compare July 23, 2026 12:14
@pkg-pr-new

pkg-pr-new Bot commented Jul 23, 2026

Copy link
Copy Markdown

Open in StackBlitz

@tanstack/ai

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

@tanstack/ai-acp

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

@tanstack/ai-angular

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

@tanstack/ai-anthropic

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

@tanstack/ai-bedrock

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

@tanstack/ai-claude-code

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

@tanstack/ai-client

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

@tanstack/ai-code-mode

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

@tanstack/ai-code-mode-skills

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

@tanstack/ai-codex

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

@tanstack/ai-devtools-core

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

@tanstack/ai-durable-stream

npm i https://pkg.pr.new/TanStack/ai/@tanstack/ai-durable-stream@988

@tanstack/ai-elevenlabs

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

@tanstack/ai-event-client

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

@tanstack/ai-fal

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

@tanstack/ai-gemini

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

@tanstack/ai-grok

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

@tanstack/ai-grok-build

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

@tanstack/ai-groq

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

@tanstack/ai-isolate-cloudflare

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

@tanstack/ai-isolate-node

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

@tanstack/ai-isolate-quickjs

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

@tanstack/ai-mcp

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

@tanstack/ai-memory

npm i https://pkg.pr.new/TanStack/ai/@tanstack/ai-memory@988

@tanstack/ai-mistral

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

@tanstack/ai-ollama

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

@tanstack/ai-openai

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

@tanstack/ai-opencode

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

@tanstack/ai-openrouter

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

@tanstack/ai-persistence

npm i https://pkg.pr.new/TanStack/ai/@tanstack/ai-persistence@988

@tanstack/ai-persistence-cloudflare

npm i https://pkg.pr.new/TanStack/ai/@tanstack/ai-persistence-cloudflare@988

@tanstack/ai-persistence-drizzle

npm i https://pkg.pr.new/TanStack/ai/@tanstack/ai-persistence-drizzle@988

@tanstack/ai-persistence-prisma

npm i https://pkg.pr.new/TanStack/ai/@tanstack/ai-persistence-prisma@988

@tanstack/ai-preact

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

@tanstack/ai-react

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

@tanstack/ai-react-ui

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

@tanstack/ai-sandbox

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

@tanstack/ai-sandbox-cloudflare

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

@tanstack/ai-sandbox-daytona

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

@tanstack/ai-sandbox-docker

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

@tanstack/ai-sandbox-local-process

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

@tanstack/ai-sandbox-sprites

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

@tanstack/ai-sandbox-vercel

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

@tanstack/ai-solid

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

@tanstack/ai-solid-ui

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

@tanstack/ai-svelte

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

@tanstack/ai-utils

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

@tanstack/ai-vue

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

@tanstack/ai-vue-ui

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

@tanstack/openai-base

npm i https://pkg.pr.new/TanStack/ai/@tanstack/openai-base@988

@tanstack/preact-ai-devtools

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

@tanstack/react-ai-devtools

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

@tanstack/solid-ai-devtools

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

commit: 4a1adb2

@AlemTuzlak
AlemTuzlak force-pushed the feat/persistence-sandbox branch from e1e51d0 to ef3e5f5 Compare July 23, 2026 12:53
@tombeckenham
tombeckenham force-pushed the feat/persistence-core branch from 0b17612 to d2d08e8 Compare July 24, 2026 01:31
@tombeckenham
tombeckenham force-pushed the feat/persistence-sandbox branch from ef3e5f5 to f4c053c Compare July 25, 2026 05:46
@tombeckenham

Copy link
Copy Markdown
Contributor

Rebased onto latest feat/persistence-core (3efe0c1d2) after the bottom of the stack moved.

Adapted to the post-schema-first core design rather than a raw cherry-pick of the pre-refactor commit:

  • Shared LocksCapability + SandboxStoreCapability (and in-memory impls) live in core @tanstack/ai
  • Locks remain on withLocks (not the state bag); optional stores.sandbox is provided by withPersistence when present
  • Backend surface: createDrizzleSandboxStore(db, table) / createPrismaSandboxStore / createD1SandboxStore; Node sqlitePersistence still returns a bag that includes sandbox
  • Sandboxes stay outside the chat BYO schema contract
  • Docs + e2e harness updated for withLocks composition

Local green: typecheck + test:lib for @tanstack/ai-persistence, @tanstack/ai-sandbox, and all four persistence packages (incl. sandbox store conformance).

AlemTuzlak and others added 2 commits July 25, 2026 15:48
Sandbox resume (SandboxStore + shared lock) is provided by withPersistence and consumed by withSandbox. SandboxStore/SandboxStoreCapability and the lock primitives live in core @tanstack/ai; the persistence backends carry a durable sandbox store; conformance testkit, e2e, docs, and the ai-sandbox skill updated.
Rebase of durable sandbox persistence onto the post-schema-first
feat/persistence-core layout:

- Shared LocksCapability + SandboxStoreCapability live in core @tanstack/ai
- Locks stay on withLocks (not the state bag); optional stores.sandbox is
  provided by withPersistence when present
- createDrizzleSandboxStore(db, table) / createPrismaSandboxStore /
  createD1SandboxStore; sqlite convenience factory includes sandbox store
- Sandboxes stay outside the chat BYO schema contract
- Update docs, e2e harness, and conformance tests for the new wiring
@tombeckenham
tombeckenham force-pushed the feat/persistence-sandbox branch from 24360f7 to 687f800 Compare July 25, 2026 05:49
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.

2 participants