git mv staged the pre-edit index content; the status edits to these two files landed in the working tree but not the archive commit. Amending the status now so the archived copies reflect Implemented.
84 lines
3.4 KiB
Markdown
84 lines
3.4 KiB
Markdown
# 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/...`
|