docs: update README to reflect current codebase

- container-runner.ts → agent-runner.ts
- Add missing files: group-queue, group-folder, router, sender-allowlist,
  session-commands, channels/registry
- Add image handling, skill sync, auto-continue, GroupQueue sections
- Add 'both' agent type, data/attachments directory
- Add npm test to development commands
This commit is contained in:
Eyejoker
2026-03-13 19:56:19 +09:00
parent d4e2d78585
commit d295eb7aaf

View File

@@ -17,7 +17,7 @@ This fork runs two independent NanoClaw instances as systemd services:
- **nanoclaw** (Claude Code) — powered by Claude Agent SDK, trigger `@claude`
- **nanoclaw-codex** (Codex) — powered by Codex app-server JSON-RPC, trigger `@codex`
Each service has its own store, data, and groups directories. Discord channels can be registered with either or both bots.
Each service has its own store, data, and groups directories. Discord channels can be registered with either agent, or both (`both` agent type for shared channels).
## Key Differences from Upstream
@@ -29,42 +29,54 @@ Each service has its own store, data, and groups directories. Discord channels c
| Session management | Container-based | Per-group `CLAUDE_CONFIG_DIR` / `CODEX_HOME` |
| Token management | Manual | Auto-refresh with session sync |
| Channel | Multi-channel (WhatsApp, Telegram, etc.) | Discord-focused |
| Image support | N/A | Bidirectional (receive as multimodal input, send as attachments) |
| Skill sync | Per-container | SSOT from `~/.claude/skills/` to all agent sessions |
| Deployment | Single service | Dual systemd services |
## Architecture
```
Discord ──► SQLite ──► Polling Loop ──┬──► Claude Agent SDK (host process)
└──► Codex App-Server (JSON-RPC stdio)
├── thread/start, thread/resume
├── turn/start (streaming)
├── turn/steer (mid-turn injection)
── Auto-approval (bypass sandbox)
Discord ──► SQLite ──► GroupQueue ──┬──► Claude Agent SDK (host process)
└──► Codex App-Server (JSON-RPC stdio)
├── thread/start, thread/resume
├── turn/start (streaming, multimodal)
├── turn/steer (mid-turn injection)
── Auto-approval (bypass sandbox)
└── Auto-continue (text-only turn retry)
```
### Directory Layout
```
nanoclaw/
├── src/ # Core source
├── src/
│ ├── index.ts # Orchestrator: state, message loop, agent invocation
│ ├── container-runner.ts # Spawns agent processes, manages env/sessions
│ ├── agent-runner.ts # Spawns agent processes, manages env/sessions/skills
│ ├── group-queue.ts # Per-group concurrency, priority queue, idle preemption
│ ├── group-folder.ts # Group directory resolution and management
│ ├── router.ts # Outbound message formatting and routing
│ ├── sender-allowlist.ts # Security: sender-based access control
│ ├── session-commands.ts # Session commands (/compact)
│ ├── token-refresh.ts # OAuth auto-refresh + session directory sync
│ ├── channels/discord.ts # Discord channel implementation
│ ├── db.ts # SQLite operations
│ ├── ipc.ts # IPC watcher and task processing
│ ├── task-scheduler.ts # Scheduled tasks (cron/interval/once)
── config.ts # Paths, intervals, trigger patterns
── ipc.ts # IPC watcher and task processing
│ ├── db.ts # SQLite operations
│ ├── config.ts # Paths, intervals, trigger patterns
│ └── channels/
│ ├── registry.ts # Channel self-registration system
│ └── discord.ts # Discord: mentions, images, typing, file attachments
├── container/
│ ├── agent-runner/ # Claude Code runner (Agent SDK)
│ ├── codex-runner/ # Codex runner (app-server JSON-RPC)
│ ├── agent-runner/ # Claude Code runner (Agent SDK, multimodal input)
│ ├── codex-runner/ # Codex runner (app-server JSON-RPC, auto-continue)
│ └── skills/ # Shared agent skills (browser, etc.)
├── store/ # Claude Code service DB
├── store-codex/ # Codex service DB
├── data/sessions/ # Per-group Claude sessions (.claude/)
├── data/
│ ├── sessions/ # Per-group Claude sessions (.claude/)
│ └── attachments/ # Downloaded Discord image attachments
├── data-codex/sessions/ # Per-group Codex sessions (.codex/)
├── groups/ # Per-group memory (Claude Code)
├── groups-codex/ # Per-group memory (Codex)
├── groups/ # Per-group memory and workspace (Claude Code)
├── groups-codex/ # Per-group memory and workspace (Codex)
└── logs/ # Service logs
```
@@ -76,8 +88,25 @@ The Codex runner (`container/codex-runner/`) communicates with `codex app-server
- **Streaming**: `item/agentMessage/delta` notifications for real-time text
- **Mid-turn steering**: IPC messages injected via `turn/steer` during execution
- **Auto-approval**: `approvalPolicy: "never"` + `sandbox: "danger-full-access"`
- **Auto-continue**: Detects text-only turns (no tool execution) and automatically retries up to 5 times to nudge the agent into actually executing tasks
- **Multimodal input**: Image attachments converted to `localImage` input blocks in `turn/start`
- **Per-group config**: Model, effort, MCP servers configured per channel
### Image Handling
Bidirectional image support through Discord:
- **Receiving** (user → agent): Discord image attachments are downloaded to `data/attachments/`, then passed as base64 `ImageBlockParam` content blocks (Claude Code) or `localImage` input blocks (Codex)
- **Sending** (agent → user): Markdown image links `[name.png](/path)` in agent responses are automatically parsed and sent as Discord file attachments. Non-image file links are converted to readable filenames (`BuildPanel.tsx:320`)
### Skill Sync
Skills are managed from a single source of truth (`~/.claude/skills/` on the server) and automatically synced to all agent session directories at process start:
- Claude Code sessions: `~/.claude/skills/` + project `container/skills/`
- Codex sessions: Same sources, synced to per-group `.codex/` directories
- Skills auto-register as slash commands (`/name`) in Claude Code and `$name` in Codex
### OAuth Token Auto-Refresh
`src/token-refresh.ts` handles Claude Code OAuth token lifecycle:
@@ -87,6 +116,16 @@ The Codex runner (`container/codex-runner/`) communicates with `codex app-server
- Syncs refreshed credentials to all per-group session directories
- Solves the known headless environment token expiry issue
### GroupQueue
`src/group-queue.ts` manages agent execution with:
- **Per-group serialization**: Only one agent process per group at a time
- **Global concurrency limit**: Configurable max concurrent agents across all groups
- **Task priority**: Scheduled tasks drain before message processing
- **Idle preemption**: Idle agents are terminated when higher-priority tasks arrive
- **Exponential backoff**: Retries with backoff on processing failure
## Setup
### Prerequisites
@@ -132,7 +171,7 @@ Channels are registered in each service's SQLite database (`registered_groups` t
- **jid**: Discord channel ID (`dc:<channel_id>`)
- **folder**: Group folder name (matches Discord channel name)
- **trigger_pattern**: Regex for bot activation (`@claude` or `@codex`)
- **agent_type**: `claude-code` or `codex`
- **agent_type**: `claude-code`, `codex`, or `both` (shared channel)
- **work_dir**: Working directory for the agent
- **container_config**: JSON config (e.g., `{"codexEffort":"high"}`)
@@ -143,6 +182,7 @@ npm run build # Build main project
cd container/agent-runner && npm run build # Build Claude runner
cd container/codex-runner && npm run build # Build Codex runner
npm run dev # Dev mode with hot reload
npm test # Run tests
```
## License