feat(capture): gate global hotkey on dictation readiness checklist

Stops the "stuck pill" failure where pressing the chord with missing
STT/LLM models triggers a recording that has nowhere to land. The
hotkey now stays disarmed until every gate (models downloaded, Input
Monitoring + Accessibility granted) is green; the empty-state checklist
in CapturesTab surfaces each unmet gate with a one-click action and
auto-arms the chord once everything turns green.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This commit is contained in:
James Pine
2026-04-23 03:09:44 -07:00
co-authored by Claude Opus 4.7
parent 868a40fb7e
commit 85a3e1363f
10 changed files with 480 additions and 14 deletions
+28
View File
@@ -427,6 +427,34 @@ class PersonalitySpeakRequest(BaseModel):
)
class ModelReadiness(BaseModel):
"""Per-model entry in the dictation readiness checklist.
``model_name`` is the canonical id used by ``POST /models/download`` so the
frontend can wire a one-click "Download" button without a second lookup.
``size`` is the user's chosen variant (e.g. "turbo", "0.6B"); ``display_name``
is what the checklist row should show ("Whisper Turbo").
"""
ready: bool
model_name: str
display_name: str
size: str
size_mb: Optional[int] = None
class CaptureReadinessResponse(BaseModel):
"""Backend gates that must be green before the global hotkey will fire.
The frontend combines this with its own TCC permission checks (input
monitoring, accessibility) into the full dictation readiness checklist.
Hotkey-enabled is the user's intent toggle and lives outside this struct.
"""
stt: ModelReadiness
llm: ModelReadiness
class HealthResponse(BaseModel):
"""Response model for health check."""