showAvatar adds an avatar column; without avatar, it shows the name's initial.
- Keep provider-specific streaming state in the host and map it into
status. - Use stable ids from the conversation store, not array indexes.
- Keep
markdown on for assistant output; sanitize untrusted Markdown at the data boundary. - Describe reasoning, tool calls, attachments, and sources with
parts instead of custom HTML in content.
| Prop | Type | Default | Description |
|---|
messages | AiElementMessage[] | required | Transcript data, rendered in order. |
markdown | boolean | true | Renders bodies through TxMarkdownView. |
compact | boolean | false | Tightens message spacing. |
emptyText | string | 'No messages yet' | Empty-state copy when no message is renderable. |
showAvatar | boolean | false | Shows an avatar column for every message. |
typingLabel | string | - | Forwarded to each message: accessible name of the typing indicator. |
| Event | Params | Description |
|---|
open-source | (source: AiSourceItem) | Re-emitted from the message whose source was clicked. |
| Slot | Props | Description |
|---|
empty | - | Replaces the built-in empty state. |
default / avatar / markdown-renderer / tool-result | Same as TxAiMessage | Forwarded to every TxAiMessage. |
| Prop | Type | Default | Description |
|---|
message | AiElementMessage | required | The message to render. |
markdown | boolean | true | Renders the body through TxMarkdownView; false keeps plain text with its line breaks. |
compact | boolean | false | Compact row density and a smaller avatar. |
showAvatar | boolean | false | Shows the avatar. |
typingLabel | string | 'AI is typing' | Accessible name of the typing indicator. |
| Event | Params | Description |
|---|
open-source | (source: AiSourceItem) | Fires when a source in a sources part is clicked; navigation is prevented. |
| Slot | Props | Description |
|---|
default | { message } | Replaces the content region; for tool cards, attachments, or custom renderers. |
avatar | { message } | Replaces the avatar when showAvatar is on. |
markdown-renderer | { part, message, streaming } | Replaces a text part's rendering; streaming is true only for the last text part of a streaming message. |
tool-result | { part } | Replaces the result area of a tool-call part once it is done. |
| Field | Type | Default | Description |
|---|
id | string | required | Stable key. |
role | 'user' | 'assistant' | 'system' | 'tool' | required | Visual and semantic role. |
content | string | required | Text or Markdown source. |
createdAt | number | string | Date | - | The host's timestamp. |
name | string | - | Display name; falls back to You / AI / Tool / System. |
avatar | string | - | Avatar image URL. |
status | 'pending' | 'streaming' | 'complete' | 'error' | - | Message lifecycle state. |
parts | AiMessagePart[] | - | When non-empty, these parts render in order instead of content. |
type AiMessagePart =
| { type: 'text', text: string } // markdown-renderer slot or TxMarkdownView
| { type: 'reasoning', text: string, done?: boolean, durationMs?: number } // TxReasoningDisclosure
| AiToolCallPart // type: 'tool-call', rendered by TxToolCallCard
| { type: 'attachment', attachments: AiAttachment[] } // read-only TxAttachmentTray
| { type: 'sources', sources: AiSourceItem[] } // TxSources
- A message with empty
content is not rendered unless it has parts or its status is pending or streaming. - Such an empty message without
parts shows a typing indicator. TxAiConversation is an aria-live="polite" region: appended messages are announced without stealing focus.
- Source:
packages/tuffex/packages/components/src/ai-elements/.
查看源码packages/tuffex/packages/components/src/ai-elements/index.ts