# 2026-07-21 Chat window full polish **Status:** Implemented. Streaming affordance, inline tool rendering, message timestamps, code-copy buttons, and per-session store isolation all landed in `web/src/lib/components/ChatThread.svelte` + the chat stores (v0.8.x–0.10.x). ## Context After fixing the streaming reactivity bug and merging the double thinking indicator, the chat window still has structural UX gaps: no streaming affordance while text flows, tools never rendered inline, no timestamps, no code copy, cross-session store leaks in floating windows, and minor overflow/style holes. ## Decisions | Question | Answer | |---|---| | Streaming feel | Typing cursor (blinking ▍) + inline indicator | | Tool calls | Expandable inline tool cards in message flow | | Empty state | Minimal — title + tagline, no suggestions | | Dark theme | Keep neutral (skip) | | Scope | Full polish — everything | ## Changes ### P0.1 Streaming cursor - **File:** `web/src/lib/components/ChatThread.svelte` - Add a blinking block-cursor (▍) appended after rendered markdown when `streaming` is true and the last assistant message has text. - Keep the inline spinner + activity label for the empty-text state. - CSS: `@keyframes` blink, `0.8s` cycle, `primary` color, `inline-block`. ### P0.2 Tool call cards - **New:** `web/src/lib/components/ToolCallCard.svelte` - **Modify:** `ChatThread.svelte` - Render `msg.tools` as collapsible cards between text blocks. - Collapsed: tool icon + name + status (running/done/error). - Expanded: pretty-printed args + result/error in `pre` blocks. - Keep it minimal — one card per tool call, no grouping. - Wire `pendingApprovals` from `msg.pendingApprovals` as approval cards below the tool list. ### P1.3 Timestamps + role labels - **Modify:** `ChatThread.svelte`, `ChatMessage` interface - Add `created_at?: string` to `ChatMessage` (populated from `Message.created_at`). - Show small muted timestamp (HH:MM) on hover or inline next to role label. - Add tiny "You" / "Nomos" labels above bubbles (subtle, muted). ### P1.4 Code copy button - **Modify:** `ChatThread.svelte` prose styles - Wrap `pre` blocks in a relative container; add a copy button (clipboard icon, top-right, opacity-0 → visible on hover). - Use `navigator.clipboard.writeText`. ### P1.5 Table overflow + user bubble fix - **Modify:** `ChatThread.svelte` prose styles - Wrap tables in `overflow-x-auto` container. - Add `overflow-wrap: break-word` to user bubbles. ### P2.6 Cross-session fixes - **Modify:** `web/src/lib/stores/chat.ts`, `SessionChatWindow.svelte` - `chatErrors`: keep global for now (session-scoped errors are rare and the dismiss is manual anyway). - `activityLog`: **per-session** — the store in `activity.ts` already derives from messages; make `computeActivityLog` session-scoped so each floating window only sees its own activity. ### P2.7 Min window size - **Modify:** `web/src/lib/stores/windows.ts` (openTaskWindow) - Add `minWidth: 600, minHeight: 400` to chat window open call. ### P2.8 Cleanup - Delete `web/src/lib/components/AgentIndicator.svelte` (dead code). - Update stale comments in `SessionChatWindow.svelte` and `TaskContextPanel.svelte` that reference a "main Chat page." - Fix prose heading hierarchy: h1 = 1.15em, h2 = 1.1em, h3 = 1.05em. ## Verification - `npx eslint` on all changed files - `go vet ./cmd/nomos/...` - `go build -o /dev/null ./cmd/nomos/...`