feat: mark each speaker with a role icon in the transcript (#5)

This commit was merged in pull request #5.
This commit is contained in:
2026-10-03 21:03:26 +00:00
parent 31eb688455
commit d448a4377b
3 changed files with 30 additions and 2 deletions
+4
View File
@@ -150,6 +150,10 @@ A few decisions worth knowing about before you change things:
**Messages render oldest first, and the detail panel shows the whole thread.** Vicinae resets list selection to the first row on every model change, and streaming changes the model on every flush, so the selected row cannot be relied on to stay put while an answer arrives. Showing the thread keeps the live answer on screen regardless.
**Both panes are required, not a layout preference.** `Detail` accepts no typed input — `onSearchTextChange` exists only on `List`, `Grid`, `Form` and `Dropdown` — so a detail-only chat command would have nothing to type into. And list rows are a fixed single line, so full message text cannot render in the list. Input needs a `List`; full text needs a `Detail`. Dropping either pane breaks the feature.
**Speakers are marked with emoji, not icon images.** `👤` and `✨` prefix each message in the transcript. Vicinae's markdown renderer is minimal and there is no reliable way to inline an `icon://` reference into markdown, whereas plain text always renders.
**Streamed deltas are buffered in refs and flushed to state on a timer** (`FLUSH_INTERVAL_MS`). Re-rendering the transcript per token makes the launcher visibly janky.
**The logic layer has no Vicinae imports.** `agent.ts`, `ollama.ts`, `tools.ts` and friends are plain TypeScript, which is why they unit test without a runtime. A test enforces this.