From ad602005ee2139be4c85d8c0b1383a8fe0ccfa3e Mon Sep 17 00:00:00 2001 From: Dominik Kundel Date: Mon, 9 Jun 2025 15:39:38 -0700 Subject: [PATCH 1/3] feat(realtime): add changePeerConnection option --- .changeset/change-peer-connection.md | 6 ++++++ .../agents-realtime/src/openaiRealtimeWebRtc.ts | 14 +++++++++++++- .../test/openaiRealtimeWebRtc.test.ts | 10 ++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 .changeset/change-peer-connection.md diff --git a/.changeset/change-peer-connection.md b/.changeset/change-peer-connection.md new file mode 100644 index 00000000..60c4a055 --- /dev/null +++ b/.changeset/change-peer-connection.md @@ -0,0 +1,6 @@ +--- +'@openai/agents-realtime': minor +--- + +Add `changePeerConnection` option to `OpenAIRealtimeWebRTC` allowing interception +and replacement of the created `RTCPeerConnection` before the offer is made. diff --git a/packages/agents-realtime/src/openaiRealtimeWebRtc.ts b/packages/agents-realtime/src/openaiRealtimeWebRtc.ts index 678640f6..67522132 100644 --- a/packages/agents-realtime/src/openaiRealtimeWebRtc.ts +++ b/packages/agents-realtime/src/openaiRealtimeWebRtc.ts @@ -61,6 +61,14 @@ export type OpenAIRealtimeWebRTCOptions = { * @see https://platform.openai.com/docs/guides/realtime#creating-an-ephemeral-token */ useInsecureApiKey?: boolean; + /** + * Optional hook invoked with the freshly created peer connection. Returning a + * different connection will override the one created by the transport layer. + * This is called right before the offer is created and can be asynchronous. + */ + changePeerConnection?: ( + peerConnection: RTCPeerConnection, + ) => RTCPeerConnection | Promise; } & OpenAIRealtimeBaseOptions; /** @@ -158,7 +166,11 @@ export class OpenAIRealtimeWebRTC const connectionUrl = new URL(baseUrl); - const peerConnection = new RTCPeerConnection(); + let peerConnection: RTCPeerConnection = new RTCPeerConnection(); + if (this.options.changePeerConnection) { + peerConnection = + await this.options.changePeerConnection(peerConnection); + } const dataChannel = peerConnection.createDataChannel('oai-events'); this.#state = { diff --git a/packages/agents-realtime/test/openaiRealtimeWebRtc.test.ts b/packages/agents-realtime/test/openaiRealtimeWebRtc.test.ts index 1a742dc9..a87e310a 100644 --- a/packages/agents-realtime/test/openaiRealtimeWebRtc.test.ts +++ b/packages/agents-realtime/test/openaiRealtimeWebRtc.test.ts @@ -195,4 +195,14 @@ describe('OpenAIRealtimeWebRTC.interrupt', () => { const rtc = new OpenAIRealtimeWebRTC(); expect(() => rtc.sendEvent({ type: 'test' } as any)).toThrow(); }); + + it('allows overriding the peer connection', async () => { + class NewPeerConnection extends FakeRTCPeerConnection {} + const custom = new NewPeerConnection(); + const rtc = new OpenAIRealtimeWebRTC({ + changePeerConnection: async () => custom as any, + }); + await rtc.connect({ apiKey: 'ek_test' }); + expect(rtc.connectionState.peerConnection).toBe(custom as any); + }); }); From 0ac9a359da79a98fc6f89a06d93258563df7d8d0 Mon Sep 17 00:00:00 2001 From: Dominik Kundel Date: Mon, 9 Jun 2025 16:26:05 -0700 Subject: [PATCH 2/3] feat(realtime): finalize changePeerConnection hook --- packages/agents-realtime/src/openaiRealtimeWebRtc.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/agents-realtime/src/openaiRealtimeWebRtc.ts b/packages/agents-realtime/src/openaiRealtimeWebRtc.ts index 67522132..a844d0c2 100644 --- a/packages/agents-realtime/src/openaiRealtimeWebRtc.ts +++ b/packages/agents-realtime/src/openaiRealtimeWebRtc.ts @@ -167,10 +167,6 @@ export class OpenAIRealtimeWebRTC const connectionUrl = new URL(baseUrl); let peerConnection: RTCPeerConnection = new RTCPeerConnection(); - if (this.options.changePeerConnection) { - peerConnection = - await this.options.changePeerConnection(peerConnection); - } const dataChannel = peerConnection.createDataChannel('oai-events'); this.#state = { @@ -238,6 +234,12 @@ export class OpenAIRealtimeWebRTC })); peerConnection.addTrack(stream.getAudioTracks()[0]); + if (this.options.changePeerConnection) { + peerConnection = + await this.options.changePeerConnection(peerConnection); + this.#state = { ...this.#state, peerConnection }; + } + const offer = await peerConnection.createOffer(); await peerConnection.setLocalDescription(offer); From 09a1615503b04500a7ee74092375d95b20e2d4c0 Mon Sep 17 00:00:00 2001 From: Dominik Kundel Date: Mon, 9 Jun 2025 16:26:44 -0700 Subject: [PATCH 3/3] Update change-peer-connection.md --- .changeset/change-peer-connection.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/change-peer-connection.md b/.changeset/change-peer-connection.md index 60c4a055..9304b710 100644 --- a/.changeset/change-peer-connection.md +++ b/.changeset/change-peer-connection.md @@ -1,5 +1,5 @@ --- -'@openai/agents-realtime': minor +'@openai/agents-realtime': patch --- Add `changePeerConnection` option to `OpenAIRealtimeWebRTC` allowing interception