Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
62e80c60
Commit
62e80c60
authored
Apr 05, 2026
by
erio
Browse files
revert: completely remove all Sora functionality
parent
dbb248df
Changes
136
Hide whitespace changes
Inline
Side-by-side
backend/cmd/server/wire_gen.go
View file @
62e80c60
...
@@ -102,12 +102,11 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
...
@@ -102,12 +102,11 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
dashboardHandler
:=
admin
.
NewDashboardHandler
(
dashboardService
,
dashboardAggregationService
)
dashboardHandler
:=
admin
.
NewDashboardHandler
(
dashboardService
,
dashboardAggregationService
)
schedulerCache
:=
repository
.
NewSchedulerCache
(
redisClient
)
schedulerCache
:=
repository
.
NewSchedulerCache
(
redisClient
)
accountRepository
:=
repository
.
NewAccountRepository
(
client
,
db
,
schedulerCache
)
accountRepository
:=
repository
.
NewAccountRepository
(
client
,
db
,
schedulerCache
)
soraAccountRepository
:=
repository
.
NewSoraAccountRepository
(
db
)
proxyRepository
:=
repository
.
NewProxyRepository
(
client
,
db
)
proxyRepository
:=
repository
.
NewProxyRepository
(
client
,
db
)
proxyExitInfoProber
:=
repository
.
NewProxyExitInfoProber
(
configConfig
)
proxyExitInfoProber
:=
repository
.
NewProxyExitInfoProber
(
configConfig
)
proxyLatencyCache
:=
repository
.
NewProxyLatencyCache
(
redisClient
)
proxyLatencyCache
:=
repository
.
NewProxyLatencyCache
(
redisClient
)
privacyClientFactory
:=
providePrivacyClientFactory
()
privacyClientFactory
:=
providePrivacyClientFactory
()
adminService
:=
service
.
NewAdminService
(
userRepository
,
groupRepository
,
accountRepository
,
soraAccountRepository
,
proxyRepository
,
apiKeyRepository
,
redeemCodeRepository
,
userGroupRateRepository
,
billingCacheService
,
proxyExitInfoProber
,
proxyLatencyCache
,
apiKeyAuthCacheInvalidator
,
client
,
settingService
,
subscriptionService
,
userSubscriptionRepository
,
privacyClientFactory
)
adminService
:=
service
.
NewAdminService
(
userRepository
,
groupRepository
,
accountRepository
,
proxyRepository
,
apiKeyRepository
,
redeemCodeRepository
,
userGroupRateRepository
,
billingCacheService
,
proxyExitInfoProber
,
proxyLatencyCache
,
apiKeyAuthCacheInvalidator
,
client
,
settingService
,
subscriptionService
,
userSubscriptionRepository
,
privacyClientFactory
)
concurrencyCache
:=
repository
.
ProvideConcurrencyCache
(
redisClient
,
configConfig
)
concurrencyCache
:=
repository
.
ProvideConcurrencyCache
(
redisClient
,
configConfig
)
concurrencyService
:=
service
.
ProvideConcurrencyService
(
concurrencyCache
,
accountRepository
,
configConfig
)
concurrencyService
:=
service
.
ProvideConcurrencyService
(
concurrencyCache
,
accountRepository
,
configConfig
)
adminUserHandler
:=
admin
.
NewUserHandler
(
adminService
,
concurrencyService
)
adminUserHandler
:=
admin
.
NewUserHandler
(
adminService
,
concurrencyService
)
...
@@ -143,7 +142,7 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
...
@@ -143,7 +142,7 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
tlsFingerprintProfileCache
:=
repository
.
NewTLSFingerprintProfileCache
(
redisClient
)
tlsFingerprintProfileCache
:=
repository
.
NewTLSFingerprintProfileCache
(
redisClient
)
tlsFingerprintProfileService
:=
service
.
NewTLSFingerprintProfileService
(
tlsFingerprintProfileRepository
,
tlsFingerprintProfileCache
)
tlsFingerprintProfileService
:=
service
.
NewTLSFingerprintProfileService
(
tlsFingerprintProfileRepository
,
tlsFingerprintProfileCache
)
accountUsageService
:=
service
.
NewAccountUsageService
(
accountRepository
,
usageLogRepository
,
claudeUsageFetcher
,
geminiQuotaService
,
antigravityQuotaFetcher
,
usageCache
,
identityCache
,
tlsFingerprintProfileService
)
accountUsageService
:=
service
.
NewAccountUsageService
(
accountRepository
,
usageLogRepository
,
claudeUsageFetcher
,
geminiQuotaService
,
antigravityQuotaFetcher
,
usageCache
,
identityCache
,
tlsFingerprintProfileService
)
antigravityGatewayService
:=
service
.
NewAntigravityGatewayService
(
accountRepository
,
gatewayCache
,
schedulerSnapshotService
,
antigravityTokenProvider
,
rateLimitService
,
httpUpstream
,
settingService
,
internal500CounterCache
)
antigravityGatewayService
:=
service
.
NewAntigravityGatewayService
(
accountRepository
,
gatewayCache
,
schedulerSnapshotService
,
antigravityTokenProvider
,
rateLimitService
,
httpUpstream
,
settingService
,
internal500CounterCache
,
accountUsageService
)
accountTestService
:=
service
.
NewAccountTestService
(
accountRepository
,
geminiTokenProvider
,
antigravityGatewayService
,
httpUpstream
,
configConfig
,
tlsFingerprintProfileService
)
accountTestService
:=
service
.
NewAccountTestService
(
accountRepository
,
geminiTokenProvider
,
antigravityGatewayService
,
httpUpstream
,
configConfig
,
tlsFingerprintProfileService
)
crsSyncService
:=
service
.
NewCRSSyncService
(
accountRepository
,
proxyRepository
,
oAuthService
,
openAIOAuthService
,
geminiOAuthService
,
configConfig
)
crsSyncService
:=
service
.
NewCRSSyncService
(
accountRepository
,
proxyRepository
,
oAuthService
,
openAIOAuthService
,
geminiOAuthService
,
configConfig
)
sessionLimitCache
:=
repository
.
ProvideSessionLimitCache
(
redisClient
,
configConfig
)
sessionLimitCache
:=
repository
.
ProvideSessionLimitCache
(
redisClient
,
configConfig
)
...
@@ -184,12 +183,7 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
...
@@ -184,12 +183,7 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
geminiMessagesCompatService
:=
service
.
NewGeminiMessagesCompatService
(
accountRepository
,
groupRepository
,
gatewayCache
,
schedulerSnapshotService
,
geminiTokenProvider
,
rateLimitService
,
httpUpstream
,
antigravityGatewayService
,
configConfig
)
geminiMessagesCompatService
:=
service
.
NewGeminiMessagesCompatService
(
accountRepository
,
groupRepository
,
gatewayCache
,
schedulerSnapshotService
,
geminiTokenProvider
,
rateLimitService
,
httpUpstream
,
antigravityGatewayService
,
configConfig
)
opsSystemLogSink
:=
service
.
ProvideOpsSystemLogSink
(
opsRepository
)
opsSystemLogSink
:=
service
.
ProvideOpsSystemLogSink
(
opsRepository
)
opsService
:=
service
.
NewOpsService
(
opsRepository
,
settingRepository
,
configConfig
,
accountRepository
,
userRepository
,
concurrencyService
,
gatewayService
,
openAIGatewayService
,
geminiMessagesCompatService
,
antigravityGatewayService
,
opsSystemLogSink
)
opsService
:=
service
.
NewOpsService
(
opsRepository
,
settingRepository
,
configConfig
,
accountRepository
,
userRepository
,
concurrencyService
,
gatewayService
,
openAIGatewayService
,
geminiMessagesCompatService
,
antigravityGatewayService
,
opsSystemLogSink
)
soraS3Storage
:=
service
.
NewSoraS3Storage
(
settingService
)
settingHandler
:=
admin
.
NewSettingHandler
(
settingService
,
emailService
,
turnstileService
,
opsService
)
settingService
.
SetOnS3UpdateCallback
(
soraS3Storage
.
RefreshClient
)
soraGenerationRepository
:=
repository
.
NewSoraGenerationRepository
(
db
)
soraQuotaService
:=
service
.
NewSoraQuotaService
(
userRepository
,
groupRepository
,
settingService
)
soraGenerationService
:=
service
.
NewSoraGenerationService
(
soraGenerationRepository
,
soraS3Storage
,
soraQuotaService
)
settingHandler
:=
admin
.
NewSettingHandler
(
settingService
,
emailService
,
turnstileService
,
opsService
,
soraS3Storage
)
opsHandler
:=
admin
.
NewOpsHandler
(
opsService
)
opsHandler
:=
admin
.
NewOpsHandler
(
opsService
)
updateCache
:=
repository
.
NewUpdateCache
(
redisClient
)
updateCache
:=
repository
.
NewUpdateCache
(
redisClient
)
gitHubReleaseClient
:=
repository
.
ProvideGitHubReleaseClient
(
configConfig
)
gitHubReleaseClient
:=
repository
.
ProvideGitHubReleaseClient
(
configConfig
)
...
@@ -223,16 +217,11 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
...
@@ -223,16 +217,11 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
userMessageQueueService
:=
service
.
ProvideUserMessageQueueService
(
userMsgQueueCache
,
rpmCache
,
configConfig
)
userMessageQueueService
:=
service
.
ProvideUserMessageQueueService
(
userMsgQueueCache
,
rpmCache
,
configConfig
)
gatewayHandler
:=
handler
.
NewGatewayHandler
(
gatewayService
,
geminiMessagesCompatService
,
antigravityGatewayService
,
userService
,
concurrencyService
,
billingCacheService
,
usageService
,
apiKeyService
,
usageRecordWorkerPool
,
errorPassthroughService
,
userMessageQueueService
,
configConfig
,
settingService
)
gatewayHandler
:=
handler
.
NewGatewayHandler
(
gatewayService
,
geminiMessagesCompatService
,
antigravityGatewayService
,
userService
,
concurrencyService
,
billingCacheService
,
usageService
,
apiKeyService
,
usageRecordWorkerPool
,
errorPassthroughService
,
userMessageQueueService
,
configConfig
,
settingService
)
openAIGatewayHandler
:=
handler
.
NewOpenAIGatewayHandler
(
openAIGatewayService
,
concurrencyService
,
billingCacheService
,
apiKeyService
,
usageRecordWorkerPool
,
errorPassthroughService
,
configConfig
)
openAIGatewayHandler
:=
handler
.
NewOpenAIGatewayHandler
(
openAIGatewayService
,
concurrencyService
,
billingCacheService
,
apiKeyService
,
usageRecordWorkerPool
,
errorPassthroughService
,
configConfig
)
soraSDKClient
:=
service
.
ProvideSoraSDKClient
(
configConfig
,
httpUpstream
,
openAITokenProvider
,
accountRepository
,
soraAccountRepository
)
soraMediaStorage
:=
service
.
ProvideSoraMediaStorage
(
configConfig
)
soraGatewayService
:=
service
.
NewSoraGatewayService
(
soraSDKClient
,
rateLimitService
,
httpUpstream
,
configConfig
)
soraClientHandler
:=
handler
.
NewSoraClientHandler
(
soraGenerationService
,
soraQuotaService
,
soraS3Storage
,
soraGatewayService
,
gatewayService
,
soraMediaStorage
,
apiKeyService
)
soraGatewayHandler
:=
handler
.
NewSoraGatewayHandler
(
gatewayService
,
soraGatewayService
,
concurrencyService
,
billingCacheService
,
usageRecordWorkerPool
,
configConfig
)
handlerSettingHandler
:=
handler
.
ProvideSettingHandler
(
settingService
,
buildInfo
)
handlerSettingHandler
:=
handler
.
ProvideSettingHandler
(
settingService
,
buildInfo
)
totpHandler
:=
handler
.
NewTotpHandler
(
totpService
)
totpHandler
:=
handler
.
NewTotpHandler
(
totpService
)
idempotencyCoordinator
:=
service
.
ProvideIdempotencyCoordinator
(
idempotencyRepository
,
configConfig
)
idempotencyCoordinator
:=
service
.
ProvideIdempotencyCoordinator
(
idempotencyRepository
,
configConfig
)
idempotencyCleanupService
:=
service
.
ProvideIdempotencyCleanupService
(
idempotencyRepository
,
configConfig
)
idempotencyCleanupService
:=
service
.
ProvideIdempotencyCleanupService
(
idempotencyRepository
,
configConfig
)
handlers
:=
handler
.
ProvideHandlers
(
authHandler
,
userHandler
,
apiKeyHandler
,
usageHandler
,
redeemHandler
,
subscriptionHandler
,
announcementHandler
,
adminHandlers
,
gatewayHandler
,
openAIGatewayHandler
,
soraGatewayHandler
,
soraClientHandler
,
handlerSettingHandler
,
totpHandler
,
idempotencyCoordinator
,
idempotencyCleanupService
)
handlers
:=
handler
.
ProvideHandlers
(
authHandler
,
userHandler
,
apiKeyHandler
,
usageHandler
,
redeemHandler
,
subscriptionHandler
,
announcementHandler
,
adminHandlers
,
gatewayHandler
,
openAIGatewayHandler
,
handlerSettingHandler
,
totpHandler
,
idempotencyCoordinator
,
idempotencyCleanupService
)
jwtAuthMiddleware
:=
middleware
.
NewJWTAuthMiddleware
(
authService
,
userService
)
jwtAuthMiddleware
:=
middleware
.
NewJWTAuthMiddleware
(
authService
,
userService
)
adminAuthMiddleware
:=
middleware
.
NewAdminAuthMiddleware
(
authService
,
userService
,
settingService
)
adminAuthMiddleware
:=
middleware
.
NewAdminAuthMiddleware
(
authService
,
userService
,
settingService
)
apiKeyAuthMiddleware
:=
middleware
.
NewAPIKeyAuthMiddleware
(
apiKeyService
,
subscriptionService
,
configConfig
)
apiKeyAuthMiddleware
:=
middleware
.
NewAPIKeyAuthMiddleware
(
apiKeyService
,
subscriptionService
,
configConfig
)
...
@@ -243,12 +232,11 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
...
@@ -243,12 +232,11 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
opsAlertEvaluatorService
:=
service
.
ProvideOpsAlertEvaluatorService
(
opsService
,
opsRepository
,
emailService
,
redisClient
,
configConfig
)
opsAlertEvaluatorService
:=
service
.
ProvideOpsAlertEvaluatorService
(
opsService
,
opsRepository
,
emailService
,
redisClient
,
configConfig
)
opsCleanupService
:=
service
.
ProvideOpsCleanupService
(
opsRepository
,
db
,
redisClient
,
configConfig
)
opsCleanupService
:=
service
.
ProvideOpsCleanupService
(
opsRepository
,
db
,
redisClient
,
configConfig
)
opsScheduledReportService
:=
service
.
ProvideOpsScheduledReportService
(
opsService
,
userService
,
emailService
,
redisClient
,
configConfig
)
opsScheduledReportService
:=
service
.
ProvideOpsScheduledReportService
(
opsService
,
userService
,
emailService
,
redisClient
,
configConfig
)
soraMediaCleanupService
:=
service
.
ProvideSoraMediaCleanupService
(
soraMediaStorage
,
configConfig
)
tokenRefreshService
:=
service
.
ProvideTokenRefreshService
(
accountRepository
,
oAuthService
,
openAIOAuthService
,
geminiOAuthService
,
antigravityOAuthService
,
compositeTokenCacheInvalidator
,
schedulerCache
,
configConfig
,
tempUnschedCache
,
privacyClientFactory
,
proxyRepository
,
oauthRefreshAPI
)
tokenRefreshService
:=
service
.
ProvideTokenRefreshService
(
accountRepository
,
soraAccountRepository
,
oAuthService
,
openAIOAuthService
,
geminiOAuthService
,
antigravityOAuthService
,
compositeTokenCacheInvalidator
,
schedulerCache
,
configConfig
,
tempUnschedCache
,
privacyClientFactory
,
proxyRepository
,
oauthRefreshAPI
)
accountExpiryService
:=
service
.
ProvideAccountExpiryService
(
accountRepository
)
accountExpiryService
:=
service
.
ProvideAccountExpiryService
(
accountRepository
)
subscriptionExpiryService
:=
service
.
ProvideSubscriptionExpiryService
(
userSubscriptionRepository
)
subscriptionExpiryService
:=
service
.
ProvideSubscriptionExpiryService
(
userSubscriptionRepository
)
scheduledTestRunnerService
:=
service
.
ProvideScheduledTestRunnerService
(
scheduledTestPlanRepository
,
scheduledTestService
,
accountTestService
,
rateLimitService
,
configConfig
)
scheduledTestRunnerService
:=
service
.
ProvideScheduledTestRunnerService
(
scheduledTestPlanRepository
,
scheduledTestService
,
accountTestService
,
rateLimitService
,
configConfig
)
v
:=
provideCleanup
(
client
,
redisClient
,
opsMetricsCollector
,
opsAggregationService
,
opsAlertEvaluatorService
,
opsCleanupService
,
opsScheduledReportService
,
opsSystemLogSink
,
soraMediaCleanupService
,
schedulerSnapshotService
,
tokenRefreshService
,
accountExpiryService
,
subscriptionExpiryService
,
usageCleanupService
,
idempotencyCleanupService
,
pricingService
,
emailQueueService
,
billingCacheService
,
usageRecordWorkerPool
,
subscriptionService
,
oAuthService
,
openAIOAuthService
,
geminiOAuthService
,
antigravityOAuthService
,
openAIGatewayService
,
scheduledTestRunnerService
,
backupService
)
v
:=
provideCleanup
(
client
,
redisClient
,
opsMetricsCollector
,
opsAggregationService
,
opsAlertEvaluatorService
,
opsCleanupService
,
opsScheduledReportService
,
opsSystemLogSink
,
schedulerSnapshotService
,
tokenRefreshService
,
accountExpiryService
,
subscriptionExpiryService
,
usageCleanupService
,
idempotencyCleanupService
,
pricingService
,
emailQueueService
,
billingCacheService
,
usageRecordWorkerPool
,
subscriptionService
,
oAuthService
,
openAIOAuthService
,
geminiOAuthService
,
antigravityOAuthService
,
openAIGatewayService
,
scheduledTestRunnerService
,
backupService
)
application
:=
&
Application
{
application
:=
&
Application
{
Server
:
httpServer
,
Server
:
httpServer
,
Cleanup
:
v
,
Cleanup
:
v
,
...
@@ -283,7 +271,6 @@ func provideCleanup(
...
@@ -283,7 +271,6 @@ func provideCleanup(
opsCleanup
*
service
.
OpsCleanupService
,
opsCleanup
*
service
.
OpsCleanupService
,
opsScheduledReport
*
service
.
OpsScheduledReportService
,
opsScheduledReport
*
service
.
OpsScheduledReportService
,
opsSystemLogSink
*
service
.
OpsSystemLogSink
,
opsSystemLogSink
*
service
.
OpsSystemLogSink
,
soraMediaCleanup
*
service
.
SoraMediaCleanupService
,
schedulerSnapshot
*
service
.
SchedulerSnapshotService
,
schedulerSnapshot
*
service
.
SchedulerSnapshotService
,
tokenRefresh
*
service
.
TokenRefreshService
,
tokenRefresh
*
service
.
TokenRefreshService
,
accountExpiry
*
service
.
AccountExpiryService
,
accountExpiry
*
service
.
AccountExpiryService
,
...
@@ -331,12 +318,6 @@ func provideCleanup(
...
@@ -331,12 +318,6 @@ func provideCleanup(
}
}
return
nil
return
nil
}},
}},
{
"SoraMediaCleanupService"
,
func
()
error
{
if
soraMediaCleanup
!=
nil
{
soraMediaCleanup
.
Stop
()
}
return
nil
}},
{
"OpsAlertEvaluatorService"
,
func
()
error
{
{
"OpsAlertEvaluatorService"
,
func
()
error
{
if
opsAlertEvaluator
!=
nil
{
if
opsAlertEvaluator
!=
nil
{
opsAlertEvaluator
.
Stop
()
opsAlertEvaluator
.
Stop
()
...
...
backend/cmd/server/wire_gen_test.go
View file @
62e80c60
...
@@ -57,7 +57,6 @@ func TestProvideCleanup_WithMinimalDependencies_NoPanic(t *testing.T) {
...
@@ -57,7 +57,6 @@ func TestProvideCleanup_WithMinimalDependencies_NoPanic(t *testing.T) {
&
service
.
OpsCleanupService
{},
&
service
.
OpsCleanupService
{},
&
service
.
OpsScheduledReportService
{},
&
service
.
OpsScheduledReportService
{},
opsSystemLogSinkSvc
,
opsSystemLogSinkSvc
,
&
service
.
SoraMediaCleanupService
{},
schedulerSnapshotSvc
,
schedulerSnapshotSvc
,
tokenRefreshSvc
,
tokenRefreshSvc
,
accountExpirySvc
,
accountExpirySvc
,
...
...
backend/internal/config/config.go
View file @
62e80c60
...
@@ -77,7 +77,6 @@ type Config struct {
...
@@ -77,7 +77,6 @@ type Config struct {
UsageCleanup
UsageCleanupConfig
`mapstructure:"usage_cleanup"`
UsageCleanup
UsageCleanupConfig
`mapstructure:"usage_cleanup"`
Concurrency
ConcurrencyConfig
`mapstructure:"concurrency"`
Concurrency
ConcurrencyConfig
`mapstructure:"concurrency"`
TokenRefresh
TokenRefreshConfig
`mapstructure:"token_refresh"`
TokenRefresh
TokenRefreshConfig
`mapstructure:"token_refresh"`
Sora
SoraConfig
`mapstructure:"sora"`
RunMode
string
`mapstructure:"run_mode" yaml:"run_mode"`
RunMode
string
`mapstructure:"run_mode" yaml:"run_mode"`
Timezone
string
`mapstructure:"timezone"`
// e.g. "Asia/Shanghai", "UTC"
Timezone
string
`mapstructure:"timezone"`
// e.g. "Asia/Shanghai", "UTC"
Gemini
GeminiConfig
`mapstructure:"gemini"`
Gemini
GeminiConfig
`mapstructure:"gemini"`
...
@@ -197,8 +196,6 @@ type TokenRefreshConfig struct {
...
@@ -197,8 +196,6 @@ type TokenRefreshConfig struct {
MaxRetries
int
`mapstructure:"max_retries"`
MaxRetries
int
`mapstructure:"max_retries"`
// 重试退避基础时间(秒)
// 重试退避基础时间(秒)
RetryBackoffSeconds
int
`mapstructure:"retry_backoff_seconds"`
RetryBackoffSeconds
int
`mapstructure:"retry_backoff_seconds"`
// 是否允许 OpenAI 刷新器同步覆盖关联的 Sora 账号 token(默认关闭)
SyncLinkedSoraAccounts
bool
`mapstructure:"sync_linked_sora_accounts"`
}
}
type
PricingConfig
struct
{
type
PricingConfig
struct
{
...
@@ -303,59 +300,6 @@ type ConcurrencyConfig struct {
...
@@ -303,59 +300,6 @@ type ConcurrencyConfig struct {
PingInterval
int
`mapstructure:"ping_interval"`
PingInterval
int
`mapstructure:"ping_interval"`
}
}
// SoraConfig 直连 Sora 配置
type
SoraConfig
struct
{
Client
SoraClientConfig
`mapstructure:"client"`
Storage
SoraStorageConfig
`mapstructure:"storage"`
}
// SoraClientConfig 直连 Sora 客户端配置
type
SoraClientConfig
struct
{
BaseURL
string
`mapstructure:"base_url"`
TimeoutSeconds
int
`mapstructure:"timeout_seconds"`
MaxRetries
int
`mapstructure:"max_retries"`
CloudflareChallengeCooldownSeconds
int
`mapstructure:"cloudflare_challenge_cooldown_seconds"`
PollIntervalSeconds
int
`mapstructure:"poll_interval_seconds"`
MaxPollAttempts
int
`mapstructure:"max_poll_attempts"`
RecentTaskLimit
int
`mapstructure:"recent_task_limit"`
RecentTaskLimitMax
int
`mapstructure:"recent_task_limit_max"`
Debug
bool
`mapstructure:"debug"`
UseOpenAITokenProvider
bool
`mapstructure:"use_openai_token_provider"`
Headers
map
[
string
]
string
`mapstructure:"headers"`
UserAgent
string
`mapstructure:"user_agent"`
DisableTLSFingerprint
bool
`mapstructure:"disable_tls_fingerprint"`
CurlCFFISidecar
SoraCurlCFFISidecarConfig
`mapstructure:"curl_cffi_sidecar"`
}
// SoraCurlCFFISidecarConfig Sora 专用 curl_cffi sidecar 配置
type
SoraCurlCFFISidecarConfig
struct
{
Enabled
bool
`mapstructure:"enabled"`
BaseURL
string
`mapstructure:"base_url"`
Impersonate
string
`mapstructure:"impersonate"`
TimeoutSeconds
int
`mapstructure:"timeout_seconds"`
SessionReuseEnabled
bool
`mapstructure:"session_reuse_enabled"`
SessionTTLSeconds
int
`mapstructure:"session_ttl_seconds"`
}
// SoraStorageConfig 媒体存储配置
type
SoraStorageConfig
struct
{
Type
string
`mapstructure:"type"`
LocalPath
string
`mapstructure:"local_path"`
FallbackToUpstream
bool
`mapstructure:"fallback_to_upstream"`
MaxConcurrentDownloads
int
`mapstructure:"max_concurrent_downloads"`
DownloadTimeoutSeconds
int
`mapstructure:"download_timeout_seconds"`
MaxDownloadBytes
int64
`mapstructure:"max_download_bytes"`
Debug
bool
`mapstructure:"debug"`
Cleanup
SoraStorageCleanupConfig
`mapstructure:"cleanup"`
}
// SoraStorageCleanupConfig 媒体清理配置
type
SoraStorageCleanupConfig
struct
{
Enabled
bool
`mapstructure:"enabled"`
Schedule
string
`mapstructure:"schedule"`
RetentionDays
int
`mapstructure:"retention_days"`
}
// GatewayConfig API网关相关配置
// GatewayConfig API网关相关配置
type
GatewayConfig
struct
{
type
GatewayConfig
struct
{
// 等待上游响应头的超时时间(秒),0表示无超时
// 等待上游响应头的超时时间(秒),0表示无超时
...
@@ -424,24 +368,6 @@ type GatewayConfig struct {
...
@@ -424,24 +368,6 @@ type GatewayConfig struct {
// 是否允许对部分 400 错误触发 failover(默认关闭以避免改变语义)
// 是否允许对部分 400 错误触发 failover(默认关闭以避免改变语义)
FailoverOn400
bool
`mapstructure:"failover_on_400"`
FailoverOn400
bool
`mapstructure:"failover_on_400"`
// Sora 专用配置
// SoraMaxBodySize: Sora 请求体最大字节数(0 表示使用 gateway.max_body_size)
SoraMaxBodySize
int64
`mapstructure:"sora_max_body_size"`
// SoraStreamTimeoutSeconds: Sora 流式请求总超时(秒,0 表示不限制)
SoraStreamTimeoutSeconds
int
`mapstructure:"sora_stream_timeout_seconds"`
// SoraRequestTimeoutSeconds: Sora 非流式请求超时(秒,0 表示不限制)
SoraRequestTimeoutSeconds
int
`mapstructure:"sora_request_timeout_seconds"`
// SoraStreamMode: stream 强制策略(force/error)
SoraStreamMode
string
`mapstructure:"sora_stream_mode"`
// SoraModelFilters: 模型列表过滤配置
SoraModelFilters
SoraModelFiltersConfig
`mapstructure:"sora_model_filters"`
// SoraMediaRequireAPIKey: 是否要求访问 /sora/media 携带 API Key
SoraMediaRequireAPIKey
bool
`mapstructure:"sora_media_require_api_key"`
// SoraMediaSigningKey: /sora/media 临时签名密钥(空表示禁用签名)
SoraMediaSigningKey
string
`mapstructure:"sora_media_signing_key"`
// SoraMediaSignedURLTTLSeconds: 临时签名 URL 有效期(秒,<=0 表示禁用)
SoraMediaSignedURLTTLSeconds
int
`mapstructure:"sora_media_signed_url_ttl_seconds"`
// 账户切换最大次数(遇到上游错误时切换到其他账户的次数上限)
// 账户切换最大次数(遇到上游错误时切换到其他账户的次数上限)
MaxAccountSwitches
int
`mapstructure:"max_account_switches"`
MaxAccountSwitches
int
`mapstructure:"max_account_switches"`
// Gemini 账户切换最大次数(Gemini 平台单独配置,因 API 限制更严格)
// Gemini 账户切换最大次数(Gemini 平台单独配置,因 API 限制更严格)
...
@@ -639,12 +565,6 @@ type GatewayUsageRecordConfig struct {
...
@@ -639,12 +565,6 @@ type GatewayUsageRecordConfig struct {
AutoScaleCooldownSeconds
int
`mapstructure:"auto_scale_cooldown_seconds"`
AutoScaleCooldownSeconds
int
`mapstructure:"auto_scale_cooldown_seconds"`
}
}
// SoraModelFiltersConfig Sora 模型过滤配置
type
SoraModelFiltersConfig
struct
{
// HidePromptEnhance 是否隐藏 prompt-enhance 模型
HidePromptEnhance
bool
`mapstructure:"hide_prompt_enhance"`
}
// TLSFingerprintConfig TLS指纹伪装配置
// TLSFingerprintConfig TLS指纹伪装配置
// 用于模拟 Claude CLI (Node.js) 的 TLS 握手特征,避免被识别为非官方客户端
// 用于模拟 Claude CLI (Node.js) 的 TLS 握手特征,避免被识别为非官方客户端
type
TLSFingerprintConfig
struct
{
type
TLSFingerprintConfig
struct
{
...
@@ -1402,13 +1322,6 @@ func setDefaults() {
...
@@ -1402,13 +1322,6 @@ func setDefaults() {
viper
.
SetDefault
(
"gateway.upstream_response_read_max_bytes"
,
int64
(
8
*
1024
*
1024
))
viper
.
SetDefault
(
"gateway.upstream_response_read_max_bytes"
,
int64
(
8
*
1024
*
1024
))
viper
.
SetDefault
(
"gateway.proxy_probe_response_read_max_bytes"
,
int64
(
1024
*
1024
))
viper
.
SetDefault
(
"gateway.proxy_probe_response_read_max_bytes"
,
int64
(
1024
*
1024
))
viper
.
SetDefault
(
"gateway.gemini_debug_response_headers"
,
false
)
viper
.
SetDefault
(
"gateway.gemini_debug_response_headers"
,
false
)
viper
.
SetDefault
(
"gateway.sora_max_body_size"
,
int64
(
256
*
1024
*
1024
))
viper
.
SetDefault
(
"gateway.sora_stream_timeout_seconds"
,
900
)
viper
.
SetDefault
(
"gateway.sora_request_timeout_seconds"
,
180
)
viper
.
SetDefault
(
"gateway.sora_stream_mode"
,
"force"
)
viper
.
SetDefault
(
"gateway.sora_model_filters.hide_prompt_enhance"
,
true
)
viper
.
SetDefault
(
"gateway.sora_media_require_api_key"
,
true
)
viper
.
SetDefault
(
"gateway.sora_media_signed_url_ttl_seconds"
,
900
)
viper
.
SetDefault
(
"gateway.connection_pool_isolation"
,
ConnectionPoolIsolationAccountProxy
)
viper
.
SetDefault
(
"gateway.connection_pool_isolation"
,
ConnectionPoolIsolationAccountProxy
)
// HTTP 上游连接池配置(针对 5000+ 并发用户优化)
// HTTP 上游连接池配置(针对 5000+ 并发用户优化)
viper
.
SetDefault
(
"gateway.max_idle_conns"
,
2560
)
// 最大空闲连接总数(高并发场景可调大)
viper
.
SetDefault
(
"gateway.max_idle_conns"
,
2560
)
// 最大空闲连接总数(高并发场景可调大)
...
@@ -1465,45 +1378,12 @@ func setDefaults() {
...
@@ -1465,45 +1378,12 @@ func setDefaults() {
viper
.
SetDefault
(
"gateway.tls_fingerprint.enabled"
,
true
)
viper
.
SetDefault
(
"gateway.tls_fingerprint.enabled"
,
true
)
viper
.
SetDefault
(
"concurrency.ping_interval"
,
10
)
viper
.
SetDefault
(
"concurrency.ping_interval"
,
10
)
// Sora 直连配置
viper
.
SetDefault
(
"sora.client.base_url"
,
"https://sora.chatgpt.com/backend"
)
viper
.
SetDefault
(
"sora.client.timeout_seconds"
,
120
)
viper
.
SetDefault
(
"sora.client.max_retries"
,
3
)
viper
.
SetDefault
(
"sora.client.cloudflare_challenge_cooldown_seconds"
,
900
)
viper
.
SetDefault
(
"sora.client.poll_interval_seconds"
,
2
)
viper
.
SetDefault
(
"sora.client.max_poll_attempts"
,
600
)
viper
.
SetDefault
(
"sora.client.recent_task_limit"
,
50
)
viper
.
SetDefault
(
"sora.client.recent_task_limit_max"
,
200
)
viper
.
SetDefault
(
"sora.client.debug"
,
false
)
viper
.
SetDefault
(
"sora.client.use_openai_token_provider"
,
false
)
viper
.
SetDefault
(
"sora.client.headers"
,
map
[
string
]
string
{})
viper
.
SetDefault
(
"sora.client.user_agent"
,
"Sora/1.2026.007 (Android 15; 24122RKC7C; build 2600700)"
)
viper
.
SetDefault
(
"sora.client.disable_tls_fingerprint"
,
false
)
viper
.
SetDefault
(
"sora.client.curl_cffi_sidecar.enabled"
,
true
)
viper
.
SetDefault
(
"sora.client.curl_cffi_sidecar.base_url"
,
"http://sora-curl-cffi-sidecar:8080"
)
viper
.
SetDefault
(
"sora.client.curl_cffi_sidecar.impersonate"
,
"chrome131"
)
viper
.
SetDefault
(
"sora.client.curl_cffi_sidecar.timeout_seconds"
,
60
)
viper
.
SetDefault
(
"sora.client.curl_cffi_sidecar.session_reuse_enabled"
,
true
)
viper
.
SetDefault
(
"sora.client.curl_cffi_sidecar.session_ttl_seconds"
,
3600
)
viper
.
SetDefault
(
"sora.storage.type"
,
"local"
)
viper
.
SetDefault
(
"sora.storage.local_path"
,
""
)
viper
.
SetDefault
(
"sora.storage.fallback_to_upstream"
,
true
)
viper
.
SetDefault
(
"sora.storage.max_concurrent_downloads"
,
4
)
viper
.
SetDefault
(
"sora.storage.download_timeout_seconds"
,
120
)
viper
.
SetDefault
(
"sora.storage.max_download_bytes"
,
int64
(
200
<<
20
))
viper
.
SetDefault
(
"sora.storage.debug"
,
false
)
viper
.
SetDefault
(
"sora.storage.cleanup.enabled"
,
true
)
viper
.
SetDefault
(
"sora.storage.cleanup.retention_days"
,
7
)
viper
.
SetDefault
(
"sora.storage.cleanup.schedule"
,
"0 3 * * *"
)
// 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秒
viper
.
SetDefault
(
"token_refresh.sync_linked_sora_accounts"
,
false
)
// 默认不跨平台覆盖 Sora token
// 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
...
@@ -1879,86 +1759,6 @@ func (c *Config) Validate() error {
...
@@ -1879,86 +1759,6 @@ func (c *Config) Validate() error {
if
c
.
Gateway
.
ProxyProbeResponseReadMaxBytes
<=
0
{
if
c
.
Gateway
.
ProxyProbeResponseReadMaxBytes
<=
0
{
return
fmt
.
Errorf
(
"gateway.proxy_probe_response_read_max_bytes must be positive"
)
return
fmt
.
Errorf
(
"gateway.proxy_probe_response_read_max_bytes must be positive"
)
}
}
if
c
.
Gateway
.
SoraMaxBodySize
<
0
{
return
fmt
.
Errorf
(
"gateway.sora_max_body_size must be non-negative"
)
}
if
c
.
Gateway
.
SoraStreamTimeoutSeconds
<
0
{
return
fmt
.
Errorf
(
"gateway.sora_stream_timeout_seconds must be non-negative"
)
}
if
c
.
Gateway
.
SoraRequestTimeoutSeconds
<
0
{
return
fmt
.
Errorf
(
"gateway.sora_request_timeout_seconds must be non-negative"
)
}
if
c
.
Gateway
.
SoraMediaSignedURLTTLSeconds
<
0
{
return
fmt
.
Errorf
(
"gateway.sora_media_signed_url_ttl_seconds must be non-negative"
)
}
if
mode
:=
strings
.
TrimSpace
(
strings
.
ToLower
(
c
.
Gateway
.
SoraStreamMode
));
mode
!=
""
{
switch
mode
{
case
"force"
,
"error"
:
default
:
return
fmt
.
Errorf
(
"gateway.sora_stream_mode must be one of: force/error"
)
}
}
if
c
.
Sora
.
Client
.
TimeoutSeconds
<
0
{
return
fmt
.
Errorf
(
"sora.client.timeout_seconds must be non-negative"
)
}
if
c
.
Sora
.
Client
.
MaxRetries
<
0
{
return
fmt
.
Errorf
(
"sora.client.max_retries must be non-negative"
)
}
if
c
.
Sora
.
Client
.
CloudflareChallengeCooldownSeconds
<
0
{
return
fmt
.
Errorf
(
"sora.client.cloudflare_challenge_cooldown_seconds must be non-negative"
)
}
if
c
.
Sora
.
Client
.
PollIntervalSeconds
<
0
{
return
fmt
.
Errorf
(
"sora.client.poll_interval_seconds must be non-negative"
)
}
if
c
.
Sora
.
Client
.
MaxPollAttempts
<
0
{
return
fmt
.
Errorf
(
"sora.client.max_poll_attempts must be non-negative"
)
}
if
c
.
Sora
.
Client
.
RecentTaskLimit
<
0
{
return
fmt
.
Errorf
(
"sora.client.recent_task_limit must be non-negative"
)
}
if
c
.
Sora
.
Client
.
RecentTaskLimitMax
<
0
{
return
fmt
.
Errorf
(
"sora.client.recent_task_limit_max must be non-negative"
)
}
if
c
.
Sora
.
Client
.
RecentTaskLimitMax
>
0
&&
c
.
Sora
.
Client
.
RecentTaskLimit
>
0
&&
c
.
Sora
.
Client
.
RecentTaskLimitMax
<
c
.
Sora
.
Client
.
RecentTaskLimit
{
c
.
Sora
.
Client
.
RecentTaskLimitMax
=
c
.
Sora
.
Client
.
RecentTaskLimit
}
if
c
.
Sora
.
Client
.
CurlCFFISidecar
.
TimeoutSeconds
<
0
{
return
fmt
.
Errorf
(
"sora.client.curl_cffi_sidecar.timeout_seconds must be non-negative"
)
}
if
c
.
Sora
.
Client
.
CurlCFFISidecar
.
SessionTTLSeconds
<
0
{
return
fmt
.
Errorf
(
"sora.client.curl_cffi_sidecar.session_ttl_seconds must be non-negative"
)
}
if
!
c
.
Sora
.
Client
.
CurlCFFISidecar
.
Enabled
{
return
fmt
.
Errorf
(
"sora.client.curl_cffi_sidecar.enabled must be true"
)
}
if
strings
.
TrimSpace
(
c
.
Sora
.
Client
.
CurlCFFISidecar
.
BaseURL
)
==
""
{
return
fmt
.
Errorf
(
"sora.client.curl_cffi_sidecar.base_url is required"
)
}
if
c
.
Sora
.
Storage
.
MaxConcurrentDownloads
<
0
{
return
fmt
.
Errorf
(
"sora.storage.max_concurrent_downloads must be non-negative"
)
}
if
c
.
Sora
.
Storage
.
DownloadTimeoutSeconds
<
0
{
return
fmt
.
Errorf
(
"sora.storage.download_timeout_seconds must be non-negative"
)
}
if
c
.
Sora
.
Storage
.
MaxDownloadBytes
<
0
{
return
fmt
.
Errorf
(
"sora.storage.max_download_bytes must be non-negative"
)
}
if
c
.
Sora
.
Storage
.
Cleanup
.
Enabled
{
if
c
.
Sora
.
Storage
.
Cleanup
.
RetentionDays
<=
0
{
return
fmt
.
Errorf
(
"sora.storage.cleanup.retention_days must be positive"
)
}
if
strings
.
TrimSpace
(
c
.
Sora
.
Storage
.
Cleanup
.
Schedule
)
==
""
{
return
fmt
.
Errorf
(
"sora.storage.cleanup.schedule is required when cleanup is enabled"
)
}
}
else
{
if
c
.
Sora
.
Storage
.
Cleanup
.
RetentionDays
<
0
{
return
fmt
.
Errorf
(
"sora.storage.cleanup.retention_days must be non-negative"
)
}
}
if
storageType
:=
strings
.
TrimSpace
(
strings
.
ToLower
(
c
.
Sora
.
Storage
.
Type
));
storageType
!=
""
&&
storageType
!=
"local"
{
return
fmt
.
Errorf
(
"sora.storage.type must be 'local'"
)
}
if
strings
.
TrimSpace
(
c
.
Gateway
.
ConnectionPoolIsolation
)
!=
""
{
if
strings
.
TrimSpace
(
c
.
Gateway
.
ConnectionPoolIsolation
)
!=
""
{
switch
c
.
Gateway
.
ConnectionPoolIsolation
{
switch
c
.
Gateway
.
ConnectionPoolIsolation
{
case
ConnectionPoolIsolationProxy
,
ConnectionPoolIsolationAccount
,
ConnectionPoolIsolationAccountProxy
:
case
ConnectionPoolIsolationProxy
,
ConnectionPoolIsolationAccount
,
ConnectionPoolIsolationAccountProxy
:
...
...
backend/internal/config/config_test.go
View file @
62e80c60
...
@@ -1554,93 +1554,6 @@ func TestValidateConfig_LogRequiredAndRotationBounds(t *testing.T) {
...
@@ -1554,93 +1554,6 @@ func TestValidateConfig_LogRequiredAndRotationBounds(t *testing.T) {
}
}
}
}
func
TestSoraCurlCFFISidecarDefaults
(
t
*
testing
.
T
)
{
resetViperWithJWTSecret
(
t
)
cfg
,
err
:=
Load
()
if
err
!=
nil
{
t
.
Fatalf
(
"Load() error: %v"
,
err
)
}
if
!
cfg
.
Sora
.
Client
.
CurlCFFISidecar
.
Enabled
{
t
.
Fatalf
(
"Sora curl_cffi sidecar should be enabled by default"
)
}
if
cfg
.
Sora
.
Client
.
CloudflareChallengeCooldownSeconds
<=
0
{
t
.
Fatalf
(
"Sora cloudflare challenge cooldown should be positive by default"
)
}
if
cfg
.
Sora
.
Client
.
CurlCFFISidecar
.
BaseURL
==
""
{
t
.
Fatalf
(
"Sora curl_cffi sidecar base_url should not be empty by default"
)
}
if
cfg
.
Sora
.
Client
.
CurlCFFISidecar
.
Impersonate
==
""
{
t
.
Fatalf
(
"Sora curl_cffi sidecar impersonate should not be empty by default"
)
}
if
!
cfg
.
Sora
.
Client
.
CurlCFFISidecar
.
SessionReuseEnabled
{
t
.
Fatalf
(
"Sora curl_cffi sidecar session reuse should be enabled by default"
)
}
if
cfg
.
Sora
.
Client
.
CurlCFFISidecar
.
SessionTTLSeconds
<=
0
{
t
.
Fatalf
(
"Sora curl_cffi sidecar session ttl should be positive by default"
)
}
}
func
TestValidateSoraCurlCFFISidecarRequired
(
t
*
testing
.
T
)
{
resetViperWithJWTSecret
(
t
)
cfg
,
err
:=
Load
()
if
err
!=
nil
{
t
.
Fatalf
(
"Load() error: %v"
,
err
)
}
cfg
.
Sora
.
Client
.
CurlCFFISidecar
.
Enabled
=
false
err
=
cfg
.
Validate
()
if
err
==
nil
||
!
strings
.
Contains
(
err
.
Error
(),
"sora.client.curl_cffi_sidecar.enabled must be true"
)
{
t
.
Fatalf
(
"Validate() error = %v, want sidecar enabled error"
,
err
)
}
}
func
TestValidateSoraCurlCFFISidecarBaseURLRequired
(
t
*
testing
.
T
)
{
resetViperWithJWTSecret
(
t
)
cfg
,
err
:=
Load
()
if
err
!=
nil
{
t
.
Fatalf
(
"Load() error: %v"
,
err
)
}
cfg
.
Sora
.
Client
.
CurlCFFISidecar
.
BaseURL
=
" "
err
=
cfg
.
Validate
()
if
err
==
nil
||
!
strings
.
Contains
(
err
.
Error
(),
"sora.client.curl_cffi_sidecar.base_url is required"
)
{
t
.
Fatalf
(
"Validate() error = %v, want sidecar base_url required error"
,
err
)
}
}
func
TestValidateSoraCurlCFFISidecarSessionTTLNonNegative
(
t
*
testing
.
T
)
{
resetViperWithJWTSecret
(
t
)
cfg
,
err
:=
Load
()
if
err
!=
nil
{
t
.
Fatalf
(
"Load() error: %v"
,
err
)
}
cfg
.
Sora
.
Client
.
CurlCFFISidecar
.
SessionTTLSeconds
=
-
1
err
=
cfg
.
Validate
()
if
err
==
nil
||
!
strings
.
Contains
(
err
.
Error
(),
"sora.client.curl_cffi_sidecar.session_ttl_seconds must be non-negative"
)
{
t
.
Fatalf
(
"Validate() error = %v, want sidecar session ttl error"
,
err
)
}
}
func
TestValidateSoraCloudflareChallengeCooldownNonNegative
(
t
*
testing
.
T
)
{
resetViperWithJWTSecret
(
t
)
cfg
,
err
:=
Load
()
if
err
!=
nil
{
t
.
Fatalf
(
"Load() error: %v"
,
err
)
}
cfg
.
Sora
.
Client
.
CloudflareChallengeCooldownSeconds
=
-
1
err
=
cfg
.
Validate
()
if
err
==
nil
||
!
strings
.
Contains
(
err
.
Error
(),
"sora.client.cloudflare_challenge_cooldown_seconds must be non-negative"
)
{
t
.
Fatalf
(
"Validate() error = %v, want cloudflare cooldown error"
,
err
)
}
}
func
TestLoad_DefaultGatewayUsageRecordConfig
(
t
*
testing
.
T
)
{
func
TestLoad_DefaultGatewayUsageRecordConfig
(
t
*
testing
.
T
)
{
resetViperWithJWTSecret
(
t
)
resetViperWithJWTSecret
(
t
)
...
...
backend/internal/domain/constants.go
View file @
62e80c60
...
@@ -22,7 +22,6 @@ const (
...
@@ -22,7 +22,6 @@ const (
PlatformOpenAI
=
"openai"
PlatformOpenAI
=
"openai"
PlatformGemini
=
"gemini"
PlatformGemini
=
"gemini"
PlatformAntigravity
=
"antigravity"
PlatformAntigravity
=
"antigravity"
PlatformSora
=
"sora"
)
)
// Account type constants
// Account type constants
...
...
backend/internal/handler/admin/account_data.go
View file @
62e80c60
...
@@ -567,15 +567,15 @@ func defaultProxyName(name string) string {
...
@@ -567,15 +567,15 @@ func defaultProxyName(name string) string {
// enrichCredentialsFromIDToken performs best-effort extraction of user info fields
// enrichCredentialsFromIDToken performs best-effort extraction of user info fields
// (email, plan_type, chatgpt_account_id, etc.) from id_token in credentials.
// (email, plan_type, chatgpt_account_id, etc.) from id_token in credentials.
// Only applies to OpenAI
/Sora
OAuth accounts. Skips expired token errors silently.
// Only applies to OpenAI OAuth accounts. Skips expired token errors silently.
// Existing credential values are never overwritten — only missing fields are filled.
// Existing credential values are never overwritten — only missing fields are filled.
func
enrichCredentialsFromIDToken
(
item
*
DataAccount
)
{
func
enrichCredentialsFromIDToken
(
item
*
DataAccount
)
{
if
item
.
Credentials
==
nil
{
if
item
.
Credentials
==
nil
{
return
return
}
}
// Only enrich OpenAI
/Sora
OAuth accounts
// Only enrich OpenAI OAuth accounts
platform
:=
strings
.
ToLower
(
strings
.
TrimSpace
(
item
.
Platform
))
platform
:=
strings
.
ToLower
(
strings
.
TrimSpace
(
item
.
Platform
))
if
platform
!=
service
.
PlatformOpenAI
&&
platform
!=
service
.
PlatformSora
{
if
platform
!=
service
.
PlatformOpenAI
{
return
return
}
}
if
strings
.
ToLower
(
strings
.
TrimSpace
(
item
.
Type
))
!=
service
.
AccountTypeOAuth
{
if
strings
.
ToLower
(
strings
.
TrimSpace
(
item
.
Type
))
!=
service
.
AccountTypeOAuth
{
...
...
backend/internal/handler/admin/account_handler.go
View file @
62e80c60
...
@@ -1875,12 +1875,6 @@ func (h *AccountHandler) GetAvailableModels(c *gin.Context) {
...
@@ -1875,12 +1875,6 @@ func (h *AccountHandler) GetAvailableModels(c *gin.Context) {
return
return
}
}
// Handle Sora accounts
if
account
.
Platform
==
service
.
PlatformSora
{
response
.
Success
(
c
,
service
.
DefaultSoraModels
(
nil
))
return
}
// Handle Claude/Anthropic accounts
// Handle Claude/Anthropic accounts
// For OAuth and Setup-Token accounts: return default models
// For OAuth and Setup-Token accounts: return default models
if
account
.
IsOAuth
()
{
if
account
.
IsOAuth
()
{
...
...
backend/internal/handler/admin/admin_service_stub_test.go
View file @
62e80c60
...
@@ -380,7 +380,6 @@ func (s *stubAdminService) CheckProxyQuality(ctx context.Context, id int64) (*se
...
@@ -380,7 +380,6 @@ func (s *stubAdminService) CheckProxyQuality(ctx context.Context, id int64) (*se
{
Target
:
"openai"
,
Status
:
"pass"
,
HTTPStatus
:
401
},
{
Target
:
"openai"
,
Status
:
"pass"
,
HTTPStatus
:
401
},
{
Target
:
"anthropic"
,
Status
:
"pass"
,
HTTPStatus
:
401
},
{
Target
:
"anthropic"
,
Status
:
"pass"
,
HTTPStatus
:
401
},
{
Target
:
"gemini"
,
Status
:
"pass"
,
HTTPStatus
:
200
},
{
Target
:
"gemini"
,
Status
:
"pass"
,
HTTPStatus
:
200
},
{
Target
:
"sora"
,
Status
:
"pass"
,
HTTPStatus
:
401
},
},
},
},
nil
},
nil
}
}
...
...
backend/internal/handler/admin/group_handler.go
View file @
62e80c60
...
@@ -84,7 +84,7 @@ func NewGroupHandler(adminService service.AdminService, dashboardService *servic
...
@@ -84,7 +84,7 @@ func NewGroupHandler(adminService service.AdminService, dashboardService *servic
type
CreateGroupRequest
struct
{
type
CreateGroupRequest
struct
{
Name
string
`json:"name" binding:"required"`
Name
string
`json:"name" binding:"required"`
Description
string
`json:"description"`
Description
string
`json:"description"`
Platform
string
`json:"platform" binding:"omitempty,oneof=anthropic openai gemini antigravity
sora
"`
Platform
string
`json:"platform" binding:"omitempty,oneof=anthropic openai gemini antigravity"`
RateMultiplier
float64
`json:"rate_multiplier"`
RateMultiplier
float64
`json:"rate_multiplier"`
IsExclusive
bool
`json:"is_exclusive"`
IsExclusive
bool
`json:"is_exclusive"`
SubscriptionType
string
`json:"subscription_type" binding:"omitempty,oneof=standard subscription"`
SubscriptionType
string
`json:"subscription_type" binding:"omitempty,oneof=standard subscription"`
...
@@ -95,10 +95,6 @@ type CreateGroupRequest struct {
...
@@ -95,10 +95,6 @@ type CreateGroupRequest struct {
ImagePrice1K
*
float64
`json:"image_price_1k"`
ImagePrice1K
*
float64
`json:"image_price_1k"`
ImagePrice2K
*
float64
`json:"image_price_2k"`
ImagePrice2K
*
float64
`json:"image_price_2k"`
ImagePrice4K
*
float64
`json:"image_price_4k"`
ImagePrice4K
*
float64
`json:"image_price_4k"`
SoraImagePrice360
*
float64
`json:"sora_image_price_360"`
SoraImagePrice540
*
float64
`json:"sora_image_price_540"`
SoraVideoPricePerRequest
*
float64
`json:"sora_video_price_per_request"`
SoraVideoPricePerRequestHD
*
float64
`json:"sora_video_price_per_request_hd"`
ClaudeCodeOnly
bool
`json:"claude_code_only"`
ClaudeCodeOnly
bool
`json:"claude_code_only"`
FallbackGroupID
*
int64
`json:"fallback_group_id"`
FallbackGroupID
*
int64
`json:"fallback_group_id"`
FallbackGroupIDOnInvalidRequest
*
int64
`json:"fallback_group_id_on_invalid_request"`
FallbackGroupIDOnInvalidRequest
*
int64
`json:"fallback_group_id_on_invalid_request"`
...
@@ -108,8 +104,6 @@ type CreateGroupRequest struct {
...
@@ -108,8 +104,6 @@ type CreateGroupRequest struct {
MCPXMLInject
*
bool
`json:"mcp_xml_inject"`
MCPXMLInject
*
bool
`json:"mcp_xml_inject"`
// 支持的模型系列(仅 antigravity 平台使用)
// 支持的模型系列(仅 antigravity 平台使用)
SupportedModelScopes
[]
string
`json:"supported_model_scopes"`
SupportedModelScopes
[]
string
`json:"supported_model_scopes"`
// Sora 存储配额
SoraStorageQuotaBytes
int64
`json:"sora_storage_quota_bytes"`
// OpenAI Messages 调度配置(仅 openai 平台使用)
// OpenAI Messages 调度配置(仅 openai 平台使用)
AllowMessagesDispatch
bool
`json:"allow_messages_dispatch"`
AllowMessagesDispatch
bool
`json:"allow_messages_dispatch"`
RequireOAuthOnly
bool
`json:"require_oauth_only"`
RequireOAuthOnly
bool
`json:"require_oauth_only"`
...
@@ -123,7 +117,7 @@ type CreateGroupRequest struct {
...
@@ -123,7 +117,7 @@ type CreateGroupRequest struct {
type
UpdateGroupRequest
struct
{
type
UpdateGroupRequest
struct
{
Name
string
`json:"name"`
Name
string
`json:"name"`
Description
string
`json:"description"`
Description
string
`json:"description"`
Platform
string
`json:"platform" binding:"omitempty,oneof=anthropic openai gemini antigravity
sora
"`
Platform
string
`json:"platform" binding:"omitempty,oneof=anthropic openai gemini antigravity"`
RateMultiplier
*
float64
`json:"rate_multiplier"`
RateMultiplier
*
float64
`json:"rate_multiplier"`
IsExclusive
*
bool
`json:"is_exclusive"`
IsExclusive
*
bool
`json:"is_exclusive"`
Status
string
`json:"status" binding:"omitempty,oneof=active inactive"`
Status
string
`json:"status" binding:"omitempty,oneof=active inactive"`
...
@@ -135,10 +129,6 @@ type UpdateGroupRequest struct {
...
@@ -135,10 +129,6 @@ type UpdateGroupRequest struct {
ImagePrice1K
*
float64
`json:"image_price_1k"`
ImagePrice1K
*
float64
`json:"image_price_1k"`
ImagePrice2K
*
float64
`json:"image_price_2k"`
ImagePrice2K
*
float64
`json:"image_price_2k"`
ImagePrice4K
*
float64
`json:"image_price_4k"`
ImagePrice4K
*
float64
`json:"image_price_4k"`
SoraImagePrice360
*
float64
`json:"sora_image_price_360"`
SoraImagePrice540
*
float64
`json:"sora_image_price_540"`
SoraVideoPricePerRequest
*
float64
`json:"sora_video_price_per_request"`
SoraVideoPricePerRequestHD
*
float64
`json:"sora_video_price_per_request_hd"`
ClaudeCodeOnly
*
bool
`json:"claude_code_only"`
ClaudeCodeOnly
*
bool
`json:"claude_code_only"`
FallbackGroupID
*
int64
`json:"fallback_group_id"`
FallbackGroupID
*
int64
`json:"fallback_group_id"`
FallbackGroupIDOnInvalidRequest
*
int64
`json:"fallback_group_id_on_invalid_request"`
FallbackGroupIDOnInvalidRequest
*
int64
`json:"fallback_group_id_on_invalid_request"`
...
@@ -148,8 +138,6 @@ type UpdateGroupRequest struct {
...
@@ -148,8 +138,6 @@ type UpdateGroupRequest struct {
MCPXMLInject
*
bool
`json:"mcp_xml_inject"`
MCPXMLInject
*
bool
`json:"mcp_xml_inject"`
// 支持的模型系列(仅 antigravity 平台使用)
// 支持的模型系列(仅 antigravity 平台使用)
SupportedModelScopes
*
[]
string
`json:"supported_model_scopes"`
SupportedModelScopes
*
[]
string
`json:"supported_model_scopes"`
// Sora 存储配额
SoraStorageQuotaBytes
*
int64
`json:"sora_storage_quota_bytes"`
// OpenAI Messages 调度配置(仅 openai 平台使用)
// OpenAI Messages 调度配置(仅 openai 平台使用)
AllowMessagesDispatch
*
bool
`json:"allow_messages_dispatch"`
AllowMessagesDispatch
*
bool
`json:"allow_messages_dispatch"`
RequireOAuthOnly
*
bool
`json:"require_oauth_only"`
RequireOAuthOnly
*
bool
`json:"require_oauth_only"`
...
@@ -258,10 +246,6 @@ func (h *GroupHandler) Create(c *gin.Context) {
...
@@ -258,10 +246,6 @@ func (h *GroupHandler) Create(c *gin.Context) {
ImagePrice1K
:
req
.
ImagePrice1K
,
ImagePrice1K
:
req
.
ImagePrice1K
,
ImagePrice2K
:
req
.
ImagePrice2K
,
ImagePrice2K
:
req
.
ImagePrice2K
,
ImagePrice4K
:
req
.
ImagePrice4K
,
ImagePrice4K
:
req
.
ImagePrice4K
,
SoraImagePrice360
:
req
.
SoraImagePrice360
,
SoraImagePrice540
:
req
.
SoraImagePrice540
,
SoraVideoPricePerRequest
:
req
.
SoraVideoPricePerRequest
,
SoraVideoPricePerRequestHD
:
req
.
SoraVideoPricePerRequestHD
,
ClaudeCodeOnly
:
req
.
ClaudeCodeOnly
,
ClaudeCodeOnly
:
req
.
ClaudeCodeOnly
,
FallbackGroupID
:
req
.
FallbackGroupID
,
FallbackGroupID
:
req
.
FallbackGroupID
,
FallbackGroupIDOnInvalidRequest
:
req
.
FallbackGroupIDOnInvalidRequest
,
FallbackGroupIDOnInvalidRequest
:
req
.
FallbackGroupIDOnInvalidRequest
,
...
@@ -269,7 +253,6 @@ func (h *GroupHandler) Create(c *gin.Context) {
...
@@ -269,7 +253,6 @@ func (h *GroupHandler) Create(c *gin.Context) {
ModelRoutingEnabled
:
req
.
ModelRoutingEnabled
,
ModelRoutingEnabled
:
req
.
ModelRoutingEnabled
,
MCPXMLInject
:
req
.
MCPXMLInject
,
MCPXMLInject
:
req
.
MCPXMLInject
,
SupportedModelScopes
:
req
.
SupportedModelScopes
,
SupportedModelScopes
:
req
.
SupportedModelScopes
,
SoraStorageQuotaBytes
:
req
.
SoraStorageQuotaBytes
,
AllowMessagesDispatch
:
req
.
AllowMessagesDispatch
,
AllowMessagesDispatch
:
req
.
AllowMessagesDispatch
,
RequireOAuthOnly
:
req
.
RequireOAuthOnly
,
RequireOAuthOnly
:
req
.
RequireOAuthOnly
,
RequirePrivacySet
:
req
.
RequirePrivacySet
,
RequirePrivacySet
:
req
.
RequirePrivacySet
,
...
@@ -313,10 +296,6 @@ func (h *GroupHandler) Update(c *gin.Context) {
...
@@ -313,10 +296,6 @@ func (h *GroupHandler) Update(c *gin.Context) {
ImagePrice1K
:
req
.
ImagePrice1K
,
ImagePrice1K
:
req
.
ImagePrice1K
,
ImagePrice2K
:
req
.
ImagePrice2K
,
ImagePrice2K
:
req
.
ImagePrice2K
,
ImagePrice4K
:
req
.
ImagePrice4K
,
ImagePrice4K
:
req
.
ImagePrice4K
,
SoraImagePrice360
:
req
.
SoraImagePrice360
,
SoraImagePrice540
:
req
.
SoraImagePrice540
,
SoraVideoPricePerRequest
:
req
.
SoraVideoPricePerRequest
,
SoraVideoPricePerRequestHD
:
req
.
SoraVideoPricePerRequestHD
,
ClaudeCodeOnly
:
req
.
ClaudeCodeOnly
,
ClaudeCodeOnly
:
req
.
ClaudeCodeOnly
,
FallbackGroupID
:
req
.
FallbackGroupID
,
FallbackGroupID
:
req
.
FallbackGroupID
,
FallbackGroupIDOnInvalidRequest
:
req
.
FallbackGroupIDOnInvalidRequest
,
FallbackGroupIDOnInvalidRequest
:
req
.
FallbackGroupIDOnInvalidRequest
,
...
@@ -324,7 +303,6 @@ func (h *GroupHandler) Update(c *gin.Context) {
...
@@ -324,7 +303,6 @@ func (h *GroupHandler) Update(c *gin.Context) {
ModelRoutingEnabled
:
req
.
ModelRoutingEnabled
,
ModelRoutingEnabled
:
req
.
ModelRoutingEnabled
,
MCPXMLInject
:
req
.
MCPXMLInject
,
MCPXMLInject
:
req
.
MCPXMLInject
,
SupportedModelScopes
:
req
.
SupportedModelScopes
,
SupportedModelScopes
:
req
.
SupportedModelScopes
,
SoraStorageQuotaBytes
:
req
.
SoraStorageQuotaBytes
,
AllowMessagesDispatch
:
req
.
AllowMessagesDispatch
,
AllowMessagesDispatch
:
req
.
AllowMessagesDispatch
,
RequireOAuthOnly
:
req
.
RequireOAuthOnly
,
RequireOAuthOnly
:
req
.
RequireOAuthOnly
,
RequirePrivacySet
:
req
.
RequirePrivacySet
,
RequirePrivacySet
:
req
.
RequirePrivacySet
,
...
...
backend/internal/handler/admin/openai_oauth_handler.go
View file @
62e80c60
...
@@ -19,9 +19,6 @@ type OpenAIOAuthHandler struct {
...
@@ -19,9 +19,6 @@ type OpenAIOAuthHandler struct {
}
}
func
oauthPlatformFromPath
(
c
*
gin
.
Context
)
string
{
func
oauthPlatformFromPath
(
c
*
gin
.
Context
)
string
{
if
strings
.
Contains
(
c
.
FullPath
(),
"/admin/sora/"
)
{
return
service
.
PlatformSora
}
return
service
.
PlatformOpenAI
return
service
.
PlatformOpenAI
}
}
...
@@ -105,7 +102,6 @@ type OpenAIRefreshTokenRequest struct {
...
@@ -105,7 +102,6 @@ type OpenAIRefreshTokenRequest struct {
// RefreshToken refreshes an OpenAI OAuth token
// RefreshToken refreshes an OpenAI OAuth token
// POST /api/v1/admin/openai/refresh-token
// POST /api/v1/admin/openai/refresh-token
// POST /api/v1/admin/sora/rt2at
func
(
h
*
OpenAIOAuthHandler
)
RefreshToken
(
c
*
gin
.
Context
)
{
func
(
h
*
OpenAIOAuthHandler
)
RefreshToken
(
c
*
gin
.
Context
)
{
var
req
OpenAIRefreshTokenRequest
var
req
OpenAIRefreshTokenRequest
if
err
:=
c
.
ShouldBindJSON
(
&
req
);
err
!=
nil
{
if
err
:=
c
.
ShouldBindJSON
(
&
req
);
err
!=
nil
{
...
@@ -145,39 +141,8 @@ func (h *OpenAIOAuthHandler) RefreshToken(c *gin.Context) {
...
@@ -145,39 +141,8 @@ func (h *OpenAIOAuthHandler) RefreshToken(c *gin.Context) {
response
.
Success
(
c
,
tokenInfo
)
response
.
Success
(
c
,
tokenInfo
)
}
}
// ExchangeSoraSessionToken exchanges Sora session token to access token
// RefreshAccountToken refreshes token for a specific OpenAI account
// POST /api/v1/admin/sora/st2at
func
(
h
*
OpenAIOAuthHandler
)
ExchangeSoraSessionToken
(
c
*
gin
.
Context
)
{
var
req
struct
{
SessionToken
string
`json:"session_token"`
ST
string
`json:"st"`
ProxyID
*
int64
`json:"proxy_id"`
}
if
err
:=
c
.
ShouldBindJSON
(
&
req
);
err
!=
nil
{
response
.
BadRequest
(
c
,
"Invalid request: "
+
err
.
Error
())
return
}
sessionToken
:=
strings
.
TrimSpace
(
req
.
SessionToken
)
if
sessionToken
==
""
{
sessionToken
=
strings
.
TrimSpace
(
req
.
ST
)
}
if
sessionToken
==
""
{
response
.
BadRequest
(
c
,
"session_token is required"
)
return
}
tokenInfo
,
err
:=
h
.
openaiOAuthService
.
ExchangeSoraSessionToken
(
c
.
Request
.
Context
(),
sessionToken
,
req
.
ProxyID
)
if
err
!=
nil
{
response
.
ErrorFrom
(
c
,
err
)
return
}
response
.
Success
(
c
,
tokenInfo
)
}
// RefreshAccountToken refreshes token for a specific OpenAI/Sora account
// POST /api/v1/admin/openai/accounts/:id/refresh
// POST /api/v1/admin/openai/accounts/:id/refresh
// POST /api/v1/admin/sora/accounts/:id/refresh
func
(
h
*
OpenAIOAuthHandler
)
RefreshAccountToken
(
c
*
gin
.
Context
)
{
func
(
h
*
OpenAIOAuthHandler
)
RefreshAccountToken
(
c
*
gin
.
Context
)
{
accountID
,
err
:=
strconv
.
ParseInt
(
c
.
Param
(
"id"
),
10
,
64
)
accountID
,
err
:=
strconv
.
ParseInt
(
c
.
Param
(
"id"
),
10
,
64
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -232,9 +197,8 @@ func (h *OpenAIOAuthHandler) RefreshAccountToken(c *gin.Context) {
...
@@ -232,9 +197,8 @@ func (h *OpenAIOAuthHandler) RefreshAccountToken(c *gin.Context) {
response
.
Success
(
c
,
dto
.
AccountFromService
(
updatedAccount
))
response
.
Success
(
c
,
dto
.
AccountFromService
(
updatedAccount
))
}
}
// CreateAccountFromOAuth creates a new OpenAI
/Sora
OAuth account from token info
// CreateAccountFromOAuth creates a new OpenAI OAuth account from token info
// POST /api/v1/admin/openai/create-from-oauth
// POST /api/v1/admin/openai/create-from-oauth
// POST /api/v1/admin/sora/create-from-oauth
func
(
h
*
OpenAIOAuthHandler
)
CreateAccountFromOAuth
(
c
*
gin
.
Context
)
{
func
(
h
*
OpenAIOAuthHandler
)
CreateAccountFromOAuth
(
c
*
gin
.
Context
)
{
var
req
struct
{
var
req
struct
{
SessionID
string
`json:"session_id" binding:"required"`
SessionID
string
`json:"session_id" binding:"required"`
...
@@ -276,11 +240,7 @@ func (h *OpenAIOAuthHandler) CreateAccountFromOAuth(c *gin.Context) {
...
@@ -276,11 +240,7 @@ func (h *OpenAIOAuthHandler) CreateAccountFromOAuth(c *gin.Context) {
name
=
tokenInfo
.
Email
name
=
tokenInfo
.
Email
}
}
if
name
==
""
{
if
name
==
""
{
if
platform
==
service
.
PlatformSora
{
name
=
"OpenAI OAuth Account"
name
=
"Sora OAuth Account"
}
else
{
name
=
"OpenAI OAuth Account"
}
}
}
// Create account
// Create account
...
...
backend/internal/handler/admin/setting_handler.go
View file @
62e80c60
...
@@ -108,7 +108,6 @@ func (h *SettingHandler) GetSettings(c *gin.Context) {
...
@@ -108,7 +108,6 @@ func (h *SettingHandler) GetSettings(c *gin.Context) {
HideCcsImportButton
:
settings
.
HideCcsImportButton
,
HideCcsImportButton
:
settings
.
HideCcsImportButton
,
PurchaseSubscriptionEnabled
:
settings
.
PurchaseSubscriptionEnabled
,
PurchaseSubscriptionEnabled
:
settings
.
PurchaseSubscriptionEnabled
,
PurchaseSubscriptionURL
:
settings
.
PurchaseSubscriptionURL
,
PurchaseSubscriptionURL
:
settings
.
PurchaseSubscriptionURL
,
SoraClientEnabled
:
settings
.
SoraClientEnabled
,
CustomMenuItems
:
dto
.
ParseCustomMenuItems
(
settings
.
CustomMenuItems
),
CustomMenuItems
:
dto
.
ParseCustomMenuItems
(
settings
.
CustomMenuItems
),
CustomEndpoints
:
dto
.
ParseCustomEndpoints
(
settings
.
CustomEndpoints
),
CustomEndpoints
:
dto
.
ParseCustomEndpoints
(
settings
.
CustomEndpoints
),
DefaultConcurrency
:
settings
.
DefaultConcurrency
,
DefaultConcurrency
:
settings
.
DefaultConcurrency
,
...
@@ -177,7 +176,6 @@ type UpdateSettingsRequest struct {
...
@@ -177,7 +176,6 @@ type UpdateSettingsRequest struct {
HideCcsImportButton
bool
`json:"hide_ccs_import_button"`
HideCcsImportButton
bool
`json:"hide_ccs_import_button"`
PurchaseSubscriptionEnabled
*
bool
`json:"purchase_subscription_enabled"`
PurchaseSubscriptionEnabled
*
bool
`json:"purchase_subscription_enabled"`
PurchaseSubscriptionURL
*
string
`json:"purchase_subscription_url"`
PurchaseSubscriptionURL
*
string
`json:"purchase_subscription_url"`
SoraClientEnabled
bool
`json:"sora_client_enabled"`
CustomMenuItems
*
[]
dto
.
CustomMenuItem
`json:"custom_menu_items"`
CustomMenuItems
*
[]
dto
.
CustomMenuItem
`json:"custom_menu_items"`
CustomEndpoints
*
[]
dto
.
CustomEndpoint
`json:"custom_endpoints"`
CustomEndpoints
*
[]
dto
.
CustomEndpoint
`json:"custom_endpoints"`
...
@@ -566,7 +564,6 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
...
@@ -566,7 +564,6 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
HideCcsImportButton
:
req
.
HideCcsImportButton
,
HideCcsImportButton
:
req
.
HideCcsImportButton
,
PurchaseSubscriptionEnabled
:
purchaseEnabled
,
PurchaseSubscriptionEnabled
:
purchaseEnabled
,
PurchaseSubscriptionURL
:
purchaseURL
,
PurchaseSubscriptionURL
:
purchaseURL
,
SoraClientEnabled
:
req
.
SoraClientEnabled
,
CustomMenuItems
:
customMenuJSON
,
CustomMenuItems
:
customMenuJSON
,
CustomEndpoints
:
customEndpointsJSON
,
CustomEndpoints
:
customEndpointsJSON
,
DefaultConcurrency
:
req
.
DefaultConcurrency
,
DefaultConcurrency
:
req
.
DefaultConcurrency
,
...
@@ -676,7 +673,6 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
...
@@ -676,7 +673,6 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
HideCcsImportButton
:
updatedSettings
.
HideCcsImportButton
,
HideCcsImportButton
:
updatedSettings
.
HideCcsImportButton
,
PurchaseSubscriptionEnabled
:
updatedSettings
.
PurchaseSubscriptionEnabled
,
PurchaseSubscriptionEnabled
:
updatedSettings
.
PurchaseSubscriptionEnabled
,
PurchaseSubscriptionURL
:
updatedSettings
.
PurchaseSubscriptionURL
,
PurchaseSubscriptionURL
:
updatedSettings
.
PurchaseSubscriptionURL
,
SoraClientEnabled
:
updatedSettings
.
SoraClientEnabled
,
CustomMenuItems
:
dto
.
ParseCustomMenuItems
(
updatedSettings
.
CustomMenuItems
),
CustomMenuItems
:
dto
.
ParseCustomMenuItems
(
updatedSettings
.
CustomMenuItems
),
CustomEndpoints
:
dto
.
ParseCustomEndpoints
(
updatedSettings
.
CustomEndpoints
),
CustomEndpoints
:
dto
.
ParseCustomEndpoints
(
updatedSettings
.
CustomEndpoints
),
DefaultConcurrency
:
updatedSettings
.
DefaultConcurrency
,
DefaultConcurrency
:
updatedSettings
.
DefaultConcurrency
,
...
...
backend/internal/handler/admin/user_handler.go
View file @
62e80c60
...
@@ -41,7 +41,6 @@ type CreateUserRequest struct {
...
@@ -41,7 +41,6 @@ type CreateUserRequest struct {
Balance
float64
`json:"balance"`
Balance
float64
`json:"balance"`
Concurrency
int
`json:"concurrency"`
Concurrency
int
`json:"concurrency"`
AllowedGroups
[]
int64
`json:"allowed_groups"`
AllowedGroups
[]
int64
`json:"allowed_groups"`
SoraStorageQuotaBytes
int64
`json:"sora_storage_quota_bytes"`
}
}
// UpdateUserRequest represents admin update user request
// UpdateUserRequest represents admin update user request
...
@@ -58,7 +57,6 @@ type UpdateUserRequest struct {
...
@@ -58,7 +57,6 @@ type UpdateUserRequest struct {
// GroupRates 用户专属分组倍率配置
// GroupRates 用户专属分组倍率配置
// map[groupID]*rate,nil 表示删除该分组的专属倍率
// map[groupID]*rate,nil 表示删除该分组的专属倍率
GroupRates
map
[
int64
]
*
float64
`json:"group_rates"`
GroupRates
map
[
int64
]
*
float64
`json:"group_rates"`
SoraStorageQuotaBytes
*
int64
`json:"sora_storage_quota_bytes"`
}
}
// UpdateBalanceRequest represents balance update request
// UpdateBalanceRequest represents balance update request
...
@@ -189,7 +187,6 @@ func (h *UserHandler) Create(c *gin.Context) {
...
@@ -189,7 +187,6 @@ func (h *UserHandler) Create(c *gin.Context) {
Balance
:
req
.
Balance
,
Balance
:
req
.
Balance
,
Concurrency
:
req
.
Concurrency
,
Concurrency
:
req
.
Concurrency
,
AllowedGroups
:
req
.
AllowedGroups
,
AllowedGroups
:
req
.
AllowedGroups
,
SoraStorageQuotaBytes
:
req
.
SoraStorageQuotaBytes
,
})
})
if
err
!=
nil
{
if
err
!=
nil
{
response
.
ErrorFrom
(
c
,
err
)
response
.
ErrorFrom
(
c
,
err
)
...
@@ -225,7 +222,6 @@ func (h *UserHandler) Update(c *gin.Context) {
...
@@ -225,7 +222,6 @@ func (h *UserHandler) Update(c *gin.Context) {
Status
:
req
.
Status
,
Status
:
req
.
Status
,
AllowedGroups
:
req
.
AllowedGroups
,
AllowedGroups
:
req
.
AllowedGroups
,
GroupRates
:
req
.
GroupRates
,
GroupRates
:
req
.
GroupRates
,
SoraStorageQuotaBytes
:
req
.
SoraStorageQuotaBytes
,
})
})
if
err
!=
nil
{
if
err
!=
nil
{
response
.
ErrorFrom
(
c
,
err
)
response
.
ErrorFrom
(
c
,
err
)
...
...
backend/internal/handler/dto/mappers.go
View file @
62e80c60
...
@@ -59,11 +59,9 @@ func UserFromServiceAdmin(u *service.User) *AdminUser {
...
@@ -59,11 +59,9 @@ func UserFromServiceAdmin(u *service.User) *AdminUser {
return
nil
return
nil
}
}
return
&
AdminUser
{
return
&
AdminUser
{
User
:
*
base
,
User
:
*
base
,
Notes
:
u
.
Notes
,
Notes
:
u
.
Notes
,
GroupRates
:
u
.
GroupRates
,
GroupRates
:
u
.
GroupRates
,
SoraStorageQuotaBytes
:
u
.
SoraStorageQuotaBytes
,
SoraStorageUsedBytes
:
u
.
SoraStorageUsedBytes
,
}
}
}
}
...
@@ -172,14 +170,9 @@ func groupFromServiceBase(g *service.Group) Group {
...
@@ -172,14 +170,9 @@ func groupFromServiceBase(g *service.Group) Group {
ImagePrice1K
:
g
.
ImagePrice1K
,
ImagePrice1K
:
g
.
ImagePrice1K
,
ImagePrice2K
:
g
.
ImagePrice2K
,
ImagePrice2K
:
g
.
ImagePrice2K
,
ImagePrice4K
:
g
.
ImagePrice4K
,
ImagePrice4K
:
g
.
ImagePrice4K
,
SoraImagePrice360
:
g
.
SoraImagePrice360
,
SoraImagePrice540
:
g
.
SoraImagePrice540
,
SoraVideoPricePerRequest
:
g
.
SoraVideoPricePerRequest
,
SoraVideoPricePerRequestHD
:
g
.
SoraVideoPricePerRequestHD
,
ClaudeCodeOnly
:
g
.
ClaudeCodeOnly
,
ClaudeCodeOnly
:
g
.
ClaudeCodeOnly
,
FallbackGroupID
:
g
.
FallbackGroupID
,
FallbackGroupID
:
g
.
FallbackGroupID
,
FallbackGroupIDOnInvalidRequest
:
g
.
FallbackGroupIDOnInvalidRequest
,
FallbackGroupIDOnInvalidRequest
:
g
.
FallbackGroupIDOnInvalidRequest
,
SoraStorageQuotaBytes
:
g
.
SoraStorageQuotaBytes
,
AllowMessagesDispatch
:
g
.
AllowMessagesDispatch
,
AllowMessagesDispatch
:
g
.
AllowMessagesDispatch
,
RequireOAuthOnly
:
g
.
RequireOAuthOnly
,
RequireOAuthOnly
:
g
.
RequireOAuthOnly
,
RequirePrivacySet
:
g
.
RequirePrivacySet
,
RequirePrivacySet
:
g
.
RequirePrivacySet
,
...
...
backend/internal/handler/dto/settings.go
View file @
62e80c60
...
@@ -61,7 +61,6 @@ type SystemSettings struct {
...
@@ -61,7 +61,6 @@ type SystemSettings struct {
HideCcsImportButton
bool
`json:"hide_ccs_import_button"`
HideCcsImportButton
bool
`json:"hide_ccs_import_button"`
PurchaseSubscriptionEnabled
bool
`json:"purchase_subscription_enabled"`
PurchaseSubscriptionEnabled
bool
`json:"purchase_subscription_enabled"`
PurchaseSubscriptionURL
string
`json:"purchase_subscription_url"`
PurchaseSubscriptionURL
string
`json:"purchase_subscription_url"`
SoraClientEnabled
bool
`json:"sora_client_enabled"`
CustomMenuItems
[]
CustomMenuItem
`json:"custom_menu_items"`
CustomMenuItems
[]
CustomMenuItem
`json:"custom_menu_items"`
CustomEndpoints
[]
CustomEndpoint
`json:"custom_endpoints"`
CustomEndpoints
[]
CustomEndpoint
`json:"custom_endpoints"`
...
@@ -128,49 +127,10 @@ type PublicSettings struct {
...
@@ -128,49 +127,10 @@ type PublicSettings struct {
CustomMenuItems
[]
CustomMenuItem
`json:"custom_menu_items"`
CustomMenuItems
[]
CustomMenuItem
`json:"custom_menu_items"`
CustomEndpoints
[]
CustomEndpoint
`json:"custom_endpoints"`
CustomEndpoints
[]
CustomEndpoint
`json:"custom_endpoints"`
LinuxDoOAuthEnabled
bool
`json:"linuxdo_oauth_enabled"`
LinuxDoOAuthEnabled
bool
`json:"linuxdo_oauth_enabled"`
SoraClientEnabled
bool
`json:"sora_client_enabled"`
BackendModeEnabled
bool
`json:"backend_mode_enabled"`
BackendModeEnabled
bool
`json:"backend_mode_enabled"`
Version
string
`json:"version"`
Version
string
`json:"version"`
}
}
// SoraS3Settings Sora S3 存储配置 DTO(响应用,不含敏感字段)
type
SoraS3Settings
struct
{
Enabled
bool
`json:"enabled"`
Endpoint
string
`json:"endpoint"`
Region
string
`json:"region"`
Bucket
string
`json:"bucket"`
AccessKeyID
string
`json:"access_key_id"`
SecretAccessKeyConfigured
bool
`json:"secret_access_key_configured"`
Prefix
string
`json:"prefix"`
ForcePathStyle
bool
`json:"force_path_style"`
CDNURL
string
`json:"cdn_url"`
DefaultStorageQuotaBytes
int64
`json:"default_storage_quota_bytes"`
}
// SoraS3Profile Sora S3 存储配置项 DTO(响应用,不含敏感字段)
type
SoraS3Profile
struct
{
ProfileID
string
`json:"profile_id"`
Name
string
`json:"name"`
IsActive
bool
`json:"is_active"`
Enabled
bool
`json:"enabled"`
Endpoint
string
`json:"endpoint"`
Region
string
`json:"region"`
Bucket
string
`json:"bucket"`
AccessKeyID
string
`json:"access_key_id"`
SecretAccessKeyConfigured
bool
`json:"secret_access_key_configured"`
Prefix
string
`json:"prefix"`
ForcePathStyle
bool
`json:"force_path_style"`
CDNURL
string
`json:"cdn_url"`
DefaultStorageQuotaBytes
int64
`json:"default_storage_quota_bytes"`
UpdatedAt
string
`json:"updated_at"`
}
// ListSoraS3ProfilesResponse Sora S3 配置列表响应
type
ListSoraS3ProfilesResponse
struct
{
ActiveProfileID
string
`json:"active_profile_id"`
Items
[]
SoraS3Profile
`json:"items"`
}
// OverloadCooldownSettings 529过载冷却配置 DTO
// OverloadCooldownSettings 529过载冷却配置 DTO
type
OverloadCooldownSettings
struct
{
type
OverloadCooldownSettings
struct
{
Enabled
bool
`json:"enabled"`
Enabled
bool
`json:"enabled"`
...
...
backend/internal/handler/dto/types.go
View file @
62e80c60
...
@@ -26,9 +26,7 @@ type AdminUser struct {
...
@@ -26,9 +26,7 @@ type AdminUser struct {
Notes
string
`json:"notes"`
Notes
string
`json:"notes"`
// GroupRates 用户专属分组倍率配置
// GroupRates 用户专属分组倍率配置
// map[groupID]rateMultiplier
// map[groupID]rateMultiplier
GroupRates
map
[
int64
]
float64
`json:"group_rates,omitempty"`
GroupRates
map
[
int64
]
float64
`json:"group_rates,omitempty"`
SoraStorageQuotaBytes
int64
`json:"sora_storage_quota_bytes"`
SoraStorageUsedBytes
int64
`json:"sora_storage_used_bytes"`
}
}
type
APIKey
struct
{
type
APIKey
struct
{
...
@@ -84,21 +82,12 @@ type Group struct {
...
@@ -84,21 +82,12 @@ type Group struct {
ImagePrice2K
*
float64
`json:"image_price_2k"`
ImagePrice2K
*
float64
`json:"image_price_2k"`
ImagePrice4K
*
float64
`json:"image_price_4k"`
ImagePrice4K
*
float64
`json:"image_price_4k"`
// Sora 按次计费配置
SoraImagePrice360
*
float64
`json:"sora_image_price_360"`
SoraImagePrice540
*
float64
`json:"sora_image_price_540"`
SoraVideoPricePerRequest
*
float64
`json:"sora_video_price_per_request"`
SoraVideoPricePerRequestHD
*
float64
`json:"sora_video_price_per_request_hd"`
// Claude Code 客户端限制
// Claude Code 客户端限制
ClaudeCodeOnly
bool
`json:"claude_code_only"`
ClaudeCodeOnly
bool
`json:"claude_code_only"`
FallbackGroupID
*
int64
`json:"fallback_group_id"`
FallbackGroupID
*
int64
`json:"fallback_group_id"`
// 无效请求兜底分组
// 无效请求兜底分组
FallbackGroupIDOnInvalidRequest
*
int64
`json:"fallback_group_id_on_invalid_request"`
FallbackGroupIDOnInvalidRequest
*
int64
`json:"fallback_group_id_on_invalid_request"`
// Sora 存储配额
SoraStorageQuotaBytes
int64
`json:"sora_storage_quota_bytes"`
// OpenAI Messages 调度开关(用户侧需要此字段判断是否展示 Claude Code 教程)
// OpenAI Messages 调度开关(用户侧需要此字段判断是否展示 Claude Code 教程)
AllowMessagesDispatch
bool
`json:"allow_messages_dispatch"`
AllowMessagesDispatch
bool
`json:"allow_messages_dispatch"`
...
...
backend/internal/handler/endpoint.go
View file @
62e80c60
...
@@ -31,7 +31,7 @@ const (
...
@@ -31,7 +31,7 @@ const (
// ──────────────────────────────────────────────────────────
// ──────────────────────────────────────────────────────────
// NormalizeInboundEndpoint maps a raw request path (which may carry
// NormalizeInboundEndpoint maps a raw request path (which may carry
// prefixes like /antigravity, /openai
, /sora
) to its canonical form.
// prefixes like /antigravity, /openai) to its canonical form.
//
//
// "/antigravity/v1/messages" → "/v1/messages"
// "/antigravity/v1/messages" → "/v1/messages"
// "/v1/chat/completions" → "/v1/chat/completions"
// "/v1/chat/completions" → "/v1/chat/completions"
...
@@ -61,7 +61,7 @@ func NormalizeInboundEndpoint(path string) string {
...
@@ -61,7 +61,7 @@ func NormalizeInboundEndpoint(path string) string {
// such as /v1/responses/compact preserved from the raw URL).
// such as /v1/responses/compact preserved from the raw URL).
// - Anthropic → /v1/messages
// - Anthropic → /v1/messages
// - Gemini → /v1beta/models
// - Gemini → /v1beta/models
// -
Sora → /v1/chat/completions
// -
Antigravity → /v1/messages (Claude) or gemini (Gemini)
// - Antigravity routes may target either Claude or Gemini, so the
// - Antigravity routes may target either Claude or Gemini, so the
// inbound endpoint is used to distinguish.
// inbound endpoint is used to distinguish.
func
DeriveUpstreamEndpoint
(
inbound
,
rawRequestPath
,
platform
string
)
string
{
func
DeriveUpstreamEndpoint
(
inbound
,
rawRequestPath
,
platform
string
)
string
{
...
@@ -82,9 +82,6 @@ func DeriveUpstreamEndpoint(inbound, rawRequestPath, platform string) string {
...
@@ -82,9 +82,6 @@ func DeriveUpstreamEndpoint(inbound, rawRequestPath, platform string) string {
case
service
.
PlatformGemini
:
case
service
.
PlatformGemini
:
return
EndpointGeminiModels
return
EndpointGeminiModels
case
service
.
PlatformSora
:
return
EndpointChatCompletions
case
service
.
PlatformAntigravity
:
case
service
.
PlatformAntigravity
:
// Antigravity accounts serve both Claude and Gemini.
// Antigravity accounts serve both Claude and Gemini.
if
inbound
==
EndpointGeminiModels
{
if
inbound
==
EndpointGeminiModels
{
...
...
backend/internal/handler/endpoint_test.go
View file @
62e80c60
...
@@ -27,11 +27,10 @@ func TestNormalizeInboundEndpoint(t *testing.T) {
...
@@ -27,11 +27,10 @@ func TestNormalizeInboundEndpoint(t *testing.T) {
{
"/v1/responses"
,
EndpointResponses
},
{
"/v1/responses"
,
EndpointResponses
},
{
"/v1beta/models"
,
EndpointGeminiModels
},
{
"/v1beta/models"
,
EndpointGeminiModels
},
// Prefixed paths (antigravity, openai
, sora
).
// Prefixed paths (antigravity, openai).
{
"/antigravity/v1/messages"
,
EndpointMessages
},
{
"/antigravity/v1/messages"
,
EndpointMessages
},
{
"/openai/v1/responses"
,
EndpointResponses
},
{
"/openai/v1/responses"
,
EndpointResponses
},
{
"/openai/v1/responses/compact"
,
EndpointResponses
},
{
"/openai/v1/responses/compact"
,
EndpointResponses
},
{
"/sora/v1/chat/completions"
,
EndpointChatCompletions
},
{
"/antigravity/v1beta/models/gemini:generateContent"
,
EndpointGeminiModels
},
{
"/antigravity/v1beta/models/gemini:generateContent"
,
EndpointGeminiModels
},
// Gin route patterns with wildcards.
// Gin route patterns with wildcards.
...
@@ -68,9 +67,6 @@ func TestDeriveUpstreamEndpoint(t *testing.T) {
...
@@ -68,9 +67,6 @@ func TestDeriveUpstreamEndpoint(t *testing.T) {
// Gemini.
// Gemini.
{
"gemini models"
,
EndpointGeminiModels
,
"/v1beta/models/gemini:gen"
,
service
.
PlatformGemini
,
EndpointGeminiModels
},
{
"gemini models"
,
EndpointGeminiModels
,
"/v1beta/models/gemini:gen"
,
service
.
PlatformGemini
,
EndpointGeminiModels
},
// Sora.
{
"sora completions"
,
EndpointChatCompletions
,
"/sora/v1/chat/completions"
,
service
.
PlatformSora
,
EndpointChatCompletions
},
// OpenAI — always /v1/responses.
// OpenAI — always /v1/responses.
{
"openai responses root"
,
EndpointResponses
,
"/v1/responses"
,
service
.
PlatformOpenAI
,
EndpointResponses
},
{
"openai responses root"
,
EndpointResponses
,
"/v1/responses"
,
service
.
PlatformOpenAI
,
EndpointResponses
},
{
"openai responses compact"
,
EndpointResponses
,
"/openai/v1/responses/compact"
,
service
.
PlatformOpenAI
,
"/v1/responses/compact"
},
{
"openai responses compact"
,
EndpointResponses
,
"/openai/v1/responses/compact"
,
service
.
PlatformOpenAI
,
"/v1/responses/compact"
},
...
...
backend/internal/handler/gateway_handler.go
View file @
62e80c60
...
@@ -859,14 +859,6 @@ func (h *GatewayHandler) Models(c *gin.Context) {
...
@@ -859,14 +859,6 @@ func (h *GatewayHandler) Models(c *gin.Context) {
platform
=
forcedPlatform
platform
=
forcedPlatform
}
}
if
platform
==
service
.
PlatformSora
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"object"
:
"list"
,
"data"
:
service
.
DefaultSoraModels
(
h
.
cfg
),
})
return
}
// Get available models from account configurations (without platform filter)
// Get available models from account configurations (without platform filter)
availableModels
:=
h
.
gatewayService
.
GetAvailableModels
(
c
.
Request
.
Context
(),
groupID
,
""
)
availableModels
:=
h
.
gatewayService
.
GetAvailableModels
(
c
.
Request
.
Context
(),
groupID
,
""
)
...
...
backend/internal/handler/handler.go
View file @
62e80c60
...
@@ -45,8 +45,6 @@ type Handlers struct {
...
@@ -45,8 +45,6 @@ type Handlers struct {
Admin
*
AdminHandlers
Admin
*
AdminHandlers
Gateway
*
GatewayHandler
Gateway
*
GatewayHandler
OpenAIGateway
*
OpenAIGatewayHandler
OpenAIGateway
*
OpenAIGatewayHandler
SoraGateway
*
SoraGatewayHandler
SoraClient
*
SoraClientHandler
Setting
*
SettingHandler
Setting
*
SettingHandler
Totp
*
TotpHandler
Totp
*
TotpHandler
}
}
...
...
backend/internal/handler/setting_handler.go
View file @
62e80c60
...
@@ -54,7 +54,6 @@ func (h *SettingHandler) GetPublicSettings(c *gin.Context) {
...
@@ -54,7 +54,6 @@ func (h *SettingHandler) GetPublicSettings(c *gin.Context) {
CustomMenuItems
:
dto
.
ParseUserVisibleMenuItems
(
settings
.
CustomMenuItems
),
CustomMenuItems
:
dto
.
ParseUserVisibleMenuItems
(
settings
.
CustomMenuItems
),
CustomEndpoints
:
dto
.
ParseCustomEndpoints
(
settings
.
CustomEndpoints
),
CustomEndpoints
:
dto
.
ParseCustomEndpoints
(
settings
.
CustomEndpoints
),
LinuxDoOAuthEnabled
:
settings
.
LinuxDoOAuthEnabled
,
LinuxDoOAuthEnabled
:
settings
.
LinuxDoOAuthEnabled
,
SoraClientEnabled
:
settings
.
SoraClientEnabled
,
BackendModeEnabled
:
settings
.
BackendModeEnabled
,
BackendModeEnabled
:
settings
.
BackendModeEnabled
,
Version
:
h
.
version
,
Version
:
h
.
version
,
})
})
...
...
Prev
1
2
3
4
5
…
7
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment