/**
 * Output Normalizer — single processing layer for all model output.
 *
 * All output from the model (text deltas, tool call arguments, final text)
 * passes through ONE normalizer before reaching the agent loop, tool dispatch,
 * event pipeline, or any client.
 *
 * Replaces the scattered filters across emitChatDelta, emitChatFinal, render.js,
 * pi-tools.ts, and attempt.ts with one coherent processing point.
 *
 * Design: model output is untrusted input.  The normalizer validates and cleans
 * it the same way you'd sanitize user input at a system boundary.
 *
 * @module
 */
import type { ModelProfile } from "../config/model-profiles.js";
export interface NormalizeTextResult {
    /** Cleaned text delta. */
    text: string;
    /** If set, the stream should be aborted immediately. */
    abort?: {
        reason: string;
    };
}
export interface OutputNormalizer {
    /** Process a text delta from the model stream. Returns cleaned text
     *  and optional abort signal (combined — no separate shouldAbort check). */
    normalizeTextDelta(delta: string): NormalizeTextResult;
    /** Process tool call arguments. Returns cleaned args with all string
     *  values stripped of control tokens. */
    normalizeToolArgs(args: Record<string, unknown>): Record<string, unknown>;
    /** Process the final accumulated text. Strips tokens, detects and removes
     *  trailing monologue blocks. Called once when the model turn completes. */
    normalizeFinalText(text: string): string;
    /** Reset state for a new model turn. */
    reset(): void;
}
/**
 * Layer 2: Structural monologue detection.
 * Detects a trailing block that:
 *  1. Starts after a double newline
 *  2. Opens with a self-referential phrase
 *  3. Contains a numbered list with assessment keywords
 *  4. Sits at the end of the text
 */
declare function detectMonologueStructural(text: string): number | null;
/**
 * Strip monologue from final text using the hierarchy:
 * Layer 2 (structural) first, Layer 3 (regex) as fallback.
 * Layer 1 (prompt tuning) happens before the model produces output.
 */
declare function stripMonologue(text: string): string;
declare function detectRepetition(text: string, minBlock: number): boolean;
declare function sanitizeArgs(args: Record<string, unknown>, modelId: string): Record<string, unknown>;
/**
 * Create an output normalizer configured for the given model profile.
 *
 * For Claude: passthrough (no stripping, no monologue, no aggressive cleaning).
 * For Gemma/vLLM: full normalization pipeline.
 * For unknown: conservative defaults.
 */
export declare function createOutputNormalizer(profile: ModelProfile, modelId: string): OutputNormalizer;
export declare const __testing: {
    detectMonologueStructural: typeof detectMonologueStructural;
    stripMonologue: typeof stripMonologue;
    detectRepetition: typeof detectRepetition;
    sanitizeArgs: typeof sanitizeArgs;
};
export {};
