@@ -5654,6 +5654,155 @@ describe('AnthropicLanguageModel', () => {
56545654 expect ( result . warnings ) . toStrictEqual ( [ ] ) ;
56555655 } ) ;
56565656
5657+ it ( 'should pass cache diagnostics to request body and add beta header' , async ( ) => {
5658+ prepareJsonFixtureResponse ( 'anthropic-text' ) ;
5659+
5660+ const result = await model . doGenerate ( {
5661+ prompt : TEST_PROMPT ,
5662+ providerOptions : {
5663+ anthropic : {
5664+ cacheDiagnostics : { previousMessageId : 'msg_previous' } ,
5665+ } satisfies AnthropicLanguageModelOptions ,
5666+ } ,
5667+ } ) ;
5668+
5669+ expect ( await server . calls [ 0 ] . requestBodyJson ) . toMatchInlineSnapshot ( `
5670+ {
5671+ "diagnostics": {
5672+ "previous_message_id": "msg_previous",
5673+ },
5674+ "max_tokens": 4096,
5675+ "messages": [
5676+ {
5677+ "content": [
5678+ {
5679+ "text": "Hello",
5680+ "type": "text",
5681+ },
5682+ ],
5683+ "role": "user",
5684+ },
5685+ ],
5686+ "model": "claude-3-haiku-20240307",
5687+ }
5688+ ` ) ;
5689+
5690+ expect ( server . calls [ 0 ] . requestHeaders [ 'anthropic-beta' ] ) . toBe (
5691+ 'cache-diagnosis-2026-04-07' ,
5692+ ) ;
5693+ expect ( result . warnings ) . toStrictEqual ( [ ] ) ;
5694+ } ) ;
5695+
5696+ it ( 'should support cache diagnostics first-turn opt-in' , async ( ) => {
5697+ prepareJsonFixtureResponse ( 'anthropic-text' ) ;
5698+
5699+ const result = await model . doGenerate ( {
5700+ prompt : TEST_PROMPT ,
5701+ providerOptions : {
5702+ anthropic : {
5703+ cacheDiagnostics : { previousMessageId : null } ,
5704+ } satisfies AnthropicLanguageModelOptions ,
5705+ } ,
5706+ } ) ;
5707+
5708+ expect ( await server . calls [ 0 ] . requestBodyJson ) . toMatchInlineSnapshot ( `
5709+ {
5710+ "diagnostics": {
5711+ "previous_message_id": null,
5712+ },
5713+ "max_tokens": 4096,
5714+ "messages": [
5715+ {
5716+ "content": [
5717+ {
5718+ "text": "Hello",
5719+ "type": "text",
5720+ },
5721+ ],
5722+ "role": "user",
5723+ },
5724+ ],
5725+ "model": "claude-3-haiku-20240307",
5726+ }
5727+ ` ) ;
5728+
5729+ expect ( server . calls [ 0 ] . requestHeaders [ 'anthropic-beta' ] ) . toBe (
5730+ 'cache-diagnosis-2026-04-07' ,
5731+ ) ;
5732+ expect ( result . warnings ) . toStrictEqual ( [ ] ) ;
5733+ } ) ;
5734+
5735+ it ( 'should expose cache diagnostics response metadata' , async ( ) => {
5736+ server . urls [ 'https://api.anthropic.com/v1/messages' ] . response = {
5737+ type : 'json-value' ,
5738+ body : {
5739+ id : 'msg_017TfcQ4AgGxKyBduUpqYPZn' ,
5740+ type : 'message' ,
5741+ role : 'assistant' ,
5742+ content : [ { type : 'text' , text : 'Hello, World!' } ] ,
5743+ model : 'claude-3-haiku-20240307' ,
5744+ stop_reason : 'end_turn' ,
5745+ stop_sequence : null ,
5746+ usage : { input_tokens : 4 , output_tokens : 30 } ,
5747+ diagnostics : {
5748+ cache_miss_reason : {
5749+ type : 'tools_changed' ,
5750+ cache_missed_input_tokens : 1024 ,
5751+ } ,
5752+ } ,
5753+ } ,
5754+ } ;
5755+
5756+ const result = await model . doGenerate ( {
5757+ prompt : TEST_PROMPT ,
5758+ providerOptions : {
5759+ anthropic : {
5760+ cacheDiagnostics : { previousMessageId : 'msg_previous' } ,
5761+ } satisfies AnthropicLanguageModelOptions ,
5762+ } ,
5763+ } ) ;
5764+
5765+ expect ( result . providerMetadata ?. anthropic ?. diagnostics ) . toEqual ( {
5766+ cache_miss_reason : {
5767+ type : 'tools_changed' ,
5768+ cache_missed_input_tokens : 1024 ,
5769+ } ,
5770+ } ) ;
5771+ } ) ;
5772+
5773+ it ( 'should warn and omit cache diagnostics when unsupported' , async ( ) => {
5774+ prepareJsonFixtureResponse ( 'anthropic-text' ) ;
5775+
5776+ const { AnthropicLanguageModel } =
5777+ await import ( './anthropic-language-model' ) ;
5778+ const model = new AnthropicLanguageModel ( 'claude-3-haiku-20240307' , {
5779+ provider : 'test-provider' ,
5780+ baseURL : 'https://api.anthropic.com/v1' ,
5781+ headers : { } ,
5782+ supportsCacheDiagnostics : false ,
5783+ } ) ;
5784+
5785+ const result = await model . doGenerate ( {
5786+ prompt : TEST_PROMPT ,
5787+ providerOptions : {
5788+ anthropic : {
5789+ cacheDiagnostics : { previousMessageId : 'msg_previous' } ,
5790+ } satisfies AnthropicLanguageModelOptions ,
5791+ } ,
5792+ } ) ;
5793+
5794+ const requestBody = await server . calls [ 0 ] . requestBodyJson ;
5795+ expect ( requestBody . diagnostics ) . toBeUndefined ( ) ;
5796+ expect ( server . calls [ 0 ] . requestHeaders [ 'anthropic-beta' ] ) . toBeUndefined ( ) ;
5797+ expect ( result . warnings ) . toEqual ( [
5798+ {
5799+ type : 'unsupported' ,
5800+ feature : 'cacheDiagnostics' ,
5801+ details : 'cache diagnostics is not supported by this provider' ,
5802+ } ,
5803+ ] ) ;
5804+ } ) ;
5805+
56575806 it ( 'should pass metadata with user_id to request body' , async ( ) => {
56585807 prepareJsonFixtureResponse ( 'anthropic-text' ) ;
56595808
@@ -8167,6 +8316,43 @@ describe('AnthropicLanguageModel', () => {
81678316 ) ;
81688317 } ) ;
81698318
8319+ it ( 'should expose streaming cache diagnostics response metadata' , async ( ) => {
8320+ server . urls [ 'https://api.anthropic.com/v1/messages' ] . response = {
8321+ type : 'stream-chunks' ,
8322+ chunks : [
8323+ `data: {"type":"message_start","message":{"id":"msg_1","type":"message","role":"assistant","content":[],"model":"claude-3-haiku-20240307","stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":17,"output_tokens":1},"diagnostics":{"cache_miss_reason":{"type":"messages_changed","cache_missed_input_tokens":2048}}}}\n\n` ,
8324+ `data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}\n\n` ,
8325+ `data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Hello"}}\n\n` ,
8326+ `data: {"type":"content_block_stop","index":0}\n\n` ,
8327+ `data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"output_tokens":5}}\n\n` ,
8328+ `data: {"type":"message_stop"}\n\n` ,
8329+ ] ,
8330+ } ;
8331+
8332+ const result = await model . doStream ( {
8333+ prompt : TEST_PROMPT ,
8334+ providerOptions : {
8335+ anthropic : {
8336+ cacheDiagnostics : { previousMessageId : 'msg_previous' } ,
8337+ } satisfies AnthropicLanguageModelOptions ,
8338+ } ,
8339+ } ) ;
8340+
8341+ const chunks = await convertReadableStreamToArray ( result . stream ) ;
8342+ const finishPart = chunks . find ( part => part . type === 'finish' ) ;
8343+
8344+ expect (
8345+ finishPart ?. type === 'finish'
8346+ ? finishPart . providerMetadata ?. anthropic ?. diagnostics
8347+ : undefined ,
8348+ ) . toEqual ( {
8349+ cache_miss_reason : {
8350+ type : 'messages_changed' ,
8351+ cache_missed_input_tokens : 2048 ,
8352+ } ,
8353+ } ) ;
8354+ } ) ;
8355+
81708356 it ( 'should support cache control' , async ( ) => {
81718357 server . urls [ 'https://api.anthropic.com/v1/messages' ] . response = {
81728358 type : 'stream-chunks' ,
0 commit comments