/**
 * Normalized provider response types for the CLEO LLM transport layer.
 *
 * Ported from Hermes `agent/transports/types.py` (Python dataclasses →
 * TypeScript interfaces, snake_case → camelCase). These types define the
 * canonical shape that all provider transports normalize responses to. The
 * shared surface is intentionally minimal — only fields that every downstream
 * consumer reads are top-level. Protocol-specific state goes in `providerData`
 * dicts so that protocol-aware code paths can access it without polluting the
 * shared type.
 *
 * @module llm/normalized-response
 * @task T9263
 * @task T9282 (W0c — Phase 4 multimodal + stream extensions)
 * @epic T-LLM-CRED-CENTRALIZATION
 * @see ADR-072 §LlmTransport — pure wire level
 */
import type { ModelTransport } from '../operations/llm.js';
import type { NormalizedDelta, TransportContext } from './interfaces.js';
import type { ApiMode } from './provider-id.js';
/**
 * Token usage reported by the provider for a single API call.
 *
 * `cachedTokens` is only populated when the provider supports prompt-cache
 * read accounting (Anthropic extended caching, Gemini cached content).
 */
export interface NormalizedUsage {
    /** Tokens consumed by the prompt. */
    inputTokens: number;
    /** Tokens generated by the model. */
    outputTokens: number;
    /** Tokens served from prompt cache (if provider supports caching). */
    cachedTokens?: number;
}
/**
 * A single normalized tool call emitted by the model.
 *
 * `id` is the protocol-canonical identifier used when constructing tool result
 * messages. May be `null` when the provider omits it (rare in practice but
 * possible with some adapters).
 *
 * `providerData` carries per-tool-call protocol metadata that only
 * protocol-aware code reads. Examples:
 * - Codex: `{ call_id: "call_XXX", response_item_id: "fc_XXX" }`
 * - Gemini: `{ extra_content: { thought_signature: "..." } }`
 */
export interface NormalizedToolCall {
    /** Provider-assigned tool-call id (may be null if provider does not surface one). */
    id: string | null;
    /** Tool name as declared in the request. */
    name: string;
    /** Arguments as a JSON string (provider-agnostic). */
    arguments: string;
    /** Provider-specific extras (raw shape, do not depend on). */
    providerData?: Record<string, unknown>;
}
/**
 * Normalized API response from any LLM provider.
 *
 * Shared fields are truly cross-provider — every caller can rely on them
 * without branching on transport. Protocol-specific state goes in
 * `providerData` so that only protocol-aware code paths read it.
 *
 * `raw` is the unmodified SDK response object. Consumers MUST narrow it with
 * a type guard before accessing fields. NEVER log `raw` without scrubbing
 * auth headers.
 */
export interface NormalizedResponse {
    /** Response id from the provider (or a synthesized id if absent). */
    id: string;
    /** Model identifier as reported by the provider. */
    model: string;
    /** Plain text content (null when the model returned only tool calls). */
    content: string | null;
    /** Tool calls, or null when none. */
    toolCalls: NormalizedToolCall[] | null;
    /**
     * Provider-reported stop reason.
     * Common values: `'end_turn'`, `'tool_use'`, `'stop'`, `'max_tokens'`,
     * `'stop_sequence'`, `'tool_calls'`, `'length'`.
     */
    stopReason: string;
    /** Token usage for this call. */
    usage: NormalizedUsage;
    /**
     * Optional model-internal reasoning trace.
     * Populated for Anthropic extended-thinking and OpenAI o1-series models.
     */
    reasoning?: string | null;
    /** Provider-specific response-level extras (raw shape, do not depend on). */
    providerData?: Record<string, unknown>;
    /**
     * Raw provider response — DO NOT log this without scrubbing auth headers.
     *
     * Typed as `unknown` because the concrete SDK response shapes
     * (Anthropic.Message, OpenAI.ChatCompletion, …) are not imported from
     * contracts. Consumers MUST narrow with a type guard before accessing fields.
     */
    raw: unknown;
}
/**
 * An image content block for multimodal messages.
 *
 * `source.type` determines how the image data is provided:
 * - `'base64'` — raw image bytes encoded as base64, with `mediaType` identifying
 *   the MIME type (e.g. `'image/png'`, `'image/jpeg'`).
 * - `'url'` — a publicly accessible URL; `data` is the URL string and `mediaType`
 *   is still populated (sniffed by {@link image-routing.ts} when not supplied by
 *   the caller).
 *
 * @see ADR-072 §LlmTransport — pure wire level (W4d image routing)
 */
export interface TransportImageBlock {
    /** Discriminant — always `'image'`. */
    readonly type: 'image';
    readonly source: {
        /** How the image data is provided. */
        readonly type: 'base64' | 'url';
        /**
         * Base64-encoded image bytes (when `type === 'base64'`) or a URL string
         * (when `type === 'url'`).
         */
        readonly data: string;
        /** MIME type, e.g. `'image/png'`, `'image/jpeg'`, `'image/webp'`. */
        readonly mediaType: string;
    };
}
/**
 * A text content block for multimodal messages.
 */
export interface TransportTextBlock {
    /** Discriminant — always `'text'`. */
    readonly type: 'text';
    /** Plain text string. */
    readonly text: string;
}
/**
 * A single message in a provider-neutral conversation turn.
 *
 * `toolUseId` is required when `role` is `'tool'` — it identifies which
 * tool call this result resolves, matching {@link NormalizedToolCall.id}.
 *
 * `content` supports both the legacy plain-string form and a multimodal block
 * array. When `content` is a string, the transport treats it as a single text
 * block. When it is an array, each element is either a {@link TransportTextBlock}
 * or a {@link TransportImageBlock} — enabling image routing (W4d) without
 * breaking existing transport consumers that only read the string form.
 */
export interface TransportMessage {
    /** Conversation turn role. */
    role: 'user' | 'assistant' | 'tool';
    /**
     * Message content.
     *
     * - Plain `string` — backwards-compatible single-text-block form used by
     *   all existing transports. Transports that do not support images receive
     *   this form only.
     * - `ReadonlyArray<TransportTextBlock | TransportImageBlock>` — multimodal
     *   block array enabling image routing (ADR-072 W4d). Transports that do not
     *   support images MUST stringify text blocks and drop image blocks (or throw
     *   if `imageMode` on the request is `'native'` — see {@link TransportRequest}).
     */
    readonly content: string | ReadonlyArray<TransportTextBlock | TransportImageBlock>;
    /** Tool-result messages: id of the call this resolves. */
    toolUseId?: string;
}
/**
 * A tool definition passed to the provider.
 *
 * `inputSchema` is a JSON Schema object describing the tool's input parameters.
 * The transport layer passes it through verbatim after any provider-specific
 * adaptation (e.g. Anthropic wraps it in `{ type: "object", ... }`).
 */
export interface TransportTool {
    /** Tool name as it will appear in {@link NormalizedToolCall.name}. */
    name: string;
    /** Human-readable description for the model. */
    description: string;
    /** JSON Schema for input parameters. */
    inputSchema: Record<string, unknown>;
}
/**
 * Request parameters passed to {@link LlmTransport.complete} and
 * {@link LlmTransport.stream}.
 *
 * `temperature` is normalized to the 0.0–1.0 range; each transport clamps it
 * to the provider's supported range before sending.
 *
 * `signal` may be used to abort in-flight requests (passed through to the
 * underlying fetch / SDK call where supported).
 *
 * @see ADR-072 §LlmTransport — pure wire level
 */
export interface TransportRequest {
    /** Model identifier — provider-specific (e.g. `'claude-sonnet-4-6'`). */
    model: string;
    /** Conversation messages in provider-neutral form. */
    messages: TransportMessage[];
    /** Maximum tokens to generate (NOT input budget). */
    maxTokens: number;
    /** Optional system prompt (Anthropic top-level `system`) or system message (OpenAI). */
    system?: string;
    /** Optional tools the model may call. */
    tools?: TransportTool[];
    /** Sampling temperature in 0.0–1.0 range; provider clamps to its own range. */
    temperature?: number;
    /** AbortSignal for request cancellation. */
    signal?: AbortSignal;
    /**
     * Prompt-cache breakpoint injection strategy.
     *
     * - `'system_and_3'` — inject cache breakpoints after the system prompt and
     *   after the last 3 user messages (Anthropic extended-caching strategy).
     * - `'prefix_and_2'` — inject at the shared prefix boundary and after the 2
     *   most-recent turns (optimised for Gemini cached content).
     * - `null` — no cache injection (default when not set).
     *
     * Transports apply the selected strategy before constructing the SDK request.
     * Unsupported strategies on a given transport are silently ignored.
     *
     * @see ADR-072 §LlmTransport — pure wire level
     */
    readonly cacheStrategy?: 'system_and_3' | 'prefix_and_2' | null;
    /**
     * Image handling mode for multimodal content blocks in {@link TransportMessage.content}.
     *
     * - `'native'` — send image blocks as-is to the provider's multimodal API.
     *   The transport MUST throw if the provider does not support native images.
     * - `'text'` — strip all image blocks; only text blocks are sent. Useful for
     *   text-only providers or when images are redundant.
     * - `'auto'` — the transport decides based on provider capability (default).
     *   Falls back to `'text'` for providers that do not support native images.
     *
     * Used by the image-routing layer (W4d) to select the per-turn input mode.
     *
     * @see ADR-072 §LlmTransport — pure wire level
     */
    readonly imageMode?: 'native' | 'text' | 'auto';
    /**
     * Anthropic-style extended thinking budget (token count).
     *
     * Providers that do NOT support thinking budgets (e.g. Moonshot) MUST
     * reject this field with an error. Transports validate this against the
     * provider profile before constructing the SDK request.
     *
     * @task T9286 (W1d — Moonshot thinkingBudgetTokens rejection)
     */
    readonly thinkingBudgetTokens?: number | null;
}
/**
 * Provider transport contract.
 *
 * Each concrete transport (Anthropic, OpenAI, Gemini) implements this
 * interface and maps provider-specific API shapes to/from
 * {@link NormalizedResponse}. Role-resolver and executor code works
 * exclusively against this interface so providers are swappable.
 *
 * As of Phase 4 (ADR-072) the interface gains two additional members:
 * - {@link apiMode} — the wire protocol spoken by this transport.
 * - {@link stream} — streaming completion returning {@link NormalizedDelta} chunks.
 *
 * Existing transport implementations MUST add stub implementations of both to
 * maintain compile parity (W0c). Wave 1 migrations replace stubs with real impls.
 *
 * @see ADR-072 §LlmTransport — pure wire level
 */
export interface LlmTransport {
    /**
     * Provider identifier — matches the `ModelTransport` union so role-resolver
     * can select the correct transport at runtime.
     */
    readonly provider: ModelTransport;
    /**
     * Wire protocol this transport speaks. Used by the session and executor layers
     * to select correct transports for providers that support multiple protocols.
     *
     * @see ADR-072 §Type lock-in — `ApiMode` closed 4-value union
     */
    readonly apiMode: ApiMode;
    /**
     * Execute a single completion call and return a normalized response.
     *
     * Implementations MUST:
     * - Never return raw credentials in the response envelope.
     * - Preserve the full provider response in {@link NormalizedResponse.raw}.
     * - Map provider-specific stop reasons to the canonical set where possible.
     *
     * @param request - Provider-neutral request parameters.
     * @param ctx - Contextual metadata (request ID, abort signal, feature flags).
     * @returns A promise that resolves to a {@link NormalizedResponse}.
     */
    complete(request: TransportRequest, ctx?: TransportContext): Promise<NormalizedResponse>;
    /**
     * Stream a completion. Each {@link NormalizedDelta} carries incremental text
     * or reasoning content.
     *
     * Implementors MUST run streaming deltas through `StreamingThinkScrubber`
     * before yielding them — reasoning content goes to `delta.reasoning`;
     * visible text goes to `delta.text`. The final delta has a non-null
     * `stopReason` and carries full usage stats in `delta.usage`.
     *
     * W0c transports carry a stub that throws until Wave 1 migration lands:
     * ```ts
     * throw new Error('STUB: W1 migration will implement stream() for <provider>');
     * ```
     *
     * @param request - Provider-neutral request parameters.
     * @param ctx - Contextual metadata (request ID, abort signal, feature flags).
     * @returns An async iterable of normalized delta chunks.
     * @see ADR-072 §LlmTransport — pure wire level
     */
    stream(request: TransportRequest, ctx: TransportContext): AsyncIterable<NormalizedDelta>;
}
//# sourceMappingURL=normalized-response.d.ts.map