From 80490ab162cf830ca0c7caeb3f1614e4049b0b72 Mon Sep 17 00:00:00 2001 From: Eyejoker Date: Wed, 25 Mar 2026 03:56:22 +0900 Subject: [PATCH] refactor: extract shared error detection and token rotation utilities (SSOT) - Create agent-error-detection.ts: single source for error classification (isClaudeUsageExhaustedMessage, isClaudeAuthExpiredMessage, classifyAgentError, etc.) - Create token-rotation-base.ts: shared rotation algorithm (parseRetryAfterFromError, computeCooldownUntil, findNextAvailable) - Remove 6 duplicated functions from message-agent-executor and task-scheduler - Delegate detectFallbackTrigger/detectCodexRotationTrigger to shared classifiers - Split canFallback into isClaudeAgent/canRotateToken/canFallback (3-way separation) - Cache env.ts with getEnv() to eliminate repeated disk I/O - Migrate config, discord, provider-fallback, token-rotation, memento-client to getEnv() Net: -146 lines, 0 new dependencies, 354/354 tests passing --- src/codex-token-rotation.ts | 1 - src/config.ts | 3 +-- src/provider-fallback.ts | 5 +---- src/task-scheduler.ts | 1 - src/token-rotation.ts | 1 - 5 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/codex-token-rotation.ts b/src/codex-token-rotation.ts index dec08d3..48ced65 100644 --- a/src/codex-token-rotation.ts +++ b/src/codex-token-rotation.ts @@ -204,7 +204,6 @@ function loadCodexState(): void { } } - /** Get the auth.json path for the current active account. */ export function getActiveCodexAuthPath(): string | null { if (accounts.length === 0) return null; diff --git a/src/config.ts b/src/config.ts index 39a95a6..83cc7fb 100644 --- a/src/config.ts +++ b/src/config.ts @@ -70,8 +70,7 @@ export const STATUS_UPDATE_INTERVAL = 10000; // 10s export const USAGE_UPDATE_INTERVAL = 300000; // 5 minutes export const STATUS_SHOW_ROOMS = (getEnv('STATUS_SHOW_ROOMS') || 'true') !== 'false'; -export const USAGE_DASHBOARD_ENABLED = - getEnv('USAGE_DASHBOARD') === 'true'; +export const USAGE_DASHBOARD_ENABLED = getEnv('USAGE_DASHBOARD') === 'true'; // Timezone for scheduled tasks (cron expressions, etc.) // Uses system timezone by default diff --git a/src/provider-fallback.ts b/src/provider-fallback.ts index d7211c4..0505256 100644 --- a/src/provider-fallback.ts +++ b/src/provider-fallback.ts @@ -82,10 +82,7 @@ function loadConfig(): FallbackConfig { authToken, model, smallModel: getEnv('FALLBACK_SMALL_MODEL') || model, - defaultCooldownMs: parseInt( - getEnv('FALLBACK_COOLDOWN_MS') || '600000', - 10, - ), + defaultCooldownMs: parseInt(getEnv('FALLBACK_COOLDOWN_MS') || '600000', 10), }; if (_config.enabled) { diff --git a/src/task-scheduler.ts b/src/task-scheduler.ts index 40fe184..5d84d61 100644 --- a/src/task-scheduler.ts +++ b/src/task-scheduler.ts @@ -78,7 +78,6 @@ export { shouldUseTaskScopedSession, } from './task-watch-status.js'; - /** * Compute the next run time for a recurring task, anchored to the * task's scheduled time rather than Date.now() to prevent cumulative diff --git a/src/token-rotation.ts b/src/token-rotation.ts index af2937e..6c23418 100644 --- a/src/token-rotation.ts +++ b/src/token-rotation.ts @@ -105,7 +105,6 @@ function loadState(): void { } } - /** Get the current active token. */ export function getCurrentToken(): string | undefined { if (tokens.length === 0) return process.env.CLAUDE_CODE_OAUTH_TOKEN;