- backends is now an ordered candidate list (first = preferred); channels
report the backend actually serving via active_backend, surfaced in the
doctor text report and --json
- new agent_reach/probe.py really executes upstream commands and tells
apart missing / broken (stale venv shebang after a system Python
upgrade) / timeout, with a reinstall prescription for broken installs
- all 13 channels migrated off which()-only checks: fixes bilibili
false-positive "bili-cli 可用" on broken shims, misleading xiaohongshu
"连接失败", rdt OSError crashing doctor, mcporter breakage masquerading
as "未配置"
- twitter: 15s probe + 1 retry (flaky 10s timeout), broken twitter-cli
now falls back to bird instead of aborting the check
- doctor survives per-channel exceptions; config supports per-channel
backend override (<channel>_backend / <CHANNEL>_BACKEND env)
- fix skill install/uninstall crash on symlinked skill dirs (the
"[Errno None] None" warning from shutil.rmtree on a symlink)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Extracted from #318 (the UTF-8/doctor core, minus the env-wrapper feature):
- new agent_reach/utils/process.py: utf8_subprocess_env() +
mcporter_utf8_env_args() — Windows GBK consoles otherwise corrupt
Chinese output from mcporter/MCP child processes
- weibo/douyin/linkedin checks and weibo install/registration now pass
the UTF-8 env (and register the MCP server with --env PYTHONUTF8=1)
- youtube: extract _has_js_runtime_config() with an OSError guard so an
unreadable yt-dlp config can't crash doctor
- test_skill_command: open SKILL.md with explicit utf-8 (Windows GBK
default broke these tests)
Co-authored-by: chidao <2980933590@qq.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds agent_reach/transcribe.py (download → compress → chunk → transcribe with provider fallback, fully mocked tests). Maintainer follow-up on the branch: wired an agent-reach transcribe CLI subcommand + skill docs so agents can actually invoke it, added the missing configure openai-key branch the error hint referenced, removed two dead static methods. 103 tests pass; wheel-gate clean.
- YouTube: warn when only Node.js is installed but yt-dlp config file
is missing (previously returned "ok" incorrectly)
- Douyin: use `mcporter list` instead of calling with a hardcoded
invalid share URL that always fails
- cli: replace bare `except:` with `except Exception:` in
`_detect_environment` to avoid catching KeyboardInterrupt/SystemExit
- cli: fix unclosed file handle for cloud VM detection
- config: use `os.open()` with 0o600 mode to eliminate permission
race window when saving credentials
yt-dlp now requires an external JS runtime (deno or Node.js) for YouTube.
Since agent-reach already installs Node.js, we configure yt-dlp to use it:
1. cli.py: install writes '--js-runtimes node' to ~/.config/yt-dlp/config
2. youtube.py: doctor checks JS runtime availability and config
3. SKILL.md: updated YouTube section with accurate troubleshooting
Bilibili note: 412 errors are IP-based (needs proxy), not cookie-related.
Fixes#47