@@ -74,6 +74,30 @@ function latestAnthropicRequestHeaders() {
7474 return new Headers ( latestAnthropicRequest ( ) . init ?. headers ) ;
7575}
7676
77+ function requireRecord ( value : unknown , label : string ) : Record < string , unknown > {
78+ if ( ! value || typeof value !== "object" || Array . isArray ( value ) ) {
79+ throw new Error ( `Expected ${ label } ` ) ;
80+ }
81+ return value as Record < string , unknown > ;
82+ }
83+
84+ function requireArray ( value : unknown , label : string ) : unknown [ ] {
85+ if ( ! Array . isArray ( value ) ) {
86+ throw new Error ( `Expected ${ label } ` ) ;
87+ }
88+ return value ;
89+ }
90+
91+ function findRecord ( items : unknown , predicate : ( record : Record < string , unknown > ) => boolean ) {
92+ for ( const item of requireArray ( items , "items" ) ) {
93+ const record = requireRecord ( item , "item" ) ;
94+ if ( predicate ( record ) ) {
95+ return record ;
96+ }
97+ }
98+ throw new Error ( "Expected matching record" ) ;
99+ }
100+
77101function makeAnthropicTransportModel (
78102 params : {
79103 id ?: string ;
@@ -154,25 +178,19 @@ describe("anthropic transport stream", () => {
154178 ) ;
155179
156180 expect ( buildGuardedModelFetchMock ) . toHaveBeenCalledWith ( model ) ;
157- expect ( guardedFetchMock ) . toHaveBeenCalledWith (
158- "https://api.anthropic.com/v1/messages" ,
159- expect . objectContaining ( {
160- method : "POST" ,
161- headers : expect . objectContaining ( {
162- "x-api-key" : "sk-ant-api" ,
163- "anthropic-version" : "2023-06-01" ,
164- "content-type" : "application/json" ,
165- accept : "application/json" ,
166- "anthropic-dangerous-direct-browser-access" : "true" ,
167- "X-Provider" : "anthropic" ,
168- "X-Call" : "1" ,
169- } ) ,
170- } ) ,
171- ) ;
172- expect ( latestAnthropicRequest ( ) . payload ) . toMatchObject ( {
173- model : "claude-sonnet-4-6" ,
174- stream : true ,
175- } ) ;
181+ const [ url , init ] = guardedFetchMock . mock . calls [ 0 ] ?? [ ] ;
182+ expect ( url ) . toBe ( "https://api.anthropic.com/v1/messages" ) ;
183+ expect ( init ?. method ) . toBe ( "POST" ) ;
184+ const headers = new Headers ( init ?. headers ) ;
185+ expect ( headers . get ( "x-api-key" ) ) . toBe ( "sk-ant-api" ) ;
186+ expect ( headers . get ( "anthropic-version" ) ) . toBe ( "2023-06-01" ) ;
187+ expect ( headers . get ( "content-type" ) ) . toBe ( "application/json" ) ;
188+ expect ( headers . get ( "accept" ) ) . toBe ( "application/json" ) ;
189+ expect ( headers . get ( "anthropic-dangerous-direct-browser-access" ) ) . toBe ( "true" ) ;
190+ expect ( headers . get ( "X-Provider" ) ) . toBe ( "anthropic" ) ;
191+ expect ( headers . get ( "X-Call" ) ) . toBe ( "1" ) ;
192+ expect ( latestAnthropicRequest ( ) . payload . model ) . toBe ( "claude-sonnet-4-6" ) ;
193+ expect ( latestAnthropicRequest ( ) . payload . stream ) . toBe ( true ) ;
176194 expect ( latestAnthropicRequestHeaders ( ) . get ( "anthropic-beta" ) ) . toBe (
177195 "fine-grained-tool-streaming-2025-05-14" ,
178196 ) ;
@@ -194,10 +212,8 @@ describe("anthropic transport stream", () => {
194212 } as AnthropicStreamOptions ,
195213 ) ;
196214
197- expect ( guardedFetchMock ) . toHaveBeenCalledWith (
198- "https://custom-proxy.example/v1/messages" ,
199- expect . objectContaining ( { method : "POST" } ) ,
200- ) ;
215+ expect ( guardedFetchMock . mock . calls [ 0 ] ?. [ 0 ] ) . toBe ( "https://custom-proxy.example/v1/messages" ) ;
216+ expect ( guardedFetchMock . mock . calls [ 0 ] ?. [ 1 ] ?. method ) . toBe ( "POST" ) ;
201217 expect ( latestAnthropicRequestHeaders ( ) . get ( "anthropic-beta" ) ) . toBeNull ( ) ;
202218 } ) ;
203219
@@ -278,11 +294,9 @@ describe("anthropic transport stream", () => {
278294 } as AnthropicStreamOptions ,
279295 ) ;
280296
281- expect ( latestAnthropicRequest ( ) . payload ) . toMatchObject ( {
282- model : "claude-sonnet-4-6" ,
283- max_tokens : 8192 ,
284- stream : true ,
285- } ) ;
297+ expect ( latestAnthropicRequest ( ) . payload . model ) . toBe ( "claude-sonnet-4-6" ) ;
298+ expect ( latestAnthropicRequest ( ) . payload . max_tokens ) . toBe ( 8192 ) ;
299+ expect ( latestAnthropicRequest ( ) . payload . stream ) . toBe ( true ) ;
286300 } ) ;
287301
288302 it ( "ignores fractional runtime maxTokens overrides that floor to zero" , async ( ) => {
@@ -297,11 +311,9 @@ describe("anthropic transport stream", () => {
297311 } as AnthropicStreamOptions ,
298312 ) ;
299313
300- expect ( latestAnthropicRequest ( ) . payload ) . toMatchObject ( {
301- model : "claude-sonnet-4-6" ,
302- max_tokens : 8192 ,
303- stream : true ,
304- } ) ;
314+ expect ( latestAnthropicRequest ( ) . payload . model ) . toBe ( "claude-sonnet-4-6" ) ;
315+ expect ( latestAnthropicRequest ( ) . payload . max_tokens ) . toBe ( 8192 ) ;
316+ expect ( latestAnthropicRequest ( ) . payload . stream ) . toBe ( true ) ;
305317 } ) ;
306318
307319 it ( "fails locally when Anthropic maxTokens is non-positive after resolution" , async ( ) => {
@@ -427,33 +439,31 @@ describe("anthropic transport stream", () => {
427439 ) ;
428440 const result = await stream . result ( ) ;
429441
430- expect ( guardedFetchMock ) . toHaveBeenCalledWith (
431- "https://api.anthropic.com/v1/messages" ,
432- expect . objectContaining ( {
433- headers : expect . objectContaining ( {
434- authorization : "Bearer sk-ant-oat-example" ,
435- "x-app" : "cli" ,
436- "user-agent" : expect . stringContaining ( "claude-cli/" ) ,
437- } ) ,
438- } ) ,
439- ) ;
442+ expect ( guardedFetchMock . mock . calls [ 0 ] ?. [ 0 ] ) . toBe ( "https://api.anthropic.com/v1/messages" ) ;
443+ const headers = new Headers ( guardedFetchMock . mock . calls [ 0 ] ?. [ 1 ] ?. headers ) ;
444+ expect ( headers . get ( "authorization" ) ) . toBe ( "Bearer sk-ant-oat-example" ) ;
445+ expect ( headers . get ( "x-app" ) ) . toBe ( "cli" ) ;
446+ expect ( headers . get ( "user-agent" ) ) . toContain ( "claude-cli/" ) ;
440447 const firstCallParams = latestAnthropicRequest ( ) . payload ;
441- expect ( firstCallParams . system ) . toEqual (
442- expect . arrayContaining ( [
443- expect . objectContaining ( {
444- text : "You are Claude Code, Anthropic's official CLI for Claude." ,
445- } ) ,
446- expect . objectContaining ( {
447- text : "Follow policy." ,
448- } ) ,
449- ] ) ,
450- ) ;
451- expect ( firstCallParams . tools ) . toEqual (
452- expect . arrayContaining ( [ expect . objectContaining ( { name : "Read" } ) ] ) ,
453- ) ;
448+ const system = requireArray ( firstCallParams . system , "system" ) ;
449+ expect (
450+ system . some (
451+ ( item ) =>
452+ requireRecord ( item , "system item" ) . text ===
453+ "You are Claude Code, Anthropic's official CLI for Claude." ,
454+ ) ,
455+ ) . toBe ( true ) ;
456+ expect (
457+ system . some ( ( item ) => requireRecord ( item , "system item" ) . text === "Follow policy." ) ,
458+ ) . toBe ( true ) ;
459+ expect (
460+ requireArray ( firstCallParams . tools , "tools" ) . some (
461+ ( item ) => requireRecord ( item , "tool" ) . name === "Read" ,
462+ ) ,
463+ ) . toBe ( true ) ;
454464 expect ( result . stopReason ) . toBe ( "toolUse" ) ;
455- expect ( result . content ) . toEqual (
456- expect . arrayContaining ( [ expect . objectContaining ( { type : "toolCall" , name : "read" } ) ] ) ,
465+ expect ( result . content . some ( ( item ) => item . type === "toolCall" && item . name === "read" ) ) . toBe (
466+ true ,
457467 ) ;
458468 } ) ;
459469
@@ -516,19 +526,16 @@ describe("anthropic transport stream", () => {
516526 }
517527 const result = await stream . result ( ) ;
518528
519- expect ( result . content ) . toEqual ( [
520- expect . objectContaining ( {
521- type : "thinking" ,
522- thinking : "checking" ,
523- thinkingSignature : "sig_2" ,
524- } ) ,
525- { type : "text" , text : "NO_REPLY" } ,
526- ] ) ;
527- expect ( events ) . toEqual (
528- expect . arrayContaining ( [
529- expect . objectContaining ( { type : "text_delta" , delta : "NO_REPLY" } ) ,
530- expect . objectContaining ( { type : "text_end" , content : "NO_REPLY" } ) ,
531- ] ) ,
529+ const thinkingContent = requireRecord ( result . content [ 0 ] , "thinking content" ) ;
530+ expect ( thinkingContent . type ) . toBe ( "thinking" ) ;
531+ expect ( thinkingContent . thinking ) . toBe ( "checking" ) ;
532+ expect ( thinkingContent . thinkingSignature ) . toBe ( "sig_2" ) ;
533+ expect ( result . content [ 1 ] ) . toEqual ( { type : "text" , text : "NO_REPLY" } ) ;
534+ expect ( events . some ( ( event ) => event . type === "text_delta" && event . delta === "NO_REPLY" ) ) . toBe (
535+ true ,
536+ ) ;
537+ expect ( events . some ( ( event ) => event . type === "text_end" && event . content === "NO_REPLY" ) ) . toBe (
538+ true ,
532539 ) ;
533540 expect ( result . usage . output ) . toBe ( 9 ) ;
534541 } ) ;
@@ -583,12 +590,12 @@ describe("anthropic transport stream", () => {
583590
584591 expect ( result . content ) . toEqual ( [ { type : "text" , text : "你好" } ] ) ;
585592 expect ( result . stopReason ) . toBe ( "stop" ) ;
586- expect ( events ) . toEqual (
587- expect . arrayContaining ( [
588- expect . objectContaining ( { type : "text_start" } ) ,
589- expect . objectContaining ( { type : "text_delta" , delta : "你好" } ) ,
590- expect . objectContaining ( { type : "text_end" , content : "你好" } ) ,
591- ] ) ,
593+ expect ( events . some ( ( event ) => event . type === "text_start" ) ) . toBe ( true ) ;
594+ expect ( events . some ( ( event ) => event . type === "text_delta" && event . delta === "你好" ) ) . toBe (
595+ true ,
596+ ) ;
597+ expect ( events . some ( ( event ) => event . type === "text_end" && event . content === "你好" ) ) . toBe (
598+ true ,
592599 ) ;
593600 } ) ;
594601
@@ -621,16 +628,13 @@ describe("anthropic transport stream", () => {
621628 } as AnthropicStreamOptions ,
622629 ) ;
623630
624- expect ( latestAnthropicRequest ( ) . payload . tools ) . toEqual ( [
625- expect . objectContaining ( {
626- name : "good_plugin_tool" ,
627- input_schema : expect . objectContaining ( {
628- properties : {
629- query : { type : "string" } ,
630- } ,
631- } ) ,
632- } ) ,
633- ] ) ;
631+ const tools = requireArray ( latestAnthropicRequest ( ) . payload . tools , "tools" ) ;
632+ expect ( tools ) . toHaveLength ( 1 ) ;
633+ const tool = requireRecord ( tools [ 0 ] , "tool" ) ;
634+ expect ( tool . name ) . toBe ( "good_plugin_tool" ) ;
635+ expect ( requireRecord ( tool . input_schema , "input schema" ) . properties ) . toEqual ( {
636+ query : { type : "string" } ,
637+ } ) ;
634638 } ) ;
635639
636640 it ( "coerces replayed malformed tool-call args to an object for Anthropic payloads" , async ( ) => {
@@ -674,20 +678,15 @@ describe("anthropic transport stream", () => {
674678 await stream . result ( ) ;
675679
676680 const firstCallParams = latestAnthropicRequest ( ) . payload ;
677- expect ( firstCallParams . messages ) . toEqual (
678- expect . arrayContaining ( [
679- expect . objectContaining ( {
680- role : "assistant" ,
681- content : expect . arrayContaining ( [
682- expect . objectContaining ( {
683- type : "tool_use" ,
684- name : "lookup" ,
685- input : { } ,
686- } ) ,
687- ] ) ,
688- } ) ,
689- ] ) ,
681+ const assistantMessage = findRecord (
682+ firstCallParams . messages ,
683+ ( record ) => record . role === "assistant" ,
684+ ) ;
685+ const toolUse = findRecord (
686+ assistantMessage . content ,
687+ ( record ) => record . type === "tool_use" && record . name === "lookup" ,
690688 ) ;
689+ expect ( toolUse . input ) . toEqual ( { } ) ;
691690 } ) ;
692691
693692 it . each ( [
@@ -721,21 +720,16 @@ describe("anthropic transport stream", () => {
721720 } as AnthropicStreamOptions ,
722721 ) ;
723722
724- expect ( latestAnthropicRequest ( ) . payload . messages ) . toEqual (
725- expect . arrayContaining ( [
726- expect . objectContaining ( {
727- role : "user" ,
728- content : expect . arrayContaining ( [
729- expect . objectContaining ( {
730- type : "tool_result" ,
731- tool_use_id : "tool_1" ,
732- content : "(no output)" ,
733- is_error : false ,
734- } ) ,
735- ] ) ,
736- } ) ,
737- ] ) ,
723+ const userMessage = findRecord (
724+ latestAnthropicRequest ( ) . payload . messages ,
725+ ( record ) => record . role === "user" ,
726+ ) ;
727+ const toolResult = findRecord (
728+ userMessage . content ,
729+ ( record ) => record . type === "tool_result" && record . tool_use_id === "tool_1" ,
738730 ) ;
731+ expect ( toolResult . content ) . toBe ( "(no output)" ) ;
732+ expect ( toolResult . is_error ) . toBe ( false ) ;
739733 } ) ;
740734
741735 it ( "drops empty text blocks from image tool results before Anthropic payloads" , async ( ) => {
@@ -770,31 +764,26 @@ describe("anthropic transport stream", () => {
770764 } as AnthropicStreamOptions ,
771765 ) ;
772766
773- expect ( latestAnthropicRequest ( ) . payload . messages ) . toEqual (
774- expect . arrayContaining ( [
775- expect . objectContaining ( {
776- role : "user" ,
777- content : expect . arrayContaining ( [
778- expect . objectContaining ( {
779- type : "tool_result" ,
780- tool_use_id : "tool_1" ,
781- content : [
782- { type : "text" , text : "(see attached image)" } ,
783- {
784- type : "image" ,
785- source : {
786- type : "base64" ,
787- media_type : "image/png" ,
788- data : imageData ,
789- } ,
790- } ,
791- ] ,
792- is_error : false ,
793- } ) ,
794- ] ) ,
795- } ) ,
796- ] ) ,
767+ const userMessage = findRecord (
768+ latestAnthropicRequest ( ) . payload . messages ,
769+ ( record ) => record . role === "user" ,
770+ ) ;
771+ const toolResult = findRecord (
772+ userMessage . content ,
773+ ( record ) => record . type === "tool_result" && record . tool_use_id === "tool_1" ,
797774 ) ;
775+ expect ( toolResult . content ) . toEqual ( [
776+ { type : "text" , text : "(see attached image)" } ,
777+ {
778+ type : "image" ,
779+ source : {
780+ type : "base64" ,
781+ media_type : "image/png" ,
782+ data : imageData ,
783+ } ,
784+ } ,
785+ ] ) ;
786+ expect ( toolResult . is_error ) . toBe ( false ) ;
798787 } ) ;
799788
800789 it ( "cancels stalled SSE body reads when the abort signal fires mid-stream" , async ( ) => {
@@ -873,10 +862,9 @@ describe("anthropic transport stream", () => {
873862 } as AnthropicStreamOptions ,
874863 ) ;
875864
876- expect ( latestAnthropicRequest ( ) . payload ) . toMatchObject ( {
877- thinking : { type : "adaptive" } ,
878- output_config : { effort : "max" } ,
879- } ) ;
865+ const payload = latestAnthropicRequest ( ) . payload ;
866+ expect ( payload . thinking ) . toEqual ( { type : "adaptive" } ) ;
867+ expect ( payload . output_config ) . toEqual ( { effort : "max" } ) ;
880868 } ) ;
881869
882870 it ( "maps xhigh thinking effort for Claude Opus 4.7 transport runs" , async ( ) => {
@@ -897,9 +885,8 @@ describe("anthropic transport stream", () => {
897885 } as AnthropicStreamOptions ,
898886 ) ;
899887
900- expect ( latestAnthropicRequest ( ) . payload ) . toMatchObject ( {
901- thinking : { type : "adaptive" } ,
902- output_config : { effort : "xhigh" } ,
903- } ) ;
888+ const payload = latestAnthropicRequest ( ) . payload ;
889+ expect ( payload . thinking ) . toEqual ( { type : "adaptive" } ) ;
890+ expect ( payload . output_config ) . toEqual ( { effort : "xhigh" } ) ;
904891 } ) ;
905892} ) ;
0 commit comments