/**
 * Text content part for multi-modal messages
 */
type TextContentPart = {
    type: 'text';
    text: string;
};
/**
 * Image content part for multi-modal messages
 * Supports base64 data URIs or URLs
 */
type ImageContentPart = {
    type: 'image';
    image: string;
    mimeType?: string;
    alt?: string;
};
/**
 * File content part for multi-modal messages
 * Supports PDF, TXT, DOCX, and other document types
 */
type FileContentPart = {
    type: 'file';
    data: string;
    mimeType: string;
    filename: string;
};
/**
 * Audio content part for multi-modal messages
 * Supports base64 data URIs or URLs
 */
type AudioContentPart = {
    type: 'audio';
    audio: string;
    mimeType?: string;
};
/**
 * Video content part for multi-modal messages
 * Supports base64 data URIs or URLs
 */
type VideoContentPart = {
    type: 'video';
    video: string;
    mimeType?: string;
};
/**
 * Union type for all content part types
 */
type ContentPart = TextContentPart | ImageContentPart | FileContentPart | AudioContentPart | VideoContentPart;
/**
 * Metadata attached to messages created during agent execution.
 */
type AgentMessageMetadata = {
    executionId?: string;
    iteration?: number;
    turnId?: string;
    agentName?: string;
    /**
     * When this message was produced by a step inside a nested flow executed
     * as a tool, identifies the parent tool call id. Enables renderers to
     * visually group or indent nested-flow output under its parent tool.
     */
    parentToolId?: string;
    /**
     * Nested flow step id that produced this message (e.g. a `send-stream`
     * or `prompt` step inside the nested flow). Stable key for that step.
     */
    parentStepId?: string;
    /**
     * Set to `true` on a tool-variant message produced from a `step_await`
     * event (`awaitReason: "local_tool_required"`). Signals to UI code that
     * the tool call is a LOCAL tool and the server is paused waiting for a
     * `POST /v1/dispatch/resume` with the user's answer keyed by tool name.
     */
    awaitingLocalTool?: boolean;
    /**
     * The provider per-call id (`toolu_…`) carried on the `step_await` /
     * `flow_await` events for a LOCAL tool (core#3878). Present only when the
     * server emits it. Two PARALLEL calls to the same tool in one turn share a
     * `toolName` (and a collapsed `toolId`) but get DISTINCT `webMcpToolCallId`s,
     * so this is the key the widget batches a single `/resume` on — preferred
     * over tool name, which collides for same-tool parallel calls. Absent →
     * fall back to the legacy name-keyed resume contract.
     */
    webMcpToolCallId?: string;
    /**
     * Set to `true` once the user has picked / typed / dismissed an answer for
     * an `ask_user_question` tool call, so renderers stop re-mounting the
     * answer-pill sheet for this tool call on subsequent render passes.
     */
    askUserQuestionAnswered?: boolean;
    /**
     * In-progress answers for a multi-question `ask_user_question` payload,
     * keyed by question text. Persisted across refresh so the user lands back
     * where they were if the page reloads mid-flow. Cleared once
     * `askUserQuestionAnswered` flips to `true`.
     */
    askUserQuestionAnswers?: Record<string, string | string[]>;
    /**
     * Current page index for a multi-question `ask_user_question` payload's
     * paginated stepper. Persists alongside `askUserQuestionAnswers`.
     */
    askUserQuestionIndex?: number;
};
/**
 * Context passed to plugin lifecycle hooks. Carries the live DOM references
 * and resolved animation settings for the currently-streaming message.
 */
type StreamAnimationContext = {
    /** The `.persona-message-content` element owning the streamed text. */
    container: HTMLElement;
    /** The outer message bubble element. */
    bubble: HTMLElement;
    /** ID of the streaming message. */
    messageId: string;
    /** Read-only reference to the message being streamed. */
    message: AgentWidgetMessage;
    /** Effective `speed` from `streamAnimation.speed`. */
    speed: number;
    /** Effective `duration` from `streamAnimation.duration`. */
    duration: number;
};
/**
 * Pluggable stream animation. Third-party packages and inline registrations
 * implement this interface to add custom reveal effects.
 *
 * Lifecycle:
 * - When the widget mounts and detects a plugin (either passed via config or
 *   auto-registered in the IIFE bundle), it injects `styles` once into the
 *   widget's style host.
 * - For each streaming assistant message whose `type` matches `name`, the
 *   widget applies `containerClass` / `bubbleClass`, wraps text per `wrap`,
 *   and — if `useCaret` is true — appends a blinking caret.
 * - Hooks fire after the live DOM is morphed; plugins use stable element IDs
 *   and `data-preserve-animation` to safely mutate per-char or per-word spans
 *   without idiomorph clobbering in-flight work.
 */
type StreamAnimationPlugin = {
    /** Plugin identifier. Matches the `type` field in `streamAnimation`. */
    name: string;
    /** Class added to `.persona-message-content` while streaming. */
    containerClass?: string;
    /** Class added to the bubble element (e.g. a one-shot scale animation). */
    bubbleClass?: string;
    /** Wrap mode applied to text nodes during streaming. @default "none" */
    wrap?: "none" | "char" | "word";
    /**
     * HTML tags whose descendant text is skipped during wrapping. Defaults to
     * `["pre", "code", "a", "script", "style"]` — useful for keeping code
     * blocks legible and link click-targets intact. Plugins that want to
     * animate characters inside inline code (e.g. `glyph-cycle`) can narrow
     * the list.
     */
    skipTags?: string[];
    /** Append a blinking caret after the last rendered char/word. */
    useCaret?: boolean;
    /** CSS string injected into the widget style host on first activation. */
    styles?: string;
    /**
     * Optional custom buffering strategy. Returns the portion of `content`
     * that should be rendered during streaming. Use this for buffering
     * schemes beyond the built-in `word` / `line` strategies.
     */
    bufferContent?: (content: string, message: AgentWidgetMessage) => string;
    /**
     * Fires once when the plugin is first activated inside a widget instance.
     * Use this to set up MutationObservers or other long-lived listeners.
     * Return an optional cleanup function that runs on widget destroy.
     */
    onAttach?: (root: HTMLElement | ShadowRoot) => (() => void) | void;
    /** Fires after each render that reaches the live DOM. */
    onAfterRender?: (ctx: StreamAnimationContext) => void;
    /** Fires when a streamed message's `streaming` flag flips to false. */
    onStreamComplete?: (ctx: StreamAnimationContext) => void;
    /**
     * Report whether the plugin still has in-flight animation work for a
     * message. When `true`, the widget keeps rendering the message in its
     * "streaming-animated" mode even after `message.streaming` flips false —
     * preventing the final non-animated render from yanking the rug out from
     * under unfinished per-char cycles or reveals.
     */
    isAnimating?: (message: AgentWidgetMessage) => boolean;
};
type AgentWidgetMessageRole = "user" | "assistant" | "system";
type AgentWidgetReasoning = {
    id: string;
    status: "pending" | "streaming" | "complete";
    chunks: string[];
    startedAt?: number;
    completedAt?: number;
    durationMs?: number;
};
type AgentWidgetToolCall = {
    id: string;
    name?: string;
    status: "pending" | "running" | "complete";
    args?: unknown;
    chunks?: string[];
    result?: unknown;
    duration?: number;
    startedAt?: number;
    completedAt?: number;
    durationMs?: number;
};
/**
 * Represents a tool approval request in the chat conversation.
 * Created when the agent requires human approval before executing a tool.
 */
type AgentWidgetApproval = {
    id: string;
    status: "pending" | "approved" | "denied" | "timeout";
    agentId: string;
    executionId: string;
    toolName: string;
    toolType?: string;
    description: string;
    parameters?: unknown;
    resolvedAt?: number;
};
type AgentWidgetMessageVariant = "assistant" | "reasoning" | "tool" | "approval";
/**
 * Per-turn / per-step stop reason emitted by the runtime on
 * `agent_turn_complete` and `step_complete` SSE events. The vocabulary is
 * owned by the upstream Runtype API — do not extend without coordination.
 *
 * - `end_turn` — natural completion (no affordance needed)
 * - `max_tool_calls` — agent loop tripped the configured tool-call ceiling
 * - `length` — provider hit max output tokens
 * - `content_filter` — provider content filter intervened
 * - `error` — provider/runtime error (prefer existing error rendering)
 * - `unknown` — explicitly reported but uninformative
 *
 * Absent (`undefined`) means "not reported" — distinct from `'unknown'`.
 */
type StopReasonKind = 'end_turn' | 'max_tool_calls' | 'length' | 'content_filter' | 'error' | 'unknown';
/**
 * Represents a message in the chat conversation.
 *
 * @property id - Unique message identifier
 * @property role - Message role: "user", "assistant", or "system"
 * @property content - Message text content (for display)
 * @property contentParts - Original multi-modal content parts (for API requests)
 * @property createdAt - ISO timestamp when message was created
 * @property streaming - Whether message is still streaming (for assistant messages)
 * @property variant - Message variant for assistant messages: "assistant", "reasoning", or "tool"
 * @property sequence - Message ordering number
 * @property reasoning - Reasoning data for assistant reasoning messages
 * @property toolCall - Tool call data for assistant tool messages
 * @property tools - Array of tool calls
 * @property viaVoice - Set to `true` when a user message is sent via voice recognition.
 *                      Useful for implementing voice-specific behaviors like auto-reactivation.
 */
type AgentWidgetMessage = {
    id: string;
    role: AgentWidgetMessageRole;
    content: string;
    createdAt: string;
    /**
     * Original multi-modal content parts for this message.
     * When present, this is sent to the API instead of `content`.
     * The `content` field contains the text-only representation for display.
     */
    contentParts?: ContentPart[];
    streaming?: boolean;
    variant?: AgentWidgetMessageVariant;
    sequence?: number;
    reasoning?: AgentWidgetReasoning;
    toolCall?: AgentWidgetToolCall;
    tools?: AgentWidgetToolCall[];
    /** Approval data for messages with variant "approval" */
    approval?: AgentWidgetApproval;
    viaVoice?: boolean;
    /**
     * Set to `true` on placeholder messages injected during Runtype voice processing.
     * Use this in `messageTransform` to detect and customize voice processing placeholders.
     *
     * @example
     * messageTransform: ({ text, message }) => {
     *   if (message.voiceProcessing && message.role === 'user') {
     *     return '<div class="my-voice-spinner">Transcribing...</div>';
     *   }
     *   return text;
     * }
     */
    voiceProcessing?: boolean;
    /**
     * Raw structured payload for this message (e.g., JSON action response).
     * Populated automatically when structured parsers run.
     */
    rawContent?: string;
    /**
     * LLM-specific content for API requests.
     * When present, this is sent to the LLM instead of `content`.
     *
     * Priority for API payload:
     * 1. `contentParts` (if present, used as-is for multi-modal)
     * 2. `llmContent` (if present, sent as string)
     * 3. `rawContent` (backward compatibility with structured parsers)
     * 4. `content` (fallback - display content)
     *
     * The `content` field is always used for UI display.
     *
     * @example
     * // Show full details to user, send summary to LLM
     * {
     *   content: "**Product:** iPhone 15 Pro\n**Price:** $1,199\n**SKU:** IP15P-256",
     *   llmContent: "[Product search: iPhone 15 Pro, $1199]"
     * }
     */
    llmContent?: string;
    /**
     * Text segment identity for chronological ordering.
     * When present, identifies which text segment this message represents
     * (e.g., "text_0", "text_1") for messages split at tool boundaries.
     */
    partId?: string;
    /**
     * Metadata for messages created during agent loop execution.
     * Contains execution context like iteration number and turn ID.
     */
    agentMetadata?: AgentMessageMetadata;
    /**
     * Per-turn stop reason reported by the runtime on `agent_turn_complete`
     * (agent-loop path) or the last `step_complete` for a prompt step
     * (dispatch / flow path). Absent when the API did not report a value.
     *
     * When set to a non-natural value (`max_tool_calls`, `length`,
     * `content_filter`, `error`), the widget renders an inline notice on
     * the assistant bubble. See `config.copy.stopReasonNotice` to override
     * the default copy.
     */
    stopReason?: StopReasonKind;
};

export type { StreamAnimationPlugin as S };
