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** (Claude Code) — powered by Claude Agent SDK, trigger `@claude`
|
||||||
- **nanoclaw-codex** (Codex) — powered by Codex app-server JSON-RPC, trigger `@codex`
|
- **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
|
## 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` |
|
| Session management | Container-based | Per-group `CLAUDE_CONFIG_DIR` / `CODEX_HOME` |
|
||||||
| Token management | Manual | Auto-refresh with session sync |
|
| Token management | Manual | Auto-refresh with session sync |
|
||||||
| Channel | Multi-channel (WhatsApp, Telegram, etc.) | Discord-focused |
|
| 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 |
|
| Deployment | Single service | Dual systemd services |
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
```
|
```
|
||||||
Discord ──► SQLite ──► Polling Loop ──┬──► Claude Agent SDK (host process)
|
Discord ──► SQLite ──► GroupQueue ──┬──► Claude Agent SDK (host process)
|
||||||
└──► Codex App-Server (JSON-RPC stdio)
|
└──► Codex App-Server (JSON-RPC stdio)
|
||||||
├── thread/start, thread/resume
|
├── thread/start, thread/resume
|
||||||
├── turn/start (streaming)
|
├── turn/start (streaming, multimodal)
|
||||||
├── turn/steer (mid-turn injection)
|
├── turn/steer (mid-turn injection)
|
||||||
└── Auto-approval (bypass sandbox)
|
├── Auto-approval (bypass sandbox)
|
||||||
|
└── Auto-continue (text-only turn retry)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Directory Layout
|
### Directory Layout
|
||||||
|
|
||||||
```
|
```
|
||||||
nanoclaw/
|
nanoclaw/
|
||||||
├── src/ # Core source
|
├── src/
|
||||||
│ ├── index.ts # Orchestrator: state, message loop, agent invocation
|
│ ├── 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
|
│ ├── 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)
|
│ ├── 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/
|
├── container/
|
||||||
│ ├── agent-runner/ # Claude Code runner (Agent SDK)
|
│ ├── agent-runner/ # Claude Code runner (Agent SDK, multimodal input)
|
||||||
│ ├── codex-runner/ # Codex runner (app-server JSON-RPC)
|
│ ├── codex-runner/ # Codex runner (app-server JSON-RPC, auto-continue)
|
||||||
│ └── skills/ # Shared agent skills (browser, etc.)
|
│ └── skills/ # Shared agent skills (browser, etc.)
|
||||||
├── store/ # Claude Code service DB
|
├── store/ # Claude Code service DB
|
||||||
├── store-codex/ # Codex 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/)
|
├── data-codex/sessions/ # Per-group Codex sessions (.codex/)
|
||||||
├── groups/ # Per-group memory (Claude Code)
|
├── groups/ # Per-group memory and workspace (Claude Code)
|
||||||
├── groups-codex/ # Per-group memory (Codex)
|
├── groups-codex/ # Per-group memory and workspace (Codex)
|
||||||
└── logs/ # Service logs
|
└── 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
|
- **Streaming**: `item/agentMessage/delta` notifications for real-time text
|
||||||
- **Mid-turn steering**: IPC messages injected via `turn/steer` during execution
|
- **Mid-turn steering**: IPC messages injected via `turn/steer` during execution
|
||||||
- **Auto-approval**: `approvalPolicy: "never"` + `sandbox: "danger-full-access"`
|
- **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
|
- **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
|
### OAuth Token Auto-Refresh
|
||||||
|
|
||||||
`src/token-refresh.ts` handles Claude Code OAuth token lifecycle:
|
`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
|
- Syncs refreshed credentials to all per-group session directories
|
||||||
- Solves the known headless environment token expiry issue
|
- 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
|
## Setup
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
@@ -132,7 +171,7 @@ Channels are registered in each service's SQLite database (`registered_groups` t
|
|||||||
- **jid**: Discord channel ID (`dc:<channel_id>`)
|
- **jid**: Discord channel ID (`dc:<channel_id>`)
|
||||||
- **folder**: Group folder name (matches Discord channel name)
|
- **folder**: Group folder name (matches Discord channel name)
|
||||||
- **trigger_pattern**: Regex for bot activation (`@claude` or `@codex`)
|
- **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
|
- **work_dir**: Working directory for the agent
|
||||||
- **container_config**: JSON config (e.g., `{"codexEffort":"high"}`)
|
- **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/agent-runner && npm run build # Build Claude runner
|
||||||
cd container/codex-runner && npm run build # Build Codex runner
|
cd container/codex-runner && npm run build # Build Codex runner
|
||||||
npm run dev # Dev mode with hot reload
|
npm run dev # Dev mode with hot reload
|
||||||
|
npm test # Run tests
|
||||||
```
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|||||||
Reference in New Issue
Block a user