import type { ActionType } from '../modern-chat-input/ModernChatInput'; import type { Message, Conversation, Suggestion, AssistantTab, AssistantMode, SearchResult, MockResponse } from './types'; export interface UseAssistantProps { /** Layout mode for the assistant panel */ mode?: AssistantMode; /** Controlled expansion state */ isExpanded?: boolean; /** Toggle callback for controlled expansion */ onToggle?: () => void; /** Initially selected tab */ defaultTab?: AssistantTab; /** Enables demo mode with mock AI responses */ demoMode?: boolean; /** Custom mock responses for demo mode */ customResponses?: MockResponse[]; /** Pre-loaded messages to hydrate an existing conversation */ initialMessages?: Message[]; /** Previously saved conversations */ savedConversations?: Conversation[]; /** Suggested prompts shown in the empty state */ suggestions?: Suggestion[]; /** Callback fired when the user sends a message */ onSendMessage?: (message: string) => void; /** Whether the assistant is currently processing a response */ isProcessing?: boolean; /** * Custom response generator — overrides demo mode defaults. * `action` is set when the user sent the message via one of the chat input's * quick actions (`'document' | 'podcast' | 'search'`, see `ModernChatInput`), * `null`/`undefined` for a plain typed message. Use it to decide whether to * populate action-specific fields — e.g. only set `searchResults`/ * `searchSources`/`attachmentType: 'search'` when `action === 'search'`, so * the search-results card doesn't appear for ordinary conversation. */ responseGenerator?: (message: string, action?: ActionType) => Promise> | string | Partial; /** * Streaming response generator — takes priority over `responseGenerator`/`demoMode` * when provided. Each yielded `Partial` replaces the current state of the * in-progress assistant message (typically a growing `content` snapshot, not a delta — * accumulate deltas yourself before yielding, the same way you'd update local state). * A placeholder message is inserted immediately and merged on every yield, so the * reply grows incrementally instead of appearing as a single block once done. * `action` has the same meaning as in `responseGenerator` above. */ streamResponseGenerator?: (message: string, action?: ActionType) => AsyncGenerator, void, unknown>; /** Extended suggestions shown when the user clicks "More suggestions" */ richSuggestions?: Suggestion[]; /** Callback fired when the user clicks a rich suggestion */ onRichAction?: (actionId: string, actionText: string) => void; /** Callback fired when the user rates a message */ onEvaluation?: (messageId: string, type: 'like' | 'dislike', reason?: string) => void; /** Negative feedback categories shown in the dislike dropdown */ feedbackOptions?: string[]; } export interface UseAssistantReturn { isFullPage: boolean; isExpanded: boolean; isMobile: boolean; abaSelecionada: AssistantTab; setAbaSelecionada: (tab: AssistantTab) => void; mensagens: Message[]; setMensagens: React.Dispatch>; mensagem: string; setMensagem: (value: string) => void; conversas: Conversation[]; conversaAtual: string | null; conversasFiltradas: Conversation[]; copiedId: string | null; generatingPodcastId: string | null; executingCommand: string | null; savedSearches: string[]; editingDocument: { content: string; title: string; } | null; setEditingDocument: (doc: { content: string; title: string; } | null) => void; showMoreSuggestions: boolean; setShowMoreSuggestions: (show: boolean) => void; evaluationState: { isOpen: boolean; messageId: string | null; type: 'dislike' | null; category?: string | null; reason: string; }; setEvaluationState: React.Dispatch>; sugestoes: Suggestion[]; messagesEndRef: React.RefObject; fileInputRef: React.RefObject; audioInputRef: React.RefObject; handleToggle: () => void; handleExpandWithTab: (tab: AssistantTab) => void; handleEnviarMensagem: (arg?: string | ActionType) => Promise; handleToggleFavorite: (messageId: string) => void; handleCopyMessage: (content: string, messageId: string) => Promise; handleGeneratePodcast: (messageId: string, content: string) => Promise; handleDownloadDocument: (content: string, fileName: string) => void; handleDownloadPodcast: (audioUrl: string, fileName: string) => void; handleEditDocument: (content: string, title: string) => void; handleNovaConversa: () => void; handleSelecionarConversa: (conversaId: string) => void; handleToggleFavoritaConversa: (conversaId: string) => void; handleOpenSearchResult: (result: SearchResult) => void; handleExecuteSearchCommand: (commandId: string, searchTerm: string, results: SearchResult[], messageId: string) => Promise; handleRichSuggestionClick: (suggestion: Suggestion) => void; handleEvaluationClick: (messageId: string, type: 'like' | 'dislike') => void; openFeedbackDialog: (messageId: string, category: string | null) => void; handleSubmitDislike: () => void; } /** * `useAssistant` — Headless hook for the XerticaAssistant component. * * Encapsulates all state management and business logic for the AI assistant panel. * Use this hook when you need to build a fully custom assistant UI while reusing * the same state logic as the default `XerticaAssistant` component. * * @example * ```tsx * import { useAssistant } from 'xertica-ui/assistant'; * * function MyCustomAssistant() { * const { * mensagens, * mensagem, * setMensagem, * handleEnviarMensagem, * isExpanded, * handleToggle, * } = useAssistant({ demoMode: true }); * * return ( *
* {mensagens.map(msg =>

{msg.content}

)} * setMensagem(e.target.value)} /> * *
* ); * } * ``` */ export declare function useAssistant({ mode, isExpanded: controlledIsExpanded, onToggle, defaultTab, demoMode, customResponses, initialMessages, savedConversations, suggestions: propSuggestions, onSendMessage, isProcessing, responseGenerator, streamResponseGenerator, richSuggestions: _richSuggestions, onRichAction, onEvaluation, }?: UseAssistantProps): UseAssistantReturn;