feat: add configurable Antigravity user agent version

This commit is contained in:
shaw
2026-05-11 22:25:20 +08:00
parent 9377c96746
commit a07a0dac63
19 changed files with 341 additions and 35 deletions
+81 -7
View File
@@ -18,6 +18,7 @@ import (
"time"
"github.com/Wei-Shaw/sub2api/internal/config"
"github.com/Wei-Shaw/sub2api/internal/pkg/antigravity"
infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
"github.com/imroc/req/v3"
"golang.org/x/sync/singleflight"
@@ -98,6 +99,16 @@ const gatewayForwardingCacheTTL = 60 * time.Second
const gatewayForwardingErrorTTL = 5 * time.Second
const gatewayForwardingDBTimeout = 5 * time.Second
// cachedAntigravityUserAgentVersion 缓存 Antigravity UA 版本号(进程内缓存,60s TTL)
type cachedAntigravityUserAgentVersion struct {
version string
expiresAt int64 // unix nano
}
const antigravityUserAgentVersionCacheTTL = 60 * time.Second
const antigravityUserAgentVersionErrorTTL = 5 * time.Second
const antigravityUserAgentVersionDBTimeout = 5 * time.Second
// DefaultSubscriptionGroupReader validates group references used by default subscriptions.
type DefaultSubscriptionGroupReader interface {
GetByID(ctx context.Context, id int64) (*Group, error)
@@ -109,13 +120,15 @@ type WebSearchManagerBuilder func(cfg *WebSearchEmulationConfig, proxyURLs map[i
// SettingService 系统设置服务
type SettingService struct {
settingRepo SettingRepository
defaultSubGroupReader DefaultSubscriptionGroupReader
proxyRepo ProxyRepository // for resolving websearch provider proxy URLs
cfg *config.Config
onUpdate func() // Callback when settings are updated (for cache invalidation)
version string // Application version
webSearchManagerBuilder WebSearchManagerBuilder
settingRepo SettingRepository
defaultSubGroupReader DefaultSubscriptionGroupReader
proxyRepo ProxyRepository // for resolving websearch provider proxy URLs
cfg *config.Config
onUpdate func() // Callback when settings are updated (for cache invalidation)
version string // Application version
webSearchManagerBuilder WebSearchManagerBuilder
antigravityUAVersionCache atomic.Value // *cachedAntigravityUserAgentVersion
antigravityUAVersionSF singleflight.Group
}
type ProviderDefaultGrantSettings struct {
@@ -810,6 +823,55 @@ func (s *SettingService) GetAvailableChannelsRuntime(ctx context.Context) Availa
}
}
// GetAntigravityUserAgentVersion 返回 Antigravity 上游请求使用的版本号。
// 后台设置优先;为空、缺失或非法时回退到 ANTIGRAVITY_USER_AGENT_VERSION / 内置默认值。
func (s *SettingService) GetAntigravityUserAgentVersion(ctx context.Context) string {
fallback := antigravity.GetDefaultUserAgentVersion()
if s == nil || s.settingRepo == nil {
return fallback
}
if cached, ok := s.antigravityUAVersionCache.Load().(*cachedAntigravityUserAgentVersion); ok && cached != nil {
if time.Now().UnixNano() < cached.expiresAt {
return cached.version
}
}
result, _, _ := s.antigravityUAVersionSF.Do("antigravity_user_agent_version", func() (any, error) {
if cached, ok := s.antigravityUAVersionCache.Load().(*cachedAntigravityUserAgentVersion); ok && cached != nil {
if time.Now().UnixNano() < cached.expiresAt {
return cached.version, nil
}
}
if ctx == nil {
ctx = context.Background()
}
dbCtx, cancel := context.WithTimeout(context.WithoutCancel(ctx), antigravityUserAgentVersionDBTimeout)
defer cancel()
value, err := s.settingRepo.GetValue(dbCtx, SettingKeyAntigravityUserAgentVersion)
if err != nil && !errors.Is(err, ErrSettingNotFound) {
slog.Warn("failed to get antigravity user agent version setting", "error", err)
s.antigravityUAVersionCache.Store(&cachedAntigravityUserAgentVersion{
version: fallback,
expiresAt: time.Now().Add(antigravityUserAgentVersionErrorTTL).UnixNano(),
})
return fallback, nil
}
version := antigravity.NormalizeUserAgentVersion(value)
if version == "" {
version = fallback
}
s.antigravityUAVersionCache.Store(&cachedAntigravityUserAgentVersion{
version: version,
expiresAt: time.Now().Add(antigravityUserAgentVersionCacheTTL).UnixNano(),
})
return version, nil
})
if version, ok := result.(string); ok && version != "" {
return version
}
return fallback
}
// SetOnUpdateCallback sets a callback function to be called when settings are updated
// This is used for cache invalidation (e.g., HTML cache in frontend server)
func (s *SettingService) SetOnUpdateCallback(callback func()) {
@@ -1586,6 +1648,7 @@ func (s *SettingService) buildSystemSettingsUpdates(ctx context.Context, setting
updates[SettingKeyEnableCCHSigning] = strconv.FormatBool(settings.EnableCCHSigning)
updates[SettingKeyEnableAnthropicCacheTTL1hInjection] = strconv.FormatBool(settings.EnableAnthropicCacheTTL1hInjection)
updates[SettingKeyRewriteMessageCacheControl] = strconv.FormatBool(settings.RewriteMessageCacheControl)
updates[SettingKeyAntigravityUserAgentVersion] = antigravity.NormalizeUserAgentVersion(settings.AntigravityUserAgentVersion)
updates[SettingPaymentVisibleMethodAlipaySource] = settings.PaymentVisibleMethodAlipaySource
updates[SettingPaymentVisibleMethodWxpaySource] = settings.PaymentVisibleMethodWxpaySource
updates[SettingPaymentVisibleMethodAlipayEnabled] = strconv.FormatBool(settings.PaymentVisibleMethodAlipayEnabled)
@@ -1657,6 +1720,15 @@ func (s *SettingService) refreshCachedSettings(settings *SystemSettings) {
rewriteMessageCacheControl: settings.RewriteMessageCacheControl,
expiresAt: time.Now().Add(gatewayForwardingCacheTTL).UnixNano(),
})
s.antigravityUAVersionSF.Forget("antigravity_user_agent_version")
antigravityUserAgentVersion := antigravity.NormalizeUserAgentVersion(settings.AntigravityUserAgentVersion)
if antigravityUserAgentVersion == "" {
antigravityUserAgentVersion = antigravity.GetDefaultUserAgentVersion()
}
s.antigravityUAVersionCache.Store(&cachedAntigravityUserAgentVersion{
version: antigravityUserAgentVersion,
expiresAt: time.Now().Add(antigravityUserAgentVersionCacheTTL).UnixNano(),
})
openAIAdvancedSchedulerSettingSF.Forget(openAIAdvancedSchedulerSettingKey)
openAIAdvancedSchedulerSettingCache.Store(&cachedOpenAIAdvancedSchedulerSetting{
enabled: settings.OpenAIAdvancedSchedulerEnabled,
@@ -2386,6 +2458,7 @@ func (s *SettingService) InitializeDefaultSettings(ctx context.Context) error {
SettingKeyAllowUngroupedKeyScheduling: "false",
SettingKeyEnableAnthropicCacheTTL1hInjection: "false",
SettingKeyRewriteMessageCacheControl: strconv.FormatBool(s.defaultRewriteMessageCacheControl()),
SettingKeyAntigravityUserAgentVersion: "",
SettingPaymentVisibleMethodAlipaySource: "",
SettingPaymentVisibleMethodWxpaySource: "",
SettingPaymentVisibleMethodAlipayEnabled: "false",
@@ -2767,6 +2840,7 @@ func (s *SettingService) parseSettings(settings map[string]string) *SystemSettin
} else {
result.RewriteMessageCacheControl = s.defaultRewriteMessageCacheControl()
}
result.AntigravityUserAgentVersion = antigravity.NormalizeUserAgentVersion(settings[SettingKeyAntigravityUserAgentVersion])
// Web search emulation: quick enabled check from the JSON config
if raw := settings[SettingKeyWebSearchEmulationConfig]; raw != "" {