File tree Expand file tree Collapse file tree 8 files changed +61
-28
lines changed Expand file tree Collapse file tree 8 files changed +61
-28
lines changed Original file line number Diff line number Diff line change 1- /**
2- * EventHandler callback
3- * @typedef {(event: {[key: string]: any}): void } EventHandlerCallbackType
4- */
51/**
62 * Inherited class for RealtimeAPI and RealtimeClient
73 * Adds basic event handling
@@ -45,6 +41,15 @@ export class RealtimeEventHandler {
4541 * @returns {true }
4642 */
4743 offNext ( eventName : string , callback ?: EventHandlerCallbackType ) : true ;
44+ /**
45+ * Waits for next event of a specific type and returns the payload
46+ * @param {string } eventName
47+ * @param {number|null } [timeout]
48+ * @returns {Promise<{[key: string]: any}|null> }
49+ */
50+ waitForNext ( eventName : string , timeout ?: number | null ) : Promise < {
51+ [ key : string ] : any ;
52+ } | null > ;
4853 /**
4954 * Executes all events in the order they were added, with .on() event handlers executing before .onNext() handlers
5055 * @param {string } eventName
Original file line number Diff line number Diff line change @@ -125,7 +125,7 @@ export class RealtimeAPI extends RealtimeEventHandler {
125125 } ,
126126 ) ;
127127 ws . on ( 'message' , ( data ) => {
128- const message = JSON . parse ( data ) ;
128+ const message = JSON . parse ( data . toString ( ) ) ;
129129 this . receive ( message . type , message ) ;
130130 } ) ;
131131 return new Promise ( ( resolve , reject ) => {
Original file line number Diff line number Diff line change @@ -3,8 +3,6 @@ import { RealtimeAPI } from './api.js';
33import { RealtimeConversation } from './conversation.js' ;
44import { RealtimeUtils } from './utils.js' ;
55
6- const sleep = ( t ) => new Promise ( ( r ) => setTimeout ( ( ) => r ( ) , t ) ) ;
7-
86/**
97 * Valid audio formats
108 * @typedef {"pcm16"|"g711-ulaw"|"g711-alaw" } AudioFormatType
@@ -648,30 +646,18 @@ export class RealtimeClient extends RealtimeEventHandler {
648646 * @returns {Promise<{item: ItemType}> }
649647 */
650648 async waitForNextItem ( ) {
651- let nextItem ;
652- this . onNext ( 'conversation.item.appended' , ( event ) => {
653- const { item } = event ;
654- nextItem = item ;
655- } ) ;
656- while ( ! nextItem ) {
657- await sleep ( 1 ) ;
658- }
659- return { item : nextItem } ;
649+ const event = await this . waitForNext ( 'conversation.item.appended' ) ;
650+ const { item } = event ;
651+ return { item } ;
660652 }
661653
662654 /**
663655 * Utility for waiting for the next `conversation.item.completed` event to be triggered by the server
664656 * @returns {Promise<{item: ItemType}> }
665657 */
666658 async waitForNextCompletedItem ( ) {
667- let nextItem ;
668- this . onNext ( 'conversation.item.completed' , ( event ) => {
669- const { item } = event ;
670- nextItem = item ;
671- } ) ;
672- while ( ! nextItem ) {
673- await sleep ( 1 ) ;
674- }
675- return { item : nextItem } ;
659+ const event = await this . waitForNext ( 'conversation.item.completed' ) ;
660+ const { item } = event ;
661+ return { item } ;
676662 }
677663}
Original file line number Diff line number Diff line change 33 * @typedef {(event: {[key: string]: any}): void } EventHandlerCallbackType
44 */
55
6+ const sleep = ( t ) => new Promise ( ( r ) => setTimeout ( ( ) => r ( ) , t ) ) ;
7+
68/**
79 * Inherited class for RealtimeAPI and RealtimeClient
810 * Adds basic event handling
@@ -97,6 +99,28 @@ export class RealtimeEventHandler {
9799 return true ;
98100 }
99101
102+ /**
103+ * Waits for next event of a specific type and returns the payload
104+ * @param {string } eventName
105+ * @param {number|null } [timeout]
106+ * @returns {Promise<{[key: string]: any}|null> }
107+ */
108+ async waitForNext ( eventName , timeout = null ) {
109+ const t0 = Date . now ( ) ;
110+ let nextEvent ;
111+ this . onNext ( eventName , ( event ) => ( nextEvent = event ) ) ;
112+ while ( ! nextEvent ) {
113+ if ( timeout ) {
114+ const t1 = Date . now ( ) ;
115+ if ( t1 - t0 > timeout ) {
116+ return null ;
117+ }
118+ }
119+ await sleep ( 1 ) ;
120+ }
121+ return nextEvent ;
122+ }
123+
100124 /**
101125 * Executes all events in the order they were added, with .on() event handlers executing before .onNext() handlers
102126 * @param {string } eventName
Original file line number Diff line number Diff line change @@ -7,6 +7,24 @@ export async function run() {
77 describe ( 'RealtimeAPI' , ( { debug = false } = { } ) => {
88 let realtime ;
99
10+ it ( 'Should instantiate the RealtimeAPI with no apiKey' , ( ) => {
11+ realtime = new RealtimeAPI ( {
12+ debug,
13+ } ) ;
14+
15+ expect ( realtime ) . to . exist ;
16+ expect ( realtime . apiKey ) . to . not . exist ;
17+ } ) ;
18+
19+ it ( 'Should fail to connect to the RealtimeAPI with no apiKey' , async ( ) => {
20+ await realtime . connect ( ) ;
21+ const event = await realtime . waitForNext ( 'server.error' , 1000 ) ;
22+
23+ expect ( event ) . to . exist ;
24+ expect ( event . error ) . to . exist ;
25+ expect ( event . error . message ) . to . contain ( 'Incorrect API key provided' ) ;
26+ } ) ;
27+
1028 it ( 'Should instantiate the RealtimeAPI' , ( ) => {
1129 realtime = new RealtimeAPI ( {
1230 apiKey : process . env . OPENAI_API_KEY ,
Original file line number Diff line number Diff line change @@ -82,7 +82,7 @@ export async function run({ debug = false } = {}) {
8282 expect ( serverEvent1 . event . type ) . to . equal ( 'session.created' ) ;
8383 } ) ;
8484
85- it ( 'Should send an audio file about toronto (.wav )' , ( ) => {
85+ it ( 'Should send an audio file about toronto (.mp3 )' , ( ) => {
8686 const sample = samples [ 'toronto-mp3' ] . base64 ;
8787 const content = [ { type : 'input_audio' , audio : sample } ] ;
8888
You can’t perform that action at this time.
0 commit comments