From 28f0d15cdaee2a1babf6e6d66de1808674306d77 Mon Sep 17 00:00:00 2001 From: Jiao Huifeng Date: Fri, 20 Mar 2026 01:45:34 +0700 Subject: [PATCH] docs: add macOS 24/7 deployment guide for EvoSci + ccproxy + Telegram STT bot (#32) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Comprehensive step-by-step guide covering: - ccproxy installation from source (patched fork required for Claude 4+) - ccproxy OAuth login via `ccproxy auth login claude-api` - EvoScientist install with telegram + stt extras using uv - STT model pre-download to avoid first-message delay - launchd plist setup for auto-start on login with KeepAlive - Full troubleshooting section based on real deployment experience: - OAuth token not found (.credentials.json location) - Packages installed in wrong Python environment (conda vs .venv) - Shell glob eating brackets in pip install 'pkg[extra]' - Whisper hallucination / VAD filter - ffmpeg approval prompts → --auto-approve - heredoc variable expansion gotcha - External drive mount timing with launchd Co-authored-by: Claude Sonnet 4.6 Co-authored-by: Xi Zhang <106144707+X-iZhang@users.noreply.github.com> --- docs/deployment-macos-24h.md | 330 +++++++++++++++++++++++++++++++++++ 1 file changed, 330 insertions(+) create mode 100644 docs/deployment-macos-24h.md diff --git a/docs/deployment-macos-24h.md b/docs/deployment-macos-24h.md new file mode 100644 index 0000000..28ae601 --- /dev/null +++ b/docs/deployment-macos-24h.md @@ -0,0 +1,330 @@ +# Running EvoScientist 24/7 on macOS (Telegram Bot + STT + ccproxy) + +This guide covers deploying EvoScientist as a fully automated 24/7 service on macOS +(tested on Mac Mini with Apple Silicon), using: + +- **EvoScientist** — the AI research agent +- **ccproxy** — local proxy that routes API calls through your Claude Code subscription +- **Telegram channel** — messaging interface +- **STT** — automatic voice message transcription (faster-whisper) + +--- + +## Prerequisites + +- macOS 13+ (Apple Silicon or Intel) +- [Claude Code](https://claude.ai/code) installed and subscription active +- [uv](https://astral.sh/uv) installed +- A Telegram bot token (from [@BotFather](https://t.me/BotFather)) +- Your Telegram user ID (from [@userinfobot](https://t.me/userinfobot)) + +--- + +## 1. Clone repositories + +```bash +mkdir -p ~/Dev/tools +cd ~/Dev/tools + +git clone git@github.com:jhfnetboy/EvoScientist.git +git clone git@github.com:jhfnetboy/ccproxy-api.git +``` + +> Both repos should sit as siblings in the same parent directory. + +--- + +## 2. Install ccproxy from source + +> **Do not** `pip install ccproxy-api` from PyPI — it lacks the adaptive thinking +> and OAuth header fixes required for Claude 4+ models. Install from the patched fork. + +```bash +cd ~/Dev/tools/ccproxy-api +git checkout jhf-research +pip install -e . +which ccproxy # verify: should print a path +``` + +--- + +## 3. Authenticate ccproxy with your Claude subscription + +This step opens a browser window to log in with your Claude account. +It only needs to be done once per machine. + +```bash +ccproxy auth login claude-api +``` + +Verify the token was saved: + +```bash +ls ~/.claude/.credentials.json # note the leading dot +``` + +--- + +## 4. Install EvoScientist from source + +```bash +cd ~/Dev/tools/EvoScientist +git checkout jhf-research + +# Install with Telegram and STT support +uv pip install -e '.[telegram,stt]' +``` + +> **Important:** always use `uv pip install`, not `pip install`, to ensure packages +> land in the correct `.venv` that the service will use. + +Verify: + +```bash +which EvoSci +EvoSci -h +``` + +--- + +## 5. Pre-download the STT model + +The STT model (~250 MB) downloads from HuggingFace on first use. +Pre-download it now to avoid a delay on the first voice message: + +```bash +uv run python -c " +from faster_whisper import WhisperModel +WhisperModel('Systran/faster-whisper-small', device='cpu', compute_type='int8') +print('STT model ready') +" +``` + +--- + +## 6. Configure EvoScientist + +```bash +cd ~/Dev/tools/EvoScientist + +EvoSci config set anthropic_base_url "http://localhost:8000/claude" +EvoSci config set anthropic_api_key "sk-dummy" +EvoSci config set model "claude-sonnet-4-6" + +# Telegram +EvoSci config set telegram_bot_token "YOUR_BOT_TOKEN" +EvoSci config set telegram_allowed_senders "YOUR_TELEGRAM_USER_ID" + +# STT voice transcription +EvoSci config set stt_enabled true +EvoSci config set stt_language zh # zh / en / auto + +# Optional: set a default workspace directory +EvoSci config set default_workdir "/absolute/path/to/your/workspace" +``` + +--- + +## 7. Smoke test before creating services + +Open two terminals: + +**Terminal 1 — ccproxy:** +```bash +ccproxy serve --port 8000 +``` + +**Terminal 2 — EvoSci:** +```bash +cd ~/Dev/tools/EvoScientist +EvoSci serve --auto-approve +``` + +Send a text message and a voice message to your Telegram bot. +If both work, proceed to set up the background services. + +--- + +## 8. Create launchd services (auto-start on login) + +Run this script once to create both plist files: + +```bash +CCPROXY=$(which ccproxy) +EVOSCI_DIR="$HOME/Dev/tools/EvoScientist" # adjust if your path differs +EVOSCI_BIN="${EVOSCI_DIR}/.venv/bin/EvoSci" + +# ── ccproxy service ────────────────────────────────────────────────── +cat > ~/Library/LaunchAgents/com.evosci.ccproxy.plist << EOF + + + + + Labelcom.evosci.ccproxy + ProgramArguments + + ${CCPROXY} + serve + --port + 8000 + + RunAtLoad + KeepAlive + StandardOutPath/tmp/ccproxy.log + StandardErrorPath/tmp/ccproxy.log + + +EOF + +# ── EvoSci serve service ───────────────────────────────────────────── +cat > ~/Library/LaunchAgents/com.evosci.serve.plist << EOF + + + + + Labelcom.evosci.serve + ProgramArguments + + ${EVOSCI_BIN} + serve + --auto-approve + + WorkingDirectory${EVOSCI_DIR} + RunAtLoad + KeepAlive + StandardOutPath/tmp/evosci.log + StandardErrorPath/tmp/evosci.log + + +EOF + +# ── Load both services ─────────────────────────────────────────────── +launchctl load ~/Library/LaunchAgents/com.evosci.ccproxy.plist +launchctl load ~/Library/LaunchAgents/com.evosci.serve.plist + +echo "Services loaded:" +launchctl list | grep evosci +``` + +--- + +## 9. Check status and logs + +```bash +# Are both services running? +launchctl list | grep evosci + +# Live logs +tail -f /tmp/evosci.log +tail -f /tmp/ccproxy.log +``` + +--- + +## Managing services + +| Action | Command | +|--------|---------| +| Restart EvoSci | `launchctl kickstart -k gui/$(id -u)/com.evosci.serve` | +| Restart ccproxy | `launchctl kickstart -k gui/$(id -u)/com.evosci.ccproxy` | +| Stop EvoSci | `launchctl unload ~/Library/LaunchAgents/com.evosci.serve.plist` | +| Stop ccproxy | `launchctl unload ~/Library/LaunchAgents/com.evosci.ccproxy.plist` | +| Reload after plist edit | `launchctl unload && launchctl load ` | + +--- + +## Troubleshooting + +### `ccproxy not found` +ccproxy is not installed. Run: +```bash +cd ~/Dev/tools/ccproxy-api && pip install -e . +``` + +### `ValueError: No valid OAuth access token available` +ccproxy cannot find your Claude login token. Run: +```bash +ccproxy auth login claude-api +``` +A browser window will open. Log in with your Claude subscription account. +Verify the token was saved at `~/.claude/.credentials.json` (hidden file, note the leading dot). + +### `Channel telegram fatal error: python-telegram-bot not installed` +The package was installed in the wrong Python environment. Use `uv pip`: +```bash +cd ~/Dev/tools/EvoScientist +uv pip install 'python-telegram-bot>=21.0' +``` + +### `zsh: no matches found: evoscientist[telegram]` +Shell interprets `[` as a glob. Always quote the package name: +```bash +uv pip install 'EvoScientist[telegram,stt]' # correct +uv pip install EvoScientist[telegram,stt] # wrong — shell eats the brackets +``` + +### Agent keeps asking to approve ffmpeg / shell commands +Add `--auto-approve` to the EvoSci serve command in the plist (see step 8). + +### Voice messages not transcribed / agent receives `[voice: ...]` annotation +STT is disabled or not installed: +```bash +EvoSci config set stt_enabled true +uv pip install faster-whisper +``` + +### Whisper outputs gibberish (`字幕by索兰娅` etc.) +This is a known Whisper hallucination on silent/very short audio. It is filtered +automatically by the built-in VAD filter and `no_speech_prob` threshold introduced +in PR #28. Make sure you are on the `jhf-research` branch or a release that includes +that fix. + +### `Could not find service "com.evosci.*" in domain` +The plist was never loaded. Run: +```bash +launchctl load ~/Library/LaunchAgents/com.evosci.ccproxy.plist +launchctl load ~/Library/LaunchAgents/com.evosci.serve.plist +``` + +### heredoc `cat > file << EOF` hangs in terminal +The shell variable inside the heredoc was not expanded because `EOF` was quoted +(`<< 'EOF'`). Use unquoted `<< EOF` when the content contains `$VARIABLES` that +should be expanded, or pre-set the variables before running the command. + +### Services on external drive not starting at boot +`/Volumes/...` paths are only available after the external drive mounts. +With `KeepAlive: true`, launchd will keep retrying every few seconds and +the services will start automatically once the drive is available. +This is normal behaviour for a Mac Mini where the drive is always connected. + +### `pip install` installs to conda base instead of `.venv` +Always use `uv pip install` inside the EvoScientist project directory, +or explicitly target the venv: +```bash +cd ~/Dev/tools/EvoScientist +uv pip install 'some-package' +``` + +--- + +## Architecture overview + +``` +Telegram app + │ voice / text message + ▼ +python-telegram-bot (polling) + │ + ▼ +EvoScientist channel layer + │ STT hook in _enqueue_raw() + │ .ogg → faster-whisper → plain text + ▼ +EvoScientist agent + │ tool calls / LLM requests + ▼ +ccproxy (localhost:8000) + │ OAuth token from ~/.claude/.credentials.json + ▼ +Anthropic Claude API (claude.ai subscription) +```