/**
 * Plugin interface for customizing widget components
 */
interface AgentWidgetPlugin {
    /**
     * Unique identifier for the plugin
     */
    id: string;
    /**
     * Optional priority (higher = runs first). Default: 0
     */
    priority?: number;
    /**
     * Custom renderer for message bubbles
     * Return null to use default renderer
     */
    renderMessage?: (context: {
        message: AgentWidgetMessage;
        defaultRenderer: () => HTMLElement;
        config: AgentWidgetConfig;
    }) => HTMLElement | null;
    /**
     * Custom renderer for launcher button
     * Return null to use default renderer
     */
    renderLauncher?: (context: {
        config: AgentWidgetConfig;
        defaultRenderer: () => HTMLElement;
        onToggle: () => void;
    }) => HTMLElement | null;
    /**
     * Custom renderer for panel header
     * Return null to use default renderer
     */
    renderHeader?: (context: {
        config: AgentWidgetConfig;
        defaultRenderer: () => HTMLElement;
        onClose?: () => void;
    }) => HTMLElement | null;
    /**
     * Custom renderer for composer/input area
     * Return null to use default renderer
     */
    renderComposer?: (context: {
        config: AgentWidgetConfig;
        defaultRenderer: () => HTMLElement;
        onSubmit: (text: string) => void;
        disabled: boolean;
    }) => HTMLElement | null;
    /**
     * Custom renderer for reasoning bubbles
     * Return null to use default renderer
     */
    renderReasoning?: (context: {
        message: AgentWidgetMessage;
        defaultRenderer: () => HTMLElement;
        config: AgentWidgetConfig;
    }) => HTMLElement | null;
    /**
     * Custom renderer for tool call bubbles
     * Return null to use default renderer
     */
    renderToolCall?: (context: {
        message: AgentWidgetMessage;
        defaultRenderer: () => HTMLElement;
        config: AgentWidgetConfig;
    }) => HTMLElement | null;
    /**
     * Called when plugin is registered
     */
    onRegister?: () => void;
    /**
     * Called when plugin is unregistered
     */
    onUnregister?: () => void;
}

/**
 * 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;
};
/**
 * Union type for all content part types
 */
type ContentPart = TextContentPart | ImageContentPart | FileContentPart;
/**
 * Message content can be a simple string or an array of content parts
 */
type MessageContent = string | ContentPart[];
type AgentWidgetContextProviderContext = {
    messages: AgentWidgetMessage[];
    config: AgentWidgetConfig;
};
type AgentWidgetContextProvider = (context: AgentWidgetContextProviderContext) => Record<string, unknown> | void | Promise<Record<string, unknown> | void>;
type AgentWidgetRequestPayloadMessage = {
    role: AgentWidgetMessageRole;
    content: MessageContent;
    createdAt: string;
};
type AgentWidgetRequestPayload = {
    messages: AgentWidgetRequestPayloadMessage[];
    flowId?: string;
    context?: Record<string, unknown>;
    metadata?: Record<string, unknown>;
};
type AgentWidgetRequestMiddlewareContext = {
    payload: AgentWidgetRequestPayload;
    config: AgentWidgetConfig;
};
type AgentWidgetRequestMiddleware = (context: AgentWidgetRequestMiddlewareContext) => AgentWidgetRequestPayload | void | Promise<AgentWidgetRequestPayload | void>;
type AgentWidgetParsedAction = {
    type: string;
    payload: Record<string, unknown>;
    raw?: unknown;
};
type AgentWidgetActionParserInput = {
    text: string;
    message: AgentWidgetMessage;
};
type AgentWidgetActionParser = (input: AgentWidgetActionParserInput) => AgentWidgetParsedAction | null | undefined;
type AgentWidgetActionHandlerResult = {
    handled?: boolean;
    displayText?: string;
    persistMessage?: boolean;
    resubmit?: boolean;
};
type AgentWidgetActionContext = {
    message: AgentWidgetMessage;
    metadata: Record<string, unknown>;
    updateMetadata: (updater: (prev: Record<string, unknown>) => Record<string, unknown>) => void;
    document: Document | null;
    /**
     * Trigger automatic model continuation.
     * Call this AFTER completing async operations (e.g., injecting search results)
     * to have the model analyze the injected data.
     *
     * Use this instead of returning `resubmit: true` for handlers that do async work,
     * as it ensures the continuation happens after the data is available in context.
     *
     * @example
     * // In an action handler
     * const results = await fetchProducts(query);
     * session.injectAssistantMessage({ content: formatResults(results) });
     * context.triggerResubmit();
     */
    triggerResubmit: () => void;
};
type AgentWidgetActionHandler = (action: AgentWidgetParsedAction, context: AgentWidgetActionContext) => AgentWidgetActionHandlerResult | void;
type AgentWidgetStoredState = {
    messages?: AgentWidgetMessage[];
    metadata?: Record<string, unknown>;
};
interface AgentWidgetStorageAdapter {
    load?: () => AgentWidgetStoredState | null | Promise<AgentWidgetStoredState | null>;
    save?: (state: AgentWidgetStoredState) => void | Promise<void>;
    clear?: () => void | Promise<void>;
}
type AgentWidgetVoiceStateEvent = {
    active: boolean;
    source: "user" | "auto" | "restore" | "system";
    timestamp: number;
};
type AgentWidgetActionEventPayload = {
    action: AgentWidgetParsedAction;
    message: AgentWidgetMessage;
};
/**
 * Feedback event payload for upvote/downvote actions on messages
 */
type AgentWidgetMessageFeedback = {
    type: "upvote" | "downvote";
    messageId: string;
    message: AgentWidgetMessage;
};
/**
 * Configuration for message action buttons (copy, upvote, downvote)
 *
 * **Client Token Mode**: When using `clientToken`, feedback is automatically
 * sent to your Runtype backend. Just enable the buttons and you're done!
 * The `onFeedback` and `onCopy` callbacks are optional for additional local handling.
 *
 * @example
 * ```typescript
 * // With clientToken - feedback is automatic!
 * config: {
 *   clientToken: 'ct_live_...',
 *   messageActions: {
 *     showUpvote: true,
 *     showDownvote: true,
 *     // No onFeedback needed - sent to backend automatically
 *   }
 * }
 * ```
 */
type AgentWidgetMessageActionsConfig = {
    /**
     * Enable/disable message actions entirely
     * @default true
     */
    enabled?: boolean;
    /**
     * Show copy button
     * @default true
     */
    showCopy?: boolean;
    /**
     * Show upvote button.
     * When using `clientToken`, feedback is sent to the backend automatically.
     * @default false
     */
    showUpvote?: boolean;
    /**
     * Show downvote button.
     * When using `clientToken`, feedback is sent to the backend automatically.
     * @default false
     */
    showDownvote?: boolean;
    /**
     * Visibility mode: 'always' shows buttons always, 'hover' shows on hover only
     * @default 'hover'
     */
    visibility?: "always" | "hover";
    /**
     * Horizontal alignment of action buttons
     * @default 'right'
     */
    align?: "left" | "center" | "right";
    /**
     * Layout style for action buttons
     * - 'pill-inside': Compact floating pill around just the buttons (default for hover)
     * - 'row-inside': Full-width row at the bottom of the message
     * @default 'pill-inside'
     */
    layout?: "pill-inside" | "row-inside";
    /**
     * Callback when user submits feedback (upvote/downvote).
     *
     * **Note**: When using `clientToken`, feedback is AUTOMATICALLY sent to your
     * backend via `/v1/client/feedback`. This callback is called IN ADDITION to
     * the automatic submission, useful for updating local UI or analytics.
     */
    onFeedback?: (feedback: AgentWidgetMessageFeedback) => void;
    /**
     * Callback when user copies a message.
     *
     * **Note**: When using `clientToken`, copy events are AUTOMATICALLY tracked
     * via `/v1/client/feedback`. This callback is called IN ADDITION to the
     * automatic tracking.
     */
    onCopy?: (message: AgentWidgetMessage) => void;
};
type AgentWidgetStateEvent = {
    open: boolean;
    source: "user" | "auto" | "api" | "system";
    timestamp: number;
};
type AgentWidgetStateSnapshot = {
    open: boolean;
    launcherEnabled: boolean;
    voiceActive: boolean;
    streaming: boolean;
};
type AgentWidgetControllerEventMap = {
    "user:message": AgentWidgetMessage;
    "assistant:message": AgentWidgetMessage;
    "assistant:complete": AgentWidgetMessage;
    "voice:state": AgentWidgetVoiceStateEvent;
    "action:detected": AgentWidgetActionEventPayload;
    "action:resubmit": AgentWidgetActionEventPayload;
    "widget:opened": AgentWidgetStateEvent;
    "widget:closed": AgentWidgetStateEvent;
    "widget:state": AgentWidgetStateSnapshot;
    "message:feedback": AgentWidgetMessageFeedback;
    "message:copy": AgentWidgetMessage;
};
type AgentWidgetFeatureFlags = {
    showReasoning?: boolean;
    showToolCalls?: boolean;
};
type AgentWidgetTheme = {
    primary?: string;
    secondary?: string;
    surface?: string;
    muted?: string;
    accent?: string;
    container?: string;
    border?: string;
    divider?: string;
    messageBorder?: string;
    inputBackground?: string;
    callToAction?: string;
    callToActionBackground?: string;
    sendButtonBackgroundColor?: string;
    sendButtonTextColor?: string;
    sendButtonBorderColor?: string;
    closeButtonColor?: string;
    closeButtonBackgroundColor?: string;
    closeButtonBorderColor?: string;
    clearChatIconColor?: string;
    clearChatBackgroundColor?: string;
    clearChatBorderColor?: string;
    tooltipBackground?: string;
    tooltipForeground?: string;
    micIconColor?: string;
    micBackgroundColor?: string;
    micBorderColor?: string;
    recordingIconColor?: string;
    recordingBackgroundColor?: string;
    recordingBorderColor?: string;
    inputFontFamily?: "sans-serif" | "serif" | "mono";
    inputFontWeight?: string;
    radiusSm?: string;
    radiusMd?: string;
    radiusLg?: string;
    launcherRadius?: string;
    buttonRadius?: string;
    /**
     * Border style for the chat panel container.
     * @example "1px solid #e5e7eb" | "none"
     * @default "1px solid var(--tvw-cw-border)"
     */
    panelBorder?: string;
    /**
     * Box shadow for the chat panel container.
     * @example "0 25px 50px -12px rgba(0,0,0,0.25)" | "none"
     * @default "0 25px 50px -12px rgba(0,0,0,0.25)"
     */
    panelShadow?: string;
    /**
     * Border radius for the chat panel container.
     * @example "16px" | "0"
     * @default "16px"
     */
    panelBorderRadius?: string;
};
type AgentWidgetLauncherConfig = {
    enabled?: boolean;
    title?: string;
    subtitle?: string;
    textHidden?: boolean;
    iconUrl?: string;
    agentIconText?: string;
    agentIconName?: string;
    agentIconHidden?: boolean;
    position?: "bottom-right" | "bottom-left" | "top-right" | "top-left";
    autoExpand?: boolean;
    width?: string;
    /**
     * When true, the widget panel will fill the full height of its container.
     * Useful for sidebar layouts where the chat should take up the entire viewport height.
     * The widget will use flex layout to ensure header stays at top, messages scroll in middle,
     * and composer stays fixed at bottom.
     *
     * @default false
     */
    fullHeight?: boolean;
    /**
     * When true, the widget panel will be positioned as a sidebar flush with the viewport edges.
     * The panel will have:
     * - No border-radius (square corners)
     * - No margins (flush with top, left/right, and bottom edges)
     * - Full viewport height
     * - Subtle shadow on the edge facing the content
     * - No border between footer and messages
     *
     * Use with `position` to control which side ('bottom-left' for left sidebar, 'bottom-right' for right sidebar).
     * Automatically enables fullHeight when true.
     *
     * @default false
     */
    sidebarMode?: boolean;
    /**
     * Width of the sidebar panel when sidebarMode is true.
     * @default "420px"
     */
    sidebarWidth?: string;
    /**
     * Offset (in pixels) to subtract from the calculated panel height.
     * Useful for adjusting the panel height when there are other fixed elements on the page.
     * Only applies when not in fullHeight or sidebarMode.
     *
     * @default 0
     */
    heightOffset?: number;
    callToActionIconText?: string;
    callToActionIconName?: string;
    callToActionIconColor?: string;
    callToActionIconBackgroundColor?: string;
    callToActionIconHidden?: boolean;
    callToActionIconPadding?: string;
    agentIconSize?: string;
    callToActionIconSize?: string;
    headerIconSize?: string;
    headerIconName?: string;
    headerIconHidden?: boolean;
    closeButtonSize?: string;
    closeButtonColor?: string;
    closeButtonBackgroundColor?: string;
    closeButtonBorderWidth?: string;
    closeButtonBorderColor?: string;
    closeButtonBorderRadius?: string;
    closeButtonPaddingX?: string;
    closeButtonPaddingY?: string;
    closeButtonPlacement?: "inline" | "top-right";
    closeButtonIconName?: string;
    closeButtonIconText?: string;
    closeButtonTooltipText?: string;
    closeButtonShowTooltip?: boolean;
    clearChat?: AgentWidgetClearChatConfig;
    /**
     * Border style for the launcher button.
     * @example "1px solid #e5e7eb" | "2px solid #3b82f6" | "none"
     * @default "1px solid #e5e7eb"
     */
    border?: string;
    /**
     * Box shadow for the launcher button.
     * @example "0 10px 15px -3px rgba(0,0,0,0.1)" | "none"
     * @default "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)"
     */
    shadow?: string;
};
type AgentWidgetSendButtonConfig = {
    borderWidth?: string;
    borderColor?: string;
    paddingX?: string;
    paddingY?: string;
    iconText?: string;
    iconName?: string;
    useIcon?: boolean;
    tooltipText?: string;
    showTooltip?: boolean;
    backgroundColor?: string;
    textColor?: string;
    size?: string;
};
type AgentWidgetClearChatConfig = {
    enabled?: boolean;
    placement?: "inline" | "top-right";
    iconName?: string;
    iconColor?: string;
    backgroundColor?: string;
    borderWidth?: string;
    borderColor?: string;
    borderRadius?: string;
    size?: string;
    paddingX?: string;
    paddingY?: string;
    tooltipText?: string;
    showTooltip?: boolean;
};
type AgentWidgetStatusIndicatorConfig = {
    visible?: boolean;
    idleText?: string;
    connectingText?: string;
    connectedText?: string;
    errorText?: string;
};
type AgentWidgetVoiceRecognitionConfig = {
    enabled?: boolean;
    pauseDuration?: number;
    iconName?: string;
    iconSize?: string;
    iconColor?: string;
    backgroundColor?: string;
    borderColor?: string;
    borderWidth?: string;
    paddingX?: string;
    paddingY?: string;
    tooltipText?: string;
    showTooltip?: boolean;
    recordingIconColor?: string;
    recordingBackgroundColor?: string;
    recordingBorderColor?: string;
    showRecordingIndicator?: boolean;
    autoResume?: boolean | "assistant";
};
type AgentWidgetToolCallConfig = {
    backgroundColor?: string;
    borderColor?: string;
    borderWidth?: string;
    borderRadius?: string;
    headerBackgroundColor?: string;
    headerTextColor?: string;
    headerPaddingX?: string;
    headerPaddingY?: string;
    contentBackgroundColor?: string;
    contentTextColor?: string;
    contentPaddingX?: string;
    contentPaddingY?: string;
    codeBlockBackgroundColor?: string;
    codeBlockBorderColor?: string;
    codeBlockTextColor?: string;
    toggleTextColor?: string;
    labelTextColor?: string;
};
type AgentWidgetSuggestionChipsConfig = {
    fontFamily?: "sans-serif" | "serif" | "mono";
    fontWeight?: string;
    paddingX?: string;
    paddingY?: string;
};
/**
 * Interface for pluggable stream parsers that extract text from streaming responses.
 * Parsers handle incremental parsing to extract text values from structured formats (JSON, XML, etc.).
 *
 * @example
 * ```typescript
 * const jsonParser: AgentWidgetStreamParser = {
 *   processChunk: async (content) => {
 *     // Extract text from JSON - return null if not JSON or text not available yet
 *     if (!content.trim().startsWith('{')) return null;
 *     const match = content.match(/"text"\s*:\s*"([^"]*)"/);
 *     return match ? match[1] : null;
 *   },
 *   getExtractedText: () => extractedText
 * };
 * ```
 */
interface AgentWidgetStreamParserResult {
    /**
     * The extracted text to display (may be partial during streaming)
     */
    text: string | null;
    /**
     * The raw accumulated content. Built-in parsers always populate this so
     * downstream middleware (action handlers, logging, etc.) can
     * inspect/parse the original structured payload.
     */
    raw?: string;
}
interface AgentWidgetStreamParser {
    /**
     * Process a chunk of content and return the extracted text (if available).
     * This method is called for each chunk as it arrives during streaming.
     * Return null if the content doesn't match this parser's format or if text is not yet available.
     *
     * @param accumulatedContent - The full accumulated content so far (including new chunk)
     * @returns The extracted text value and optionally raw content, or null if not yet available or format doesn't match
     */
    processChunk(accumulatedContent: string): Promise<AgentWidgetStreamParserResult | string | null> | AgentWidgetStreamParserResult | string | null;
    /**
     * Get the currently extracted text value (may be partial).
     * This is called synchronously to get the latest extracted text without processing.
     *
     * @returns The currently extracted text value, or null if not yet available
     */
    getExtractedText(): string | null;
    /**
     * Clean up any resources when parsing is complete.
     */
    close?(): Promise<void> | void;
}
/**
 * Component renderer function signature for custom components
 */
type AgentWidgetComponentRenderer = (props: Record<string, unknown>, context: {
    message: AgentWidgetMessage;
    config: AgentWidgetConfig;
    updateProps: (newProps: Record<string, unknown>) => void;
}) => HTMLElement;
/**
 * Result from custom SSE event parser
 */
type AgentWidgetSSEEventResult = {
    /** Text content to display */
    text?: string;
    /** Whether the stream is complete */
    done?: boolean;
    /** Error message if an error occurred */
    error?: string;
} | null;
/**
 * Custom SSE event parser function
 * Allows transforming non-standard SSE event formats to persona's expected format
 */
type AgentWidgetSSEEventParser = (eventData: unknown) => AgentWidgetSSEEventResult | Promise<AgentWidgetSSEEventResult>;
/**
 * Custom fetch function for full control over API requests
 * Use this for custom authentication, request transformation, etc.
 */
type AgentWidgetCustomFetch = (url: string, init: RequestInit, payload: AgentWidgetRequestPayload) => Promise<Response>;
/**
 * Dynamic headers function - called before each request
 */
type AgentWidgetHeadersFunction = () => Record<string, string> | Promise<Record<string, string>>;
/**
 * Session information returned after client token initialization.
 * Contains session ID, expiry time, flow info, and config from the server.
 */
type ClientSession = {
    /** Unique session identifier */
    sessionId: string;
    /** When the session expires */
    expiresAt: Date;
    /** Flow information */
    flow: {
        id: string;
        name: string;
        description: string | null;
    };
    /** Configuration from the server */
    config: {
        welcomeMessage: string | null;
        placeholder: string;
        theme: Record<string, unknown> | null;
    };
};
/**
 * Raw API response from /v1/client/init endpoint
 */
type ClientInitResponse = {
    sessionId: string;
    expiresAt: string;
    flow: {
        id: string;
        name: string;
        description: string | null;
    };
    config: {
        welcomeMessage: string | null;
        placeholder: string;
        theme: Record<string, unknown> | null;
    };
};
/**
 * Request payload for /v1/client/chat endpoint
 */
type ClientChatRequest = {
    sessionId: string;
    messages: Array<{
        id?: string;
        role: 'user' | 'assistant' | 'system';
        content: MessageContent;
    }>;
    /** ID for the expected assistant response message */
    assistantMessageId?: string;
    metadata?: Record<string, unknown>;
    context?: Record<string, unknown>;
};
/**
 * Feedback types supported by the API
 */
type ClientFeedbackType = 'upvote' | 'downvote' | 'copy' | 'csat' | 'nps';
/**
 * Request payload for /v1/client/feedback endpoint
 */
type ClientFeedbackRequest = {
    sessionId: string;
    /** Required for upvote, downvote, copy feedback types */
    messageId?: string;
    type: ClientFeedbackType;
    /** Required for csat (1-5) and nps (0-10) feedback types */
    rating?: number;
    /** Optional comment for any feedback type */
    comment?: string;
};
/**
 * Context provided to header render functions
 */
type HeaderRenderContext = {
    config: AgentWidgetConfig;
    onClose?: () => void;
    onClearChat?: () => void;
};
/**
 * Context provided to message render functions
 */
type MessageRenderContext = {
    message: AgentWidgetMessage;
    config: AgentWidgetConfig;
    streaming: boolean;
};
/**
 * Context provided to slot render functions
 */
type SlotRenderContext = {
    config: AgentWidgetConfig;
    defaultContent: () => HTMLElement | null;
};
/**
 * Header layout configuration
 * Allows customization of the header section appearance and behavior
 */
type AgentWidgetHeaderLayoutConfig = {
    /**
     * Layout preset: "default" | "minimal" | "expanded"
     * - default: Standard layout with icon, title, subtitle, and buttons
     * - minimal: Simplified layout with just title and close button
     * - expanded: Full branding area with additional content space
     */
    layout?: "default" | "minimal" | "expanded";
    /** Show/hide the header icon */
    showIcon?: boolean;
    /** Show/hide the title */
    showTitle?: boolean;
    /** Show/hide the subtitle */
    showSubtitle?: boolean;
    /** Show/hide the close button */
    showCloseButton?: boolean;
    /** Show/hide the clear chat button */
    showClearChat?: boolean;
    /**
     * Custom renderer for complete header override
     * When provided, replaces the entire header with custom content
     */
    render?: (context: HeaderRenderContext) => HTMLElement;
};
/**
 * Avatar configuration for message bubbles
 */
type AgentWidgetAvatarConfig = {
    /** Whether to show avatars */
    show?: boolean;
    /** Position of avatar relative to message bubble */
    position?: "left" | "right";
    /** URL or emoji for user avatar */
    userAvatar?: string;
    /** URL or emoji for assistant avatar */
    assistantAvatar?: string;
};
/**
 * Timestamp configuration for message bubbles
 */
type AgentWidgetTimestampConfig = {
    /** Whether to show timestamps */
    show?: boolean;
    /** Position of timestamp relative to message */
    position?: "inline" | "below";
    /** Custom formatter for timestamp display */
    format?: (date: Date) => string;
};
/**
 * Message layout configuration
 * Allows customization of how chat messages are displayed
 */
type AgentWidgetMessageLayoutConfig = {
    /**
     * Layout preset: "bubble" | "flat" | "minimal"
     * - bubble: Standard chat bubble appearance (default)
     * - flat: Flat messages without bubble styling
     * - minimal: Minimal styling with reduced padding/borders
     */
    layout?: "bubble" | "flat" | "minimal";
    /** Avatar configuration */
    avatar?: AgentWidgetAvatarConfig;
    /** Timestamp configuration */
    timestamp?: AgentWidgetTimestampConfig;
    /** Group consecutive messages from the same role */
    groupConsecutive?: boolean;
    /**
     * Custom renderer for user messages
     * When provided, replaces the default user message rendering
     */
    renderUserMessage?: (context: MessageRenderContext) => HTMLElement;
    /**
     * Custom renderer for assistant messages
     * When provided, replaces the default assistant message rendering
     */
    renderAssistantMessage?: (context: MessageRenderContext) => HTMLElement;
};
/**
 * Available layout slots for content injection
 */
type WidgetLayoutSlot = "header-left" | "header-center" | "header-right" | "body-top" | "messages" | "body-bottom" | "footer-top" | "composer" | "footer-bottom";
/**
 * Slot renderer function signature
 * Returns HTMLElement to render in the slot, or null to use default content
 */
type SlotRenderer = (context: SlotRenderContext) => HTMLElement | null;
/**
 * Main layout configuration
 * Provides comprehensive control over widget layout and appearance
 *
 * @example
 * ```typescript
 * config: {
 *   layout: {
 *     header: { layout: "minimal" },
 *     messages: {
 *       avatar: { show: true, assistantAvatar: "/bot.png" },
 *       timestamp: { show: true, position: "below" }
 *     },
 *     slots: {
 *       "footer-top": () => {
 *         const el = document.createElement("div");
 *         el.textContent = "Powered by AI";
 *         return el;
 *       }
 *     }
 *   }
 * }
 * ```
 */
type AgentWidgetLayoutConfig = {
    /** Header layout configuration */
    header?: AgentWidgetHeaderLayoutConfig;
    /** Message layout configuration */
    messages?: AgentWidgetMessageLayoutConfig;
    /** Slot renderers for custom content injection */
    slots?: Partial<Record<WidgetLayoutSlot, SlotRenderer>>;
    /**
     * Show/hide the header section entirely.
     * When false, the header (including icon, title, buttons) is completely hidden.
     * @default true
     */
    showHeader?: boolean;
    /**
     * Show/hide the footer/composer section entirely.
     * When false, the footer (including input field, send button, suggestions) is completely hidden.
     * Useful for read-only conversation previews.
     * @default true
     */
    showFooter?: boolean;
};
/**
 * Token types for marked renderer methods
 */
type AgentWidgetMarkdownHeadingToken = {
    type: "heading";
    raw: string;
    depth: 1 | 2 | 3 | 4 | 5 | 6;
    text: string;
    tokens: unknown[];
};
type AgentWidgetMarkdownCodeToken = {
    type: "code";
    raw: string;
    text: string;
    lang?: string;
    escaped?: boolean;
};
type AgentWidgetMarkdownBlockquoteToken = {
    type: "blockquote";
    raw: string;
    text: string;
    tokens: unknown[];
};
type AgentWidgetMarkdownTableToken = {
    type: "table";
    raw: string;
    header: Array<{
        text: string;
        tokens: unknown[];
    }>;
    rows: Array<Array<{
        text: string;
        tokens: unknown[];
    }>>;
    align: Array<"left" | "center" | "right" | null>;
};
type AgentWidgetMarkdownLinkToken = {
    type: "link";
    raw: string;
    href: string;
    title: string | null;
    text: string;
    tokens: unknown[];
};
type AgentWidgetMarkdownImageToken = {
    type: "image";
    raw: string;
    href: string;
    title: string | null;
    text: string;
};
type AgentWidgetMarkdownListToken = {
    type: "list";
    raw: string;
    ordered: boolean;
    start: number | "";
    loose: boolean;
    items: unknown[];
};
type AgentWidgetMarkdownListItemToken = {
    type: "list_item";
    raw: string;
    task: boolean;
    checked?: boolean;
    loose: boolean;
    text: string;
    tokens: unknown[];
};
type AgentWidgetMarkdownParagraphToken = {
    type: "paragraph";
    raw: string;
    text: string;
    tokens: unknown[];
};
type AgentWidgetMarkdownCodespanToken = {
    type: "codespan";
    raw: string;
    text: string;
};
type AgentWidgetMarkdownStrongToken = {
    type: "strong";
    raw: string;
    text: string;
    tokens: unknown[];
};
type AgentWidgetMarkdownEmToken = {
    type: "em";
    raw: string;
    text: string;
    tokens: unknown[];
};
/**
 * Custom renderer overrides for markdown elements.
 * Each method receives the token and should return an HTML string.
 * Return `false` to use the default renderer.
 *
 * @example
 * ```typescript
 * renderer: {
 *   heading(token) {
 *     return `<h${token.depth} class="custom-heading">${token.text}</h${token.depth}>`;
 *   },
 *   link(token) {
 *     return `<a href="${token.href}" target="_blank" rel="noopener">${token.text}</a>`;
 *   }
 * }
 * ```
 */
type AgentWidgetMarkdownRendererOverrides = {
    /** Override heading rendering (h1-h6) */
    heading?: (token: AgentWidgetMarkdownHeadingToken) => string | false;
    /** Override code block rendering */
    code?: (token: AgentWidgetMarkdownCodeToken) => string | false;
    /** Override blockquote rendering */
    blockquote?: (token: AgentWidgetMarkdownBlockquoteToken) => string | false;
    /** Override table rendering */
    table?: (token: AgentWidgetMarkdownTableToken) => string | false;
    /** Override link rendering */
    link?: (token: AgentWidgetMarkdownLinkToken) => string | false;
    /** Override image rendering */
    image?: (token: AgentWidgetMarkdownImageToken) => string | false;
    /** Override list rendering (ul/ol) */
    list?: (token: AgentWidgetMarkdownListToken) => string | false;
    /** Override list item rendering */
    listitem?: (token: AgentWidgetMarkdownListItemToken) => string | false;
    /** Override paragraph rendering */
    paragraph?: (token: AgentWidgetMarkdownParagraphToken) => string | false;
    /** Override inline code rendering */
    codespan?: (token: AgentWidgetMarkdownCodespanToken) => string | false;
    /** Override strong/bold rendering */
    strong?: (token: AgentWidgetMarkdownStrongToken) => string | false;
    /** Override emphasis/italic rendering */
    em?: (token: AgentWidgetMarkdownEmToken) => string | false;
    /** Override horizontal rule rendering */
    hr?: () => string | false;
    /** Override line break rendering */
    br?: () => string | false;
    /** Override deleted/strikethrough rendering */
    del?: (token: {
        type: "del";
        raw: string;
        text: string;
        tokens: unknown[];
    }) => string | false;
    /** Override checkbox rendering (in task lists) */
    checkbox?: (token: {
        checked: boolean;
    }) => string | false;
    /** Override HTML passthrough */
    html?: (token: {
        type: "html";
        raw: string;
        text: string;
    }) => string | false;
    /** Override text rendering */
    text?: (token: {
        type: "text";
        raw: string;
        text: string;
    }) => string | false;
};
/**
 * Markdown parsing options (subset of marked options)
 */
type AgentWidgetMarkdownOptions = {
    /**
     * Enable GitHub Flavored Markdown (tables, strikethrough, autolinks).
     * @default true
     */
    gfm?: boolean;
    /**
     * Convert \n in paragraphs into <br>.
     * @default true
     */
    breaks?: boolean;
    /**
     * Conform to original markdown.pl as much as possible.
     * @default false
     */
    pedantic?: boolean;
    /**
     * Add id attributes to headings.
     * @default false
     */
    headerIds?: boolean;
    /**
     * Prefix for heading id attributes.
     * @default ""
     */
    headerPrefix?: string;
    /**
     * Mangle email addresses for spam protection.
     * @default true
     */
    mangle?: boolean;
    /**
     * Silent mode - don't throw on parse errors.
     * @default false
     */
    silent?: boolean;
};
/**
 * Markdown configuration for customizing how markdown is rendered in chat messages.
 * Provides three levels of control:
 *
 * 1. **CSS Variables** - Override styles via `--cw-md-*` CSS custom properties
 * 2. **Parsing Options** - Configure marked behavior via `options`
 * 3. **Custom Renderers** - Full control via `renderer` overrides
 *
 * @example
 * ```typescript
 * // Level 2: Configure parsing options
 * config: {
 *   markdown: {
 *     options: {
 *       gfm: true,
 *       breaks: true,
 *       headerIds: true
 *     }
 *   }
 * }
 * ```
 *
 * @example
 * ```typescript
 * // Level 3: Custom renderers
 * config: {
 *   markdown: {
 *     renderer: {
 *       heading(token) {
 *         return `<h${token.depth} class="custom-h${token.depth}">${token.text}</h${token.depth}>`;
 *       },
 *       link(token) {
 *         return `<a href="${token.href}" target="_blank">${token.text}</a>`;
 *       },
 *       table(token) {
 *         // Wrap tables in a scrollable container
 *         return `<div class="table-scroll">${this.parser.parse(token.tokens)}</div>`;
 *       }
 *     }
 *   }
 * }
 * ```
 */
type AgentWidgetMarkdownConfig = {
    /**
     * Markdown parsing options.
     * These are passed directly to the marked parser.
     */
    options?: AgentWidgetMarkdownOptions;
    /**
     * Custom renderer overrides for specific markdown elements.
     * Each method receives a token object and should return an HTML string.
     * Return `false` to fall back to the default renderer.
     */
    renderer?: AgentWidgetMarkdownRendererOverrides;
    /**
     * Disable default markdown CSS styles.
     * When true, the widget won't apply any default styles to markdown elements,
     * allowing you to provide your own CSS.
     *
     * @default false
     */
    disableDefaultStyles?: boolean;
};
/**
 * Configuration for file attachments in the composer.
 * Enables users to attach images to their messages.
 *
 * @example
 * ```typescript
 * config: {
 *   attachments: {
 *     enabled: true,
 *     allowedTypes: ['image/png', 'image/jpeg', 'image/gif', 'image/webp'],
 *     maxFileSize: 5 * 1024 * 1024, // 5MB
 *     maxFiles: 4
 *   }
 * }
 * ```
 */
type AgentWidgetAttachmentsConfig = {
    /**
     * Enable/disable file attachments.
     * @default false
     */
    enabled?: boolean;
    /**
     * Allowed MIME types for attachments.
     * @default ['image/png', 'image/jpeg', 'image/gif', 'image/webp']
     */
    allowedTypes?: string[];
    /**
     * Maximum file size in bytes.
     * @default 10485760 (10MB)
     */
    maxFileSize?: number;
    /**
     * Maximum number of files per message.
     * @default 4
     */
    maxFiles?: number;
    /**
     * Button icon name (from Lucide icons).
     * @default 'image-plus'
     */
    buttonIconName?: string;
    /**
     * Tooltip text for the attachment button.
     * @default 'Attach image'
     */
    buttonTooltipText?: string;
    /**
     * Callback when a file is rejected (wrong type or too large).
     */
    onFileRejected?: (file: File, reason: 'type' | 'size' | 'count') => void;
};
/**
 * Configuration for persisting widget state across page navigations.
 * Stores open/closed state, voice recognition state, and voice mode in browser storage.
 *
 * @example
 * ```typescript
 * config: {
 *   persistState: true  // Use defaults: sessionStorage, persist open state
 * }
 * ```
 *
 * @example
 * ```typescript
 * config: {
 *   persistState: {
 *     storage: 'local',  // Use localStorage instead of sessionStorage
 *     keyPrefix: 'myapp-',  // Custom prefix for storage keys
 *     persist: {
 *       openState: true,
 *       voiceState: true,
 *       focusInput: true
 *     },
 *     clearOnChatClear: true
 *   }
 * }
 * ```
 */
type AgentWidgetPersistStateConfig = {
    /**
     * Storage type to use.
     * @default 'session'
     */
    storage?: 'local' | 'session';
    /**
     * Prefix for storage keys.
     * @default 'persona-'
     */
    keyPrefix?: string;
    /**
     * What state to persist.
     */
    persist?: {
        /**
         * Persist widget open/closed state.
         * @default true
         */
        openState?: boolean;
        /**
         * Persist voice recognition state.
         * @default true
         */
        voiceState?: boolean;
        /**
         * Focus input when restoring open state.
         * @default true
         */
        focusInput?: boolean;
    };
    /**
     * Clear persisted state when chat is cleared.
     * @default true
     */
    clearOnChatClear?: boolean;
};
type AgentWidgetConfig = {
    apiUrl?: string;
    flowId?: string;
    /**
     * Client token for direct browser-to-API communication.
     * When set, the widget uses /v1/client/* endpoints instead of /v1/dispatch.
     * Mutually exclusive with apiKey/headers authentication.
     *
     * @example
     * ```typescript
     * config: {
     *   clientToken: 'ct_live_flow01k7_a8b9c0d1e2f3g4h5i6j7k8l9'
     * }
     * ```
     */
    clientToken?: string;
    /**
     * Callback when session is initialized (client token mode only).
     * Receives session info including expiry time.
     *
     * @example
     * ```typescript
     * config: {
     *   onSessionInit: (session) => {
     *     console.log('Session started:', session.sessionId);
     *   }
     * }
     * ```
     */
    onSessionInit?: (session: ClientSession) => void;
    /**
     * Callback when session expires or errors (client token mode only).
     * Widget should prompt user to refresh.
     *
     * @example
     * ```typescript
     * config: {
     *   onSessionExpired: () => {
     *     alert('Your session has expired. Please refresh the page.');
     *   }
     * }
     * ```
     */
    onSessionExpired?: () => void;
    /**
     * Get stored session ID for session resumption (client token mode only).
     * Called when initializing a new session to check if there's a previous session_id
     * that should be passed to /client/init to resume the same conversation record.
     *
     * @example
     * ```typescript
     * config: {
     *   getStoredSessionId: () => {
     *     const stored = localStorage.getItem('session_id');
     *     return stored || null;
     *   }
     * }
     * ```
     */
    getStoredSessionId?: () => string | null;
    /**
     * Store session ID for session resumption (client token mode only).
     * Called when a new session is initialized to persist the session_id
     * so it can be used to resume the conversation later.
     *
     * @example
     * ```typescript
     * config: {
     *   setStoredSessionId: (sessionId) => {
     *     localStorage.setItem('session_id', sessionId);
     *   }
     * }
     * ```
     */
    setStoredSessionId?: (sessionId: string) => void;
    /**
     * Static headers to include with each request.
     * For dynamic headers (e.g., auth tokens), use `getHeaders` instead.
     */
    headers?: Record<string, string>;
    /**
     * Dynamic headers function - called before each request.
     * Useful for adding auth tokens that may change.
     * @example
     * ```typescript
     * getHeaders: async () => ({
     *   'Authorization': `Bearer ${await getAuthToken()}`
     * })
     * ```
     */
    getHeaders?: AgentWidgetHeadersFunction;
    copy?: {
        welcomeTitle?: string;
        welcomeSubtitle?: string;
        inputPlaceholder?: string;
        sendButtonLabel?: string;
    };
    theme?: AgentWidgetTheme;
    /**
     * Theme colors for dark mode. Applied when dark mode is detected
     * (when colorScheme is 'dark' or 'auto' with dark mode active).
     * If not provided, falls back to `theme` colors.
     *
     * @example
     * ```typescript
     * config: {
     *   theme: { primary: '#111827', surface: '#ffffff' },
     *   darkTheme: { primary: '#f9fafb', surface: '#1f2937' },
     *   colorScheme: 'auto'
     * }
     * ```
     */
    darkTheme?: AgentWidgetTheme;
    /**
     * Color scheme mode for the widget.
     * - 'light': Always use light theme (default)
     * - 'dark': Always use dark theme
     * - 'auto': Automatically detect from page (HTML class or prefers-color-scheme)
     *
     * When 'auto', detection order:
     * 1. Check if `<html>` has 'dark' class
     * 2. Fall back to `prefers-color-scheme: dark` media query
     *
     * @default 'light'
     */
    colorScheme?: 'auto' | 'light' | 'dark';
    features?: AgentWidgetFeatureFlags;
    launcher?: AgentWidgetLauncherConfig;
    initialMessages?: AgentWidgetMessage[];
    suggestionChips?: string[];
    suggestionChipsConfig?: AgentWidgetSuggestionChipsConfig;
    debug?: boolean;
    formEndpoint?: string;
    launcherWidth?: string;
    sendButton?: AgentWidgetSendButtonConfig;
    statusIndicator?: AgentWidgetStatusIndicatorConfig;
    voiceRecognition?: AgentWidgetVoiceRecognitionConfig;
    toolCall?: AgentWidgetToolCallConfig;
    postprocessMessage?: (context: {
        text: string;
        message: AgentWidgetMessage;
        streaming: boolean;
        raw?: string;
    }) => string;
    plugins?: AgentWidgetPlugin[];
    contextProviders?: AgentWidgetContextProvider[];
    requestMiddleware?: AgentWidgetRequestMiddleware;
    actionParsers?: AgentWidgetActionParser[];
    actionHandlers?: AgentWidgetActionHandler[];
    storageAdapter?: AgentWidgetStorageAdapter;
    /**
     * Called after state is loaded from the storage adapter, but before the widget
     * initializes with that state. Use this to transform or inject messages based
     * on external state (e.g., navigation flags, checkout returns).
     *
     * This hook runs synchronously and must return the (potentially modified) state.
     *
     * @example
     * ```typescript
     * config: {
     *   onStateLoaded: (state) => {
     *     // Check for pending navigation message
     *     const navMessage = consumeNavigationFlag();
     *     if (navMessage) {
     *       return {
     *         ...state,
     *         messages: [...(state.messages || []), {
     *           id: `nav-${Date.now()}`,
     *           role: 'assistant',
     *           content: navMessage,
     *           createdAt: new Date().toISOString()
     *         }]
     *       };
     *     }
     *     return state;
     *   }
     * }
     * ```
     */
    onStateLoaded?: (state: AgentWidgetStoredState) => AgentWidgetStoredState;
    /**
     * Registry of custom components that can be rendered from JSON directives.
     * Components are registered by name and can be invoked via JSON responses
     * with the format: `{"component": "ComponentName", "props": {...}}`
     *
     * @example
     * ```typescript
     * config: {
     *   components: {
     *     ProductCard: (props, context) => {
     *       const card = document.createElement("div");
     *       card.innerHTML = `<h3>${props.title}</h3><p>$${props.price}</p>`;
     *       return card;
     *     }
     *   }
     * }
     * ```
     */
    components?: Record<string, AgentWidgetComponentRenderer>;
    /**
     * Enable component streaming. When true, component props will be updated
     * incrementally as they stream in from the JSON response.
     *
     * @default true
     */
    enableComponentStreaming?: boolean;
    /**
     * Custom stream parser for extracting text from streaming structured responses.
     * Handles incremental parsing of JSON, XML, or other formats.
     * If not provided, uses the default JSON parser.
     *
     * @example
     * ```typescript
     * streamParser: () => ({
     *   processChunk: async (content) => {
     *     // Return null if not your format, or extracted text if available
     *     if (!content.trim().startsWith('{')) return null;
     *     return extractText(content);
     *   },
     *   getExtractedText: () => extractedText
     * })
     * ```
     */
    streamParser?: () => AgentWidgetStreamParser;
    /**
     * Additional localStorage key to clear when the clear chat button is clicked.
     * The widget automatically clears `"persona-chat-history"` by default.
     * Use this option to clear additional keys (e.g., if you're using a custom storage key).
     *
     * @example
     * ```typescript
     * config: {
     *   clearChatHistoryStorageKey: "my-custom-chat-history"
     * }
     * ```
     */
    clearChatHistoryStorageKey?: string;
    /**
     * Built-in parser type selector. Provides an easy way to choose a parser without importing functions.
     * If both `parserType` and `streamParser` are provided, `streamParser` takes precedence.
     *
     * - `"plain"` - Plain text parser (default). Passes through text as-is.
     * - `"json"` - JSON parser using partial-json. Extracts `text` field from JSON objects incrementally.
     * - `"regex-json"` - Regex-based JSON parser. Less robust but faster fallback for simple JSON.
     * - `"xml"` - XML parser. Extracts text content from XML tags.
     *
     * @example
     * ```typescript
     * config: {
     *   parserType: "json"  // Use built-in JSON parser
     * }
     * ```
     *
     * @example
     * ```typescript
     * config: {
     *   parserType: "json",
     *   streamParser: () => customParser()  // Custom parser overrides parserType
     * }
     * ```
     */
    parserType?: "plain" | "json" | "regex-json" | "xml";
    /**
     * Custom fetch function for full control over API requests.
     * Use this for custom authentication, request/response transformation, etc.
     *
     * When provided, this function is called instead of the default fetch.
     * You receive the URL, RequestInit, and the payload that would be sent.
     *
     * @example
     * ```typescript
     * config: {
     *   customFetch: async (url, init, payload) => {
     *     // Transform request for your API format
     *     const myPayload = {
     *       flow: { id: 'my-flow-id' },
     *       messages: payload.messages,
     *       options: { stream_response: true }
     *     };
     *
     *     // Add auth header
     *     const token = await getAuthToken();
     *
     *     return fetch('/my-api/dispatch', {
     *       method: 'POST',
     *       headers: {
     *         'Content-Type': 'application/json',
     *         'Authorization': `Bearer ${token}`
     *       },
     *       body: JSON.stringify(myPayload),
     *       signal: init.signal
     *     });
     *   }
     * }
     * ```
     */
    customFetch?: AgentWidgetCustomFetch;
    /**
     * Custom SSE event parser for non-standard streaming response formats.
     *
     * Use this when your API returns SSE events in a different format than expected.
     * Return `{ text }` for text chunks, `{ done: true }` for completion,
     * `{ error }` for errors, or `null` to ignore the event.
     *
     * @example
     * ```typescript
     * // For Runtype API format
     * config: {
     *   parseSSEEvent: (data) => {
     *     if (data.type === 'step_chunk' && data.chunk) {
     *       return { text: data.chunk };
     *     }
     *     if (data.type === 'flow_complete') {
     *       return { done: true };
     *     }
     *     if (data.type === 'step_error') {
     *       return { error: data.error };
     *     }
     *     return null; // Ignore other events
     *   }
     * }
     * ```
     */
    parseSSEEvent?: AgentWidgetSSEEventParser;
    /**
     * Layout configuration for customizing widget appearance and structure.
     * Provides control over header, messages, and content slots.
     *
     * @example
     * ```typescript
     * config: {
     *   layout: {
     *     header: { layout: "minimal" },
     *     messages: { avatar: { show: true } }
     *   }
     * }
     * ```
     */
    layout?: AgentWidgetLayoutConfig;
    /**
     * Markdown rendering configuration.
     * Customize how markdown is parsed and rendered in chat messages.
     *
     * Override methods:
     * 1. **CSS Variables** - Override `--cw-md-*` variables in your stylesheet
     * 2. **Options** - Configure marked parser behavior
     * 3. **Renderers** - Custom rendering functions for specific elements
     * 4. **postprocessMessage** - Complete control over message transformation
     *
     * @example
     * ```typescript
     * config: {
     *   markdown: {
     *     options: { breaks: true, gfm: true },
     *     renderer: {
     *       link(token) {
     *         return `<a href="${token.href}" target="_blank">${token.text}</a>`;
     *       }
     *     }
     *   }
     * }
     * ```
     */
    markdown?: AgentWidgetMarkdownConfig;
    /**
     * Configuration for message action buttons (copy, upvote, downvote).
     * Shows action buttons on assistant messages for user feedback.
     *
     * @example
     * ```typescript
     * config: {
     *   messageActions: {
     *     enabled: true,
     *     showCopy: true,
     *     showUpvote: true,
     *     showDownvote: true,
     *     visibility: 'hover',
     *     onFeedback: (feedback) => {
     *       console.log('Feedback:', feedback.type, feedback.messageId);
     *     },
     *     onCopy: (message) => {
     *       console.log('Copied message:', message.id);
     *     }
     *   }
     * }
     * ```
     */
    messageActions?: AgentWidgetMessageActionsConfig;
    /**
     * Configuration for file attachments in the composer.
     * When enabled, users can attach images to their messages.
     *
     * @example
     * ```typescript
     * config: {
     *   attachments: {
     *     enabled: true,
     *     maxFileSize: 5 * 1024 * 1024, // 5MB
     *     maxFiles: 4
     *   }
     * }
     * ```
     */
    attachments?: AgentWidgetAttachmentsConfig;
    /**
     * Persist widget state (open/closed, voice mode) across page navigations.
     * When `true`, uses default settings with sessionStorage.
     * When an object, allows customizing storage type, key prefix, and what to persist.
     *
     * @example
     * ```typescript
     * // Simple usage - persist open state in sessionStorage
     * config: {
     *   persistState: true
     * }
     * ```
     *
     * @example
     * ```typescript
     * // Advanced usage
     * config: {
     *   persistState: {
     *     storage: 'local',  // Use localStorage
     *     persist: {
     *       openState: true,
     *       voiceState: true,
     *       focusInput: true
     *     }
     *   }
     * }
     * ```
     */
    persistState?: boolean | AgentWidgetPersistStateConfig;
};
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;
};
type AgentWidgetMessageVariant = "assistant" | "reasoning" | "tool";
/**
 * 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[];
    viaVoice?: 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;
};
/**
 * Options for injecting a message into the conversation.
 * Supports dual-content where UI display differs from LLM context.
 *
 * @example
 * // Same content for user and LLM
 * {
 *   role: 'assistant',
 *   content: 'Here are your search results...'
 * }
 *
 * @example
 * // Different content: user sees full details, LLM sees summary
 * {
 *   role: 'assistant',
 *   content: '**Found 3 products:**\n- iPhone 15 Pro ($1,199)\n- iPhone 15 ($999)',
 *   llmContent: '[Search results: 3 iPhones, $999-$1199]'
 * }
 */
type InjectMessageOptions = {
    /**
     * Message role: "assistant", "user", or "system"
     */
    role: AgentWidgetMessageRole;
    /**
     * Content displayed to the user in the chat UI.
     * This is what appears in the message bubble.
     */
    content: string;
    /**
     * Content sent to the LLM in API requests.
     * When omitted, `content` is used for both display and LLM.
     *
     * Use cases:
     * - Redacted content: Show full product details to user, send summary to LLM
     * - Structured data: Show formatted markdown to user, send JSON to LLM
     * - Token optimization: Show verbose content to user, send concise version to LLM
     */
    llmContent?: string;
    /**
     * Multi-modal content parts for the LLM (images, files).
     * Takes precedence over `llmContent` when present.
     * The `content` field is still used for UI display.
     */
    contentParts?: ContentPart[];
    /**
     * Optional message ID. If omitted, auto-generated based on role.
     */
    id?: string;
    /**
     * Optional creation timestamp (ISO string). If omitted, uses current time.
     */
    createdAt?: string;
    /**
     * Optional sequence number for ordering.
     */
    sequence?: number;
    /**
     * Whether the message is still streaming (for incremental updates).
     * @default false
     */
    streaming?: boolean;
};
/**
 * Options for injecting assistant messages (most common case).
 * Role defaults to 'assistant'.
 */
type InjectAssistantMessageOptions = Omit<InjectMessageOptions, "role">;
/**
 * Options for injecting user messages.
 * Role defaults to 'user'.
 */
type InjectUserMessageOptions = Omit<InjectMessageOptions, "role">;
/**
 * Options for injecting system messages.
 * Role defaults to 'system'.
 */
type InjectSystemMessageOptions = Omit<InjectMessageOptions, "role">;
type AgentWidgetEvent = {
    type: "message";
    message: AgentWidgetMessage;
} | {
    type: "status";
    status: "connecting" | "connected" | "error" | "idle";
} | {
    type: "error";
    error: Error;
};
type AgentWidgetInitOptions = {
    target: string | HTMLElement;
    config?: AgentWidgetConfig;
    useShadowDom?: boolean;
    onReady?: () => void;
    windowKey?: string;
    debugTools?: boolean;
};

type DispatchOptions = {
    messages: AgentWidgetMessage[];
    signal?: AbortSignal;
    /** Pre-generated ID for the expected assistant response (for feedback tracking) */
    assistantMessageId?: string;
};
type SSEHandler = (event: AgentWidgetEvent) => void;
declare class AgentWidgetClient {
    private config;
    private readonly apiUrl;
    private readonly headers;
    private readonly debug;
    private readonly createStreamParser;
    private readonly contextProviders;
    private readonly requestMiddleware?;
    private readonly customFetch?;
    private readonly parseSSEEvent?;
    private readonly getHeaders?;
    private clientSession;
    private sessionInitPromise;
    constructor(config?: AgentWidgetConfig);
    /**
     * Check if running in client token mode
     */
    isClientTokenMode(): boolean;
    /**
     * Get the appropriate API URL based on mode
     */
    private getClientApiUrl;
    /**
     * Get the current client session (if any)
     */
    getClientSession(): ClientSession | null;
    /**
     * Initialize session for client token mode.
     * Called automatically on first message if not already initialized.
     */
    initSession(): Promise<ClientSession>;
    private _doInitSession;
    /**
     * Clear the current client session
     */
    clearClientSession(): void;
    /**
     * Get the feedback API URL
     */
    private getFeedbackApiUrl;
    /**
     * Send feedback for a message (client token mode only).
     * Supports upvote, downvote, copy, csat, and nps feedback types.
     *
     * @param feedback - The feedback request payload
     * @returns Promise that resolves when feedback is sent successfully
     * @throws Error if not in client token mode or if session is invalid
     *
     * @example
     * ```typescript
     * // Message feedback (upvote/downvote/copy)
     * await client.sendFeedback({
     *   sessionId: sessionId,
     *   messageId: messageId,
     *   type: 'upvote'
     * });
     *
     * // CSAT feedback (1-5 rating)
     * await client.sendFeedback({
     *   sessionId: sessionId,
     *   type: 'csat',
     *   rating: 5,
     *   comment: 'Great experience!'
     * });
     *
     * // NPS feedback (0-10 rating)
     * await client.sendFeedback({
     *   sessionId: sessionId,
     *   type: 'nps',
     *   rating: 9
     * });
     * ```
     */
    sendFeedback(feedback: ClientFeedbackRequest): Promise<void>;
    /**
     * Submit message feedback (upvote, downvote, or copy).
     * Convenience method for sendFeedback with message-level feedback.
     *
     * @param messageId - The ID of the message to provide feedback for
     * @param type - The feedback type: 'upvote', 'downvote', or 'copy'
     */
    submitMessageFeedback(messageId: string, type: 'upvote' | 'downvote' | 'copy'): Promise<void>;
    /**
     * Submit CSAT (Customer Satisfaction) feedback.
     * Convenience method for sendFeedback with CSAT feedback.
     *
     * @param rating - Rating from 1 to 5
     * @param comment - Optional comment
     */
    submitCSATFeedback(rating: number, comment?: string): Promise<void>;
    /**
     * Submit NPS (Net Promoter Score) feedback.
     * Convenience method for sendFeedback with NPS feedback.
     *
     * @param rating - Rating from 0 to 10
     * @param comment - Optional comment
     */
    submitNPSFeedback(rating: number, comment?: string): Promise<void>;
    /**
     * Send a message - handles both proxy and client token modes
     */
    dispatch(options: DispatchOptions, onEvent: SSEHandler): Promise<void>;
    /**
     * Client token mode dispatch
     */
    private dispatchClientToken;
    /**
     * Proxy mode dispatch (original implementation)
     */
    private dispatchProxy;
    private buildPayload;
    /**
     * Handle custom SSE event parsing via parseSSEEvent callback
     * Returns true if event was handled, false otherwise
     */
    private handleCustomSSEEvent;
    private streamResponse;
}

type AgentWidgetSessionStatus = "idle" | "connecting" | "connected" | "error";
type SessionCallbacks = {
    onMessagesChanged: (messages: AgentWidgetMessage[]) => void;
    onStatusChanged: (status: AgentWidgetSessionStatus) => void;
    onStreamingChanged: (streaming: boolean) => void;
    onError?: (error: Error) => void;
};
declare class AgentWidgetSession {
    private config;
    private callbacks;
    private client;
    private messages;
    private status;
    private streaming;
    private abortController;
    private sequenceCounter;
    private clientSession;
    constructor(config: AgentWidgetConfig | undefined, callbacks: SessionCallbacks);
    /**
     * Check if running in client token mode
     */
    isClientTokenMode(): boolean;
    /**
     * Initialize the client session (for client token mode).
     * This is called automatically on first message, but can be called
     * explicitly to pre-initialize the session and get config from server.
     */
    initClientSession(): Promise<ClientSession | null>;
    /**
     * Set the client session after initialization
     */
    setClientSession(session: ClientSession): void;
    /**
     * Get current client session
     */
    getClientSession(): ClientSession | null;
    /**
     * Check if session is valid and not expired
     */
    isSessionValid(): boolean;
    /**
     * Clear session (on expiry or error)
     */
    clearClientSession(): void;
    /**
     * Get the underlying client instance (for advanced use cases like feedback)
     */
    getClient(): AgentWidgetClient;
    /**
     * Submit message feedback (upvote, downvote, or copy) to the API.
     * Only available in client token mode.
     *
     * @param messageId - The ID of the message to provide feedback for
     * @param type - The feedback type: 'upvote', 'downvote', or 'copy'
     */
    submitMessageFeedback(messageId: string, type: 'upvote' | 'downvote' | 'copy'): Promise<void>;
    /**
     * Submit CSAT (Customer Satisfaction) feedback to the API.
     * Only available in client token mode.
     *
     * @param rating - Rating from 1 to 5
     * @param comment - Optional comment
     */
    submitCSATFeedback(rating: number, comment?: string): Promise<void>;
    /**
     * Submit NPS (Net Promoter Score) feedback to the API.
     * Only available in client token mode.
     *
     * @param rating - Rating from 0 to 10
     * @param comment - Optional comment
     */
    submitNPSFeedback(rating: number, comment?: string): Promise<void>;
    updateConfig(next: AgentWidgetConfig): void;
    getMessages(): AgentWidgetMessage[];
    getStatus(): AgentWidgetSessionStatus;
    isStreaming(): boolean;
    /**
     * @deprecated Use injectMessage() instead.
     * Injects a raw event into the session event handler.
     */
    injectTestEvent(event: AgentWidgetEvent): void;
    /**
     * Inject a message into the conversation.
     * This is the primary API for adding messages programmatically.
     *
     * Supports dual-content where the displayed content differs from what the LLM receives.
     *
     * @param options - Message injection options including dual-content support
     * @returns The created message object
     *
     * @example
     * // Same content for user and LLM
     * session.injectMessage({
     *   role: 'assistant',
     *   content: 'Here are the search results...'
     * });
     *
     * @example
     * // Different content for user and LLM (redaction)
     * session.injectMessage({
     *   role: 'assistant',
     *   content: '**Found 3 products:**\n- iPhone 15 Pro ($1,199)\n- iPhone 15 ($999)',
     *   llmContent: '[Search results: 3 iPhone products, $799-$1199]'
     * });
     */
    injectMessage(options: InjectMessageOptions): AgentWidgetMessage;
    /**
     * Convenience method for injecting assistant messages.
     * Role defaults to 'assistant'.
     *
     * @example
     * // Simple assistant message
     * session.injectAssistantMessage({
     *   content: 'Here are your search results...'
     * });
     *
     * @example
     * // With redacted LLM content
     * session.injectAssistantMessage({
     *   content: 'Full product details for the user...',
     *   llmContent: '[Product details summary]'
     * });
     */
    injectAssistantMessage(options: InjectAssistantMessageOptions): AgentWidgetMessage;
    /**
     * Convenience method for injecting user messages.
     * Role defaults to 'user'.
     *
     * @example
     * session.injectUserMessage({
     *   content: 'Add iPhone 15 Pro to my cart'
     * });
     */
    injectUserMessage(options: InjectUserMessageOptions): AgentWidgetMessage;
    /**
     * Convenience method for injecting system messages.
     * Role defaults to 'system'.
     *
     * @example
     * // Inject context that guides LLM behavior
     * session.injectSystemMessage({
     *   content: '[Context updated]',  // Minimal display
     *   llmContent: 'User is viewing iPhone 15 Pro. Cart has 2 items.'
     * });
     */
    injectSystemMessage(options: InjectSystemMessageOptions): AgentWidgetMessage;
    sendMessage(rawInput: string, options?: {
        viaVoice?: boolean;
        /** Multi-modal content parts (e.g., images) to include with the message */
        contentParts?: ContentPart[];
    }): Promise<void>;
    /**
     * Continue the conversation without adding a new user message.
     * Triggers the model to respond based on the current conversation state.
     *
     * Use this for automatic continuation after action handlers inject data
     * (e.g., search results) that the model should analyze.
     *
     * @example
     * // After injecting search results, trigger model to analyze them
     * session.injectAssistantMessage({ content: 'Found 5 products...' });
     * session.continueConversation();
     */
    continueConversation(): Promise<void>;
    cancel(): void;
    clearMessages(): void;
    hydrateMessages(messages: AgentWidgetMessage[]): void;
    private handleEvent;
    private setStatus;
    private setStreaming;
    private appendMessage;
    private upsertMessage;
    private ensureSequence;
    private nextSequence;
    private sortMessages;
}

/**
 * Feedback UI components for CSAT and NPS collection
 */
type CSATFeedbackOptions = {
    /** Callback when user submits CSAT feedback */
    onSubmit: (rating: number, comment?: string) => void | Promise<void>;
    /** Callback when user dismisses the feedback form */
    onDismiss?: () => void;
    /** Title text */
    title?: string;
    /** Subtitle/question text */
    subtitle?: string;
    /** Placeholder for optional comment field */
    commentPlaceholder?: string;
    /** Submit button text */
    submitText?: string;
    /** Skip button text */
    skipText?: string;
    /** Show comment field */
    showComment?: boolean;
    /** Rating labels (5 items for ratings 1-5) */
    ratingLabels?: [string, string, string, string, string];
};
type NPSFeedbackOptions = {
    /** Callback when user submits NPS feedback */
    onSubmit: (rating: number, comment?: string) => void | Promise<void>;
    /** Callback when user dismisses the feedback form */
    onDismiss?: () => void;
    /** Title text */
    title?: string;
    /** Subtitle/question text */
    subtitle?: string;
    /** Placeholder for optional comment field */
    commentPlaceholder?: string;
    /** Submit button text */
    submitText?: string;
    /** Skip button text */
    skipText?: string;
    /** Show comment field */
    showComment?: boolean;
    /** Low label (left side) */
    lowLabel?: string;
    /** High label (right side) */
    highLabel?: string;
};
/**
 * Create a CSAT (Customer Satisfaction) feedback form
 * Rating scale: 1-5
 */
declare function createCSATFeedback(options: CSATFeedbackOptions): HTMLElement;
/**
 * Create an NPS (Net Promoter Score) feedback form
 * Rating scale: 0-10
 */
declare function createNPSFeedback(options: NPSFeedbackOptions): HTMLElement;

type Controller = {
    update: (config: AgentWidgetConfig) => void;
    destroy: () => void;
    open: () => void;
    close: () => void;
    toggle: () => void;
    clearChat: () => void;
    setMessage: (message: string) => boolean;
    submitMessage: (message?: string) => boolean;
    startVoiceRecognition: () => boolean;
    stopVoiceRecognition: () => boolean;
    /**
     * Inject a message into the conversation with dual-content support.
     * Auto-opens the widget if closed and launcher is enabled.
     */
    injectMessage: (options: InjectMessageOptions) => AgentWidgetMessage;
    /**
     * Convenience method for injecting assistant messages.
     */
    injectAssistantMessage: (options: InjectAssistantMessageOptions) => AgentWidgetMessage;
    /**
     * Convenience method for injecting user messages.
     */
    injectUserMessage: (options: InjectUserMessageOptions) => AgentWidgetMessage;
    /**
     * Convenience method for injecting system messages.
     */
    injectSystemMessage: (options: InjectSystemMessageOptions) => AgentWidgetMessage;
    /**
     * @deprecated Use injectMessage() instead.
     */
    injectTestMessage: (event: AgentWidgetEvent) => void;
    getMessages: () => AgentWidgetMessage[];
    getStatus: () => AgentWidgetSessionStatus;
    getPersistentMetadata: () => Record<string, unknown>;
    updatePersistentMetadata: (updater: (prev: Record<string, unknown>) => Record<string, unknown>) => void;
    on: <K extends keyof AgentWidgetControllerEventMap>(event: K, handler: (payload: AgentWidgetControllerEventMap[K]) => void) => () => void;
    off: <K extends keyof AgentWidgetControllerEventMap>(event: K, handler: (payload: AgentWidgetControllerEventMap[K]) => void) => void;
    isOpen: () => boolean;
    isVoiceActive: () => boolean;
    getState: () => AgentWidgetStateSnapshot;
    showCSATFeedback: (options?: Partial<CSATFeedbackOptions>) => void;
    showNPSFeedback: (options?: Partial<NPSFeedbackOptions>) => void;
    submitCSATFeedback: (rating: number, comment?: string) => Promise<void>;
    submitNPSFeedback: (rating: number, comment?: string) => Promise<void>;
};
declare const createAgentExperience: (mount: HTMLElement, initialConfig?: AgentWidgetConfig, runtimeOptions?: {
    debugTools?: boolean;
}) => Controller;
type AgentWidgetController = Controller;

type AgentWidgetInitHandle = AgentWidgetController & {
    host: HTMLElement;
};
declare const initAgentWidget: (options: AgentWidgetInitOptions) => AgentWidgetInitHandle;

declare const createLocalStorageAdapter: (key?: string) => AgentWidgetStorageAdapter;

type ActionManagerProcessContext = {
    text: string;
    message: AgentWidgetMessage;
    streaming: boolean;
    raw?: string;
};
type ActionManagerOptions = {
    parsers: AgentWidgetActionParser[];
    handlers: AgentWidgetActionHandler[];
    getSessionMetadata: () => Record<string, unknown>;
    updateSessionMetadata: (updater: (prev: Record<string, unknown>) => Record<string, unknown>) => void;
    emit: <K extends keyof AgentWidgetControllerEventMap>(event: K, payload: AgentWidgetControllerEventMap[K]) => void;
    documentRef: Document | null;
};
declare const defaultJsonActionParser: AgentWidgetActionParser;
declare const defaultActionHandlers: Record<string, AgentWidgetActionHandler>;
declare const createActionManager: (options: ActionManagerOptions) => {
    process: (context: ActionManagerProcessContext) => {
        text: string;
        persist: boolean;
        resubmit?: boolean;
    } | null;
    syncFromMetadata: () => void;
};

/**
 * Options for creating a markdown processor
 */
type MarkdownProcessorOptions = {
    /** Marked parsing options */
    markedOptions?: AgentWidgetMarkdownOptions;
    /** Custom renderer overrides */
    renderer?: AgentWidgetMarkdownRendererOverrides;
};
/**
 * Creates a configured markdown processor with custom options and renderers.
 *
 * @param options - Configuration options for the markdown processor
 * @returns A function that converts markdown text to HTML
 *
 * @example
 * ```typescript
 * // Basic usage with defaults
 * const processor = createMarkdownProcessor();
 * const html = processor("# Hello World");
 *
 * // With custom options
 * const processor = createMarkdownProcessor({
 *   markedOptions: { gfm: true, breaks: true },
 *   renderer: {
 *     link(token) {
 *       return `<a href="${token.href}" target="_blank">${token.text}</a>`;
 *     }
 *   }
 * });
 * ```
 */
declare const createMarkdownProcessor: (options?: MarkdownProcessorOptions) => (text: string) => string;
/**
 * Creates a markdown processor from AgentWidgetMarkdownConfig.
 * This is a convenience function that maps the widget config to processor options.
 *
 * @param config - The markdown configuration from widget config
 * @returns A function that converts markdown text to HTML
 */
declare const createMarkdownProcessorFromConfig: (config?: AgentWidgetMarkdownConfig) => (text: string) => string;
/**
 * Basic markdown renderer using default settings.
 * Remember to sanitize the returned HTML if you render untrusted content in your host page.
 *
 * For custom configuration, use `createMarkdownProcessor()` or `createMarkdownProcessorFromConfig()`.
 */
declare const markdownPostprocessor: (text: string) => string;
/**
 * Escapes HTML entities. Used as the default safe renderer.
 */
declare const escapeHtml: (text: string) => string;
/**
 * Creates a directive postprocessor with custom markdown configuration.
 * Converts special directives (either `<Form type="init" />` or
 * `<Directive>{"component":"form","type":"init"}</Directive>`) into placeholder
 * elements that the widget upgrades after render. Remaining text is rendered as
 * Markdown with the provided configuration.
 *
 * @param markdownConfig - Optional markdown configuration
 * @returns A function that processes text with directives and markdown
 */
declare const createDirectivePostprocessor: (markdownConfig?: AgentWidgetMarkdownConfig) => (text: string) => string;
/**
 * Converts special directives (either `<Form type="init" />` or
 * `<Directive>{"component":"form","type":"init"}</Directive>`) into placeholder
 * elements that the widget upgrades after render. Remaining text is rendered as
 * Markdown using default settings.
 *
 * For custom markdown configuration, use `createDirectivePostprocessor()`.
 */
declare const directivePostprocessor: (text: string) => string;

/**
 * Plain text parser - passes through text as-is without any parsing.
 * This is the default parser.
 */
declare const createPlainTextParser: () => AgentWidgetStreamParser;
/**
 * JSON parser using regex-based extraction.
 * Extracts the 'text' field from JSON responses using regex patterns.
 * This is a simpler regex-based alternative to createJsonStreamParser.
 * Less robust for complex/malformed JSON but has no external dependencies.
 */
declare const createRegexJsonParser: () => AgentWidgetStreamParser;
/**
 * JSON stream parser using partial-json library.
 * Extracts the 'text' field from JSON responses using the partial-json library,
 * which is specifically designed for parsing incomplete JSON from LLMs.
 * This is the recommended parser as it's more robust than regex.
 *
 * Library: https://github.com/promplate/partial-json-parser-js
 */
declare const createJsonStreamParser: () => AgentWidgetStreamParser;
/**
 * Flexible JSON stream parser that can extract text from various field names.
 * This parser looks for display text in multiple possible fields, making it
 * compatible with different JSON response formats.
 *
 * @param textExtractor Optional function to extract display text from parsed JSON.
 *                      If not provided, looks for common text fields.
 */
declare const createFlexibleJsonStreamParser: (textExtractor?: (parsed: any) => string | null) => AgentWidgetStreamParser;
/**
 * XML stream parser.
 * Extracts text from <text>...</text> tags in XML responses.
 */
declare const createXmlParser: () => AgentWidgetStreamParser;

/**
 * Content Utilities
 *
 * Helper functions for working with multi-modal message content.
 */

/**
 * Normalize content to ContentPart[] format.
 * Converts string content to a single text content part.
 */
declare function normalizeContent(content: MessageContent): ContentPart[];
/**
 * Extract display text from content parts.
 * Concatenates all text parts into a single string.
 */
declare function getDisplayText(content: MessageContent): string;
/**
 * Check if content contains any images.
 */
declare function hasImages(content: MessageContent): boolean;
/**
 * Get all image parts from content.
 */
declare function getImageParts(content: MessageContent): ImageContentPart[];
/**
 * Create a text-only content part.
 */
declare function createTextPart(text: string): TextContentPart;
/**
 * Create an image content part from a base64 data URI or URL.
 *
 * @param image - Base64 data URI (data:image/...) or URL
 * @param options - Optional mimeType and alt text
 */
declare function createImagePart(image: string, options?: {
    mimeType?: string;
    alt?: string;
}): ImageContentPart;
/**
 * Convert a File object to an image content part.
 * Reads the file and converts it to a base64 data URI.
 */
declare function fileToImagePart(file: File): Promise<ImageContentPart>;
/**
 * Validate that a file is an acceptable image type.
 *
 * @param file - The file to validate
 * @param acceptedTypes - Array of accepted MIME types (default: common image types)
 * @param maxSizeBytes - Maximum file size in bytes (default: 10MB)
 */
declare function validateImageFile(file: File, acceptedTypes?: string[], maxSizeBytes?: number): {
    valid: boolean;
    error?: string;
};

/**
 * Attachment Manager
 *
 * Handles file selection, validation, preview generation, and content part creation
 * for the composer attachment feature. Supports both images and documents.
 */

/**
 * Pending attachment with preview
 */
interface PendingAttachment {
    id: string;
    file: File;
    previewUrl: string | null;
    contentPart: ImageContentPart | FileContentPart;
}
/**
 * Attachment manager configuration
 */
interface AttachmentManagerConfig {
    allowedTypes?: string[];
    maxFileSize?: number;
    maxFiles?: number;
    onFileRejected?: (file: File, reason: "type" | "size" | "count") => void;
    onAttachmentsChange?: (attachments: PendingAttachment[]) => void;
}
/**
 * Creates and manages attachments for the composer
 */
declare class AttachmentManager {
    private attachments;
    private config;
    private previewsContainer;
    constructor(config?: AttachmentManagerConfig);
    /**
     * Set the previews container element
     */
    setPreviewsContainer(container: HTMLElement | null): void;
    /**
     * Update the configuration (e.g., when allowed types change)
     */
    updateConfig(config: Partial<AttachmentManagerConfig>): void;
    /**
     * Get current attachments
     */
    getAttachments(): PendingAttachment[];
    /**
     * Get content parts for all attachments
     */
    getContentParts(): ContentPart[];
    /**
     * Check if there are any attachments
     */
    hasAttachments(): boolean;
    /**
     * Get the number of attachments
     */
    count(): number;
    /**
     * Handle file input change event
     */
    handleFileSelect(files: FileList | null): Promise<void>;
    /**
     * Remove an attachment by ID
     */
    removeAttachment(id: string): void;
    /**
     * Clear all attachments
     */
    clearAttachments(): void;
    /**
     * Render a preview for an attachment (image thumbnail or file icon)
     */
    private renderPreview;
    /**
     * Update the visibility of the previews container
     */
    private updatePreviewsVisibility;
    /**
     * Create an AttachmentManager from widget config
     */
    static fromConfig(config?: AgentWidgetAttachmentsConfig, onAttachmentsChange?: (attachments: PendingAttachment[]) => void): AttachmentManager;
}

/**
 * Message ID utilities for client-side message tracking
 * Used for feedback integration with the Runtype API
 */
/**
 * Generate a unique message ID for tracking
 * Format: msg_{timestamp_base36}_{random_8chars}
 */
declare function generateMessageId(): string;
/**
 * Generate a unique user message ID
 * Format: usr_{timestamp_base36}_{random_8chars}
 */
declare function generateUserMessageId(): string;
/**
 * Generate a unique assistant message ID
 * Format: ast_{timestamp_base36}_{random_8chars}
 */
declare function generateAssistantMessageId(): string;

type CodeFormat = "esm" | "script-installer" | "script-manual" | "script-advanced" | "react-component" | "react-advanced";
/**
 * Hook code templates for code generation.
 * Each hook can be provided as a string (code template) OR as an actual function.
 * Functions are automatically serialized via `.toString()`.
 *
 * IMPORTANT: When providing functions:
 * - Functions must be self-contained (no external variables/closures)
 * - External variables will be undefined when the generated code runs
 * - Use arrow functions or regular function expressions
 *
 * @example
 * ```typescript
 * // Both of these work:
 *
 * // As string:
 * { getHeaders: "async () => ({ 'Authorization': 'Bearer token' })" }
 *
 * // As function (recommended - better IDE support):
 * { getHeaders: async () => ({ 'Authorization': 'Bearer token' }) }
 * ```
 */
type CodeGeneratorHooks = {
    /**
     * Custom getHeaders function.
     * Should return an object with header key-value pairs.
     *
     * @example
     * ```typescript
     * async () => ({ 'Authorization': `Bearer ${await getAuthToken()}` })
     * ```
     */
    getHeaders?: string | (() => Record<string, string> | Promise<Record<string, string>>);
    /**
     * Custom onFeedback callback for message actions.
     * Receives a feedback object with type, messageId, and message.
     *
     * @example
     * ```typescript
     * (feedback) => { console.log('Feedback:', feedback.type); }
     * ```
     */
    onFeedback?: string | ((feedback: {
        type: string;
        messageId: string;
        message: unknown;
    }) => void);
    /**
     * Custom onCopy callback for message actions.
     * Receives the message that was copied.
     *
     * @example
     * ```typescript
     * (message) => { analytics.track('message_copied', { id: message.id }); }
     * ```
     */
    onCopy?: string | ((message: unknown) => void);
    /**
     * Custom requestMiddleware function.
     * Receives { payload, config } context.
     *
     * @example
     * ```typescript
     * ({ payload }) => ({ ...payload, metadata: { pageUrl: window.location.href } })
     * ```
     */
    requestMiddleware?: string | ((context: {
        payload: unknown;
        config: unknown;
    }) => unknown);
    /**
     * Custom action handlers array.
     * Array of handler functions.
     *
     * @example
     * ```typescript
     * [
     *   (action, context) => {
     *     if (action.type === 'custom') {
     *       return { handled: true };
     *     }
     *   }
     * ]
     * ```
     */
    actionHandlers?: string | Array<(action: unknown, context: unknown) => unknown>;
    /**
     * Custom action parsers array.
     * Array of parser functions.
     */
    actionParsers?: string | Array<(context: unknown) => unknown>;
    /**
     * Custom postprocessMessage function.
     * Receives { text, message, streaming, raw } context.
     * Will override the default markdownPostprocessor.
     *
     * @example
     * ```typescript
     * ({ text }) => customMarkdownProcessor(text)
     * ```
     */
    postprocessMessage?: string | ((context: {
        text: string;
        message?: unknown;
        streaming?: boolean;
        raw?: string;
    }) => string);
    /**
     * Custom context providers array.
     * Array of provider functions.
     */
    contextProviders?: string | Array<() => unknown>;
    /**
     * Custom stream parser factory.
     * Should be a function that returns a StreamParser.
     */
    streamParser?: string | (() => unknown);
};
/**
 * Options for code generation beyond format selection.
 */
type CodeGeneratorOptions = {
    /**
     * Custom hook code to inject into the generated snippet.
     * Hooks are JavaScript/TypeScript code strings that will be
     * inserted at appropriate locations in the output.
     */
    hooks?: CodeGeneratorHooks;
    /**
     * Whether to include comments explaining each hook.
     * @default true
     */
    includeHookComments?: boolean;
};
declare function generateCodeSnippet(config: any, format?: CodeFormat, options?: CodeGeneratorOptions): string;

/**
 * The current version of the @runtypelabs/persona package.
 * This is automatically derived from package.json.
 */
declare const VERSION: string;

declare class PluginRegistry {
    private plugins;
    /**
     * Register a plugin
     */
    register(plugin: AgentWidgetPlugin): void;
    /**
     * Unregister a plugin
     */
    unregister(pluginId: string): void;
    /**
     * Get all plugins sorted by priority
     */
    getAll(): AgentWidgetPlugin[];
    /**
     * Get plugins for a specific instance (from config)
     * Merges instance plugins with globally registered plugins
     */
    getForInstance(instancePlugins?: AgentWidgetPlugin[]): AgentWidgetPlugin[];
    /**
     * Clear all plugins
     */
    clear(): void;
}
declare const pluginRegistry: PluginRegistry;

/**
 * Context provided to component renderers
 */
interface ComponentContext {
    message: AgentWidgetMessage;
    config: AgentWidgetConfig;
    /**
     * Update component props during streaming
     */
    updateProps: (newProps: Record<string, unknown>) => void;
}
/**
 * Component renderer function signature
 */
type ComponentRenderer = (props: Record<string, unknown>, context: ComponentContext) => HTMLElement;
/**
 * Component registry for managing custom components
 */
declare class ComponentRegistry {
    private components;
    /**
     * Register a custom component
     */
    register(name: string, renderer: ComponentRenderer): void;
    /**
     * Unregister a component
     */
    unregister(name: string): void;
    /**
     * Get a component renderer by name
     */
    get(name: string): ComponentRenderer | undefined;
    /**
     * Check if a component is registered
     */
    has(name: string): boolean;
    /**
     * Get all registered component names
     */
    getAllNames(): string[];
    /**
     * Clear all registered components
     */
    clear(): void;
    /**
     * Register multiple components at once
     */
    registerAll(components: Record<string, ComponentRenderer>): void;
}
/**
 * Global component registry instance
 */
declare const componentRegistry: ComponentRegistry;

/**
 * Represents a component directive extracted from JSON
 */
interface ComponentDirective {
    component: string;
    props: Record<string, unknown>;
    raw: string;
}
/**
 * Creates a parser that extracts component directives from JSON streams
 * This parser looks for objects with a "component" field and extracts
 * the component name and props incrementally as they stream in.
 */
declare function createComponentStreamParser(): {
    /**
     * Get the currently extracted component directive
     */
    getExtractedDirective: () => ComponentDirective | null;
    /**
     * Process a chunk of JSON and extract component directive if present
     */
    processChunk: (accumulatedContent: string) => ComponentDirective | null;
    /**
     * Reset the parser state
     */
    reset: () => void;
};
/**
 * Type guard to check if an object is a component directive
 */
declare function isComponentDirectiveType(obj: unknown): obj is ComponentDirective;

type MessageTransform = (context: {
    text: string;
    message: AgentWidgetMessage;
    streaming: boolean;
    raw?: string;
}) => string;
type MessageActionCallbacks = {
    onCopy?: (message: AgentWidgetMessage) => void;
    onFeedback?: (feedback: AgentWidgetMessageFeedback) => void;
};
declare const createTypingIndicator: () => HTMLElement;
/**
 * Create message action buttons (copy, upvote, downvote)
 */
declare const createMessageActions: (message: AgentWidgetMessage, actionsConfig: AgentWidgetMessageActionsConfig, callbacks?: MessageActionCallbacks) => HTMLElement;
/**
 * Create standard message bubble
 * Supports layout configuration for avatars, timestamps, and visual presets
 */
declare const createStandardBubble: (message: AgentWidgetMessage, transform: MessageTransform, layoutConfig?: AgentWidgetMessageLayoutConfig, actionsConfig?: AgentWidgetMessageActionsConfig, actionCallbacks?: MessageActionCallbacks) => HTMLElement;
/**
 * Create bubble with custom renderer support
 * Uses custom renderer if provided in layout config, otherwise falls back to standard bubble
 */
declare const createBubbleWithLayout: (message: AgentWidgetMessage, transform: MessageTransform, layoutConfig?: AgentWidgetMessageLayoutConfig, actionsConfig?: AgentWidgetMessageActionsConfig, actionCallbacks?: MessageActionCallbacks) => HTMLElement;

/**
 * Options for component middleware
 */
interface ComponentMiddlewareOptions {
    config: AgentWidgetConfig;
    message: AgentWidgetMessage;
    transform: MessageTransform;
    onPropsUpdate?: (props: Record<string, unknown>) => void;
}
/**
 * Renders a component directive into an HTMLElement
 */
declare function renderComponentDirective(directive: ComponentDirective, options: ComponentMiddlewareOptions): HTMLElement | null;
/**
 * Creates middleware that processes component directives from streamed JSON
 */
declare function createComponentMiddleware(): {
    /**
     * Process accumulated content and extract component directive
     */
    processChunk: (accumulatedContent: string) => ComponentDirective | null;
    /**
     * Get the currently extracted directive
     */
    getDirective: () => ComponentDirective | null;
    /**
     * Reset the parser state
     */
    reset: () => void;
};
/**
 * Checks if a message contains a component directive in its raw content
 */
declare function hasComponentDirective(message: AgentWidgetMessage): boolean;
/**
 * Extracts component directive from a complete message
 */
declare function extractComponentDirectiveFromMessage(message: AgentWidgetMessage): ComponentDirective | null;

/**
 * Default light theme colors
 */
declare const DEFAULT_LIGHT_THEME: AgentWidgetTheme;
/**
 * Default dark theme colors
 */
declare const DEFAULT_DARK_THEME: AgentWidgetTheme;
/**
 * Default widget configuration
 * Single source of truth for all default values
 */
declare const DEFAULT_WIDGET_CONFIG: Partial<AgentWidgetConfig>;
/**
 * Helper to deep merge user config with defaults
 * This ensures all default values are present while allowing selective overrides
 */
declare function mergeWithDefaults(config?: Partial<AgentWidgetConfig>): Partial<AgentWidgetConfig>;

interface HeaderElements {
    header: HTMLElement;
    iconHolder: HTMLElement;
    headerTitle: HTMLElement;
    headerSubtitle: HTMLElement;
    closeButton: HTMLButtonElement;
    closeButtonWrapper: HTMLElement;
    clearChatButton: HTMLButtonElement | null;
    clearChatButtonWrapper: HTMLElement | null;
}
interface HeaderBuildContext {
    config?: AgentWidgetConfig;
    showClose?: boolean;
    onClose?: () => void;
    onClearChat?: () => void;
}
/**
 * Build the header section of the panel.
 * Extracted for reuse and plugin override support.
 */
declare const buildHeader: (context: HeaderBuildContext) => HeaderElements;
/**
 * Attach header elements to the container, handling placement modes.
 */
declare const attachHeaderToContainer: (container: HTMLElement, headerElements: HeaderElements, config?: AgentWidgetConfig) => void;

interface ComposerElements {
    footer: HTMLElement;
    suggestions: HTMLElement;
    composerForm: HTMLFormElement;
    textarea: HTMLTextAreaElement;
    sendButton: HTMLButtonElement;
    sendButtonWrapper: HTMLElement;
    micButton: HTMLButtonElement | null;
    micButtonWrapper: HTMLElement | null;
    statusText: HTMLElement;
    attachmentButton: HTMLButtonElement | null;
    attachmentButtonWrapper: HTMLElement | null;
    attachmentInput: HTMLInputElement | null;
    attachmentPreviewsContainer: HTMLElement | null;
    actionsRow: HTMLElement;
    leftActions: HTMLElement;
    rightActions: HTMLElement;
}
interface ComposerBuildContext {
    config?: AgentWidgetConfig;
    onSubmit?: (text: string) => void;
    disabled?: boolean;
}
/**
 * Build the composer/footer section of the panel.
 * Extracted for reuse and plugin override support.
 */
declare const buildComposer: (context: ComposerBuildContext) => ComposerElements;

interface HeaderLayoutContext {
    config: AgentWidgetConfig;
    showClose?: boolean;
    onClose?: () => void;
    onClearChat?: () => void;
}
type HeaderLayoutRenderer = (context: HeaderLayoutContext) => HeaderElements;
/**
 * Build default header layout
 * Full header with icon, title, subtitle, clear chat, and close button
 */
declare const buildDefaultHeader: HeaderLayoutRenderer;
/**
 * Build minimal header layout
 * Simplified layout with just title and close button
 */
declare const buildMinimalHeader: HeaderLayoutRenderer;
/**
 * Build expanded header layout
 * Full branding area with additional space for custom content
 */
declare const buildExpandedHeader: HeaderLayoutRenderer;
/**
 * Header layout registry
 * Maps layout names to their renderer functions
 */
declare const headerLayouts: Record<string, HeaderLayoutRenderer>;
/**
 * Get header layout renderer by name
 */
declare const getHeaderLayout: (layoutName: string) => HeaderLayoutRenderer;
/**
 * Build header based on layout configuration
 * Applies layout config settings to determine which layout to use
 */
declare const buildHeaderWithLayout: (config: AgentWidgetConfig, layoutConfig?: AgentWidgetHeaderLayoutConfig, context?: Partial<HeaderLayoutContext>) => HeaderElements;

export { type AgentWidgetAttachmentsConfig, type AgentWidgetAvatarConfig, AgentWidgetClient, type AgentWidgetConfig, type AgentWidgetController, type AgentWidgetCustomFetch, type AgentWidgetEvent, type AgentWidgetFeatureFlags, type AgentWidgetHeaderLayoutConfig, type AgentWidgetHeadersFunction, type AgentWidgetInitHandle, type AgentWidgetInitOptions, type AgentWidgetLauncherConfig, type AgentWidgetLayoutConfig, type AgentWidgetMarkdownConfig, type AgentWidgetMarkdownOptions, type AgentWidgetMarkdownRendererOverrides, type AgentWidgetMessage, type AgentWidgetMessageActionsConfig, type AgentWidgetMessageFeedback, type AgentWidgetMessageLayoutConfig, type AgentWidgetPlugin, type AgentWidgetRequestPayload, type AgentWidgetSSEEventParser, type AgentWidgetSSEEventResult, AgentWidgetSession, type AgentWidgetSessionStatus, type AgentWidgetStreamParser, type AgentWidgetStreamParserResult, type AgentWidgetTheme, type AgentWidgetTimestampConfig, AttachmentManager, type AttachmentManagerConfig, type CSATFeedbackOptions, type ClientChatRequest, type ClientFeedbackRequest, type ClientFeedbackType, type ClientInitResponse, type ClientSession, type CodeFormat, type CodeGeneratorHooks, type CodeGeneratorOptions, type ComponentContext, type ComponentDirective, type ComponentRenderer, type ComposerBuildContext, type ComposerElements, type ContentPart, DEFAULT_DARK_THEME, DEFAULT_LIGHT_THEME, DEFAULT_WIDGET_CONFIG, type HeaderBuildContext, type HeaderElements, type HeaderLayoutContext, type HeaderLayoutRenderer, type HeaderRenderContext, type ImageContentPart, type InjectAssistantMessageOptions, type InjectMessageOptions, type InjectSystemMessageOptions, type InjectUserMessageOptions, type MarkdownProcessorOptions, type MessageActionCallbacks, type MessageContent, type MessageRenderContext, type MessageTransform, type NPSFeedbackOptions, type PendingAttachment, type SlotRenderContext, type SlotRenderer, type TextContentPart, VERSION, type WidgetLayoutSlot, attachHeaderToContainer, buildComposer, buildDefaultHeader, buildExpandedHeader, buildHeader, buildHeaderWithLayout, buildMinimalHeader, componentRegistry, createActionManager, createAgentExperience, createBubbleWithLayout, createCSATFeedback, createComponentMiddleware, createComponentStreamParser, createDirectivePostprocessor, createFlexibleJsonStreamParser, createImagePart, createJsonStreamParser, createLocalStorageAdapter, createMarkdownProcessor, createMarkdownProcessorFromConfig, createMessageActions, createNPSFeedback, createPlainTextParser, createRegexJsonParser, createStandardBubble, createTextPart, createTypingIndicator, createXmlParser, initAgentWidget as default, defaultActionHandlers, defaultJsonActionParser, directivePostprocessor, escapeHtml, extractComponentDirectiveFromMessage, fileToImagePart, generateAssistantMessageId, generateCodeSnippet, generateMessageId, generateUserMessageId, getDisplayText, getHeaderLayout, getImageParts, hasComponentDirective, hasImages, headerLayouts, initAgentWidget, isComponentDirectiveType, markdownPostprocessor, mergeWithDefaults, normalizeContent, pluginRegistry, renderComponentDirective, validateImageFile };
