/** * Type definitions for @geepers/chat */ // ========== Provider ========== export type Provider = | 'xai' | 'anthropic' | 'openai' | 'cohere' | 'mistral' | 'perplexity' | 'huggingface' | 'gemini' | 'ollama'; export interface ProviderConfig { /** Model identifier string sent to the API Gateway */ model: string; /** Human-readable display label */ label: string; } // ========== Messages ========== export type MessageRole = 'user' | 'assistant' | 'system'; export interface Message { /** Unique message identifier */ id: string; /** Sender role */ role: MessageRole; /** Message text content */ content: string; /** Unix timestamp (ms) when message was created */ timestamp: number; /** Provider that generated this message (assistant only) */ provider?: Provider; } // ========== Conversations ========== export interface ConversationRecord { /** Unique conversation identifier (UUID v4) */ id: string; /** Title derived from first user message */ title: string; /** Ordered message history (excludes system prompt) */ messages: Message[]; /** Active provider when conversation was saved */ provider: Provider; /** System prompt for this conversation (may be empty) */ systemPrompt: string; /** Unix timestamp (ms) when conversation was created */ createdAt: number; /** Unix timestamp (ms) when conversation was last modified */ updatedAt: number; } // ========== Events ========== export type ChatEventType = | 'message' | 'stream-chunk' | 'stream-start' | 'stream-end' | 'error' | 'conversation-change'; export interface MessageEvent { type: 'message'; message: Message; } export interface StreamChunkEvent { type: 'stream-chunk'; chunk: string; accumulated: string; messageId: string; } export interface StreamStartEvent { type: 'stream-start'; messageId: string; } export interface StreamEndEvent { type: 'stream-end'; message: Message; } export interface ErrorEvent { type: 'error'; error: Error; } export interface ConversationChangeEvent { type: 'conversation-change'; conversationId: string | null; } export type ChatEvent = | MessageEvent | StreamChunkEvent | StreamStartEvent | StreamEndEvent | ErrorEvent | ConversationChangeEvent; export type ChatEventHandler = (event: T) => void; // ========== Configuration ========== export interface WelcomeHint { /** Short label shown on the hint chip button */ label: string; /** Full text sent as the message when the hint is clicked */ prompt: string; } export type ThemeMode = 'light' | 'dark' | 'auto'; export interface ChatConfig { /** * API Gateway base URL. * Defaults to 'https://api.dr.eamer.dev/v1' if not provided. */ gateway?: string; /** API key sent as X-API-Key header. Falls back to localStorage 'api_key' if not set. */ apiKey?: string; /** Initial provider selection. Defaults to 'xai'. */ provider?: Provider; /** Initial model override. If omitted the default from MODELS[provider] is used. */ model?: string; /** System prompt prepended to every conversation. */ systemPrompt?: string; /** Initial conversation ID to restore. Loads from localStorage if found. */ conversationId?: string; /** Theme preference. Defaults to 'auto' (respects OS preference). */ theme?: ThemeMode; /** * Hint chips shown on the welcome screen. * Pass an empty array to disable the welcome screen entirely. */ welcomeHints?: WelcomeHint[]; /** * localStorage key prefix for conversation persistence. * Defaults to 'gchat_conversations'. Override to namespace multiple instances. */ storageKey?: string; // ---- Lifecycle callbacks ---- /** Called when an assistant message finishes streaming. */ onMessage?: (message: Message) => void; /** Called when an error occurs (network, API, or parsing). */ onError?: (error: Error) => void; /** Called immediately when a stream begins. */ onStreamStart?: (messageId: string) => void; /** Called when a stream finishes (including aborted streams). */ onStreamEnd?: (message: Message) => void; }