Post-review cleanup of Phase 4. Closes Finding #9 properly and corrects
the Finding #13 documentation lie surfaced in the code-review report.
Capability schema:
- Replace `AgentOverridable bool` with `AgentOverridableAs string` on
ParamSchema. Empty string = not overridable; non-empty = the generic
key alias (`"speed"`, `"emotion"`, `"style"`).
- Each provider declaration now carries the alias inline, so the
generic↔native mapping has a single TS-readable source.
Frontend:
- Web `tts-override-block.tsx` drops the inline `GENERIC_TO_NATIVE`
literal and derives the bidirectional adapter from the filtered
capability params (each param self-describes its alias). Adapter
tests rewritten around the new shape.
- Desktop `AgentDetailPanel.tsx` drops the 45-line inline IIFE in
favour of a new `<TtsOverrideFineTune>` component that uses the
same alias-based mapping.
Backend:
- Move `AgentTTSParamsAllowedKeys` + `ValidateAgentTTSParams` to
`internal/audio/agent_params_adapter.go`. HTTP `validate.go` and WS
`gateway/methods/agents_update.go` both delegate, eliminating the
duplicated `{speed, emotion, style}` literal.
Cleanup:
- Delete orphan i18n keys `MsgTtsParamInvalidJSON` and
`MsgTtsParamDependsOn` from `keys.go` + en/vi/zh catalogs (no
in-code references; DependsOn is FE-only, JSON parse failures
already surface via slog).
Documentation:
- `prompt-settings-section.tsx` Finding #13 comment rewritten to
honestly describe the best-effort merge into a fresh local copy of
the cached `otherConfig` prop. Concurrent-tab clobber remains
possible — server-side JSON-merge-patch endpoint planned for v2.
Tests: 9 backend suites (race), web 217/217, desktop build clean,
both Go build tags pass.
Phase 4 — final phase of the TTS params/layout/agent-override plan.
Adds a 3-key allow-list (`speed`, `emotion`, `style`) per agent stored
in `agents.other_config.tts_params`. Backend resolves and merges into
`opts.Params` PER ATTEMPT inside the fallback loop so each provider
sees its own native shape — never the primary's keys when fallback
runs (Finding #1 critical).
Backend:
- `AgentOverridable bool` on `audio.ParamSchema`. UI filter reads this
flag from /v1/tts/capabilities; no separate TS literal mirror —
capabilities API is the single source of truth (Finding #9).
- `audio.AdaptAgentParams(generic, provider)` maps the 3 generic keys
to provider-native paths (e.g. `speed` → `voice_settings.speed` for
ElevenLabs, flat `speed` for OpenAI/MiniMax, dropped for Edge/Gemini).
- `Manager.SynthesizeWithFallbackAdapted` adapts inside the loop so
fallback providers receive correctly-shaped params.
- `manager_auto.go` and `tools/tts.go` Execute do per-attempt adaptation
on the tenant + direct + fallback call sites.
- Drop log bumped to `slog.Info("tts.agent.params.dropped", ...)` for
audit trail when a generic key isn't supported by the active provider.
- Cross-check test asserts every adapter switch case has at least one
capability ParamSchema with `AgentOverridable: true`, and vice versa.
Security (red-team findings):
- Allow-list ENFORCED at write path: `validateAgentTTSParams` in HTTP
`handleUpdate` AND WS `agents_update` rejects any `tts_params` key
outside `{speed, emotion, style}` (Finding #5).
- 64KB body cap on agent PUT via `http.MaxBytesReader` (Finding #6).
- Explicit tenant-scope guard after `agents.GetByID` (Finding #12).
- Concurrent-tab clobber: handleSave merges `tts_params` into a fresh
copy of `otherConfig` rather than reusing stale state (Finding #13).
- Rate-limit verified — RoleAdmin gate sufficient for v1 (Finding #15).
Frontend (web + desktop):
- `TtsOverrideBlock` rewritten: filters capability params to
`agent_overridable === true`, renders via `DynamicParamForm`. Hides
entirely for providers with no overridable params (Edge, Gemini).
- Bidirectional adapter (generic ↔ capability-native form state) so
agent storage stays in generic keys while UI works in native paths.
25 round-trip tests cover all 5 providers.
- Desktop `AgentDetailPanel` gains an inline fine-tune section gated
on `globalProvider`, reusing the desktop `DynamicParamForm`.
i18n: `tts.override.params.title` ("Fine-tune") added to web + desktop
en/vi/zh.
Tests: all 9 backend suites green (race), web 214/214, desktop build
clean, both Go build tags pass.
Implement native ElevenLabs Scribe STT provider with POST /v1/speech-to-text endpoint. Supports 20MB audio cap, multipart form submission, configurable model and language. Includes comprehensive unit tests for happy path, audio size validation, API errors, and edge cases.
Add StreamingTTSProvider interface for audio streaming support. Implement voice
caching with TTL+LRU. Add ElevenLabs model validation and voice list retrieval.