Repository navigation
Fix SDK Explorer sandbox execution hangs - #1559
Conversation
- Write `execute({ files })` inputs before `/execute`
- Stop failed `run()` calls from waiting on output streams
- Filter non-reusable storage env in Explorer demos
|
The latest Agentuity deployment details.
|
|
Warning Review limit reached
More reviews will be available in 48 minutes and 9 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more credits in the billing tab to continue. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThis PR refines sandbox execution to handle credentials more carefully, stages files via a dedicated endpoint before execution, and fixes control flow to prevent hung output streams from masking execution failures. The changes span sandbox route handlers, core execution services, and corresponding test suites. ChangesSandbox Credential and Execution Flow Improvements
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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. Comment |
📦 Canary Packages Publishedversion: PackagesInstallAdd to your {
"dependencies": {
"@agentuity/webhook": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-webhook-3.0.8-5daa8b3.tgz",
"@agentuity/schema": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-schema-3.0.8-5daa8b3.tgz",
"@agentuity/adapter": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-adapter-3.0.8-5daa8b3.tgz",
"@agentuity/schedule": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-schedule-3.0.8-5daa8b3.tgz",
"@agentuity/core": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-core-3.0.8-5daa8b3.tgz",
"@agentuity/server": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-server-3.0.8-5daa8b3.tgz",
"@agentuity/vite": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-vite-3.0.8-5daa8b3.tgz",
"@agentuity/keyvalue": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-keyvalue-3.0.8-5daa8b3.tgz",
"@agentuity/queue": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-queue-3.0.8-5daa8b3.tgz",
"@agentuity/analytics": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-analytics-3.0.8-5daa8b3.tgz",
"@agentuity/local": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-local-3.0.8-5daa8b3.tgz",
"@agentuity/cli": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-cli-3.0.8-5daa8b3.tgz",
"@agentuity/postgres": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-postgres-3.0.8-5daa8b3.tgz",
"@agentuity/db": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-db-3.0.8-5daa8b3.tgz",
"@agentuity/coder-tui": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-coder-tui-3.0.8-5daa8b3.tgz",
"@agentuity/opencode": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-opencode-3.0.8-5daa8b3.tgz",
"@agentuity/aigateway": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-aigateway-3.0.8-5daa8b3.tgz",
"@agentuity/email": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-email-3.0.8-5daa8b3.tgz",
"@agentuity/sandbox": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-sandbox-3.0.8-5daa8b3.tgz",
"@agentuity/hono": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-hono-3.0.8-5daa8b3.tgz",
"@agentuity/runtime": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-runtime-3.0.8-5daa8b3.tgz",
"@agentuity/task": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-task-3.0.8-5daa8b3.tgz",
"@agentuity/storage": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-storage-3.0.8-5daa8b3.tgz",
"@agentuity/stream": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-stream-3.0.8-5daa8b3.tgz",
"@agentuity/drizzle": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-drizzle-3.0.8-5daa8b3.tgz",
"@agentuity/claude-code": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-claude-code-3.0.8-5daa8b3.tgz",
"@agentuity/pi": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-pi-3.0.8-5daa8b3.tgz",
"@agentuity/telemetry": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-telemetry-3.0.8-5daa8b3.tgz",
"@agentuity/migrate": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-migrate-3.0.8-5daa8b3.tgz",
"create-agentuity": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/create-agentuity-3.0.8-5daa8b3.tgz",
"@agentuity/coder": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-coder-3.0.8-5daa8b3.tgz",
"@agentuity/vector": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-vector-3.0.8-5daa8b3.tgz"
}
}Or install directly: bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-webhook-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-schema-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-adapter-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-schedule-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-core-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-server-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-vite-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-keyvalue-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-queue-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-analytics-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-local-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-cli-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-postgres-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-db-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-coder-tui-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-opencode-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-aigateway-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-email-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-sandbox-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-hono-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-runtime-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-task-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-storage-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-stream-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-drizzle-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-claude-code-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-pi-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-telemetry-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-migrate-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/create-agentuity-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-coder-3.0.8-5daa8b3.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/3.0.8-5daa8b3/agentuity-vector-3.0.8-5daa8b3.tgz |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/server/test/sandbox-client.test.ts (1)
261-338: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winAssert the
/fs→/executecall order explicitly.This regression currently proves that both requests happen and that
/executeomitsfiles, but it does not prove that file staging happens first. A reversed implementation would still satisfy these assertions and reintroduce the race this test is meant to catch.💡 Tighten the regression
test('execute with files should stage files before executing command', async () => { + const calls: string[] = []; let executeRequestBody: Record<string, unknown> | null = null; let writeFilesRequestBody: Record<string, unknown> | null = null; mockFetch(async (url, opts) => { if (opts?.method === 'POST' && url.includes('/fs/sandbox-123')) { + calls.push('fs'); writeFilesRequestBody = JSON.parse(opts.body as string); return new Response( JSON.stringify({ success: true, data: { filesWritten: 2 }, @@ if (opts?.method === 'POST' && url.includes('/execute')) { + calls.push('execute'); executeRequestBody = JSON.parse(opts.body as string); return new Response( JSON.stringify({ success: true, @@ expect(writeFilesRequestBody!.files).toEqual([ { path: 'script.ts', content: Buffer.from('console.log("hello")').toString('base64') }, { path: 'data.json', content: Buffer.from('{"key": "value"}').toString('base64') }, ]); expect(executeRequestBody).not.toBeNull(); expect(executeRequestBody!.command).toEqual(['bun', 'run', 'script.ts']); expect(executeRequestBody!.files).toBeUndefined(); + expect(calls).toEqual(['fs', 'execute']); });🤖 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/server/test/sandbox-client.test.ts` around lines 261 - 338, The test currently only checks that both the /fs write and /execute requests occurred and that execute omitted files, but doesn't assert their order; update the mockFetch handlers in the test (the POST handler for URLs containing '/fs/sandbox-123' and the POST handler for URLs containing '/execute') to push markers into a local sequence array (e.g., push 'write' in the fs handler and 'execute' in the execute handler) when each handler runs, then after calling SandboxClient.create() and sandbox.execute(...) assert that the sequence array equals ['write','execute'] to guarantee files are staged before execution; keep existing checks for writeFilesRequestBody and executeRequestBody.
🧹 Nitpick comments (1)
docs/src/api/test/sandbox-route.test.ts (1)
10-11: 📐 Maintainability & Code Quality | 💤 Low valueConsider using
process.envconsistently for portability.While
Bun.envis valid and works in Bun runtime, usingprocess.envthroughout the test file (as done insetStorageEnvon lines 131-138) would improve consistency and make the code more portable across different runtimes.♻️ Optional refactor for consistency
-Bun.env.SANDBOX_SNAPSHOT_ID = 'snapshot_test'; -Bun.env.AGENTUITY_SDK_KEY = 'sdk_test'; +process.env.SANDBOX_SNAPSHOT_ID = 'snapshot_test'; +process.env.AGENTUITY_SDK_KEY = 'sdk_test';🤖 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 `@docs/src/api/test/sandbox-route.test.ts` around lines 10 - 11, The test uses Bun.env.SANDBOX_SNAPSHOT_ID and Bun.env.AGENTUITY_SDK_KEY while other helpers (setStorageEnv) use process.env; change the two assignments to process.env.SANDBOX_SNAPSHOT_ID = 'snapshot_test' and process.env.AGENTUITY_SDK_KEY = 'sdk_test' to keep environment access consistent and portable, leaving the same keys/values and any existing tear-down or restore behavior intact.
🤖 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 `@packages/core/src/services/sandbox/execute.ts`:
- Around line 88-94: The current execute flow calls sandboxWriteFiles (in
execute.ts) before attempting the execute request, causing the workspace to be
mutated even if the subsequent execute fails; either defer file staging into the
same request (create an atomic executeWithFiles server endpoint that accepts
files + execute in one call) or add a reliable rollback path: after calling
sandboxWriteFiles(sandboxId, files, orgId, signal) invoke the execute RPC and if
it returns non-2xx, 409/404, is cancelled, or errors on transport, call a
cleanup API (e.g., sandboxDeleteFiles or sandboxCleanupFiles) with the same
sandboxId/files (and propagate the original error) and ensure the same
signal/timeout is used so partial staging is cleaned up; update execute.ts to
use the new atomic endpoint or implement the try -> finally rollback logic
around sandboxWriteFiles and reference sandboxWriteFiles, sandboxId,
options.files, and the execute RPC call.
In `@packages/core/src/services/sandbox/run.ts`:
- Around line 255-264: The race between executionGet and sandboxGetStatus in
waitForRunCompletion leaves the losing long-poll alive; after completionPromise
(the Promise.race) resolves in sandboxRun(), explicitly abort the still-pending
waiter so its underlying request is cancelled. Modify waitForRunCompletion()/the
callers to use separate AbortController(s) for each branch (or return a cancel
function) and, once completionPromise settles (the variable finalExecution is
set), call abort() on the controller for the branch that lost the race; ensure
abortController used for streamsPromise is not confused with the per-waiter
controllers so streamsPromise behavior remains unchanged.
---
Outside diff comments:
In `@packages/server/test/sandbox-client.test.ts`:
- Around line 261-338: The test currently only checks that both the /fs write
and /execute requests occurred and that execute omitted files, but doesn't
assert their order; update the mockFetch handlers in the test (the POST handler
for URLs containing '/fs/sandbox-123' and the POST handler for URLs containing
'/execute') to push markers into a local sequence array (e.g., push 'write' in
the fs handler and 'execute' in the execute handler) when each handler runs,
then after calling SandboxClient.create() and sandbox.execute(...) assert that
the sequence array equals ['write','execute'] to guarantee files are staged
before execution; keep existing checks for writeFilesRequestBody and
executeRequestBody.
---
Nitpick comments:
In `@docs/src/api/test/sandbox-route.test.ts`:
- Around line 10-11: The test uses Bun.env.SANDBOX_SNAPSHOT_ID and
Bun.env.AGENTUITY_SDK_KEY while other helpers (setStorageEnv) use process.env;
change the two assignments to process.env.SANDBOX_SNAPSHOT_ID = 'snapshot_test'
and process.env.AGENTUITY_SDK_KEY = 'sdk_test' to keep environment access
consistent and portable, leaving the same keys/values and any existing tear-down
or restore behavior intact.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: da411d9a-2382-4cf7-8510-c3c9df89c362
📒 Files selected for processing (5)
docs/src/api/sandbox/route.tsdocs/src/api/test/sandbox-route.test.tspackages/core/src/services/sandbox/execute.tspackages/core/src/services/sandbox/run.tspackages/server/test/sandbox-client.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
- GitHub Check: Migrate Chain (v1 → v2 → v3)
- GitHub Check: Queue CLI Tests (bun)
- GitHub Check: Queue CLI Tests (node)
- GitHub Check: Package Installation & Usage Test (node)
- GitHub Check: Postgres SSL Integration Test
- GitHub Check: Framework Demo Tests
- GitHub Check: Package Installation & Usage Test (bun)
- GitHub Check: Service Client Smoke Tests
- GitHub Check: Windows WSL CLI Smoke Test
- GitHub Check: Pack & Upload
- GitHub Check: Build
- GitHub Check: Agentuity Deployment
🧰 Additional context used
📓 Path-based instructions (5)
packages/core/src/**/*.ts
📄 CodeRabbit inference engine (packages/core/AGENTS.md)
packages/core/src/**/*.ts: Build TypeScript code usingbun run buildwhich compiles with tsc
Run TypeScript type checking withbun run typecheck
Ensure runtime compatibility with both Browser and Node/Bun environments - no runtime-specific code
Use ESNext as build target with TypeScript declaration files
Use TypeScript-first development - all code must be TypeScript
Prefer interfaces for public APIs
Use generics for reusable type utilities
Ensure no framework coupling - code must work in any JavaScript environment
Many exports aretypeorinterfaceonly - usetypekeyword for type-only exports
Ensure all exports are pure with no side effects or global mutations
All relative imports in TypeScript files MUST include the.tsextension for proper ESM module resolution
Files:
packages/core/src/services/sandbox/execute.tspackages/core/src/services/sandbox/run.ts
packages/core/src/services/**/*.ts
📄 CodeRabbit inference engine (packages/core/AGENTS.md)
packages/core/src/services/**/*.ts: Follow StandardSchemaV1 spec for validation interfaces
Storage services must take a FetchAdapter for HTTP abstraction
Files:
packages/core/src/services/sandbox/execute.tspackages/core/src/services/sandbox/run.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Run
bun run formatusing Biome with tabs (width 3), single quotes, semicolons, lineWidth 100, and trailingCommas es5
Files:
packages/core/src/services/sandbox/execute.tspackages/core/src/services/sandbox/run.tspackages/server/test/sandbox-client.test.tsdocs/src/api/sandbox/route.tsdocs/src/api/test/sandbox-route.test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use TypeScript in strict mode with ESNext target and bundler moduleResolution
UseStructuredErrorfrom@agentuity/corefor error handling
Files:
packages/core/src/services/sandbox/execute.tspackages/core/src/services/sandbox/run.tspackages/server/test/sandbox-client.test.tsdocs/src/api/sandbox/route.tsdocs/src/api/test/sandbox-route.test.ts
**/packages/*/test/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/packages/*/test/**/*.{ts,tsx}: Place tests intest/folder parallel tosrc/directory, never insidesrc/or under__tests__/
Import from../src/in test files
Use@agentuity/test-utilsfor shared mocks in tests
Files:
packages/server/test/sandbox-client.test.ts
🧠 Learnings (5)
📚 Learning: 2025-12-21T00:31:41.858Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 274
File: packages/cli/src/cmd/build/vite/server-bundler.ts:12-41
Timestamp: 2025-12-21T00:31:41.858Z
Learning: In Bun runtime, BuildMessage and ResolveMessage are global types and are not exported from the bun module. Do not import { BuildMessage } from 'bun' or similar; these types are available globally and should be used without import. This applies to all TypeScript files that target the Bun runtime within the repository.
Applied to files:
packages/core/src/services/sandbox/execute.tspackages/core/src/services/sandbox/run.tspackages/server/test/sandbox-client.test.tsdocs/src/api/sandbox/route.tsdocs/src/api/test/sandbox-route.test.ts
📚 Learning: 2025-12-30T00:13:37.849Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 355
File: packages/server/src/api/sandbox/util.ts:2-6
Timestamp: 2025-12-30T00:13:37.849Z
Learning: In the packages/server tree, treat code as runtime-agnostic between Node.js and Bun. Ensure TypeScript files (e.g., util.ts) import and use APIs in a way that works under both runtimes. It is acceptable to rely on Bun’s Node.js compatibility for built-ins accessed via the node: namespace (e.g., node:events, node:stream, node:buffer). During reviews, prefer patterns and imports that remain compatible with Bun's environment, and flag any hard dependencies on runtime-specific globals or non-portable Node APIs.
Applied to files:
packages/server/test/sandbox-client.test.ts
📚 Learning: 2026-02-21T02:05:57.982Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 1010
File: packages/drizzle/test/proxy.test.ts:594-603
Timestamp: 2026-02-21T02:05:57.982Z
Learning: Do not rely on StructuredError from agentuity/core in test files or simple error handling paths. In tests and straightforward error handling, use plain Error objects to represent failures, reserving StructuredError for more complex error scenarios in application logic.
Applied to files:
packages/server/test/sandbox-client.test.tsdocs/src/api/test/sandbox-route.test.ts
📚 Learning: 2025-12-19T14:19:33.765Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 259
File: packages/cli/src/cmd/build/vite/registry-generator.ts:306-312
Timestamp: 2025-12-19T14:19:33.765Z
Learning: Route files under src/api should use the .ts extension only (no .tsx) and regex patterns for such paths should anchor to \.ts$ (e.g., /\/.ts$/). Agent files may support both .ts and .tsx, but route files in the Agentuity SDK codebase are restricted to .ts. This guideline applies to all similar route files under src/api across the repository.
Applied to files:
docs/src/api/sandbox/route.tsdocs/src/api/test/sandbox-route.test.ts
📚 Learning: 2026-02-25T22:13:01.823Z
Learnt from: Huijiro
Repo: agentuity/sdk PR: 1063
File: apps/testing/vite-rsc-app/agentuity/src/api/index.ts:26-26
Timestamp: 2026-02-25T22:13:01.823Z
Learning: Agentuity SDK requires default exports for API route files (e.g., src/api/**/index.ts and src/api/**/route.ts) because the CLI's generateRouteRegistry relies on default exports to discover routes. Using named exports will skip route generation and lead to runtime 500 errors. This overrides typical guidance about named exports in index.ts files; ensure a default export is present in all relevant API route files under src/api/**/.
Applied to files:
docs/src/api/sandbox/route.ts
🔇 Additional comments (5)
docs/src/api/sandbox/route.ts (3)
85-126: LGTM!
288-293: LGTM!
13-13: 📐 Maintainability & Code QualityRelative imports in
docs/src/apidon’t use.tsextensions
docs/src/api/**(includingdocs/src/api/sandbox/route.ts) consistently uses extensionless relative imports likeimport { sse } from '../http';, and there are no relative imports with.tsextensions indocs/src/api. The.ts-extension convention appears to be specific topackages/core/src/**, not the docs layer.docs/src/api/test/sandbox-route.test.ts (2)
106-192: LGTM!
208-338: LGTM!
- Roll back staged execute files when `/execute` is rejected - Abort the losing `run()` completion waiter after a race win - Cover both paths in sandbox client tests
Summary
Fixes SDK Explorer sandbox runs that could stay on
Executing...even after the route sent a command.execute({ files })API, but stages files before calling/executesandboxRun()return failed terminal states without waiting for output streams that stay openWhy
The Explorer route was using the same high-level shape everywhere: send a bundled script file, then run it inside a sandbox. That is the right API for callers, but the live execute path can hang when files are sent inside the execute request.
The safer flow is two steps:
The object-storage demo had a second boundary issue. Some deployment-provided storage values are scoped to the parent runtime. A child sandbox needs reusable storage env, so the route now forwards only the compatible S3-shaped values for that demo.
Implementation
The public caller shape stays the same:
Under the hood,
sandboxExecute()now stages files before it sends the execute request:The execute request then carries the command, timeout, and stream options. It does not send file payloads inline.
sandboxRun()also checks the terminal execution status before waiting for output streams to drain:That lets failed creates and failed executions return promptly instead of waiting on streams that may remain open until the client deadline.
For SDK Explorer object storage, the route copies storage env only for the object-storage script:
The helper prefers reusable
S3_*values and skips parent-scoped credential values that cannot be reused inside a child sandbox.Verification
git diff --cached --checkbun test src/api/test/sandbox-route.test.tsbun test test/sandbox-client.test.tsbunx biome check docs/src/api/sandbox/route.ts docs/src/api/test/sandbox-route.test.ts packages/core/src/services/sandbox/execute.ts packages/core/src/services/sandbox/run.ts packages/server/test/sandbox-client.test.tscd docs && bun run typecheckcd packages/core && bun run typecheckcd packages/server && bun run typecheckcd packages/core && bun run buildcd packages/server && bun run buildcd docs && bun run build:runagentuity devSDK Explorer sweep: all 18 sandbox route scripts emitted terminaldoneSummary by CodeRabbit
Bug Fixes
Tests