Commit Graph

963 Commits

Author SHA1 Message Date
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
744e2ce6e2 style: format agent rotation updates 2026-03-24 17:09:17 +09:00
Eyejoker
8b2c46b89e fix: harden agent shutdown and auth rotation 2026-03-24 17:08:48 +09:00
Eyejoker
77b4ab1c83 fix: use token suffix for usage cache key (prefix is identical)
All OAuth tokens start with "sk-ant-oat01-" so slice(0,12) produced
the same cache key for every token. Use slice(-8) instead.
2026-03-24 15:45:58 +09:00
Eyejoker
6fc1c77418 fix: suppress 401 auth errors from chat output
401 authentication errors are now filtered from Discord messages
and only logged. Prevents "Failed to authenticate" from reaching users.
2026-03-24 15:42:29 +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
991f2bf2fd test: align fallback expectations after merge 2026-03-24 03:56:07 +09:00
Eyejoker
0724914a43 merge: integrate remote token rotation + memory pipeline
Merge remote main (token rotation, usage API, dashboard fixes)
with local memory pipeline changes. Smart quote encoding fixed.
Test alignment pending.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 03:53:15 +09:00
Eyejoker
5cd424017f style: prettier formatting from pre-commit hook
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 03:49:00 +09:00
Eyejoker
3467e245d5 feat: auto memory pipeline — host-driven Memento recall/reflect
Add automatic memory integration so EJClaw host directly calls Memento
MCP for recall at session start and reflect on compact, removing
reliance on agent voluntary tool use.

Stage 1: New sessions get room memory briefing injected into system
prompt (CLAUDE.md / AGENTS.md) via host-side MCP client.

Stage 2: PreCompact hook automatically calls reflect + remember to
persist session summaries as room-memory fragments.

Also restores missing source files (token-rotation, codex-token-rotation,
claude-usage exports) to fix full build from source.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 03:48:36 +09:00
Eyejoker
f6ba879e8a fix: usage API rate-limit guard and cleanup debug logging 2026-03-24 03:47:46 +09:00
Eyejoker
6a73421d4f fix: use ignoreRateLimits in retryClaudeWithRotation loops
Without this, token rotation was blocked by stale cooldowns even
when the target token had available usage.
2026-03-24 03:47:22 +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
2ab6c25f0e feat: fetch Claude account profiles (plan type) on startup
- Call /api/oauth/profile for each token, cache in memory
- Display plan type (max/pro/free) next to Claude account names
- Profiles fetched once on startup, no periodic refresh needed
2026-03-24 01:41:23 +09:00
Eyejoker
16f4e6ccb9 fix: force dashboard refresh after Codex account scan completes 2026-03-24 01:39:15 +09:00
Eyejoker
ed9123d66c fix: always capture reset times even at 0% usage (>= instead of >) 2026-03-24 01:38:28 +09:00
Eyejoker
c51d80bd07 style: prettier formatting 2026-03-24 01:37:14 +09:00
Eyejoker
92c82c192a fix: fixed-width reset format Xd Yh / Xh Ym for alignment 2026-03-24 01:35:00 +09:00
Eyejoker
9f8b4ae0aa fix: space between h/m in reset format, padStart(7) 2026-03-24 01:33:48 +09:00
Eyejoker
2ffb4d5696 fix: fixed-width English reset format for monospace alignment 2026-03-24 01:32:18 +09:00
Eyejoker
6ac706f9c5 fix: unify reset time format to relative (Xh Ym 후) for all rows 2026-03-24 01:31:10 +09:00
Eyejoker
0375912c2b fix: render reset times in dashboard usage rows 2026-03-24 01:29:32 +09:00
Eyejoker
9e091df6f6 fix: scan all Codex limits for max 5h/7d, persist d7 reset times
- Iterate all rate limits per account instead of just display[0]
- Track and persist 7-day reset time separately (resetD7At)
- Show both 5h and 7d cached usage for inactive Codex accounts
2026-03-24 01:28:48 +09:00
Eyejoker
c7a3a56386 feat: scan all Codex accounts on startup + hourly, cache 5h/7d usage
- Scan all Codex accounts by spawning app-server with each auth dir
- Cache primary (5h) and secondary (7d) usage per account
- Show cached usage + reset remaining time on dashboard
- Persist d7 usage in rotation state file
- formatResetRemaining: "Xh Ym 후" / "N일 후" format
- Remove isRateLimited guard for cached display
2026-03-24 01:25:02 +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
2e6fc4a08e fix: add warn log for usage content build failures 2026-03-23 23:18:47 +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
30be180f4b fix: codex rate-limit retry immediately instead of next request 2026-03-23 23:07:35 +09:00
Eyejoker
816b0a39cc feat: Codex account rotation + fix rate-limit detection
- New codex-token-rotation module: rotates between multiple
  ~/.codex-accounts/{n}/auth.json on rate-limit
- Copies active account auth to session dir before each spawn
- Fix detectFallbackTrigger to match "usage limit" / "hit your limit"
- Fix streamed error detection: remove claude-only guard so codex
  rate-limit errors are caught even when output.status is "success"
- Add rotation in both task-scheduler and message-agent-executor
2026-03-23 23:06:17 +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
Eyejoker
ee65330e66 fix: rollback codex SDK to 0.115.0 (0.116.0 causes stuck turns) 2026-03-23 20:38:30 +09:00
Eyejoker
45a332f6bb docs: update Node requirement to 24+ 2026-03-23 20:30:29 +09:00
Eyejoker
961b8ccf65 docs: add SDK version badges to README 2026-03-23 20:17:52 +09:00
Eyejoker
2161b555ec fix: dedup intermediate/final, filter long descriptions, update SDKs
- Track lastIntermediateText to prevent duplicate Discord delivery
  when same text arrives as both intermediate and final
- Filter task_progress descriptions >80 chars (AI summaries)
- Mark completed subagents with  instead of removing
- Update claude-agent-sdk 0.2.76→0.2.81, codex 0.115→0.116
2026-03-23 20:16:54 +09:00
Eyejoker
21a6be84b4 feat: multi-agent progress tracking with per-subagent display
Track each subagent separately via agentId from SDK task events.
Single subagent shows detailed view with activity sub-lines,
multiple subagents show compact one-line-each format.
2026-03-23 19:46:08 +09:00
Eyejoker
8c98ad9faf fix: intermediate text as standalone messages, preserve progress
Add 'intermediate' phase for assistant text between tool calls.
These are sent as separate Discord messages without finalizing
or disrupting the active progress message.
2026-03-23 19:29:16 +09:00
Eyejoker
720086808a fix: intermediate text as separate messages, not progress heading
Intermediate assistant text (e.g., "서브에이전트 4개 병렬로 띄웠어요")
is now emitted as regular messages (no phase), not progress heading
updates. Progress heading is only set by task_started (🔄) events.
2026-03-23 19:26:20 +09:00
Eyejoker
be9dfa64b0 fix: deduplicate progress at runner level, not host revert
Buffer intermediate assistant text in the runner. When result arrives
with matching text, discard the buffered progress instead of emitting
it. This prevents the duplicate from ever reaching Discord, eliminating
the flash-then-revert behavior.
2026-03-23 19:22:14 +09:00
Eyejoker
83df0e7dc1 fix: use task_started description as immediate heading, dedupe final
- Show subagent description from task_started immediately (no 30s wait)
- Remove AI summary (agentProgressSummaries) — task_started is sufficient
- Revert progress heading to previous when final text matches current
- Track previousProgressText in direct-update path
2026-03-23 19:20:23 +09:00
Eyejoker
a8a1c9b45a fix: throttle progress edits via 5s ticker, prevent Discord rate limit
- Remove per-tool-activity sync calls (was flooding Discord with edits)
- Ticker-only sync at 5s intervals for time + tool activity updates
- Summary updates heading directly when progress message exists
- Prevent duplicate progress message creation with progressCreating flag
2026-03-23 19:13:51 +09:00
Eyejoker
5112af6741 fix: progress ticker on tool-activity, last-line └, summary+description both shown
- Ensure progressTicker runs during tool-activity updates for time refresh
- Last activity line uses └ instead of ├
- Summary (📋) and description shown together when both present
- Description indented as sub-item under summary
2026-03-23 18:52:17 +09:00
Eyejoker
6268ee64ed fix: prevent bot ping-pong in implicit continuation window
Exclude is_bot_message from implicit continuation trigger check.
Previously, bot A's response would trigger bot B's continuation
window, causing infinite back-and-forth responses.

Also: tool activity sub-lines use description over summary,
and max activities reduced to 2.
2026-03-23 18:44:43 +09:00
Eyejoker
ac11cb7df1 feat: show tool activity sub-lines in progress messages
Display subagent tool descriptions as sub-lines under the main
progress text, updating in-place via Discord message edit.
Shows up to 5 recent tool activities (e.g., "Reading index.ts").
2026-03-23 18:31:20 +09:00
Eyejoker
bf1453541f fix: buffer progress to prevent final-like text from showing
Progress updates are now buffered: each new progress flushes the
previous one. The latest pending progress is discarded when final
arrives with matching text, preventing duplicate display in Discord.
2026-03-23 18:23:46 +09:00
Eyejoker
08a560f144 fix: revert progress to previous text when final matches last progress
When the final result text is identical to the last progress update,
edit the progress message back to the previous progress text to avoid
showing the same content twice in Discord.
2026-03-23 18:06:17 +09:00
Eyejoker
0438d9113b fix: clean up progress tracking, fix subagent summary field handling
- Use system/task_progress subtype (not top-level type) for subagent events
- Extract intermediate assistant text between tool calls as progress
- Only show SDK-generated summaries for subagent progress (skip noisy per-tool updates)
- Truncate progress messages to Discord 2000 char limit
- Remove verbose debug logging from production
2026-03-23 17:59:49 +09:00
Eyejoker
7908115ea8 feat: enable subagent progress summaries in Claude runner
- Set agentProgressSummaries: true in SDK query options
- Handle task_progress and task_started events from subagents
- Subagent progress summaries streamed as progress phase to Discord
2026-03-23 17:09:42 +09:00