sandbox-agent/docs/react-components.mdx
Nathan Flurry febe8601f6
feat: add process management support (#207)
* feat: improve inspector UI for processes and fix PTY terminal

- Simplify ProcessRunTab layout: compact form with collapsible Advanced section for timeout/maxOutputBytes
- Rewrite ProcessesTab: collapsible create form, lightweight list items with status dots, clean detail panel with tabs
- Extract error details: use problem.detail instead of generic "Stream Error" title for better error messages
- Fix GhosttyTerminal binary frame parsing: handle server's binary ArrayBuffer control frames (ready/exit/error)
- Enable WebSocket proxying in Vite dev server with ws: true
- Set TERM=xterm-256color default for TTY processes so tools like tmux, vim, htop work out of the box
- Remove orange gradient background from terminal container for cleaner look
- Remove orange left border from selected process list items
- Update inspector CSS with new process/terminal styles

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

* fix: address review issues and add processes documentation

- Fix unstable onExit callback in ProcessesTab (useCallback)
- Fix SSE follow stream race condition (subscribe before history read)
- Update inspector.mdx with new process management features
- Change observability icon to avoid conflict with processes
- Add docs/processes.mdx covering the full process management API

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: simplify processes doc — rename sections, remove low-level protocol

- Rename "Interactive terminals" to "Terminals" with "Connect to a terminal" sub-heading
- Add TTY process creation step at top of Terminals section
- Remove low-level WebSocket protocol table and raw WebSocket example
- Keep browser terminal emulator reference with Ghostty link

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: update GhosttyTerminal permalink to latest commit

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: use main branch permalink for GhosttyTerminal reference

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: refine process API — WebSocket binary protocol, SDK terminal session, updated tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: update GhosttyTerminal permalink to 636eefb

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* inspector: use websocket terminal API

* sdk: restore high-level terminal session

* docs: update inspector terminal permalink

* inspector: update run once placeholder

* Fix lazy install v1 API test fixture

* Add reusable React terminal component

* Fix terminal WebSocket ready state checks

---------

Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-07 17:58:31 -08:00

103 lines
2.6 KiB
Text

---
title: "React Components"
description: "Drop-in React components for Sandbox Agent frontends."
icon: "react"
---
`@sandbox-agent/react` exposes small React components built on top of the `sandbox-agent` SDK.
## Install
```bash
npm install @sandbox-agent/react@0.2.x
```
## Full example
This example connects to a running Sandbox Agent server, starts a tty shell, renders `ProcessTerminal`, and cleans up the process when the component unmounts.
```tsx TerminalPane.tsx expandable highlight={5,32-36,71}
"use client";
import { useEffect, useState } from "react";
import { SandboxAgent } from "sandbox-agent";
import { ProcessTerminal } from "@sandbox-agent/react";
export default function TerminalPane() {
const [client, setClient] = useState<SandboxAgent | null>(null);
const [processId, setProcessId] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
let cancelled = false;
let sdk: SandboxAgent | null = null;
let createdProcessId: string | null = null;
const cleanup = async () => {
if (!sdk || !createdProcessId) {
return;
}
await sdk.killProcess(createdProcessId, { waitMs: 1_000 }).catch(() => {});
await sdk.deleteProcess(createdProcessId).catch(() => {});
};
const start = async () => {
try {
sdk = await SandboxAgent.connect({
baseUrl: "http://127.0.0.1:2468",
});
const process = await sdk.createProcess({
command: "sh",
interactive: true,
tty: true,
});
if (cancelled) {
createdProcessId = process.id;
await cleanup();
await sdk.dispose();
return;
}
createdProcessId = process.id;
setClient(sdk);
setProcessId(process.id);
} catch (err) {
const message = err instanceof Error ? err.message : "Failed to start terminal.";
setError(message);
}
};
void start();
return () => {
cancelled = true;
void cleanup();
void sdk?.dispose();
};
}, []);
if (error) {
return <div>{error}</div>;
}
if (!client || !processId) {
return <div>Starting terminal...</div>;
}
return <ProcessTerminal client={client} processId={processId} height={480} />;
}
```
## Component
`ProcessTerminal` attaches to a running tty process.
- `client`: a `SandboxAgent` client
- `processId`: the process to attach to
- `height`, `style`, `terminalStyle`: optional layout overrides
- `onExit`, `onError`: optional lifecycle callbacks
See [Processes](/processes) for the lower-level terminal APIs.