e79bed7afedad333448072f282e6ebb5c2ea1292
Voice utterances and text messages on the same Discord channel now share one Claude session, and Echo's voice replies are mirrored back into the text channel. Replaces the old voice:<id> session-key split. Changes: - src/adapters/_text_chunks.py: new leaf module for split_message (used by both discord_bot and voice pipeline) - src/router.py: drop voice: prefix from session_key; add [voice] marker; strip leading [speaker:/[voice] tokens from user input (anti-jailbreak); remove dead double-clear of voice: key - src/claude_session.py: include personality/VOICE_MODE.md unconditionally (rules become per-turn-aware via [speaker:] prefix instead of session flag) - src/voice/pipeline.py: VoiceSession splits text_channel_id + voice_channel_id; resolve text channel per-send (no stale refs); mirror Echo's reply text into the text channel after route_message returns - src/adapters/discord_voice.py: /voice join passes both channel ids - src/adapters/discord_bot.py: import split_message from leaf module - personality/VOICE_MODE.md: rewrite as per-turn dynamic rules; add synthesis instructions for text turns after voice turns Tests: - tests/test_router.py: 4 new cases (plain channel_id, anti-jailbreak, text-adapter regression, no-double-clear) - tests/test_pipeline_mirror.py: new — Echo reply mirror chunking, empty guard, mirror_enabled=False, send-raises resilience - tests/test_voice_session_channel_ids.py: new — split-attr contract + metrics payload schema - tests/test_voice_session_cleanup.py: update for new kwargs Plan: /home/moltbot/.claude/plans/vreau-ca-tot-textul-greedy-rivest.md Co-Authored-By: Claude Opus 4.7 <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
73%
HTML
23.3%
Shell
2.6%
JavaScript
0.6%
CSS
0.5%