Changeset 0.9.3 (#53)

This commit is contained in:
2026-02-23 23:55:22 +00:00
parent ac7c7c7d59
commit 90021157e6
20 changed files with 897 additions and 414 deletions

View File

@@ -2,6 +2,85 @@
All notable changes to Chat Switchboard.
## [0.9.3] — 2026-02-23
### Changed
- **Code blocks: button-driven collapse** — Replaced `<details>` wrapper with
inline collapse/expand toggle button in the code toolbar. Auto-collapses at
>15 lines with a fade mask; toggle available on all blocks >5 lines. User
can always expand/collapse regardless of threshold. Smooth CSS transition
instead of native `<details>` jump.
- **Thinking blocks: always visible** — Thinking blocks are always rendered in
the DOM regardless of the `showThinking` setting. The setting now controls
whether blocks start expanded (`<details open>`) or collapsed. User can
always click to toggle. Setting label updated to "Auto-expand thinking blocks".
### Added
- **Admin default model** — New `default_model` policy in Admin → Settings.
Dropdown populated from enabled models. When a user has no saved selection
(fresh login, cleared browser) or their saved model is no longer available,
the admin default is used before falling back to first visible. Resolution
chain: `localStorage → admin default → first visible`.
- **Reasoning/thinking support for OpenAI-compatible providers** — Models that
send `reasoning_content` in stream deltas (Grok, DeepSeek, etc.) now have
thinking blocks streamed live and persisted as `<think>` tags. Renders as
collapsible thinking blocks in both streaming and history views.
- **Favicon animation during generation** — Browser tab favicon pulses with
cascading dot opacity animation while a completion is in progress, restoring
to the static favicon when done.
- **Tool calls in message history** — Tool call metadata (name, arguments,
result, error status) is now persisted alongside assistant messages in the
database. History view renders tool calls as collapsed `<details>` blocks
showing "🔧 tool_name → done" with expandable input/output JSON.
- **Notes tool: "View note" link** — When a notes tool (`note_create`,
`note_update`, etc.) completes, a "📝 View note" button appears in both
the live streaming tool indicator and the history tool call block. Clicking
opens the Notes panel and navigates directly to the note.
- **Notes panel: Copy button** — "Copy" button added to note read mode,
copies title + content as markdown to clipboard.
- **Brand hover: jitter-free crossfade** — Sidebar brand logo→collapse icon
swap uses opacity crossfade instead of `display: none` toggle, eliminating
layout reflow jitter on hover.
### Fixed
- **Model selector shows unavailable model** — Selector restoration searched
all models including user-hidden ones. Saved selection (localStorage) for a
hidden model like Claude Opus would re-select it on every page load even when
only Grok was visible. Resolution now filters to visible models only.
- **Refresh toast shows wrong count** — "Loaded 33 models" counted all models
including hidden; now shows only visible count ("Loaded 1 model").
- **Tool calls vanish after completion** — Live streaming tool indicators
disappeared when `reloadActivePath()` rebuilt messages from DB. Fixed: the
`getActivePath` query now includes `tool_calls` column, and `PathMessage`
carries the data through to the frontend renderer.
- **Tool result "undefined results" text** — Operator precedence bug in tool
result summary parser caused `undefined results` to display for note_create.
Fixed summary logic to properly branch on title vs count.
- **Regenerate streams at wrong position** — Regen'd response appeared below
the full conversation (appended at bottom) then snapped to correct position
after completion. Fixed: display is now truncated to the parent message
before streaming starts, so the new response streams in-place as a clean
branch. Backend context was already correct (excludes old response).
- **Regenerate loses tools, reasoning, and tool execution** — Regen handler
was a stripped-down copy of the completion handler missing tool definitions,
tool execution loop, reasoning_content forwarding, and tool_calls persistence.
Model lost access to note tools on regen and fell back to generic capabilities.
Refactored: extracted `streamWithToolLoop()` into `stream_loop.go` as the
single canonical streaming implementation. Both `streamCompletion` (normal
chat) and `Regenerate` now call the shared function — only persistence
differs. Future streaming features (new event types, tool capabilities)
automatically apply to all code paths.
- **OpenRouter free models crash** — Free models with nil pricing caused
`pq: invalid input syntax for type json` on catalog sync. Nil pricing now
routes through `ToJSON()` producing `"{}"` instead of nil `[]byte`.
- **API key appears unsaved** — `ListGlobalConfigs` returned raw
`ProviderConfig` structs where `APIKeyEnc` is `json:"-"` (never serialized),
so `has_key` was always `undefined`. Now returns computed `has_key` field.
- **Case-insensitive usernames** — Login, registration, and all user lookups
use `LOWER()` in SQL. All user creation paths normalize to lowercase.
New migration `002_ci_username.sql` adds `LOWER()` unique indexes and
normalizes existing rows.
## [0.9.2] — 2026-02-23
### Added