settings_view.go 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. package service
  2. import "strings"
  3. func firstNonEmpty(values ...string) string {
  4. for _, value := range values {
  5. if trimmed := strings.TrimSpace(value); trimmed != "" {
  6. return trimmed
  7. }
  8. }
  9. return ""
  10. }
  11. type SystemSettings struct {
  12. RegistrationEnabled bool
  13. EmailVerifyEnabled bool
  14. RegistrationEmailSuffixWhitelist []string
  15. RegistrationEmailDomainQuotaEnabled bool // 白名单非空时放行非白名单域名限量注册(默认关闭)
  16. PromoCodeEnabled bool
  17. PasswordResetEnabled bool
  18. FrontendURL string
  19. InvitationCodeEnabled bool
  20. TotpEnabled bool // TOTP 双因素认证
  21. PasskeyEnabled bool // Passkey 登录
  22. SessionBindingEnabled bool // 会话 IP/UA 绑定(变更即失效)
  23. StepUpEnabled bool // 敏感操作 step-up 2FA 门控
  24. AuditLogRetentionDays int // 审计日志保留天数(<=0 永久保留)
  25. LoginAgreementEnabled bool
  26. LoginAgreementMode string
  27. LoginAgreementUpdatedAt string
  28. LoginAgreementDocuments []LoginAgreementDocument
  29. SMTPHost string
  30. SMTPPort int
  31. SMTPUsername string
  32. SMTPPassword string
  33. SMTPPasswordConfigured bool
  34. SMTPFrom string
  35. SMTPFromName string
  36. SMTPUseTLS bool
  37. TurnstileEnabled bool
  38. TurnstileSiteKey string
  39. TurnstileSecretKey string
  40. TurnstileSecretKeyConfigured bool
  41. TencentCaptchaEnabled bool
  42. TencentCaptchaAppID string
  43. TencentCaptchaAppSecretKey string
  44. TencentCaptchaAppSecretKeyConfigured bool
  45. TencentCaptchaCloudSecretID string
  46. TencentCaptchaCloudSecretIDConfigured bool
  47. TencentCaptchaCloudSecretKey string
  48. TencentCaptchaCloudSecretKeyConfigured bool
  49. TencentCaptchaRegion string
  50. AliyunCaptchaEnabled bool
  51. AliyunCaptchaAccessKeyID string
  52. AliyunCaptchaAccessKeySecret string
  53. AliyunCaptchaAccessKeySecretConfigured bool
  54. AliyunCaptchaSceneID string
  55. AliyunCaptchaPrefix string
  56. AliyunCaptchaRegion string
  57. APIKeyACLTrustForwardedIP bool
  58. ForwardedClientIPHeaders []string
  59. // LinuxDo Connect OAuth 登录
  60. LinuxDoConnectEnabled bool
  61. LinuxDoConnectClientID string
  62. LinuxDoConnectClientSecret string
  63. LinuxDoConnectClientSecretConfigured bool
  64. LinuxDoConnectRedirectURL string
  65. // DingTalk Connect OAuth 登录
  66. DingTalkConnectEnabled bool
  67. DingTalkConnectClientID string
  68. DingTalkConnectClientSecret string
  69. DingTalkConnectClientSecretConfigured bool
  70. DingTalkConnectRedirectURL string
  71. DingTalkConnectCorpRestrictionPolicy string
  72. DingTalkConnectInternalCorpID string
  73. DingTalkConnectBypassRegistration bool
  74. DingTalkConnectSyncCorpEmail bool
  75. DingTalkConnectSyncDisplayName bool
  76. DingTalkConnectSyncDept bool
  77. DingTalkConnectSyncCorpEmailAttrKey string
  78. DingTalkConnectSyncDisplayNameAttrKey string
  79. DingTalkConnectSyncDeptAttrKey string
  80. DingTalkConnectSyncCorpEmailAttrName string
  81. DingTalkConnectSyncDisplayNameAttrName string
  82. DingTalkConnectSyncDeptAttrName string
  83. // WeChat Connect OAuth 登录
  84. WeChatConnectEnabled bool
  85. WeChatConnectAppID string
  86. WeChatConnectAppSecret string
  87. WeChatConnectAppSecretConfigured bool
  88. WeChatConnectOpenAppID string
  89. WeChatConnectOpenAppSecret string
  90. WeChatConnectOpenAppSecretConfigured bool
  91. WeChatConnectMPAppID string
  92. WeChatConnectMPAppSecret string
  93. WeChatConnectMPAppSecretConfigured bool
  94. WeChatConnectMobileAppID string
  95. WeChatConnectMobileAppSecret string
  96. WeChatConnectMobileAppSecretConfigured bool
  97. WeChatConnectOpenEnabled bool
  98. WeChatConnectMPEnabled bool
  99. WeChatConnectMobileEnabled bool
  100. WeChatConnectMode string
  101. WeChatConnectScopes string
  102. WeChatConnectRedirectURL string
  103. WeChatConnectFrontendRedirectURL string
  104. // Generic OIDC OAuth 登录
  105. OIDCConnectEnabled bool
  106. OIDCConnectProviderName string
  107. OIDCConnectClientID string
  108. OIDCConnectClientSecret string
  109. OIDCConnectClientSecretConfigured bool
  110. OIDCConnectIssuerURL string
  111. OIDCConnectDiscoveryURL string
  112. OIDCConnectAuthorizeURL string
  113. OIDCConnectTokenURL string
  114. OIDCConnectUserInfoURL string
  115. OIDCConnectJWKSURL string
  116. OIDCConnectScopes string
  117. OIDCConnectRedirectURL string
  118. OIDCConnectFrontendRedirectURL string
  119. OIDCConnectTokenAuthMethod string
  120. OIDCConnectUsePKCE bool
  121. OIDCConnectValidateIDToken bool
  122. OIDCConnectAllowedSigningAlgs string
  123. OIDCConnectClockSkewSeconds int
  124. OIDCConnectRequireEmailVerified bool
  125. OIDCConnectUserInfoEmailPath string
  126. OIDCConnectUserInfoIDPath string
  127. OIDCConnectUserInfoUsernamePath string
  128. // GitHub / Google 邮箱快捷登录
  129. GitHubOAuthEnabled bool
  130. GitHubOAuthClientID string
  131. GitHubOAuthClientSecret string
  132. GitHubOAuthClientSecretConfigured bool
  133. GitHubOAuthRedirectURL string
  134. GitHubOAuthFrontendRedirectURL string
  135. GoogleOAuthEnabled bool
  136. GoogleOAuthClientID string
  137. GoogleOAuthClientSecret string
  138. GoogleOAuthClientSecretConfigured bool
  139. GoogleOAuthRedirectURL string
  140. GoogleOAuthFrontendRedirectURL string
  141. SiteName string
  142. SiteLogo string
  143. SiteSubtitle string
  144. APIBaseURL string
  145. ContactInfo string
  146. DocURL string
  147. HomeContent string
  148. CompactHomeEnabled bool
  149. HideCcsImportButton bool
  150. PurchaseSubscriptionEnabled bool
  151. PurchaseSubscriptionURL string
  152. TableDefaultPageSize int
  153. TablePageSizeOptions []int
  154. CustomMenuItems string // JSON array of custom menu items
  155. CustomEndpoints string // JSON array of custom endpoints
  156. DefaultConcurrency int
  157. DefaultBalance float64
  158. RiskControlEnabled bool
  159. CyberSessionBlockEnabled bool
  160. CyberSessionBlockTTLSeconds int
  161. AffiliateEnabled bool
  162. AffiliateRebateRate float64
  163. AffiliateRebateFreezeHours int
  164. AffiliateRebateDurationDays int
  165. AffiliateRebatePerInviteeCap float64
  166. AdminRechargeRebateEnabled bool
  167. DefaultUserRPMLimit int
  168. DefaultSubscriptions []DefaultSubscriptionSetting
  169. // Model fallback configuration
  170. EnableModelFallback bool `json:"enable_model_fallback"`
  171. FallbackModelAnthropic string `json:"fallback_model_anthropic"`
  172. FallbackModelOpenAI string `json:"fallback_model_openai"`
  173. FallbackModelGemini string `json:"fallback_model_gemini"`
  174. FallbackModelAntigravity string `json:"fallback_model_antigravity"`
  175. // Identity patch configuration (Claude -> Gemini)
  176. EnableIdentityPatch bool `json:"enable_identity_patch"`
  177. IdentityPatchPrompt string `json:"identity_patch_prompt"`
  178. // Ops monitoring (vNext)
  179. OpsMonitoringEnabled bool
  180. OpsRealtimeMonitoringEnabled bool
  181. OpsQueryModeDefault string
  182. OpsMetricsIntervalSeconds int
  183. // Channel Monitor feature
  184. ChannelMonitorEnabled bool `json:"channel_monitor_enabled"`
  185. ChannelMonitorMode string `json:"channel_monitor_mode"`
  186. ChannelMonitorDefaultIntervalSeconds int `json:"channel_monitor_default_interval_seconds"`
  187. ChannelMonitorHideThroughput bool `json:"channel_monitor_hide_throughput"`
  188. ChannelMonitorShowQuota bool `json:"channel_monitor_show_quota"`
  189. ChannelMonitorHideUserRanking bool `json:"channel_monitor_hide_user_ranking"`
  190. // Grok model mapping policy (admin settings; empty mapping falls back to these).
  191. GrokDefaultTextModel string `json:"grok_default_text_model"`
  192. GrokCrossClientModelMapEnabled bool `json:"grok_cross_client_model_map_enabled"`
  193. GrokDefaultBaseURLMode string `json:"grok_default_base_url_mode"`
  194. // Available Channels feature (user-facing aggregate view)
  195. AvailableChannelsEnabled bool `json:"available_channels_enabled"`
  196. // Model Plaza feature (public group/model pricing showcase)
  197. ModelPlazaEnabled bool `json:"model_plaza_enabled"`
  198. ModelPlazaRequireAuth bool `json:"model_plaza_require_auth"`
  199. ModelPlazaDescription string `json:"model_plaza_description"`
  200. PluginManagementEnabled bool `json:"plugin_management_enabled"`
  201. // Claude Code version check
  202. MinClaudeCodeVersion string
  203. MaxClaudeCodeVersion string
  204. // 分组隔离:允许未分组 Key 调度(默认 false → 403)
  205. AllowUngroupedKeyScheduling bool
  206. // Backend 模式:禁用用户注册和自助服务,仅管理员可登录
  207. BackendModeEnabled bool
  208. // Gateway forwarding behavior
  209. OpenAITTFTMode string // Responses first_token_ms 统计口径(默认 semantic)
  210. EnableFingerprintUnification bool // 是否统一 OAuth 账号的指纹头(默认 true)
  211. EnableMetadataPassthrough bool // 是否透传客户端原始 metadata(默认 false)
  212. EnableCCHSigning bool // 已废弃 no-op:新版 CLI 取消 cch 签名后网关不再注入/签名 cch,开关无效果
  213. EnableClaudeOAuthSystemPromptInjection bool // 是否对 Claude OAuth mimic 路径注入 Claude Code system blocks(默认 true)
  214. ClaudeOAuthSystemPrompt string // Claude OAuth mimic 路径注入的通用扩展 system prompt;空值使用内置默认
  215. ClaudeOAuthSystemPromptBlocks string // Claude OAuth mimic 路径注入的 system blocks JSON 配置;空值使用内置默认
  216. EnableAnthropicCacheTTL1hInjection bool // 是否对 Anthropic OAuth/SetupToken 请求体注入 1h cache_control ttl(默认 false)
  217. EnableClientDatelineNormalization bool // 是否对 Anthropic OAuth/SetupToken 请求体做客户端 dateline 归一化(默认 true)
  218. RewriteMessageCacheControl bool // 是否改写 messages[*].content[*].cache_control(默认 false)
  219. AntigravityUserAgentVersion string // Antigravity 上游 User-Agent 版本号;空值使用配置/默认值
  220. OpenAICodexUserAgent string // OpenAI Codex 上游完整 User-Agent;空值由 Codex 客户端版本号拼出标准 TUI UA
  221. OpenAICodexClientVersion string // 出站声明的 Codex 客户端版本号(管理员覆写);空值跟随自动同步值
  222. OpenAICodexClientVersionSynced string // 自动同步到的官方最新稳定版版本号(只读展示)
  223. OpenAICodexVersionAutoSyncEnabled bool // 是否启用 Codex 客户端版本号自动同步(默认 true)
  224. MinCodexVersion string // codex_cli_only 最低 Codex 引擎版本;空=不检查
  225. MaxCodexVersion string // codex_cli_only 最高 Codex 引擎版本;空=不检查
  226. CodexCLIOnlyBlacklist string // codex_cli_only 全局黑名单 JSON([]AllowedClientEntry,OR deny)
  227. CodexCLIOnlyWhitelist string // codex_cli_only 全局白名单 JSON([]AllowedClientEntry,AND allow)
  228. CodexCLIOnlyAllowAppServerClients bool // codex_cli_only App Server 开关:对未列名客户端开闸(默认 false)
  229. CodexCLIOnlyEngineFingerprintSignals string // codex_cli_only 引擎指纹门信号列表 JSON([]EngineFingerprintSignal)
  230. // Web Search Emulation
  231. WebSearchEmulationEnabled bool // 是否启用 web search 模拟
  232. // Payment visible method routing
  233. PaymentVisibleMethodAlipaySource string
  234. PaymentVisibleMethodWxpaySource string
  235. PaymentVisibleMethodAlipayEnabled bool
  236. PaymentVisibleMethodWxpayEnabled bool
  237. // OpenAI 账号调度
  238. OpenAILowUpstreamRatePriorityEnabled bool
  239. OpenAIOAuthSchedulingRateMultiplier float64
  240. OpenAIAdvancedSchedulerEnabled bool
  241. OpenAIAdvancedSchedulerStickyWeightedEnabled bool
  242. OpenAIAdvancedSchedulerSubscriptionPriorityEnabled bool
  243. OpenAIAdvancedSchedulerLBTopK string
  244. OpenAIAdvancedSchedulerWeightPriority string
  245. OpenAIAdvancedSchedulerWeightLoad string
  246. OpenAIAdvancedSchedulerWeightQueue string
  247. OpenAIAdvancedSchedulerWeightErrorRate string
  248. OpenAIAdvancedSchedulerWeightTTFT string
  249. OpenAIAdvancedSchedulerWeightReset string
  250. OpenAIAdvancedSchedulerWeightQuotaHeadroom string
  251. OpenAIAdvancedSchedulerWeightUpstreamCost string
  252. OpenAIAdvancedSchedulerWeightPreviousResponse string
  253. OpenAIAdvancedSchedulerWeightSessionSticky string
  254. OpenAIAdvancedSchedulerEffectiveLBTopK string
  255. OpenAIAdvancedSchedulerEffectiveWeightPriority string
  256. OpenAIAdvancedSchedulerEffectiveWeightLoad string
  257. OpenAIAdvancedSchedulerEffectiveWeightQueue string
  258. OpenAIAdvancedSchedulerEffectiveWeightErrorRate string
  259. OpenAIAdvancedSchedulerEffectiveWeightTTFT string
  260. OpenAIAdvancedSchedulerEffectiveWeightReset string
  261. OpenAIAdvancedSchedulerEffectiveWeightQuotaHeadroom string
  262. OpenAIAdvancedSchedulerEffectiveWeightUpstreamCost string
  263. OpenAIAdvancedSchedulerEffectiveWeightPreviousResponse string
  264. OpenAIAdvancedSchedulerEffectiveWeightSessionSticky string
  265. // 余额不足提醒
  266. BalanceLowNotifyEnabled bool
  267. BalanceLowNotifyThreshold float64
  268. BalanceLowNotifyRechargeURL string
  269. // 订阅到期提醒
  270. SubscriptionExpiryNotifyEnabled bool
  271. // 账号限额通知
  272. AccountQuotaNotifyEnabled bool
  273. AccountQuotaNotifyEmails []NotifyEmailEntry
  274. // 系统全局默认平台配额(key = platform,nil/缺省 = 不限制)
  275. DefaultPlatformQuotas map[string]*DefaultPlatformQuotaSetting `json:"default_platform_quotas"`
  276. // 系统全局账号自动停调阈值(key = platform,100 = disabled)
  277. AccountSchedulingThresholds map[string]int `json:"account_scheduling_thresholds"`
  278. // 允许终端用户在用量页查看自己的失败请求
  279. AllowUserViewErrorRequests bool
  280. }
  281. type DefaultSubscriptionSetting struct {
  282. GroupID int64 `json:"group_id"`
  283. ValidityDays int `json:"validity_days"`
  284. }
  285. type PublicSettings struct {
  286. RegistrationEnabled bool
  287. EmailVerifyEnabled bool
  288. ForceEmailOnThirdPartySignup bool
  289. RegistrationEmailSuffixWhitelist []string
  290. RegistrationEmailDomainQuotaEnabled bool
  291. PromoCodeEnabled bool
  292. PasswordResetEnabled bool
  293. InvitationCodeEnabled bool
  294. TotpEnabled bool // TOTP 双因素认证
  295. PasskeyEnabled bool
  296. LoginAgreementEnabled bool
  297. LoginAgreementMode string
  298. LoginAgreementUpdatedAt string
  299. LoginAgreementRevision string
  300. LoginAgreementDocuments []LoginAgreementDocument
  301. TurnstileEnabled bool
  302. TurnstileSiteKey string
  303. TencentCaptchaEnabled bool
  304. TencentCaptchaAppID string
  305. TencentCaptchaRegion string
  306. AliyunCaptchaEnabled bool
  307. AliyunCaptchaSceneID string
  308. AliyunCaptchaPrefix string
  309. AliyunCaptchaRegion string
  310. SiteName string
  311. SiteLogo string
  312. SiteSubtitle string
  313. APIBaseURL string
  314. ContactInfo string
  315. DocURL string
  316. HomeContent string
  317. CompactHomeEnabled bool
  318. HideCcsImportButton bool
  319. PurchaseSubscriptionEnabled bool
  320. PurchaseSubscriptionURL string
  321. TableDefaultPageSize int
  322. TablePageSizeOptions []int
  323. CustomMenuItems string // JSON array of custom menu items
  324. CustomEndpoints string // JSON array of custom endpoints
  325. LinuxDoOAuthEnabled bool
  326. DingTalkOAuthEnabled bool
  327. WeChatOAuthEnabled bool
  328. WeChatOAuthOpenEnabled bool
  329. WeChatOAuthMPEnabled bool
  330. WeChatOAuthMobileEnabled bool
  331. BackendModeEnabled bool
  332. PaymentEnabled bool
  333. OIDCOAuthEnabled bool
  334. OIDCOAuthProviderName string
  335. GitHubOAuthEnabled bool
  336. GoogleOAuthEnabled bool
  337. Version string
  338. BalanceLowNotifyEnabled bool
  339. AccountQuotaNotifyEnabled bool
  340. BalanceLowNotifyThreshold float64
  341. BalanceLowNotifyRechargeURL string
  342. // Channel Monitor feature
  343. ChannelMonitorEnabled bool `json:"channel_monitor_enabled"`
  344. ChannelMonitorMode string `json:"channel_monitor_mode"`
  345. ChannelMonitorDefaultIntervalSeconds int `json:"channel_monitor_default_interval_seconds"`
  346. ChannelMonitorHideThroughput bool `json:"channel_monitor_hide_throughput"`
  347. ChannelMonitorShowQuota bool `json:"channel_monitor_show_quota"`
  348. ChannelMonitorHideUserRanking bool `json:"channel_monitor_hide_user_ranking"`
  349. // Grok model mapping policy (admin settings).
  350. GrokDefaultTextModel string `json:"grok_default_text_model"`
  351. GrokCrossClientModelMapEnabled bool `json:"grok_cross_client_model_map_enabled"`
  352. GrokDefaultBaseURLMode string `json:"grok_default_base_url_mode"`
  353. // Available Channels feature (user-facing aggregate view)
  354. AvailableChannelsEnabled bool `json:"available_channels_enabled"`
  355. // Model Plaza feature (public group/model pricing showcase)
  356. ModelPlazaEnabled bool `json:"model_plaza_enabled"`
  357. ModelPlazaRequireAuth bool `json:"model_plaza_require_auth"`
  358. PluginManagementEnabled bool `json:"plugin_management_enabled"`
  359. // Affiliate (邀请返利) feature toggle
  360. AffiliateEnabled bool `json:"affiliate_enabled"`
  361. // 风控中心功能开关
  362. RiskControlEnabled bool `json:"risk_control_enabled"`
  363. // 允许终端用户在用量页查看自己的失败请求
  364. AllowUserViewErrorRequests bool `json:"allow_user_view_error_requests"`
  365. }
  366. type LoginAgreementDocument struct {
  367. ID string `json:"id"`
  368. Title string `json:"title"`
  369. ContentMD string `json:"content_md"`
  370. }
  371. type WeChatConnectOAuthConfig struct {
  372. Enabled bool
  373. LegacyAppID string
  374. LegacyAppSecret string
  375. OpenAppID string
  376. OpenAppSecret string
  377. MPAppID string
  378. MPAppSecret string
  379. MobileAppID string
  380. MobileAppSecret string
  381. OpenEnabled bool
  382. MPEnabled bool
  383. MobileEnabled bool
  384. Mode string
  385. Scopes string
  386. RedirectURL string
  387. FrontendRedirectURL string
  388. }
  389. func (cfg WeChatConnectOAuthConfig) SupportsMode(mode string) bool {
  390. switch normalizeWeChatConnectModeSetting(mode) {
  391. case "mp":
  392. return cfg.MPEnabled
  393. case "mobile":
  394. return cfg.MobileEnabled
  395. default:
  396. return cfg.OpenEnabled
  397. }
  398. }
  399. func (cfg WeChatConnectOAuthConfig) ScopeForMode(mode string) string {
  400. switch normalizeWeChatConnectModeSetting(mode) {
  401. case "mp":
  402. return normalizeWeChatConnectScopeSetting(cfg.Scopes, "mp")
  403. case "mobile":
  404. return ""
  405. }
  406. return defaultWeChatConnectScopeForMode("open")
  407. }
  408. func (cfg WeChatConnectOAuthConfig) AppIDForMode(mode string) string {
  409. switch normalizeWeChatConnectModeSetting(mode) {
  410. case "mp":
  411. return strings.TrimSpace(firstNonEmpty(cfg.MPAppID, cfg.LegacyAppID))
  412. case "mobile":
  413. return strings.TrimSpace(firstNonEmpty(cfg.MobileAppID, cfg.LegacyAppID))
  414. }
  415. return strings.TrimSpace(firstNonEmpty(cfg.OpenAppID, cfg.LegacyAppID))
  416. }
  417. func (cfg WeChatConnectOAuthConfig) AppSecretForMode(mode string) string {
  418. switch normalizeWeChatConnectModeSetting(mode) {
  419. case "mp":
  420. return strings.TrimSpace(firstNonEmpty(cfg.MPAppSecret, cfg.LegacyAppSecret))
  421. case "mobile":
  422. return strings.TrimSpace(firstNonEmpty(cfg.MobileAppSecret, cfg.LegacyAppSecret))
  423. }
  424. return strings.TrimSpace(firstNonEmpty(cfg.OpenAppSecret, cfg.LegacyAppSecret))
  425. }
  426. // StreamTimeoutSettings 流超时处理配置(仅控制超时后的处理方式,超时判定由网关配置控制)
  427. type StreamTimeoutSettings struct {
  428. // Enabled 是否启用流超时处理
  429. Enabled bool `json:"enabled"`
  430. // Action 超时后的处理方式: "temp_unsched" | "error" | "none"
  431. Action string `json:"action"`
  432. // TempUnschedMinutes 临时不可调度持续时间(分钟)
  433. TempUnschedMinutes int `json:"temp_unsched_minutes"`
  434. // ThresholdCount 触发阈值次数(累计多少次超时才触发)
  435. ThresholdCount int `json:"threshold_count"`
  436. // ThresholdWindowMinutes 阈值窗口时间(分钟)
  437. ThresholdWindowMinutes int `json:"threshold_window_minutes"`
  438. }
  439. // StreamTimeoutAction 流超时处理方式常量
  440. const (
  441. StreamTimeoutActionTempUnsched = "temp_unsched" // 临时不可调度
  442. StreamTimeoutActionError = "error" // 标记为错误状态
  443. StreamTimeoutActionNone = "none" // 不处理
  444. )
  445. // DefaultStreamTimeoutSettings 返回默认的流超时配置
  446. func DefaultStreamTimeoutSettings() *StreamTimeoutSettings {
  447. return &StreamTimeoutSettings{
  448. Enabled: false,
  449. Action: StreamTimeoutActionTempUnsched,
  450. TempUnschedMinutes: 5,
  451. ThresholdCount: 3,
  452. ThresholdWindowMinutes: 10,
  453. }
  454. }
  455. // RectifierSettings 请求整流器配置
  456. type RectifierSettings struct {
  457. Enabled bool `json:"enabled"` // 总开关
  458. ThinkingSignatureEnabled bool `json:"thinking_signature_enabled"` // Thinking 签名整流
  459. ThinkingBudgetEnabled bool `json:"thinking_budget_enabled"` // Thinking Budget 整流
  460. APIKeySignatureEnabled bool `json:"apikey_signature_enabled"` // API Key 签名整流开关
  461. APIKeySignaturePatterns []string `json:"apikey_signature_patterns"` // API Key 自定义匹配关键词
  462. }
  463. // DefaultRectifierSettings 返回默认的整流器配置(全部启用)
  464. func DefaultRectifierSettings() *RectifierSettings {
  465. return &RectifierSettings{
  466. Enabled: true,
  467. ThinkingSignatureEnabled: true,
  468. ThinkingBudgetEnabled: true,
  469. }
  470. }
  471. // Beta Policy 策略常量
  472. const (
  473. BetaPolicyActionPass = "pass" // 透传,不做任何处理
  474. BetaPolicyActionFilter = "filter" // 过滤,从 beta header 中移除该 token
  475. BetaPolicyActionBlock = "block" // 拦截,直接返回错误
  476. BetaPolicyScopeAll = "all" // 所有账号类型
  477. BetaPolicyScopeOAuth = "oauth" // 仅 OAuth 账号
  478. BetaPolicyScopeAPIKey = "apikey" // 仅 API Key 账号
  479. BetaPolicyScopeBedrock = "bedrock" // 仅 AWS Bedrock 账号
  480. )
  481. // BetaPolicyRule 单条 Beta 策略规则
  482. type BetaPolicyRule struct {
  483. BetaToken string `json:"beta_token"` // beta token 值
  484. Action string `json:"action"` // "pass" | "filter" | "block"
  485. Scope string `json:"scope"` // "all" | "oauth" | "apikey" | "bedrock"
  486. ErrorMessage string `json:"error_message,omitempty"` // 自定义错误消息 (action=block 时生效)
  487. ModelWhitelist []string `json:"model_whitelist,omitempty"` // 模型匹配模式列表(为空=对所有模型生效)
  488. FallbackAction string `json:"fallback_action,omitempty"` // 未匹配白名单的模型的处理方式
  489. FallbackErrorMessage string `json:"fallback_error_message,omitempty"` // 未匹配白名单时的自定义错误消息 (fallback_action=block 时生效)
  490. }
  491. // BetaPolicySettings Beta 策略配置
  492. type BetaPolicySettings struct {
  493. Rules []BetaPolicyRule `json:"rules"`
  494. }
  495. // OverloadCooldownSettings 529过载冷却配置
  496. type OverloadCooldownSettings struct {
  497. // Enabled 是否在收到529时暂停账号调度
  498. Enabled bool `json:"enabled"`
  499. // CooldownMinutes 冷却时长(分钟)
  500. CooldownMinutes int `json:"cooldown_minutes"`
  501. }
  502. // RateLimit429CooldownSettings 429默认回避配置
  503. type RateLimit429CooldownSettings struct {
  504. // Enabled 是否在无法解析上游重置时间时应用默认429回避
  505. Enabled bool `json:"enabled"`
  506. // CooldownSeconds 默认回避时长(秒)
  507. CooldownSeconds int `json:"cooldown_seconds"`
  508. }
  509. // OpenAIImagesOAuthUnavailableCooldownSettings controls how long an OAuth account's image capability is paused when unavailable.
  510. type OpenAIImagesOAuthUnavailableCooldownSettings struct {
  511. CooldownMinutes int `json:"cooldown_minutes"`
  512. }
  513. const (
  514. openAIImagesOAuthUnavailableDefaultCooldownMinutes = 30
  515. openAIImagesOAuthUnavailableMaxCooldownMinutes = 120
  516. )
  517. // OpenAIAPIKeyHealthBreakerSettings controls cross-instance failure counting for OpenAI pool API keys.
  518. type OpenAIAPIKeyHealthBreakerSettings struct {
  519. Enabled bool `json:"enabled"`
  520. WindowMinutes int `json:"window_minutes"`
  521. FailureThreshold int `json:"failure_threshold"`
  522. CooldownMinutes int `json:"cooldown_minutes"`
  523. }
  524. func DefaultOpenAIAPIKeyHealthBreakerSettings() *OpenAIAPIKeyHealthBreakerSettings {
  525. return &OpenAIAPIKeyHealthBreakerSettings{
  526. Enabled: false,
  527. WindowMinutes: 2,
  528. FailureThreshold: 10,
  529. CooldownMinutes: 5,
  530. }
  531. }
  532. // DefaultOverloadCooldownSettings 返回默认的过载冷却配置(启用,10分钟)
  533. func DefaultOverloadCooldownSettings() *OverloadCooldownSettings {
  534. return &OverloadCooldownSettings{
  535. Enabled: true,
  536. CooldownMinutes: 10,
  537. }
  538. }
  539. // DefaultRateLimit429CooldownSettings 返回默认的429回避配置(启用,5秒)
  540. func DefaultRateLimit429CooldownSettings() *RateLimit429CooldownSettings {
  541. return &RateLimit429CooldownSettings{
  542. Enabled: true,
  543. CooldownSeconds: 5,
  544. }
  545. }
  546. func DefaultOpenAIImagesOAuthUnavailableCooldownSettings() *OpenAIImagesOAuthUnavailableCooldownSettings {
  547. return &OpenAIImagesOAuthUnavailableCooldownSettings{CooldownMinutes: openAIImagesOAuthUnavailableDefaultCooldownMinutes}
  548. }
  549. // DefaultBetaPolicySettings 返回默认的 Beta 策略配置
  550. //
  551. // context-1m-2025-08-07 的默认策略:
  552. // - 仅 claude-sonnet-5 及后续版本(如 claude-sonnet-5-*)在上游默认支持 1M 上下文。
  553. // - Sonnet 4.x 及以下、Opus、Haiku 上游都不支持该 beta,透传上去会被上游 400 或降级。
  554. // - 因此默认对 sonnet-5* 放行、其余全部过滤,与上游能力保持一致。
  555. //
  556. // 白名单需要覆盖每个上游路径的模型 ID 变形:
  557. // - 直连 Anthropic API(OAuth mimic / API Key / SetupToken):模型保持客户端原样
  558. // (如 "claude-sonnet-5"、"claude-sonnet-5-YYYYMMDD"、"claude-sonnet-5-thinking")。
  559. // - Vertex AI:normalizeVertexAnthropicModelID 会把 "-YYYYMMDD" 后缀转成 "@YYYYMMDD"
  560. // (如 "claude-sonnet-5@YYYYMMDD")。
  561. // - AWS Bedrock:ResolveBedrockModelID 会输出带跨区域前缀的模型 ID
  562. // (us./eu./apac./jp./au./us-gov./global. 或无前缀的 "anthropic." 形式)。
  563. //
  564. // 白名单只用后缀通配符(matchModelPattern 语义),因此每个路径都需要显式列出前缀。
  565. // 精确匹配 "claude-sonnet-5" + 后缀 "-*" 与 "@*",可覆盖直连/Vertex 场景,同时避免误伤
  566. // 未来可能出现的 "claude-sonnet-50" 或 "claude-sonnet-5.x" 之类的意外命名。
  567. func DefaultBetaPolicySettings() *BetaPolicySettings {
  568. return &BetaPolicySettings{
  569. Rules: []BetaPolicyRule{
  570. {
  571. BetaToken: "fast-mode-2026-02-01",
  572. Action: BetaPolicyActionFilter,
  573. Scope: BetaPolicyScopeAll,
  574. },
  575. {
  576. BetaToken: "context-1m-2025-08-07",
  577. Action: BetaPolicyActionPass,
  578. Scope: BetaPolicyScopeAll,
  579. ModelWhitelist: []string{
  580. // 直连 Anthropic API(客户端请求 model 原样)
  581. "claude-sonnet-5",
  582. "claude-sonnet-5-*",
  583. // Vertex AI 走 normalizeVertexAnthropicModelID 后 "@YYYYMMDD" 格式
  584. "claude-sonnet-5@*",
  585. // AWS Bedrock cross-region inference profile
  586. "us.anthropic.claude-sonnet-5*",
  587. "eu.anthropic.claude-sonnet-5*",
  588. "apac.anthropic.claude-sonnet-5*",
  589. "jp.anthropic.claude-sonnet-5*",
  590. "au.anthropic.claude-sonnet-5*",
  591. "us-gov.anthropic.claude-sonnet-5*",
  592. "global.anthropic.claude-sonnet-5*",
  593. // AWS Bedrock 无 cross-region 前缀
  594. "anthropic.claude-sonnet-5*",
  595. },
  596. FallbackAction: BetaPolicyActionFilter,
  597. },
  598. },
  599. }
  600. }
  601. // OpenAI Fast Policy 策略常量
  602. // OpenAI 的 "fast 模式" 通过请求体中的 service_tier 字段识别:
  603. // - "priority"(客户端可传 "fast",归一化为 "priority"):fast 模式
  604. // - "ultrafast":Codex/API 的 Ultrafast 档位
  605. // - "flex":低优先级模式
  606. // - 省略:normal 默认
  607. //
  608. // 本策略复用 BetaPolicyAction*/BetaPolicyScope* 常量语义,只是匹配键从
  609. // anthropic-beta header 换成 body 的 service_tier 字段。
  610. const (
  611. OpenAIFastTierAny = "all" // 匹配任意已识别的 service_tier
  612. OpenAIFastTierPriority = "priority" // 仅匹配 fast(priority)
  613. OpenAIFastTierUltrafast = "ultrafast" // 仅匹配 ultrafast
  614. OpenAIFastTierFlex = "flex" // 仅匹配 flex
  615. // OpenAIFastPolicyActionForcePriority 会保留 service_tier 字段并强制写成
  616. // priority,用于把 flex/auto/default/scale 等已识别 tier 收敛为 fast。
  617. OpenAIFastPolicyActionForcePriority = "force_priority"
  618. )
  619. // OpenAIFastPolicyRule 单条 OpenAI fast/flex 策略规则
  620. type OpenAIFastPolicyRule struct {
  621. ServiceTier string `json:"service_tier"` // "priority" | "ultrafast" | "flex" | "auto" | "default" | "scale" | "all"
  622. Action string `json:"action"` // "pass" | "filter" | "block" | "force_priority"
  623. Scope string `json:"scope"` // "all" | "oauth" | "apikey" | "bedrock"
  624. UserIDs []int64 `json:"user_ids,omitempty"` // 空=所有 Sub2API 用户;非空=仅指定 API Key 所属用户
  625. ErrorMessage string `json:"error_message,omitempty"` // 自定义错误消息 (action=block 时生效)
  626. ModelWhitelist []string `json:"model_whitelist,omitempty"` // 模型匹配模式列表(为空=对所有模型生效)
  627. FallbackAction string `json:"fallback_action,omitempty"` // 未匹配白名单的模型的处理方式
  628. FallbackErrorMessage string `json:"fallback_error_message,omitempty"` // 未匹配白名单时的自定义错误消息 (fallback_action=block 时生效)
  629. }
  630. // OpenAIFastPolicySettings OpenAI fast 策略配置
  631. type OpenAIFastPolicySettings struct {
  632. Rules []OpenAIFastPolicyRule `json:"rules"`
  633. }
  634. // DefaultOpenAIFastPolicySettings 返回默认的 OpenAI fast 策略配置。
  635. // 默认不配置任何规则,保留 OpenAI 上游 service_tier 语义;管理员如需
  636. // 限制 priority/flex,可以在 admin UI 中显式配置 filter 或 block 规则。
  637. func DefaultOpenAIFastPolicySettings() *OpenAIFastPolicySettings {
  638. return &OpenAIFastPolicySettings{
  639. Rules: []OpenAIFastPolicyRule{},
  640. }
  641. }