@@ -340,12 +340,6 @@ describe('executeAnthropicProviderRequest none thinking level', () => {
340340 return create . mock . calls [ 0 ] [ 0 ] as Anthropic . Messages . MessageCreateParams
341341 }
342342
343- it ( 'sends bare between_tools thinking on claude-sonnet-5-5' , async ( ) => {
344- const payload = await sendWithThinkingNone ( 'claude-sonnet-5-5' )
345- expect ( payload . thinking ) . toEqual ( { type : 'between_tools' } )
346- expect ( payload . output_config ) . toBeUndefined ( )
347- } )
348-
349343 it . each ( [ 'claude-sonnet-5' , 'claude-opus-5-5' ] ) (
350344 'sends no thinking config on %s' ,
351345 async ( model ) => {
@@ -796,6 +790,89 @@ describe('streaming', () => {
796790 }
797791 } )
798792 } )
793+
794+ /**
795+ * Both tool loops rebuild the request for every turn after a tool call, so
796+ * Sonnet 5.5's `none` mapping must survive past the first request: a later
797+ * turn without it would silently run adaptive thinking at the API default.
798+ */
799+ describe ( 'executeAnthropicProviderRequest none thinking level across tool turns' , ( ) => {
800+ const lookupTool = {
801+ id : 'lookup' ,
802+ name : 'lookup' ,
803+ description : 'Lookup' ,
804+ params : { } ,
805+ parameters : { type : 'object' , properties : { } , required : [ ] } ,
806+ }
807+ const toolTurn = message (
808+ [ { type : 'tool_use' , id : 'tool-1' , name : 'lookup' , input : { } } ] ,
809+ 'tool_use'
810+ )
811+ const answerTurn = message ( [ { type : 'text' , text : 'done' } ] , 'end_turn' )
812+
813+ function expectBareBetweenTools ( payloads : Anthropic . Messages . MessageCreateParams [ ] ) {
814+ expect ( payloads ) . toHaveLength ( 2 )
815+ for ( const payload of payloads ) {
816+ expect ( payload . thinking ) . toEqual ( { type : 'between_tools' } )
817+ expect ( payload . output_config ) . toBeUndefined ( )
818+ }
819+ }
820+
821+ it ( 'sends bare between_tools on every non-streaming turn' , async ( ) => {
822+ mockExecuteTool . mockResolvedValue ( { success : true , output : { value : 'tool result' } } )
823+ const create = vi . fn ( ) . mockResolvedValueOnce ( toolTurn ) . mockResolvedValueOnce ( answerTurn )
824+
825+ await executeAnthropicProviderRequest (
826+ {
827+ model : 'claude-sonnet-5-5' ,
828+ apiKey : 'test-key' ,
829+ maxTokens : 1024 ,
830+ thinkingLevel : 'none' ,
831+ agentEvents : true ,
832+ messages : [ { role : 'user' , content : 'Look this up' } ] ,
833+ tools : [ lookupTool ] ,
834+ } ,
835+ {
836+ providerId : 'anthropic' ,
837+ providerLabel : 'Anthropic' ,
838+ createClient : ( ) => ( { messages : { create } } ) as never ,
839+ logger : { info : vi . fn ( ) , warn : vi . fn ( ) , error : vi . fn ( ) , debug : vi . fn ( ) } ,
840+ }
841+ )
842+
843+ expectBareBetweenTools ( create . mock . calls . map ( ( call ) => call [ 0 ] ) )
844+ } )
845+
846+ it ( 'sends bare between_tools on every streaming turn' , async ( ) => {
847+ mockExecuteTool . mockResolvedValue ( { success : true , output : { value : 'tool result' } } )
848+ const createStream = vi
849+ . fn ( )
850+ . mockReturnValueOnce ( stream ( [ { type : 'message_stop' } ] , toolTurn ) )
851+ . mockReturnValueOnce ( stream ( [ { type : 'message_stop' } ] , answerTurn ) )
852+
853+ const result = ( await executeAnthropicProviderRequest (
854+ {
855+ model : 'claude-sonnet-5-5' ,
856+ apiKey : 'test-key' ,
857+ stream : true ,
858+ maxTokens : 1024 ,
859+ thinkingLevel : 'none' ,
860+ agentEvents : true ,
861+ messages : [ { role : 'user' , content : 'Look this up' } ] ,
862+ tools : [ lookupTool ] ,
863+ } ,
864+ {
865+ providerId : 'anthropic' ,
866+ providerLabel : 'Anthropic' ,
867+ createClient : ( ) => ( { messages : { stream : createStream } } ) as never ,
868+ logger : { info : vi . fn ( ) , warn : vi . fn ( ) , error : vi . fn ( ) , debug : vi . fn ( ) } ,
869+ }
870+ ) ) as StreamingExecution
871+ await collectEvents ( result )
872+
873+ expectBareBetweenTools ( createStream . mock . calls . map ( ( call ) => call [ 0 ] ) )
874+ } )
875+ } )
799876} )
800877
801878/**
0 commit comments