Skip to content

feat: add Daytona Code Mode isolate driver#645

Open
mu-hashmi wants to merge 4 commits into
TanStack:mainfrom
mu-hashmi:feat/daytona-adapter
Open

feat: add Daytona Code Mode isolate driver#645
mu-hashmi wants to merge 4 commits into
TanStack:mainfrom
mu-hashmi:feat/daytona-adapter

Conversation

@mu-hashmi
Copy link
Copy Markdown

@mu-hashmi mu-hashmi commented May 26, 2026

Changes

This adds @tanstack/ai-isolate-daytona, a Code Mode isolate driver for caller-owned Daytona sandboxes.

The driver sends wrapped Code Mode programs to sandbox.process.codeRun, reads the marker envelope from Daytona stdout/result, and keeps TanStack tool implementations on the host. When generated code calls an external_* tool, Daytona returns need_tools; the host runs the matching ToolBinding.execute callbacks and replays the program with the tool results.

A few details matter here:

  • createContext is a logical Code Mode context. It does not create or delete Daytona sandboxes.
  • timeout is a total execution budget in milliseconds. Daytona receives the remaining budget as a per-call seconds timeout.
  • maxToolRounds counts host tool callback rounds, not raw codeRun calls.
  • The stdout marker is generated per execution so user output containing the public marker prefix does not spoof the result envelope.

The PR also updates the Code Mode isolate docs and adds a changeset for the new package.

Test plan

  • pnpm test:pr
  • pnpm test:e2e
  • DAYTONA_LIVE_TEST=1 DAYTONA_API_KEY=<redacted> pnpm --filter @tanstack/ai-isolate-daytona test:live

I also ran the narrower package checks while developing:

  • pnpm --filter @tanstack/ai-isolate-daytona test:lib -- --run tests/isolate-driver.test.ts tests/wrap-code.test.ts tests/live.test.ts
  • pnpm --filter @tanstack/ai-isolate-daytona test:types
  • pnpm --filter @tanstack/ai-isolate-daytona test:eslint
  • pnpm --filter @tanstack/ai-isolate-daytona build
  • pnpm --filter @tanstack/ai-isolate-daytona test:build

Notes:

  • The live Daytona suite created real TypeScript, JavaScript, and Python sandboxes and cleaned them up in finally.
  • Vitest/Vite prints the existing examples/ts-svelte-chat/.svelte-kit/tsconfig.json warning during several commands. The commands still passed.
  • E2E prints existing mocked provider error logs during some tests. The Playwright run still passed.

Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm run test:pr.

Release impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Summary by CodeRabbit

  • New Features

    • Added Daytona sandbox isolate driver support for Code Mode, enabling remote sandbox execution with configurable sandbox policy, execution timeouts, and tool-round limits.
    • Published a companion Daytona package with usage examples and local validation/test guidance.
  • Documentation

    • Updated Code Mode docs and isolate-driver comparison to include Daytona, installation steps, configuration options, execution-flow guidance, and sandbox usage notes.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 26, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b86947a7-b180-4632-8c98-3c36abef52be

📥 Commits

Reviewing files that changed from the base of the PR and between 132edff and 84c4f28.

📒 Files selected for processing (3)
  • docs/code-mode/code-mode-isolates.md
  • docs/code-mode/code-mode.md
  • packages/ai-isolate-daytona/README.md
✅ Files skipped from review due to trivial changes (2)
  • docs/code-mode/code-mode-isolates.md
  • docs/code-mode/code-mode.md

📝 Walkthrough

Walkthrough

Adds a Daytona-backed IsolateDriver implementation and package, plus README and Code Mode documentation updates to document installation, configuration options (sandbox, timeout, maxToolRounds), and the sandbox execution/replay flow.

Changes

Daytona Isolate Driver

Layer / File(s) Summary
Release metadata
.changeset/daytona-isolate-driver.md
Changeset entry marks @tanstack/ai-isolate-daytona for a minor version bump with driver addition description.
Code Mode guide integration
docs/code-mode/code-mode.md
Secure sandboxing text, install instructions, isolate drivers list/table, driver selection guidance, and Next Steps updated to include Daytona.
Isolates reference and Daytona guide
docs/code-mode/code-mode-isolates.md
Page header/keywords, driver comparison table (adds Daytona column), and full Daytona Driver section describing installation, options (sandbox, timeout, maxToolRounds), and execution via sandbox.process.codeRun.
Package README
packages/ai-isolate-daytona/README.md
New README documenting installation, usage example, createDaytonaIsolateDriver(config) API, operational requirements, and test instructions.
Driver: config & helpers
packages/ai-isolate-daytona/src/isolate-driver.ts (lines 1-129)
Adds DaytonaIsolateDriverConfig and helper utilities for timeouts, marker IDs, schema conversion, and error normalization.
Driver: parsing & tool dispatch
packages/ai-isolate-daytona/src/isolate-driver.ts (lines 130-340)
Adds timeout wrapping, envelope parsing, strict envelope validation, tool-call parsing with ID checks/duplicate detection, and single-tool execution dispatch producing structured results.
Driver: context & execute loop
packages/ai-isolate-daytona/src/isolate-driver.ts (lines 341-530)
Implements DaytonaIsolateContext execute loop calling sandbox.process.codeRun, handling need_tools rounds, batching tool executions, enforcing maxToolRounds, caching/merging tool results, disposal behavior, and error normalization.
Driver factory
packages/ai-isolate-daytona/src/isolate-driver.ts (lines 532-555)
Exports createDaytonaIsolateDriver, validates config defaults, and creates per-isolate contexts wired to the provided sandbox and bindings.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

A rabbit in a Daytona shell,
runs code, replays tools, and hums a spell.
Docs hop in, examples align,
sandboxed rounds keep time divine.
🐰🏁

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add Daytona Code Mode isolate driver' clearly and accurately summarizes the main change—addition of a new Daytona isolate driver for Code Mode.
Description check ✅ Passed The description comprehensively covers changes, includes detailed behavior documentation, test plan with specific commands and results, follows the template structure (Changes, Checklist, Release impact), and demonstrates thorough testing.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

@mu-hashmi mu-hashmi marked this pull request as ready for review May 26, 2026 17:39
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
packages/typescript/ai-isolate-daytona/tests/wrap-code.test.ts (1)

1-276: ⚡ Quick win

Move this unit test file to be colocated with the source module.

wrap-code.test.ts should sit alongside src/wrap-code.ts rather than under tests/ to match the repo’s unit test placement rule.

As per coding guidelines: "Define unit tests in *.test.ts files alongside source files".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/typescript/ai-isolate-daytona/tests/wrap-code.test.ts` around lines
1 - 276, The test file wrap-code.test.ts is currently under tests/ but must be
colocated with its module; move the entire wrap-code.test.ts so it sits next to
src/wrap-code.ts, update any import paths if necessary (ensure imports like
'../src/wrap-code' still resolve from the new location or change them to
'./wrap-code'), and run the test suite to verify nothing breaks; keep the test
filename and contents unchanged aside from import path fixes and ensure test
runner picks up the colocated *.test.ts file.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/code-mode/code-mode-isolates.md`:
- Around line 230-239: The fenced diagram block starting with the lines "Driver
(your server)              Daytona sandbox" is missing a fence language and
triggers MD040; update the triple-backtick fence that surrounds that ASCII
diagram to include a language label (e.g., change ``` to ```text) so the code
block is explicitly marked as plain text and will satisfy markdown linting.

In `@packages/typescript/ai-isolate-daytona/package.json`:
- Around line 1-59: Add the required packageManager field to this package.json
to pin pnpm to the repo standard: add "packageManager": "pnpm@10.17.0" at the
top-level of the JSON (near other root keys such as "name" and "version") so the
manifest explicitly declares pnpm@10.17.0 for consistent lockfile/tooling
behavior.

In `@packages/typescript/ai-isolate-daytona/README.md`:
- Around line 62-70: The fenced diagram block in the README is unlabeled and
triggers MD040; update the opening triple-backtick fence for the diagram (the
block starting with "Host process                         Daytona sandbox") to
include a language label (e.g., change ``` to ```text) so the block becomes a
labeled code fence and satisfies the markdown linter.

In `@packages/typescript/ai-isolate-daytona/src/isolate-driver.ts`:
- Around line 130-133: The timeoutAfter helper currently creates an uncancelled
timer; change timeoutAfter(milliseconds) to return both a promise and a cancel
function (e.g., { promise, cancel } or [promise, cancel]) where cancel calls
clearTimeout on the stored timer id; then update the Promise.race call sites
that race timeoutAfter() with work (the two Promise.race usages) to call the
cancel function when the work branch wins so the pending timer is cleared and
not left accumulating.

---

Nitpick comments:
In `@packages/typescript/ai-isolate-daytona/tests/wrap-code.test.ts`:
- Around line 1-276: The test file wrap-code.test.ts is currently under tests/
but must be colocated with its module; move the entire wrap-code.test.ts so it
sits next to src/wrap-code.ts, update any import paths if necessary (ensure
imports like '../src/wrap-code' still resolve from the new location or change
them to './wrap-code'), and run the test suite to verify nothing breaks; keep
the test filename and contents unchanged aside from import path fixes and ensure
test runner picks up the colocated *.test.ts file.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6f9da31f-ab9d-49c6-afaa-7116d73a5dc0

📥 Commits

Reviewing files that changed from the base of the PR and between 0de0cba and 31b5eac.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (14)
  • .changeset/daytona-isolate-driver.md
  • docs/code-mode/code-mode-isolates.md
  • docs/code-mode/code-mode.md
  • packages/typescript/ai-isolate-daytona/README.md
  • packages/typescript/ai-isolate-daytona/package.json
  • packages/typescript/ai-isolate-daytona/src/index.ts
  • packages/typescript/ai-isolate-daytona/src/isolate-driver.ts
  • packages/typescript/ai-isolate-daytona/src/types.ts
  • packages/typescript/ai-isolate-daytona/src/wrap-code.ts
  • packages/typescript/ai-isolate-daytona/tests/isolate-driver.test.ts
  • packages/typescript/ai-isolate-daytona/tests/live.test.ts
  • packages/typescript/ai-isolate-daytona/tests/wrap-code.test.ts
  • packages/typescript/ai-isolate-daytona/tsconfig.json
  • packages/typescript/ai-isolate-daytona/vite.config.ts

Comment thread docs/code-mode/code-mode-isolates.md Outdated
Comment on lines +1 to +59
{
"name": "@tanstack/ai-isolate-daytona",
"version": "0.0.1",
"description": "Daytona sandbox driver for TanStack AI Code Mode TypeScript execution.",
"author": "",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/TanStack/ai.git",
"directory": "packages/typescript/ai-isolate-daytona"
},
"type": "module",
"module": "./dist/esm/index.js",
"types": "./dist/esm/index.d.ts",
"exports": {
".": {
"types": "./dist/esm/index.d.ts",
"import": "./dist/esm/index.js"
}
},
"sideEffects": false,
"engines": {
"node": ">=18"
},
"files": [
"dist",
"src"
],
"scripts": {
"build": "vite build",
"clean": "premove ./build ./dist",
"lint:fix": "eslint ./src --fix",
"test:build": "publint --strict",
"test:eslint": "eslint ./src",
"test:live": "vitest --run tests/live.test.ts",
"test:lib": "vitest --passWithNoTests",
"test:lib:dev": "pnpm test:lib --watch",
"test:types": "tsc"
},
"keywords": [
"ai",
"ai-sdk",
"typescript",
"tanstack",
"code-mode",
"daytona",
"sandbox",
"isolate",
"code-execution"
],
"peerDependencies": {
"@tanstack/ai-code-mode": "workspace:*"
},
"devDependencies": {
"@daytona/sdk": "^0.180.0",
"@tanstack/ai-code-mode": "workspace:*",
"@vitest/coverage-v8": "4.0.14"
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add packageManager to pin pnpm version.

This manifest does not declare the required package manager pin, which can lead to inconsistent lockfile/tooling behavior across contributors.

Suggested fix
 {
   "name": "`@tanstack/ai-isolate-daytona`",
   "version": "0.0.1",
+  "packageManager": "pnpm@10.17.0",
   "description": "Daytona sandbox driver for TanStack AI Code Mode TypeScript execution.",

As per coding guidelines "**/package.json: Use pnpm@10.17.0 as the package manager for this repository".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{
"name": "@tanstack/ai-isolate-daytona",
"version": "0.0.1",
"description": "Daytona sandbox driver for TanStack AI Code Mode TypeScript execution.",
"author": "",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/TanStack/ai.git",
"directory": "packages/typescript/ai-isolate-daytona"
},
"type": "module",
"module": "./dist/esm/index.js",
"types": "./dist/esm/index.d.ts",
"exports": {
".": {
"types": "./dist/esm/index.d.ts",
"import": "./dist/esm/index.js"
}
},
"sideEffects": false,
"engines": {
"node": ">=18"
},
"files": [
"dist",
"src"
],
"scripts": {
"build": "vite build",
"clean": "premove ./build ./dist",
"lint:fix": "eslint ./src --fix",
"test:build": "publint --strict",
"test:eslint": "eslint ./src",
"test:live": "vitest --run tests/live.test.ts",
"test:lib": "vitest --passWithNoTests",
"test:lib:dev": "pnpm test:lib --watch",
"test:types": "tsc"
},
"keywords": [
"ai",
"ai-sdk",
"typescript",
"tanstack",
"code-mode",
"daytona",
"sandbox",
"isolate",
"code-execution"
],
"peerDependencies": {
"@tanstack/ai-code-mode": "workspace:*"
},
"devDependencies": {
"@daytona/sdk": "^0.180.0",
"@tanstack/ai-code-mode": "workspace:*",
"@vitest/coverage-v8": "4.0.14"
}
}
{
"name": "`@tanstack/ai-isolate-daytona`",
"version": "0.0.1",
"packageManager": "pnpm@10.17.0",
"description": "Daytona sandbox driver for TanStack AI Code Mode TypeScript execution.",
"author": "",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/TanStack/ai.git",
"directory": "packages/typescript/ai-isolate-daytona"
},
"type": "module",
"module": "./dist/esm/index.js",
"types": "./dist/esm/index.d.ts",
"exports": {
".": {
"types": "./dist/esm/index.d.ts",
"import": "./dist/esm/index.js"
}
},
"sideEffects": false,
"engines": {
"node": ">=18"
},
"files": [
"dist",
"src"
],
"scripts": {
"build": "vite build",
"clean": "premove ./build ./dist",
"lint:fix": "eslint ./src --fix",
"test:build": "publint --strict",
"test:eslint": "eslint ./src",
"test:live": "vitest --run tests/live.test.ts",
"test:lib": "vitest --passWithNoTests",
"test:lib:dev": "pnpm test:lib --watch",
"test:types": "tsc"
},
"keywords": [
"ai",
"ai-sdk",
"typescript",
"tanstack",
"code-mode",
"daytona",
"sandbox",
"isolate",
"code-execution"
],
"peerDependencies": {
"`@tanstack/ai-code-mode`": "workspace:*"
},
"devDependencies": {
"`@daytona/sdk`": "^0.180.0",
"`@tanstack/ai-code-mode`": "workspace:*",
"`@vitest/coverage-v8`": "4.0.14"
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/typescript/ai-isolate-daytona/package.json` around lines 1 - 59, Add
the required packageManager field to this package.json to pin pnpm to the repo
standard: add "packageManager": "pnpm@10.17.0" at the top-level of the JSON
(near other root keys such as "name" and "version") so the manifest explicitly
declares pnpm@10.17.0 for consistent lockfile/tooling behavior.

Comment thread packages/ai-isolate-daytona/README.md Outdated
Comment thread packages/ai-isolate-daytona/src/isolate-driver.ts Outdated
@socket-security
Copy link
Copy Markdown

socket-security Bot commented May 26, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​daytona/​sdk@​0.180.07510010098100

View full report

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
packages/ai-isolate-daytona/src/isolate-driver.ts (1)

130-146: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Timer type should be ReturnType<typeof setTimeout> for Node.js compatibility.

In Node.js, setTimeout returns a Timeout object rather than a number. Using number here is incorrect for the Node.js runtime, though it works at runtime since clearTimeout accepts both types. The past review's proposed fix correctly used ReturnType<typeof setTimeout>.

🔧 Proposed fix
 async function withTimeout<T>(
   promise: Promise<T>,
   milliseconds: number,
 ): Promise<T | undefined> {
-  let timer: number | undefined
+  let timer: ReturnType<typeof setTimeout> | undefined
   const timeout = new Promise<undefined>((resolve) => {
     timer = setTimeout(resolve, milliseconds)
   })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ai-isolate-daytona/src/isolate-driver.ts` around lines 130 - 146,
The timer variable in withTimeout is typed as number which is incorrect for
Node.js; change the type of timer to ReturnType<typeof setTimeout> (and adjust
the timeout Promise factory to assign timer via setTimeout) so clearTimeout
receives the proper type — update the declaration "let timer: number |
undefined" to use ReturnType<typeof setTimeout> and ensure other uses (timer !==
undefined, clearTimeout(timer)) remain valid.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@packages/ai-isolate-daytona/src/isolate-driver.ts`:
- Around line 130-146: The timer variable in withTimeout is typed as number
which is incorrect for Node.js; change the type of timer to ReturnType<typeof
setTimeout> (and adjust the timeout Promise factory to assign timer via
setTimeout) so clearTimeout receives the proper type — update the declaration
"let timer: number | undefined" to use ReturnType<typeof setTimeout> and ensure
other uses (timer !== undefined, clearTimeout(timer)) remain valid.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fb620614-05cd-4438-99d6-bc837bb9abb5

📥 Commits

Reviewing files that changed from the base of the PR and between c5a8374 and 132edff.

📒 Files selected for processing (3)
  • docs/code-mode/code-mode-isolates.md
  • packages/ai-isolate-daytona/README.md
  • packages/ai-isolate-daytona/src/isolate-driver.ts
✅ Files skipped from review due to trivial changes (2)
  • packages/ai-isolate-daytona/README.md
  • docs/code-mode/code-mode-isolates.md

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