@@ -484,6 +484,25 @@ describe("AI SDK conversion utilities", () => {
484484 } )
485485 } )
486486
487+ it ( "uses args when tool-call input is an empty object" , ( ) => {
488+ const part = {
489+ type : "tool-call" as const ,
490+ toolCallId : "call_1" ,
491+ toolName : "attempt_completion" ,
492+ input : { } ,
493+ args : { result : "done" } ,
494+ }
495+ const chunks = [ ...processAiSdkStreamPart ( part as any ) ]
496+
497+ expect ( chunks ) . toHaveLength ( 1 )
498+ expect ( chunks [ 0 ] ) . toEqual ( {
499+ type : "tool_call" ,
500+ id : "call_1" ,
501+ name : "attempt_completion" ,
502+ arguments : '{"result":"done"}' ,
503+ } )
504+ } )
505+
487506 it ( "processes complete tool-call chunks with arguments" , ( ) => {
488507 const part = {
489508 type : "tool-call" as const ,
@@ -502,7 +521,7 @@ describe("AI SDK conversion utilities", () => {
502521 } )
503522 } )
504523
505- it ( "emits the complete tool-call chunk after streaming input chunks" , ( ) => {
524+ it ( "emits complete tool-input-available after streaming input chunks" , ( ) => {
506525 const seenStreamingToolCallIds = new Set < string > ( )
507526 const chunks = [
508527 ...processAiSdkStreamPart (
@@ -516,7 +535,7 @@ describe("AI SDK conversion utilities", () => {
516535 ...processAiSdkStreamPart ( { type : "tool-input-end" as const , id : "call_1" } , seenStreamingToolCallIds ) ,
517536 ...processAiSdkStreamPart (
518537 {
519- type : "tool-call " as const ,
538+ type : "tool-input-available " as const ,
520539 toolCallId : "call_1" ,
521540 toolName : "attempt_completion" ,
522541 input : { result : "done" } ,
@@ -534,6 +553,78 @@ describe("AI SDK conversion utilities", () => {
534553 } ,
535554 ] )
536555 expect ( seenStreamingToolCallIds . has ( "call_1" ) ) . toBe ( false )
556+ expect ( seenStreamingToolCallIds . has ( "completed:call_1" ) ) . toBe ( true )
557+ } )
558+
559+ it ( "ignores duplicate tool-call chunks after complete tool-input-available chunks" , ( ) => {
560+ const seenStreamingToolCallIds = new Set < string > ( )
561+ const chunks = [
562+ ...processAiSdkStreamPart (
563+ {
564+ type : "tool-input-available" as const ,
565+ toolCallId : "call_1" ,
566+ toolName : "attempt_completion" ,
567+ input : { result : "done" } ,
568+ } ,
569+ seenStreamingToolCallIds ,
570+ ) ,
571+ ...processAiSdkStreamPart (
572+ {
573+ type : "tool-call" as const ,
574+ toolCallId : "call_1" ,
575+ toolName : "attempt_completion" ,
576+ input : { result : "done" } ,
577+ } ,
578+ seenStreamingToolCallIds ,
579+ ) ,
580+ ]
581+
582+ expect ( chunks ) . toEqual ( [
583+ {
584+ type : "tool_call" ,
585+ id : "call_1" ,
586+ name : "attempt_completion" ,
587+ arguments : '{"result":"done"}' ,
588+ } ,
589+ ] )
590+ expect ( seenStreamingToolCallIds . has ( "completed:call_1" ) ) . toBe ( false )
591+ } )
592+
593+ it ( "ignores tool-input-available for calls that are still streaming input" , ( ) => {
594+ const seenStreamingToolCallIds = new Set < string > ( )
595+ const chunks = [
596+ ...processAiSdkStreamPart (
597+ { type : "tool-input-start" as const , id : "call_1" , toolName : "attempt_completion" } ,
598+ seenStreamingToolCallIds ,
599+ ) ,
600+ ...processAiSdkStreamPart (
601+ {
602+ type : "tool-input-available" as const ,
603+ toolCallId : "call_1" ,
604+ toolName : "attempt_completion" ,
605+ input : { } ,
606+ } ,
607+ seenStreamingToolCallIds ,
608+ ) ,
609+ ...processAiSdkStreamPart (
610+ {
611+ type : "tool-call" as const ,
612+ toolCallId : "call_1" ,
613+ toolName : "attempt_completion" ,
614+ input : { result : "done" } ,
615+ } ,
616+ seenStreamingToolCallIds ,
617+ ) ,
618+ ]
619+
620+ expect ( chunks ) . toEqual ( [
621+ {
622+ type : "tool_call" ,
623+ id : "call_1" ,
624+ name : "attempt_completion" ,
625+ arguments : '{"result":"done"}' ,
626+ } ,
627+ ] )
537628 } )
538629
539630 it ( "processes source chunks with URL" , ( ) => {
0 commit comments