Skip to content

feat(integrations): add Daytona integration with sandbox lifecycle, code execution, and file tools#4987

Merged
waleedlatif1 merged 7 commits into
stagingfrom
worktree-daytona-integration
Jun 12, 2026
Merged

feat(integrations): add Daytona integration with sandbox lifecycle, code execution, and file tools#4987
waleedlatif1 merged 7 commits into
stagingfrom
worktree-daytona-integration

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Add Daytona integration: 12 tools covering sandbox lifecycle (create/list/get/start/stop/delete), code execution (run Python/JS/TS, execute shell commands), file transfer (upload/download/list), and git clone
  • Tools call the Daytona management API (app.daytona.io/api) and toolbox API (proxy.app.daytona.io/toolbox) directly; request/response shapes validated against the official OpenAPI specs
  • File upload goes through an internal route (/api/tools/daytona/upload) with internal auth, file access checks, and contract validation; download returns a UserFile via the standard file output pipeline
  • Daytona block with operation dropdown, conditional fields, basic/advanced file inputs via canonicalParamId, BlockMeta with 8 templates and 4 skills
  • DaytonaIcon, registry entries, generated docs with manual intro description

Type of Change

  • New feature

Testing

Live-tested every operation end-to-end against the real Daytona API with a personal API key: sandbox create with labels/env, get, list with label filter and pagination, execute command (env/cwd/timeout), run code (Python and JavaScript), multipart upload, list files, download with byte-for-byte round-trip, git clone, stop/start lifecycle with state polling, delete. Also: typecheck clean, check:api-validation strict passes, tools/blocks structural test suites pass (196 tests).

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jun 12, 2026 1:55am

Request Review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@cursor

cursor Bot commented Jun 12, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
New surface runs arbitrary shell/code in external sandboxes and forwards user files and API keys; upload route adds auth and access checks but expands remote-execution blast radius if misconfigured.

Overview
Adds a Daytona integration so workflows can manage isolated cloud sandboxes and run untrusted code via API key.

Twelve tools cover sandbox lifecycle (create/list/get/start/stop/delete), in-sandbox run code (Python/JS/TS), execute command, file upload/download/list, and git clone. Most calls go straight to Daytona’s management and toolbox APIs; upload is proxied through /api/tools/daytona/upload with internal auth, file access checks, a Zod contract, and a 100MB limit.

The Daytona workflow block, tool registry, integrations.json, docs (daytona.mdx), and DaytonaIcon wiring are included, plus templates/skills on the block meta.

Notion branding shifts to a white card background and a fixed black icon fill (docs, blocks, catalog). Integration landing pages move the “Last updated” line below the CTAs with subtler styling. API validation baseline increments for the new upload route.

Reviewed by Cursor Bugbot for commit abd1849. Configure here.

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@gitguardian

gitguardian Bot commented Jun 12, 2026

Copy link
Copy Markdown

️✅ There are no secrets present in this pull request anymore.

If these secrets were true positive and are still valid, we highly recommend you to revoke them.
While these secrets were previously flagged, we no longer have a reference to the
specific commits where they were detected. Once a secret has been leaked into a git
repository, you should consider it compromised, even if it was deleted immediately.
Find here more information about risks.


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit e416012. Configure here.

@greptile-apps

greptile-apps Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a complete Daytona integration: 12 tools covering sandbox lifecycle (create/list/get/start/stop/delete), code execution (run Python/JS/TS, execute shell), file transfer (upload/download/list), and git clone. An internal route (/api/tools/daytona/upload) handles multipart upload with auth and size checks; all other tools call the Daytona management and toolbox APIs directly.

  • 12 new tools wired into the tool and block registries, with a BlockConfig covering conditional sub-block fields, an authMode: ApiKey pattern, and BlockMeta with 8 templates and 4 agent skills.
  • Internal upload route validates auth, enforces a 100 MB size guard using userFile.size before downloading from storage, and proxies a multipart FormData to Daytona.
  • Incidental change: NotionIcon's fill attribute changed from currentColor to #000000 in both apps/sim/components/icons.tsx and apps/docs/components/icons.tsx, coordinated with a Notion bgColor flip to #FFFFFF.

Confidence Score: 5/5

Safe to merge — the Daytona integration is complete and all issues flagged in previous review rounds have been addressed.

All 12 tools are correctly wired, API key visibility follows the user-only pattern throughout, the upload route pre-checks file size before downloading from storage, lifecycle endpoints tolerate empty response bodies via parseDaytonaJson, and zero-valued numeric params are preserved with the !== undefined && !== '' guard. The only new finding is a cosmetic regression in the NotionIcon fill attribute that was changed incidentally from currentColor to #000000.

apps/sim/components/icons.tsx and apps/docs/components/icons.tsx — the NotionIcon fill hardcoding warrants a quick confirm that all rendering contexts (toolbar, dropdowns) still look correct on dark backgrounds.

Important Files Changed

Filename Overview
apps/sim/tools/daytona/utils.ts Shared utilities: URL builders, parseDaytonaJson (empty-body tolerant), extractDaytonaError, toOptionalNumber/toOptionalBoolean, and mapDaytonaSandbox. Well-guarded and consistent.
apps/sim/app/api/tools/daytona/upload/route.ts Internal upload route; pre-download size check on userFile.size, post-decode check for base64 path, internal auth via checkInternalAuth, and assertToolFileAccess authorization — previous review issues resolved.
apps/sim/blocks/blocks/daytona.ts Block config with 12 operations, conditional sub-blocks, proper !== undefined && !== '' guards for zero-valued numeric params (autoStop/autoArchive/autoDelete/timeout), and canonical file input mapping.
apps/sim/tools/daytona/run_code.ts Run code tool with correct exitCode ?? -1 sentinel, timeout via toOptionalNumber, and envs table transform.
apps/sim/components/icons.tsx Adds DaytonaIcon (hardcoded black fills, consistent with white bgColor). Incidentally changes NotionIcon fill from currentColor to #000000, hardcoding the color and potentially breaking dark-theme rendering contexts.

Sequence Diagram

sequenceDiagram
    participant W as Workflow Engine
    participant UT as upload_file tool
    participant IR as /api/tools/daytona/upload
    participant S as File Storage
    participant D as Daytona Toolbox API

    W->>UT: invoke(apiKey, sandboxId, file, destinationPath)
    UT->>IR: POST JSON body (apiKey, sandboxId, file ref, destinationPath)
    IR->>IR: checkInternalAuth()
    IR->>IR: processFilesToUserFiles()
    IR->>IR: assertToolFileAccess(key, userId)
    IR->>IR: guard: userFile.size ≤ 100MB?
    IR->>S: downloadFileFromStorage(userFile)
    S-->>IR: fileBuffer
    IR->>IR: guard: fileBuffer.length ≤ 100MB?
    IR->>D: "POST /toolbox/{sandboxId}/files/upload?path=...  (multipart FormData, Bearer apiKey)"
    D-->>IR: 200 OK
    IR-->>UT: "{success, uploadedPath, name, size}"
    UT-->>W: output
Loading

Reviews (8): Last reviewed commit: "fix(daytona): forward explicit zero cpu/..." | Re-trigger Greptile

Comment thread apps/sim/app/api/tools/daytona/upload/route.ts
Comment thread apps/sim/app/api/tools/daytona/upload/route.ts
Comment thread apps/sim/tools/daytona/delete_sandbox.ts Outdated
Comment thread apps/sim/blocks/blocks/daytona.ts Outdated
@greptile-apps

greptile-apps Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a Daytona integration with 12 tools covering the full sandbox lifecycle (create/list/get/start/stop/delete), code execution (run Python/JS/TS, execute shell), file transfer (upload/download/list), and git clone. A dedicated upload route at /api/tools/daytona/upload proxies file writes server-side while direct tool calls hit the Daytona management and toolbox APIs.

  • 12 tools follow the existing ToolConfig pattern; utils.ts centralizes URL builders, error extraction, and sandbox object mapping to keep individual tool files thin.
  • Upload route wires internal auth, assertToolFileAccess, and a 100 MB size guard around a multipart POST to Daytona's toolbox API; a legacy base64 path is preserved for backward compatibility.
  • Block config with canonicalParamId for file inputs, conditional sub-block visibility, and BlockMeta with 8 templates and 4 agent skills rounds out the UI surface.

Confidence Score: 3/5

The integration is well-structured overall, but two issues in the upload route and the lifecycle tools (delete/start/stop) could cause real failures: large files are fully buffered before rejection, and response.json() is called unconditionally on responses that may carry no body.

The upload route downloads the full file buffer from storage before applying the 100 MB size guard, even though userFile.size is already known — a file just over the limit consumes server memory unnecessarily. The delete (and start/stop) tools call response.json() without checking whether a body is present; if the Daytona API returns 204 for any of these operations the tool will throw a JSON parse error, leaving the user with a failure message even though the operation succeeded.

apps/sim/app/api/tools/daytona/upload/route.ts (size check ordering) and apps/sim/tools/daytona/delete_sandbox.ts / start_sandbox.ts / stop_sandbox.ts (unconditional response.json() on lifecycle endpoints).

Important Files Changed

Filename Overview
apps/sim/app/api/tools/daytona/upload/route.ts Internal upload proxy route with auth, file access checks, and size limiting — but the 100 MB size guard fires after the full buffer is fetched from storage; the pre-known userFile.size should be checked first.
apps/sim/tools/daytona/delete_sandbox.ts Calls response.json() after DELETE; will throw if Daytona returns 204 No Content, causing a failure even on a successful delete.
apps/sim/tools/daytona/list_sandboxes.ts Labels filter serialized as JSON.stringify() in query string — may not match Daytona API's expected format for the labels query parameter.
apps/sim/tools/daytona/run_code.ts Runs code in sandbox via toolbox API; defaults exitCode to 0 when absent which could mask failures; otherwise well-structured.
apps/sim/tools/daytona/utils.ts Clean shared utilities for URL building, error extraction, sandbox object mapping, and type coercion; well-factored and consistent.
apps/sim/blocks/blocks/daytona.ts Block config with conditional sub-block visibility, canonicalParamId for file inputs, and a full params mapping switch; looks complete and correctly wired.
apps/sim/tools/daytona/types.ts Type definitions for all 12 tools; well-organized with shared base interfaces and clear response shapes.
apps/sim/tools/daytona/create_sandbox.ts Creates sandbox via management API with correct optional-param handling using toOptionalNumber/toOptionalBoolean helpers; clean implementation.
apps/sim/tools/daytona/download_file.ts Downloads file bytes from sandbox toolbox API and returns as base64-encoded UserFile; correct content-type extraction and filename parsing.
apps/sim/lib/api/contracts/tools/daytona.ts Zod contract for the upload route; body schema covers all three input modes (file object, legacy base64, file name override) with appropriate optionality.

Sequence Diagram

sequenceDiagram
    participant Client as Client (Workflow Executor)
    participant UploadRoute as /api/tools/daytona/upload
    participant Storage as File Storage
    participant DaytonaProxy as proxy.app.daytona.io/toolbox
    participant DaytonaAPI as app.daytona.io/api

    Note over Client,DaytonaAPI: Upload File (proxied through internal route)
    Client->>UploadRoute: "POST {apiKey, sandboxId, file, destinationPath}"
    UploadRoute->>UploadRoute: checkInternalAuth()
    UploadRoute->>UploadRoute: parseRequest + validate contract
    UploadRoute->>UploadRoute: assertToolFileAccess(userFile.key)
    UploadRoute->>Storage: downloadFileFromStorage(userFile)
    Storage-->>UploadRoute: fileBuffer (N bytes)
    UploadRoute->>UploadRoute: "size check (> 100MB?)"
    UploadRoute->>DaytonaProxy: "POST /toolbox/{sandboxId}/files/upload?path=..."
    DaytonaProxy-->>UploadRoute: 200 OK
    UploadRoute-->>Client: "{success, uploadedPath, name, size}"

    Note over Client,DaytonaAPI: All other tools (direct external calls)
    Client->>DaytonaAPI: POST /sandbox (create)
    DaytonaAPI-->>Client: sandbox object
    Client->>DaytonaProxy: "POST /toolbox/{id}/process/execute"
    DaytonaProxy-->>Client: "{exitCode, result}"
    Client->>DaytonaProxy: "GET /toolbox/{id}/files/download?path=..."
    DaytonaProxy-->>Client: file bytes
Loading

Reviews (2): Last reviewed commit: "feat(integrations): add Daytona integrat..." | Re-trigger Greptile

Comment thread apps/sim/app/api/tools/daytona/upload/route.ts
Comment thread apps/sim/tools/daytona/delete_sandbox.ts Outdated
Comment thread apps/sim/tools/daytona/list_sandboxes.ts
Comment thread apps/sim/tools/daytona/run_code.ts Outdated
@waleedlatif1 waleedlatif1 force-pushed the worktree-daytona-integration branch from e416012 to e9d30c7 Compare June 12, 2026 01:10
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/tools/daytona/download_file.ts
Comment thread apps/sim/tools/daytona/delete_sandbox.ts
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/app/api/tools/daytona/upload/route.ts
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 8230fbf. Configure here.

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile The two issues cited in the confidence score rationale are already fixed on the current head (8230fbf):

  • Upload size-check ordering: fixed in e9d30c7 — the route now gates on userFile.size before downloadFileFromStorage, and 8230fbf also rejects oversized base64 payloads before decoding.
  • Unconditional response.json() in delete/start/stop: fixed in e9d30c7 — all three lifecycle tools parse via an empty-body-tolerant parseDaytonaJson helper, and d67724f falls back to the requested sandbox ID when the body is empty.

Please re-review the latest commit.

- Pre-check file size via userFile.size before downloading from storage in the upload route
- Tolerate empty response bodies in delete/start/stop sandbox tools
- Preserve explicit timeout 0 for run_code and execute_command
- Default missing exitCode to -1 so unknown state is distinguishable from success
- Reject blank sandbox IDs, clamp list limit to 1-200, trim destination path
- Clarify that toolbox operations require the sandbox ID (not name)
- Bump contract route baseline to 812 for the new daytona upload route
@waleedlatif1 waleedlatif1 force-pushed the worktree-daytona-integration branch from 8230fbf to cee3094 Compare June 12, 2026 01:45
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/blocks/blocks/daytona.ts Outdated
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit abd1849. Configure here.

@waleedlatif1 waleedlatif1 merged commit c3b98eb into staging Jun 12, 2026
15 checks passed
@waleedlatif1 waleedlatif1 deleted the worktree-daytona-integration branch June 12, 2026 02:13
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