Skip to content

fix: use web standard event apis for twilio websocket #127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

threepointone
Copy link
Contributor

the twilio websocket extension used the node ws specific apis for attaching event handlers, which made it throw in a cloudflare environment. this patch adds a fix to the types, and uses .addEventListener on the websocket instead of .on. this also adds a fix to load the right shim for workerd when using @openai/agents-realtime

the twilio websocket extension used the node `ws` specific apis for attaching event handlers, which made it throw in a cloudflare environment. this patch adds a fix to the types, and uses `.addEventListener` on the websocket instead of `.on`. this also adds a fix to load the right shim for workerd when using `@openai/agents-realtime`
Copy link

changeset-bot bot commented Jun 19, 2025

🦋 Changeset detected

Latest commit: cc04a29

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@openai/agents Patch
@openai/agents-extensions Patch
@openai/agents-realtime Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@@ -7,7 +7,13 @@ import {
RealtimeSessionConfig,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My IDE autoformatted this file, but the changes are minimal, pointed out below

Comment on lines +10 to +16
import type {
WebSocket as NodeWebSocket,
MessageEvent as NodeMessageEvent,
ErrorEvent as NodeErrorEvent,
} from 'ws';

import type { ErrorEvent } from 'undici-types';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import some types

@@ -48,7 +54,7 @@ export type TwilioRealtimeTransportLayerOptions =
* ```
*/
export class TwilioRealtimeTransportLayer extends OpenAIRealtimeWebSocket {
#twilioWebSocket: WebSocket;
#twilioWebSocket: WebSocket | NodeWebSocket;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change this type here to accept ws or a standard WebSocket

'Invalid mark name received:',
data.mark.name,
);
this.#twilioWebSocket.addEventListener(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change this to use .addEventListener

'message',
(message: MessageEvent | NodeMessageEvent) => {
try {
const data = JSON.parse(message.data.toString());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use message.data here

);
},
);
this.#twilioWebSocket.addEventListener('close', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change this to .addEventListener

this.close();
}
});
this.#twilioWebSocket.addEventListener(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change this to addEventListener

@@ -18,7 +24,7 @@ export type TwilioRealtimeTransportLayerOptions =
* The websocket that is receiving messages from Twilio's Media Streams API. Typically the
* connection gets passed into your request handler when running your WebSocket server.
*/
twilioWebSocket: WebSocket;
twilioWebSocket: WebSocket | NodeWebSocket;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

accept the websocket type

@threepointone
Copy link
Contributor Author

whoops, missed one failing test, should be fixed now

@threepointone
Copy link
Contributor Author

actually, don't land this just yet, I think there might be some quirks to handle

@@ -149,7 +150,8 @@ export class OpenAIRealtimeWebSocket
);
}

const websocketArguments = isBrowserEnvironment()
// browsers and workerd should use the protocols argument, node should use the headers argument
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

workerd's WebSocket constructor is "standards" based, so can't pass headers

export function isBrowserEnvironment(): boolean {
return false;
}
export const useWebSocketProtocols = true;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

open to some other name for this, but this seemed clear

@threepointone
Copy link
Contributor Author

ok, now it should be good to review and/or land.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants