import type { PairingRegistry } from './pairing-registry.js'; export type RpcError = { code: 'paused' | 'invalid' | 'timeout' | 'schema-error' | 'internal' | string; detail?: string; }; export type RpcOptions = { timeoutMs?: number; }; /** * Send an `rpc` frame to the paired browser and await its * matching `rpc-reply` / `rpc-error`. Runs its own one-shot frame * subscription against the registry — no state stored on the * registry itself, which keeps the registry small enough to * implement in a Durable Object or other stateful primitive. * * Rejects with `{code: 'paused'}` when the pairing is absent, * `{code: 'timeout'}` when the browser doesn't reply in time, * or whatever the browser sent in its `rpc-error` frame otherwise. */ export declare function rpc(registry: PairingRegistry, tid: string, tool: string, args: unknown, opts?: RpcOptions): Promise; /** Three-way result of awaiting a confirmation resolution. */ export type ConfirmWaitResult = { outcome: 'confirmed'; stateAfter?: unknown; } | { outcome: 'user-cancelled'; } | { outcome: 'timeout'; }; /** * Await a `confirm-resolved` frame for the given `confirmId`. Three-way: * - `confirmed` — the user approved (carries `stateAfter`). * - `user-cancelled` — the user explicitly rejected. * - `timeout` — no resolution arrived in `timeoutMs`, or the * pairing dropped before one did. * * Timeout is reported HONESTLY as `timeout` (not as a fake * `user-cancelled`): the confirm is still live in the browser and a * later approval may still fire, so callers must surface * `pending-confirmation` / `still-pending` rather than lie about a * rejection. Pairing drop maps to `timeout` for the same reason — the * user wasn't present to cancel, they simply weren't reachable. * * LEVEL-TRIGGERED. The browser emits `confirm-resolved` exactly once. * `/message` and `/confirm-result` long-poll in series: each tears its * subscriber down on timeout, and the next re-arms a fresh one. If the * user approves in that inter-poll gap, an edge-triggered subscriber * would miss the frame forever (the action ran but the agent polls * `still-pending` indefinitely). To close that gap, the registry buffers * every `confirm-resolved` outcome keyed by `confirmId` with a TTL, and * this helper checks that buffer BEFORE subscribing — returning * immediately when the resolution already arrived. */ export declare function waitForConfirm(registry: PairingRegistry, tid: string, confirmId: string, timeoutMs: number): Promise; /** * Long-poll for a state change under `path` (a JSON pointer; `undefined` * watches the whole state). Used by `/lap/v1/wait` for external state * pushes (WebSocket messages, timers) arriving while the LLM is idle. * * Subscription-driven: the server ARMS a `watch { id, path }` on the * browser, which then emits a `state-update` carrying that `id` only * when the pointer's resolved value actually changes — so an idle * session ships nothing per commit, and a path-scoped wait matches the * right change (the old `/`-broadcast-plus-prefix scheme could never * match a specific path). We correlate strictly by `id`, disarm the * watch (`unwatch`) whichever way the poll settles, and return the full * `stateAfter` snapshot the browser sent. */ export declare function waitForChange(registry: PairingRegistry, tid: string, path: string | undefined, timeoutMs: number): Promise<{ status: 'changed' | 'timeout'; stateAfter: unknown; }>; //# sourceMappingURL=rpc.d.ts.map