Skip to content

feat: make command parameter optional for POST /api/sandboxes#204

Closed
sweetmantech wants to merge 1 commit intotestfrom
sweetmantech/myc-4138-docs-post-apisandboxes-commands-optional-to-simply-create-a
Closed

feat: make command parameter optional for POST /api/sandboxes#204
sweetmantech wants to merge 1 commit intotestfrom
sweetmantech/myc-4138-docs-post-apisandboxes-commands-optional-to-simply-create-a

Conversation

@sweetmantech
Copy link
Contributor

@sweetmantech sweetmantech commented Feb 4, 2026

Summary

  • Make the command parameter optional in POST /api/sandboxes
  • When command is omitted, sandbox is created without triggering the run-sandbox-command task
  • The runId field is only included in the response when a command was provided

Test plan

  • Call POST /api/sandboxes without command - verify sandbox is created, no runId returned
  • Call POST /api/sandboxes with command - verify sandbox is created with runId
  • Verify no regression in existing functionality

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Command parameter is now optional when creating sandboxes; you can create a sandbox without executing a command initially, enabling more flexible initialization workflows.

Allow creating a sandbox without providing a command, which skips
triggering the run-sandbox-command task. This enables users to simply
create a sandbox environment without executing any commands.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@vercel
Copy link
Contributor

vercel bot commented Feb 4, 2026

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

Project Deployment Actions Updated (UTC)
recoup-api Ready Ready Preview Feb 4, 2026 3:04pm

@coderabbitai
Copy link

coderabbitai bot commented Feb 4, 2026

📝 Walkthrough

Walkthrough

The changes make the command field optional when creating sandboxes, allowing sandbox creation without immediately executing a command. The API documentation, request validation schema, and handler logic are updated to reflect this new behavior, with runId only returned when a command is provided.

Changes

Cohort / File(s) Summary
API Documentation & Response Schema
app/api/sandboxes/route.ts
Updated POST /api/sandboxes documentation to indicate command is optional. Made runId optional in response schema and clarified it only appears when a command was provided.
Request Validation
lib/sandbox/validateSandboxBody.ts
Changed command field from required to optional while maintaining minimum length validation (.min(1)) when present.
Execution Handler
lib/sandbox/createSandboxPostHandler.ts
Updated handler to conditionally trigger run-sandbox-command task only when command is provided; sandbox is created regardless, but runId is only captured and returned when command execution occurs.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • Recoupable-com/Recoup-API#195: Modifies the same sandbox creation flow including route, request schema, and handler logic for conditional command execution and runId handling.

Poem

🏗️ Sandboxes now waltz with newfound grace,
Commands become optional in this flexible space,
Create without rushing, let tasks unfold slow,
Run when you're ready, or let them just flow,
Conditional whispers of code made more kind! ✨

🚥 Pre-merge checks | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Solid & Clean Code ⚠️ Warning Error handling violates SRP by conflating 'no command' and 'command failed' into identical responses, hiding execution failures from clients. Return explicit 502 error response when triggerRunSandboxCommand fails to distinguish command failures from missing commands.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch sweetmantech/myc-4138-docs-post-apisandboxes-commands-optional-to-simply-create-a

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.

@github-actions
Copy link

github-actions bot commented Feb 4, 2026

Braintrust eval report

Catalog Opportunity Analysis Evaluation (HEAD-1770217418)

Score Average Improvements Regressions
Catalog_availability 41% (+1pp) 1 🟢 -
Llm_calls 0 (+0) - -
Tool_calls 0 (+0) - -
Errors 0 (+0) - -
Llm_errors 0 (+0) - -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -
Duration 33.19s (-1.9s) 4 🟢 1 🔴

Catalog Songs Count Evaluation (HEAD-1770217418)

Score Average Improvements Regressions
Llm_calls 4 (+0) - -
Tool_calls 0 (+0) - -
Errors 3 (+0) - -
Llm_errors 1 (+0) - -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -
Duration 10.65s (-5.99s) 3 🟢 -

First Week Album Sales Evaluation (HEAD-1770217418)

Score Average Improvements Regressions
Llm_calls 1 (+0) - -
Tool_calls 0 (+0) - -
Errors 1 (+0) - -
Llm_errors 0 (+0) - -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -
Duration 13.74s (-1.92s) 3 🟢 1 🔴

Memory & Storage Tools Evaluation (HEAD-1770217418)

Score Average Improvements Regressions
Tools_called 0% (+0pp) - -
Llm_calls 0 (+0) - -
Tool_calls 0 (+0) - -
Errors 0 (+0) - -
Llm_errors 0 (+0) - -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -
Duration 17.84s (-42.22s) 1 🟢 -

Monthly Listeners Tracking Evaluation (HEAD-1770217418)

Score Average Improvements Regressions
Llm_calls 2 (+0) - -
Tool_calls 0 (+0) - -
Errors 2 (+0) - -
Llm_errors 1 (+0) - -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -
Duration 11.56s (-1.51s) 3 🟢 2 🔴

Search Web Tool Evaluation (HEAD-1770217418)

Score Average Improvements Regressions
Llm_calls 2.73 (-0.27) - 1 🔴
Tool_calls 0 (+0) - -
Errors 1.82 (-0.18) 1 🟢 -
Llm_errors 0.91 (-0.09) 1 🟢 -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -
Duration 21.6s (-3.25s) 7 🟢 3 🔴

Social Scraping Evaluation (HEAD-1770217418)

Score Average Improvements Regressions
Tools_called 0% (+0pp) - -
Llm_calls 0 (+0) - -
Tool_calls 0 (+0) - -
Errors 0 (+0) - -
Llm_errors 0 (+0) - -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -
Duration 30.63s (+3.39s) 2 🟢 4 🔴

Spotify Followers Evaluation (HEAD-1770217418)

Score Average Improvements Regressions
Llm_calls 3 (+0) - -
Tool_calls 0 (+0) - -
Errors 3 (+0) - -
Llm_errors 2 (+0) - -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -
Duration 15.21s (+0.09s) 2 🟢 3 🔴

Spotify Tools Evaluation (HEAD-1770217418)

Score Average Improvements Regressions
Llm_calls 0 (+0) - -
Tool_calls 0 (+0) - -
Errors 0 (+0) - -
Llm_errors 0 (+0) - -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -

TikTok Analytics Questions Evaluation (HEAD-1770217418)

Score Average Improvements Regressions
Question_answered 0% (+0pp) - -
Llm_calls 0 (+0) - -
Tool_calls 0 (+0) - -
Errors 0 (+0) - -
Llm_errors 0 (+0) - -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -
Duration 13.42s (-1.05s) 1 🟢 1 🔴

Copy link

@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: 1

🤖 Fix all issues with AI agents
In `@lib/sandbox/createSandboxPostHandler.ts`:
- Around line 43-57: The current catch in createSandboxPostHandler swallows
triggerRunSandboxCommand failures, making a missing runId indistinguishable from
"no command provided"; change the catch in the block that calls
triggerRunSandboxCommand to propagate a proper error response instead of just
logging: when triggerRunSandboxCommand({ command: validated.command, args:
validated.args, cwd: validated.cwd, sandboxId: result.sandboxId, accountId:
validated.accountId }) throws, rethrow or return a 4xx/5xx error (include the
original error message) so the handler returns failure to the client rather than
a success without runId; update any callers/response flow that rely on runId
accordingly.
🧹 Nitpick comments (1)
lib/sandbox/validateSandboxBody.ts (1)

8-10: Harden command validation against whitespace-only values.

min(1) still allows " ". Consider trimming before validation to avoid “empty but non-empty” commands.

♻️ Suggested change
-  command: z.string().min(1, "command cannot be empty").optional(),
+  command: z.string().trim().min(1, "command cannot be empty").optional(),

Comment on lines +43 to +57
// Trigger the command execution task only if a command was provided
let runId: string | undefined;
try {
const handle = await triggerRunSandboxCommand({
command: validated.command,
args: validated.args,
cwd: validated.cwd,
sandboxId: result.sandboxId,
accountId: validated.accountId,
});
runId = handle.id;
} catch (triggerError) {
console.error("Failed to trigger run-sandbox-command task:", triggerError);
if (validated.command) {
try {
const handle = await triggerRunSandboxCommand({
command: validated.command,
args: validated.args,
cwd: validated.cwd,
sandboxId: result.sandboxId,
accountId: validated.accountId,
});
runId = handle.id;
} catch (triggerError) {
console.error("Failed to trigger run-sandbox-command task:", triggerError);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Return an error when a requested command fails to trigger.

Right now a client can send command and still get a success response without runId if the trigger fails. That’s indistinguishable from “no command provided” and hides execution failures.

🐛 Suggested change
     if (validated.command) {
       try {
         const handle = await triggerRunSandboxCommand({
           command: validated.command,
           args: validated.args,
           cwd: validated.cwd,
           sandboxId: result.sandboxId,
           accountId: validated.accountId,
         });
         runId = handle.id;
       } catch (triggerError) {
         console.error("Failed to trigger run-sandbox-command task:", triggerError);
+        return NextResponse.json(
+          { status: "error", error: "Failed to run command in sandbox" },
+          { status: 502, headers: getCorsHeaders() },
+        );
       }
     }
🤖 Prompt for AI Agents
In `@lib/sandbox/createSandboxPostHandler.ts` around lines 43 - 57, The current
catch in createSandboxPostHandler swallows triggerRunSandboxCommand failures,
making a missing runId indistinguishable from "no command provided"; change the
catch in the block that calls triggerRunSandboxCommand to propagate a proper
error response instead of just logging: when triggerRunSandboxCommand({ command:
validated.command, args: validated.args, cwd: validated.cwd, sandboxId:
result.sandboxId, accountId: validated.accountId }) throws, rethrow or return a
4xx/5xx error (include the original error message) so the handler returns
failure to the client rather than a success without runId; update any
callers/response flow that rely on runId accordingly.

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

Comments