Skip to content

fix(desktop): QA fixes — model picker, slash commands, voice input - #810

Merged
agentforce314 merged 2 commits into
mainfrom
fix/desktop-qa-round1
Aug 8, 2026
Merged

fix(desktop): QA fixes — model picker, slash commands, voice input#810
agentforce314 merged 2 commits into
mainfrom
fix/desktop-qa-round1

Conversation

@agentforce314

Copy link
Copy Markdown
Owner

Hands-on QA of the desktop app surfaced several broken surfaces where clawcodex serve answered too thinly. Each was found by driving the real app over CDP and fixed + verified live.

Model config (round 1)

  • Picker showed "No models found": model.options returned {providers: []} with no live session, but the composer opens the picker on the welcome screen. Now falls back to a session-independent catalog from config (provider_catalog). The full provider-grouped list renders.
  • Model switching did nothing: serve had no config.set handler. Ported the TUI's setModel (incl. the provider-mismatch → set_provider → re-apply retry the picker relies on) + permission_mode/effort/provider/thinking/logoColor keys. Verified: sonnet-4-6 → opus-5 applies.

Slash commands (round 1)

  • / menu showed "No matches": commands.catalog/complete.slash were empty stubs. Ported the built-in command list + merge live skills & workflow commands — the menu shows all 89 commands.
  • Commands didn't run: added slash.exec/command.dispatch (ported dispatchSlash) with a skill_command fallback. Verified: /context, /cost, /version, /eco, /thinking return real data.

Voice input (round 2)

  • Mic silently did nothing: POST /api/audio/transcribe was unimplemented (404). Added it — transcribes via an OpenAI-compatible Whisper endpoint from provider config (configurable via voice.stt_provider/stt_model). The renderer was also throwing away ok/error and returning an empty transcript; now it surfaces the backend's actionable message (which the recorder already toasts).

Verification

  • 52 desktop pytest cases (25 new across catalog/dispatch/audio), all green.
  • Renderer typecheck green; lint at the reference baseline (0 errors / 88 warnings).
  • Every fix driven live in the running app.

🤖 Generated with Claude Code

agentforce314 and others added 2 commits August 8, 2026 08:30
Two surfaces the desktop QA found broken, both because serve answered too
thinly:

Model config:
- model.options returned {providers: []} whenever there was no live session
  — but the composer opens the picker on the WELCOME screen, before the
  first prompt. The picker showed 'No models found'. Now model.options falls
  back to a session-independent catalog built straight from config
  (provider_catalog + default provider/model), so the full provider-grouped
  list renders immediately.
- Added config.set: model switching (config.set key=model) went nowhere —
  serve had no handler. Ported the TUI client's setModel, including the
  provider-mismatch → set_provider → re-apply-model retry the picker relies
  on, plus permission_mode/effort/provider/thinking/logoColor keys.
  Verified live: sonnet-4-6 → opus-5 applies and get_settings confirms.

Slash commands:
- commands.catalog / complete.slash were empty stubs, so the '/' menu showed
  'No matches. Try /help.' Ported the built-in command list (desktop_commands
  .py, mirroring the TUI's SLASHES) and merge live skills (list_skills) +
  workflow commands (list_workflow_commands). The menu now shows the full
  catalog (89 commands with a session).
- Added slash.exec / command.dispatch (desktop_slash.py), porting the TUI's
  dispatchSlash map: each command relays to its agent control and formats a
  one-line result, with a skill_command fallback for user skills/workflows.
  Verified live: /context, /cost, /version, /eco, /thinking all return real
  data.

18 new pytest cases (catalog build/merge/complete, dispatch mapping +
skill fallback + never-raises, catalog-from-config). All 45 desktop server
tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ssage) (QA round 2)

The mic button posted to POST /api/audio/transcribe, which serve didn't
implement — the request hit the 404 catch-all and the renderer silently
returned an empty transcript, so the mic looked dead.

Backend:
- New /api/audio/transcribe (src/server/desktop_audio.py): decodes the
  recorded data URL and transcribes it via an OpenAI-compatible
  /audio/transcriptions (Whisper) endpoint, using a configured provider's
  key + base URL (openai/groq host Whisper). Provider + model are
  configurable (voice.stt_provider / voice.stt_model). The agent core's STT
  is an abstract stub, so this is the first working transcription path.
- Actionable failures instead of raw upstream JSON: no STT-capable provider
  configured, or a chat-only gateway that rejects the transcription model
  (the user's LiteLLM gateway has no Whisper), both return a clear
  'configure a Whisper provider' message.

Renderer:
- transcribeVoiceAudio threw away result.ok/error and returned the empty
  transcript on failure — now it throws the backend's actionable message,
  which the voice recorder already surfaces via notifyError. Added the
   field to AudioTranscriptionResponse and an sttFailed string across
  all five locales.

7 new pytest cases (data-url decode, success via mocked Whisper endpoint
asserting the multipart request, model-rejection + no-provider actionable
errors, empty clip, config model override). Renderer typecheck green; lint
back to the reference baseline (0 errors / 88 warnings).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@agentforce314
agentforce314 enabled auto-merge (squash) August 8, 2026 15:39
@agentforce314
agentforce314 merged commit fdc16b1 into main Aug 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant