@@ -92,28 +92,57 @@ export class NodeWebSocketHandler implements WebSocketHandler {
92
92
}
93
93
94
94
const messageQueue : unknown [ ] = [ ] ;
95
+ const errorQueue : Error [ ] = [ ] ;
95
96
let resolvePromise : ( ( ) => void ) | null = null ;
96
97
let isClosed = false ;
97
98
98
99
const messageListener = async ( event : MessageEvent ) : Promise < void > => {
100
+ let data : string ;
99
101
if ( event . data instanceof Blob ) {
100
- try {
101
- const obj = JSON . parse ( await event . data . text ( ) ) as unknown ;
102
- messageQueue . push ( obj ) ;
103
- if ( resolvePromise ) {
104
- resolvePromise ( ) ;
105
- resolvePromise = null ;
106
- }
107
- } catch ( e ) {
108
- console . warn ( 'Failed to parse WebSocket message to JSON:' , e ) ;
109
- }
102
+ data = await event . data . text ( ) ;
103
+ } else if ( typeof event . data === 'string' ) {
104
+ data = event . data ;
110
105
} else {
111
- throw new AIError (
112
- AIErrorCode . PARSE_FAILED ,
113
- `Failed to parse WebSocket response to JSON. ` +
114
- `Expected data to be a Blob, but was ${ typeof event . data } .`
106
+ errorQueue . push (
107
+ new AIError (
108
+ AIErrorCode . PARSE_FAILED ,
109
+ `Failed to parse WebSocket response. Expected data to be a Blob or string, but was ${ typeof event . data } .`
110
+ )
111
+ ) ;
112
+ if ( resolvePromise ) {
113
+ resolvePromise ( ) ;
114
+ resolvePromise = null ;
115
+ }
116
+ return ;
117
+ }
118
+
119
+ try {
120
+ const obj = JSON . parse ( data ) as unknown ;
121
+ messageQueue . push ( obj ) ;
122
+ } catch ( e ) {
123
+ const err = e as Error ;
124
+ errorQueue . push (
125
+ new AIError (
126
+ AIErrorCode . PARSE_FAILED ,
127
+ `Error parsing WebSocket message to JSON: ${ err . message } `
128
+ )
115
129
) ;
116
130
}
131
+
132
+ if ( resolvePromise ) {
133
+ resolvePromise ( ) ;
134
+ resolvePromise = null ;
135
+ }
136
+ } ;
137
+
138
+ const errorListener = ( ) : void => {
139
+ errorQueue . push (
140
+ new AIError ( AIErrorCode . FETCH_ERROR , 'WebSocket connection error.' )
141
+ ) ;
142
+ if ( resolvePromise ) {
143
+ resolvePromise ( ) ;
144
+ resolvePromise = null ;
145
+ }
117
146
} ;
118
147
119
148
const closeListener = ( ) : void => {
@@ -122,15 +151,21 @@ export class NodeWebSocketHandler implements WebSocketHandler {
122
151
resolvePromise ( ) ;
123
152
resolvePromise = null ;
124
153
}
125
- // Clean up listeners to prevent memory leaks
154
+ // Clean up listeners to prevent memory leaks.
126
155
this . ws ?. removeEventListener ( 'message' , messageListener ) ;
127
156
this . ws ?. removeEventListener ( 'close' , closeListener ) ;
157
+ this . ws ?. removeEventListener ( 'error' , errorListener ) ;
128
158
} ;
129
159
130
160
this . ws . addEventListener ( 'message' , messageListener ) ;
131
161
this . ws . addEventListener ( 'close' , closeListener ) ;
162
+ this . ws . addEventListener ( 'error' , errorListener ) ;
132
163
133
164
while ( ! isClosed ) {
165
+ if ( errorQueue . length > 0 ) {
166
+ const error = errorQueue . shift ( ) ! ;
167
+ throw error ;
168
+ }
134
169
if ( messageQueue . length > 0 ) {
135
170
yield messageQueue . shift ( ) ! ;
136
171
} else {
@@ -139,6 +174,12 @@ export class NodeWebSocketHandler implements WebSocketHandler {
139
174
} ) ;
140
175
}
141
176
}
177
+
178
+ // If the loop terminated because isClosed is true, check for any final errors
179
+ if ( errorQueue . length > 0 ) {
180
+ const error = errorQueue . shift ( ) ! ;
181
+ throw error ;
182
+ }
142
183
}
143
184
144
185
close ( code ?: number , reason ?: string ) : Promise < void > {
@@ -148,7 +189,7 @@ export class NodeWebSocketHandler implements WebSocketHandler {
148
189
}
149
190
150
191
this . ws . addEventListener ( 'close' , ( ) => resolve ( ) , { once : true } ) ;
151
- // Calling 'close' during these states results in an error.
192
+ // Calling 'close' during these states results in an error
152
193
if (
153
194
this . ws . readyState === WebSocket . CLOSED ||
154
195
this . ws . readyState === WebSocket . CONNECTING
0 commit comments