# AI chat

A complete AI chat with streamed markdown answers, folding reasoning, tool chips, citations, and a model switcher.

- ID: `ai-chat`
- Import: `animui/ai-chat`
- Category: block
- Runtime exports: `AiChat`, `sampleResponder`, `StreamText`
- Declaration: `types/pro/ai-chat.d.ts`
- Type provenance: reconstructed-from-docs-and-runtime
- Related: ai-composer, chat-thread, agent-run, support-conversation, text-shimmer

```tsx
import { AiChat } from 'animui/ai-chat';
```

This import example is not a complete render recipe: read the declaration below and its local references for required props, data, callbacks and provider context. Use `animui info ai-chat` to resolve the local declaration graph. Global setup is in `llms.txt`.

```ts
/** Reconstructed from saved Arc documentation and runtime binding evidence; original TypeScript source was unavailable. */
import type { ComponentType, ReactNode, CSSProperties, Ref, ButtonHTMLAttributes, HTMLAttributes, ReactElement } from 'react';

export interface ChatMessage { id: string; role: 'user' | 'assistant' | 'system'; text: string; }
export interface ChatRequest { conversationId: string | null; messages: ChatMessage[]; prompt: string; attachments: string[]; model: string; }
export type ChatStreamEvent = { type: 'thinking'; text: string } | { type: 'tool'; tool: { id: string; name: string; status?: string } } | { type: 'sources'; sources: { title: string; url: string }[] } | { type: 'text'; text: string };
export type ChatResponder = (request: ChatRequest, signal: AbortSignal) => AsyncIterable<ChatStreamEvent>;
export interface AiChatProps {
  defaultConversations?: string | number | boolean | ReactNode;
  onConversationsChange?: () => void;
  activeId?: string;
  defaultActiveId?: string;
  onActiveChange?: () => void;
  models?: string | number | boolean | ReactNode;
  model?: string | number | boolean | ReactNode;
  defaultModel?: string | number | boolean | ReactNode;
  onModelChange?: () => void;
  sidebarOpen?: string | number | boolean | ReactNode;
  defaultSidebarOpen?: string | number | boolean | ReactNode;
  onSidebarOpenChange?: () => void;
  suggestions?: string | number | boolean | ReactNode;
  respond?: string | number | boolean | ReactNode;
  greeting?: string | number | boolean | ReactNode;
  notice?: string | number | boolean | ReactNode;
  user?: string | number | boolean | ReactNode;
  className?: string;
}

export declare const AiChat: ComponentType<AiChatProps>;
export declare const sampleResponder: ChatResponder;
export interface StreamTextProps {
  text?: string | number | boolean | ReactNode;
  streaming?: string | number | boolean | ReactNode;
  reduced?: string | number | boolean | ReactNode;
  className?: string;
}

export declare const StreamText: ComponentType<StreamTextProps>;

export default AiChat;
```
