config: add auto-compact settings for Claude and Codex agents
Claude: CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=50 (~500K on 1M context) Codex: model_auto_compact_token_limit=258000 (matching CLI default)
This commit is contained in:
71
src/token-rotation-base.ts
Normal file
71
src/token-rotation-base.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Token Rotation Base Utilities (SSOT)
|
||||
*
|
||||
* Shared algorithms for Claude and Codex token rotation.
|
||||
* Extracted from token-rotation.ts and codex-token-rotation.ts
|
||||
* to eliminate duplicate implementations.
|
||||
*/
|
||||
|
||||
export const BUFFER_MS = 3 * 60_000; // 3 min buffer after reset time
|
||||
export const DEFAULT_COOLDOWN_MS = 3_600_000; // 1 hour fallback
|
||||
|
||||
/**
|
||||
* Parse "try again at Mar 26th, 2026 9:00 AM" or "resets at ..." from
|
||||
* an error message. Returns timestamp in ms, or null if not found.
|
||||
*
|
||||
* Uses the wider regex from token-rotation.ts that also matches
|
||||
* "resets at" patterns (codex-token-rotation only matched "try again at").
|
||||
*/
|
||||
export function parseRetryAfterFromError(error?: string): number | null {
|
||||
if (!error) return null;
|
||||
const match = error.match(
|
||||
/(?:try again at|resets?\s+(?:at\s+)?)\s*(\w+ \d{1,2}(?:st|nd|rd|th)?,?\s+\d{4}\s+\d{1,2}:\d{2}\s*(?:AM|PM)?)/i,
|
||||
);
|
||||
if (!match) return null;
|
||||
try {
|
||||
const cleaned = match[1].replace(/(\d+)(?:st|nd|rd|th)/i, '$1');
|
||||
const ts = new Date(cleaned).getTime();
|
||||
if (Number.isNaN(ts)) return null;
|
||||
return ts;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute when a rate-limited token should become available again.
|
||||
* Parses retry-after from error message, falling back to DEFAULT_COOLDOWN_MS.
|
||||
*/
|
||||
export function computeCooldownUntil(error?: string): number {
|
||||
const retryAt = parseRetryAfterFromError(error);
|
||||
if (retryAt) return retryAt + BUFFER_MS;
|
||||
return Date.now() + DEFAULT_COOLDOWN_MS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the next available (non-rate-limited) item in a rotation pool.
|
||||
* Returns the index, or null if all are exhausted.
|
||||
*
|
||||
* This is the shared rotation algorithm used by both Claude token rotation
|
||||
* and Codex account rotation.
|
||||
*/
|
||||
export function findNextAvailable<
|
||||
T extends { rateLimitedUntil: number | null },
|
||||
>(
|
||||
items: T[],
|
||||
currentIndex: number,
|
||||
opts?: { ignoreRateLimits?: boolean },
|
||||
): number | null {
|
||||
const now = Date.now();
|
||||
const ignoreRL = opts?.ignoreRateLimits ?? false;
|
||||
|
||||
for (let i = 1; i < items.length; i++) {
|
||||
const idx = (currentIndex + i) % items.length;
|
||||
const item = items[idx];
|
||||
if (ignoreRL || !item.rateLimitedUntil || item.rateLimitedUntil <= now) {
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user