@@ -636,7 +636,7 @@ describe("RooHandler", () => {
636636 handler = new RooHandler ( mockOptions )
637637 } )
638638
639- it ( "should yield tool calls when finish_reason is tool_calls" , async ( ) => {
639+ it ( "should yield raw tool call chunks when tool_calls present " , async ( ) => {
640640 mockCreate . mockResolvedValueOnce ( {
641641 [ Symbol . asyncIterator ] : async function * ( ) {
642642 yield {
@@ -689,14 +689,27 @@ describe("RooHandler", () => {
689689 chunks . push ( chunk )
690690 }
691691
692- const toolCallChunks = chunks . filter ( ( chunk ) => chunk . type === "tool_call" )
693- expect ( toolCallChunks ) . toHaveLength ( 1 )
694- expect ( toolCallChunks [ 0 ] . id ) . toBe ( "call_123" )
695- expect ( toolCallChunks [ 0 ] . name ) . toBe ( "read_file" )
696- expect ( toolCallChunks [ 0 ] . arguments ) . toBe ( '{"path":"test.ts"}' )
692+ // Verify we get raw tool call chunks
693+ const rawChunks = chunks . filter ( ( chunk ) => chunk . type === "tool_call_partial" )
694+
695+ expect ( rawChunks ) . toHaveLength ( 2 )
696+ expect ( rawChunks [ 0 ] ) . toEqual ( {
697+ type : "tool_call_partial" ,
698+ index : 0 ,
699+ id : "call_123" ,
700+ name : "read_file" ,
701+ arguments : '{"path":"' ,
702+ } )
703+ expect ( rawChunks [ 1 ] ) . toEqual ( {
704+ type : "tool_call_partial" ,
705+ index : 0 ,
706+ id : undefined ,
707+ name : undefined ,
708+ arguments : 'test.ts"}' ,
709+ } )
697710 } )
698711
699- it ( "should yield tool calls even when finish_reason is not set (fallback behavior) " , async ( ) => {
712+ it ( "should yield raw tool call chunks even when finish_reason is not tool_calls " , async ( ) => {
700713 mockCreate . mockResolvedValueOnce ( {
701714 [ Symbol . asyncIterator ] : async function * ( ) {
702715 yield {
@@ -718,12 +731,11 @@ describe("RooHandler", () => {
718731 } ,
719732 ] ,
720733 }
721- // Stream ends without finish_reason being set to "tool_calls"
722734 yield {
723735 choices : [
724736 {
725737 delta : { } ,
726- finish_reason : "stop" , // Different finish reason
738+ finish_reason : "stop" ,
727739 index : 0 ,
728740 } ,
729741 ] ,
@@ -738,15 +750,19 @@ describe("RooHandler", () => {
738750 chunks . push ( chunk )
739751 }
740752
741- // Tool calls should still be yielded via the fallback mechanism
742- const toolCallChunks = chunks . filter ( ( chunk ) => chunk . type === "tool_call" )
743- expect ( toolCallChunks ) . toHaveLength ( 1 )
744- expect ( toolCallChunks [ 0 ] . id ) . toBe ( "call_456" )
745- expect ( toolCallChunks [ 0 ] . name ) . toBe ( "write_to_file" )
746- expect ( toolCallChunks [ 0 ] . arguments ) . toBe ( '{"path":"test.ts","content":"hello"}' )
753+ const rawChunks = chunks . filter ( ( chunk ) => chunk . type === "tool_call_partial" )
754+
755+ expect ( rawChunks ) . toHaveLength ( 1 )
756+ expect ( rawChunks [ 0 ] ) . toEqual ( {
757+ type : "tool_call_partial" ,
758+ index : 0 ,
759+ id : "call_456" ,
760+ name : "write_to_file" ,
761+ arguments : '{"path":"test.ts","content":"hello"}' ,
762+ } )
747763 } )
748764
749- it ( "should handle multiple tool calls" , async ( ) => {
765+ it ( "should handle multiple tool calls with different indices " , async ( ) => {
750766 mockCreate . mockResolvedValueOnce ( {
751767 [ Symbol . asyncIterator ] : async function * ( ) {
752768 yield {
@@ -800,15 +816,16 @@ describe("RooHandler", () => {
800816 chunks . push ( chunk )
801817 }
802818
803- const toolCallChunks = chunks . filter ( ( chunk ) => chunk . type === "tool_call" )
804- expect ( toolCallChunks ) . toHaveLength ( 2 )
805- expect ( toolCallChunks [ 0 ] . id ) . toBe ( "call_1" )
806- expect ( toolCallChunks [ 0 ] . name ) . toBe ( "read_file" )
807- expect ( toolCallChunks [ 1 ] . id ) . toBe ( "call_2" )
808- expect ( toolCallChunks [ 1 ] . name ) . toBe ( "read_file" )
819+ const rawChunks = chunks . filter ( ( chunk ) => chunk . type === "tool_call_partial" )
820+
821+ expect ( rawChunks ) . toHaveLength ( 2 )
822+ expect ( rawChunks [ 0 ] . index ) . toBe ( 0 )
823+ expect ( rawChunks [ 0 ] . id ) . toBe ( "call_1" )
824+ expect ( rawChunks [ 1 ] . index ) . toBe ( 1 )
825+ expect ( rawChunks [ 1 ] . id ) . toBe ( "call_2" )
809826 } )
810827
811- it ( "should accumulate tool call arguments across multiple chunks " , async ( ) => {
828+ it ( "should emit raw chunks for streaming arguments " , async ( ) => {
812829 mockCreate . mockResolvedValueOnce ( {
813830 [ Symbol . asyncIterator ] : async function * ( ) {
814831 yield {
@@ -876,14 +893,15 @@ describe("RooHandler", () => {
876893 chunks . push ( chunk )
877894 }
878895
879- const toolCallChunks = chunks . filter ( ( chunk ) => chunk . type === "tool_call" )
880- expect ( toolCallChunks ) . toHaveLength ( 1 )
881- expect ( toolCallChunks [ 0 ] . id ) . toBe ( "call_789" )
882- expect ( toolCallChunks [ 0 ] . name ) . toBe ( "execute_command" )
883- expect ( toolCallChunks [ 0 ] . arguments ) . toBe ( '{"command":"npm install"}' )
896+ const rawChunks = chunks . filter ( ( chunk ) => chunk . type === "tool_call_partial" )
897+
898+ expect ( rawChunks ) . toHaveLength ( 3 )
899+ expect ( rawChunks [ 0 ] . arguments ) . toBe ( '{"command":"' )
900+ expect ( rawChunks [ 1 ] . arguments ) . toBe ( "npm install" )
901+ expect ( rawChunks [ 2 ] . arguments ) . toBe ( '"}' )
884902 } )
885903
886- it ( "should not yield empty tool calls when no tool calls present" , async ( ) => {
904+ it ( "should not yield tool call chunks when no tool calls present" , async ( ) => {
887905 mockCreate . mockResolvedValueOnce ( {
888906 [ Symbol . asyncIterator ] : async function * ( ) {
889907 yield {
@@ -902,8 +920,8 @@ describe("RooHandler", () => {
902920 chunks . push ( chunk )
903921 }
904922
905- const toolCallChunks = chunks . filter ( ( chunk ) => chunk . type === "tool_call " )
906- expect ( toolCallChunks ) . toHaveLength ( 0 )
923+ const rawChunks = chunks . filter ( ( chunk ) => chunk . type === "tool_call_partial " )
924+ expect ( rawChunks ) . toHaveLength ( 0 )
907925 } )
908926 } )
909927} )
0 commit comments