Commit Graph

332 Commits

Author SHA1 Message Date
Ayaan Zaidi 6f63fc288a fix(android): return NOT_AUTHORIZED when notify permission is lost 2026-03-01 20:32:14 +05:30
Ayaan Zaidi 759a0fc1b2 chore(android): remove deprecated AGP gradle flags 2026-03-01 20:32:14 +05:30
Ayaan Zaidi 9c2f7e2a9d style(android): format gradle kotlin scripts 2026-03-01 20:32:14 +05:30
Ayaan Zaidi 348a7dd5b3 fix(android): guard notification post permission 2026-03-01 20:32:14 +05:30
Ayaan Zaidi 7f9274b71d chore(android): add kotlin lint/format tooling 2026-03-01 20:32:14 +05:30
Greg Mousseau ba430cc65b fix(android): drainingTts identity check, mark stopped on WebSocket failure
- Codex P2: drain coroutine now only clears drainingTts if it's the
  same instance (=== check), preventing a newer drain from being
  unreachable by stopTts.
- Codex P2: set stopped=true on WebSocket onFailure so subsequent
  sendText calls are rejected and stale state doesn't persist.
2026-03-01 20:03:26 +05:30
Greg Mousseau ccca99c472 fix(android): ignore stale out-of-order agent events in streaming TTS
Agent events arrive on multiple threads concurrently. A stale event
with shorter accumulated text was falsely triggering 'text diverged',
causing the streaming TTS to restart with a new WebSocket — resulting
in multiple simultaneous ElevenLabs connections (2-3 voices) and
eventual system TTS fallback when hasReceivedAudio was false.

Fix: if sentFullText.startsWith(fullText), the event is stale (we
already have this text), not diverged. Accept and ignore it.
2026-03-01 20:03:26 +05:30
Greg Mousseau a583261775 fix(android): wire speaker mute to TalkMode, release audio focus on stop
- Codex P1: setSpeakerEnabled now syncs talkMode.setPlaybackEnabled
  so muting the speaker works when ttsOnAllResponses is active.
- Codex P2: abandonAudioFocus() called in stopSpeaking to prevent
  audio focus leak after TTS completes or is interrupted.
2026-03-01 20:03:26 +05:30
Greg Mousseau 930841cd7c fix(android): wire MP3 fallback call, prevent double-speaking
- Codex P1: streamAndPlayMp3 was computed but never called after PCM
  failure. Now properly invoked as fallback.
- Codex P2: MicCaptureManager.speakAssistantReply now skipped when
  TalkModeManager.ttsOnAllResponses is active, preventing both
  pipelines from speaking the same assistant reply.
2026-03-01 20:03:26 +05:30
Greg Mousseau 587790e84a fix(android): talk mode stability — thread safety, TTS fallback, mic cooldown
Bug fixes:
- @Synchronized on ElevenLabsStreamingTts.sendText/finish to prevent
  sentFullText/sentTextLength races across OkHttp and caller threads
- Pre-set pendingRunId via onRunIdKnown callback before chat.send to
  eliminate race where gateway events arrive before runId is stored
- Track drain coroutine as Job; cancel prior on rapid mic toggle to
  prevent duplicate TTS and stale transcript sends
- Mic button disabled during 2s drain cooldown (micCooldown StateFlow)

Codex review fixes:
- Gate agent streaming TTS on sessionKey to prevent cross-session
  audio leaks (P1)
- Clear ElevenLabs credentials when talk.provider is not elevenlabs;
  gate streaming TTS on activeProviderIsElevenLabs (P2)

System TTS fallback fixes:
- Null streamingTts immediately in finishStreamingTts so next response
  gets a fresh TTS instance
- Add hasReceivedAudio flag to ElevenLabsStreamingTts to detect when
  WebSocket connects but returns no audio (invalid key, network error)
- Fall back to playTtsForText when streaming TTS produced no audio
- Track ttsJob to cleanly cancel prior playTtsForText on new response
- Re-throw CancellationException instead of cascading into fallback
  attempts that also get cancelled
2026-03-01 20:03:26 +05:30
Greg Mousseau 4748ba491d fix(android): chat history refresh and mic capture improvements for voice
ChatController:
- final/aborted/error run events now trigger a history refresh regardless of
  whether the runId is in pendingRuns; only delta events require the run to be
  tracked (prevents voice-initiated responses from being silently dropped)

MicCaptureManager:
- Don't auto-send on onResults silence detection — accumulate transcript
  segments and send when mic is toggled off, giving the recognizer time to
  finish processing buffered audio
- Capture any partial live transcript if no final segments arrived (2s drain
  window before stop)
- Join multi-segment transcripts with sentence-ending punctuation to avoid
  run-on text sent to the gateway
2026-03-01 20:03:26 +05:30
Greg Mousseau 68db055f1a feat(android): wire TalkModeManager into NodeRuntime for voice screen TTS
TalkModeManager is instantiated lazily in NodeRuntime and drives ElevenLabs
streaming TTS for all assistant responses when the voice screen is active.
MicCaptureManager continues to own STT and chat.send; TalkModeManager is
TTS-only (ttsOnAllResponses = true, setEnabled never called).

- talkMode.ttsOnAllResponses = true when mic is enabled or voice screen active
- Barge-in: tapping the mic button calls stopTts() before re-enabling mic
- Lifecycle: PostOnboardingTabs LaunchedEffect + VoiceTabScreen onDispose both
  call setVoiceScreenActive(false) so TTS stops cleanly on tab switch or
  app backgrounding
- applyMainSessionKey wires the session key into TalkModeManager so it
  subscribes to the correct chat session for TTS
2026-03-01 20:03:26 +05:30
Greg Mousseau f0fcecd7c1 feat(android): ElevenLabsStreamingTts — WebSocket streaming TTS with PCM playback
Streams text to the ElevenLabs WebSocket API and plays audio in real-time
via AudioTrack (PCM 24kHz). Key design points:

- sendText(fullText) takes the full accumulated text and only transmits the
  new suffix, detecting divergence for restart
- Chunks are queued if the WebSocket isn't yet connected; flushed in onOpen
- finish() sends EOS to ElevenLabs; deferred if called before onOpen fires
- sendText returns true (not false) when finished=true to avoid treating a
  normal end-of-stream as a diverge restart
- finishStreamingTts coroutine uses identity check before nulling streamingTts
  to prevent a mid-drain restart from orphaning a live TTS session
- eleven_v3 does NOT support WebSocket streaming; use eleven_flash_v2_5
2026-03-01 20:03:26 +05:30
Ayaan Zaidi 1d7b76a90e fix(android-voice): rotate playback token per assistant reply 2026-02-28 20:05:59 +05:30
Ayaan Zaidi addc619087 fix(android-voice): retry talk config after transient failures 2026-02-28 20:05:59 +05:30
Ayaan Zaidi 930e94024a fix(android-voice): cancel in-flight speech when speaker muted 2026-02-28 20:05:59 +05:30
Ayaan Zaidi 727ae469cf perf(android): reduce mic conversation update churn 2026-02-28 20:05:59 +05:30
Ayaan Zaidi 3daed77ba9 fix(android): unify voice speaker gating and config refresh 2026-02-28 20:05:59 +05:30
Ayaan Zaidi 72e135083a feat(android-voice): add speaker toggle in voice tab 2026-02-28 20:05:59 +05:30
Ayaan Zaidi fb92a91ef7 fix(android): speak final voice replies in mic capture flow 2026-02-28 20:05:59 +05:30
Ayaan Zaidi fcf3e5b0a0 fix(android): expose talk-mode assistant speech entrypoint 2026-02-28 20:05:59 +05:30
Ayaan Zaidi eea081c709 fix(android): update onboarding pairing commands 2026-02-28 20:05:59 +05:30
Ayaan Zaidi 548a28a13f fix(android): request onboarding permissions per toggle 2026-02-28 20:05:59 +05:30
Ayaan Zaidi 3f056a7294 fix(android): block onboarding advance until special setup is complete 2026-02-28 12:29:52 +05:30
Ayaan Zaidi cd61edb0f3 fix(android): add missing capability setup surfaces 2026-02-28 12:29:52 +05:30
Ayaan Zaidi f1bb26642c fix(gateway): scope notification wakeups to session 2026-02-28 11:18:01 +05:30
Ayaan Zaidi 9d3ccf4754 feat(gateway): enable Android notify + notification events 2026-02-28 11:18:01 +05:30
Ayaan Zaidi 1bc9da8f9e fix(android): stabilize motion sampling and gate pedometer command 2026-02-28 09:27:54 +05:30
Ayaan Zaidi 18e7938dfd refactor(android): remove unreachable motion classify branch 2026-02-28 09:27:54 +05:30
Ayaan Zaidi 943dce37be feat(android): wire new device capabilities into runtime 2026-02-28 09:27:54 +05:30
Ayaan Zaidi b9e474deb4 feat(android): add motion activity and pedometer handlers 2026-02-28 09:27:54 +05:30
Ayaan Zaidi f75385981a feat(android): add calendar capability handlers 2026-02-28 09:27:54 +05:30
Ayaan Zaidi 81ebe7de46 feat(android): add contacts capability handlers 2026-02-28 09:27:54 +05:30
Ayaan Zaidi c8ad229776 feat(android): add photos latest handler 2026-02-28 09:27:54 +05:30
Ayaan Zaidi f637cbd246 feat(android): add system notification handler 2026-02-28 09:27:54 +05:30
Ayaan Zaidi 3f06693e7d refactor(android): share node capability and command manifest 2026-02-28 08:46:50 +05:30
Peter Steinberger fe807e4bed chore(release): bump 2026.2.27 and split changelog 2026-02-27 16:09:28 +01:00
Ayaan Zaidi 3a35035512 fix(android): send object params for canvas capability refresh 2026-02-27 13:26:42 +05:30
Ayaan Zaidi 6222d6650b fix(android): avoid duplicate A2UI readiness probe on happy path 2026-02-27 12:16:36 +05:30
Ayaan Zaidi 8187fbc571 fix(android): refresh scoped canvas URLs without trailing slash 2026-02-27 12:16:36 +05:30
Ayaan Zaidi d53b24d185 fix(android): return valid debug.ed25519 diagnostics JSON 2026-02-27 12:16:36 +05:30
Ayaan Zaidi 34486f8c10 fix(android): retry A2UI after canvas capability refresh 2026-02-27 12:16:36 +05:30
Ayaan Zaidi 9b64ad30c4 docs(android): add integration test preconditions and pitfalls 2026-02-27 12:16:36 +05:30
Ayaan Zaidi 0896bb09b0 feat(android): wire runtime canvas capability refresh 2026-02-27 12:16:36 +05:30
Ayaan Zaidi 22d422a792 refactor(android-node): share battery snapshot parsing across device handlers 2026-02-27 10:15:21 +05:30
Ayaan Zaidi 284f75500c refactor(android-node): unify notifications snapshot rebind preflight 2026-02-27 10:15:21 +05:30
Ayaan Zaidi bbab0b005e fix(android): rebind listener before notification actions 2026-02-27 10:15:21 +05:30
Ayaan Zaidi 8807267bfd fix(android): allow open and reply on non-clearable notifications 2026-02-27 10:15:21 +05:30
Ayaan Zaidi d0ec3de588 feat(android): implement device diagnostics and notification actions 2026-02-27 10:15:21 +05:30
Ayaan Zaidi e99b323a6b feat(node): add device diagnostics and notification action commands 2026-02-27 10:15:21 +05:30