| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
fix(app): recover from broken BLE pairing Failure-Class: none | 1 个月前 | |
feat(listen): demote freemium threshold event to Plus-only (S18) (#12906) Basic no longer enters on-device through FreemiumThresholdReachedEvent; that event is now the Plus meter warning. The client paywall sheet follows the same plan gate. Co-authored-by: Cursor <cursoragent@cursor.com> | 9 天前 | |
fix(app): detect stale iOS bond after CV1 DFU and stop reconnect loops (#14158) After guarded CV1 firmware updates, iOS can retain a stale bond while the pendant advertises normally. CoreBluetooth then fails with pairing_lost (error 14) and the app previously kept auto-reconnecting without surfacing recovery. Classify pairing_lost reliably (including NSError/CBErrorDomain variants), block native auto-reconnect for stale bonds, gate Dart ensureConnection while recovery is required, and present the existing forget-device guidance dialog. Verification: - Added app/test/services/devices/stale_bond_recovery_test.dart - Added app/ios/test/omi_ble_pairing_policy_test.rb (ios-ble-pairing-policy manifest check) Fixes #11308 Failure-Class: none Co-authored-by: Cursor Agent <cursoragent@cursor.com> | 4 小时前 | |
fix(app): stop OnDeviceWhisperProvider discarding the configured language (#12002) OnDeviceWhisperProvider.transcribe declared an optional named parameter `String? language` that shadowed the provider's `language` field. The only caller, PurePollingSocket._flushBuffer, never passes it (ISttProvider has no such parameter), so `(language == 'multi' ? '' : language) ?? ''` always resolved the parameter to null and whisper.cpp always ran with '' (auto- detect) — silently dropping the language the user picked in transcription settings and delivered via TranscriptSocketServiceFactory._createPollingSocket. The sibling OnDeviceAppleProvider already resolves `language ?? this.language`. Fix: extract request construction into buildTranscribeRequest(), which resolves the per-call language against the configured field the same way the Apple provider does ('multi' still maps to '' for whisper auto-detect), and call it from transcribe(). The seam is @visibleForTesting so the regression test asserts the exact value handed to TranscribeRequest without touching whisper's FFI. Verification: - flutter test test/services/sockets/on_device_whisper_provider_test.dart → 3/3 passed (provider-language fallback incl. 'ru', per-call override, 'multi' → ''). - bash app/test.sh (full suite, Flutter 3.47.1) → 1393 passed, 0 failed. - bash app/scripts/analyze_ratchet.sh → passed (no new occurrences). Failure-Class: none Co-authored-by: Claude Fable 5 <noreply@anthropic.com> | 25 天前 | |
Revert "fix(app): run bounded cloud sync grace when screen locks (#7221) (#11…" This reverts commit a20f19c5bcffd32ddfd9bf79173b5a82dcf5cd75. | 1 个月前 | |
fix(app,backend): phone-call live transcript never appears A 32s iOS VoIP call verified: audio worked, /v4/listen accepted the session, two STT sockets initialized — and zero audio bytes ever reached them. Every layer then reported success: teardown deleted the empty conversation (delete_empty_recording_conversation) and the app kept the transcript placeholder with the status chip hidden for idle/active. Root causes fixed on the client: the EventChannel audio path dropped or killed the stream on a single type mismatch (hard Uint8List/int casts, no resubscribe); every 20ms Core Audio buffer hopped onto the main queue as its own Map event (~100/s across two channels), which a CallKit-active call cannot sustain; and audioDevice.start() during CallKit activation was a silent no-op when Twilio had not initialized the capturer yet. - PhoneCallService coerces data/channel types (List<int>, Int8List, generic lists, numeric/string channels), counts coercion/drop, never unsubscribes on a bad event, and resubscribes after stream error/done - iOS/Android audio events are coalesced (~100ms per channel) on a dedicated bounded queue instead of one main-thread post per buffer - deferred audioDevice.start() is retried after initializeCapturer / startCapturing so a running call never keeps a live socket with no tap - after 3s of an accepted socket with zero prefixed frames the app shows a visible no-audio state instead of the transcript placeholder, and fires Phone Call Transcript Session with per-channel counts - backend: count accepted listen sessions, first audio, unknown channel prefixes (previously dropped silently), and record outcome=no_audio_teardown before deleting a silent phone-call conversation's empty record — closed enums only, no identifiers Failure-Class: new | 15 天前 |