Move TTS routes behind auth middleware and attach JWT to local
proxy requests from the frontend. Previously both /api/hermes/tts
and /api/tts/proxy/audio/speech were publicly accessible without
authentication, allowing unauthenticated callers to consume Edge
TTS resources through the server.
Changes:
- server: move ttsRoutes from public to protected route section
- client: auto-attach JWT when baseUrl is a local path (/...)
and no external API key is configured
- client: import getApiKey() instead of raw localStorage access
The authStatus() controller previously returned the first users
username to unauthenticated clients. The frontend never used this
value — `fetchAuthStatus()` in LoginView.vue discards the return
value entirely. Remove the field to prevent username enumeration.
Changes:
- server: drop `username` from authStatus response body
- server: remove unused `findFirstUser` import
- client: remove `username` from AuthStatus interface
The hermes-agent CLI KawaiiSpinner sends decorative kaomoji text
like "(◕‿◕✿) pondering..." through thinking_callback for its TUI
widget. The bridge forwarded this as thinking.delta events, which
the frontend stored in the message reasoning field.
Over long conversations this contaminated the model's context:
_copy_reasoning_content_for_api promoted the kaomoji text to
reasoning_content, causing the LLM to reproduce kaomoji patterns
in a self-reinforcing degradation loop.
Fix: _make_thinking_callback unconditionally sends empty text.
thinking_callback is purely CLI spinner status — it has no place in
conversation history. Actual model reasoning (reasoning.delta) is
unaffected.