/**
 * Drives pi's `--mode rpc` JSON-RPC protocol over stdio and maps agent
 * events into the daemon's typed UI events (the same set that
 * claude-stream.js / copilot-stream.js / acp.js emit).
 *
 * Lifecycle:
 *   1. Daemon spawns `pi --mode rpc [--model ...]`
 *   2. This module sends `prompt` on stdin
 *   3. pi streams events on stdout (agent_start, message_update, …)
 *   4. We translate them to: status, text_delta, thinking_delta,
 *      tool_use, tool_result, usage
 *   5. On `agent_end` we finish the SSE stream
 *
 * Extension UI requests from pi are auto-resolved (the web UI has no
 * dialog surfaces), and fire-and-forget notifications are silently
 * consumed to keep the protocol clean.
 */
import type { ChildProcess } from 'node:child_process';
type JsonRecord = Record<string, unknown>;
type SendAgentEvent = (channel: string, payload: JsonRecord) => void;
type PiRpcSessionOptions = {
    child: ChildProcess;
    prompt: string;
    cwd?: string;
    model?: string | null;
    send: SendAgentEvent;
    imagePaths?: string[];
    uploadRoot?: string;
};
type PiRpcSession = {
    hasFatalError(): boolean;
    abort(): void;
};
type PiRpcContext = {
    runStartedAt: number;
    sentFirstToken: {
        value: boolean;
    };
};
/**
 * Map a single pi RPC event to zero or more daemon UI events.
 *
 * No I/O or child process interaction; mutates `ctx.sentFirstToken`
 * to track streaming state.
 * `send` callback and `ctx` are provided by the caller.
 *
 * @param {object} raw        - parsed JSON from pi's stdout
 * @param {function} send     - (channel, payload) emitter
 * @param {object} ctx        - session context
 * @param {number} ctx.runStartedAt - Date.now() at session start
 * @param {{ value: boolean }} ctx.sentFirstToken - mutable flag
 * @returns {string|null} 'agent_end' if the agent is done, null otherwise
 */
export declare function mapPiRpcEvent(raw: JsonRecord, send: SendAgentEvent, ctx: PiRpcContext): 'agent_end' | null;
/**
 * Attach a pi RPC session to a spawned child process.
 *
 * Emits `status: initializing` with the model name immediately so the UI
 * can show "pi · claude-sonnet-4-5" like every other adapter. Then sends
 * the prompt via RPC and streams events back.
 *
 * The returned `abort()` method sends an RPC `abort` command so pi can
 * clean up gracefully (flush logs, finalize session files, etc.). The
 * caller (runs.cancel()) owns the SIGTERM fallback — abort() does not
 * kill the child process itself.
 *
 * @param {object} opts
 * @param {import('node:child_process').ChildProcess} opts.child  - spawned pi process
 * @param {string} opts.prompt   - composed user message
 * @param {string} [opts.cwd]    - working directory
 * @param {string|null} [opts.model] - model id (null = default)
 * @param {string[]} [opts.imagePaths] - absolute paths to image files for multimodal input
 * @param {string} [opts.uploadRoot] - root directory that image paths must remain inside after symlink resolution
 * @param {function} opts.send   - SSE send function
 * @returns {{ hasFatalError(): boolean, abort(): void }}
 */
export declare function attachPiRpcSession({ child, prompt, cwd: _cwd, model, send, imagePaths, uploadRoot, }: PiRpcSessionOptions): PiRpcSession;
/**
 * Parse `pi --list-models` tabular output into the model-picker format
 * used by the daemon's /api/agents endpoint.
 *
 * Input lines look like:
 *   provider         model                  context  max-out  thinking  images
 *   anthropic        claude-sonnet-4-5      200K      64K      yes        yes
 *
 * We collapse to `provider/model` ids and prepend the synthetic default.
 */
type PiModelOption = {
    id: string;
    label: string;
};
export declare function parsePiModels(stdout: unknown): PiModelOption[] | null;
export {};
