@@ -332,6 +332,166 @@ func TestHomeEnabledHidesManagementEndpointsAndControlPanel(t *testing.T) {
332332 })
333333}
334334
335+ func TestAmpProviderModelRoutes (t * testing.T ) {
336+ testCases := []struct {
337+ name string
338+ path string
339+ wantStatus int
340+ wantContains string
341+ }{
342+ {
343+ name : "openai root models" ,
344+ path : "/api/provider/openai/models" ,
345+ wantStatus : http .StatusOK ,
346+ wantContains : `"object":"list"` ,
347+ },
348+ {
349+ name : "groq root models" ,
350+ path : "/api/provider/groq/models" ,
351+ wantStatus : http .StatusOK ,
352+ wantContains : `"object":"list"` ,
353+ },
354+ {
355+ name : "openai models" ,
356+ path : "/api/provider/openai/v1/models" ,
357+ wantStatus : http .StatusOK ,
358+ wantContains : `"object":"list"` ,
359+ },
360+ {
361+ name : "anthropic models" ,
362+ path : "/api/provider/anthropic/v1/models" ,
363+ wantStatus : http .StatusOK ,
364+ wantContains : `"data"` ,
365+ },
366+ {
367+ name : "google models v1" ,
368+ path : "/api/provider/google/v1/models" ,
369+ wantStatus : http .StatusOK ,
370+ wantContains : `"models"` ,
371+ },
372+ {
373+ name : "google models v1beta" ,
374+ path : "/api/provider/google/v1beta/models" ,
375+ wantStatus : http .StatusOK ,
376+ wantContains : `"models"` ,
377+ },
378+ }
379+
380+ for _ , tc := range testCases {
381+ tc := tc
382+ t .Run (tc .name , func (t * testing.T ) {
383+ server := newTestServer (t )
384+
385+ req := httptest .NewRequest (http .MethodGet , tc .path , nil )
386+ req .Header .Set ("Authorization" , "Bearer test-key" )
387+
388+ rr := httptest .NewRecorder ()
389+ server .engine .ServeHTTP (rr , req )
390+
391+ if rr .Code != tc .wantStatus {
392+ t .Fatalf ("unexpected status code for %s: got %d want %d; body=%s" , tc .path , rr .Code , tc .wantStatus , rr .Body .String ())
393+ }
394+ if body := rr .Body .String (); ! strings .Contains (body , tc .wantContains ) {
395+ t .Fatalf ("response body for %s missing %q: %s" , tc .path , tc .wantContains , body )
396+ }
397+ })
398+ }
399+ }
400+
401+ func TestModelsDispatchByAnthropicVersionHeader (t * testing.T ) {
402+ modelRegistry := registry .GetGlobalRegistry ()
403+ clientID := "test-anthropic-version-dispatch"
404+ modelRegistry .RegisterClient (clientID , "claude" , []* registry.ModelInfo {
405+ {
406+ ID : "claude-sonnet-4-6" ,
407+ Object : "model" ,
408+ OwnedBy : "anthropic" ,
409+ Type : "claude" ,
410+ DisplayName : "Claude 4.6 Sonnet" ,
411+ ContextLength : 200000 ,
412+ MaxCompletionTokens : 64000 ,
413+ },
414+ })
415+ t .Cleanup (func () {
416+ modelRegistry .UnregisterClient (clientID )
417+ })
418+
419+ server := newTestServer (t )
420+
421+ // Anthropic API request (Anthropic-Version header, non-claude-cli User-Agent) -> Claude format.
422+ t .Run ("anthropic version header routes to claude format" , func (t * testing.T ) {
423+ req := httptest .NewRequest (http .MethodGet , "/v1/models" , nil )
424+ req .Header .Set ("Authorization" , "Bearer test-key" )
425+ req .Header .Set ("User-Agent" , "Zed/1.0" )
426+ req .Header .Set ("Anthropic-Version" , "2023-06-01" )
427+
428+ rr := httptest .NewRecorder ()
429+ server .engine .ServeHTTP (rr , req )
430+ if rr .Code != http .StatusOK {
431+ t .Fatalf ("status = %d, want %d body=%s" , rr .Code , http .StatusOK , rr .Body .String ())
432+ }
433+
434+ var resp struct {
435+ Object string `json:"object"`
436+ HasMore * bool `json:"has_more"`
437+ Data []map [string ]any `json:"data"`
438+ }
439+ if err := json .Unmarshal (rr .Body .Bytes (), & resp ); err != nil {
440+ t .Fatalf ("failed to parse response JSON: %v; body=%s" , err , rr .Body .String ())
441+ }
442+ if resp .Object == "list" {
443+ t .Fatalf ("expected Claude format (no object=list), got OpenAI format: %s" , rr .Body .String ())
444+ }
445+ if resp .HasMore == nil {
446+ t .Fatalf ("expected Claude envelope with has_more, got %s" , rr .Body .String ())
447+ }
448+
449+ var claudeModel map [string ]any
450+ for _ , m := range resp .Data {
451+ if id , _ := m ["id" ].(string ); id == "claude-sonnet-4-6" {
452+ claudeModel = m
453+ }
454+ }
455+ if claudeModel == nil {
456+ t .Fatalf ("expected claude-sonnet-4-6 in response, got %s" , rr .Body .String ())
457+ }
458+ for _ , field := range []string {"max_input_tokens" , "max_tokens" , "display_name" } {
459+ if _ , ok := claudeModel [field ]; ! ok {
460+ t .Fatalf ("expected Claude model to include %q, got %v" , field , claudeModel )
461+ }
462+ }
463+ })
464+
465+ // Plain request (no Anthropic-Version, non-claude-cli User-Agent) -> OpenAI format, unaffected.
466+ t .Run ("plain request stays on openai format" , func (t * testing.T ) {
467+ req := httptest .NewRequest (http .MethodGet , "/v1/models" , nil )
468+ req .Header .Set ("Authorization" , "Bearer test-key" )
469+ req .Header .Set ("User-Agent" , "Mozilla/5.0" )
470+
471+ rr := httptest .NewRecorder ()
472+ server .engine .ServeHTTP (rr , req )
473+ if rr .Code != http .StatusOK {
474+ t .Fatalf ("status = %d, want %d body=%s" , rr .Code , http .StatusOK , rr .Body .String ())
475+ }
476+
477+ var resp struct {
478+ Object string `json:"object"`
479+ Data []map [string ]any `json:"data"`
480+ }
481+ if err := json .Unmarshal (rr .Body .Bytes (), & resp ); err != nil {
482+ t .Fatalf ("failed to parse response JSON: %v; body=%s" , err , rr .Body .String ())
483+ }
484+ if resp .Object != "list" {
485+ t .Fatalf ("expected OpenAI format (object=list), got %s" , rr .Body .String ())
486+ }
487+ for _ , m := range resp .Data {
488+ if _ , ok := m ["max_input_tokens" ]; ok {
489+ t .Fatalf ("did not expect max_input_tokens in OpenAI format, got %v" , m )
490+ }
491+ }
492+ })
493+ }
494+
335495func TestModelsWithClientVersionReturnsCodexCatalog (t * testing.T ) {
336496 modelRegistry := registry .GetGlobalRegistry ()
337497 clientID := "test-client-version-catalog"
0 commit comments