跳到主要内容
非官方简体中文翻译,内容版权归 Mastra 所有,遵循 Apache-2.0 许可。

SandboxProcessManager

Added in: @mastra/core@1.7.0

Abstract base class for managing background processes in sandboxes. Provides methods to spawn processes, list them, get handles by PID, and kill them.

BlaxelSandbox, DaytonaSandbox, E2BSandbox, ModalSandbox, and LocalSandbox all include built-in process managers. You don't need to instantiate this class directly unless you're building a custom sandbox provider.

Usage example
Usage example的直接链接

Access the process manager through the sandbox's processes property:

src/mastra/index.ts
import { LocalSandbox } from '@mastra/core/workspace'

const sandbox = new LocalSandbox({ workingDirectory: './workspace' })
await sandbox.start()

// Spawn a background process
const handle = await sandbox.processes.spawn('node server.js', {
env: { PORT: '3000' },
onStdout: data => console.log(data),
})

// List all tracked processes
const procs = await sandbox.processes.list()

// Get a handle by PID
const proc = await sandbox.processes.get(handle.pid)

// Kill a process
await sandbox.processes.kill(handle.pid)

Methods
Methods的直接链接

spawn(command, options?)
spawncommand-options的直接链接

Spawn a background process. Returns a ProcessHandle immediately without waiting for the process to finish.

const handle = await sandbox.processes.spawn('npm run dev', {
cwd: '/app',
env: { NODE_ENV: 'development' },
onStdout: data => console.log(data),
})

Parameters:

command:

string
The command to run. Interpreted by the shell.

options?:

SpawnProcessOptions
Optional settings for the spawned process.
SpawnProcessOptions

timeout?:

number
Timeout in milliseconds. Kills the process if exceeded.

env?:

NodeJS.ProcessEnv
Environment variables for the process.

cwd?:

string
Working directory for the process. Defaults to the sandbox's configured workingDirectory, then the provider default.

onStdout?:

(data: string) => void
Callback for stdout chunks. Called as data arrives.

onStderr?:

(data: string) => void
Callback for stderr chunks. Called as data arrives.

abortSignal?:

AbortSignal
Signal to abort the process. When aborted, the process is killed.

stdinMode?:

'pipe' | 'ignore'
How stdin is wired. 'pipe' (default) opens a writable stdin for sendStdin() and writer. 'ignore' closes stdin so commands that read it see immediate EOF. Honored by the local, Docker, and E2B providers.

Returns: Promise<ProcessHandle>

list()
list的直接链接

List all tracked processes. Returns info about each process including PID, running state, and exit code.

const procs = await sandbox.processes.list()
for (const proc of procs) {
console.log(proc.pid, proc.running, proc.exitCode)
}

Returns: Promise<ProcessInfo[]>

get(pid)
getpid的直接链接

Get a handle to a process by PID. Returns undefined if the process isn't found or has already been dismissed.

const handle = await sandbox.processes.get(1234)
if (handle) {
console.log(handle.stdout)
await handle.kill()
}

Returns: Promise<ProcessHandle | undefined>

kill(pid)
killpid的直接链接

Kill a process by PID. Waits for the process to terminate before returning. Returns true if the process was killed, false if it wasn't found.

const killed = await sandbox.processes.kill(handle.pid)

Returns: Promise<boolean>

ProcessInfo
processinfo的直接链接

Information about a tracked process, returned by list().

pid:

string
Process ID.

command?:

string
The command that was executed.

running:

boolean
Whether the process is still running.

exitCode?:

number
Exit code if the process has finished.

ProcessHandle
processhandle的直接链接

Handle to a spawned background process. Provides methods to read output, send or close stdin, wait for completion, and kill the process.

You don't create ProcessHandle instances directly. They're returned by spawn() and get().

Usage example
Usage example的直接链接

const handle = await sandbox.processes.spawn('npm run dev', {
onStdout: data => console.log(data),
})

// Read accumulated output
console.log(handle.pid)
console.log(handle.stdout)
console.log(handle.stderr)
console.log(handle.exitCode) // undefined while running

// Wait for completion
const result = await handle.wait()

// Send stdin and signal EOF
await handle.sendStdin('input data\n')
await handle.closeStdin()

// Kill the process
await handle.kill()

Properties
Properties的直接链接

pid:

string
Process ID.

stdout:

string
Accumulated stdout output so far.

stderr:

string
Accumulated stderr output so far.

exitCode:

number | undefined
Exit code. undefined while the process is still running.

command:

string | undefined
The command that was spawned. Set automatically by the process manager.

reader:

Readable
Readable stream of stdout. Useful for protocols like LSP or JSON-RPC that communicate over stdio.

writer:

Writable
Writable stream to stdin. Ending the stream calls closeStdin(). Useful for protocols like LSP or JSON-RPC that communicate over stdio.

Methods
Methods的直接链接

wait(options?)
waitoptions的直接链接

Wait for the process to exit and return the result. Optionally pass onStdout/onStderr callbacks to stream output while waiting. Callbacks are automatically removed when wait() resolves.

// Simple wait
const result = await handle.wait()
console.log(result.success, result.exitCode, result.stdout)

// Wait with streaming
const result = await handle.wait({
onStdout: data => process.stdout.write(data),
onStderr: data => process.stderr.write(data),
})

Parameters:

options?:

WaitOptions
Optional settings for waiting.
WaitOptions

onStdout?:

(data: string) => void
Callback for stdout chunks while waiting.

onStderr?:

(data: string) => void
Callback for stderr chunks while waiting.

Returns: Promise<CommandResult>

The CommandResult object contains:

success:

boolean
true if exit code is 0.

exitCode:

number
Numeric exit code.

stdout:

string
Full stdout output.

stderr:

string
Full stderr output.

executionTimeMs:

number
Execution time in milliseconds.

timedOut?:

boolean
true if the process was killed due to timeout.

killed?:

boolean
true if the process was killed by a signal.

kill()
kill的直接链接

Kill the process. Returns true if the process was killed, false if it had already exited.

const killed = await handle.kill()

Returns: Promise<boolean>

sendStdin(data)
sendstdindata的直接链接

Send data to the process's stdin. Throws if the process has already exited or stdin isn't available.

await handle.sendStdin('console.log("hello")\n')

Returns: Promise<void>

closeStdin()
closestdin的直接链接

Close the process's stdin to signal end-of-file (EOF). Use this after sending all input to commands that read until stdin closes. An exited process or an unavailable stdin causes a throw. Providers without a stdin close primitive throw UnsupportedStdinCloseError.

const handle = await sandbox.processes.spawn('cat')
await handle.sendStdin('input data\n')
await handle.closeStdin()
const result = await handle.wait()

Calling handle.writer.end() also closes stdin. On providers without stdin close support, writer.end() finishes the stream without an error.

Returns: Promise<void>

Stream interop
Stream interop的直接链接

ProcessHandle exposes reader and writer properties for integration with Node.js stream-based protocols like LSP or JSON-RPC:

import {
createMessageConnection,
StreamMessageReader,
StreamMessageWriter,
} from 'vscode-jsonrpc/node'

const handle = await sandbox.processes.spawn('typescript-language-server --stdio')

const connection = createMessageConnection(
new StreamMessageReader(handle.reader),
new StreamMessageWriter(handle.writer),
)
connection.listen()

Building a custom process manager
Building a custom process manager的直接链接

To build a process manager for a custom sandbox provider, extend SandboxProcessManager and implement spawn() and list(). The base class automatically wraps your methods with ensureRunning() so the sandbox starts before any process operation.

import { SandboxProcessManager, ProcessHandle } from '@mastra/core/workspace'
import type { ProcessInfo, SpawnProcessOptions } from '@mastra/core/workspace'

class MyProcessManager extends SandboxProcessManager<MySandbox> {
async spawn(command: string, options: SpawnProcessOptions = {}): Promise<ProcessHandle> {
// Your spawn implementation
const handle = new MyProcessHandle(/* ... */)
this._tracked.set(handle.pid, handle)
return handle
}

async list(): Promise<ProcessInfo[]> {
return Array.from(this._tracked.values()).map(handle => ({
pid: handle.pid,
running: handle.exitCode === undefined,
exitCode: handle.exitCode,
}))
}
}

Pass the process manager to your sandbox via the processes option in MastraSandbox:

class MySandbox extends MastraSandbox {
constructor() {
super({
name: 'MySandbox',
processes: new MyProcessManager(),
})
}
}

When a process manager is provided, MastraSandbox automatically creates a default executeCommand implementation that uses spawn() + wait(), so you don't need to implement both.