From 0b86f937f4265c090abe0e7ef2e3f68a46e487c3 Mon Sep 17 00:00:00 2001 From: Eyejoker Date: Mon, 23 Mar 2026 22:41:07 +0900 Subject: [PATCH] fix: read tokens from .env file, clean up debug logs - token-rotation reads from readEnvFile() (systemd doesn't load .env) - fetchAllClaudeUsage polling log demoted to debug level - Remove verbose dashboard send/create logs --- src/claude-usage.test.ts | 5 ++++- src/claude-usage.ts | 32 ++++++++++++++++---------------- src/token-rotation.ts | 21 ++++++++++++++++++--- src/unified-dashboard.ts | 30 ++++++++++++++++++++++++------ 4 files changed, 62 insertions(+), 26 deletions(-) diff --git a/src/claude-usage.test.ts b/src/claude-usage.test.ts index ce661c7..884a7bb 100644 --- a/src/claude-usage.test.ts +++ b/src/claude-usage.test.ts @@ -7,7 +7,10 @@ describe('ClaudeUsageData', () => { const data: ClaudeUsageData = { five_hour: { utilization: 45.2, resets_at: '2026-03-23T17:00:00Z' }, seven_day: { utilization: 72.1, resets_at: '2026-03-29T00:00:00Z' }, - seven_day_sonnet: { utilization: 60.0, resets_at: '2026-03-29T00:00:00Z' }, + seven_day_sonnet: { + utilization: 60.0, + resets_at: '2026-03-29T00:00:00Z', + }, seven_day_opus: { utilization: 80.0, resets_at: '2026-03-29T00:00:00Z' }, }; diff --git a/src/claude-usage.ts b/src/claude-usage.ts index b286eae..4c863e1 100644 --- a/src/claude-usage.ts +++ b/src/claude-usage.ts @@ -25,9 +25,10 @@ interface UsageApiResponse { seven_day_opus?: { utilization: number; resets_at?: string }; } -function mapWindow( - w?: { utilization: number; resets_at?: string }, -): { utilization: number; resets_at: string } | undefined { +function mapWindow(w?: { + utilization: number; + resets_at?: string; +}): { utilization: number; resets_at: string } | undefined { if (!w) return undefined; return { utilization: w.utilization, resets_at: w.resets_at || '' }; } @@ -77,10 +78,7 @@ async function fetchUsageForToken( if ((err as Error).name === 'AbortError') { logger.warn('Claude usage API: request timed out'); } else { - logger.warn( - { err }, - 'Claude usage API: fetch failed', - ); + logger.warn({ err }, 'Claude usage API: fetch failed'); } return null; } finally { @@ -93,8 +91,7 @@ async function fetchUsageForToken( * Uses the current active token from rotation. */ export async function fetchClaudeUsage(): Promise { - const token = - getCurrentToken() || process.env.CLAUDE_CODE_OAUTH_TOKEN; + const token = getCurrentToken() || process.env.CLAUDE_CODE_OAUTH_TOKEN; if (!token) { logger.debug('No Claude OAuth token available for usage check'); return null; @@ -116,18 +113,21 @@ export interface ClaudeAccountUsage { */ export async function fetchAllClaudeUsage(): Promise { const allTokens = getAllTokens(); + logger.debug({ tokenCount: allTokens.length }, 'fetchAllClaudeUsage called'); if (allTokens.length === 0) { // Single token fallback const token = process.env.CLAUDE_CODE_OAUTH_TOKEN; if (!token) return []; const usage = await fetchUsageForToken(token); - return [{ - index: 0, - masked: `${token.slice(0, 20)}...${token.slice(-4)}`, - isActive: true, - isRateLimited: false, - usage, - }]; + return [ + { + index: 0, + masked: `${token.slice(0, 20)}...${token.slice(-4)}`, + isActive: true, + isRateLimited: false, + usage, + }, + ]; } const results: ClaudeAccountUsage[] = []; diff --git a/src/token-rotation.ts b/src/token-rotation.ts index 997a970..9874732 100644 --- a/src/token-rotation.ts +++ b/src/token-rotation.ts @@ -10,6 +10,7 @@ * All exhausted: fall through to provider fallback (Kimi etc.) */ +import { readEnvFile } from './env.js'; import { logger } from './logger.js'; interface TokenState { @@ -25,8 +26,16 @@ export function initTokenRotation(): void { if (initialized) return; initialized = true; - const multi = process.env.CLAUDE_CODE_OAUTH_TOKENS; - const single = process.env.CLAUDE_CODE_OAUTH_TOKEN; + const envFile = readEnvFile([ + 'CLAUDE_CODE_OAUTH_TOKENS', + 'CLAUDE_CODE_OAUTH_TOKEN', + ]); + const multi = + process.env.CLAUDE_CODE_OAUTH_TOKENS || + envFile.CLAUDE_CODE_OAUTH_TOKENS; + const single = + process.env.CLAUDE_CODE_OAUTH_TOKEN || + envFile.CLAUDE_CODE_OAUTH_TOKEN; const raw = multi ? multi @@ -103,7 +112,13 @@ export function getTokenCount(): number { } /** Get all configured tokens (masked for display, raw for API calls). */ -export function getAllTokens(): { index: number; token: string; masked: string; isActive: boolean; isRateLimited: boolean }[] { +export function getAllTokens(): { + index: number; + token: string; + masked: string; + isActive: boolean; + isRateLimited: boolean; +}[] { const now = Date.now(); return tokens.map((t, i) => ({ index: i, diff --git a/src/unified-dashboard.ts b/src/unified-dashboard.ts index 0fbf0bd..3d83766 100644 --- a/src/unified-dashboard.ts +++ b/src/unified-dashboard.ts @@ -551,17 +551,31 @@ async function buildUsageContent(): Promise { }; const rows: UsageRow[] = []; - const claudeAccounts = liveClaudeAccounts - || (cachedClaudeUsageData ? [{ index: 0, masked: '', isActive: true, isRateLimited: false, usage: cachedClaudeUsageData }] : []); + const claudeAccounts = + liveClaudeAccounts || + (cachedClaudeUsageData + ? [ + { + index: 0, + masked: '', + isActive: true, + isRateLimited: false, + usage: cachedClaudeUsageData, + }, + ] + : []); for (const account of claudeAccounts) { const u = account.usage; if (!u) continue; const h5 = u.five_hour; const d7 = u.seven_day; - const label = claudeAccounts.length > 1 - ? `Claude${account.index + 1}${account.isActive ? '⚡' : ''}${account.isRateLimited ? '🚫' : ''}` - : claudeUsageIsCached ? 'Claude*' : 'Claude'; + const label = + claudeAccounts.length > 1 + ? `Claude${account.index + 1}${account.isActive ? '⚡' : ''}${account.isRateLimited ? '🚫' : ''}` + : claudeUsageIsCached + ? 'Claude*' + : 'Claude'; rows.push({ name: label, h5pct: h5 @@ -717,6 +731,10 @@ export async function startUnifiedDashboard( await refreshChannelMeta(opts); const content = buildUnifiedDashboardContent(); if (!content) { + logger.warn( + { cachedUsageLength: cachedUsageContent.length, statusShowRooms: STATUS_SHOW_ROOMS }, + 'Dashboard content empty, skipping render', + ); statusMessageId = null; return; } @@ -728,7 +746,7 @@ export async function startUnifiedDashboard( if (id) statusMessageId = id; } } catch (err) { - logger.debug({ err }, 'Dashboard update failed'); + logger.warn({ err }, 'Dashboard update failed'); statusMessageId = null; } };