import { type ToolManager } from "./tool-manager.js";
/** Container home directory for the Docker sandbox (node:20-slim, USER node) */
export declare const CONTAINER_HOME = "/home/node";
/** Container-side agent directory prefix (always forward slashes) */
export declare const CONTAINER_AGENT_DIR = "/home/node/.bobbit/agent/";
export interface RpcBridgeOptions {
    /** Path to pi-coding-agent cli.js. Auto-resolved if omitted. */
    cliPath?: string;
    /** Working directory for the agent process */
    cwd?: string;
    /** Additional CLI arguments */
    args?: string[];
    /** Path to a custom system prompt file. When set, passed as --system-prompt to the agent. */
    systemPromptPath?: string;
    /** Extra environment variables */
    env?: Record<string, string>;
    /** Whether this session runs in a Docker sandbox (affects timeouts). */
    sandboxed?: boolean;
    /** Env vars to inject into the container (API keys, etc.) */
    sandboxCredentials?: Record<string, string>;
    /** Gateway URL for the agent to call back */
    gatewayUrl?: string;
    /** Auth token for the agent */
    gatewayToken?: string;
    /** Container ID to use with docker exec (from sandbox pool) */
    containerId?: string;
    /** Tool manager for resolving extension paths (optional — falls back to TOOLS_DIR). */
    toolManager?: ToolManager;
    /**
     * Pin the agent's model at spawn time via `--model <provider>/<modelId>`.
     * Avoids the redundant initial `model_change` event that pi-coding-agent
     * emits when booting with its hardcoded default before Bobbit calls
     * `setModel`. Silently ignored if malformed.
     */
    initialModel?: string;
    /**
     * Pin the agent's thinking level at spawn time via `--thinking <level>`.
     * Valid: off|minimal|low|medium|high. Silently ignored otherwise.
     */
    initialThinkingLevel?: string;
}
export type RpcEventListener = (event: any) => void;
/**
 * Lightweight bridge to a pi-coding-agent running in RPC mode.
 * Communicates via JSONL (one JSON object per line) over stdin/stdout.
 *
 * Test harnesses can register an alternative factory via
 * `RpcBridge.registerFactory(fn)` to route specific options (e.g. the E2E
 * in-process mock) to a custom implementation that matches the public
 * interface (`IRpcBridge`). The production code is unchanged: it still
 * calls `new RpcBridge(opts)` and the factory intercepts transparently.
 */
export interface IRpcBridge {
    start(): Promise<void>;
    stop(): Promise<void>;
    prompt(text: string, images?: Array<{
        type: "image";
        data: string;
        mimeType: string;
    }>): Promise<any>;
    steer(text: string): Promise<any>;
    abort(): Promise<any>;
    getState(): Promise<any>;
    getMessages(): Promise<any>;
    setModel(provider: string, modelId: string): Promise<any>;
    setThinkingLevel(level: string): Promise<any>;
    compact(timeoutMs?: number): Promise<any>;
    waitForReady(overallTimeoutMs?: number): Promise<void>;
    sendCommand(command: Record<string, any>, timeoutMs?: number): Promise<any>;
    onEvent(listener: RpcEventListener): () => void;
    readonly running: boolean;
}
export type RpcBridgeFactory = (options: RpcBridgeOptions) => IRpcBridge | null;
/**
 * Register an alternative bridge factory. Called by test harnesses to
 * route mock sessions to an in-process implementation. Return `null` from
 * the factory to fall through to the default child-process RpcBridge.
 */
export declare function registerRpcBridgeFactory(factory: RpcBridgeFactory | null): void;
/**
 * Build the pi-coding-agent CLI arg list from RpcBridgeOptions.
 *
 * Exported for unit testing (mocking child_process.spawn is brittle).
 * Order matters: --model and --thinking are inserted BEFORE caller-supplied
 * `options.args` so any explicit override in `args` (e.g. `--model x` from
 * a custom flow) wins over the spawn-time pin.
 */
export declare function buildAgentArgs(options: RpcBridgeOptions): string[];
export declare class RpcBridge {
    private options;
    private process;
    private requestId;
    private pending;
    private eventListeners;
    private lineBuffer;
    /** Persistent UTF-8 decoders so a multibyte char split across two stdout/
     *  stderr reads is reassembled instead of corrupted into U+FFFD (S14 — the
     *  agent's own stdin reader uses StringDecoder; we mirror it here). A per-
     *  chunk `chunk.toString("utf-8")` would mojibake long CJK/emoji output. */
    private stdoutDecoder;
    private stderrDecoder;
    /** Ring buffer of last stderr lines — included in exit error messages for diagnostics. */
    private stderrTail;
    constructor(options?: RpcBridgeOptions);
    start(): Promise<void>;
    /**
     * Spawn the child process (docker exec or direct node).
     * Factored out of start() so retry logic can re-attempt.
     */
    private _spawnProcess;
    /**
     * Attach stdout/stderr/stdin/error/exit handlers to this.process.
     * Factored out of start() so retry logic can re-attach after re-spawn.
     */
    private _attachProcessHandlers;
    /** Subscribe to agent events. Returns unsubscribe function. */
    onEvent(listener: RpcEventListener): () => void;
    /** Send an RPC command and wait for its response. */
    sendCommand(command: Record<string, any>, timeoutMs?: number): Promise<any>;
    prompt(text: string, images?: Array<{
        type: "image";
        data: string;
        mimeType: string;
    }>): Promise<any>;
    steer(text: string): Promise<any>;
    abort(): Promise<any>;
    getState(): Promise<any>;
    /**
     * Wait for the agent process to become responsive.
     * Sends get_state pings with short timeouts until one succeeds.
     * Used after spawning Docker containers where initialization can take 30-60s.
     */
    waitForReady(overallTimeoutMs?: number): Promise<void>;
    setModel(provider: string, modelId: string): Promise<any>;
    setThinkingLevel(level: string): Promise<any>;
    compact(timeoutMs?: number): Promise<any>;
    getMessages(): Promise<any>;
    stop(): Promise<void>;
    get running(): boolean;
    /**
     * Spawn an agent process inside an already-running pool container via docker exec.
     * The container already has all bind mounts and env vars configured.
     */
    private spawnDockerExec;
    /**
     * Remap agent CLI args from host paths to container paths.
     * All sandbox sessions use pool containers with session-prompts/ mounted.
     */
    private remapArgsForContainer;
    private handleData;
}
/**
 * Convert a Windows path (e.g. C:\foo\bar) to Docker-compatible POSIX path (/c/foo/bar).
 * On non-Windows platforms, returns the path unchanged.
 */
export declare function toDockerPath(p: string): string;
/**
 * Translate a container-internal path back to its host-side equivalent.
 * Uses the known bind-mount mappings from docker-args.ts.
 *
 * Returns the original path unchanged if it doesn't match any known mount.
 * On Windows, the returned path uses OS-native separators.
 */
export declare function containerPathToHost(containerPath: string): string;
/**
 * Translate a host-side path to its container-internal equivalent.
 * Inverse of containerPathToHost().
 *
 * Returns the original path unchanged if it doesn't match any known mount.
 */
export declare function hostPathToContainer(hostPath: string): string;
/**
 * Resolve the parent directory of @earendil-works/pi-coding-agent package.
 * This is the directory that will be mounted as /node_modules in Docker,
 * so that /node_modules/@earendil-works/pi-coding-agent/dist/cli.js works.
 */
export declare function resolveAgentModulesDir(): string;
//# sourceMappingURL=rpc-bridge.d.ts.map