HyperSaaS
FrontendChat

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 message

Messages 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 buttons

Users 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 buttons

Tool Messages

// Renders:
// - Collapsed summary (e.g., "Searched knowledge base")
// - Expandable chain-of-thought showing tool inputs/outputs
// - Parsed citation sources for RAG results

Tool 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 LocationTag components
  • 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

ActionDescription
CopyCopy message text to clipboard
EditToggle inline editing mode, save with Enter
RegenerateRe-invoke the AI for the user message
Expand toolShow/hide tool call chain-of-thought

Edit & Regenerate

When a user edits a message:

  1. Message enters edit mode (textarea replaces rendered text)
  2. User modifies and saves
  3. 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.

On this page