Skip to content

feat(provider-utils): add spawnCommand method to Experimental_Sandbox to allow for detached command execution#15551

Merged
felixarntz merged 7 commits into
mainfrom
fa/sandbox-spawn-command
May 26, 2026
Merged

feat(provider-utils): add spawnCommand method to Experimental_Sandbox to allow for detached command execution#15551
felixarntz merged 7 commits into
mainfrom
fa/sandbox-spawn-command

Conversation

@felixarntz
Copy link
Copy Markdown
Collaborator

Background

Experimental_Sandbox only exposed runCommand, 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, which runCommand cannot 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 spawnCommand as a new primitive on Experimental_Sandbox, returning a process handle (Experimental_SandboxProcess) that streams stdout/stderr and exposes wait() / kill(). runCommand is now conceptually a thin wrapper: spawn → drain both streams → await wait().

  • New type Experimental_SandboxProcess (re-exported from provider-utils and ai).
  • Example sandbox implementations (VercelSandbox, LocalSandbox, JustBashSandbox, and the e2e Vercel sandbox) implement real spawnCommand. LocalSandbox switches from promisify(exec) to child_process.spawn. JustBashSandbox switches from wrapping Bash to wrapping just-bash's Sandbox (which supports detached: true); the three example callers are updated to await 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

  • All commits are signed (PRs with unsigned commits cannot be merged)
  • Tests have been added / updated (for bug fixes / features)
  • Documentation has been added / updated (for bug fixes / features)
  • A patch changeset for relevant packages has been added (for bug fixes / features - run pnpm changeset in the project root)
  • I have reviewed this pull request (self-review)

stderr: new ReadableStream<Uint8Array>({ start: c => c.close() }),
wait: async () => ({ exitCode: 0 }),
kill: async () => {},
}),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

having mock-sandbox in provider utils might avoid having these changes

* `runCommand` is conceptually a thin wrapper over this primitive: spawn,
* collect both streams to strings, await `wait()`, return the result.
*/
readonly spawnCommand: (options: {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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)

workingDirectory?: string;
abortSignal?: AbortSignal;
}) {
const proc = await this.spawnCommand({
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

process

/**
* Resolve when the process exits, yielding its exit code.
*/
wait(): PromiseLike<{ exitCode: number }>;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

waitForExit ? (wait might be fine)

@felixarntz
Copy link
Copy Markdown
Collaborator Author

@lgrammel renamed runCommand and spawnCommand to just run and spawn, as discussed.

@felixarntz felixarntz merged commit 6c93e36 into main May 26, 2026
48 checks passed
@felixarntz felixarntz deleted the fa/sandbox-spawn-command branch May 26, 2026 17:04
@github-actions
Copy link
Copy Markdown
Contributor

🚀 Published in:

Package Version
ai 7.0.0-canary.153 github npm
@ai-sdk/alibaba 2.0.0-canary.55 github npm
@ai-sdk/amazon-bedrock 5.0.0-canary.70 github npm
@ai-sdk/angular 3.0.0-canary.153 github npm
@ai-sdk/anthropic 4.0.0-canary.60 github npm
@ai-sdk/anthropic-aws 1.0.0-canary.1 github npm
@ai-sdk/assemblyai 3.0.0-canary.46 github npm
@ai-sdk/azure 4.0.0-canary.64 github npm
@ai-sdk/baseten 2.0.0-canary.52 github npm
@ai-sdk/black-forest-labs 2.0.0-canary.46 github npm
@ai-sdk/bytedance 2.0.0-canary.46 github npm
@ai-sdk/cerebras 3.0.0-canary.52 github npm
@ai-sdk/cohere 4.0.0-canary.48 github npm
@ai-sdk/deepgram 3.0.0-canary.45 github npm
@ai-sdk/deepinfra 3.0.0-canary.52 github npm
@ai-sdk/deepseek 3.0.0-canary.49 github npm
@ai-sdk/elevenlabs 3.0.0-canary.45 github npm
@ai-sdk/fal 3.0.0-canary.45 github npm
@ai-sdk/fireworks 3.0.0-canary.52 github npm
@ai-sdk/gateway 4.0.0-canary.92 github npm
@ai-sdk/gladia 3.0.0-canary.45 github npm
@ai-sdk/google 4.0.0-canary.73 github npm
@ai-sdk/google-vertex 5.0.0-canary.95 github npm
@ai-sdk/groq 4.0.0-canary.48 github npm
@ai-sdk/huggingface 2.0.0-canary.52 github npm
@ai-sdk/hume 3.0.0-canary.45 github npm
@ai-sdk/klingai 4.0.0-canary.46 github npm
@ai-sdk/langchain 3.0.0-canary.153 github npm
@ai-sdk/llamaindex 3.0.0-canary.153 github npm
@ai-sdk/lmnt 3.0.0-canary.45 github npm
@ai-sdk/luma 3.0.0-canary.45 github npm
@ai-sdk/mcp 2.0.0-canary.54 github npm
@ai-sdk/mistral 4.0.0-canary.50 github npm
@ai-sdk/moonshotai 3.0.0-canary.52 github npm
@ai-sdk/open-responses 2.0.0-canary.48 github npm
@ai-sdk/openai 4.0.0-canary.64 github npm
@ai-sdk/openai-compatible 3.0.0-canary.52 github npm
@ai-sdk/otel 1.0.0-canary.99 github npm
@ai-sdk/perplexity 4.0.0-canary.48 github npm
@ai-sdk/prodia 2.0.0-canary.48 github npm
@ai-sdk/provider-utils 5.0.0-canary.44 github npm
@ai-sdk/quiverai 2.0.0-canary.1 github npm
@ai-sdk/react 4.0.0-canary.155 github npm
@ai-sdk/replicate 3.0.0-canary.46 github npm
@ai-sdk/revai 3.0.0-canary.46 github npm
@ai-sdk/rsc 3.0.0-canary.154 github npm
@ai-sdk/svelte 5.0.0-canary.153 github npm
@ai-sdk/togetherai 3.0.0-canary.52 github npm
@ai-sdk/valibot 3.0.0-canary.44 github npm
@ai-sdk/vercel 3.0.0-canary.52 github npm
@ai-sdk/voyage 2.0.0-canary.19 github npm
@ai-sdk/vue 4.0.0-canary.153 github npm
@ai-sdk/workflow 1.0.0-canary.70 github npm
@ai-sdk/xai 4.0.0-canary.68 github npm

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.

3 participants