Skip to content

fix: 修正 Codex free 账号用量显示到每周窗口 - #3316

Merged
seefs001 merged 1 commit into
QuantumNous:mainfrom
Honghurumeng:main
Mar 18, 2026
Merged

fix: 修正 Codex free 账号用量显示到每周窗口#3316
seefs001 merged 1 commit into
QuantumNous:mainfrom
Honghurumeng:main

Conversation

@Honghurumeng

@Honghurumeng Honghurumeng commented Mar 18, 2026

Copy link
Copy Markdown
Contributor

Summary

  • 修正 Codex 渠道 free 账号的额度窗口展示逻辑
  • 当上游返回 "plan_type": "free" 时,将实际用量展示到“每周窗口”而不是“5小时窗口”
  • 5小时窗口改为空态展示,避免误导性地显示 0%
image

Background

Codex 渠道用量弹窗当前固定将 rate_limit.primary_window 渲染为“5小时窗口”,将 rate_limit.secondary_window 渲染为“每周窗口”。

但在 free 账号场景下,上游返回中会包含 "plan_type": "free",此类账号没有 5 小时窗口,只有每周窗口。由于前端没有根据 plan_type或窗口时长做实际归类,导致真实的周用量被错误展示在左侧“5小时窗口”中,右侧“每周窗口”反而为空或显示不正确。

本 PR 修正该展示层问题,使 free 账号的额度信息能够正确落到每周窗口中,同时保留对非 free 场景的兼容。

Changes

web/src/components/table/channels/modals/CodexUsageModal.jsx

新增额度窗口归类逻辑:

  • 增加 plan_type 归一化处理
  • 增加基于 limit_window_seconds 的窗口识别逻辑
  • 优先根据窗口时长识别“5小时窗口”与“每周窗口”
  • plan_type === 'free' 时,强制将有效窗口映射到“每周窗口”,不再错误显示到“5小时窗口”

调整窗口卡片展示逻辑:

  • 当窗口数据不存在时,显示空态 -
  • 不再对空窗口渲染误导性的进度条和 0%
  • 保持原有进度条、重置时间、距离重置、窗口时长等展示方式不变

Testing

  • 本地执行前端构建,确认改动可正常编译
  • 本地启动服务并手动验证 Codex 用量弹窗展示
  • 验证 plan_type: free 场景下,用量显示在“每周窗口”
  • 验证无有效 5 小时窗口时,左侧卡片显示为空态

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Rate limit window displays now gracefully handle missing data scenarios with placeholder indicators.
    • Improved rendering logic to ensure consistent display of usage metrics across different plan configurations.

@coderabbitai

coderabbitai Bot commented Mar 18, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

This change enhances rate limit window resolution logic in the CodexUsageModal component by introducing new helper functions to derive normalized window data from rate_limit and plan_type, while improving null-safety in UI rendering when data is unavailable.

Changes

Cohort / File(s) Summary
Rate Limit Window Resolution & UI Rendering
web/src/components/table/channels/modals/CodexUsageModal.jsx
Added window-rate resolution helpers (normalizePlanType, getWindowDurationSeconds, classifyWindowByDuration, resolveRateLimitWindows) to transform raw rate_limit data into structured fiveHourWindow and weeklyWindow objects. Updated CodexUsageView to consume resolved windows instead of primary/secondary. Enhanced RateLimitWindowCard with null-safety checks, conditional rendering of progress/duration info, and placeholder display when windowData is absent.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~35 minutes

Suggested reviewers

  • seefs001

Poem

🐰 Hop, hop! The windows align,
Five hours and weeks, now divine,
When data runs thin, a dash appears kind,
No crashes or crashes—just peace of mind!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: fixing Codex free account usage display to show in the weekly window instead of the 5-hour window, which matches the core objective of the pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can customize the high-level summary generated by CodeRabbit.

Configure the reviews.high_level_summary_instructions setting to provide custom instructions for generating the high-level summary.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
web/src/components/table/channels/modals/CodexUsageModal.jsx (1)

57-60: Match the actual 5h / 7d durations instead of using a 24h split.

Line 60 currently labels every window < 24h as “5小时窗口” and every window >= 24h as “每周窗口”. A 6-hour or 24-hour upstream window would be shown under the wrong card title. Prefer matching the known 5-hour / 7-day values, then leaving unknown durations unmapped.

♻️ Proposed change
+const FIVE_HOUR_WINDOW_SECONDS = 5 * 60 * 60;
+const WEEKLY_WINDOW_SECONDS = 7 * 24 * 60 * 60;
+const WINDOW_TOLERANCE_SECONDS = 60;
+
 const classifyWindowByDuration = (windowData) => {
   const seconds = getWindowDurationSeconds(windowData);
   if (seconds == null) return null;
-  return seconds >= 24 * 60 * 60 ? 'weekly' : 'fiveHour';
+  if (
+    Math.abs(seconds - FIVE_HOUR_WINDOW_SECONDS) <= WINDOW_TOLERANCE_SECONDS
+  ) {
+    return 'fiveHour';
+  }
+  if (
+    Math.abs(seconds - WEEKLY_WINDOW_SECONDS) <= WINDOW_TOLERANCE_SECONDS
+  ) {
+    return 'weekly';
+  }
+  return null;
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/components/table/channels/modals/CodexUsageModal.jsx` around lines 57
- 60, The classifyWindowByDuration function incorrectly splits at 24h; change it
to map only the known durations by reading seconds from
getWindowDurationSeconds(windowData) and returning 'fiveHour' when seconds
equals 5 * 3600 and 'weekly' when seconds equals 7 * 24 * 3600, otherwise return
null so unknown window lengths (e.g., 6h or 24h) remain unmapped; update the
comparisons in classifyWindowByDuration accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@web/src/components/table/channels/modals/CodexUsageModal.jsx`:
- Around line 133-136: The current hasWindowData check only verifies keys exist
and will treat placeholder objects (e.g., { used_percent: null, reset_at: null
}) as populated; update the logic used by hasWindowData (or create a helper like
isMeaningfulWindowData) to ensure the object contains actual meaningful values
before rendering the usage card—for example require used_percent to be a finite
number (or other concrete fields you rely on) and/or non-null reset_at; then use
that stricter predicate wherever hasWindowData is referenced (including the
rendering block around the card currently at the render for lines ~152-175) so
placeholder objects are treated as empty.

---

Nitpick comments:
In `@web/src/components/table/channels/modals/CodexUsageModal.jsx`:
- Around line 57-60: The classifyWindowByDuration function incorrectly splits at
24h; change it to map only the known durations by reading seconds from
getWindowDurationSeconds(windowData) and returning 'fiveHour' when seconds
equals 5 * 3600 and 'weekly' when seconds equals 7 * 24 * 3600, otherwise return
null so unknown window lengths (e.g., 6h or 24h) remain unmapped; update the
comparisons in classifyWindowByDuration accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7b140fdf-cbaf-4bc7-9d9e-409745253591

📥 Commits

Reviewing files that changed from the base of the PR and between a1a92c1 and 5bb8fe6.

📒 Files selected for processing (1)
  • web/src/components/table/channels/modals/CodexUsageModal.jsx

Comment on lines +133 to +136
const hasWindowData =
!!windowData &&
typeof windowData === 'object' &&
Object.keys(windowData).length > 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Treat placeholder objects as empty windows.

hasWindowData only checks whether the object has keys. If the API returns a placeholder like { used_percent: null, reset_at: null, ... }, Lines 152-175 still render a populated card with a 0% bar, which is the empty-state regression this PR is trying to avoid.

💡 Proposed fix
-  const hasWindowData =
-    !!windowData &&
-    typeof windowData === 'object' &&
-    Object.keys(windowData).length > 0;
+  const hasWindowData =
+    !!windowData &&
+    typeof windowData === 'object' &&
+    [
+      windowData?.used_percent,
+      windowData?.reset_at,
+      windowData?.reset_after_seconds,
+      getWindowDurationSeconds(windowData),
+    ].some((value) => value != null);

Also applies to: 152-175

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/components/table/channels/modals/CodexUsageModal.jsx` around lines
133 - 136, The current hasWindowData check only verifies keys exist and will
treat placeholder objects (e.g., { used_percent: null, reset_at: null }) as
populated; update the logic used by hasWindowData (or create a helper like
isMeaningfulWindowData) to ensure the object contains actual meaningful values
before rendering the usage card—for example require used_percent to be a finite
number (or other concrete fields you rely on) and/or non-null reset_at; then use
that stricter predicate wherever hasWindowData is referenced (including the
rendering block around the card currently at the render for lines ~152-175) so
placeholder objects are treated as empty.

@seefs001
seefs001 merged commit ede0ad1 into QuantumNous:main Mar 18, 2026
1 check passed
@coderabbitai coderabbitai Bot mentioned this pull request Mar 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants