import type { Driver, DriverEvent } from './driver/index.js';
import { type FrameworkEvent } from './events.js';
/** Inputs to {@link emitSessionStart}. */
export interface SessionStartOptions {
    emit: (event: FrameworkEvent) => void;
    driver: Driver;
    /** The workspace the agent works in. */
    cwd: string;
    /** The session link, literal or templated with `{sessionId}`. */
    sessionLink?: string | undefined;
    /** The model id the driver was started with (#1438), recorded on the event per leg. */
    model?: string | undefined;
}
/**
 * Emit the agent's opening `session` event. A literal link is shown right away; a
 * templated one (`.../{sessionId}`) can only resolve once the driver reports its
 * session id, so it waits for the `session-update` from {@link createDriverEventHandler}.
 */
export declare function emitSessionStart(opts: SessionStartOptions): void;
/** Inputs to {@link createDriverEventHandler}. */
export interface DriverEventHandlerOptions {
    emit: (event: FrameworkEvent) => void;
    /** The session link template, when the caller configured one. */
    sessionLink?: string | undefined;
}
/** What {@link createDriverEventHandler} hands back. */
export interface DriverEventHandler {
    /** Wire this as the driver session's `onEvent`. */
    onDriverEvent: (event: DriverEvent) => void;
}
/**
 * Watch the driver's black box (#165) and turn it into the agent's stream: surface the real session
 * id as `session-update` once known (that is the honest handle a UI links to, and it changes per
 * prompt, so re-emit), and fold each turn's usage into the agent total.
 *
 * It used to trip two self-stops here as well — a per-agent USD cap and a mid-run quota gate — each
 * firing *after* the turn that crossed it, when its cost was already spent (E1).
 */
export declare function createDriverEventHandler(opts: DriverEventHandlerOptions): DriverEventHandler;
/** Inputs to {@link createAgentControls}. */
export interface AgentControlsOptions {
    emit: (event: FrameworkEvent) => void;
    /** The caller's abort signal (Stop button / Ctrl+C / control channel), if any. */
    signal?: AbortSignal | undefined;
    sessionLink?: string | undefined;
}
/** The agent's abort plumbing plus its driver-event sink. */
export interface AgentControls extends DriverEventHandler {
    /** The composed signal every driver turn runs under: the caller's, or the answer's. */
    agentSignal: AbortSignal;
    /** Trips a clean stop when the user answers a gate with a `stop` option (#358). */
    answerController: AbortController;
}
/**
 * Compose the agent's signal and wire its driver-event handler in one place. The caller's signal is
 * OR'd (via {@link AbortSignal.any}) with the one self-stop left — an answer that says to stop
 * (#358) — so anything downstream that watches `agentSignal` stops the same way regardless of which
 * fired.
 *
 * There were three (E1). A per-agent USD cap and a mid-run quota gate also aborted a session that
 * was already going, which is the worst moment to economise: the tokens are already spent, the
 * work is half-done, and what is saved is the cheap part while what is lost is the expensive part.
 * Spending is decided once, before a session starts.
 *
 * What survives is the one a *person* asked for. It used to be reached through the gate's kind —
 * a decline of an `await-confirmation` — and now through the option the agent marked, which is
 * the same stop with the plan-approval special case taken out of it (D6).
 */
export declare function createAgentControls(opts: AgentControlsOptions): AgentControls;
/** Inputs to {@link endStopDetail}. */
export interface StopDetailOptions {
    /** The error the agent's turn loop threw. */
    err: unknown;
    /** The caller's own signal, to tell a caller stop from a self-stop. */
    signal?: AbortSignal | undefined;
    /** The gate-answer stop (#358), which is a stop rather than a failure however it surfaced. */
    answerController: AbortController;
}
/**
 * Classify why an agent's turn loop threw and render the `end` event's `detail`. A caller interrupt
 * or an answer that said to stop (#358) are clean stops; anything else is a real failure. Shared
 * so the two agent paths can never disagree on what "stopped" means.
 */
export declare function endStopDetail(opts: StopDetailOptions): {
    stopped: boolean;
    detail: string;
};
//# sourceMappingURL=agent-telemetry.d.ts.map