Commit Graph

332 Commits

Author SHA1 Message Date
Eyejoker
f281a2ee52 style: apply formatter to runtime files 2026-03-20 03:42:22 +09:00
Eyejoker
a293a701f4 fix: restore regressions from discord-only refactor 2026-03-20 03:41:53 +09:00
Eyejoker
2b08851c2f style: format config and db 2026-03-20 01:08:15 +09:00
Eyejoker
bb0628e8f4 refactor: remove legacy container and non-discord remnants 2026-03-20 01:07:46 +09:00
Eyejoker
41afcb91cf feat: integrate Memento MCP for shared memory across agents
- Add MEMENTO_MCP_SSE_URL/ACCESS_KEY/REMOTE_PATH to readEnvFile
- Merge .env vars into cleanEnv for runner process inheritance
- Claude Code runner: add memento-mcp via mcp-remote in mcpServers
- Codex runner: inject memento-mcp section into config.toml
- Various improvements: CI watch, task scheduler, DB, IPC auth
2026-03-20 00:12:43 +09:00
Eyejoker
e7200a1ed8 Fix Codex task target JID injection 2026-03-19 14:35:30 +09:00
Eyejoker
aa063ccea4 Reset Codex progress tracking between turns 2026-03-19 04:02:51 +09:00
Eyejoker
f2ad1331a9 Rebrand NanoClaw to EJClaw 2026-03-19 03:31:41 +09:00
Eyejoker
29b78fc286 Refine Codex progress message tracking 2026-03-19 03:22:31 +09:00
Eyejoker
779d57c392 Stabilize paired-room orchestration and Codex app-server flow 2026-03-19 02:57:14 +09:00
Eyejoker
b710d4a33d chore: update claude-agent-sdk to 0.2.76, read dashboard config from .env
- Bump @anthropic-ai/claude-agent-sdk 0.2.68 → 0.2.76
- Read STATUS_CHANNEL_ID and USAGE_DASHBOARD from .env file
2026-03-16 05:54:17 +09:00
Eyejoker
385f3a0349 feat: block follow-up IPC after closeStdin with closingStdin flag
Prevent piping new messages to an agent that is shutting down.
Reset flag on new process start and cleanup.
2026-03-16 05:39:35 +09:00
Eyejoker
ea03956d0a feat: show session ID in dashboard status display
Add session label (last 8 chars) next to each group status.
Export buildStatusContent and DashboardOptions for testing.
2026-03-16 05:36:30 +09:00
Eyejoker
6f38f1cd63 feat: add SESSION_COMMAND_USER_IDS for admin session command access
Allow configured user IDs to execute session commands (/clear etc.)
in non-main groups. Adds isAdminSender check alongside isFromMe.
2026-03-16 05:14:38 +09:00
Eyejoker
7e77f37948 refactor: extract dashboard and message-runtime from index.ts
- Extract dashboard code into src/dashboard.ts
- Extract message runtime into src/message-runtime.ts
- Improve group-queue with better concurrency handling
- Update agent-runner with enhanced env/config passing
- Simplify DB operations and cleanup unused code
- Update README for Codex SDK architecture
2026-03-16 05:08:19 +09:00
Eyejoker
e23315ed48 feat: usage/server dashboard with progress bars and aligned labels 2026-03-15 22:37:40 +09:00
Eyejoker
9a6d9f4c4b revert: roll back DB merge, keep useful improvements
Fully revert DB merge patch (WAL, composite PK, SERVICE_ID in IPC/
router_state/sessions). Return to proven split-DB architecture.

Keep:
- Docker/Apple Container cleanup
- Usage dashboard CLAUDE_CODE_OAUTH_TOKEN fallback
- Codex runner heartbeat
- Agent-runner stderr timeout reset
2026-03-15 22:35:53 +09:00
Eyejoker
e2d6476cdf refactor: rename container/ to runners/
No longer using Docker containers — agents run as direct host
processes. The directory name now reflects the actual purpose.

Updated all references across source code, docs, and skills.
2026-03-15 19:29:23 +09:00
Eyejoker
6f4b6f8df7 feat: prepare DB for shared access (WAL, service partitioning)
Phase 0-2 of data unification:
- Enable WAL mode + busy_timeout for safe concurrent access
- router_state: keys prefixed with SERVICE_ID (lazy migration)
- sessions: composite PK (group_folder, agent_type)
- registered_groups: filtered by SERVICE_AGENT_TYPE on load
- Logger: service name tag for unified log streams

All changes are backward-compatible with the current split setup.
Actual directory merge (Phase 3-4) is a separate step.
2026-03-15 19:26:34 +09:00
Eyejoker
26783e520e refactor: switch codex runner from app-server to SDK
Replace raw JSON-RPC app-server protocol with @openai/codex-sdk.
The SDK wraps `codex exec` which ensures complete task execution per
turn, fixing the issue where app-server mode ended turns prematurely
(agent saying "하겠습니다" without doing the work).

Also fix AGENTS.md copy in agent-runner (was copying instructions.md
which Codex CLI doesn't read).
2026-03-14 22:42:47 +09:00
Eyejoker
66bc3c6ff1 fix: skip discord-codex channel registration on codex service
The codex service uses its own DISCORD_BOT_TOKEN via systemd
EnvironmentFile, so the discord-codex secondary channel is only
relevant for the primary service. Removes spurious credential
missing warning on codex service startup.
2026-03-14 19:13:16 +09:00
Eyejoker
35356dd8a7 refactor: remove token-refresh, use env-based auth only
Delete token-refresh.ts and credentials.json sync. Auth is now
via CLAUDE_CODE_OAUTH_TOKEN in .env (1-year setup-token).
No more auto-refresh loop or credentials.json dependency.
2026-03-14 19:09:40 +09:00
Eyejoker
3546a35354 refactor: skip token auto-refresh when using env-based auth
When CLAUDE_CODE_OAUTH_TOKEN or ANTHROPIC_API_KEY is set in .env,
the credentials.json refresh loop is unnecessary. setup-token
generates a 1-year token, making auto-refresh redundant.
2026-03-14 19:01:30 +09:00
Eyejoker
e4eca65c7c feat: suppress Discord link embed previews on bot messages
Add MessageFlags.SuppressEmbeds to all send() calls so URLs in
agent responses don't generate large preview cards.
2026-03-14 03:29:26 +09:00
Eyejoker
f388323987 chore: increase text file inline limit from 8000 to 32000 chars
11k char deployment logs were getting truncated, cutting off the
actual error. 32k is safe for 200k context window.
2026-03-14 02:34:34 +09:00
Eyejoker
ae1b37694e feat: inline text file attachments from Discord
Download and inline content of .txt and other text-based file
attachments instead of showing just the filename placeholder.
Handles long copy-pastes that Discord auto-converts to .txt files.
Truncates at 8000 chars with a note.
2026-03-14 02:32:14 +09:00
Eyejoker
b8421b659d feat: switch audio transcription from OpenAI Whisper to Groq Whisper
Groq runs the same whisper-large-v3-turbo model at 200x+ real-time speed.
Falls back to OpenAI Whisper if GROQ_API_KEY is not set.
Logs elapsed time per transcription for monitoring.
2026-03-14 01:51:38 +09:00
Eyejoker
b8292e14a1 feat: shared transcription cache to avoid duplicate Whisper API calls
Both services (nanoclaw + nanoclaw-codex) now share cache/transcriptions/
directory. When one service transcribes audio, the other reads from cache
instead of making a second Whisper API call. Uses .pending file to
coordinate concurrent transcription attempts.
2026-03-14 01:40:35 +09:00
Eyejoker
7a726c335d feat: purge status channel on startup for clean dashboard
- Add purgeChannel() to Channel interface and DiscordChannel
- Uses bulkDelete for recent messages, individual delete for old ones
- Called once at startup before creating fresh dashboard messages
2026-03-14 00:52:41 +09:00
Eyejoker
d06a835163 fix: usage dashboard - remove title, use system uptime, handle null limitName, drop seconds from timestamp
- Remove "📊 Usage 보고" title line
- Use os.uptime() instead of process.uptime() for actual server uptime
- Handle null limitName in Codex rate limits (fallback to limitId or 'Codex')
- Fix Codex usage parsing: extract from rateLimitsByLimitId object
- Fix formatResetKST to handle unix timestamps (number type)
- Remove seconds from update timestamp display
2026-03-14 00:50:29 +09:00
Eyejoker
26d50933de fix: re-throw editMessage errors so dashboard can reset message ID 2026-03-14 00:45:25 +09:00
Eyejoker
9e36d9d8d2 style: prettier formatting for discord test 2026-03-14 00:44:02 +09:00
Eyejoker
e0fcf836f4 feat: gate usage dashboard behind USAGE_DASHBOARD env var
Only one service needs to show system resources + API usage.
Set USAGE_DASHBOARD=true on the primary service only.
2026-03-13 23:51:31 +09:00
Eyejoker
cf75a1b993 feat: API usage in live dashboard + Discord channel names
- Fetch Claude Code usage via OAuth API (five_hour/seven_day)
- Fetch Codex usage via app-server JSON-RPC (rateLimits/read)
- System resources: CPU%, memory, disk in GB with emoji thresholds
- Show actual Discord channel names (#name) instead of DB-stored names
- Guard against overlapping usage updates (async API calls)
2026-03-13 23:48:36 +09:00
Eyejoker
7dcb3fe1e4 feat: status dashboard categories/ordering + live usage dashboard
- Add getChannelMeta to Discord channel (batch guild fetch)
- Status dashboard groups by Discord category, sorts by position
- Add live usage dashboard (CPU, memory, disk, uptime) with message edit
- Fix 4 failing discord.test.ts tests (sendMessage format, image fetch mock)
2026-03-13 23:42:45 +09:00
Eyejoker
27d4ea05dc feat: add status dashboard for live agent monitoring
Dedicated Discord channel shows per-group agent status with live
elapsed time. Single message is edited every 10s instead of spamming.

- GroupQueue tracks startedAt timestamps and exposes getStatuses()
- Channel interface gets editMessage/sendAndTrack for message editing
- STATUS_CHANNEL_ID env var to configure the dashboard channel
- Shows processing/idle/waiting/inactive per registered group
2026-03-13 23:05:32 +09:00
Eyejoker
6a65136ff2 style: collapse multiline parseInt in config 2026-03-13 22:44:58 +09:00
Eyejoker
8bd5f71a95 chore: remove container legacy references
- Delete container/build.sh (Docker build script, no longer used)
- Remove "auth" npm script (whatsapp-auth.ts doesn't exist)
- Remove CONTAINER_* env var fallbacks from config.ts
- Update CLAUDE.md: container-runner → agent-runner, fix descriptions
- Rename MAX_CONCURRENT_CONTAINERS → MAX_CONCURRENT_AGENTS in systemd
2026-03-13 20:22:17 +09:00
Eyejoker
d4e2d78585 fix: clean up empty bullet points after stripping image links 2026-03-13 19:32:34 +09:00
Eyejoker
288c3c63c7 feat: convert non-image markdown links to readable filenames in Discord
[BuildPanel.tsx](/long/path#L320) → `BuildPanel.tsx:320`
Keeps Discord output clean since local paths aren't clickable anyway.
2026-03-13 19:28:17 +09:00
Eyejoker
3cff07cc2e refactor: remove SendImage tag, rely on natural markdown link parsing
LLMs naturally produce [name.png](/path) markdown links for images.
Parse only this pattern instead of teaching agents a custom tag.
Remove Image Handling sections from instructions.
2026-03-13 19:24:49 +09:00
Eyejoker
fd5c81401d feat: also parse markdown image links for Discord image sending
Support [name.png](/path) format in addition to [SendImage: /path].
LLMs naturally produce markdown links, so both patterns are recognized.
Only absolute paths with image extensions are matched.
2026-03-13 19:23:49 +09:00
Eyejoker
a1db0e2161 feat: support agent-to-user image sending via Discord
Parse [SendImage: /absolute/path] tags from agent responses and send
them as Discord file attachments alongside the text message.
2026-03-13 19:18:09 +09:00
Eyejoker
8a0e407526 feat: add Discord image receiving for Claude Code and Codex agents
Download Discord image attachments to DATA_DIR/attachments/ and pass
them as multimodal content blocks to both agent types:
- Claude Code: base64 ImageBlockParam via Agent SDK MessageParam
- Codex: localImage input block via app-server turn/start
2026-03-13 19:15:23 +09:00
Eyejoker
09a089ccaf refactor: unify skill sync, remove commands directory
- Remove commands/ sync from agent-runner (skills/ is SSOT for both agents)
- Remove ~/.codex/skills/ as source (use ~/.claude/skills/ only)
- Codex uses $skill prefix, Claude Code uses /skill — both read from skills/
- Minor formatting fixes in config.ts, group-queue.test.ts, index.ts
2026-03-13 17:03:28 +09:00
Eyejoker
922ec60517 fix: sync Claude Code skills/commands to Codex sessions
Codex sessions now also receive skills and commands from ~/.claude/
in addition to ~/.codex/, so both agents share the same tool set
(patch, linear, sentry, coolify, exa, playwright, sprite, etc.)
2026-03-13 16:45:36 +09:00
Eyejoker
bd7f4408ae refactor: rename container references to agent across codebase
- container-runner.ts → agent-runner.ts
- ContainerInput/Output → AgentInput/Output
- ContainerConfig → AgentConfig
- runContainerAgent → runAgentProcess
- CONTAINER_TIMEOUT → AGENT_TIMEOUT (with env fallback)
- MAX_CONCURRENT_CONTAINERS → MAX_CONCURRENT_AGENTS
- containerName → processName, isTaskContainer → isTaskProcess
- DB column container_config kept as-is (backwards compat)
2026-03-13 16:18:36 +09:00
Eyejoker
35277cea0a feat: codex app-server integration, token sync fix, typing fix
- Rewrite codex-runner to use `codex app-server` JSON-RPC instead of
  `codex exec`. Supports streaming (item/agentMessage/delta), session
  persistence (thread/start, thread/resume), and mid-turn message
  injection (turn/steer with IPC polling during execution).
- Fix token refresh not syncing to per-group session directories,
  causing 401 errors on running agents.
- Fix typing indicator staying on when codex returns null result
  by always clearing typing on any streaming callback.
- Update README and CLAUDE.md to reflect dual-service architecture,
  host process mode, and codex app-server integration.
2026-03-13 16:03:08 +09:00
Eyejoker
0515edc93d feat: OAuth auto-refresh, Codex session resume, MCP injection, and secret sanitization
- Add token-refresh module that auto-renews Claude OAuth tokens 30min before expiry
- Fix Codex session loss on service restart by resuming previous sessions
- Inject nanoclaw MCP server into Codex config.toml for send_message/schedule_task
- Sanitize ANTHROPIC_API_KEY and CLAUDE_CODE_OAUTH_TOKEN from Codex subprocess env
2026-03-12 02:47:24 +09:00
Eyejoker
3fd9ce18b5 feat: sync skills to per-group Codex session dirs 2026-03-11 20:06:38 +09:00