/** * The atomic unit — a single message in a chat session. * * Composed of role + content + optional rich-data slots (attachments, * sources, tool calls). Serializable: no Date, no Map. */ import type { ChatAttachment, ChatSource } from './attachment'; import type { MessageBlock } from './block'; import type { ChatMessageMetrics } from './events'; import type { ChatPersona, ChatRole } from './persona'; import type { ChatToolCall } from './tool-call'; export interface ChatMessage { id: string; role: ChatRole; content: string; /** epoch ms — serializable. */ createdAt: number; /** * Stable per-session transcript position, supplied by hosts whose backend * keys messages by an absolute sequence (e.g. a monotonic `chat_history.seq`). * The synthetic `id` is a UI key only; `seq` is the durable handle the host * passes back to an authoritative edit/truncate API. Optional — engines that * don't track a backend seq leave it undefined. */ seq?: number; isStreaming?: boolean; isError?: boolean; /** Bumps on edit so memo keys invalidate. */ version?: number; /** Per-message persona override (multi-user / multi-bot). Falls back to * `ChatConfig.user` / `ChatConfig.assistant` when absent. */ sender?: ChatPersona; /** Simple status indicator above message ("Searching knowledge base..."). */ toolActivity?: string; toolCalls?: ChatToolCall[]; attachments?: ChatAttachment[]; /** Rich tool-component blocks rendered after the message body. */ blocks?: MessageBlock[]; sources?: ChatSource[]; tokensIn?: number; tokensOut?: number; /** Per-turn metrics (from a `message_metrics` stream event). */ metrics?: ChatMessageMetrics; /** Concrete model the request resolved to (from a `resolved_model` event). */ resolvedModel?: string; }