fix(backend): 修复 golangci-lint 报告的问题
- gofmt: 修复代码格式问题 - errcheck: 处理 WriteString 和 Close 返回值 - staticcheck: 错误信息改为小写开头 - staticcheck: 移除无效的 nil 检查 - staticcheck: 使用 append 替换循环 - staticcheck: 使用无条件的 TrimPrefix - ineffassign: 移除无效赋值 - unused: 移除未使用的 geminiOAuthService 字段 - 重新生成 wire_gen.go
This commit is contained in:
@@ -88,7 +88,7 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
|||||||
geminiTokenCache := repository.NewGeminiTokenCache(client)
|
geminiTokenCache := repository.NewGeminiTokenCache(client)
|
||||||
geminiTokenProvider := service.NewGeminiTokenProvider(accountRepository, geminiTokenCache, geminiOAuthService)
|
geminiTokenProvider := service.NewGeminiTokenProvider(accountRepository, geminiTokenCache, geminiOAuthService)
|
||||||
httpUpstream := repository.NewHTTPUpstream(configConfig)
|
httpUpstream := repository.NewHTTPUpstream(configConfig)
|
||||||
accountTestService := service.NewAccountTestService(accountRepository, oAuthService, openAIOAuthService, geminiOAuthService, geminiTokenProvider, httpUpstream)
|
accountTestService := service.NewAccountTestService(accountRepository, oAuthService, openAIOAuthService, geminiTokenProvider, httpUpstream)
|
||||||
concurrencyCache := repository.NewConcurrencyCache(client)
|
concurrencyCache := repository.NewConcurrencyCache(client)
|
||||||
concurrencyService := service.NewConcurrencyService(concurrencyCache)
|
concurrencyService := service.NewConcurrencyService(concurrencyCache)
|
||||||
crsSyncService := service.NewCRSSyncService(accountRepository, proxyRepository, oAuthService, openAIOAuthService, geminiOAuthService)
|
crsSyncService := service.NewCRSSyncService(accountRepository, proxyRepository, oAuthService, openAIOAuthService, geminiOAuthService)
|
||||||
|
|||||||
@@ -221,10 +221,10 @@ func setDefaults() {
|
|||||||
|
|
||||||
// TokenRefresh
|
// TokenRefresh
|
||||||
viper.SetDefault("token_refresh.enabled", true)
|
viper.SetDefault("token_refresh.enabled", true)
|
||||||
viper.SetDefault("token_refresh.check_interval_minutes", 5) // 每5分钟检查一次
|
viper.SetDefault("token_refresh.check_interval_minutes", 5) // 每5分钟检查一次
|
||||||
viper.SetDefault("token_refresh.refresh_before_expiry_hours", 0.5) // 提前30分钟刷新(适配Google 1小时token)
|
viper.SetDefault("token_refresh.refresh_before_expiry_hours", 0.5) // 提前30分钟刷新(适配Google 1小时token)
|
||||||
viper.SetDefault("token_refresh.max_retries", 3) // 最多重试3次
|
viper.SetDefault("token_refresh.max_retries", 3) // 最多重试3次
|
||||||
viper.SetDefault("token_refresh.retry_backoff_seconds", 2) // 重试退避基础2秒
|
viper.SetDefault("token_refresh.retry_backoff_seconds", 2) // 重试退避基础2秒
|
||||||
|
|
||||||
// Gemini OAuth - configure via environment variables or config file
|
// Gemini OAuth - configure via environment variables or config file
|
||||||
// GEMINI_OAUTH_CLIENT_ID and GEMINI_OAUTH_CLIENT_SECRET
|
// GEMINI_OAUTH_CLIENT_ID and GEMINI_OAUTH_CLIENT_SECRET
|
||||||
|
|||||||
@@ -19,4 +19,3 @@ var DefaultModels = []Model{
|
|||||||
|
|
||||||
// DefaultTestModel is the default model to preselect in test flows.
|
// DefaultTestModel is the default model to preselect in test flows.
|
||||||
const DefaultTestModel = "gemini-2.5-pro"
|
const DefaultTestModel = "gemini-2.5-pro"
|
||||||
|
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ func EffectiveOAuthConfig(cfg OAuthConfig, oauthType string) (OAuthConfig, error
|
|||||||
|
|
||||||
// Require OAuth credentials to be configured
|
// Require OAuth credentials to be configured
|
||||||
if effective.ClientID == "" || effective.ClientSecret == "" {
|
if effective.ClientID == "" || effective.ClientSecret == "" {
|
||||||
return OAuthConfig{}, fmt.Errorf("Gemini OAuth credentials not configured. Set GEMINI_OAUTH_CLIENT_ID and GEMINI_OAUTH_CLIENT_SECRET environment variables")
|
return OAuthConfig{}, fmt.Errorf("gemini OAuth credentials not configured, set GEMINI_OAUTH_CLIENT_ID and GEMINI_OAUTH_CLIENT_SECRET environment variables")
|
||||||
}
|
}
|
||||||
|
|
||||||
if effective.Scopes == "" {
|
if effective.Scopes == "" {
|
||||||
|
|||||||
@@ -22,4 +22,3 @@ func HTTPStatusToGoogleStatus(status int) string {
|
|||||||
return "UNKNOWN"
|
return "UNKNOWN"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ type AccountTestService struct {
|
|||||||
accountRepo AccountRepository
|
accountRepo AccountRepository
|
||||||
oauthService *OAuthService
|
oauthService *OAuthService
|
||||||
openaiOAuthService *OpenAIOAuthService
|
openaiOAuthService *OpenAIOAuthService
|
||||||
geminiOAuthService *GeminiOAuthService
|
|
||||||
geminiTokenProvider *GeminiTokenProvider
|
geminiTokenProvider *GeminiTokenProvider
|
||||||
httpUpstream HTTPUpstream
|
httpUpstream HTTPUpstream
|
||||||
}
|
}
|
||||||
@@ -53,7 +52,6 @@ func NewAccountTestService(
|
|||||||
accountRepo AccountRepository,
|
accountRepo AccountRepository,
|
||||||
oauthService *OAuthService,
|
oauthService *OAuthService,
|
||||||
openaiOAuthService *OpenAIOAuthService,
|
openaiOAuthService *OpenAIOAuthService,
|
||||||
geminiOAuthService *GeminiOAuthService,
|
|
||||||
geminiTokenProvider *GeminiTokenProvider,
|
geminiTokenProvider *GeminiTokenProvider,
|
||||||
httpUpstream HTTPUpstream,
|
httpUpstream HTTPUpstream,
|
||||||
) *AccountTestService {
|
) *AccountTestService {
|
||||||
@@ -61,7 +59,6 @@ func NewAccountTestService(
|
|||||||
accountRepo: accountRepo,
|
accountRepo: accountRepo,
|
||||||
oauthService: oauthService,
|
oauthService: oauthService,
|
||||||
openaiOAuthService: openaiOAuthService,
|
openaiOAuthService: openaiOAuthService,
|
||||||
geminiOAuthService: geminiOAuthService,
|
|
||||||
geminiTokenProvider: geminiTokenProvider,
|
geminiTokenProvider: geminiTokenProvider,
|
||||||
httpUpstream: httpUpstream,
|
httpUpstream: httpUpstream,
|
||||||
}
|
}
|
||||||
@@ -460,7 +457,7 @@ func (s *AccountTestService) testGeminiAccountConnection(c *gin.Context, account
|
|||||||
func (s *AccountTestService) buildGeminiAPIKeyRequest(ctx context.Context, account *model.Account, modelID string, payload []byte) (*http.Request, error) {
|
func (s *AccountTestService) buildGeminiAPIKeyRequest(ctx context.Context, account *model.Account, modelID string, payload []byte) (*http.Request, error) {
|
||||||
apiKey := account.GetCredential("api_key")
|
apiKey := account.GetCredential("api_key")
|
||||||
if strings.TrimSpace(apiKey) == "" {
|
if strings.TrimSpace(apiKey) == "" {
|
||||||
return nil, fmt.Errorf("No API key available")
|
return nil, fmt.Errorf("no API key available")
|
||||||
}
|
}
|
||||||
|
|
||||||
baseURL := account.GetCredential("base_url")
|
baseURL := account.GetCredential("base_url")
|
||||||
@@ -486,13 +483,13 @@ func (s *AccountTestService) buildGeminiAPIKeyRequest(ctx context.Context, accou
|
|||||||
// buildGeminiOAuthRequest builds request for Gemini OAuth accounts
|
// buildGeminiOAuthRequest builds request for Gemini OAuth accounts
|
||||||
func (s *AccountTestService) buildGeminiOAuthRequest(ctx context.Context, account *model.Account, modelID string, payload []byte) (*http.Request, error) {
|
func (s *AccountTestService) buildGeminiOAuthRequest(ctx context.Context, account *model.Account, modelID string, payload []byte) (*http.Request, error) {
|
||||||
if s.geminiTokenProvider == nil {
|
if s.geminiTokenProvider == nil {
|
||||||
return nil, fmt.Errorf("Gemini token provider not configured")
|
return nil, fmt.Errorf("gemini token provider not configured")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get access token (auto-refreshes if needed)
|
// Get access token (auto-refreshes if needed)
|
||||||
accessToken, err := s.geminiTokenProvider.GetAccessToken(ctx, account)
|
accessToken, err := s.geminiTokenProvider.GetAccessToken(ctx, account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Failed to get access token: %w", err)
|
return nil, fmt.Errorf("failed to get access token: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
projectID := strings.TrimSpace(account.GetCredential("project_id"))
|
projectID := strings.TrimSpace(account.GetCredential("project_id"))
|
||||||
|
|||||||
@@ -365,10 +365,6 @@ func (s *GeminiMessagesCompatService) Forward(ctx context.Context, c *gin.Contex
|
|||||||
return nil, fmt.Errorf("unsupported account type: %s", account.Type)
|
return nil, fmt.Errorf("unsupported account type: %s", account.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
if buildReq == nil {
|
|
||||||
return nil, s.writeClaudeError(c, http.StatusBadGateway, "upstream_error", "Gemini upstream not configured")
|
|
||||||
}
|
|
||||||
|
|
||||||
var resp *http.Response
|
var resp *http.Response
|
||||||
for attempt := 1; attempt <= geminiMaxRetries; attempt++ {
|
for attempt := 1; attempt <= geminiMaxRetries; attempt++ {
|
||||||
upstreamReq, idHeader, err := buildReq(ctx)
|
upstreamReq, idHeader, err := buildReq(ctx)
|
||||||
@@ -1128,7 +1124,6 @@ func (s *GeminiMessagesCompatService) handleStreamingResponse(c *gin.Context, re
|
|||||||
"index": openToolIndex,
|
"index": openToolIndex,
|
||||||
})
|
})
|
||||||
openToolIndex = -1
|
openToolIndex = -1
|
||||||
openToolID = ""
|
|
||||||
openToolName = ""
|
openToolName = ""
|
||||||
seenToolJSON = ""
|
seenToolJSON = ""
|
||||||
}
|
}
|
||||||
@@ -2069,7 +2064,7 @@ func extractClaudeContentText(v any) string {
|
|||||||
}
|
}
|
||||||
if pm["type"] == "text" {
|
if pm["type"] == "text" {
|
||||||
if text, ok := pm["text"].(string); ok {
|
if text, ok := pm["text"].(string); ok {
|
||||||
sb.WriteString(text)
|
_, _ = sb.WriteString(text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -436,7 +436,7 @@ func fetchProjectIDFromResourceManager(ctx context.Context, accessToken, proxyUR
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("resource manager request failed: %w", err)
|
return "", fmt.Errorf("resource manager request failed: %w", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer func() { _ = resp.Body.Close() }()
|
||||||
|
|
||||||
bodyBytes, err := io.ReadAll(resp.Body)
|
bodyBytes, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -445,13 +445,11 @@ func (s *PricingService) buildModelLookupCandidates(modelLower string) []string
|
|||||||
normalizeModelNameForPricing(modelLower),
|
normalizeModelNameForPricing(modelLower),
|
||||||
modelLower,
|
modelLower,
|
||||||
}
|
}
|
||||||
for _, cand := range []string{
|
candidates = append(candidates,
|
||||||
strings.TrimPrefix(modelLower, "models/"),
|
strings.TrimPrefix(modelLower, "models/"),
|
||||||
lastSegment(modelLower),
|
lastSegment(modelLower),
|
||||||
lastSegment(strings.TrimPrefix(modelLower, "models/")),
|
lastSegment(strings.TrimPrefix(modelLower, "models/")),
|
||||||
} {
|
)
|
||||||
candidates = append(candidates, cand)
|
|
||||||
}
|
|
||||||
|
|
||||||
seen := make(map[string]struct{}, len(candidates))
|
seen := make(map[string]struct{}, len(candidates))
|
||||||
out := make([]string, 0, len(candidates))
|
out := make([]string, 0, len(candidates))
|
||||||
@@ -479,13 +477,8 @@ func normalizeModelNameForPricing(model string) string {
|
|||||||
// - projects/.../locations/.../publishers/google/models/gemini-1.5-pro
|
// - projects/.../locations/.../publishers/google/models/gemini-1.5-pro
|
||||||
model = strings.TrimSpace(model)
|
model = strings.TrimSpace(model)
|
||||||
model = strings.TrimLeft(model, "/")
|
model = strings.TrimLeft(model, "/")
|
||||||
|
model = strings.TrimPrefix(model, "models/")
|
||||||
if strings.HasPrefix(model, "models/") {
|
model = strings.TrimPrefix(model, "publishers/google/models/")
|
||||||
model = strings.TrimPrefix(model, "models/")
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(model, "publishers/google/models/") {
|
|
||||||
model = strings.TrimPrefix(model, "publishers/google/models/")
|
|
||||||
}
|
|
||||||
|
|
||||||
if idx := strings.LastIndex(model, "/publishers/google/models/"); idx != -1 {
|
if idx := strings.LastIndex(model, "/publishers/google/models/"); idx != -1 {
|
||||||
model = model[idx+len("/publishers/google/models/"):]
|
model = model[idx+len("/publishers/google/models/"):]
|
||||||
|
|||||||
Reference in New Issue
Block a user