From f0022f59a244f32b57747808f592bd13a9a026b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Fri, 13 Mar 2026 20:14:27 +0800 Subject: [PATCH] ccm,ocm: block utilization decrease within same rate-limit window updateStateFromHeaders unconditionally applied header utilization values even when they were lower than the current state, causing poll-sourced values to be overwritten by stale header values. Parse reset timestamps before utilization and only allow decreases when the reset timestamp changes (indicating a new rate-limit window). Also add math.Ceil to CCM external credential for consistency with default credential. --- service/ccm/credential_external.go | 12 ++++---- service/ccm/credential_state.go | 29 +++++++++++------- service/ocm/credential_external.go | 23 ++++++++------- service/ocm/credential_state.go | 47 ++++++++++++++++++++---------- 4 files changed, 67 insertions(+), 44 deletions(-) diff --git a/service/ccm/credential_external.go b/service/ccm/credential_external.go index 7459a8891..141c893c3 100644 --- a/service/ccm/credential_external.go +++ b/service/ccm/credential_external.go @@ -368,15 +368,18 @@ func (c *externalCredential) updateStateFromHeaders(headers http.Header) { oldFiveHour := c.state.fiveHourUtilization oldWeekly := c.state.weeklyUtilization + if value, exists := parseOptionalAnthropicResetHeader(headers, "anthropic-ratelimit-unified-5h-reset"); exists { + c.state.fiveHourReset = value + } if utilization := headers.Get("anthropic-ratelimit-unified-5h-utilization"); utilization != "" { value, err := strconv.ParseFloat(utilization, 64) if err == nil { - // Remote CCM writes aggregated utilization as 0.0-1.0; convert to percentage c.state.fiveHourUtilization = value * 100 } } - if value, exists := parseOptionalAnthropicResetHeader(headers, "anthropic-ratelimit-unified-5h-reset"); exists { - c.state.fiveHourReset = value + + if value, exists := parseOptionalAnthropicResetHeader(headers, "anthropic-ratelimit-unified-7d-reset"); exists { + c.state.weeklyReset = value } if utilization := headers.Get("anthropic-ratelimit-unified-7d-utilization"); utilization != "" { value, err := strconv.ParseFloat(utilization, 64) @@ -384,9 +387,6 @@ func (c *externalCredential) updateStateFromHeaders(headers http.Header) { c.state.weeklyUtilization = value * 100 } } - if value, exists := parseOptionalAnthropicResetHeader(headers, "anthropic-ratelimit-unified-7d-reset"); exists { - c.state.weeklyReset = value - } c.state.lastUpdated = time.Now() if isFirstUpdate || int(c.state.fiveHourUtilization*100) != int(oldFiveHour*100) || int(c.state.weeklyUtilization*100) != int(oldWeekly*100) { c.logger.Debug("usage update for ", c.tag, ": 5h=", c.state.fiveHourUtilization, "%, weekly=", c.state.weeklyUtilization, "%") diff --git a/service/ccm/credential_state.go b/service/ccm/credential_state.go index 6ecdd50a8..788058547 100644 --- a/service/ccm/credential_state.go +++ b/service/ccm/credential_state.go @@ -338,32 +338,39 @@ func (c *defaultCredential) updateStateFromHeaders(headers http.Header) { oldFiveHour := c.state.fiveHourUtilization oldWeekly := c.state.weeklyUtilization + fiveHourResetChanged := false + if value, exists := parseOptionalAnthropicResetHeader(headers, "anthropic-ratelimit-unified-5h-reset"); exists { + if value.After(c.state.fiveHourReset) { + fiveHourResetChanged = true + c.state.fiveHourReset = value + } + } if utilization := headers.Get("anthropic-ratelimit-unified-5h-utilization"); utilization != "" { value, err := strconv.ParseFloat(utilization, 64) if err == nil { newValue := math.Ceil(value * 100) - if newValue < c.state.fiveHourUtilization { - c.logger.Error("header 5h utilization for ", c.tag, " is lower than current: ", newValue, " < ", c.state.fiveHourUtilization) + if newValue >= c.state.fiveHourUtilization || fiveHourResetChanged { + c.state.fiveHourUtilization = newValue } - c.state.fiveHourUtilization = newValue } } - if value, exists := parseOptionalAnthropicResetHeader(headers, "anthropic-ratelimit-unified-5h-reset"); exists { - c.state.fiveHourReset = value + + weeklyResetChanged := false + if value, exists := parseOptionalAnthropicResetHeader(headers, "anthropic-ratelimit-unified-7d-reset"); exists { + if value.After(c.state.weeklyReset) { + weeklyResetChanged = true + c.state.weeklyReset = value + } } if utilization := headers.Get("anthropic-ratelimit-unified-7d-utilization"); utilization != "" { value, err := strconv.ParseFloat(utilization, 64) if err == nil { newValue := math.Ceil(value * 100) - if newValue < c.state.weeklyUtilization { - c.logger.Error("header weekly utilization for ", c.tag, " is lower than current: ", newValue, " < ", c.state.weeklyUtilization) + if newValue >= c.state.weeklyUtilization || weeklyResetChanged { + c.state.weeklyUtilization = newValue } - c.state.weeklyUtilization = newValue } } - if value, exists := parseOptionalAnthropicResetHeader(headers, "anthropic-ratelimit-unified-7d-reset"); exists { - c.state.weeklyReset = value - } c.state.lastUpdated = time.Now() if isFirstUpdate || int(c.state.fiveHourUtilization*100) != int(oldFiveHour*100) || int(c.state.weeklyUtilization*100) != int(oldWeekly*100) { c.logger.Debug("usage update for ", c.tag, ": 5h=", c.state.fiveHourUtilization, "%, weekly=", c.state.weeklyUtilization, "%") diff --git a/service/ocm/credential_external.go b/service/ocm/credential_external.go index d396705f2..0d6e6b4b1 100644 --- a/service/ocm/credential_external.go +++ b/service/ocm/credential_external.go @@ -395,13 +395,6 @@ func (c *externalCredential) updateStateFromHeaders(headers http.Header) { activeLimitIdentifier = "codex" } - fiveHourPercent := headers.Get("x-" + activeLimitIdentifier + "-primary-used-percent") - if fiveHourPercent != "" { - value, err := strconv.ParseFloat(fiveHourPercent, 64) - if err == nil { - c.state.fiveHourUtilization = value - } - } fiveHourResetAt := headers.Get("x-" + activeLimitIdentifier + "-primary-reset-at") if fiveHourResetAt != "" { value, err := strconv.ParseInt(fiveHourResetAt, 10, 64) @@ -409,13 +402,14 @@ func (c *externalCredential) updateStateFromHeaders(headers http.Header) { c.state.fiveHourReset = time.Unix(value, 0) } } - weeklyPercent := headers.Get("x-" + activeLimitIdentifier + "-secondary-used-percent") - if weeklyPercent != "" { - value, err := strconv.ParseFloat(weeklyPercent, 64) + fiveHourPercent := headers.Get("x-" + activeLimitIdentifier + "-primary-used-percent") + if fiveHourPercent != "" { + value, err := strconv.ParseFloat(fiveHourPercent, 64) if err == nil { - c.state.weeklyUtilization = value + c.state.fiveHourUtilization = value } } + weeklyResetAt := headers.Get("x-" + activeLimitIdentifier + "-secondary-reset-at") if weeklyResetAt != "" { value, err := strconv.ParseInt(weeklyResetAt, 10, 64) @@ -423,6 +417,13 @@ func (c *externalCredential) updateStateFromHeaders(headers http.Header) { c.state.weeklyReset = time.Unix(value, 0) } } + weeklyPercent := headers.Get("x-" + activeLimitIdentifier + "-secondary-used-percent") + if weeklyPercent != "" { + value, err := strconv.ParseFloat(weeklyPercent, 64) + if err == nil { + c.state.weeklyUtilization = value + } + } c.state.lastUpdated = time.Now() if isFirstUpdate || int(c.state.fiveHourUtilization*100) != int(oldFiveHour*100) || int(c.state.weeklyUtilization*100) != int(oldWeekly*100) { c.logger.Debug("usage update for ", c.tag, ": 5h=", c.state.fiveHourUtilization, "%, weekly=", c.state.weeklyUtilization, "%") diff --git a/service/ocm/credential_state.go b/service/ocm/credential_state.go index 821183da2..81019336b 100644 --- a/service/ocm/credential_state.go +++ b/service/ocm/credential_state.go @@ -345,32 +345,47 @@ func (c *defaultCredential) updateStateFromHeaders(headers http.Header) { activeLimitIdentifier = "codex" } - fiveHourPercent := headers.Get("x-" + activeLimitIdentifier + "-primary-used-percent") - if fiveHourPercent != "" { - value, err := strconv.ParseFloat(fiveHourPercent, 64) - if err == nil { - c.state.fiveHourUtilization = value - } - } + fiveHourResetChanged := false fiveHourResetAt := headers.Get("x-" + activeLimitIdentifier + "-primary-reset-at") if fiveHourResetAt != "" { value, err := strconv.ParseInt(fiveHourResetAt, 10, 64) if err == nil { - c.state.fiveHourReset = time.Unix(value, 0) + newReset := time.Unix(value, 0) + if newReset.After(c.state.fiveHourReset) { + fiveHourResetChanged = true + c.state.fiveHourReset = newReset + } + } + } + fiveHourPercent := headers.Get("x-" + activeLimitIdentifier + "-primary-used-percent") + if fiveHourPercent != "" { + value, err := strconv.ParseFloat(fiveHourPercent, 64) + if err == nil { + if value >= c.state.fiveHourUtilization || fiveHourResetChanged { + c.state.fiveHourUtilization = value + } + } + } + + weeklyResetChanged := false + weeklyResetAt := headers.Get("x-" + activeLimitIdentifier + "-secondary-reset-at") + if weeklyResetAt != "" { + value, err := strconv.ParseInt(weeklyResetAt, 10, 64) + if err == nil { + newReset := time.Unix(value, 0) + if newReset.After(c.state.weeklyReset) { + weeklyResetChanged = true + c.state.weeklyReset = newReset + } } } weeklyPercent := headers.Get("x-" + activeLimitIdentifier + "-secondary-used-percent") if weeklyPercent != "" { value, err := strconv.ParseFloat(weeklyPercent, 64) if err == nil { - c.state.weeklyUtilization = value - } - } - weeklyResetAt := headers.Get("x-" + activeLimitIdentifier + "-secondary-reset-at") - if weeklyResetAt != "" { - value, err := strconv.ParseInt(weeklyResetAt, 10, 64) - if err == nil { - c.state.weeklyReset = time.Unix(value, 0) + if value >= c.state.weeklyUtilization || weeklyResetChanged { + c.state.weeklyUtilization = value + } } } c.state.lastUpdated = time.Now()