feat(provider-utils): add spawnCommand method to Experimental_Sandbox to allow for detached command execution#15551
Merged
Merged
Conversation
dancer
approved these changes
May 22, 2026
lgrammel
reviewed
May 26, 2026
| stderr: new ReadableStream<Uint8Array>({ start: c => c.close() }), | ||
| wait: async () => ({ exitCode: 0 }), | ||
| kill: async () => {}, | ||
| }), |
Collaborator
There was a problem hiding this comment.
having mock-sandbox in provider utils might avoid having these changes
lgrammel
reviewed
May 26, 2026
| * `runCommand` is conceptually a thin wrapper over this primitive: spawn, | ||
| * collect both streams to strings, await `wait()`, return the result. | ||
| */ | ||
| readonly spawnCommand: (options: { |
Collaborator
There was a problem hiding this comment.
wondering about the name re discoverability.
spawnProcess makes more sense to me. The docs say process and it returns a SandboxProcess.
or if we want command, runCommandDetached (not a big fan though)
lgrammel
reviewed
May 26, 2026
| workingDirectory?: string; | ||
| abortSignal?: AbortSignal; | ||
| }) { | ||
| const proc = await this.spawnCommand({ |
lgrammel
reviewed
May 26, 2026
| /** | ||
| * Resolve when the process exits, yielding its exit code. | ||
| */ | ||
| wait(): PromiseLike<{ exitCode: number }>; |
Collaborator
There was a problem hiding this comment.
waitForExit ? (wait might be fine)
lgrammel
approved these changes
May 26, 2026
Collaborator
Author
|
@lgrammel renamed |
Contributor
|
🚀 Published in:
|
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.
Background
Experimental_Sandboxonly exposedrunCommand, which runs to completion and returns buffered stdout/stderr. Consumers building agents/harnesses on top need a way to spawn a long-running process and react to its output as it arrives, whichrunCommandcannot provide. Just like how we use streams for the foundations for reading and writing files, we should use streams for the foundation of running a command.Summary
Adds
spawnCommandas a new primitive onExperimental_Sandbox, returning a process handle (Experimental_SandboxProcess) that streamsstdout/stderrand exposeswait()/kill().runCommandis now conceptually a thin wrapper: spawn → drain both streams → awaitwait().Experimental_SandboxProcess(re-exported fromprovider-utilsandai).VercelSandbox,LocalSandbox,JustBashSandbox, and the e2e Vercel sandbox) implement realspawnCommand.LocalSandboxswitches frompromisify(exec)tochild_process.spawn.JustBashSandboxswitches from wrappingBashto wrappingjust-bash'sSandbox(which supportsdetached: true); the three example callers are updated toawait Sandbox.create(...).This is being ported over from the much larger experimental PR #15496, as a reasonable immediate win for the sandbox abstraction.
Manual Verification
Rerun the examples to verify.
Checklist
pnpm changesetin the project root)