import type React from 'react'; import type { ButtonView, PopupPlacement } from '@gravity-ui/uikit'; import { ActionConfig } from "./common.js"; import { ToolMessageProps } from "./tool.js"; /** * Context object passed to popup content generator function */ export interface ActionPopupContext { /** Update popup content without closing it */ setContent: (content: React.ReactNode) => void; /** Update popup title dynamically */ setTitle: (title: string | undefined) => void; /** Update popup subtitle dynamically */ setSubtitle: (subtitle: string | undefined) => void; /** Programmatically close the popup */ closePopup: () => void; } /** * Configuration for action popup */ export interface ActionPopupConfig { /** Function that generates popup content */ getContent: (message: TMessage, context: ActionPopupContext) => React.ReactNode; /** Optional popup title (can be overridden by actionPopupProps) */ title?: string; /** Optional popup subtitle (can be overridden by actionPopupProps) */ subtitle?: string; /** Optional popup placement (can be overridden by actionPopupProps) */ placement?: PopupPlacement; } export type BaseMessageActionConfig = ActionConfig & { /** Optional popup configuration for this action */ popup?: ActionPopupConfig; }; /** * BaseMessage action can be either: * - BaseMessageActionConfig object with properties (including type for default icons) * - React.ReactNode for fully custom content */ export type BaseMessageAction = BaseMessageActionConfig | React.ReactNode; export type UserRating = 'like' | 'dislike'; export declare enum BaseMessageActionType { Copy = "copy", Edit = "edit", Retry = "retry", Like = "like", Dislike = "dislike", Delete = "delete" } /** * Default action descriptor for message action buttons. * Generic over the message type to provide typed onClick handler. */ export type DefaultMessageAction = { type?: string; onClick: (message: TMessage) => void; icon?: React.ReactNode; /** * Arbitrary button content (text, badges, or any ReactNode). * Takes precedence over `icon` when both are provided. * Can be a static ReactNode or a render function that receives the message, * allowing dynamic content based on message data (e.g. token count from metadata). */ children?: React.ReactNode | ((message: TMessage) => React.ReactNode); label?: string; view?: ButtonView; /** Optional popup configuration for this action */ popup?: ActionPopupConfig; }; /** * React component used to render extra contextual info for a message * (e.g. token count, latency). Receives the message as a `message` prop. */ export type MessageExtraInfoComponent = React.ComponentType<{ message: TMessage; }>; export type BaseMessageProps = { children: React.ReactNode; role: TMessageRole; actions?: BaseMessageAction[]; /** Extra info node rendered alongside the action buttons (e.g. token count). */ extraInfo?: React.ReactNode; userRating?: UserRating; timestamp?: string; showTimestamp?: boolean; showActionsOnHover?: boolean; className?: string; qa?: string; /** Callback when action with popup config is clicked */ onActionPopup?: (action: BaseMessageActionConfig, anchorElement: HTMLElement) => void; }; export type TMessageMetadata = Record; /** Context passed when a message is sent via suggestion click */ export type TSuggestionContext = { id?: string; data?: Record; }; export type TSubmitData = { content: string; attachments?: File[]; metadata?: TMessageMetadata; /** Set when the message is sent by clicking a suggestion */ suggestion?: TSuggestionContext; }; export type TMessageRole = 'user' | 'assistant' | 'system'; export type TMessageContent = { id?: string; type: Type; data: Data; }; export type TextMessageContentData = { text: string; }; export type TextMessageContent = TMessageContent<'text', TextMessageContentData>; export type ThinkingMessageContentData = { title?: string; content: string | string[]; status: 'thinking' | 'thought'; defaultExpanded?: boolean; showStatusIndicator?: boolean; onCopyClick?: () => void; enabledCopy?: boolean; className?: string; qa?: string; }; export type ThinkingMessageContent = TMessageContent<'thinking', ThinkingMessageContentData>; export type ToolMessageContentData = ToolMessageProps & { /** MCP arguments, pretty-printed JSON. Read by AIStudioChat's tool renderer. */ mcpRequest?: string; /** MCP output (or error), pretty-printed JSON. Read by AIStudioChat's tool renderer. */ mcpResponse?: string; }; export type ToolMessageContent = TMessageContent<'tool', ToolMessageContentData>; export type TDefaultMessageContent = TextMessageContent | ThinkingMessageContent | ToolMessageContent; export type TMessageContentUnion = TDefaultMessageContent | TCustomMessageContent; export type TAssistantMessageContent = string | TMessageContentUnion | TMessageContentUnion[]; export type TBaseMessage = Pick & { id?: string; error?: unknown; metadata?: Metadata; }; export type FileAttachment = { id: string; name: string; mimeType?: string; }; export type TUserMessage = TBaseMessage & { role: 'user'; content: string; format?: 'plain' | 'markdown'; avatarUrl?: string; /** Base64 data URLs or regular image URLs attached to the message */ images?: string[]; /** File attachments sent with this message */ fileAttachments?: FileAttachment[]; }; export type TAssistantMessage = TBaseMessage & { role: 'assistant'; content: TAssistantMessageContent; userRating?: UserRating; }; export type TChatMessage = TUserMessage | TAssistantMessage;