@@ -304,6 +304,8 @@ type accountResponse struct {
304304 LastUsedAt string `json:"last_used_at"`
305305 SuccessRequests int64 `json:"success_requests"`
306306 ErrorRequests int64 `json:"error_requests"`
307+ RetryErrorRequests int64 `json:"retry_error_requests"`
308+ RateLimitAttempts int64 `json:"rate_limit_attempts"`
307309 UsagePercent7d * float64 `json:"usage_percent_7d"`
308310 UsagePercent5h * float64 `json:"usage_percent_5h"`
309311 Usage5hDetail * accountUsageWindow `json:"usage_5h_detail,omitempty"`
@@ -315,6 +317,9 @@ type accountResponse struct {
315317 LastRateLimitedAt string `json:"last_rate_limited_at,omitempty"`
316318 LastTimeoutAt string `json:"last_timeout_at,omitempty"`
317319 LastServerErrorAt string `json:"last_server_error_at,omitempty"`
320+ CooldownReason string `json:"cooldown_reason,omitempty"`
321+ CooldownUntil string `json:"cooldown_until,omitempty"`
322+ ModelCooldowns []modelCooldownResponse `json:"model_cooldowns,omitempty"`
318323 Enabled bool `json:"enabled"`
319324 Locked bool `json:"locked"`
320325 AllowedAPIKeyIDs []int64 `json:"allowed_api_key_ids"`
@@ -325,6 +330,13 @@ type accountResponse struct {
325330 ImageQuotaResetAt string `json:"image_quota_reset_at,omitempty"`
326331}
327332
333+ type modelCooldownResponse struct {
334+ Model string `json:"model"`
335+ Reason string `json:"reason"`
336+ ResetAt string `json:"reset_at"`
337+ Remaining int64 `json:"remaining_seconds"`
338+ }
339+
328340type accountUsageWindow struct {
329341 Requests int64 `json:"requests"`
330342 Tokens int64 `json:"tokens"`
@@ -442,15 +454,32 @@ func (h *Handler) ListAccounts(c *gin.Context) {
442454 if ! debug .LastServerErrorAt .IsZero () {
443455 resp .LastServerErrorAt = debug .LastServerErrorAt .Format (time .RFC3339 )
444456 }
457+ if reason , until := acc .GetCooldownSnapshot (); ! until .IsZero () && until .After (time .Now ()) {
458+ resp .CooldownReason = reason
459+ resp .CooldownUntil = until .Format (time .RFC3339 )
460+ }
461+ for _ , cooldown := range acc .ActiveModelCooldowns () {
462+ resp .ModelCooldowns = append (resp .ModelCooldowns , modelCooldownResponse {
463+ Model : cooldown .Model ,
464+ Reason : cooldown .Reason ,
465+ ResetAt : cooldown .ResetAt .Format (time .RFC3339 ),
466+ Remaining : int64 (time .Until (cooldown .ResetAt ).Seconds ()),
467+ })
468+ }
445469 // 使用运行时状态(优先于 DB 状态)
446470 resp .Status = acc .RuntimeStatus ()
471+ } else if row .CooldownUntil .Valid && row .CooldownUntil .Time .After (time .Now ()) {
472+ resp .CooldownReason = row .CooldownReason
473+ resp .CooldownUntil = row .CooldownUntil .Time .Format (time .RFC3339 )
447474 }
448475 if resp .DispatchScore == 0 {
449476 resp .DispatchScore = dispatchScoreFallback (resp .SchedulerScore , resp .ScoreBiasEffective , resp .HealthTier , resp .Status )
450477 }
451478 if rc , ok := reqCounts [row .ID ]; ok {
452479 resp .SuccessRequests = rc .SuccessCount
453480 resp .ErrorRequests = rc .ErrorCount
481+ resp .RetryErrorRequests = rc .RetryErrorCount
482+ resp .RateLimitAttempts = rc .RateLimitAttemptCount
454483 }
455484 if usage , ok := usage5h [row .ID ]; ok {
456485 resp .Usage5hDetail = & accountUsageWindow {
@@ -2142,6 +2171,7 @@ type settingsResponse struct {
21422171 ProxyPoolEnabled bool `json:"proxy_pool_enabled"`
21432172 FastSchedulerEnabled bool `json:"fast_scheduler_enabled"`
21442173 MaxRetries int `json:"max_retries"`
2174+ MaxRateLimitRetries int `json:"max_rate_limit_retries"`
21452175 AllowRemoteMigration bool `json:"allow_remote_migration"`
21462176 DatabaseDriver string `json:"database_driver"`
21472177 DatabaseLabel string `json:"database_label"`
@@ -2182,6 +2212,7 @@ type updateSettingsReq struct {
21822212 ProxyPoolEnabled * bool `json:"proxy_pool_enabled"`
21832213 FastSchedulerEnabled * bool `json:"fast_scheduler_enabled"`
21842214 MaxRetries * int `json:"max_retries"`
2215+ MaxRateLimitRetries * int `json:"max_rate_limit_retries"`
21852216 AllowRemoteMigration * bool `json:"allow_remote_migration"`
21862217 ModelMapping * string `json:"model_mapping"`
21872218 ResinURL * string `json:"resin_url"`
@@ -2234,6 +2265,7 @@ func (h *Handler) GetSettings(c *gin.Context) {
22342265 ProxyPoolEnabled : h .store .GetProxyPoolEnabled (),
22352266 FastSchedulerEnabled : h .store .FastSchedulerEnabled (),
22362267 MaxRetries : h .store .GetMaxRetries (),
2268+ MaxRateLimitRetries : h .store .GetMaxRateLimitRetries (),
22372269 AllowRemoteMigration : h .store .GetAllowRemoteMigration () && adminAuthSource != "disabled" ,
22382270 DatabaseDriver : h .databaseDriver ,
22392271 DatabaseLabel : h .databaseLabel ,
@@ -2436,6 +2468,18 @@ func (h *Handler) UpdateSettings(c *gin.Context) {
24362468 log .Printf ("设置已更新: max_retries = %d" , v )
24372469 }
24382470
2471+ if req .MaxRateLimitRetries != nil {
2472+ v := * req .MaxRateLimitRetries
2473+ if v < 0 {
2474+ v = 0
2475+ }
2476+ if v > 10 {
2477+ v = 10
2478+ }
2479+ h .store .SetMaxRateLimitRetries (v )
2480+ log .Printf ("设置已更新: max_rate_limit_retries = %d" , v )
2481+ }
2482+
24392483 if req .AllowRemoteMigration != nil {
24402484 if * req .AllowRemoteMigration && ! hasAdminSecret {
24412485 writeError (c , http .StatusBadRequest , "请先设置管理密钥,再启用远程迁移" )
@@ -2560,6 +2604,7 @@ func (h *Handler) UpdateSettings(c *gin.Context) {
25602604 ProxyPoolEnabled : h .store .GetProxyPoolEnabled (),
25612605 FastSchedulerEnabled : h .store .FastSchedulerEnabled (),
25622606 MaxRetries : h .store .GetMaxRetries (),
2607+ MaxRateLimitRetries : h .store .GetMaxRateLimitRetries (),
25632608 AllowRemoteMigration : h .store .GetAllowRemoteMigration () && hasAdminSecret ,
25642609 ModelMapping : h .store .GetModelMapping (),
25652610 ResinURL : resinURL ,
@@ -2612,6 +2657,7 @@ func (h *Handler) UpdateSettings(c *gin.Context) {
26122657 ProxyPoolEnabled : h .store .GetProxyPoolEnabled (),
26132658 FastSchedulerEnabled : h .store .FastSchedulerEnabled (),
26142659 MaxRetries : h .store .GetMaxRetries (),
2660+ MaxRateLimitRetries : h .store .GetMaxRateLimitRetries (),
26152661 AllowRemoteMigration : h .store .GetAllowRemoteMigration () && adminAuthSource != "disabled" ,
26162662 DatabaseDriver : h .databaseDriver ,
26172663 DatabaseLabel : h .databaseLabel ,
0 commit comments