Messages
Message rendering with markdown, citations, and tool results.
Message Grouping
The MessageList component groups messages into conversation turns:
User message
├── Tool call message(s) (optional, collapsed)
└── Assistant response message
User message
└── Assistant response messageMessages are grouped by linking assistant and tool messages back to their parent user message. The grouping logic is memoized to avoid expensive recomputation on every render.
Message Types
User Messages
// Renders:
// - Message content (editable inline)
// - Copy, Edit, Regenerate action buttonsUsers can edit a message inline and regenerate the AI response from that point.
Assistant Messages
// Renders:
// - Markdown content via MessageMarkdown
// - Location tags (clickable → map)
// - Numbered inline citations and their sources (if RAG results present)
// - Copy, thumbs-up and thumbs-down buttonsTool Messages
// Renders:
// - Collapsed summary (e.g., "Searched knowledge base")
// - Expandable chain-of-thought showing tool inputs/outputs
// - Parsed citation sources for RAG resultsTool messages are collapsed by default. Expanding shows the raw tool call details.
Markdown Rendering
MessageMarkdown renders AI responses with rich formatting:
<ReactMarkdown
remarkPlugins={[remarkGfm]}
components={{
p: ({ children }) => <p>{processLocationTags(children)}</p>,
code: ({ children, className }) => <CodeBlock language={className} />,
table: ({ children }) => <div className="overflow-x-auto"><table>{children}</table></div>,
img: ({ src, alt }) => <Image src={src} alt={alt} />,
}}
/>Features:
- GitHub Flavored Markdown — tables, strikethrough, task lists
- Code blocks — syntax highlighting with Shiki
- Location tagging — scans text for location names, wraps in clickable
LocationTagcomponents - Responsive tables — horizontal scroll wrapper
Citation Sources
When the assistant uses the RAG tool, CitationSources parses the tool message JSON and displays sources:
┌─────────────────────────┬─────────────────────────┐
│ 📄 Product Guide.pdf │ 🌐 example.com/article │
│ Page 12, §Install │ Web article │
│ [View Document] │ [Open Link] │
├─────────────────────────┼─────────────────────────┤
│ 📹 YouTube Video │ 📄 Report.docx │
│ [02:34] timestamp │ Page 5, §Summary │
│ [Watch] │ [View Document] │
└─────────────────────────┴─────────────────────────┘Source types:
- File — Shows document name, page number, section heading. Click opens document viewer.
- Web URL — Shows URL. Click opens external link.
- YouTube — Shows video title with timestamp. Click opens video at timestamp.
Message Actions
| Action | Description |
|---|---|
| Copy | Copy message text to clipboard |
| Edit | Toggle inline editing mode, save with Enter |
| Regenerate | Re-invoke the AI for the user message |
| Expand tool | Show/hide tool call chain-of-thought |
Edit & Regenerate
When a user edits a message:
- Message enters edit mode (textarea replaces rendered text)
- User modifies and saves
POST .../messages/{id}/edit/stream/saves the new text and streams a new reply
When regenerating:
POST /api/workspaces/{ws}/chats/{session}/messages/regenerate/stream/Both stream like a new message, and the new reply becomes another branch of the user message; earlier replies are kept.
Ratings
Thumbs up or down on an assistant answer, with an optional reason, posts to .../messages/{id}/feedback/. A second click on the same thumb clears the rating. Ratings are per user, and show up in Langfuse when tracing is on.
Branching
If a message has multiple AI responses (from regeneration), the UI shows branch navigation:
◄ 1/3 ►Users can cycle through response branches to compare different AI outputs.