Skip to content

feat(named-sandboxes) rebase latest commits from main#138

Merged
marc-vercel merged 20 commits intonamed-sandboxesfrom
named-sandboxes-rebase-main
Apr 8, 2026
Merged

feat(named-sandboxes) rebase latest commits from main#138
marc-vercel merged 20 commits intonamed-sandboxesfrom
named-sandboxes-rebase-main

Conversation

@marc-vercel
Copy link
Copy Markdown
Collaborator

@marc-vercel marc-vercel commented Apr 8, 2026

Rebasing named-sandboxes. Commits that I am moving:

  1. cf13a34 — refactor(sdk): build @vercel/sandbox with tsdown dual outputs (refactor(sdk): build @vercel/sandbox with tsdown dual outputs #84)
  2. 772989c — Support "use workflow" serialization for Sandbox and Command (Support "use workflow" serialization for Sandbox and Command #72)
  3. cc74dbf — fix(sandbox): read package.json with fs instead of ESM import (fix(sandbox): read package.json with fs instead of ESM import #119)
  4. a6b8ce9 — feat(skill): update beta documentation for default snapshot expiration (feat(skill): update beta documentation for default snapshot expiration #125)
  5. 184cd42 — patch(vercel-sandbox): count length by bytes and not ASCII for binaries (patch(vercel-sandbox): count length by bytes and not ASCII for binaries #127)
  6. 451c42e — feat(sandbox): accept string and Uint8Array in writeFiles content (feat(sandbox): accept string and Uint8Array in writeFiles content #128)
  7. ad52dec — Version Packages (Version Packages #122)
  8. b91b9e4 — fix(sandbox): initialize API client in Command before reading output (fix(sandbox): initialize API client in Command before reading output #130)
  9. 28237b8 — refactor(workflow-code-runner): inline Sandbox calls in workflow function (refactor(workflow-code-runner): inline Sandbox calls in workflow function #129)
  10. 0786e18 — Version Packages (Version Packages #131)
  11. 9555162 — fix(sandbox): handle abort signal and early stream close in runCommand (fix(sandbox): handle abort signal and early stream close in runCommand #135)
  12. db4e5f3 — Version Packages (Version Packages #137)

I had to resolve multiple merge conflicts, specially with the commits 1 and 2. I've also added some tests for them because they were touching sandbox.ts for serializing and deserializing, and in this branch we moved most of the logic to session.ts.

Schniz and others added 12 commits April 8, 2026 10:18
- 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

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

- Updated dependencies
\[[`cf13a34221c2b83c25c73d94929d05e0a697aecf`](cf13a34),
[`772989c59a3c27efa98153cdc54b6e35c1c15eae`](772989c),
[`184cd42d8d3b1ea1df354529cb6ba103a33e18d3`](184cd42),
[`451c42efb94ab9c9dc330b4742071ac01008044d`](451c42e)]:
    -   @vercel/sandbox@1.9.1

- 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))

- Updated dependencies
\[[`cf13a34221c2b83c25c73d94929d05e0a697aecf`](cf13a34),
[`772989c59a3c27efa98153cdc54b6e35c1c15eae`](772989c),
[`184cd42d8d3b1ea1df354529cb6ba103a33e18d3`](184cd42),
[`451c42efb94ab9c9dc330b4742071ac01008044d`](451c42e)]:
    -   @vercel/sandbox@1.9.1

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

- Updated dependencies
\[[`b91b9e49fb7d2c5a4b601c07c125e6e5a2c43441`](b91b9e4)]:
    -   @vercel/sandbox@1.9.2

- Fix `stdout()`/`stderr()`/`output()` failing on deserialized `Command`
instances with "logs() requires an API client" error.
([#130](#130))

- Updated dependencies
\[[`b91b9e49fb7d2c5a4b601c07c125e6e5a2c43441`](b91b9e4)]:
    -   @vercel/sandbox@1.9.2

- Updated dependencies
\[[`b91b9e49fb7d2c5a4b601c07c125e6e5a2c43441`](b91b9e4)]:
    -   @vercel/sandbox@1.9.2

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 8, 2026

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

Project Deployment Actions Updated (UTC)
sandbox Ready Ready Preview, Comment, Open in v0 Apr 8, 2026 1:15pm
sandbox-cli Ready Ready Preview, Comment, Open in v0 Apr 8, 2026 1:15pm
sandbox-sdk Ready Ready Preview, Comment, Open in v0 Apr 8, 2026 1:15pm
sandbox-sdk-ai-example Ready Ready Preview, Comment, Open in v0 Apr 8, 2026 1:15pm
workflow-code-runner Ready Ready Preview, Comment, Open in v0 Apr 8, 2026 1:15pm

Request Review

@socket-security
Copy link
Copy Markdown

socket-security bot commented Apr 8, 2026

@socket-security
Copy link
Copy Markdown

socket-security bot commented Apr 8, 2026

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
High CVE: npm defu: Prototype pollution via `__proto__` key in defaults argument

CVE: GHSA-737v-mqg7-c878 defu: Prototype pollution via __proto__ key in defaults argument (HIGH)

Affected versions: < 6.1.5

Patched version: 6.1.5

From: pnpm-lock.yamlnpm/workflow@4.2.0-beta.73npm/defu@6.1.4

ℹ Read more on: This package | This alert | What is a CVE?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Remove or replace dependencies that include known high severity CVEs. Consumers can use dependency overrides or npm audit fix --force to remove vulnerable dependencies.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/defu@6.1.4. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

pbzona and others added 2 commits April 8, 2026 12:30
#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.

- Updated dependencies
\[[`9555162f33690dfa18530aeca93af05188ebd2ed`](9555162)]:
    -   @vercel/sandbox@1.9.3

- Handle abort signal and early stream close in runCommand to avoid
misleading Zod error
([#135](#135))

- Updated dependencies
\[[`9555162f33690dfa18530aeca93af05188ebd2ed`](9555162)]:
    -   @vercel/sandbox@1.9.3

- 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>
@marc-vercel marc-vercel marked this pull request as ready for review April 8, 2026 10:59
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.

7 participants