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:
78
README.md
78
README.md
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user