@@ -264,5 +264,138 @@ describe("AnthropicHandler", () => {
264264 expect ( result . reasoningBudget ) . toBeUndefined ( )
265265 expect ( result . temperature ) . toBe ( 0 )
266266 } )
267+
268+ it ( "should enable 1M context window when anthropicBeta1MContext is true for Claude Sonnet 4" , ( ) => {
269+ const handler = new AnthropicHandler ( {
270+ apiKey : "test-api-key" ,
271+ apiModelId : "claude-sonnet-4-20250514" ,
272+ anthropicBeta1MContext : true ,
273+ } )
274+
275+ const model = handler . getModel ( )
276+
277+ // Should have 1M context window when enabled
278+ expect ( model . info . contextWindow ) . toBe ( 1_000_000 )
279+ // Should use tier pricing for >200K context
280+ expect ( model . info . inputPrice ) . toBe ( 6.0 )
281+ expect ( model . info . outputPrice ) . toBe ( 22.5 )
282+ expect ( model . info . cacheWritesPrice ) . toBe ( 7.5 )
283+ expect ( model . info . cacheReadsPrice ) . toBe ( 0.6 )
284+ } )
285+
286+ it ( "should use default context window when anthropicBeta1MContext is false for Claude Sonnet 4" , ( ) => {
287+ const handler = new AnthropicHandler ( {
288+ apiKey : "test-api-key" ,
289+ apiModelId : "claude-sonnet-4-20250514" ,
290+ anthropicBeta1MContext : false ,
291+ } )
292+
293+ const model = handler . getModel ( )
294+
295+ // Should use default context window (200k)
296+ expect ( model . info . contextWindow ) . toBe ( 200_000 )
297+ // Should use default pricing for ≤200K context
298+ expect ( model . info . inputPrice ) . toBe ( 3.0 )
299+ expect ( model . info . outputPrice ) . toBe ( 15.0 )
300+ expect ( model . info . cacheWritesPrice ) . toBe ( 3.75 )
301+ expect ( model . info . cacheReadsPrice ) . toBe ( 0.3 )
302+ } )
303+
304+ it ( "should not affect context window for non-Claude Sonnet 4 models" , ( ) => {
305+ const handler = new AnthropicHandler ( {
306+ apiKey : "test-api-key" ,
307+ apiModelId : "claude-3-5-sonnet-20241022" ,
308+ anthropicBeta1MContext : true ,
309+ } )
310+
311+ const model = handler . getModel ( )
312+
313+ // Should use default context window for non-Sonnet 4 models
314+ expect ( model . info . contextWindow ) . toBe ( 200_000 )
315+ } )
316+ } )
317+
318+ describe ( "createMessage with 1M context beta" , ( ) => {
319+ it ( "should include context-1m-2025-08-07 beta header when enabled for Claude Sonnet 4" , async ( ) => {
320+ const handler = new AnthropicHandler ( {
321+ apiKey : "test-api-key" ,
322+ apiModelId : "claude-sonnet-4-20250514" ,
323+ anthropicBeta1MContext : true ,
324+ } )
325+
326+ const systemPrompt = "You are a helpful assistant."
327+ const messages : Anthropic . Messages . MessageParam [ ] = [ { role : "user" , content : "Hello" } ]
328+
329+ const stream = handler . createMessage ( systemPrompt , messages )
330+ const chunks : any [ ] = [ ]
331+ for await ( const chunk of stream ) {
332+ chunks . push ( chunk )
333+ }
334+
335+ // Verify that the create method was called with the correct beta headers
336+ expect ( mockCreate ) . toHaveBeenCalledWith (
337+ expect . objectContaining ( {
338+ model : "claude-sonnet-4-20250514" ,
339+ } ) ,
340+ expect . objectContaining ( {
341+ headers : expect . objectContaining ( {
342+ "anthropic-beta" : expect . stringContaining ( "context-1m-2025-08-07" ) ,
343+ } ) ,
344+ } ) ,
345+ )
346+
347+ // Verify that both betas are included
348+ const callArgs = mockCreate . mock . calls [ 0 ]
349+ const headers = callArgs [ 1 ] ?. headers
350+ expect ( headers ?. [ "anthropic-beta" ] ) . toContain ( "prompt-caching-2024-07-31" )
351+ expect ( headers ?. [ "anthropic-beta" ] ) . toContain ( "context-1m-2025-08-07" )
352+ } )
353+
354+ it ( "should not include context-1m beta header when disabled for Claude Sonnet 4" , async ( ) => {
355+ const handler = new AnthropicHandler ( {
356+ apiKey : "test-api-key" ,
357+ apiModelId : "claude-sonnet-4-20250514" ,
358+ anthropicBeta1MContext : false ,
359+ } )
360+
361+ const systemPrompt = "You are a helpful assistant."
362+ const messages : Anthropic . Messages . MessageParam [ ] = [ { role : "user" , content : "Hello" } ]
363+
364+ const stream = handler . createMessage ( systemPrompt , messages )
365+ const chunks : any [ ] = [ ]
366+ for await ( const chunk of stream ) {
367+ chunks . push ( chunk )
368+ }
369+
370+ // Verify that the create method was called without the 1M context beta
371+ const callArgs = mockCreate . mock . calls [ 0 ]
372+ const headers = callArgs [ 1 ] ?. headers
373+ expect ( headers ?. [ "anthropic-beta" ] ) . toContain ( "prompt-caching-2024-07-31" )
374+ expect ( headers ?. [ "anthropic-beta" ] ) . not . toContain ( "context-1m-2025-08-07" )
375+ } )
376+
377+ it ( "should handle thinking models with 1M context beta correctly" , async ( ) => {
378+ const handler = new AnthropicHandler ( {
379+ apiKey : "test-api-key" ,
380+ apiModelId : "claude-3-7-sonnet-20250219:thinking" ,
381+ anthropicBeta1MContext : true , // This shouldn't affect non-Sonnet 4 models
382+ } )
383+
384+ const systemPrompt = "You are a helpful assistant."
385+ const messages : Anthropic . Messages . MessageParam [ ] = [ { role : "user" , content : "Hello" } ]
386+
387+ const stream = handler . createMessage ( systemPrompt , messages )
388+ const chunks : any [ ] = [ ]
389+ for await ( const chunk of stream ) {
390+ chunks . push ( chunk )
391+ }
392+
393+ // Verify that the 1M context beta is NOT included for non-Sonnet 4 models
394+ const callArgs = mockCreate . mock . calls [ 0 ]
395+ const headers = callArgs [ 1 ] ?. headers
396+ expect ( headers ?. [ "anthropic-beta" ] ) . toContain ( "output-128k-2025-02-19" )
397+ expect ( headers ?. [ "anthropic-beta" ] ) . toContain ( "prompt-caching-2024-07-31" )
398+ expect ( headers ?. [ "anthropic-beta" ] ) . not . toContain ( "context-1m-2025-08-07" )
399+ } )
267400 } )
268401} )
0 commit comments