Commit Graph
7 Commits
Author SHA1 Message Date
Tanmay Deep SharmaandClaude Opus 4.7 c6c3ba054e fix(whatsapp-call): stop browser from bypassing media server on inbound
Inbound calls were reaching the media server, DTLS was completing after
the DTLSRoleServer fix, and yet no media flowed — Meta still timed out
at 20s. Tracing the session 182412 showed why: the browser uploaded a
local .webm recording at t+22s. That only happens on the legacy
browser-direct-to-Meta path, which means the browser negotiated WebRTC
straight with Meta instead of waiting for the media server's agent
offer.

Root cause: GET /whatsapp_calls/:id returns Meta's sdp_offer whenever
the call is ringing, regardless of media-server mode. The FE calls
that endpoint from acceptWhatsappCallById when the call isn't in the
incoming-calls store yet (page reload, bubble click). It then sees a
truthy sdpOffer, isServerRelayCall() returns false, and the browser
dials Meta itself. Meta's DTLS was with *our* media server, so the
browser's peer connection never got media and Meta saw silence.

Fix:
- show omits sdp_offer / ice_servers when media_server_enabled and
  returns media_server_enabled as an explicit flag so the FE picks the
  right path.
- broadcast_incoming_call carries the same flag through ActionCable.
- FE isServerRelayCall prefers the explicit flag; only falls back to
  sdpOffer presence when the flag isn't provided.
- acceptWhatsappCallById and the ActionCable handler propagate the
  flag into the call object.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 18:31:20 +07:00
tds-1androot 5e5dc21f2f feat(whatsapp-call): add server-side WebRTC media server for call persistence
Implements a Pion Go B2BUA media server sidecar that sits between Meta's
WhatsApp Cloud API and the agent's browser, enabling call persistence
across page reloads, server-side recording, multi-participant support,
audio injection, and AI integration readiness.

Go Media Server (enterprise/media-server/):
- Pion WebRTC v4 B2BUA with Peer A (Meta) and Peer B (Agent) connections
- Real-time OGG/Opus recording with crash recovery
- Audio bridge with multi-peer fan-out and AudioConsumer plugin interface
- Audio injection from OGG files with loop support for hold music
- Session manager with graceful shutdown and orphaned recording recovery
- HTTP API with Bearer token auth, health checks, and metrics

Rails Integration:
- Whatsapp::MediaServerClient HTTP client for Go sidecar communication
- Dual-mode CallService: legacy browser-direct and server-relay paths
- Media server callback controller for agent disconnect/recording/terminate
- CallRecordingFetchJob: downloads OGG from Go server to ActiveStorage/S3
- CallCleanupJob: sweeps stale ringing and in-progress calls
- New endpoints: active, agent_answer, reconnect, join, play_audio
- DB migration: media_session_id column with indexes

Frontend:
- Dual-mode composable auto-detecting legacy vs server-relay
- handleAgentOffer() for receiving SDP from media server
- useCallReconnection composable for page reload recovery
- Removed terminateCallOnUnload in server-relay mode
- Simplified outbound call flow in ConversationHeader
- New ActionCable event: whatsapp_call.agent_offer

Documentation:
- Server-side WebRTC architecture spec (1505 lines)
- Implementation plan with 119 trackable checklist items
- Feature spec, PR breakdown, and relay architecture docs
2026-04-21 04:47:53 +00:00
rootandClaude Opus 4.6 f49032610f refactor(whatsapp-call): migrate to unified Call model from PR #14026
Replace the WhatsappCall model with the unified Call model introduced
in feat/voice-call-model (PR #14026), enabling multi-provider support
(Twilio + WhatsApp) under a single data model.

Key changes:
- Delete WhatsappCall model and its 3 migrations (whatsapp_calls table)
- Enhance Call model with WhatsApp-specific helpers (sdp_offer,
  ice_servers, recording_url, direction_label, ringing?, in_progress?)
- Update all backend services, controller, and jobs to use Call model
- Map statuses: accepted→in_progress, rejected→failed, missed→no_answer,
  ended→completed
- Map directions: inbound→incoming, outbound→outgoing (enums)
- Rename call_id column to provider_call_id, always set provider: :whatsapp
- Add authorization check on initiate action
- Add race condition guard in outbound call_connect webhook handler
- Consolidate direction_label helper into Call model (DRY)
- Update frontend data key from waCallId to callId in VoiceCall bubble
- Remove whatsapp_calls table from schema.rb, fix missing started_at

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-12 17:17:30 +00:00
Tanmay Deep Sharma 504a32214e feat(whatsapp-call): add call recording, transcription, beforeunload termination and documentation 2026-03-24 13:13:49 +05:30
Tanmay Deep Sharma 1e3c6ad620 fix: refactor whatsapp calling for lint compliance, outbound call UI, and SDP handling 2026-03-18 14:59:56 +05:30
Tanmay Deep Sharma c813505e7d fix: inbound and outbound email 2026-03-16 16:18:59 +05:30
Tanmay Deep Sharma f849cbb76a feat(whatsapp): add calling enable/disable toggle in inbox settings UI 2026-03-06 10:09:53 +05:30