mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-19 16:17:56 +00:00
Merge pull request #7526 from HuntercodeT/fix/passthrough-model-discovery-merge
fix(gateway): let OpenAI passthrough accounts supplement model discovery instead of hiding mapped models
This commit is contained in:
@@ -287,6 +287,18 @@ func TestGatewayModels_UnmappedOpenAIAccountsSupplementMappedModels(t *testing.T
|
||||
accounts: accounts[1:],
|
||||
want: []string{sparkModel, alias},
|
||||
},
|
||||
{
|
||||
// A passthrough account with a stale mapping behaves like an unmapped
|
||||
// one: it adds the defaults but never its own mapping keys, and it no
|
||||
// longer hides the aliases declared on ordinary accounts.
|
||||
name: "passthrough account contributes defaults without hiding mapped aliases",
|
||||
accounts: append([]service.Account{{
|
||||
ID: 5, Platform: service.PlatformOpenAI, Type: service.AccountTypeOAuth,
|
||||
Credentials: map[string]any{"model_mapping": map[string]any{"stale-model": "stale-model"}},
|
||||
Extra: map[string]any{"openai_passthrough": true},
|
||||
}}, accounts[1:]...),
|
||||
want: append(openai.DefaultModelIDs(), alias),
|
||||
},
|
||||
{
|
||||
name: "unmapped accounts from another platform do not add defaults",
|
||||
accounts: append([]service.Account{{ID: 4, Platform: service.PlatformAnthropic}}, accounts[1:]...),
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/config"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/ctxkey"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/openai"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/usagestats"
|
||||
gocache "github.com/patrickmn/go-cache"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -670,7 +671,9 @@ func TestGetAvailableModels_OpenAIPassthroughUsesDefaultFallback(t *testing.T) {
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "passthrough wins over ordinary account mapping",
|
||||
// The passthrough account serves the default set (its stale mapping is
|
||||
// ignored), while the ordinary account's mapping still reaches the list.
|
||||
name: "passthrough contributes defaults alongside ordinary account mapping",
|
||||
accounts: []Account{
|
||||
{
|
||||
ID: 2,
|
||||
@@ -684,7 +687,7 @@ func TestGetAvailableModels_OpenAIPassthroughUsesDefaultFallback(t *testing.T) {
|
||||
Extra: map[string]any{"openai_passthrough": true},
|
||||
},
|
||||
},
|
||||
want: nil,
|
||||
want: dedupeAndSortModelIDs(append([]string{"configured-model"}, openai.DefaultModelIDs()...)),
|
||||
},
|
||||
{
|
||||
name: "ordinary accounts preserve mapped whitelist",
|
||||
@@ -708,7 +711,9 @@ func TestGetAvailableModels_OpenAIPassthroughUsesDefaultFallback(t *testing.T) {
|
||||
modelsListCacheTTL: time.Minute,
|
||||
}
|
||||
|
||||
require.Equal(t, tt.want, svc.GetAvailableModels(context.Background(), &groupID, PlatformOpenAI))
|
||||
got := svc.GetAvailableModels(context.Background(), &groupID, PlatformOpenAI)
|
||||
require.Equal(t, tt.want, got)
|
||||
require.NotContains(t, got, "stale-model", "passthrough mapping must never reach the public list")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1433,15 +1433,13 @@ func (s *GatewayService) GetAvailableModels(ctx context.Context, groupID *int64,
|
||||
hasAnyMapping := false
|
||||
|
||||
for _, acc := range accounts {
|
||||
// Passthrough routing accepts models independently of model_mapping. A stale
|
||||
// mapping on any eligible passthrough account therefore cannot define the
|
||||
// public whitelist; return nil so the handler uses its default model set.
|
||||
// Passthrough routing accepts models independently of model_mapping, so a
|
||||
// stale mapping on a passthrough account must not narrow the public list.
|
||||
// Treat it like an unmapped account: skip its mapping here and let
|
||||
// supplementUnmappedOpenAIModels contribute the default set. Mappings on
|
||||
// the ordinary accounts in the same group still count.
|
||||
if platform == PlatformOpenAI && acc.IsOpenAIPassthroughEnabled() {
|
||||
if s.modelsListCache != nil {
|
||||
s.modelsListCache.Set(cacheKey, []string(nil), s.modelsListCacheTTL)
|
||||
modelsListCacheStoreTotal.Add(1)
|
||||
}
|
||||
return nil
|
||||
continue
|
||||
}
|
||||
|
||||
mapping := acc.GetModelMapping()
|
||||
|
||||
@@ -29,15 +29,17 @@ func GroupModelAllowlistFromDomain(cfg domain.GroupModelAllowlist) GroupModelAll
|
||||
}
|
||||
|
||||
// supplementUnmappedOpenAIModels ensures a partial mapping catalog does not
|
||||
// hide models from unmapped OpenAI accounts. An empty catalog is left unchanged
|
||||
// so callers retain their existing discovery fallback.
|
||||
// hide models from unmapped or passthrough OpenAI accounts (passthrough routing
|
||||
// ignores model_mapping, so it serves the same default set as an unmapped
|
||||
// account). An empty catalog is left unchanged so callers retain their existing
|
||||
// discovery fallback.
|
||||
func supplementUnmappedOpenAIModels(accounts []Account, models []string) []string {
|
||||
if len(models) == 0 {
|
||||
return models
|
||||
}
|
||||
for i := range accounts {
|
||||
account := &accounts[i]
|
||||
if account.Platform == PlatformOpenAI && len(account.GetModelMapping()) == 0 {
|
||||
if account.Platform == PlatformOpenAI && (account.IsOpenAIPassthroughEnabled() || len(account.GetModelMapping()) == 0) {
|
||||
return dedupeAndSortModelIDs(slices.Concat(models, openai.DefaultModelIDs()))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user