Skip to content

feat: Added leap0 as sandbox#1

Merged
steven-passynkov merged 1 commit into
leap0-dev:mainfrom
ipassynk:feat/leap0-integration
Apr 11, 2026
Merged

feat: Added leap0 as sandbox#1
steven-passynkov merged 1 commit into
leap0-dev:mainfrom
ipassynk:feat/leap0-integration

Conversation

@ipassynk
Copy link
Copy Markdown
Collaborator

@ipassynk ipassynk commented Apr 11, 2026

Added leap0 as sandbox

Summary by CodeRabbit

  • New Features

    • Added Leap0 as a supported sandbox provider; configure with LEAP0_API_KEY.
    • New Leap0-powered sandbox capabilities: create sandboxes, run code (JS/TS/Python), run commands, and full filesystem operations.
  • Chores

    • Added Leap0 runtime package dependency.
    • Updated documentation and examples to include Leap0 provider and configuration.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 11, 2026

📝 Walkthrough

Walkthrough

Adds Leap0 as a third sandbox provider: new env var, README updates, an npm dependency, provider selection wiring, and a Leap0 implementation module with sandbox, filesystem, and execution tools.

Changes

Cohort / File(s) Summary
Configuration & Documentation
\.env\.example, README\.md
Added LEAP0_API_KEY placeholder; updated README to document Leap0 as an additional sandbox provider and added Leap0-specific tooling directory to docs.
Dependencies
package\.json
Added runtime dependency leap0@^0.3.1.
Provider Integration
src/mastra/tools/index.ts
Extended provider set to include leap0; updated getProvider() to check LEAP0_API_KEY; replaced 2-way selectTool with 3-way pickTool and routed exported tool bindings to Leap0 when selected.
Leap0 Implementation
src/mastra/tools/leap0/tools.ts, src/mastra/tools/leap0/utils.ts
New Leap0 client utilities and ~12 exported tools for sandbox lifecycle, code execution, filesystem ops, and command execution. Contains timeout/unit conversions, path normalization/validation, error normalization, temp-file handling, and a disabled watchDirectory. (Large, logic-dense file to review.)

Sequence Diagram

sequenceDiagram
    participant Caller as Caller (tools index)
    participant Selector as Provider Selector
    participant Client as Leap0 Client
    participant Sandbox as Leap0 Sandbox
    participant FS as Filesystem / Process

    Caller->>Selector: request tool (createSandbox / runCode / fs ops)
    Selector->>Selector: check envs (DAYTONA, E2B, LEAP0)
    Selector-->>Caller: provider = leap0

    Caller->>Client: getLeap0Client()
    Client-->>Caller: Leap0Client (cached)

    Caller->>Sandbox: createSandbox(envs, timeout)
    Sandbox->>FS: initialize workspace
    FS-->>Sandbox: ready
    Sandbox-->>Caller: { sandboxId }

    Caller->>Sandbox: runCode(sandboxId, code, opts)
    alt language == js
        Sandbox->>FS: write temp .js file
        FS->>FS: spawn node process (timeout mapped)
    else language == ts/python
        Sandbox->>Client: codeInterpreter.execute(language, opts)
    end
    FS-->>Sandbox: execution result
    Sandbox-->>Caller: execution output / contextId
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • feat: Added leap0 as sandbox #1 — Implements the same Leap0 integration: LEAP0_API_KEY, leap0 dependency, src/mastra/tools/leap0/{tools.ts,utils.ts}, and provider wiring in src/mastra/tools/index.ts.

Poem

🐰 A hop, a key, a brand-new day,
Leap0 bounds in to join the play.
Sandboxes build and code will run,
Temp files cleaned when tasks are done.
My whiskers twitch — a job well spun!

🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding leap0 as a new sandbox provider option to the codebase.

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

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

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

Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.env.example:
- Around line 8-9: The .env.example sets MODEL=groq/llama-3.3-70b-versatile
which conflicts with the README/setup that only instructs users to add
OPENAI_API_KEY; update .env.example so its default MODEL matches the documented
setup (e.g., revert MODEL to openai/gpt-4o-mini) or add a note and the required
GROQ_API_KEY variable; specifically change the MODEL entry and, if keeping the
Groq default, add GROQ_API_KEY and an explanatory comment near MODEL to keep
credentials and docs in sync.

In `@README.md`:
- Line 99: Edit the provider overview sentence to explicitly call out that Leap0
does not support live directory monitoring: update the README line that
currently says "Automatically uses Daytona, E2B, or Leap0 based on which API key
you set" to note that Leap0 lacks watchDirectory/live directory monitoring;
reference the implementation in src/mastra/tools/leap0/tools.ts and its
watchDirectory function which returns a fixed unsupported error, and add a short
caveat like "Note: Leap0 does not support live directory monitoring
(watchDirectory) at this time." Ensure the wording is concise and visible in the
provider overview.

In `@src/mastra/tools/leap0/tools.ts`:
- Around line 147-159: The sandbox.codeInterpreter.execute call in this tool
auto-creates a persistent interpreter context (execution.context_id) when none
is supplied, leaking sessions; either modify the tool's input schema to accept a
contextId and pass it into sandbox.codeInterpreter.execute so callers can
control lifecycle (and return the contextId in the response), or immediately
clean up after execution by calling
sandbox.codeInterpreter.delete_context(execution.context_id) before returning;
update the code path around sandbox.codeInterpreter.execute and the returned
object (serializeCodeResult) to include or account for the context_id as
appropriate.

In `@src/mastra/tools/leap0/utils.ts`:
- Around line 20-35: normalizeSandboxPath currently concatenates strings and can
return workspace-prefixed paths that still contain "."/".." segments (e.g.,
"/workspace/../etc"), causing filesystem calls to target outside the workspace;
change it to canonicalize with Node's path utilities: compute a resolved
absolute path using path.resolve(WORKSPACE_ROOT, trimmed) for relative inputs
(and path.resolve(trimmed) for absolute inputs), then normalize, and enforce
confinement by rejecting/throwing if the resolved path is outside WORKSPACE_ROOT
(check resolved === WORKSPACE_ROOT or resolved.startsWith(WORKSPACE_ROOT +
path.sep)); ensure all return values are the canonical resolved path without any
"."/".." segments and keep references to normalizeSandboxPath and WORKSPACE_ROOT
when locating the fix.
🪄 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: e3b5873f-2985-4bc7-ae13-7d5327cb94f0

📥 Commits

Reviewing files that changed from the base of the PR and between 87d8063 and 1e8934a.

📒 Files selected for processing (6)
  • .env.example
  • README.md
  • package.json
  • src/mastra/tools/index.ts
  • src/mastra/tools/leap0/tools.ts
  • src/mastra/tools/leap0/utils.ts

Comment thread .env.example Outdated
Comment thread README.md
Comment thread src/mastra/tools/leap0/tools.ts Outdated
Comment thread src/mastra/tools/leap0/utils.ts Outdated
@ipassynk ipassynk force-pushed the feat/leap0-integration branch from 1e8934a to 59523c6 Compare April 11, 2026 21:57
Copy link
Copy Markdown

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

🧹 Nitpick comments (3)
src/mastra/tools/leap0/tools.ts (2)

578-599: Zod defaults make null-coalescing redundant.

The input schema defines .default(30000) for timeoutMs and .default(true) for captureOutput, so Zod provides these values before execute runs. The ?? operators on lines 582 and 591 are unnecessary.

♻️ Suggested simplification
-      const timeoutSeconds = timeoutMsToSeconds(timeoutMs ?? 30000);
+      const timeoutSeconds = timeoutMsToSeconds(timeoutMs);
       const cwd = workingDirectory ? normalizeSandboxPath(workingDirectory) : undefined;
       ...
       const executionTime = Date.now() - startTime;
-      const capture = captureOutput ?? true;
       return {
         success: result.exitCode === 0,
         exitCode: result.exitCode,
-        stdout: capture ? result.stdout : '',
-        stderr: capture ? result.stderr : '',
+        stdout: captureOutput ? result.stdout : '',
+        stderr: captureOutput ? result.stderr : '',
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/mastra/tools/leap0/tools.ts` around lines 578 - 599, The execute handler
applies redundant null-coalescing because the input Zod schema already supplies
defaults for timeoutMs and captureOutput; remove the unnecessary "??" uses so
timeoutMs is passed directly into timeoutMsToSeconds and captureOutput is used
directly when building the return (i.e., drop "timeoutMs ?? 30000" and
"captureOutput ?? true" and simplify the local variable "capture" to use
captureOutput directly); update references in execute (function name execute,
timeoutMsToSeconds call, captureOutput usage, and the result construction that
sets stdout/stderr) accordingly.

39-48: Guard against negative byte values.

Math.log(bytes) returns NaN for negative inputs, which would propagate through the calculation. While unlikely from valid filesystem stats, a defensive check prevents unexpected output.

🛡️ Suggested fix
 function formatBytes(bytes: number): string {
   const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
-  if (bytes === 0) {
+  if (bytes <= 0) {
     return '0 B';
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/mastra/tools/leap0/tools.ts` around lines 39 - 48, The formatBytes
function can produce NaN for negative inputs because Math.log(bytes) is invalid;
add a defensive guard at the top of formatBytes (before computing rawIndex) to
handle non-positive or non-finite inputs—e.g., if bytes <= 0 || !isFinite(bytes)
return '0 B'—so the subsequent use of rawIndex, i and sizes remains safe and
predictable.
.env.example (1)

19-19: Consider alphabetical ordering for API keys.

The static analysis tool suggests placing LEAP0_API_KEY before MISTRAL_API_KEY to maintain alphabetical order among the API key entries. This is a minor consistency improvement.

♻️ Suggested reordering
 GROQ_API_KEY=
 CEREBRAS_API_KEY=
+LEAP0_API_KEY=
 MISTRAL_API_KEY=
 DAYTONA_API_KEY=
 E2B_API_KEY=
-LEAP0_API_KEY=
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.env.example at line 19, Reorder the API key entries in .env.example to be
alphabetically consistent by moving the LEAP0_API_KEY line so it appears before
MISTRAL_API_KEY; update the file by locating the LEAP0_API_KEY and
MISTRAL_API_KEY entries and swapping their positions to ensure alphabetical
ordering of API key environment variables.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.env.example:
- Line 19: Reorder the API key entries in .env.example to be alphabetically
consistent by moving the LEAP0_API_KEY line so it appears before
MISTRAL_API_KEY; update the file by locating the LEAP0_API_KEY and
MISTRAL_API_KEY entries and swapping their positions to ensure alphabetical
ordering of API key environment variables.

In `@src/mastra/tools/leap0/tools.ts`:
- Around line 578-599: The execute handler applies redundant null-coalescing
because the input Zod schema already supplies defaults for timeoutMs and
captureOutput; remove the unnecessary "??" uses so timeoutMs is passed directly
into timeoutMsToSeconds and captureOutput is used directly when building the
return (i.e., drop "timeoutMs ?? 30000" and "captureOutput ?? true" and simplify
the local variable "capture" to use captureOutput directly); update references
in execute (function name execute, timeoutMsToSeconds call, captureOutput usage,
and the result construction that sets stdout/stderr) accordingly.
- Around line 39-48: The formatBytes function can produce NaN for negative
inputs because Math.log(bytes) is invalid; add a defensive guard at the top of
formatBytes (before computing rawIndex) to handle non-positive or non-finite
inputs—e.g., if bytes <= 0 || !isFinite(bytes) return '0 B'—so the subsequent
use of rawIndex, i and sizes remains safe and predictable.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3b52fc1d-41f9-46db-bfe2-d94715fe8150

📥 Commits

Reviewing files that changed from the base of the PR and between 1e8934a and 59523c6.

📒 Files selected for processing (6)
  • .env.example
  • README.md
  • package.json
  • src/mastra/tools/index.ts
  • src/mastra/tools/leap0/tools.ts
  • src/mastra/tools/leap0/utils.ts
✅ Files skipped from review due to trivial changes (2)
  • package.json
  • src/mastra/tools/index.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • README.md
  • src/mastra/tools/leap0/utils.ts

@steven-passynkov steven-passynkov merged commit 9d14c58 into leap0-dev:main Apr 11, 2026
1 check passed
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