fix(desktop): transcription not auto-starting after proxy migration#6211
Conversation
…ble check After the Deepgram/Gemini proxy migration (d0a5939), the backend no longer serves these API keys and loadEnvironment() skips them from .env. This left APIKeyService.keysAvailable permanently false, blocking the transcription auto-start in DesktopHomeView.onAppear. The onChange fallback for isLoaded has a race condition (fires only on change, not initial value), so if fetchKeys() completes before the view appears, transcription never starts. Fix: include OMI_API_URL in the keysAvailable check since proxy mode only needs the backend URL (set synchronously by loadEnvironment). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Greptile SummaryThis PR fixes a regression introduced by the Deepgram/Gemini proxy migration where transcription (and screen analysis) would never auto-start on app launch. The root cause was that The fix extends
Confidence Score: 5/5Safe to merge — the fix is minimal, correctly targeted, and resolves a real regression with no behaviour change for properly configured environments. The single changed line is a surgical extension of a boolean predicate. Root cause analysis is accurate and the fix matches. Only remaining finding is a P2 style suggestion that would only manifest in a misconfigured .env. No files require special attention — APIKeyService.swift has one minor style suggestion but is otherwise correct. Important Files Changed
Sequence DiagramsequenceDiagram
participant App as App Launch
participant AS as AppState.init()
participant LE as loadEnvironment()
participant AKS as APIKeyService
participant DHV as DesktopHomeView.onAppear
participant TS as TranscriptionService
App->>AS: init()
AS->>LE: loadEnvironment() [synchronous]
LE-->>AS: setenv("OMI_API_URL", url, 1)
Note over AS,LE: OMI_API_URL set before any view appears
App->>AKS: startFetchingKeys() [async]
Note over AKS: fetchKeys() starts in background
App->>DHV: onAppear fires
DHV->>AKS: keysAvailable? [Before fix: checks GEMINI/DEEPGRAM → false]
Note over DHV,AKS: After fix: also checks OMI_API_URL → true (already set)
DHV->>TS: startTranscription() ✅
AKS-->>AKS: fetchKeys() completes → isLoaded = true
Note over DHV: onChange(isLoaded): isTranscribing already true → no-op ✅
Reviews (1): Last reviewed commit: "chore(desktop): add changelog entry for ..." | Re-trigger Greptile |
| /// In proxy mode (OMI_API_URL set), no client-side Deepgram/Gemini keys are needed. | ||
| nonisolated static var keysAvailable: Bool { | ||
| getenv("GEMINI_API_KEY") != nil || getenv("DEEPGRAM_API_KEY") != nil | ||
| getenv("GEMINI_API_KEY") != nil || getenv("DEEPGRAM_API_KEY") != nil || getenv("OMI_API_URL") != nil |
There was a problem hiding this comment.
Presence check doesn't guard against empty/whitespace
OMI_API_URL
getenv("OMI_API_URL") != nil returns a non-nil pointer even when the env var is set to a whitespace-only value (e.g. OMI_API_URL= in .env). In that case keysAvailable returns true, transcription auto-starts, but APIClient.baseURL falls through to its !url.isEmpty guard and logs "OMI API: OMI_API_URL not set — API calls will fail" — a silent mismatch.
The existing GEMINI_API_KEY / DEEPGRAM_API_KEY paths are safe because those keys are only written by applyToEnvironment() when the value is non-nil, but OMI_API_URL comes from loadEnvironment() which calls setenv after only a whitespace-trim.
Consider aligning with the non-empty check already used in APIClient.swift:
| getenv("GEMINI_API_KEY") != nil || getenv("DEEPGRAM_API_KEY") != nil || getenv("OMI_API_URL") != nil | |
| getenv("GEMINI_API_KEY") != nil || getenv("DEEPGRAM_API_KEY") != nil | |
| || (getenv("OMI_API_URL").flatMap { String(validatingUTF8: $0) }.map { !$0.trimmingCharacters(in: .whitespaces).isEmpty } ?? false) |
Test Results ✅Branch: Test SetupSimulated signed-in user by setting UserDefaults ( Key Log ResultsPASS — transcription auto-starts: No FAIL lines:
Root cause confirmedBefore the fix: After the fix: |
Summary
APIKeyService.keysAvailablewas permanentlyfalsebecause the backend no longer returns Deepgram/Gemini API keys andloadEnvironment()skips them from.envDesktopHomeView.onAppear, and theonChange(of: isLoaded)fallback has a race condition where it doesn't fire iffetchKeys()completes before the view appearsOMI_API_URLin thekeysAvailablecheck, since proxy mode only needs the backend URL (set synchronously byloadEnvironment())Root cause
keysAvailablecheckedgetenv("GEMINI_API_KEY") != nil || getenv("DEEPGRAM_API_KEY") != nil, but since the proxy migration:/v1/config/api-keysno longer returns these keysloadEnvironment()skips them from.env(marked as backend-served)keysAvailableis alwaysfalseonAppeardefers transcription →onChangemay never fire (race condition) → transcription never startsTest plan
🤖 Generated with Claude Code