Skip to content

feat(combos): add reset-aware routing strategy#2015

Closed
JxnLexn wants to merge 1 commit into
diegosouzapw:mainfrom
JxnLexn:feat/reset-aware-routing
Closed

feat(combos): add reset-aware routing strategy#2015
JxnLexn wants to merge 1 commit into
diegosouzapw:mainfrom
JxnLexn:feat/reset-aware-routing

Conversation

@JxnLexn
Copy link
Copy Markdown
Contributor

@JxnLexn JxnLexn commented May 6, 2026

Summary

  • Adds a new reset-aware Combo routing strategy for Codex account pools.
  • The strategy scores accounts using remaining 5h/session quota, remaining weekly quota, reset timing, configurable weights, and a 5h exhaustion guard.
  • Similar scores rotate with round-robin tie-breaking so equivalent accounts are used fairly.
  • Adds UI/i18n labels and guidance for the new strategy.

Related Issues

  • Closes: N/A
  • Related to: N/A

Validation

  • npm run lint
  • npm run test:unit
  • npm run test:coverage
  • Coverage is still >= 60% for statements, lines, functions, and branches
  • SonarQube PR analysis is green or any remaining issues are explicitly documented below

SonarQube PR analysis was not run locally.

Tests Added Or Updated

  • Updated combo-strategies.test.ts
    • Adds coverage for preferring an account with lower weekly remaining quota when its reset is much sooner.
    • Adds coverage for avoiding accounts near 5h/session exhaustion.
    • Adds coverage for round-robin tie-breaking between equivalent reset-aware scores.

Coverage Notes

  • This PR changes production code in open-sse and src.
  • The new routing behavior is covered by combo-strategies.test.ts.
  • Final coverage gate passed:
    • Statements: 82.78%
    • Branches: 75.13%
    • Functions: 85.28%
    • Lines: 82.78%
  • No coverage recovery follow-up is required.

Reviewer Notes

  • No database migration is required; the new strategy and config values are stored through existing Combo JSON config.
  • New optional config fields:
    • resetAwareSessionWeight
    • resetAwareWeeklyWeight
    • resetAwareTieBandPercent
    • resetAwareExhaustionGuardPercent
  • Codex quota fetch failures degrade gracefully instead of blocking routing.
  • The strategy is primarily useful for Codex accounts with live 5h and weekly quota telemetry; mixed-provider Combos fall back safely when quota data is unavailable.
  • Local push issues were caused by stale hook/test processes and Node ABI mismatch; validation was completed with Node v22.22.2.

@JxnLexn JxnLexn requested a review from diegosouzapw as a code owner May 6, 2026 20:05
@JxnLexn JxnLexn closed this May 6, 2026
@JxnLexn
Copy link
Copy Markdown
Contributor Author

JxnLexn commented May 6, 2026

still need to test some stuff, i'll reopen once tests are finished

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ffde066951

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +817 to +819
if (config.exhaustionGuard > 0 && sessionRemaining < config.exhaustionGuard) {
score *= Math.max(0.05, sessionRemaining / config.exhaustionGuard);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Deprioritize weekly-exhausted Codex accounts

When a Codex account is at or above the weekly quota preflight threshold but its weekly reset is soon, this score can still rank it ahead of a usable account because the exhaustion guard only applies to sessionRemaining. In that scenario getProviderCredentialsWithQuotaPreflight will reject the forced connection as quota-exhausted and the combo then falls back on every request, adding avoidable latency/noisy failures even though the reset-aware sorter already had the weekly window data needed to skip or heavily penalize it.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new 'reset-aware' routing strategy for model combos, specifically designed to optimize Codex account usage by balancing remaining quota against 5h and weekly reset windows. The implementation includes scoring logic, UI configuration options, and unit tests. Feedback focuses on performance and reliability improvements, specifically suggesting the use of concurrency for connection fetching, implementing limits on simultaneous quota requests to avoid network bursts, and addressing potential clock drift issues in reset urgency calculations.

const connectionById = new Map<string, Record<string, unknown>>();
const expandedTargets: ResolvedComboTarget[] = [];

for (const target of targets) {
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.

medium

The loop iterates through targets and performs sequential await on getCodexConnectionsForTarget. While there is a local connectionCache, the initial calls for each unique provider will be sequential. Consider using Promise.all to fetch connections for all targets concurrently to improve performance, especially for combos with multiple providers.

Comment on lines +898 to +917
const scoredTargets = await Promise.all(
expandedTargets.map(async (target, index) => {
let quota: unknown = null;
if (isCodexTarget(target) && target.connectionId) {
try {
quota = await fetchCodexQuota(
target.connectionId,
connectionById.get(target.connectionId)
);
} catch (error) {
log.warn?.(
"COMBO",
`Reset-aware quota fetch failed for connection=${target.connectionId}: ${error instanceof Error ? error.message : String(error)}`
);
}
}
const { score } = scoreResetAwareQuota(quota, config);
return { target, score, index };
})
);
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.

medium

Using Promise.all to fetch quotas for all expandedTargets concurrently is efficient, but it could lead to a burst of network requests if a combo contains a large number of Codex accounts. Since fetchCodexQuota has a 60s cache, this is mostly an issue on the first request or after cache expiration. If the number of accounts is expected to be very high, consider implementing a concurrency limit for these background fetches.

Comment on lines +776 to +783
function getResetUrgency(resetAt: string | null | undefined, windowMs: number): number {
if (!resetAt) return 0.5;
const resetTime = new Date(resetAt).getTime();
if (!Number.isFinite(resetTime)) return 0.5;
const msUntilReset = resetTime - Date.now();
if (msUntilReset <= 0) return 1;
return clamp01(1 - msUntilReset / windowMs);
}
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.

medium

The getResetUrgency function relies on Date.now(), which uses the system clock. If the server's system time is significantly out of sync with the Codex provider's clock, the urgency calculation (and thus the routing) may be inaccurate. While codexQuotaFetcher.ts attempts to normalize resetAt using Date.now() when reset_after_seconds is provided, a direct comparison with system time is still a potential point of drift.

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.

1 participant