import { type RepetitionEvent } from "./repetition.js";
import { type AssistantMessage, type ModelOutputInvalid, type StreamDropCause } from "../internal/llm.js";
/**
 * design/157 A10 — stream-parser pieces that the anthropic and openai SSE lanes carried BYTE-IDENTICALLY
 * (verified by diff at 1469481: a 16-line repetition-telemetry closure). Provider-agnostic policy, so it
 * lives here once and each lane keeps a pointer comment.
 *
 * REF-B1 extends that: the fail-closed ARGUMENT PARSE inside each lane's `closeToolCall*` (identical down to
 * its comment) is hoisted here as {@link parseStreamedToolArgs}. Only the parse — each lane keeps its own
 * accumulator fields, its `closedTc` cache and its own id prefix, which are real wire-format differences.
 *
 * Deliberately NOT hoisted: each lane's own degenerate-cut bookkeeping (`degenTextBlock` / `degenFace` are
 * lane-specific content shapes).
 *
 * Internal module: not re-exported from `src/index.ts`.
 */
/** The warning (CC 2.1.220's words; gone from 2.1.245 on — 2.1.296 asks for a resume instead) stamped beside `partialFinalized` when a stream ended before its close — by the
 *  mid-stream promotion (the body threw) and by the parsers' own finalize (content arrived, no finish frame). */
export declare const STREAM_TORN_WARNING = "Connection closed mid-response. The response above may be incomplete.";
/** A provider word as a stream-end seat carries it: the word in the provider echo shape, else `?` — the fact that a
 *  word arrived survives, bytes outside the shape do not (the echo discipline: dropped, never rewritten). */
export declare function echoFoldedWord(raw: string): string;
/**
 * The record of what arrived after a stream's first terminal statement — the one ordering rule both wire parsers
 * apply: the first ending (a finish / stop reason, a message stop, an in-band error) decides the turn; after it the
 * turn is frozen, only the usage trailer is read, and every later ending or content frame is refused and counted
 * here. Rides `AssistantMessage.streamEndIgnored` (the first refused frame's kind and word, how many came); the
 * Runner announces it (`route.stream_end_ignored`).
 */
export declare function createStreamEndLedger(): {
    note(statement: StreamEndStatement, word: string): void;
    readonly ignored: AssistantMessage["streamEndIgnored"];
};
type StreamEndStatement = NonNullable<AssistantMessage["streamEndIgnored"]>["statement"];
/**
 * REF-B1 — turn a streamed tool call's accumulated argument bytes into its arguments object, FAIL-CLOSED. The ONE
 * judge of a streamed call's arguments: a call runs only with arguments that are a complete JSON object.
 *
 * - valid JSON **object** → that object (a complete `{}` included);
 * - no bytes (`""`) → `{}` when the wire closed the call — the provider's frame carried no arguments, a no-argument
 *   call; `undefined` when it did not — the stream stopped before the call's first argument byte arrived, and nothing
 *   says it was a no-argument call rather than a cut one;
 * - anything else (truncated/invalid JSON, or a top-level string/array/number/null) → `undefined`.
 *
 * `closed` is the lane's evidence that the wire ended THIS call, with no default (a lane that does not state it does
 * not compile): the call's own close frame, or a stream end that says the model finished its turn (not the output-cap
 * stop, not no stop at all). Another call opening is no evidence — a gateway may open several calls before any
 * argument byte arrives. One reading in the three lanes; each lane states which of these it has.
 *
 * bug-hunt #6 (kept from finalize): a non-object must never reach `tool.execute` / the MCP wire. `undefined`
 * means "do not emit a `toolcall_end` for this call"; callers must NOT cache that outcome — finalize retries
 * the parse against the complete accumulation.
 */
export declare function parseStreamedToolArgs(json: string, closed: boolean): Record<string, unknown> | undefined;
/**
 * The cause of a call slot that never received its NAME — the other component of a call, judged by the same evidence as
 * its arguments ({@link parseStreamedToolArgs}'s `closed`): a slot the wire closed has no name because none was sent
 * (`unnamed`); a slot nothing closed was cut before its name arrived (`truncated`). A call is whole only with both parts;
 * a missing part on an unclosed call is a cut call, whichever part is missing.
 */
export declare function nameMissingCause(closed: boolean): "unnamed" | "truncated";
/** One drop note of a turn: what was dropped, how many, and the sentence the model reads. */
export interface TurnNote {
    readonly cause: StreamDropCause;
    readonly count: number;
    readonly text: string;
}
/**
 * Place a turn's engine notes in its final content: AHEAD of the first tool call, in order, or at the end of a turn
 * that has none. Every dropped call (cut arguments, no tool name) and dropped stream frames are stated so the model
 * re-issues them — also when text survived and no call did; a partial batch still executes its valid calls (a brain
 * `error` is a terminal task failure, not a re-prompt). No block may follow the calls: the Anthropic Messages API
 * rejects a `tool_use` followed by anything but another `tool_use`. The same notes are stamped on the turn's message as
 * its stream drops (`stampStreamDrops`), the run's source for the person's line (`task.tool_turn_incomplete`): the
 * model's sentence and the person's line come from one list. One rule for the three lanes.
 */
export declare function placeTurnNotes(message: Pick<AssistantMessage, "diagnostics">, content: AssistantMessage["content"], notes: readonly TurnNote[]): void;
/**
 * The cause clause of a dropped call's "not valid JSON" message. The output cap is named only when the stream says
 * the cap cut it — the lane's own cap stop, or a counted output at or over the cap on the wire; a stream that ended
 * without its stop frame names the transport instead; any other stop adds nothing (naming the cap there sent a reader
 * after a budget that was never reached). One rule for the lanes that carry the clause.
 */
export declare function truncationCauseClause(facts: TurnCapFacts & {
    terminalFrameSeen: boolean;
}): string;
/** One turn's output-cap facts as the lane holds them — the record {@link truncationCauseClause} words and
 *  {@link modelOutputInvalidOf} carries: the lane's cap stop, the provider's output count (as reported), the cap the
 *  committed request carried. */
export interface TurnCapFacts {
    capStop: boolean;
    outputTokens: number | undefined;
    capTokens: number | undefined;
}
/**
 * The structured account of a turn that FAILED for its dropped tool calls (`AssistantMessage.modelOutputInvalid`) —
 * the lane calls it on the arm whose message is the dropped-calls sentence. `cause` is `truncated` when any call's
 * arguments were cut (the sentence's first part), else `unnamed`; `outputLimit` rides with `truncated`, read off the
 * same {@link TurnCapFacts} the sentence's cap clause reads. One rule for the three lanes.
 */
export declare function modelOutputInvalidOf(drops: {
    truncated: number;
    unnamed: number;
}, cap: TurnCapFacts): ModelOutputInvalid | undefined;
/** Repetition telemetry for ONE stream — the cut event plus the allowance-spared hits. */
export interface RepetitionPoll {
    /** Inspect the accumulated text; returns whether it is degenerate (the caller trips its own cut). */
    poll(text: string): boolean;
    /** The cut event, once a poll tripped. */
    readonly cut: RepetitionEvent | undefined;
    /** Allowance-spared hits, deduped by rule+segment with the loop's PEAK depth kept. */
    readonly spared: RepetitionEvent[];
}
/**
 * Repetition telemetry (2026-07-10): the cut event + allowance-spared hits for THIS stream.
 * Polls re-inspect the same growing text every ~64 chars — dedupe spared by rule+segment so one
 * boot block doesn't log once per poll. Attached to the final message as `repetition`.
 */
export declare function createRepetitionPoll(): RepetitionPoll;
/** Record the provider's OWN name for the model that answered, on the shared partial (hence on the final
 *  message every lane spreads `...partial` into) — ONE rule for the three lanes' spellings (`chunk.model` /
 *  `message_start.message.model` / `response.model`), WRITE twin of `providerReportedModel`
 *  (`core/message-utils.ts`). The LAST frame that NAMES a model decides and the seat carries it only when it
 *  differs; naming nothing (no name, or the empty string — {@link providerEchoReading}) is not an update, naming the
 *  REQUESTED id RETRACTS an earlier substitution. A name outside {@link isProviderEchoShape} is dropped — not an
 *  update — and counted once per response (`echo_dropped`, `field: "responseModel"`). */
export declare function noteResponseModel(partial: {
    responseModel?: string;
}, reported: unknown, requestedId: string): void;
export {};
