@@ -312,17 +312,15 @@ class OpenAICompletionService extends BaseService {
312
312
if ( stream ) {
313
313
let usage_promise = new TeePromise ( ) ;
314
314
315
- const entire = [ ] ;
316
- const stream = new PassThrough ( ) ;
317
- const retval = new TypedValue ( {
318
- $ : 'stream' ,
319
- content_type : 'application/x-ndjson' ,
320
- chunked : true ,
321
- } , stream ) ;
322
- ( async ( ) => {
315
+ const init_chat_stream = async ( { chatStream } ) => {
316
+ const message = chatStream . message ( ) ;
317
+ let textblock = message . contentBlock ( { type : 'text' } ) ;
318
+ let toolblock = null ;
319
+ let mode = 'text' ;
320
+ const tool_call_blocks = [ ] ;
321
+
323
322
for await ( const chunk of completion ) {
324
- // console.log('CHUNK', chunk, JSON.stringify(chunk?.choices?.[0]?.delta ?? null));
325
- entire . push ( chunk ) ;
323
+ console . log ( 'CHUNK' , chunk , JSON . stringify ( chunk ?. choices ?. [ 0 ] ?. delta ?? null ) ) ;
326
324
if ( chunk . usage ) {
327
325
usage_promise . resolve ( {
328
326
input_tokens : chunk . usage . prompt_tokens ,
@@ -331,18 +329,47 @@ class OpenAICompletionService extends BaseService {
331
329
continue ;
332
330
}
333
331
if ( chunk . choices . length < 1 ) continue ;
334
- if ( nou ( chunk . choices [ 0 ] . delta . content ) ) continue ;
335
- const str = JSON . stringify ( {
336
- text : chunk . choices [ 0 ] . delta . content
337
- } ) ;
338
- stream . write ( str + '\n' ) ;
332
+
333
+ const choice = chunk . choices [ 0 ] ;
334
+
335
+ if ( ! nou ( choice . delta . content ) ) {
336
+ if ( mode === 'tool' ) {
337
+ toolblock . end ( ) ;
338
+ mode = 'text' ;
339
+ textblock = message . contentBlock ( { type : 'text' } ) ;
340
+ }
341
+ textblock . addText ( choice . delta . content ) ;
342
+ continue ;
343
+ }
344
+
345
+ if ( ! nou ( choice . delta . tool_calls ) ) {
346
+ if ( mode === 'text' ) {
347
+ mode = 'tool' ;
348
+ textblock . end ( ) ;
349
+ }
350
+ for ( const tool_call of choice . delta . tool_calls ) {
351
+ if ( ! tool_call_blocks [ tool_call . index ] ) {
352
+ toolblock = message . contentBlock ( {
353
+ type : 'tool_use' ,
354
+ id : tool_call . function . name ,
355
+ } ) ;
356
+ tool_call_blocks [ tool_call . index ] = toolblock ;
357
+ } else {
358
+ toolblock = tool_call_blocks [ tool_call . index ] ;
359
+ }
360
+ toolblock . addPartialJSON ( tool_call . function . arguments ) ;
361
+ }
362
+ }
339
363
}
340
- stream . end ( ) ;
341
- } ) ( ) ;
364
+
365
+ if ( mode === 'text' ) textblock . end ( ) ;
366
+ if ( mode === 'tool' ) toolblock . end ( ) ;
367
+ message . end ( ) ;
368
+ } ;
342
369
343
370
return new TypedValue ( { $ : 'ai-chat-intermediate' } , {
344
371
stream : true ,
345
- response : retval ,
372
+ init_chat_stream ,
346
373
usage_promise : usage_promise ,
347
374
} ) ;
348
375
return retval ;
0 commit comments