import { T as ToolHost } from '../tool-host-BqJRPr_T.js'; import { B as Bridge } from '../types-D_TzdBsK.js'; import '../types-ITRQFAir.js'; /** * A shell/profile an agent can switch a terminal to. Mirrors fancy-term's * `ShellProfile` (kept local so the bridge never imports fancy-term). */ type TerminalShell = { id: string; label: string; icon?: string; }; /** * One terminal the bridge can drive. A Human+ app often hosts **several** * terminals on a screen (a build pane, a server pane, an agent scratch shell); * each is a `TerminalRef` with a stable `id` so an agent can read/write any of * them — not just "its own". Wire the function fields to that terminal's * fancy-term `TerminalHandle`. */ type TerminalRef = { /** Stable id used to address this terminal (`terminal_list` enumerates them). */ id: string; /** Human label, e.g. "Build", "Server". Defaults to the id. */ label?: string; /** True for the focused terminal — the default target when no id is passed. */ active?: boolean; /** Read the visible buffer as text (wire to `TerminalHandle.getBuffer`). */ getBuffer: () => string; /** Write raw data / keystrokes (wire to `TerminalHandle.write`). */ write: (data: string) => void; /** Run a command. Defaults to writing `${command}\r`; override for a real runner. */ runCommand?: (command: string) => void | Promise; /** Clear the viewport (wire to `TerminalHandle.clear`). */ clear?: () => void; /** Current text selection (wire to `TerminalHandle.getSelection`). */ getSelection?: () => string; /** Shells this terminal offers (cmd, PowerShell, …). */ listShells?: () => TerminalShell[]; /** Switch this terminal's active shell by id. */ setShell?: (id: string) => void | Promise; /** This terminal's active shell id. */ getShell?: () => string | undefined; }; /** * Single-terminal adapter (back-compat). A `TerminalRef` without the * `id`/`label`/`active` bookkeeping — pass it as `{ adapter }` and the bridge * treats it as the one (active) terminal. Use `{ terminals }` for multiple. */ type TerminalBridgeAdapter = Omit & { /** fancy-screens screen id (optional) so activity events know which screen the terminal lives in. */ screenId?: string; }; type StagedKind = "write" | "run"; type Staged = { id: string; kind: StagedKind; data: string; terminalId: string; }; type TerminalBridgeOptions = { /** A single terminal (back-compat). Mutually exclusive with `terminals`. */ adapter?: TerminalBridgeAdapter; /** * The live list of terminals on the screen. Use this when the app hosts more * than one terminal so an agent can `terminal_list` then target any of them by * id — i.e. reach into another terminal in the same screen. */ terminals?: () => TerminalRef[]; /** fancy-screens screen id for activity events (defaults to `adapter.screenId`). */ screenId?: string; agent?: { id: string; name?: string; color?: string; }; /** * Trust-but-verify (Human+ contract for inhabited surfaces). When on, * `terminal_write` + `terminal_run` don't execute — they **stage** the command * (returning a pending id) and fire `onPending`. A human confirms via the * returned bridge's `confirm(id)` (wire it to a human-only control). * * **Default: ON.** The terminal is the most dangerous surface (arbitrary shell), * and possession of the relay session token = permission to call every tool, so * it must fail SAFE. Pass `false` only for a fully-trusted, non-shared terminal * where auto-execution is acceptable. A host that leaves this on MUST wire a * human confirm path (`onPending` + `bridge.confirm`), or staged commands never run. */ pendingMode?: boolean; /** Notified when a command is staged (pendingMode) — show it + offer confirm / reject. */ onPending?: (pending: Staged) => void; /** * Expose `terminal_confirm` / `terminal_reject` as agent-callable tools. * **Default: false** — otherwise the *same* agent that staged a command could * confirm it, defeating the human-in-the-loop. Leave off and confirm via the * returned `bridge.confirm(id)` wired to a human control. */ allowAgentConfirm?: boolean; /** * Per-terminal authorization. Return false to hide a terminal id from this * agent entirely (it won't appear in `terminal_list` and can't be targeted). * Use it to scope an agent to its own pane(s); without it, `{ terminals }` * grants the agent full read/write over EVERY terminal in the list. */ canAccess?: (terminalId: string) => boolean; }; type TerminalBridge = Bridge & { /** Execute a staged command by id — wire a host confirm button to this. No-op if not pending. */ confirm: (id: string) => void; /** Drop a staged command by id without executing. */ reject: (id: string) => void; /** Commands currently awaiting confirmation. */ pending: () => Staged[]; }; /** * registerTerminalBridge — MCP access to one **or many** terminal surfaces on a * screen. An agent reads the visible buffer (`terminal_read`), writes input * (`terminal_write`), and runs commands (`terminal_run`) through the host; every * mutation broadcasts an `AgentActivity` event. With `pendingMode`, destructive * actions are staged for human confirmation (`terminal_confirm` / `terminal_reject` * / `terminal_pending`). * * **Multi-terminal:** pass `{ terminals }` (vs a single `{ adapter }`) and every * tool takes an optional `terminal` id; `terminal_list` enumerates them. This is * how an agent **reaches into another terminal in the same screen** rather than * being stuck in one. When a terminal offers shells, the agent can also list * (`terminal_list_shells`) and switch (`terminal_set_shell`) its shell. Tool * prefix `terminal_*`. */ declare function registerTerminalBridge(host: ToolHost, options: TerminalBridgeOptions): TerminalBridge; export { type TerminalBridge, type TerminalBridgeAdapter, type TerminalBridgeOptions, type TerminalRef, type TerminalShell, registerTerminalBridge };