@@ -51,13 +51,20 @@ class StreamProcessor {
51
51
this . clientProvidedTools = clientProvidedTools ;
52
52
}
53
53
54
- async processStream ( body : ReadableStream < Uint8Array > ) : Promise < void > {
54
+ async processStream (
55
+ body : ReadableStream < Uint8Array > ,
56
+ abortSignal ?: AbortSignal
57
+ ) : Promise < void > {
55
58
const reader = body . getReader ( ) ;
56
59
const decoder = new TextDecoder ( ) ;
57
60
let buffer = '' ;
58
61
59
62
try {
60
63
while ( true ) {
64
+ if ( abortSignal ?. aborted ) {
65
+ throw new Error ( 'Stream processing was aborted' ) ;
66
+ }
67
+
61
68
const { done, value } = await reader . read ( ) ;
62
69
if ( done ) break ;
63
70
@@ -73,6 +80,11 @@ class StreamProcessor {
73
80
}
74
81
}
75
82
} catch ( error ) {
83
+ if ( abortSignal ?. aborted || ( error as Error ) . name === 'AbortError' ) {
84
+ console . log ( 'Stream processing was cancelled' ) ;
85
+ return ;
86
+ }
87
+
76
88
const apiError : SchemaError = {
77
89
error : ( error as Error ) . message || 'Unknown error' ,
78
90
} ;
@@ -215,10 +227,10 @@ class StreamProcessor {
215
227
}
216
228
217
229
private finalizeIncompleteToolCalls ( ) : void {
218
- for ( const [ , toolCall ] of this . incompleteToolCalls . entries ( ) ) {
230
+ this . incompleteToolCalls . forEach ( ( toolCall ) => {
219
231
if ( ! toolCall . id || ! toolCall . function . name ) {
220
232
globalThis . console . warn ( 'Incomplete tool call detected:' , toolCall ) ;
221
- continue ;
233
+ return ;
222
234
}
223
235
224
236
const completedToolCall = {
@@ -237,15 +249,26 @@ class StreamProcessor {
237
249
}
238
250
this . callbacks . onMCPTool ?.( completedToolCall ) ;
239
251
} catch ( argError ) {
240
- globalThis . console . warn (
241
- `Invalid MCP tool arguments for ${ toolCall . function . name } :` ,
242
- argError
243
- ) ;
252
+ const isIncompleteJSON =
253
+ toolCall . function . arguments &&
254
+ ! toolCall . function . arguments . trim ( ) . endsWith ( '}' ) ;
255
+
256
+ if ( isIncompleteJSON ) {
257
+ globalThis . console . warn (
258
+ `Incomplete MCP tool arguments for ${ toolCall . function . name } (stream was likely interrupted):` ,
259
+ toolCall . function . arguments
260
+ ) ;
261
+ } else {
262
+ globalThis . console . warn (
263
+ `Invalid MCP tool arguments for ${ toolCall . function . name } :` ,
264
+ argError
265
+ ) ;
266
+ }
244
267
}
245
268
} else {
246
269
this . callbacks . onTool ?.( completedToolCall ) ;
247
270
}
248
- }
271
+ } ) ;
249
272
this . incompleteToolCalls . clear ( ) ;
250
273
}
251
274
@@ -280,7 +303,7 @@ export class InferenceGatewayClient {
280
303
this . apiKey = options . apiKey ;
281
304
this . defaultHeaders = options . defaultHeaders || { } ;
282
305
this . defaultQuery = options . defaultQuery || { } ;
283
- this . timeout = options . timeout || 30000 ;
306
+ this . timeout = options . timeout || 60000 ; // Increased default timeout to 60 seconds
284
307
this . fetchFn = options . fetch || globalThis . fetch ;
285
308
}
286
309
@@ -404,17 +427,23 @@ export class InferenceGatewayClient {
404
427
* @param request - Chat completion request (must include at least model and messages)
405
428
* @param callbacks - Callbacks for handling streaming events
406
429
* @param provider - Optional provider to use for this request
430
+ * @param abortSignal - Optional AbortSignal to cancel the request
407
431
*/
408
432
async streamChatCompletion (
409
433
request : Omit <
410
434
SchemaCreateChatCompletionRequest ,
411
435
'stream' | 'stream_options'
412
436
> ,
413
437
callbacks : ChatCompletionStreamCallbacks ,
414
- provider ?: Provider
438
+ provider ?: Provider ,
439
+ abortSignal ?: AbortSignal
415
440
) : Promise < void > {
416
441
try {
417
- const response = await this . initiateStreamingRequest ( request , provider ) ;
442
+ const response = await this . initiateStreamingRequest (
443
+ request ,
444
+ provider ,
445
+ abortSignal
446
+ ) ;
418
447
419
448
if ( ! response . body ) {
420
449
const error : SchemaError = {
@@ -440,7 +469,7 @@ export class InferenceGatewayClient {
440
469
callbacks ,
441
470
clientProvidedTools
442
471
) ;
443
- await streamProcessor . processStream ( response . body ) ;
472
+ await streamProcessor . processStream ( response . body , abortSignal ) ;
444
473
} catch ( error ) {
445
474
const apiError : SchemaError = {
446
475
error : ( error as Error ) . message || 'Unknown error occurred' ,
@@ -458,7 +487,8 @@ export class InferenceGatewayClient {
458
487
SchemaCreateChatCompletionRequest ,
459
488
'stream' | 'stream_options'
460
489
> ,
461
- provider ?: Provider
490
+ provider ?: Provider ,
491
+ abortSignal ?: AbortSignal
462
492
) : Promise < Response > {
463
493
const query : Record < string , string > = { } ;
464
494
if ( provider ) {
@@ -485,6 +515,11 @@ export class InferenceGatewayClient {
485
515
}
486
516
487
517
const controller = new AbortController ( ) ;
518
+
519
+ const combinedSignal = abortSignal
520
+ ? AbortSignal . any ( [ abortSignal , controller . signal ] )
521
+ : controller . signal ;
522
+
488
523
const timeoutId = globalThis . setTimeout (
489
524
( ) => controller . abort ( ) ,
490
525
this . timeout
@@ -501,7 +536,7 @@ export class InferenceGatewayClient {
501
536
include_usage : true ,
502
537
} ,
503
538
} ) ,
504
- signal : controller . signal ,
539
+ signal : combinedSignal ,
505
540
} ) ;
506
541
507
542
if ( ! response . ok ) {
0 commit comments