package gateway import ( "strings" "github.com/rose_cat707/luminary/internal/model" "github.com/rose_cat707/luminary/internal/store/cache" ) type routeTarget struct { ProviderID uint ProviderKeyID uint // 0 = auto load balance } func (s *Service) resolveRoute(ingressID uint, modelName string) *routeTarget { rules := s.cache.ListRoutingRules(ingressID) var best *model.RoutingRule for i := range rules { r := rules[i] if !r.Enabled { continue } if !matchPattern(r.ModelPattern, modelName) { continue } if best == nil || r.Priority > best.Priority { best = &r } } if best == nil { return nil } return &routeTarget{ProviderID: best.ProviderID, ProviderKeyID: best.ProviderKeyID} } func matchPattern(pattern, model string) bool { if pattern == "" || pattern == "*" { return true } if strings.HasSuffix(pattern, "*") { return strings.HasPrefix(model, strings.TrimSuffix(pattern, "*")) } return pattern == model } func (s *Service) findProvidersForModel(modelName string, allowed []string, category model.ProviderCategory, route *routeTarget) ([]model.Provider, error) { if route != nil { if p, ok := s.cache.GetProvider(route.ProviderID); ok && p.Category == category && p.Enabled { if cache.MatchesList(allowed, p.Name) || cache.MatchesList(allowed, string(p.Type)) || cache.MatchesList(allowed, "*") { return []model.Provider{p}, nil } } } var matched []model.Provider for _, p := range s.cache.ListProviders() { if p.Category != category || !model.IsCategorySupported(p.Category) || !p.Enabled { continue } if !cache.MatchesList(allowed, p.Name) && !cache.MatchesList(allowed, string(p.Type)) { continue } if s.providerSupportsModel(&p, modelName) { matched = append(matched, p) } } if len(matched) == 0 { if parts := strings.SplitN(modelName, "/", 2); len(parts) == 2 { if p, ok := s.cache.GetProviderByName(parts[0]); ok && p.Category == category && p.Enabled { if s.providerSupportsModel(&p, parts[1]) { return []model.Provider{p}, nil } } } return nil, errNoProvider(modelName) } return matched, nil } func (s *Service) providerSupportsModel(p *model.Provider, modelName string) bool { models := s.cache.GetModels(p.ID) if len(models) == 0 { for _, k := range s.cache.ListProviderKeys(p.ID) { allowed := cache.ParseJSONList(k.ModelsJSON) if cache.MatchesList(allowed, modelName) || cache.MatchesList(allowed, "*") { return true } } return false } for _, m := range models { if m.Enabled && modelEntryMatches(m, modelName) { return true } } return false } func errNoProvider(model string) error { return &gatewayError{msg: "no provider found for model " + model} } type gatewayError struct{ msg string } func (e *gatewayError) Error() string { return e.msg }