0.3.7 is a layout-and-voice release. The chat header keeps every action visible across sm, md, and lg, the Settings dialog gets a wider sidebar and in-tab sub-navigation, speech grows from a single Gemini Live path into a pluggable provider system, and the Usage page learns to draw charts.
Model-Generated Session Titles
A new Sparkles button in the chat header (and a matching mobile-menu entry) asks the active model to rename the current session based on its content. The handler snapshots the live messages, feeds a preview to the model with a minimal-reasoning configuration, and writes the cleaned title back via sessions.updateTitle. Tooltip feedback reports "Generating title…", "Renamed to …", or the error message.
Speech & Voice — New Tab, New Providers
Speech is now its own Settings tab, and src/keating/speech.ts exposes a SpeechProvider interface backed by a lazy registry. Built-in providers:
- Gemini Live — existing audio-out path, refactored behind the interface. Stable.
- OpenAI TTS —
gpt-4o-mini-tts,tts-1, andtts-1-hdvia/v1/audio/speech, with steerable affect/pace on the mini model. Stable. - OpenAI Realtime — full WebRTC duplex: mints an ephemeral session, exchanges SDP, attaches the mic when enabled, and plays the remote audio track. Flagged preview (per-utterance session, untested against your account).
- Supertonic-3 (local) — wires
onnxruntime-weband downloads the 4 ONNX files plustts.jsonandunicode_indexer.jsonfrom the Hugging Face repo. Flagged experimental: sessions load and warm up, but the text→tokens→duration→vectors→vocoder synthesis pipeline still needs to be ported from the Pythonsupertonicpackage. - Custom TTS — paste any OpenAI-compatible
/v1/audio/speechendpoint: label, base URL, model id, voice, provider-key name, and optional API path.
A microphone toggle in the same tab is honored by duplex providers like OpenAI Realtime. The voice tool the agent calls (keating_voice) dispatches to the active provider through the registry instead of hard-coding Gemini.
Usage Charts
The Usage page now includes five panels powered by src/components/UsageCharts.tsx:
- Topic mix donut — artifacts grouped by topic, recharts
PieChartwith a shared palette. - Feedback signal donut — confident / off-track / confused from
learnerState.feedbackHistory. - Curriculum timeline — a hand-rolled SVG Gantt across
learnerState.sessions(start/end + topics covered), color-matched to the donut. - Daily activity heatmap — 12 weeks of sessions/day, GitHub-style grid (also hand-rolled SVG).
- Coming up — open
Verificationchecklists pluslearnerState.weaknesses[]/strengths[]. Honest stand-in for "due" work since storage has no SRS field yet.
Responsive Layout & Settings Navigation
At the md breakpoint the chat header was silently dropping Settings, New Session, History, Speech, and Artifacts: the hamburger was hidden (md:hidden) before the inline icons started showing. All seven action icons now render together from sm upward and the hamburger collapses to xs only; the mobile dropdown gained the missing New Session / Session history entries.
The Settings dialog widened to max-w-5xl with a wider sidebar on md/lg, and the heavy Providers & Models tab gained a sticky chip-style sub-section navigator (Cloud / Visibility / My Models / Custom Providers) with scrollIntoView jumps and per-section scroll-mt-20. The Speech & Voice tab uses the same pattern.
Suggested-Prompts Auto-Load-More
The suggested-prompts strip used to randomize three items and only let the "More" pill swap them out. Pressing the right-arrow at the end of the list now appends fresh suggestions filtered against what's already been shown, growing the strip until the underlying pool is exhausted. The "More" pill follows the same semantics and hides once nothing new is left.
Honest Status: Preview vs. Experimental
The Speech tab uses badge color to tell you exactly where each provider stands. Stable providers ship no badge. Preview means the integration is wired end-to-end but hasn't been validated against a live account in this release — OpenAI Realtime falls here because the per-utterance session pattern needs to mature into a persistent duplex channel. Experimental means the wiring deliberately stops short of a working call — Supertonic-3 falls here because the four ONNX models load fine in browser, but reproducing the Python supertonic package's tokenization, duration alignment, voice-style conditioning, and vocoder windowing in JS is its own follow-up. Picking either provider surfaces a clear error rather than a silent failure.