From 8f22f5cdf094fe746b44bef4e41bfd2f97db7e82 Mon Sep 17 00:00:00 2001 From: dawn <90008@klbr.net> Date: Wed, 9 Sep 2026 14:58:30 +0300 Subject: [PATCH] fix(fetcher): classify codex rate windows by duration and drop fake session limit --- Sources/UsageTray/UsageFetcher.swift | 83 +++++++++++++++++----------- 1 file changed, 52 insertions(+), 31 deletions(-) diff --git a/Sources/UsageTray/UsageFetcher.swift b/Sources/UsageTray/UsageFetcher.swift index 77df7fe..67da3b1 100644 --- a/Sources/UsageTray/UsageFetcher.swift +++ b/Sources/UsageTray/UsageFetcher.swift @@ -241,44 +241,65 @@ public actor UsageFetcher { var session5hWindow: UsageWindowItem? = nil var weeklyWindow: UsageWindowItem? = nil + func makeCodexWindow(dict: [String: Any], limitReached: Bool, fallbackToWeekly: Bool) -> UsageWindowItem { + let usedPct = (dict["used_percent"] as? Double) + ?? (dict["used_percent"] as? Int).map(Double.init) + ?? 0.0 + let windowSeconds = (dict["limit_window_seconds"] as? Double) + ?? (dict["limit_window_seconds"] as? Int).map(Double.init) + ?? 0.0 + let resetAfterSeconds = (dict["reset_after_seconds"] as? Double) + ?? (dict["reset_after_seconds"] as? Int).map(Double.init) + ?? 0.0 + + var resetDate: Date? = nil + if let resetAt = (dict["reset_at"] as? Double) ?? (dict["reset_at"] as? Int).map(Double.init) { + resetDate = Date(timeIntervalSince1970: resetAt > 1_000_000_000_000 ? resetAt / 1000 : resetAt) + } else if resetAfterSeconds > 0 { + resetDate = Date().addingTimeInterval(resetAfterSeconds) + } + + let isSession: Bool + if windowSeconds > 0 { + isSession = windowSeconds <= 86_400 + } else if resetAfterSeconds > 0 { + isSession = resetAfterSeconds <= 86_400 + } else { + isSession = !fallbackToWeekly + } + + let id = isSession ? "codex:session:5h" : "codex:weekly:7d" + let label = isSession ? "Session (5h)" : "Weekly (7d)" + let isExhausted = limitReached || usedPct >= 100.0 + + return UsageWindowItem( + id: id, + label: label, + usedPercent: usedPct, + resetsAt: resetDate, + detail: isExhausted ? "Exhausted (100%)" : String(format: "%.0f%% used", usedPct), + isExhausted: isExhausted + ) + } + if let rateLimit = json["rate_limit"] as? [String: Any] { let limitReached = (rateLimit["limit_reached"] as? Bool) ?? false if let primary = rateLimit["primary_window"] as? [String: Any] { - let usedPct = (primary["used_percent"] as? Double) ?? 0.0 - var resetDate: Date? = nil - if let resetAt = primary["reset_at"] as? Double { - resetDate = Date(timeIntervalSince1970: resetAt) + let item = makeCodexWindow(dict: primary, limitReached: limitReached, fallbackToWeekly: false) + if item.id == "codex:session:5h" { + session5hWindow = item + } else { + weeklyWindow = item } - weeklyWindow = UsageWindowItem( - id: "codex:weekly:7d", - label: "Weekly (7d)", - usedPercent: usedPct, - resetsAt: resetDate, - detail: limitReached ? "Exhausted (100%)" : String(format: "%.0f%% used", usedPct), - isExhausted: limitReached || usedPct >= 100.0 - ) } - } - // 5-Hour Session window from additional rate limits - if let addLimits = json["additional_rate_limits"] as? [[String: Any]] { - for item in addLimits { - if let rl = item["rate_limit"] as? [String: Any] { - if let pw = rl["primary_window"] as? [String: Any] { - let pct = (pw["used_percent"] as? Double) ?? 0.0 - var rDate: Date? = nil - if let rAt = pw["reset_at"] as? Double { rDate = Date(timeIntervalSince1970: rAt) } - session5hWindow = UsageWindowItem( - id: "codex:session:5h", - label: "Session (5h)", - usedPercent: pct, - resetsAt: rDate, - detail: String(format: "%.0f%% used", pct), - isExhausted: pct >= 100.0 - ) - break - } + if let secondary = rateLimit["secondary_window"] as? [String: Any] { + let item = makeCodexWindow(dict: secondary, limitReached: limitReached, fallbackToWeekly: true) + if item.id == "codex:session:5h" { + session5hWindow = item + } else { + weeklyWindow = item } } } -- 2.51.2