thread-master/apps/backend/internal/module/usage/usecase/resolver.go

95 lines
2.4 KiB
Go

package usecase
import (
"context"
"strings"
"apps/backend/internal/module/ai"
memberDomain "apps/backend/internal/module/member/domain"
"apps/backend/internal/module/usage/domain"
)
// SettingsResolver uses member settings + platform config.
type SettingsResolver struct {
Members memberDomain.Repository
PlatformAI string // legacy / xAI fallback
PlatformXAI string
PlatformOpenCode string
PlatformExa string
}
func (r *SettingsResolver) platformAIKey(provider string) string {
switch ai.NormalizeProvider(provider) {
case ai.ProviderOpenCodeGo:
if k := strings.TrimSpace(r.PlatformOpenCode); k != "" {
return k
}
default:
if k := strings.TrimSpace(r.PlatformXAI); k != "" {
return k
}
if k := strings.TrimSpace(r.PlatformAI); k != "" {
return k
}
}
return ""
}
func (r *SettingsResolver) Resolve(ctx context.Context, uid int64, meter string) (string, bool, error) {
st, err := r.Members.GetSettings(ctx, uid)
if err != nil || st == nil {
st = memberDomain.DefaultSettings(uid)
}
provider := ai.NormalizeProvider(st.Provider)
switch meter {
case domain.MeterAICopy, domain.MeterAIResearch, domain.MeterAIImage:
if st.KeyForProvider(provider) != "" {
return domain.KeyModeByok, true, nil
}
if r.platformAIKey(provider) != "" {
return domain.KeyModePlatform, true, nil
}
return "", false, nil
case domain.MeterWebSearch:
if st.ExaAPIKeyConfigured && st.ExaAPIKey != "" {
return domain.KeyModeByok, true, nil
}
if r.PlatformExa != "" {
return domain.KeyModePlatform, true, nil
}
return "", false, nil
default:
return "", false, nil
}
}
// ResolveKey returns actual key material for call (never log).
func (r *SettingsResolver) ResolveKey(ctx context.Context, uid int64, meter string) (keyMode, apiKey string, err error) {
mode, has, err := r.Resolve(ctx, uid, meter)
if err != nil {
return "", "", err
}
if !has {
return "", "", domain.ErrNoKey
}
st, _ := r.Members.GetSettings(ctx, uid)
if st == nil {
st = memberDomain.DefaultSettings(uid)
}
provider := ai.NormalizeProvider(st.Provider)
switch mode {
case domain.KeyModeByok:
if meter == domain.MeterWebSearch {
return mode, st.ExaAPIKey, nil
}
return mode, st.KeyForProvider(provider), nil
default:
if meter == domain.MeterWebSearch {
return mode, r.PlatformExa, nil
}
return mode, r.platformAIKey(provider), nil
}
}
var _ KeyResolver = (*SettingsResolver)(nil)