Merge main onto named-sandboxes branch#176
Merged
Merged
Conversation
## Summary - migrate `@vercel/sandbox` from custom TypeScript dual-build scripts to `tsdown` with unbundled `esm` + `cjs` outputs - add explicit export-map conditions for root and deep `./dist/*.js` paths so `import` resolves `.js` and `require` resolves `.cjs` - add package export resolution tests to verify Node `import` and `require` behavior, and include a changeset for the SDK package ## Validation - `pnpm build` (in `packages/vercel-sandbox`) - `pnpm typecheck` (in `packages/vercel-sandbox`) - `pnpm test src/package-exports.test.ts` (in `packages/vercel-sandbox`) --------- Co-authored-by: Luke Phillips-Sheard <luke.phillips-sheard@vercel.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Luke PS <LukeSheard@users.noreply.github.com>
#125) Changes: - Add documentation of the new supported `snapshot-expiration` parameter in our beta (both SDK/CLI). - Add in references documentation for our API endpoints, and also documentation for our persistent sandbox (beta) concept.
…es (#127) We have a bug in how we count the length of the contents, as we assume it is in ASCII. When the contents are binary (a character can have multiple bytes), we run into `Error: Size mismatch` when trying to write/read due to not taking into account these extra bytes. I've used AI to create a script to reproduce the bug, and here are the results. Without the fix: ``` Sandbox undefined created 1. Writing ASCII string (no Buffer.from)... OK: Hello world 2. Writing multi-byte UTF-8 string (no Buffer.from)... String .length (chars): 4 Buffer.byteLength: 5 /Users/marc/Documents/Repositories/my-sandbox-app/node_modules/.pnpm/tar-stream@3.1.7/node_modules/tar-stream/pack.js:103 return cb(new Error('Size mismatch')) ^ Error: Size mismatch ``` With the fix: ``` Sandbox undefined created 1. Writing ASCII string (no Buffer.from)... OK: Hello world 2. Writing multi-byte UTF-8 string (no Buffer.from)... String .length (chars): 4 Buffer.byteLength: 5 OK: café 3. Writing emoji + CJK string (no Buffer.from)... String .length (chars): 40 Buffer.byteLength: 63 OK: Hello 🌍🌎🌏! Grüße aus München. 日本語テスト。 ```
## Summary - Widens the `writeFiles()` `content` type from `Buffer` to `string | Uint8Array` (`Buffer` is implied since it extends `Uint8Array`) - This allows passing strings directly without needing `Buffer.from()`, which is important for environments where `Buffer` is not available (e.g. workflow runtime contexts) - Renames the internal `FileBuffer` interface to `FileData` to reflect the widened type - Adds tests for string and Uint8Array content in `FileWriter` - Fixes all `FileWriter` tests to properly `await` the `writer.end()` promise
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## sandbox@2.5.7 ### Patch Changes - Updated dependencies \[[`cf13a34221c2b83c25c73d94929d05e0a697aecf`](cf13a34), [`772989c59a3c27efa98153cdc54b6e35c1c15eae`](772989c), [`184cd42d8d3b1ea1df354529cb6ba103a33e18d3`](184cd42), [`451c42efb94ab9c9dc330b4742071ac01008044d`](451c42e)]: - @vercel/sandbox@1.9.1 ## @vercel/sandbox@1.9.1 ### Patch Changes - Build and publish both ESM and CJS outputs for the SDK package. ([#84](#84)) - Support useworkflow serialization for sandboxes and commands ([#72](#72)) - Fix a Size mismatch when encoding binaries during write operations ([#127](#127)) - Accept `string` and `Uint8Array` in `writeFiles()` content, not just `Buffer`. ([#128](#128)) ## sandbox-filesystem-snapshots@0.0.12 ### Patch Changes - Updated dependencies \[[`cf13a34221c2b83c25c73d94929d05e0a697aecf`](cf13a34), [`772989c59a3c27efa98153cdc54b6e35c1c15eae`](772989c), [`184cd42d8d3b1ea1df354529cb6ba103a33e18d3`](184cd42), [`451c42efb94ab9c9dc330b4742071ac01008044d`](451c42e)]: - @vercel/sandbox@1.9.1 ## workflow-code-runner@0.1.1 ### Patch Changes - Updated dependencies \[[`cf13a34221c2b83c25c73d94929d05e0a697aecf`](cf13a34), [`772989c59a3c27efa98153cdc54b6e35c1c15eae`](772989c), [`184cd42d8d3b1ea1df354529cb6ba103a33e18d3`](184cd42), [`451c42efb94ab9c9dc330b4742071ac01008044d`](451c42e)]: - @vercel/sandbox@1.9.1 --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Marc Codina <marc.codina@vercel.com>
…130) ## Summary - Fixes `stdout()`, `stderr()`, and `output()` failing with "logs() requires an API client" on deserialized `Command`/`CommandFinished` instances - After workflow deserialization, `_client` is null. `getCachedOutput()` calls `logs()` which is synchronous and throws immediately if `_client` is not set. The fix calls `ensureClient()` before `logs()` to lazily initialize the client. - Adds `throwIfAborted()` guard before `ensureClient()` to short-circuit on already-aborted signals, matching the pattern in `wait()` - Adds a test for deserialized `CommandFinished` without cached output to exercise the fix
…tion (#129) ## Summary - Removes `steps/sandbox.ts` — the wrapper functions (`createSandbox`, `execute`, `stopSandbox`) were redundant since `Sandbox.create()` and all instance methods already have `"use step"` built in - Inlines all Sandbox calls directly in the `"use workflow"` function in `workflows/code-runner.ts` - Passes code as a string to `writeFiles()` instead of wrapping with `Buffer.from()` (which is unavailable in the workflow runtime) Depends on #130.
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## sandbox@2.5.8 ### Patch Changes - Updated dependencies \[[`b91b9e49fb7d2c5a4b601c07c125e6e5a2c43441`](b91b9e4)]: - @vercel/sandbox@1.9.2 ## @vercel/sandbox@1.9.2 ### Patch Changes - Fix `stdout()`/`stderr()`/`output()` failing on deserialized `Command` instances with "logs() requires an API client" error. ([#130](#130)) ## sandbox-filesystem-snapshots@0.0.13 ### Patch Changes - Updated dependencies \[[`b91b9e49fb7d2c5a4b601c07c125e6e5a2c43441`](b91b9e4)]: - @vercel/sandbox@1.9.2 ## workflow-code-runner@0.1.2 ### Patch Changes - Updated dependencies \[[`b91b9e49fb7d2c5a4b601c07c125e6e5a2c43441`](b91b9e4)]: - @vercel/sandbox@1.9.2 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
#135) ## Summary When `runCommand` is called with `wait: true`, the API returns an ndjson stream with two JSON chunks (command started, command finished). Two problems with how this stream is consumed: 1. **Abort signal hangs forever.** If an `AbortSignal` fires mid-stream (e.g. `AbortSignal.timeout()`), the HTTP body closes but the `jsonlines` transform stream stays open. The `iterator.next()` call waiting for the second chunk blocks indefinitely — it never resolves or rejects. 2. **Early stream close throws ZodError.** If the stream closes after the first chunk but before the second (e.g. server drops connection), `iterator.next()` returns `{ done: true, value: undefined }`. `CommandFinishedResponse.parse(undefined)` then throws a Zod validation error instead of a meaningful message. ### Fix - Wire the abort signal to `jsonlinesStream.destroy()` so pending `iterator.next()` calls reject immediately instead of hanging - Check `iterator.done` before parsing to throw a `StreamError` instead of a ZodError - Clean up the abort listener when the stream is fully consumed ## Test plan - [ ] `throws abort error (not Zod error) when signal aborts before stream finishes` — abort mid-stream rejects instead of hanging - [ ] `throws StreamError when stream closes before finished chunk arrives` — early close throws StreamError, not ZodError - [ ] `rejects when signal is already aborted before stream starts` — pre-aborted signal rejects immediately - [ ] Existing `runCommand` and full suite tests still pass First commit shows the intentionally failing tests to illustrate the behavior. Open to suggestions on the specific error handling behavior, I just don't think it should be a Zod error in these cases. It's technically expected but could be more helpful.
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## sandbox@2.5.9 ### Patch Changes - Updated dependencies \[[`9555162f33690dfa18530aeca93af05188ebd2ed`](9555162)]: - @vercel/sandbox@1.9.3 ## @vercel/sandbox@1.9.3 ### Patch Changes - Handle abort signal and early stream close in runCommand to avoid misleading Zod error ([#135](#135)) ## sandbox-filesystem-snapshots@0.0.14 ### Patch Changes - Updated dependencies \[[`9555162f33690dfa18530aeca93af05188ebd2ed`](9555162)]: - @vercel/sandbox@1.9.3 ## workflow-code-runner@0.1.3 ### Patch Changes - Updated dependencies \[[`9555162f33690dfa18530aeca93af05188ebd2ed`](9555162)]: - @vercel/sandbox@1.9.3 --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Marc Codina <marc.codina@vercel.com>
The CLI tests are not working. ``` FAIL test/args/auth.test.ts [ test/args/auth.test.ts ] FAIL test/args/scope.test.ts [ test/args/scope.test.ts ] FAIL test/commands/cp.test.ts [ test/commands/cp.test.ts ] FAIL test/types/duration.test.ts [ test/types/duration.test.ts ] Error: require() of ES Module /Users/marc/Documents/Repositories/sandbox/node_modules/.pnpm/chalk@5.6.0/node_modules/chalk/source/index.js from /Users/marc/Documents/Repositories/sandbox/node_modules/.pnpm/cmd-ts@0.15.0/node_modules/cmd-ts/dist/cjs/subcommands.js not supported. Instead change the require of index.js in /Users/marc/Documents/Repositories/sandbox/node_modules/.pnpm/cmd-ts@0.15.0/node_modules/cmd-ts/dist/cjs/subcommands.js to a dynamic import() which is available in all CommonJS modules. ❯ Object.<anonymous> ../../node_modules/.pnpm/cmd-ts@0.15.0/node_modules/cmd-ts/dist/cjs/subcommands.js:40:33 ``` Fix them by adding a new vitest config file where we explicitly point `cmd-ts` to load the ESM entry.
The default Undici `Agent` is currently not reused across instances of `Sandbox` / `Snapshot` classes, which means we are not reusing the already opened connection pools.
This PR introduces a node:fs-compatible API for the Vercel Sandbox environment. The goal is to provide a familiar, minimal subset of Node’s filesystem interface that works within the constraints of the Sandbox runtime, enabling easier portability of existing Node.js code and libraries. In particular provide something we can pass directly around with `just-bash` as an `fs` implementation without needing their `Sandbox` primitive wrapper. --------- Co-authored-by: Nathan Rajlich <n@n8.io>
…140) ## Summary - Adds `WORKFLOW_SERIALIZE` / `WORKFLOW_DESERIALIZE` static methods to the `Snapshot` class, fixing serialization errors when a `Snapshot` instance is returned from a workflow step. - Uses the same lazy-client pattern as `Sandbox` and `Command`: only plain `SnapshotMetadata` is serialized (credentials are excluded), and an API client is lazily created via `ensureClient()` when needed after deserialization. - Includes 10 tests covering serialize/deserialize roundtrips, credential exclusion, and full `dehydrate`/`hydrate` through the workflow runtime pipeline.
## Summary - Fetches both `/v2/user` and `/v2/teams` in parallel to build an ordered list of candidate teams for scope inference - Tries `user.defaultTeamId` first, then falls back to the best hobby-plan OWNER team (personal team matching username, or most recently updated) - Filters fallback candidates by `billing.plan === 'hobby'` and `membership.role === 'OWNER'` to avoid selecting pro/enterprise teams - On 403, skips to the next candidate instead of failing immediately - Only throws after all candidates are exhausted, with a helpful error message including the authenticated username --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Marc Codina <marc.codina@vercel.com>
the changeset definition is wrong
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @vercel/sandbox@1.10.0 ### Minor Changes - Expose Filesystem api from Sandbox ([#112](#112)) ### Patch Changes - Reuse Undici `Agent` across instances ([#143](#143)) - Smarter fallback team selection for scope inference: tries `defaultTeamId` first, then the best hobby-plan OWNER team (personal team or most recently updated). Filters fallback candidates by `billing.plan === 'hobby'` to avoid selecting pro/enterprise teams. Skips teams that return 403 and shows a helpful error when no team allows sandbox creation. ([#120](#120)) - Add workflow serialization support for the `Snapshot` class via `WORKFLOW_SERIALIZE` / `WORKFLOW_DESERIALIZE`, fixing serialization errors when a `Snapshot` instance is returned from a workflow step. ([#140](#140)) ## sandbox@2.5.10 ### Patch Changes - Smarter fallback team selection for scope inference: tries `defaultTeamId` first, then the best hobby-plan OWNER team (personal team or most recently updated). Filters fallback candidates by `billing.plan === 'hobby'` to avoid selecting pro/enterprise teams. Skips teams that return 403 and shows a helpful error when no team allows sandbox creation. ([#120](#120)) - Updated dependencies \[[`9dc0ac96d1d531b5a44786c92d6ddc2ce4890791`](9dc0ac9), [`494c2ddae5899b7f793cbd906a2a62260bd08885`](494c2dd), [`3fbabb95946771e41d8b17b7f8cb8d2972beba25`](3fbabb9), [`42515e1ede4468fad204e5332ade0ee5d8dce3e5`](42515e1)]: - @vercel/sandbox@1.10.0 ## sandbox-filesystem-snapshots@0.0.15 ### Patch Changes - Updated dependencies \[[`9dc0ac96d1d531b5a44786c92d6ddc2ce4890791`](9dc0ac9), [`494c2ddae5899b7f793cbd906a2a62260bd08885`](494c2dd), [`3fbabb95946771e41d8b17b7f8cb8d2972beba25`](3fbabb9), [`42515e1ede4468fad204e5332ade0ee5d8dce3e5`](42515e1)]: - @vercel/sandbox@1.10.0 ## workflow-code-runner@0.1.4 ### Patch Changes - Updated dependencies \[[`9dc0ac96d1d531b5a44786c92d6ddc2ce4890791`](9dc0ac9), [`494c2ddae5899b7f793cbd906a2a62260bd08885`](494c2dd), [`3fbabb95946771e41d8b17b7f8cb8d2972beba25`](3fbabb9), [`42515e1ede4468fad204e5332ade0ee5d8dce3e5`](42515e1)]: - @vercel/sandbox@1.10.0 --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Gal Schlezinger <gal@spitfire.co.il>
Enterprise now supports 32 vCPUs as per https://vercel.com/changelog/vercel-sandbox-now-supports-up-to-32-vcpu-64-gb-ram-configurations . This PR updates the README.md to reflect that.
Fix the timeout examples so that we do not introduce `1h` because it exceeds hobby limits. Now the example is just `5m` or `30m`. Also, fix how we show the timeout. Before, we rounded the timeout to the closes unit (in his case 1 hour): ``` ❯ sandbox list ID STATUS CREATED MEMORY VCPUS RUNTIME TIMEOUT SNAPSHOT sbx_MGhwG22sB5zWNiPtGcvDsUUeN7GY running 6 minutes ago 4,096 MB 2 node24 in 1 hour - sbx_tk00HLr2SZvXzjcXT24wJ4zshsCY running 8 minutes ago 4,096 MB 2 node24 in 1 hour - ``` Now, we show the exact timeout value: ``` ❯ sandbox list ID STATUS CREATED MEMORY VCPUS RUNTIME TIMEOUT SNAPSHOT sbx_MGhwG22sB5zWNiPtGcvDsUUeN7GY running 7 minutes ago 4,096 MB 2 node24 in 53 minutes - sbx_tk00HLr2SZvXzjcXT24wJ4zshsCY running 8 minutes ago 4,096 MB 2 node24 in 52 minutes - ```
This adds a GHA and a new token that set for triggering the GHA on `vercel/vercel` to uptick the version for sandbox cli t make vercel cli up to date with sandbox cli
Update the base URL API for the auth requests in the SDK to `vercel.com/api` Also removing `packages/sandbox/src/util/api.ts` because it was unused
Fix the release pipeline by using trusted publishing. --------- Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
We need to make the changeset commits signed. As of now, we are getting this error from the PR that changeset attempts to create: ``` remote: error: GH013: Repository rule violations found for refs/heads/changeset-release/main. remote: Review all repository rules at https://github.com/vercel/sandbox/rules?ref=refs%2Fheads%2Fchangeset-release%2Fmain remote: remote: - Commits must have verified signatures. remote: Found 1 violation: remote: remote: 027faa7 remote: To https://github.com/vercel/sandbox ! [remote rejected] HEAD -> changeset-release/main (push declined due to repository rule violations) ```
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## sandbox@2.5.11 ### Patch Changes - Improve timeout hour format and example values ([#150](#150)) - Updated dependencies \[[`92725f07386f692c9492deff6ba4595fa754c465`](92725f0)]: - @vercel/sandbox@1.10.1 ## @vercel/sandbox@1.10.1 ### Patch Changes - Update auth API base URL ([#166](#166)) ## sandbox-filesystem-snapshots@0.0.16 ### Patch Changes - Updated dependencies \[[`92725f07386f692c9492deff6ba4595fa754c465`](92725f0)]: - @vercel/sandbox@1.10.1 ## workflow-code-runner@0.1.5 ### Patch Changes - Updated dependencies \[[`92725f07386f692c9492deff6ba4595fa754c465`](92725f0)]: - @vercel/sandbox@1.10.1 --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Marc Codina <marc.codina@vercel.com>
…blisher (#170) Enforce Github Actions to use Node24 instead of the default (Node 22) because we need at least npm ≥ 11.5.1 to use trusted publishing. Node 22 ships with npm 10.x, which is too old and does not support it. We are trying to fix this CI error now: ``` > changeset publish 🦋 info npm info sandbox 🦋 info npm info @vercel/sandbox 🦋 info sandbox is being published because our local version (2.5.11) has not been published on npm 🦋 info @vercel/sandbox is being published because our local version (1.10.1) has not been published on npm 🦋 info Publishing "sandbox" at "2.5.11" 🦋 info Publishing "@vercel/sandbox" at "1.10.1" 🦋 error an error occurred while publishing @vercel/sandbox: ENEEDAUTH This command requires you to be logged in to https://registry.npmjs.org/ 🦋 error You need to authorize this machine using `npm adduser` 🦋 error npm error code ENEEDAUTH 🦋 error npm error need auth This command requires you to be logged in to https://registry.npmjs.org/ 🦋 error npm error need auth You need to authorize this machine using `npm adduser` 🦋 error npm error A complete log of this run can be found in: /home/runner/.npm/_logs/2026-04-29T10_02_05_534Z-debug-0.log 🦋 error 🦋 error an error occurred while publishing sandbox: ENEEDAUTH This command requires you to be logged in to https://registry.npmjs.org/ 🦋 error You need to authorize this machine using `npm adduser` 🦋 error npm error code ENEEDAUTH 🦋 error npm error need auth This command requires you to be logged in to https://registry.npmjs.org/ 🦋 error npm error need auth You need to authorize this machine using `npm adduser` 🦋 error npm error A complete log of this run can be found in: /home/runner/.npm/_logs/2026-04-29T10_02_05_755Z-debug-0.log 🦋 error 🦋 error packages failed to publish: 🦋 sandbox@2.5.11 🦋 @vercel/sandbox@1.10.1 ```
# Conflicts: # .github/workflows/publish.yml # examples/filesystem-snapshots/CHANGELOG.md # examples/filesystem-snapshots/package.json # examples/workflow-code-runner/CHANGELOG.md # examples/workflow-code-runner/package.json # packages/sandbox/CHANGELOG.md # packages/sandbox/docs/index.md # packages/sandbox/package.json # packages/vercel-sandbox/CHANGELOG.md # packages/vercel-sandbox/package.json # packages/vercel-sandbox/src/api-client/api-client.test.ts # packages/vercel-sandbox/src/api-client/api-client.ts # packages/vercel-sandbox/src/command.serialize.test.ts # packages/vercel-sandbox/src/command.test.ts # packages/vercel-sandbox/src/command.ts # packages/vercel-sandbox/src/index.ts # packages/vercel-sandbox/src/sandbox.serialize.test.ts # packages/vercel-sandbox/src/sandbox.test.ts # packages/vercel-sandbox/src/sandbox.ts # packages/vercel-sandbox/src/snapshot.serialize.test.ts # packages/vercel-sandbox/src/snapshot.ts # packages/vercel-sandbox/src/utils/get-credentials.test.ts # packages/vercel-sandbox/src/utils/network-policy.test.ts # packages/vercel-sandbox/src/utils/network-policy.ts # packages/vercel-sandbox/src/utils/sandbox-snapshot.ts # packages/vercel-sandbox/src/version.ts
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
LukeSheard
approved these changes
May 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.