Commit Graph

16 Commits

Author SHA1 Message Date
Eyejoker
58ed721d6e feat: auto-recreate reviewer containers on token rotation
When OAuth tokens rotate or refresh, all reviewer containers are
automatically removed. The next reviewer turn recreates them with
the latest token, preventing 401 auth failures.

Uses callback pattern to avoid circular dependencies:
- token-rotation.ts: onTokenRotated(cb)
- token-refresh.ts: onTokenRefreshed(cb)
- index.ts: registers recreateAllReviewerContainers as callback
2026-03-30 21:51:45 +09:00
Eyejoker
ba9f6871b6 feat: add codex review failover and suppress output hardening 2026-03-28 05:40:38 +09:00
Eyejoker
18788f7f91 chore: add state transition logging 2026-03-25 12:16:09 +09:00
Eyejoker
b6d3f879ef refactor: add recovery mode + shared JSON/error/fetch utilities
- GroupQueue recovery mode: limit to 3 concurrent agents for 60s after restart
  to prevent API rate-limit storms (configurable via env vars)
- getErrorMessage: replace 14 occurrences of instanceof Error pattern
- readJsonFile/writeJsonFile: replace 19 occurrences of JSON+fs pattern
- fetchWithTimeout: replace 3 occurrences of AbortController pattern

354/354 tests passing
2026-03-25 07:08:49 +09:00
Eyejoker
5ea3439c5f refactor: extract shared utilities, protocol constants, and retry loop
Phase 3: provider-retry.ts — shared Claude rotation loop (SSOT)
  - retryClaudeWithRotation extracted from message-agent-executor + task-scheduler
  - ~200 lines of duplicated retry logic removed

Phase 4: types.ts — AgentOutputPhase + VisiblePhase unified
Phase 5: types.ts — AgentConfig extended with claudeThinking/claudeThinkingBudget

Utilities (utils.ts):
  - getErrorMessage: 14 occurrences of instanceof Error pattern → 1 function
  - readJsonFile/writeJsonFile: 19 occurrences of JSON+fs pattern → 2 functions
  - fetchWithTimeout: 3 occurrences of AbortController pattern → 1 function
  - formatElapsedKorean: deduplicated from task-watch-status + message-turn-controller

Protocol (agent-protocol.ts):
  - OUTPUT_START/END_MARKER centralized (runners keep local copies with SSOT reference)
  - IMAGE_TAG_RE, IPC constants documented

Runner: show "대화 요약 중..." progress message during auto-compact

Net: -137 lines, 354/354 tests passing
2026-03-25 04:59:49 +09:00
Eyejoker
80490ab162 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
2026-03-25 03:56:22 +09:00
Eyejoker
906a3dfadb 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)
2026-03-25 03:56:03 +09:00
Eyejoker
55d865586d style: prettier formatting 2026-03-24 15:35:46 +09:00
Eyejoker
f4b02af4dd feat: restore OAuth token auto-refresh with multi-account support
Restores token-refresh.ts that was deleted in 35356dd. Now works
with multi-account token rotation:
- Refreshes tokens from ~/.claude/.credentials.json (account 0)
  and ~/.claude-accounts/{n}/.credentials.json (account 1+)
- Updates token-rotation memory and .env on refresh
- Syncs credentials to session directories
- 5-min check interval, refreshes 30 min before expiry
- forceRefreshToken() export for 401 recovery
2026-03-24 15:35:37 +09:00
Eyejoker
f6ba879e8a fix: usage API rate-limit guard and cleanup debug logging 2026-03-24 03:47:46 +09:00
Eyejoker
120f16e9e1 fix: Claude token rotation, usage-exhausted fallback, and usage API caching
- Fix token rotation not taking effect: getCurrentToken() was shadowed
  by static .env CLAUDE_CODE_OAUTH_TOKEN value in agent environment
- Don't fall back to Kimi on usage-exhausted (only on transient 429/network)
- Add disk cache for Claude usage API data (survives restarts, 429s)
- Rate-limit usage API calls to 1 per token per 5 minutes
- Add ignoreRateLimits option to rotateToken() for exhausted recovery
- Rotate to next token in getActiveProvider() when current is exhausted
- Add isUsageExhausted() helper to provider-fallback
2026-03-24 03:40:51 +09:00
Eyejoker
60dab43a3f feat: parse retry-after from errors, cache codex usage per account
- Parse "try again at" time from rate-limit errors instead of
  fixed 1-hour cooldown, with 3-min buffer after reset
- Pass error message to rotateToken/rotateCodexToken for parsing
- Cache usage % and reset time per Codex account for dashboard
- Persist cached usage in rotation state file across restarts
- Show rate-limited Codex accounts with cached 100% + reset time
- Fix dashboard text indicators (*!/space) for monospace alignment
2026-03-24 01:16:54 +09:00
Eyejoker
7401626356 feat: persist rotation state across restarts, fix dashboard alignment
- Save currentIndex + rateLimits to JSON file in DATA_DIR
- Restore on startup so rotation survives service restarts
- Replace emoji indicators with text (*/!) for monospace alignment
- Dynamic column width based on longest name
- Show Codex accounts with plan type on dashboard
2026-03-23 23:16:54 +09:00
Eyejoker
0b86f937f4 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
2026-03-23 22:41:07 +09:00
Eyejoker
83b25fb7bd feat: Claude usage API + multi-account dashboard display
- Replace expect/CLI hack with direct HTTP API call
  (GET api.anthropic.com/api/oauth/usage with OAuth token)
- Add fetchAllClaudeUsage() for per-token usage fetching
- Export getAllTokens() from token-rotation for usage queries
- Dashboard shows each account separately (Claude1, Claude2)
  with  for active token, 🚫 for rate-limited
2026-03-23 22:15:06 +09:00
Eyejoker
d378598f2e feat: Claude OAuth token rotation on rate-limit
- New token-rotation module: stores multiple tokens from
  CLAUDE_CODE_OAUTH_TOKENS env var (comma-separated)
- On rate-limit, rotates to next healthy token before falling
  back to Kimi provider
- Also fixes: intermediate text routes to progress message
  when no subagents active (prevents message flooding)
2026-03-23 22:01:06 +09:00