-
Notifications
You must be signed in to change notification settings - Fork 56
fix(forecast,runtime): review fixes for #670 and #671 — keep the default forecast on codex, harden the pinned-503 reset #672
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4a43761
fec9988
75d3fc9
199cda5
5b76c68
c112ddc
2a03c2b
2047d9e
63c83bc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,7 @@ import { | |
| isQuotaCacheEntryExhausted, | ||
| quotaUsedPercentIsExhausted, | ||
| } from "./quota-readiness.js"; | ||
| import type { ModelFamily } from "./request/helpers/model-map.js"; | ||
| import { getRateLimitResetTimeForFamily } from "./runtime/account-status.js"; | ||
| import type { AccountMetadataV3 } from "./storage.js"; | ||
| import type { TokenFailure } from "./types.js"; | ||
|
|
@@ -27,6 +28,12 @@ export interface ForecastAccountInput { | |
| quotaCache?: QuotaCacheData | null; | ||
| allAccounts?: readonly AccountMetadataV3[]; | ||
| runtimeOverlay?: RuntimeForecastOverlay | null; | ||
| /** | ||
| * Prompt family whose per-family rate-limit records gate this forecast. | ||
| * Callers with a model in hand resolve it via getModelProfile; the codex | ||
| * default preserves the historical behavior for model-less surfaces. | ||
| */ | ||
| family?: ModelFamily; | ||
| } | ||
|
|
||
| export interface RuntimeForecastOverlay { | ||
|
|
@@ -245,7 +252,7 @@ export function evaluateForecastAccount( | |
| const rateLimitResetAt = getRateLimitResetTimeForFamily( | ||
| account, | ||
| now, | ||
| "codex", | ||
| input.family ?? "codex", | ||
| ); | ||
|
Comment on lines
252
to
256
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When an explicit model has a sibling model’s rate-limit record or overlapping family and exact-model records, this family-wide helper scans every sibling key and selects the earliest reset, while runtime selection checks only the family and exact model keys until the latest gate expires. This makes Knowledge Base Used: Quota, Usage, and Budget Tracking Prompt To Fix With AIThis is a comment left during a code review.
Path: lib/forecast.ts
Line: 252-256
Comment:
**model-specific forecast gating is broken**
When an explicit model has a sibling model’s rate-limit record or overlapping family and exact-model records, this family-wide helper scans every sibling key and selects the earliest reset, while runtime selection checks only the family and exact model keys until the latest gate expires. This makes `forecast`, `best`, and `report` report incorrect availability or wait times, and `best` can recommend the wrong account.
**Knowledge Base Used:** [Quota, Usage, and Budget Tracking](https://app.greptile.com/zeian/-/custom-context/knowledge-base/ndycode/codex-multi-auth/-/docs/quota-usage.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly. |
||
| if (typeof rateLimitResetAt === "number") { | ||
| const remaining = Math.max(0, rateLimitResetAt - now); | ||
|
|
@@ -298,7 +305,10 @@ export function evaluateForecastAccount( | |
| // drop the overlay reason when the condition it describes is no longer | ||
| // active. Each reason validates only against its own backing disk state | ||
| // ("rate-limited" -> rateLimitResetTimes, "cooling-down" -> coolingDownUntil) | ||
| // so we never substitute a misleading reason string. Non-time-bounded | ||
| // so we never substitute a misleading reason string. The rate-limited | ||
| // cross-check is family-aware through rateLimitResetAt above: a record for | ||
| // the forecast's own family keeps the reason, while a record for another | ||
| // family neither sustains it nor gates this model's availability. Non-time-bounded | ||
| // reasons ("circuit-open", "token-exhausted", "policy-blocked") have no disk | ||
| // expiry to check and are always applied. | ||
| const coolingDownActive = | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
use the canonical forced-pin environment variable.
docs/reference/error-contracts.md:123anddocs/reference/error-contracts.md:132advertiseCODEX_MULTI_AUTH_FORCE_ACCOUNT_INDEX, butdocs/reference/error-contracts.md:19and the documented contract useCODEX_MULTI_AUTH_FORCE_ACCOUNT. Use the canonical name, or document both names only if both are supported.proposed fix
As per coding guidelines, “A forced account selected with
--accountorCODEX_MULTI_AUTH_FORCE_ACCOUNTmust be ephemeral.” As per path instructions, keep documentation consistent with actual CLI flags and workflows.🤖 Prompt for AI Agents
Sources: Coding guidelines, Path instructions