import { type LlmRole } from './llm/registry.js';
export type BackendKind = 'agent' | 'llm' | 'backend';
export interface BackendRef {
    kind: BackendKind;
    /** For kind='agent' this is the AgentAdapter name; for kind='llm' a
     *  role; for kind='backend' a backend name from llmBackends. */
    name: string;
}
export interface CompareInput {
    prompt: string;
    systemPrompt?: string;
    a: BackendRef;
    b: BackendRef;
    /** When set + the role has a configured backend, ask the judge to
     *  pick a winner. Common choices: 'evaluator' or 'cheap'. */
    judgeRole?: LlmRole;
    /** Per-side wall-clock cap (overrides default 60s). */
    perSideTimeoutMs?: number;
    /** Per-side output character cap (default 4 000). */
    maxOutputChars?: number;
    /** Optional IM context for agent-kind sides. callHelperAgent needs
     *  platform/channel/thread to resolve sticky sessions; without them
     *  it picks the first registered agent. Defaults are fine for CLI
     *  use; slash-command callers should pass through their context. */
    platform?: string;
    channelId?: string;
    threadId?: string;
}
export interface SideResult {
    ref: BackendRef;
    ok: boolean;
    /** Output text (truncated to maxOutputChars; empty when ok=false). */
    text: string;
    /** Wall-clock latency in ms. Populated even on failure. */
    durationMs: number;
    /** Best-effort token counts. Native LLM sides have full numbers;
     *  CLI / native AgentAdapter sides only have what their adapter
     *  surfaces — usually null. */
    tokensIn?: number;
    tokensOut?: number;
    /** Human-readable error message when ok=false. */
    error?: string;
}
export interface JudgeVerdict {
    /** 'a' | 'b' | 'tie'. 'inconclusive' when the judge didn't return a
     *  parseable answer. */
    pick: 'a' | 'b' | 'tie' | 'inconclusive';
    /** Short rationale from the judge (≤ 200 chars). */
    reason: string;
    backendName: string;
    durationMs: number;
    tokensIn?: number;
    tokensOut?: number;
}
export interface CompareResult {
    a: SideResult;
    b: SideResult;
    judge?: JudgeVerdict;
    /** Echoed back so callers can log the exact request shape. */
    input: CompareInput;
}
/**
 * Run the comparison. Never throws — every failure mode lands in the
 * SideResult.ok=false branch with a populated `error` field.
 */
export declare function runRouterCompare(input: CompareInput): Promise<CompareResult>;
/** Parse "agent:claude-code" / "llm:cheap" / "backend:deepseek-chat"
 *  into a typed BackendRef. Returns null when the spec is malformed —
 *  caller should surface a user-facing error. */
export declare function parseBackendRef(spec: string): BackendRef | null;
/**
 * Render a CompareResult into a markdown body for IM / CLI display.
 * Section ordering: header, A, B, judge verdict (if present).
 */
export declare function formatCompareResult(r: CompareResult): string;
//# sourceMappingURL=router-compare.d.ts.map