/**
 * ACP Protocol Adapter — a thin wrapper over the official @agentclientprotocol/sdk
 * `ClientSideConnection`. qlogicagent is the ACP *client* (host); spawned external
 * agents (codex-acp, claude-agent-acp, openclaw, …) are the ACP *agents*.
 *
 * The SDK owns the wire protocol entirely: JSON-RPC 2.0 / NDJSON framing, request↔response
 * correlation, and the reverse-RPC dispatch. This module owns only the three concerns the SDK
 * leaves to the host:
 *   1. bridging a Node ChildProcess's stdio to the SDK's web-stream transport (ndJsonStream)
 *   2. mapping our loose `AcpHostRequestHandler` onto the typed SDK `Client` interface
 *   3. translating SDK `session/update` notifications into qlogicagent's internal `turn.*` methods
 *
 * Extension capabilities (clientCapabilities.qlogicagent) are forwarded verbatim — the SDK does
 * not strip outgoing params (validation runs only on the receiving side), so openclaw interop is
 * preserved.
 */
import type { ChildProcess } from "node:child_process";
import type { AcpInitializeResult, AcpSessionResult, AcpPromptResponse, McpServerConfig } from "../../protocol/wire/acp-agent-management.js";
/**
 * Handler for agent→host requests (fs, terminal, permission, elicitation).
 * Host implementations should implement the methods they support. This is intentionally loose
 * (Record-typed) — {@link AcpProtocolAdapter} bridges it onto the SDK's strongly-typed Client.
 */
export interface AcpHostRequestHandler {
    /** Read a text file from the host filesystem. */
    readTextFile?(params: {
        path: string;
    }): Promise<{
        content: string;
    } | undefined>;
    /** Write a text file on the host filesystem. */
    writeTextFile?(params: {
        path: string;
        content: string;
    }): Promise<Record<string, unknown> | undefined>;
    /** Request permission for a tool call. Returns the chosen option id (host responsibility). */
    requestPermission?(params: Record<string, unknown>): Promise<{
        optionId: string;
    }>;
    /** Elicitation request (ask user for input). */
    elicitation?(params: Record<string, unknown>): Promise<Record<string, unknown>>;
    /** Create a terminal session. */
    createTerminal?(params: Record<string, unknown>): Promise<Record<string, unknown> | undefined>;
    /** Terminal output data. */
    terminalOutput?(params: Record<string, unknown>): Promise<Record<string, unknown> | undefined>;
    /** Release a terminal. */
    releaseTerminal?(params: Record<string, unknown>): Promise<Record<string, unknown>>;
    /** Wait for terminal exit. */
    waitForTerminalExit?(params: Record<string, unknown>): Promise<Record<string, unknown> | undefined>;
    /** Kill a terminal. */
    killTerminal?(params: Record<string, unknown>): Promise<Record<string, unknown>>;
    /** Extension method (unknown method from agent). */
    extMethod?(method: string, params: unknown): Promise<unknown>;
}
/** Internal representation of an ACP notification translated to qlogicagent format. */
export interface TranslatedNotification {
    method: string;
    params: Record<string, unknown>;
}
/** An auth method an agent advertises when it needs the user to log in (subset of ACP shape). */
export interface AcpAuthMethod {
    id?: string;
    name?: string;
    description?: string;
}
/**
 * Thrown when an agent rejects session setup because the user must authenticate first — e.g. kimi
 * returns -32000 "Authentication required" with a `kimi login` authMethod. Carries the agent's
 * advertised authMethods and `retryable = false`, so the spawn layer surfaces it immediately (a
 * missing login never heals by retrying) with an actionable message instead of a generic failure.
 */
export declare class AcpAuthRequiredError extends Error {
    readonly retryable: false;
    readonly authMethods: AcpAuthMethod[];
    constructor(message: string, authMethods: AcpAuthMethod[]);
}
/**
 * Recognise the ACP "authentication required" failure (by code -32000, an authMethods payload, or
 * message text) and convert it to an {@link AcpAuthRequiredError} whose message tells the user how
 * to log in (from the agent's own authMethod description). Returns null for any other error.
 */
export declare function asAuthRequiredError(err: unknown, fallbackAuthMethods?: AcpAuthMethod[]): AcpAuthRequiredError | null;
export declare class AcpProtocolAdapter {
    private conn;
    private child;
    private onNotification;
    private hostHandler;
    /**
     * Attach to a child process's stdio for ACP communication.
     * Constructs the official ClientSideConnection over the child's stdin/stdout. The connection's
     * read loop starts immediately, so incoming notifications + reverse-RPC are live after this call.
     *
     * @param child The spawned ACP agent process
     * @param onNotification Callback for agent notifications (raw method + params; caller translates)
     * @param hostHandler Optional handler for agent→host requests (fs, terminal, permission)
     */
    attach(child: ChildProcess, onNotification?: (method: string, params: unknown) => void, hostHandler?: AcpHostRequestHandler): void;
    /**
     * Build the SDK Client implementation (agent→host reverse-RPC) from our loose host handler.
     * Re-reads this.hostHandler / this.onNotification on each call so detach() takes effect.
     */
    private buildClient;
    /** Detach from the child process. The SDK read loop ends when the child's stdout closes. */
    detach(): void;
    private requireConn;
    /** Race a connection call against a timeout; optionally run a side effect (e.g. cancel) on timeout. */
    private withTimeout;
    /**
     * Perform the ACP initialize handshake. Sends standard clientInfo + clientCapabilities plus the
     * qlogicagent extension capability (forwarded verbatim by the SDK).
     */
    initialize(_child?: ChildProcess): Promise<AcpInitializeResult>;
    /**
     * Create an ACP session (session/new). A non-standard systemPrompt is forwarded under `_meta`
     * (the ACP extension mechanism) so it survives validation on the agent side.
     */
    createSession(_child: ChildProcess, options: {
        cwd: string;
        mcpServers?: McpServerConfig[];
        additionalDirectories?: string[];
        systemPrompt?: string;
    }): Promise<AcpSessionResult>;
    /**
     * Send a prompt to a running ACP session (session/prompt). Content streams back via session/update
     * notifications during execution; the response carries only { stopReason, usage? }. On timeout the
     * turn is cancelled (session/cancel) so the agent stops cleanly.
     */
    sendPrompt(_child: ChildProcess, sessionId: string, content: string, timeoutMs?: number): Promise<AcpPromptResponse>;
    /**
     * Resume an existing ACP session (session/load — replays history via notifications).
     * Only valid when the agent advertised the loadSession capability.
     */
    resumeSession(_child: ChildProcess, sessionId: string, options?: {
        cwd?: string;
        mcpServers?: McpServerConfig[];
    }): Promise<AcpSessionResult>;
    /**
     * Translate an ACP notification into qlogicagent's internal format.
     * Returns null if the notification is not translatable (handled separately).
     *
     * Standard ACP: agent sends "session/update" with params { sessionId, update: { sessionUpdate, … } }.
     * Used by both the external-agent path (this adapter) and the internal/builtin agent path, so it
     * stays a pure static function decoupled from the connection.
     */
    static translateNotification(method: string, params: unknown): TranslatedNotification | null;
}
