- fix(web): Svelte 5 identity-based reactivity broke text_delta streaming — immutable message objects in all three chat handlers so text streams live - feat(web): streaming cursor + inline status indicator merged into message flow - feat(web): expandable inline tool call cards in chat thread - feat(web): merge Plan + Event log into one backbone Activity timeline — filled status nodes, branch stubs, auto-scroll follow mode, per-session activityLog, compact for the rail - fix(nomos): add X-Accel-Buffering:no to /chat SSE (proxy buffering) - fix(nomos): plan step auto-close SQL param bug (store.go) - polish: timestamps, role labels, code copy button, table overflow, min window size, delete AgentIndicator/ActivityTimeline dead code
80 lines
3.1 KiB
Markdown
80 lines
3.1 KiB
Markdown
# 2026-07-21 Chat window full polish
|
|
|
|
## 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/...`
|