Add markdown-to-HTML rendering for assistant messages using Markdig with HTML sanitization. Includes cached rendering to avoid lag during streaming, styled markdown elements (code blocks, tables, lists, blockquotes) within chat bubbles, and 18 unit tests covering rendering and XSS prevention. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
109 lines
4.0 KiB
Markdown
109 lines
4.0 KiB
Markdown
## Purpose
|
|
|
|
Define the chat interface — message display, input handling, auto-scroll, and routing.
|
|
|
|
## Requirements
|
|
|
|
### Requirement: Message display
|
|
|
|
The chat page SHALL display messages in a vertically scrolling list, with each message showing the sender role (user or assistant), the message content, and a visual distinction between user and assistant messages (e.g., alignment, color, or avatar). Assistant messages SHALL render content as formatted HTML converted from markdown; user messages SHALL display as plain text.
|
|
|
|
#### Scenario: User message displayed
|
|
|
|
- **WHEN** the user sends a message
|
|
- **THEN** the message appears in the message list aligned or styled to indicate it is from the user, rendered as plain text
|
|
|
|
#### Scenario: Assistant message displayed
|
|
|
|
- **WHEN** the assistant responds
|
|
- **THEN** the response appears in the message list with distinct styling from user messages, with markdown content rendered as formatted HTML
|
|
|
|
#### Scenario: Message ordering
|
|
|
|
- **WHEN** multiple messages exist in the conversation
|
|
- **THEN** messages are displayed in chronological order, oldest at top
|
|
|
|
### Requirement: Message input
|
|
|
|
The chat page SHALL provide a text input area at the bottom of the page where the user can type and submit messages.
|
|
|
|
#### Scenario: Submit via button
|
|
|
|
- **WHEN** the user types text and clicks the send button
|
|
- **THEN** the message is added to the conversation and the input is cleared
|
|
|
|
#### Scenario: Submit via Enter key
|
|
|
|
- **WHEN** the user types text and presses Enter
|
|
- **THEN** the message is submitted (same as clicking send)
|
|
|
|
#### Scenario: Empty input blocked
|
|
|
|
- **WHEN** the user attempts to send an empty or whitespace-only message
|
|
- **THEN** nothing is sent and no message is added
|
|
|
|
#### Scenario: Input disabled during streaming
|
|
|
|
- **WHEN** the assistant is currently streaming a response
|
|
- **THEN** the input field and send button are disabled until streaming completes
|
|
|
|
### Requirement: Thinking indicator
|
|
|
|
The chat page SHALL show a visual indicator while waiting for the first token from the assistant.
|
|
|
|
#### Scenario: Indicator shown during wait
|
|
|
|
- **WHEN** the user sends a message and the assistant has not yet started streaming
|
|
- **THEN** a thinking indicator (e.g., animated dots) is shown in the assistant message area
|
|
|
|
#### Scenario: Indicator replaced by content
|
|
|
|
- **WHEN** the first token arrives from the stream
|
|
- **THEN** the thinking indicator is replaced by the streamed text
|
|
|
|
### Requirement: Streaming AI response
|
|
|
|
The assistant SHALL reply with a real AI response streamed from the backend API, using the full conversation history as context. Tokens appear incrementally as they arrive.
|
|
|
|
#### Scenario: Bot replies with streamed AI response
|
|
|
|
- **WHEN** the user sends any message
|
|
- **THEN** the assistant message appears and grows token by token as the stream delivers text
|
|
|
|
#### Scenario: Full history sent with each request
|
|
|
|
- **WHEN** the user sends a message after prior exchanges
|
|
- **THEN** all previous user and assistant messages are included in the API request so the AI has conversational context
|
|
|
|
### Requirement: New chat button
|
|
|
|
The chat page SHALL provide a button to clear the current conversation and start a new one.
|
|
|
|
#### Scenario: User starts a new chat
|
|
|
|
- **WHEN** the user clicks the "New Chat" button
|
|
- **THEN** all messages are cleared and the empty state is shown
|
|
|
|
#### Scenario: New chat button disabled during streaming
|
|
|
|
- **WHEN** the assistant is currently streaming a response
|
|
- **THEN** the "New Chat" button is disabled
|
|
|
|
### Requirement: Auto-scroll
|
|
|
|
The message list SHALL automatically scroll to the newest message when a new message is added.
|
|
|
|
#### Scenario: New message scrolls into view
|
|
|
|
- **WHEN** a new message (user or assistant) is added to the conversation
|
|
- **THEN** the message list scrolls to the bottom so the new message is visible
|
|
|
|
### Requirement: Chat page is default route
|
|
|
|
The chat page SHALL be the default route (`/`) of the application.
|
|
|
|
#### Scenario: App opens to chat
|
|
|
|
- **WHEN** the user navigates to the root URL
|
|
- **THEN** the chat page is displayed
|