/**
 * GatewayAgentRunner — webchat agent invocation and the surrounding control
 * surface (abort, steer, clarify-bridge plumbing, scheduled continuations).
 *
 * Was 200 lines of `GatewayService` covering seven concerns that all hung off
 * the same handful of fields (`activeWebchatRunBySession`, `runAbortControllers`,
 * `clarifyBridge`, `runRelay`):
 *
 *   - `runAgent(message, channel, chatId, ...)` — wraps {@link runGatewayAgent}
 *   - `abortAgentRun(runId)` — POST /api/agent/abort + cleanup
 *   - `steerWebchatAgent(chatId, message)` — Agent.steer queue at tool boundary
 *   - `submitClarifyResponse(requestId, answer)` — UI answers a `clarify` call
 *   - `enqueueWebchatPersistentGoalKickoff(sessionKey, goalText)` — initial
 *     `/goal` kickoff posts the goal text as the next user turn
 *   - `drainScheduledWebchatContinuation(sk, msg)` — background continuation
 *     (extension scheduler + persistent-goal flow)
 *   - `clarifyForSession({ sessionKey, request })` — clarify-bridge dispatch
 *     used by `gatewayClarify.requestClarification` in AgentService
 *
 * Owns the two state maps (`activeWebchatRunBySession`, `runAbortControllers`)
 * directly so peer coordinators (sessions-api, marketplace, config) cannot
 * accidentally mutate them.
 */
import type { Config } from '../../config/schema.js';
import type { MessageBus } from '../../infra/bus/index.js';
import type { AgentService } from '../../agent/service.js';
import type { ChannelManager } from '../../channels/manager.js';
import type { SessionIndex } from '../../session/index.js';
import { AgentRunRelay, type RelayEvent } from '../agent-run-relay.js';
import { ClarifyBridge, type ClarifyBridgeRequest } from '../clarify-bridge.js';
export interface GatewayAgentRunnerOptions {
    bus: MessageBus;
    sessionIndex: SessionIndex;
    /** Resolved lazily — the runner is constructed before AgentService exists. */
    getAgentService: () => AgentService;
    getChannelManager: () => ChannelManager;
    getConfig: () => Config;
    /** SSE emit (re-used so `runAgent` events broadcast to subscribers). */
    emit: (type: string, payload: unknown) => void;
}
export declare class GatewayAgentRunner {
    private readonly opts;
    readonly runRelay: AgentRunRelay;
    /** Per-run abort for webchat (POST /api/agent/abort or client disconnect). */
    private readonly runAbortControllers;
    private readonly clarifyBridge;
    /** Maps webchat session key → active `runId` for `clarify` tool routing. */
    private readonly activeWebchatRunBySession;
    constructor(opts: GatewayAgentRunnerOptions);
    /** True when a webchat agent run is currently in-flight for `sessionKey`. */
    hasActiveRun(sessionKey: string): boolean;
    getActiveRunId(sessionKey: string): string | undefined;
    getClarifyBridge(): ClarifyBridge;
    /** Called from `GatewayService.stop()` so the bridge gets cleaned up. */
    disposeClarifyBridge(): void;
    runAgent(message: string, channel: string, chatId: string, attachments?: Array<{
        type: string;
        mimeType?: string;
        data?: string;
        name?: string;
        size?: number;
    }>, thinking?: string, runOptions?: {
        signal?: AbortSignal;
        clientCreatedAtMs?: number;
    }): AsyncGenerator<{
        type: string;
        content?: string;
        status?: string;
        runId?: string;
    }, {
        status: string;
        summary: string;
    }, unknown>;
    /** Abort an in-flight webchat agent run (matches `runId` from SSE `status`). */
    abortAgentRun(runId: string): boolean;
    /**
     * Queue steering text for an active webchat run (`Agent.steer` /
     * tool-boundary injection). `chatId` is the same as `POST /api/agent` body
     * (`sessionKey` or legacy peer id).
     */
    steerWebchatAgent(chatId: string, message: string): Promise<{
        ok: true;
    } | {
        ok: false;
        code: 'BAD_REQUEST' | 'NO_ACTIVE_RUN' | 'STEER_FAILED';
    }>;
    /** Deliver a user's answer to a pending `clarify` tool call. */
    submitClarifyResponse(requestId: string, answer: string): boolean;
    /** Hermes-style: after HTTP sets a goal, enqueue the goal text as the next user turn. */
    enqueueWebchatPersistentGoalKickoff(sessionKey: string, goalText: string): void;
    /** Background drain for extension-initiated webchat turns (`scheduleWebchatContinuation`). */
    drainScheduledWebchatContinuation(sessionKey: string, message: string): Promise<void>;
    /**
     * Resolve clarify-bridge config for `sessionKey`: who delivers the question
     * (webchat SSE, Telegram message, or both), then start the bridge request.
     * Rejects when neither path is available (e.g. CLI without webchat or TG).
     *
     * `publishSseFor(runId)` is the bridge into AgentService's
     * `turnDispatcher.enqueueWebchatSseEvent`. We take it as a callback so the
     * runner does not import AgentService statically.
     */
    requestClarification(opts: {
        sessionKey: string;
        request: ClarifyBridgeRequest;
        publishSseFor: (runId: string) => (e: RelayEvent) => void;
    }): Promise<string>;
    private deliverTelegramClarify;
}
