diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..a39a541 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,82 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Frankenbot is a multi-agent event management system for the Diversity Ball Wien 2026. It's a Flask app (single-file `app.py`, ~3400 lines) with 13 specialized AI agents that handle tasks like budgeting, catering, music rights, tax advice, and team coordination. Agents are executed via **OpenCode CLI** (`opencode run`) which connects to Claude models via Anthropic. + +## Running the App + +```bash +# Start directly +python3 app.py + +# Or via systemd (production) +sudo systemctl restart frankenbot +sudo systemctl status frankenbot +sudo journalctl -u frankenbot -f + +# App runs on port 5050 (not 5000, that's Zou/Kitsu) +# Accessible at https://frankenbot.equalizent.media/ +``` + +## Architecture + +### Agent System + +Each agent lives in `agents//` with: +- `systemprompt.md` - Role and instructions +- `personality.md` - Behavioral traits +- `reminders.md` - Persistent notes +- `memory/` - JSON files (tasks.json, notes.json, conversations.json, max 100 entries each) +- `work/` - Agent output directory (used as cwd during execution) + +**Execution flow:** User prompt → load systemprompt + personality + memory summary + team summary → call `opencode run --model --format json ` → parse response for special commands (@CREATE_SUBTASK, @SEND_EMAIL, @ASK_ORCHESTRATOR, etc.) → return to user. + +Model assignments are in `agent_config.json`. Fallback model: `opencode/big-pickle`. + +### Database (SQLite: `email_journal.db`) + +Four tables: `email_journal` (IMAP message tracking), `tasks` (persistent task queue with status pending→in_progress→completed), `team_members` (real people with roles/contact), `app_settings` (key-value config). Auto-migrated on startup. + +### Background Threads (5 daemon threads) + +1. **EmailPoller** - IMAP check every 2 min, whitelist-filtered (@diversityball.at) +2. **TaskWorker** - Processes email tasks from queue every 10s +3. **TaskBeat** - Auto-delegates pending orchestrator tasks every 10s +4. **OrchestratorBeat** - Escalates stuck tasks every 30 min +5. **TelegramBot** - Polls for messages (if configured) + +### SSE Streaming + +`/api/agent-stream` uses `subprocess.Popen` with OpenCode, reads stdout line-by-line, yields JSON SSE events. Browser uses `fetch()` + ReadableStream. Nginx must have `proxy_buffering off`. + +### Authentication + +Single shared password (`APP_PASSWORD` in .env). `@login_required` decorator on all routes except `/login` and `/logout`. Flask session with 7-day lifetime. + +## Key Files + +| File | What it does | +|---|---| +| `app.py` | Everything: routes, agent execution, DB, email, telegram, background threads | +| `agent_config.json` | Agent → model mapping (editable via web UI /agents) | +| `.env` | APP_PASSWORD, email credentials (IMAP/SMTP), Telegram token | +| `templates/base.html` | Shared layout (Bootstrap 5, dark theme, navbar) | +| `static/style.css` | All custom styles | + +## Important Patterns + +- **Agent commands**: Agents can embed `@CREATE_SUBTASK`, `@SEND_EMAIL`, `@ASK_ORCHESTRATOR`, `@SUGGEST_AGENT`, `@READ_KNOWLEDGE`, `@SEND_TELEGRAM`, `@UPDATE_TEAM_MEMBER` in their responses. These are parsed by `parse_agent_commands()` and executed by the system. +- **Session cookie limit**: Don't store large data in Flask session (4KB cookie limit). The orchestrator knowledge base and agent prompts must be loaded on-demand, not cached in session. +- **Port 5050**: Port 5000 is used by Zou/Kitsu on this server. Don't change back to 5000. +- **OpenCode CLI**: Must be installed and authenticated separately (`opencode auth`). Binary at `~/.opencode/bin/opencode`. + +## Deployment + +- **Server**: 212.186.132.27 (signtime-kitsu) +- **nginx**: Reverse proxy on `frankenbot.equalizent.media` → localhost:5050 +- **SSL**: Let's Encrypt via certbot (auto-renew) +- **systemd**: `/etc/systemd/system/frankenbot.service`, runs as user `eric` +- **Git remote**: `https://git.poweroftwo.studio/Pjot/frankenbot.git`