diff --git a/.changeset/bumpy-cats-run.md b/.changeset/bumpy-cats-run.md new file mode 100644 index 00000000..47f2894c --- /dev/null +++ b/.changeset/bumpy-cats-run.md @@ -0,0 +1,5 @@ +--- +'@openai/agents-realtime': patch +--- + +fix: #552 WebSocket Realtime Agent: invalid_request_error with decimal audio_end_ms data diff --git a/packages/agents-realtime/src/openaiRealtimeWebsocket.ts b/packages/agents-realtime/src/openaiRealtimeWebsocket.ts index de1e9dcc..3c4e7935 100644 --- a/packages/agents-realtime/src/openaiRealtimeWebsocket.ts +++ b/packages/agents-realtime/src/openaiRealtimeWebsocket.ts @@ -426,7 +426,8 @@ export class OpenAIRealtimeWebSocket } const length = this._audioLengthMs ?? Number.POSITIVE_INFINITY; - const audio_end_ms = Math.max(0, Math.min(Math.floor(elapsedTime), length)); + // audio_end_ms must be an integer + const audio_end_ms = Math.max(0, Math.floor(Math.min(elapsedTime, length))); this.emit('audio_interrupted'); this.sendEvent({ diff --git a/packages/agents-realtime/test/openaiRealtimeWebsocket.test.ts b/packages/agents-realtime/test/openaiRealtimeWebsocket.test.ts index 75b2b8bf..db135648 100644 --- a/packages/agents-realtime/test/openaiRealtimeWebsocket.test.ts +++ b/packages/agents-realtime/test/openaiRealtimeWebsocket.test.ts @@ -205,6 +205,22 @@ describe('OpenAIRealtimeWebSocket', () => { expect(baseSpy).toHaveBeenCalled(); }); + it('_interrupt floors fractional audio length when clamping', () => { + const ws = new OpenAIRealtimeWebSocket(); + const sendSpy = vi + .spyOn(OpenAIRealtimeWebSocket.prototype as any, 'sendEvent') + .mockImplementation(() => {}); + // @ts-expect-error - testing protected field. + ws._audioLengthMs = 42.8; + ws._interrupt(100, false); + const call = sendSpy.mock.calls.find( + (c: unknown[]) => (c[0] as any).type === 'conversation.item.truncate', + ); + expect((call?.[0] as any).audio_end_ms).toBe(42); + expect(Number.isInteger((call?.[0] as any).audio_end_ms)).toBe(true); + sendSpy.mockRestore(); + }); + it('_interrupt quantizes and clamps elapsedTime', () => { const ws = new OpenAIRealtimeWebSocket(); const sendSpy = vi