Files
oh-my-pi/docs/tools/computer.md
T
2026-07-24 01:40:05 +00:00

227 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# computer
> Capture and control the real host desktop through native OS APIs. This is not the `browser` tool and does not use Chromium, CDP, Puppeteer, DOM, or ARIA surfaces.
User setup, safety guidance, platform permissions, and verified limitations: [Native computer use](../computer-use.md).
## Source
- Entry: `packages/coding-agent/src/tools/computer.ts`
- Model-facing prompt: `packages/coding-agent/src/prompts/tools/computer.md`
- Safety prompt: `packages/coding-agent/src/prompts/system/computer-safety.md`
- Tool registration/gate: `packages/coding-agent/src/tools/index.ts`
- Approval wrapper: `packages/coding-agent/src/extensibility/extensions/wrapper.ts`
- Renderer: `packages/coding-agent/src/tools/computer-renderer.ts`
- Supervisor/protocol: `packages/coding-agent/src/tools/computer/{supervisor,protocol,worker,worker-entry}.ts`
- Native implementation: `crates/pi-natives/src/desktop.rs`
- Portable Linux stub: `crates/pi-natives/src/desktop_unsupported.rs`
- Native loader: `packages/natives/native/loader-state.js`
- Provider types: `packages/ai/src/types.ts`
- OpenAI GA schemas: `packages/ai/src/providers/openai-responses-server-schema.ts`
- OpenAI conversion/replay: `packages/ai/src/providers/openai-shared.ts`, `openai-responses.ts`, `openai-codex-responses.ts`, `azure-openai-responses.ts`
## Availability and declaration
- `computer.enabled` gates registration and defaults to `false`.
- Enabled tool load mode: `essential`.
- Concurrency: `exclusive`.
- Native descriptor: `{ type: "computer" }`.
- Providers serialize the descriptor only when `model.supportsComputerUse === true`.
- Automatic capability derivation covers GA `gpt-5.4+` IDs on OpenAI Responses, OpenAI Codex Responses, and Azure OpenAI Responses; explicit model metadata overrides derivation.
- Unsupported-model history conversion replaces native call/output items with stable assistant text notes.
Unlike `browser`, `computer` operates the entire visible host session. It can act in IDEs, terminals, native applications, browser windows, and system dialogs, but has no structured application/DOM inspection.
## Settings
| Setting | Type | Default | Contract |
|---|---|---:|---|
| `computer.enabled` | boolean | `false` | Register tool. |
| `computer.backend` | `auto \| native` | `auto` | Both prohibit non-native fallback. |
| `computer.display` | string | `all` | `all` or numeric native monitor ID. |
| `computer.maxWidth` | number | `1920` | Maximum composite PNG width; must be positive. |
| `computer.maxHeight` | number | `1200` | Maximum composite PNG height; must be positive. |
Constructor snapshots these settings into one `DesktopSessionOptions`. No setting is reread per call.
## Inputs
Public schema:
```ts
{
actions?: unknown[]
}
```
The schema stays generic because provider-native `computer_call` metadata is authoritative. `execute()` chooses `context.toolCall.providerMetadata.actions` when metadata type is `computer`; otherwise it uses `params.actions`. Missing, empty, or invalid action arrays fail before worker dispatch.
### GA action shapes
| Type | Shape |
|---|---|
| `click` | `{ type, button: "left" \| "right" \| "wheel" \| "back" \| "forward", x, y, keys? }` |
| `double_click` | `{ type, x, y, keys: string[] \| null }` |
| `drag` | `{ type, path: Array<{x,y}>, keys? }`; native minimum two points |
| `keypress` | `{ type, keys: string[] }`; non-empty array and entries |
| `move` | `{ type, x, y, keys? }` |
| `screenshot` | `{ type }` |
| `scroll` | `{ type, x, y, scroll_x, scroll_y, keys? }` |
| `type` | `{ type, text: string }` |
| `wait` | `{ type }`; fixed two-second sleep |
Native validation rejects missing and unexpected fields before emitting input. Coordinate values must map to non-negative `i32` screenshot pixels. Mouse `keys` accept unique modifier keys only. Keypress strings are case-insensitive, accept aliases and `+`-separated chords, and fall back to one Unicode character. `wheel` is the GA middle-button spelling; `middle` is invalid.
Scroll conversion: nonzero provider delta `d` becomes `sign(d) × max(1, floor((abs(d)+50)/100))` native steps.
## Approval
`computerApproval(args)` returns:
- `read`: every action is `screenshot` or `wait`;
- `exec`: any input action, missing actions, or malformed action.
Approval prompts render up to 12 ordered action summaries, truncate each line to 240 characters, and cap the combined details at 2,000 characters.
Provider safety checks come from native call metadata, not parameters. Wrapper precedence:
1. Resolve ordinary mode and `tools.approval.computer` policy.
2. Explicit `deny` blocks immediately.
3. Pending provider checks force interactive approval regardless of `yolo`, `autoApprove`, per-tool `allow`, or xdev approval.
4. No UI fails closed with `Tool "computer" has pending provider safety checks but no interactive UI is available.`
5. Approval sets `context.providerSafetyApproved = true`.
6. Tool execution checks the marker again.
7. Successful output echoes pending checks as acknowledged checks.
The agent's system safety prompt independently treats all UI as untrusted and requires point-of-risk confirmation for consequential actions. Provider approval does not replace direct user authorization.
## Outputs
One successful call returns:
- `content`: one `{ type: "image", mimeType: "image/png", detail: "original", data: <base64> }` block;
- `details.width` / `height`: composite PNG dimensions;
- `details.backend`: `quartz`, `x11`, `wayland`, or `win32`;
- `details.displayServer`: OS display endpoint/subsystem label when known;
- `details.capturePermission` / `inputPermission`: `granted`, `denied`, `unknown`, or `unavailable`;
- `details.displays`: selected display geometry in global logical and screenshot-pixel spaces;
- `details.capabilities`: current native backend/capture/input status;
- `details.actions`: executed action type names;
- `providerMetadata.type`: `computer`;
- `providerMetadata.screenshot`: inline `computer_screenshot.image_url` data URI;
- `providerMetadata.acknowledgedSafetyChecks`: exact approved provider checks.
The renderer merges call and result. Expanded output shows every display; collapsed output shows at most three. Each row includes native ID/name, logical rectangle, PNG pixel rectangle, scale, and primary flag.
OMP native execution never creates a provider Files upload. The provider contract also accepts `{ type: "computer_screenshot", file_id }`; gateway/history parsing preserves that reference in metadata, and capable-model replay emits it unchanged.
## Flow
1. Tool registration checks `computer.enabled`.
2. `ComputerTool` constructs a `ComputerSupervisor` with session settings but does not start a worker.
3. Provider adapter exposes the native declaration only for capable models.
4. Provider `action`/`actions` and pending safety checks become typed tool-call metadata.
5. Extension wrapper resolves tool approval and mandatory provider safety approval.
6. `ComputerTool.execute()` chooses metadata actions, validates the batch, and rechecks safety approval.
7. Supervisor serializes execution behind a promise tail and lazily starts one Bun worker.
8. Worker constructs one native `DesktopSession` and reports capabilities.
9. A first coordinate batch triggers a pre-capture when no frame exists.
10. Native session validates all actions, executes them in order, and captures one fresh final PNG.
11. Worker transfers the PNG buffer to the parent and preserves session/frame state for the next call.
12. Tool returns image content, display/capability details, and exact GA result metadata.
## Capture and coordinate mapping
Native capture enumerates selected monitors, sorts by logical `y/x/id`, coalesces mirrored rectangles, and rejects duplicate IDs, invalid scale/size, and overlapping non-mirrored layouts. Monitor images are captured at native pixels.
The compositor builds the global logical bounding rectangle, then selects one render scale limited by native density and configured width/height. Display gaps remain opaque black. Maximum allocation: 268,435,456 composite pixels.
Every `DesktopDisplay` carries:
```ts
{
id, name,
x, y, width, height, scale, // global logical space
pixelX, pixelY, pixelWidth, pixelHeight, // returned PNG space
isPrimary
}
```
Coordinate mapping finds the containing PNG display rectangle, scales locally to logical width/height, then adds global origin. Negative global origins work. Negative screenshot points, image bounds, and layout-gap points fail closed.
Before each coordinate action, native code re-enumerates displays and compares ID, logical rectangle, and scale against the stored frame. Difference clears the stored frame and returns `DESKTOP_LAYOUT_CHANGED`; caller must capture again.
## Platform variants
| Target | Native surface |
|---|---|
| `darwin-x64`, `darwin-arm64` | Real `DesktopSession` in core addon: xcap/CoreGraphics capture, Quartz `CGEvent` pointer events, native input. Screen Recording preflight; Accessibility required operationally. |
| `linux-x64` glibc | Core addon remains GUI-free. Separate `pi_natives.desktop.linux-x64[-variant].node` is loaded on first `DesktopSession` construction. X11 capture/input or XWayland capture plus portal/libei input. |
| `linux-arm64` | Published core has typed unsupported stub; no packaged desktop leaf. |
| Linux musl | Explicit typed unsupported stub. |
| `win32-x64` | Real `DesktopSession` in core addon: xcap, native input, `SendInput` absolute movement over the virtual desktop. |
| Other targets | Native package loader rejects unsupported platform tag. |
Wayland detection wins when `XDG_SESSION_TYPE=wayland` or `WAYLAND_DISPLAY` is set. Capture still requires `DISPLAY` because xcap 0.9.6 uses XWayland. Linux input first verifies the session bus and `org.freedesktop.portal.Desktop`, then initializes Enigo/libei without asking OMP to open a permission prompt. Coordinate input rejects Wayland frames containing more than one selected display.
macOS capture calls `CGPreflightScreenCaptureAccess()` without prompting. Input creation also disables automatic permission prompts. Windows sets DPI awareness and maps pointer coordinates with `MOUSEEVENTF_VIRTUALDESK`, supporting negative origins and secondary displays.
## Worker and session lifecycle
`ComputerSupervisor`:
- start timeout: 10 seconds;
- close timeout: 1.5 seconds;
- serializes calls even after an earlier call rejects;
- on abort, terminates worker and rejects pending requests;
- owner registry supports bulk close on session/eval-owner teardown.
`ComputerWorkerCore` also serializes inbound messages. It initializes once, holds `#hasFrame`, closes native session once, then unsubscribes and closes transport.
Native `DesktopSession` starts a named `omp-desktop-session` thread. Capture/execute/close requests use a FIFO channel. Operation waits are bounded to one minute; explicit close waits up to two seconds and is idempotent. Destructor sends best-effort close but does not block indefinitely on a stuck worker.
## Side effects
- Captures every selected visible display into model/provider context.
- Emits real user-session keyboard and pointer events.
- Keeps a native worker and desktop session alive across calls.
- May expose visible secrets, notifications, other applications, and system dialogs in screenshots.
- Linux x64 may lazily `dlopen` the separately packaged GUI-linked addon.
- Does not launch a browser, upload to provider Files, persist screenshots as local files, or create arbitrary child processes beyond its dedicated Bun/native workers.
## Errors
Stable native codes:
- `DESKTOP_INVALID_OPTIONS`
- `DESKTOP_INVALID_ACTION`
- `DESKTOP_BACKEND_UNAVAILABLE`
- `DESKTOP_PERMISSION_DENIED`
- `DESKTOP_CAPTURE_FAILED`
- `DESKTOP_INPUT_FAILED`
- `DESKTOP_LAYOUT_CHANGED`
- `DESKTOP_COORDINATE_OUT_OF_BOUNDS`
- `DESKTOP_SESSION_CLOSED`
- `DESKTOP_WORKER_FAILED`
Tool/wrapper errors also include:
- `Computer call requires at least one action`
- `Computer call contains an invalid action`
- `Computer session is closed`
- `Provider safety checks require interactive approval before computer input`
- `Timed out starting native computer worker`
- `Tool "computer" has pending provider safety checks but no interactive UI is available.`
Key platform failures and remedies are listed in [Native computer use: Troubleshooting](../computer-use.md#troubleshooting).
## Limits and proof boundary
- No non-native backend or browser fallback.
- No pure Wayland capture; XWayland required.
- No safe multi-display coordinate input on Wayland.
- Published Linux native desktop addon: x64 glibc only.
- Windows backend implemented but not remotely exercised for this feature.
- Real remote macOS proof used `ComputerSupervisor` → worker → native session on a real macOS host, controlling TextEdit with global hotkey, double-click, click, type, and 1920×1080 Quartz capture after permissions were granted.
- That proof did not include a live OpenAI native provider round trip. GA transport and replay are contract-tested locally.