fix(media-server): make agent peer bidirectional

The agent peer built its offer via AddTrack, which pion materializes as a
sendonly transceiver. The browser could therefore receive customer audio
but had no m-line to send its microphone — one-shot answer cannot add a
new m-line. Result: audio one-way at best, and in practice neither
direction worked because the bridge never saw an agent remote track.

Switch to AddTransceiverFromTrack with direction sendrecv, matching the
Meta-peer fix. The browser can now respond sendrecv and the bridge's
agent-to-Meta forwarding actually has a source.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tanmay Deep Sharma
2026-04-21 16:51:04 +07:00
co-authored by Claude Opus 4.7
parent 980dccea78
commit 83f32cddac
@@ -99,11 +99,18 @@ func NewAgentPeer(cfg *config.Config, id string, role PeerRole, iceServers []web
return nil, "", fmt.Errorf("create local track: %w", err)
}
sender, err := pc.AddTrack(localTrack)
// Bind the local track to a sendrecv transceiver so the offer advertises
// both directions: we send customer audio to the browser, and we expect
// the browser's microphone audio back. AddTrack alone yields a sendonly
// m=audio, leaving the browser with nowhere to send mic audio.
transceiver, err := pc.AddTransceiverFromTrack(localTrack, webrtc.RTPTransceiverInit{
Direction: webrtc.RTPTransceiverDirectionSendrecv,
})
if err != nil {
pc.Close()
return nil, "", fmt.Errorf("add local track: %w", err)
return nil, "", fmt.Errorf("add audio transceiver: %w", err)
}
sender := transceiver.Sender()
// Consume RTCP packets from the sender to avoid blocking.
go func() {