51e56af557c3445c31b15c1c9d383bdf15a19579
Echo Core devine planning agent: poartă o conversație multi-fază cu Marius folosind skill-urile gstack (/office-hours → /plan-ceo-review → /plan-eng-review → /plan-design-review opt) și produce final-plan.md în ~/workspace/<slug>/scripts/ralph/, gata să fie consumat de Ralph PRD generator (W3) noaptea. Decizii arhitecturale (din eng review + spike findings): - PlanningSession ca clasă SEPARATĂ de chat-ul main (NU mode=string param) — separation explicit. claude_session.py rămâne strict pentru chat; planning trăiește în src/planning_session.py + src/planning_orchestrator.py. Inheritance literală nu se aplică (claude_session.py expune funcții module-level, nu o clasă) — separation e satisfacută prin module distinct. - Fresh subprocess PER skill phase, NU single resumed session — phase-urile coordinează via disk artifacts (gstack convention în ~/.gstack/projects/<slug>/). Avoids context window growth. - --max-turns 20 default + retry pe error_max_turns la --max-turns 30. Spike a arătat că prompt-uri complexe pot exploda turn budget-ul. - approved-tasks.json schema extins cu planning_session_id + final_plan_path (Status flow: pending → planning → approved → running → complete). - State separat în sessions/planning.json (NU active.json), keyed pe (adapter, channel_id) pentru re-resume la restart echo-core. Trigger-e: - Discord: slash command /plan <slug> [descriere] cu autocomplete pe pending, buton "🧠 Planifică" în RalphProjectView, și /cancel slash command. - Telegram: /plan + /cancel commands, plus buton "🧠 Planifică" în ralph project keyboard. - Router: state-aware routing — dacă chat-ul e în planning, mesajele plain trec la PlanningOrchestrator.respond() prin --resume; /cancel revine la status pending; /advance / "Continuă faza" advance fază nouă (fresh subprocess); /finalize sau "Dau drumul" promote la status approved. Discord defer pattern: toate butoanele noi (PlanningActiveView, PlanningFinalView, "🧠 Planifică") apelează await interaction.response.defer(ephemeral=True) ÎNAINTE de orice IO — evită "Interaction failed" pe IO >3s. UX strings warm + colaborativ (per design review): "🧠 Pornesc planning pentru ...", "Răspunde aici", "Continuă faza", "Dau drumul tonight", "Anulează" — niciun "Submit/Approve/Cancel" generic. Tests: 23 noi (test_planning_session, test_planning_orchestrator, test_router_planning) — toate pass. Mock pe _run_claude pentru a evita subprocess Claude real în CI. Files new: prompts/planning_agent.md src/planning_session.py src/planning_orchestrator.py tests/test_planning_session.py tests/test_planning_orchestrator.py tests/test_router_planning.py Files modified: src/claude_session.py — _run_claude(cwd=...) optional + surface subtype/is_error src/router.py — state-aware routing, start_planning_session, planning_advance/approve/cancel, _ralph_propose schema cu planning_session_id + final_plan_path src/adapters/discord_bot.py — /plan + /cancel slash commands; planning views imported src/adapters/discord_views.py — PlanningActiveView, PlanningFinalView, "Planifică" button în RalphProjectView, _split_chunks helper src/adapters/telegram_bot.py — /plan + /cancel handlers, callback_ralph extins cu plan/planadvance/plancancel/planapprove, planning keyboards Status testelor pe modulele atinse: 75 passed, 0 failed (test_claude_session security_section preexistent — neatins). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Echo Core
AI-powered personal assistant bot with Discord, Telegram, and WhatsApp bridges. Uses Claude Code CLI for conversation, with persistent sessions, cron scheduling, semantic memory search, and heartbeat monitoring.
Quick Start
# Interactive setup wizard (recommended for first install)
bash setup.sh
The wizard handles prerequisites, virtual environment, bridge tokens, config, and systemd services in 10 guided steps.
Manual Setup
# 1. Create venv and install dependencies
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# 2. Store Discord token in keyring
./cli.py secrets set discord_token
# 3. Edit config.json (bot name, owner ID, channels)
# 4. Start
systemctl --user start echo-core
Architecture
┌─────────────┐
│ Claude CLI │
└──────┬──────┘
│
┌──────┴──────┐
│ Router │
└──────┬──────┘
┌────────────┼────────────┐
│ │ │
┌─────┴─────┐ ┌───┴───┐ ┌──────┴──────┐
│ Discord │ │Telegram│ │ WhatsApp │
│ (d.py) │ │(ptb) │ │(Baileys+py) │
└────────────┘ └────────┘ └─────────────┘
- Discord: slash commands via discord.py
- Telegram: commands + inline keyboards via python-telegram-bot
- WhatsApp: Node.js Baileys bridge + Python polling adapter
- All three run concurrently in the same asyncio event loop
Key Components
| Component | Description |
|---|---|
src/main.py |
Entry point — starts all adapters + scheduler + heartbeat |
src/router.py |
Routes messages to Claude or handles commands |
src/claude_session.py |
Claude Code CLI wrapper with --resume sessions |
src/credential_store.py |
Keyring-based secrets manager |
src/scheduler.py |
APScheduler cron jobs |
src/heartbeat.py |
Periodic health checks |
src/memory_search.py |
Ollama embeddings + SQLite semantic search |
cli.py |
CLI tool — status, doctor, logs, secrets, cron, etc. |
setup.sh |
Interactive 10-step setup wizard |
bridge/whatsapp/ |
Node.js WhatsApp bridge (Baileys + Express) |
CLI Usage
The setup wizard installs eco as a global command (~/.local/bin/eco):
eco status # Bot online/offline, uptime
eco doctor # Full diagnostic check
eco restart # Restart the service
eco restart --bridge # Restart bot + WhatsApp bridge
eco stop # Stop the service
eco logs # Tail echo-core.log (last 20 lines)
eco logs 50 # Last 50 lines
eco secrets list # Show stored credentials
eco secrets set <name> # Store a secret in keyring
eco secrets test # Check required secrets
eco sessions list # Active Claude sessions
eco sessions clear # Clear all sessions
eco channel list # Registered Discord channels
eco cron list # Show scheduled jobs
eco cron run <name> # Force-run a cron job
eco memory search "<query>" # Semantic search in memory
eco memory reindex # Rebuild search index
eco heartbeat # Run health checks
eco whatsapp status # WhatsApp bridge connection
eco whatsapp qr # QR code pairing instructions
eco send <alias> <message> # Send message via router
Configuration
config.json — runtime configuration:
{
"bot": {
"name": "Echo",
"default_model": "opus",
"owner": "DISCORD_USER_ID",
"admins": ["TELEGRAM_USER_ID"]
},
"channels": { },
"telegram_channels": { },
"whatsapp": {
"enabled": true,
"bridge_url": "http://127.0.0.1:8098",
"owner": "PHONE_NUMBER"
},
"whatsapp_channels": { }
}
Secrets (Discord/Telegram tokens) are stored in the system keyring, not in config files.
Services
Echo Core runs as systemd user services:
systemctl --user start echo-core # Start bot
systemctl --user start echo-whatsapp-bridge # Start WA bridge
systemctl --user status echo-core # Check status
journalctl --user -u echo-core -f # Follow logs
Requirements
- Python 3.12+
- Claude Code CLI
- Node.js 22+ (only for WhatsApp bridge)
Tests
source .venv/bin/activate
pytest tests/
440 tests, zero failures.
Description
Languages
Python
69.9%
HTML
26.1%
Shell
2.9%
JavaScript
0.6%
CSS
0.5%