Marius Mutu 51e56af557 feat(ralph): conversational planning agent (W2)
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>
2026-04-26 18:38:51 +00:00
2026-04-25 08:19:40 +00:00
2026-04-25 22:10:07 +00:00
2026-02-19 14:09:12 +00:00
2026-02-17 09:30:35 +00:00
2026-04-23 09:44:20 +00:00

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
No description provided
Readme 6.4 MiB
Languages
Python 69.9%
HTML 26.1%
Shell 2.9%
JavaScript 0.6%
CSS 0.5%