feat: Phase 2 — chat templates, reasoning parser, collapsible TUI, mouse support

- internal/llama/template.go: ChatML/Llama3 template engine with stop tokens
- internal/agent/reasoning.go: parse <think>/<reasoning> tags from LLM output
- companion/promptbuilder.go: output structured BuildResult, add date/time context
- agent/agent.go: wire templates + reasoning split into message loop
- storage: add reasoning TEXT column to messages table + migration
- channel/tui.go: collapsible reasoning (tab toggle), mouse scroll, polished dimmed style
- config: CHAT_TEMPLATE env var (chatml|llama3|none)
- plan.md: mark Phase 2 complete, add themes TODO
This commit is contained in:
2026-06-10 09:42:45 +03:30
parent f57b42fd6e
commit 3895ca68c0
14 changed files with 327 additions and 144 deletions

31
plan.md
View File

@@ -142,31 +142,28 @@ CREATE TABLE context_state (
### Chat Template Engine
- [ ] `internal/llama/template.go` — chat template formatter:
- [x] `internal/llama/template.go` — chat template formatter:
- ChatML: `<|im_start|>system\n...<|im_end|>\n<|im_start|>user\n...<|im_end|>\n<|im_start|>assistant\n`
- Llama 3 instruct: `<|begin_of_text|><|start_header_id|>system<|end_header_id|>\n...<|eot_id|>`
- DeepSeek R1: with `...` support
- Configurable via env `CHAT_TEMPLATE=chatml` (default)
- [ ] Refactor `companion/promptbuilder.go` to output structured segments (system context, personality, relationship, conversation history, user message)
- [ ] Let template.go wrap those segments in the chosen format
- [ ] Add `stop` tokens per template (`<|im_end|>`, `<|eot_id|>`)
- [ ] **Test:** "hi" produces just the response, no meta-text
- Configurable via env `CHAT_TEMPLATE=chatml|llama3|none` (default: chatml)
- [x] Refactor `companion/promptbuilder.go` to output structured `BuildResult`
- [x] Let template.go wrap those segments in the chosen format
- [x] Add `stop` tokens per template (`<|im_end|>`, `<|eot_id|>`)
### Reasoning Parser
- [ ] `internal/agent/reasoning.go` — parse `...`, `...`, or custom tags from model output
- [ ] Split response into `Reasoning` (thoughts) and `Content` (final answer)
- [ ] Store both separately in the `messages` table
- [ ] Feed only `Content` back into context window (reasoning is discarded after display)
- [x] `internal/agent/reasoning.go` — parse `<think>`, `<reasoning>`, `<reason>`, `<thinking>` tags
- [x] Split response into `Reasoning` (thoughts) and `Content` (final answer)
- [x] Store both separately in the `messages` table
- [x] Feed only `Content` back into context window (reasoning is discarded after display)
### TUI Enhancement
- [ ] Render reasoning in a collapsible section:
- Header: "💭 (or `...`) with reasoning snippet
- On click/expand: show full reasoning in dimmed/italic style (`lipgloss.Color("#6B7280")`)
- [ ] Render final answer in normal assistant style (green/bold)
- [ ] Reasoning hidden by default, toggle with a keybinding (e.g., `tab`)
- [ ] **Test:** Send a prompt that triggers reasoning, verify collapsible display
- [x] Render reasoning in a collapsible section (dimmed/italic, `lipgloss.Color("#6B7280")`)
- [x] Render final answer in normal assistant style (green/bold)
- [x] Reasoning hidden by default, toggle with `tab` key
- [x] Mouse support (`tea.WithMouseCellMotion()` + viewport scroll)
- [ ] User-selectable themes (env var or file) for colors, reasoning style, input bar
---