@@ -359,6 +359,100 @@ func TestAmpProviderModelRoutes(t *testing.T) {
359359 }
360360}
361361
362+ func TestModelsDispatchByAnthropicVersionHeader (t * testing.T ) {
363+ modelRegistry := registry .GetGlobalRegistry ()
364+ clientID := "test-anthropic-version-dispatch"
365+ modelRegistry .RegisterClient (clientID , "claude" , []* registry.ModelInfo {
366+ {
367+ ID : "claude-sonnet-4-6" ,
368+ Object : "model" ,
369+ OwnedBy : "anthropic" ,
370+ Type : "claude" ,
371+ DisplayName : "Claude 4.6 Sonnet" ,
372+ ContextLength : 200000 ,
373+ MaxCompletionTokens : 64000 ,
374+ },
375+ })
376+ t .Cleanup (func () {
377+ modelRegistry .UnregisterClient (clientID )
378+ })
379+
380+ server := newTestServer (t )
381+
382+ // Anthropic API request (Anthropic-Version header, non-claude-cli User-Agent) -> Claude format.
383+ t .Run ("anthropic version header routes to claude format" , func (t * testing.T ) {
384+ req := httptest .NewRequest (http .MethodGet , "/v1/models" , nil )
385+ req .Header .Set ("Authorization" , "Bearer test-key" )
386+ req .Header .Set ("User-Agent" , "Zed/1.0" )
387+ req .Header .Set ("Anthropic-Version" , "2023-06-01" )
388+
389+ rr := httptest .NewRecorder ()
390+ server .engine .ServeHTTP (rr , req )
391+ if rr .Code != http .StatusOK {
392+ t .Fatalf ("status = %d, want %d body=%s" , rr .Code , http .StatusOK , rr .Body .String ())
393+ }
394+
395+ var resp struct {
396+ Object string `json:"object"`
397+ HasMore * bool `json:"has_more"`
398+ Data []map [string ]any `json:"data"`
399+ }
400+ if err := json .Unmarshal (rr .Body .Bytes (), & resp ); err != nil {
401+ t .Fatalf ("failed to parse response JSON: %v; body=%s" , err , rr .Body .String ())
402+ }
403+ if resp .Object == "list" {
404+ t .Fatalf ("expected Claude format (no object=list), got OpenAI format: %s" , rr .Body .String ())
405+ }
406+ if resp .HasMore == nil {
407+ t .Fatalf ("expected Claude envelope with has_more, got %s" , rr .Body .String ())
408+ }
409+
410+ var claudeModel map [string ]any
411+ for _ , m := range resp .Data {
412+ if id , _ := m ["id" ].(string ); id == "claude-sonnet-4-6" {
413+ claudeModel = m
414+ }
415+ }
416+ if claudeModel == nil {
417+ t .Fatalf ("expected claude-sonnet-4-6 in response, got %s" , rr .Body .String ())
418+ }
419+ for _ , field := range []string {"max_input_tokens" , "max_tokens" , "display_name" } {
420+ if _ , ok := claudeModel [field ]; ! ok {
421+ t .Fatalf ("expected Claude model to include %q, got %v" , field , claudeModel )
422+ }
423+ }
424+ })
425+
426+ // Plain request (no Anthropic-Version, non-claude-cli User-Agent) -> OpenAI format, unaffected.
427+ t .Run ("plain request stays on openai format" , func (t * testing.T ) {
428+ req := httptest .NewRequest (http .MethodGet , "/v1/models" , nil )
429+ req .Header .Set ("Authorization" , "Bearer test-key" )
430+ req .Header .Set ("User-Agent" , "Mozilla/5.0" )
431+
432+ rr := httptest .NewRecorder ()
433+ server .engine .ServeHTTP (rr , req )
434+ if rr .Code != http .StatusOK {
435+ t .Fatalf ("status = %d, want %d body=%s" , rr .Code , http .StatusOK , rr .Body .String ())
436+ }
437+
438+ var resp struct {
439+ Object string `json:"object"`
440+ Data []map [string ]any `json:"data"`
441+ }
442+ if err := json .Unmarshal (rr .Body .Bytes (), & resp ); err != nil {
443+ t .Fatalf ("failed to parse response JSON: %v; body=%s" , err , rr .Body .String ())
444+ }
445+ if resp .Object != "list" {
446+ t .Fatalf ("expected OpenAI format (object=list), got %s" , rr .Body .String ())
447+ }
448+ for _ , m := range resp .Data {
449+ if _ , ok := m ["max_input_tokens" ]; ok {
450+ t .Fatalf ("did not expect max_input_tokens in OpenAI format, got %v" , m )
451+ }
452+ }
453+ })
454+ }
455+
362456func TestModelsWithClientVersionReturnsCodexCatalog (t * testing.T ) {
363457 modelRegistry := registry .GetGlobalRegistry ()
364458 clientID := "test-client-version-catalog"
0 commit comments