feat(experience): one-liner install/update docs catch up + version-watching skill
The one-liner entry docs were untouched by the backend upgrade — new users following "帮我安装 Agent Reach" would still get the old world. Now: - docs/install.md: xiaohongshu section rewritten (desktop OpenCLI with the one manual extension click / server xiaohongshu-mcp with QR + 150MB first-run warning / legacy xhs-cli kept as fallback); Reddit section says plainly there is no zero-config path; optional-channel menu gains OpenCLI; upstream table matches the new routing with a doctor --json pointer - docs/update.md: full rewrite — upgrade-only-what-exists tool refresh (incl. npm update for OpenCLI/mcporter, pinned git source for rdt-cli), one-time OpenCLI offer for desktops, skill sync now rides doctor's auto-sync instead of an inline python blob, WeChat-era content removed - check-update / watch: "update available" now leads with the one-liner (帮我更新 Agent Reach:<update.md>) which updates package + tools + skill; bare pip stays as the package-only alternative - fix: version compare was `!=` — a local build AHEAD of the latest release (installed from main during a release window) was told to "update" into a downgrade; now semantic tuple compare with fallback (+4 tests) - skill (zh+en): description gains a NOT-for boundary (fetch-only, no write ops, defer to dedicated skills); new standing rule — after substantial tasks run check-update and append a one-liner update hint to the wrap-up, never interrupting or nagging - SKILL_en.md restructured to the same three-layer skeleton as the Chinese version (124-line body, shared references/) instead of a 263-line everything-inline page Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+34
-6
@@ -1635,6 +1635,35 @@ def _github_get_with_retry(url, timeout=10, retries=3, sleeper=time.sleep):
|
|||||||
return None, "unknown", retries
|
return None, "unknown", retries
|
||||||
|
|
||||||
|
|
||||||
|
#: Full update = package + upstream tools + skill. The one-liner walks an
|
||||||
|
#: agent through all three (docs/update.md); bare pip only updates the package.
|
||||||
|
_UPDATE_INSTRUCTIONS = (
|
||||||
|
"更新方式(推荐,复制这句话给你的 AI Agent,会完整更新本体+上游工具+skill):\n"
|
||||||
|
" 帮我更新 Agent Reach:https://raw.githubusercontent.com/Panniantong/agent-reach/main/docs/update.md\n"
|
||||||
|
"仅更新本体(不含上游工具和 skill):\n"
|
||||||
|
" pip install --upgrade https://github.com/Panniantong/agent-reach/archive/main.zip"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _is_newer_version(remote: str, local: str) -> bool:
|
||||||
|
"""True if remote is strictly newer than local (semantic compare).
|
||||||
|
|
||||||
|
A plain != would tell users "update available" when their local build is
|
||||||
|
AHEAD of the latest release (e.g. installed from main during a release
|
||||||
|
window) — and walk them into a downgrade.
|
||||||
|
"""
|
||||||
|
def parse(v):
|
||||||
|
try:
|
||||||
|
return tuple(int(x) for x in v.strip().split("."))
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
r, l = parse(remote), parse(local)
|
||||||
|
if r is None or l is None:
|
||||||
|
return remote != local # unparseable — fall back to old behavior
|
||||||
|
return r > l
|
||||||
|
|
||||||
|
|
||||||
def _cmd_check_update():
|
def _cmd_check_update():
|
||||||
"""Check for newer versions on GitHub."""
|
"""Check for newer versions on GitHub."""
|
||||||
from agent_reach import __version__
|
from agent_reach import __version__
|
||||||
@@ -1654,7 +1683,7 @@ def _cmd_check_update():
|
|||||||
latest = data.get("tag_name", "").lstrip("v")
|
latest = data.get("tag_name", "").lstrip("v")
|
||||||
body = data.get("body", "")
|
body = data.get("body", "")
|
||||||
|
|
||||||
if latest and latest != __version__:
|
if latest and _is_newer_version(latest, __version__):
|
||||||
print(f"最新版本: v{latest} ← 有更新!")
|
print(f"最新版本: v{latest} ← 有更新!")
|
||||||
if body:
|
if body:
|
||||||
print()
|
print()
|
||||||
@@ -1663,8 +1692,7 @@ def _cmd_check_update():
|
|||||||
for line in body.strip().split("\n")[:20]:
|
for line in body.strip().split("\n")[:20]:
|
||||||
print(f" {line}")
|
print(f" {line}")
|
||||||
print()
|
print()
|
||||||
print("更新命令:")
|
print(_UPDATE_INSTRUCTIONS)
|
||||||
print(" pip install --upgrade https://github.com/Panniantong/agent-reach/archive/main.zip")
|
|
||||||
return "update_available"
|
return "update_available"
|
||||||
print(f"✅ 已是最新版本")
|
print(f"✅ 已是最新版本")
|
||||||
return "up_to_date"
|
return "up_to_date"
|
||||||
@@ -1686,8 +1714,7 @@ def _cmd_check_update():
|
|||||||
date = commit.get("commit", {}).get("committer", {}).get("date", "")[:10]
|
date = commit.get("commit", {}).get("committer", {}).get("date", "")[:10]
|
||||||
print(f"最新提交: {sha} ({date}) {msg}")
|
print(f"最新提交: {sha} ({date}) {msg}")
|
||||||
print()
|
print()
|
||||||
print("更新命令:")
|
print(_UPDATE_INSTRUCTIONS)
|
||||||
print(" pip install --upgrade https://github.com/Panniantong/agent-reach/archive/main.zip")
|
|
||||||
return "unknown"
|
return "unknown"
|
||||||
|
|
||||||
commit_err = _classify_github_response_error(resp2)
|
commit_err = _classify_github_response_error(resp2)
|
||||||
@@ -1760,7 +1787,8 @@ def _cmd_watch():
|
|||||||
if release_body:
|
if release_body:
|
||||||
for line in release_body.strip().split("\n")[:10]:
|
for line in release_body.strip().split("\n")[:10]:
|
||||||
print(f" {line}")
|
print(f" {line}")
|
||||||
print(f" 更新: pip install --upgrade https://github.com/Panniantong/agent-reach/archive/main.zip")
|
print(" 更新(一句话发给 Agent 即可完整更新):")
|
||||||
|
print(" 帮我更新 Agent Reach:https://raw.githubusercontent.com/Panniantong/agent-reach/main/docs/update.md")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ description: >
|
|||||||
Zero config for 6 channels. Run `agent-reach doctor --json` to see which
|
Zero config for 6 channels. Run `agent-reach doctor --json` to see which
|
||||||
backend serves each platform right now.
|
backend serves each platform right now.
|
||||||
|
|
||||||
|
NOT for: 写报告/数据分析/翻译等内容加工(本 skill 只负责从互联网获取内容);
|
||||||
|
发帖/评论/点赞等写操作;已有专门 skill 的平台(先用专门 skill)。
|
||||||
|
|
||||||
【路由方式】SKILL.md 包含路由表和常用命令,复杂场景需按需阅读对应分类的 references/*.md。
|
【路由方式】SKILL.md 包含路由表和常用命令,复杂场景需按需阅读对应分类的 references/*.md。
|
||||||
分类:search / social (小红书/推特/B站/V2EX/Reddit) / career(LinkedIn) / dev(github) / web(网页/文章/RSS) / video(YouTube/B站/播客)。
|
分类:search / social (小红书/推特/B站/V2EX/Reddit) / career(LinkedIn) / dev(github) / web(网页/文章/RSS) / video(YouTube/B站/播客)。
|
||||||
triggers:
|
triggers:
|
||||||
@@ -46,6 +49,11 @@ metadata:
|
|||||||
2. **声明你在用什么**:开始干活前说一句「使用 agent-reach 的 X 平台 / Y 后端」。
|
2. **声明你在用什么**:开始干活前说一句「使用 agent-reach 的 X 平台 / Y 后端」。
|
||||||
3. **失败按 references 里的重试链处理**,不要瞎猜命令。
|
3. **失败按 references 里的重试链处理**,不要瞎猜命令。
|
||||||
4. **全网调研类任务**:组合多平台(Exa 搜索 + Twitter/Reddit 看讨论 + 小红书/B站看中文场景),并行收集再汇总。
|
4. **全网调研类任务**:组合多平台(Exa 搜索 + Twitter/Reddit 看讨论 + 小红书/B站看中文场景),并行收集再汇总。
|
||||||
|
5. **替用户盯版本**:完成一次较大的调研/多平台任务后,顺手跑
|
||||||
|
`agent-reach check-update`(很快,一个 API 调用)。有新版就在收尾汇报里附一句:
|
||||||
|
「Agent Reach 有新版 vX.Y.Z,复制这句话给我即可更新:帮我更新 Agent Reach:
|
||||||
|
https://raw.githubusercontent.com/Panniantong/agent-reach/main/docs/update.md」。
|
||||||
|
不要中断当前任务去更新,也不要重复提醒同一个版本。
|
||||||
|
|
||||||
## 路由表
|
## 路由表
|
||||||
|
|
||||||
|
|||||||
+72
-210
@@ -13,251 +13,113 @@ description: >
|
|||||||
Zero config for 6 channels. Run `agent-reach doctor --json` to see which
|
Zero config for 6 channels. Run `agent-reach doctor --json` to see which
|
||||||
backend serves each platform right now.
|
backend serves each platform right now.
|
||||||
|
|
||||||
Triggers: "research", "deep dive", "search twitter", "search xiaohongshu",
|
NOT for: writing reports/analysis/translation (this skill only FETCHES
|
||||||
"watch this video", "search the web", "look this up", "youtube transcript",
|
internet content); posting/commenting/liking (write operations); platforms
|
||||||
"search reddit", "read this link", "bilibili", "V2EX",
|
that already have a dedicated skill installed (prefer that skill).
|
||||||
"xiaoyuzhou", "podcast", "xueqiu", "stock quote", "雪球", "股票".
|
|
||||||
metadata:
|
metadata:
|
||||||
openclaw:
|
openclaw:
|
||||||
homepage: https://github.com/Panniantong/Agent-Reach
|
homepage: https://github.com/Panniantong/Agent-Reach
|
||||||
---
|
---
|
||||||
|
|
||||||
# Agent Reach — Usage Guide
|
# Agent Reach — internet capability router
|
||||||
|
|
||||||
Upstream tools for 13 platforms. Call them directly.
|
13 platforms, multiple backends each. **When this skill exists, use it for
|
||||||
|
these platforms — do not invent your own approach.**
|
||||||
|
|
||||||
Run `agent-reach doctor` to check which channels are available.
|
## Standing rules (apply for the whole session)
|
||||||
|
|
||||||
## ⚠️ Workspace Rules
|
1. **Health-check before acting**: for multi-backend platforms (XiaoHongShu /
|
||||||
|
Reddit / Bilibili / Twitter), run `agent-reach doctor --json` first and
|
||||||
|
pick the command group matching each platform's `active_backend`.
|
||||||
|
2. **Announce what you use**: say "using agent-reach, platform X via backend Y"
|
||||||
|
before starting.
|
||||||
|
3. **On failure, follow the retry chains in references/** — never guess
|
||||||
|
commands.
|
||||||
|
4. **For broad research tasks**: combine platforms (Exa for web search +
|
||||||
|
Twitter/Reddit for discussions + XiaoHongShu/Bilibili for Chinese
|
||||||
|
perspectives), collect in parallel, then synthesize.
|
||||||
|
5. **Watch versions for the user**: after finishing a substantial
|
||||||
|
multi-platform task, run `agent-reach check-update` (fast, one API call).
|
||||||
|
If a new version exists, append one line to your wrap-up: "Agent Reach
|
||||||
|
vX.Y.Z is available — paste this to me to update: 帮我更新 Agent Reach:
|
||||||
|
https://raw.githubusercontent.com/Panniantong/agent-reach/main/docs/update.md".
|
||||||
|
Never interrupt the current task to update; never nag about the same version twice.
|
||||||
|
|
||||||
**Never create files in the agent workspace.** Use `/tmp/` for temporary output and `~/.agent-reach/` for persistent data.
|
## Routing table
|
||||||
|
|
||||||
## Web — Any URL
|
| User intent | Category | Details |
|
||||||
|
|---------|------|---------|
|
||||||
```bash
|
| Web / code search | search | [references/search.md](references/search.md) |
|
||||||
curl -s "https://r.jina.ai/URL"
|
| XiaoHongShu / Twitter / Bilibili / V2EX / Reddit | social | [references/social.md](references/social.md) |
|
||||||
```
|
| Jobs / LinkedIn | career | [references/career.md](references/career.md) |
|
||||||
|
| GitHub / code | dev | [references/dev.md](references/dev.md) |
|
||||||
## Web Search (Exa)
|
| Web pages / articles / RSS | web | [references/web.md](references/web.md) |
|
||||||
|
| YouTube / Bilibili / podcast transcripts | video | [references/video.md](references/video.md) |
|
||||||
|
|
||||||
|
## Zero-config quick commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Exa web search
|
||||||
mcporter call 'exa.web_search_exa(query: "query", numResults: 5)'
|
mcporter call 'exa.web_search_exa(query: "query", numResults: 5)'
|
||||||
mcporter call 'exa.get_code_context_exa(query: "code question", tokensNum: 3000)'
|
|
||||||
```
|
|
||||||
|
|
||||||
## Twitter/X (twitter-cli)
|
# Read any web page
|
||||||
|
curl -s "https://r.jina.ai/URL"
|
||||||
|
|
||||||
```bash
|
# GitHub search
|
||||||
twitter -c search "query" -n 10 # search (-c = compact JSON, LLM-friendly)
|
|
||||||
twitter -c tweet URL_OR_ID # read tweet + replies (supports /status/ URLs)
|
|
||||||
twitter -c article URL_OR_ID # read a Twitter Article
|
|
||||||
twitter -c user-posts @username -n 20 # user timeline
|
|
||||||
twitter -c feed -n 20 # home timeline
|
|
||||||
```
|
|
||||||
|
|
||||||
> Binary is `twitter` (`pipx install twitter-cli`, ≥ 0.8.5). The `bird` name in older docs has been retired. If `search` returns 404, run `pipx upgrade twitter-cli`.
|
|
||||||
|
|
||||||
## YouTube (yt-dlp)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yt-dlp --dump-json "URL" # video metadata
|
|
||||||
yt-dlp --write-sub --write-auto-sub --sub-lang "zh-Hans,zh,en" --skip-download -o "/tmp/%(id)s" "URL"
|
|
||||||
# download subtitles, then read the .vtt file
|
|
||||||
yt-dlp --dump-json "ytsearch5:query" # search
|
|
||||||
```
|
|
||||||
|
|
||||||
## Bilibili (bili-cli / OpenCLI)
|
|
||||||
|
|
||||||
> ⚠️ Do NOT use yt-dlp for bilibili — its risk control 412-blocks yt-dlp in
|
|
||||||
> every configuration (verified 2026-06). yt-dlp is for YouTube only.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bili video BVxxx # video detail, no login needed
|
|
||||||
bili search "query" --type video -n 5 # search
|
|
||||||
bili hot -n 10 # trending
|
|
||||||
opencli bilibili subtitle BVxxx # subtitles (desktop Chrome)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Reddit (login required — no zero-config path)
|
|
||||||
|
|
||||||
> Anonymous .json endpoints are 403-blocked and official API registration is
|
|
||||||
> approval-gated (2025-11). Every backend needs a logged-in session.
|
|
||||||
> Check `agent-reach doctor --json` for the active backend.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
opencli reddit search "query" -f yaml # desktop, browser session
|
|
||||||
rdt search "query" --limit 10 # legacy/server, cookie login
|
|
||||||
rdt read POST_ID # post + comments
|
|
||||||
```
|
|
||||||
|
|
||||||
## GitHub (gh CLI)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gh search repos "query" --sort stars --limit 10
|
gh search repos "query" --sort stars --limit 10
|
||||||
gh repo view owner/repo
|
|
||||||
gh search code "query" --language python
|
|
||||||
gh issue list -R owner/repo --state open
|
|
||||||
gh issue view 123 -R owner/repo
|
|
||||||
```
|
|
||||||
|
|
||||||
## XiaoHongShu (multi-backend — check doctor for active backend)
|
# YouTube subtitles (NOTE: never use yt-dlp for Bilibili — see video.md)
|
||||||
|
yt-dlp --write-sub --skip-download -o "/tmp/%(id)s" "URL"
|
||||||
|
|
||||||
```bash
|
# V2EX hot topics
|
||||||
# Desktop preferred: OpenCLI (reuses browser session, zero config)
|
|
||||||
opencli xiaohongshu search "query" -f yaml
|
|
||||||
opencli xiaohongshu note "NOTE_URL" -f yaml
|
|
||||||
|
|
||||||
# Server: xiaohongshu-mcp via mcporter (QR login; always pass --timeout 120000)
|
|
||||||
mcporter call 'xiaohongshu.search_feeds(keyword: "query")' --timeout 120000
|
|
||||||
mcporter call 'xiaohongshu.get_feed_detail(feed_id: "xxx", xsec_token: "yyy")' --timeout 120000
|
|
||||||
|
|
||||||
# Legacy fallback: xhs-cli (upstream unmaintained since 2026-03)
|
|
||||||
xhs search "query"
|
|
||||||
xhs read NOTE_ID_OR_URL
|
|
||||||
```
|
|
||||||
|
|
||||||
> Requires login. Use Cookie-Editor to import cookies.
|
|
||||||
|
|
||||||
> **Tip: Clean bloated output.** The XHS API returns large JSON with many unused fields.
|
|
||||||
> Pipe through the formatter to save context:
|
|
||||||
> ```bash
|
|
||||||
> mcporter call 'xiaohongshu.search_feeds(keyword: "query")' | agent-reach format xhs
|
|
||||||
> ```
|
|
||||||
> This keeps only: title, content, author, engagement counts, image URLs, and tags.
|
|
||||||
|
|
||||||
## Xiaoyuzhou Podcast (groq-whisper + ffmpeg)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Transcribe a single podcast episode (outputs text to /tmp/)
|
|
||||||
~/.agent-reach/tools/xiaoyuzhou/transcribe.sh "https://www.xiaoyuzhoufm.com/episode/EPISODE_ID"
|
|
||||||
```
|
|
||||||
|
|
||||||
> Requires `ffmpeg` and a Groq API key (free).
|
|
||||||
> Configure the key with `agent-reach configure groq-key YOUR_KEY`.
|
|
||||||
> On first run, install the tools with `agent-reach install --env=auto`.
|
|
||||||
> Run `agent-reach doctor` to check status.
|
|
||||||
> Output Markdown files are saved to `/tmp/` by default.
|
|
||||||
|
|
||||||
## LinkedIn (mcporter)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mcporter call 'linkedin.get_person_profile(linkedin_url: "https://linkedin.com/in/username")'
|
|
||||||
mcporter call 'linkedin.search_people(keyword: "AI engineer", limit: 10)'
|
|
||||||
```
|
|
||||||
|
|
||||||
Fallback: `curl -s "https://r.jina.ai/https://linkedin.com/in/username"`
|
|
||||||
|
|
||||||
## V2EX (public API)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Hot topics
|
|
||||||
curl -s "https://www.v2ex.com/api/topics/hot.json" -H "User-Agent: agent-reach/1.0"
|
curl -s "https://www.v2ex.com/api/topics/hot.json" -H "User-Agent: agent-reach/1.0"
|
||||||
|
|
||||||
# Topics in a node (node_name examples: python, tech, jobs, qna)
|
# Bilibili search (bili-cli, no login needed)
|
||||||
curl -s "https://www.v2ex.com/api/topics/show.json?node_name=python&page=1" -H "User-Agent: agent-reach/1.0"
|
bili search "query" --type video -n 5
|
||||||
|
|
||||||
# Topic details (extract topic_id from URLs like https://www.v2ex.com/t/1234567)
|
|
||||||
curl -s "https://www.v2ex.com/api/topics/show.json?id=TOPIC_ID" -H "User-Agent: agent-reach/1.0"
|
|
||||||
|
|
||||||
# Topic replies
|
|
||||||
curl -s "https://www.v2ex.com/api/replies/show.json?topic_id=TOPIC_ID&page=1" -H "User-Agent: agent-reach/1.0"
|
|
||||||
|
|
||||||
# User profile
|
|
||||||
curl -s "https://www.v2ex.com/api/members/show.json?username=USERNAME" -H "User-Agent: agent-reach/1.0"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Python example (`V2EXChannel`):
|
## Login-backed platforms (pick by doctor's active_backend)
|
||||||
|
|
||||||
```python
|
```bash
|
||||||
from agent_reach.channels.v2ex import V2EXChannel
|
# Twitter search (twitter-cli preferred; retry chain in social.md)
|
||||||
|
twitter search "query" -n 10
|
||||||
|
|
||||||
ch = V2EXChannel()
|
# Reddit (NO zero-config path — OpenCLI or rdt-cli, login required)
|
||||||
|
opencli reddit search "query" -f yaml # desktop
|
||||||
|
rdt search "query" --limit 10 # legacy/server
|
||||||
|
|
||||||
# Get hot topics (default 20 items)
|
# XiaoHongShu (desktop prefers OpenCLI)
|
||||||
# Returned fields: id, title, url, replies, node_name, node_title, content(first 200 chars), created
|
opencli xiaohongshu search "query" -f yaml
|
||||||
topics = ch.get_hot_topics(limit=10)
|
|
||||||
for t in topics:
|
|
||||||
print(f"[{t['node_title']}] {t['title']} ({t['replies']} replies) {t['url']}")
|
|
||||||
print(f" id={t['id']} created={t['created']}")
|
|
||||||
|
|
||||||
# Get latest topics for a specific node
|
|
||||||
# Returned fields: id, title, url, replies, node_name, node_title, content(first 200 chars), created
|
|
||||||
node_topics = ch.get_node_topics("python", limit=5)
|
|
||||||
for t in node_topics:
|
|
||||||
print(t["id"], t["title"], t["url"])
|
|
||||||
|
|
||||||
# Get one topic plus replies
|
|
||||||
# Returned fields: id, title, url, content, replies_count, node_name, node_title,
|
|
||||||
# author, created, replies (list of {author, content, created})
|
|
||||||
topic = ch.get_topic(1234567)
|
|
||||||
print(topic["title"], "—", topic["author"])
|
|
||||||
for r in topic["replies"]:
|
|
||||||
print(f" {r['author']}: {r['content'][:80]}")
|
|
||||||
|
|
||||||
# Get user info
|
|
||||||
# Returned fields: id, username, url, website, twitter, psn, github, btc, location, bio, avatar, created
|
|
||||||
user = ch.get_user("Livid")
|
|
||||||
print(user["username"], user["bio"], user["github"])
|
|
||||||
|
|
||||||
# Search (not supported by the public V2EX API; returns guidance instead)
|
|
||||||
result = ch.search("asyncio")
|
|
||||||
print(result[0]["error"]) # Use built-in site search or the Exa channel instead
|
|
||||||
```
|
```
|
||||||
|
|
||||||
> No auth required. Results are public JSON. V2EX node names are listed at https://www.v2ex.com/planes
|
## Environment check
|
||||||
|
|
||||||
## Xueqiu (public API)
|
```bash
|
||||||
|
# Channel availability + which backend serves each platform
|
||||||
```python
|
agent-reach doctor --json
|
||||||
from agent_reach.channels.xueqiu import XueqiuChannel
|
|
||||||
|
|
||||||
ch = XueqiuChannel()
|
|
||||||
|
|
||||||
# Get stock quotes (symbol examples: SH600519 mainland China, SZ000858 Shenzhen, AAPL US, 00700 HK)
|
|
||||||
# Returned fields: symbol, name, current, percent, chg, high, low, open, last_close,
|
|
||||||
# volume, amount, market_capital, turnover_rate, pe_ttm, timestamp
|
|
||||||
quote = ch.get_stock_quote("AAPL")
|
|
||||||
print(f"{quote['name']} ({quote['symbol']}): {quote['current']} ({quote['percent']}%)")
|
|
||||||
|
|
||||||
# Search stocks
|
|
||||||
# Returned fields: symbol, name, exchange
|
|
||||||
stocks = ch.search_stock("Apple", limit=5)
|
|
||||||
for s in stocks:
|
|
||||||
print(f"{s['name']} ({s['symbol']}) - {s['exchange']}")
|
|
||||||
|
|
||||||
# Hot posts
|
|
||||||
# Returned fields: id, title, text(first 200 chars), author, likes, url
|
|
||||||
posts = ch.get_hot_posts(limit=10)
|
|
||||||
for p in posts:
|
|
||||||
print(f"{p['author']}: {p['text'][:50]}... ({p['likes']} likes)")
|
|
||||||
|
|
||||||
# Hot stocks (stock_type=10 popularity ranking, stock_type=12 watchlist ranking)
|
|
||||||
# Returned fields: symbol, name, current, percent, rank
|
|
||||||
hot = ch.get_hot_stocks(limit=10, stock_type=10)
|
|
||||||
for s in hot:
|
|
||||||
print(f"#{s['rank']} {s['name']} ({s['symbol']}): {s['current']} ({s['percent']}%)")
|
|
||||||
```
|
```
|
||||||
|
|
||||||
> No login required. Agent Reach auto-fetches session cookies, and all public APIs can be used directly.
|
## Workspace rules
|
||||||
|
|
||||||
## RSS (feedparser)
|
**Never create files in the agent workspace.** Use `/tmp/` for temporary
|
||||||
|
output and `~/.agent-reach/` for persistent data.
|
||||||
|
|
||||||
```python
|
## Detailed references
|
||||||
python3 -c "
|
|
||||||
import feedparser
|
|
||||||
for e in feedparser.parse('FEED_URL').entries[:5]:
|
|
||||||
print(f'{e.title} — {e.link}')
|
|
||||||
"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Troubleshooting
|
Read the matching file when you need specifics (commands above cover the
|
||||||
|
common cases; references hold per-backend command groups, caveats, retry
|
||||||
|
chains — note: reference docs are written in Chinese, commands are universal):
|
||||||
|
|
||||||
- **Channel not working?** Run `agent-reach doctor` — it shows status and fix instructions.
|
- [Search](references/search.md) — Exa AI search
|
||||||
- **Twitter fetch failed?** Ensure `undici` is installed: `npm install -g undici`. Configure a proxy if needed: `agent-reach configure proxy URL`.
|
- [Social](references/social.md) — XiaoHongShu, Twitter, Bilibili, V2EX, Reddit (multi-backend groups)
|
||||||
|
- [Career](references/career.md) — LinkedIn
|
||||||
|
- [Dev](references/dev.md) — GitHub CLI
|
||||||
|
- [Web](references/web.md) — Jina Reader, RSS
|
||||||
|
- [Video](references/video.md) — YouTube, Bilibili, Xiaoyuzhou
|
||||||
|
|
||||||
## Setting Up a Channel ("help me configure XXX")
|
## Configure a channel
|
||||||
|
|
||||||
If a channel needs setup (cookies, Docker, etc.), fetch the install guide:
|
If a channel needs setup, fetch the install guide:
|
||||||
https://raw.githubusercontent.com/Panniantong/agent-reach/main/docs/install.md
|
https://raw.githubusercontent.com/Panniantong/agent-reach/main/docs/install.md
|
||||||
|
|
||||||
The user only provides cookies. Everything else is your job.
|
The user only provides cookies / one extension click; the agent does the rest.
|
||||||
|
|||||||
+42
-40
@@ -20,7 +20,7 @@ Copy this to your AI Agent:
|
|||||||
|
|
||||||
### Goal
|
### Goal
|
||||||
|
|
||||||
Install Agent Reach and all upstream tools so your user's agent has full internet access. After installation, you'll use the upstream tools directly (twitter-cli, rdt-cli, xhs-cli, yt-dlp, mcporter, gh CLI, etc.) — Agent Reach is just the installer and health checker.
|
Install Agent Reach and all upstream tools so your user's agent has full internet access. After installation, you'll use the upstream tools directly (OpenCLI, twitter-cli, bili-cli, rdt-cli, yt-dlp, mcporter, gh CLI, etc.) — Agent Reach is the selector, installer, health checker and router, never a wrapper.
|
||||||
|
|
||||||
### ⚠️ Boundaries
|
### ⚠️ Boundaries
|
||||||
|
|
||||||
@@ -96,12 +96,13 @@ After installing the basics, **ask the user** which additional channels they nee
|
|||||||
>
|
>
|
||||||
> 还有这些可选渠道,你需要哪些?
|
> 还有这些可选渠道,你需要哪些?
|
||||||
>
|
>
|
||||||
|
> - 🌟 **OpenCLI**(桌面推荐)— 一次安装,小红书/Reddit/B站字幕/Twitter 备选全解锁(复用浏览器登录态,零配置;只需在 Chrome 商店点一次"添加扩展")
|
||||||
> - 🐦 **Twitter/X** — 搜推文、看时间线(需要登录 Cookie)
|
> - 🐦 **Twitter/X** — 搜推文、看时间线(需要登录 Cookie)
|
||||||
> - 📈 **雪球** — 股票行情、热门帖子(需要登录 Cookie)
|
> - 📈 **雪球** — 股票行情、热门帖子(需要登录 Cookie)
|
||||||
> - 🎙️ **小宇宙播客** — 音频转文字(需要免费 Groq Key)
|
> - 🎙️ **小宇宙播客** — 音频转文字(需要免费 Groq Key)
|
||||||
> - 📕 **小红书** — 阅读、搜索、发帖(需要登录)
|
> - 📕 **小红书** — 搜索、阅读、评论(桌面走 OpenCLI;服务器用 xiaohongshu-mcp 扫码)
|
||||||
> - 📖 **Reddit** — 搜索和阅读帖子
|
> - 📖 **Reddit** — 搜索和阅读帖子(必须登录态:桌面 OpenCLI 或 rdt-cli + Cookie)
|
||||||
> - 📺 **B站完整版** — 热门、排行、搜索
|
> - 📺 **B站完整版** — 热门、排行、搜索、视频详情(bili-cli,无需登录)
|
||||||
> - 💼 **LinkedIn** — Profile、职位搜索
|
> - 💼 **LinkedIn** — Profile、职位搜索
|
||||||
>
|
>
|
||||||
> 告诉我你要哪些,比如"帮我装小红书和 Twitter"。或者说"全部装"。
|
> 告诉我你要哪些,比如"帮我装小红书和 Twitter"。或者说"全部装"。
|
||||||
@@ -109,11 +110,11 @@ After installing the basics, **ask the user** which additional channels they nee
|
|||||||
Based on the user's choice, run:
|
Based on the user's choice, run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
agent-reach install --env=auto --channels=twitter,xiaohongshu # Example: user chose Twitter + XHS
|
agent-reach install --env=auto --channels=opencli,xiaohongshu # Example: desktop user chose XHS (OpenCLI-backed)
|
||||||
agent-reach install --env=auto --channels=all # User wants everything
|
agent-reach install --env=auto --channels=all # User wants everything
|
||||||
```
|
```
|
||||||
|
|
||||||
Supported channel names: `twitter`, `xiaoyuzhou`, `xueqiu`, `xiaohongshu`, `reddit`, `bilibili`, `linkedin`, `all`
|
Supported channel names: `opencli`, `twitter`, `xiaoyuzhou`, `xueqiu`, `xiaohongshu`, `reddit`, `bilibili`, `linkedin`, `all`
|
||||||
|
|
||||||
### Step 3: Fix what's broken
|
### Step 3: Fix what's broken
|
||||||
|
|
||||||
@@ -159,44 +160,43 @@ agent-reach configure twitter-cookies "PASTED_STRING"
|
|||||||
>
|
>
|
||||||
> 如果用户报告 "fetch failed",参考 [troubleshooting.md](troubleshooting.md)
|
> 如果用户报告 "fetch failed",参考 [troubleshooting.md](troubleshooting.md)
|
||||||
|
|
||||||
**Reddit & Bilibili full access (server users):**
|
**Reddit (login is mandatory — no zero-config path):**
|
||||||
> "Reddit and Bilibili block server IPs. To unlock full access, I need a residential proxy. You can get one at https://webshare.io ($1/month). Send me the proxy address."
|
> Reddit 的匿名接口已被封、官方 API 需人工审批。桌面用户首选 OpenCLI(浏览器里登录过 reddit.com 即可用);服务器/存量用户用 rdt-cli:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
agent-reach configure proxy http://user:pass@ip:port
|
pipx install 'git+https://github.com/public-clis/rdt-cli.git' # PyPI 落后,从 GitHub 装
|
||||||
|
rdt login # 自动提取浏览器 Cookie;服务器无浏览器时按 doctor 提示手动写 Cookie
|
||||||
```
|
```
|
||||||
|
|
||||||
**XiaoHongShu / 小红书 (xhs-cli):**
|
> 中国大陆访问 Reddit 需要代理;服务器 IP 被风控时可配住宅代理(如 https://webshare.io,约 $1/月):
|
||||||
> "小红书通过 xhs-cli 访问,pipx 一行安装,不需要 Docker。"
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pipx install xiaohongshu-cli
|
|
||||||
xhs login
|
|
||||||
```
|
|
||||||
|
|
||||||
> `xhs login` 会自动从浏览器提取 Cookie。如果自动提取失败,可以手动导入:
|
|
||||||
>
|
|
||||||
> **手动导入 Cookie(Cookie-Editor 方式):**
|
|
||||||
> 1. 用户在自己的浏览器登录小红书 (xiaohongshu.com)
|
|
||||||
> 2. 用 [Cookie-Editor](https://chromewebstore.google.com/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm) 插件导出 Cookie(JSON 或 Header String 格式均可)
|
|
||||||
> 3. 把 Cookie 字符串发给 Agent
|
|
||||||
> 4. Agent 运行命令完成登录:
|
|
||||||
>
|
|
||||||
> ```bash
|
> ```bash
|
||||||
> # JSON 格式(Cookie-Editor → Export → JSON)
|
> agent-reach configure proxy http://user:pass@ip:port
|
||||||
> agent-reach configure xhs-cookies '[{"name":"web_session","value":"xxx","domain":".xiaohongshu.com",...}]'
|
|
||||||
>
|
|
||||||
> # 或 Header String 格式(Cookie-Editor → Export → Header String)
|
|
||||||
> agent-reach configure xhs-cookies "key1=val1; key2=val2; ..."
|
|
||||||
> ```
|
> ```
|
||||||
|
|
||||||
|
**XiaoHongShu / 小红书(多后端,按环境选):**
|
||||||
|
|
||||||
|
> **桌面电脑(推荐 OpenCLI):**
|
||||||
|
> "小红书走 OpenCLI——复用你浏览器里的登录态,平时刷过小红书就直接能用,零配置。"
|
||||||
|
|
||||||
|
```bash
|
||||||
|
agent-reach install --channels opencli
|
||||||
|
```
|
||||||
|
|
||||||
|
> 装完后引导用户做唯一一步手动操作(Chrome 安全限制,无法代劳):
|
||||||
|
> 1. 打开 https://chromewebstore.google.com/detail/opencli/ildkmabpimmkaediidaifkhjpohdnifk
|
||||||
|
> 2. 点「添加至 Chrome」
|
||||||
|
> 3. 运行 `opencli doctor` 验证(显示 Extension: connected 即成功)
|
||||||
>
|
>
|
||||||
> **注意:** 推荐使用 Cookie-Editor 导出方式,不要依赖 QR 扫码登录。
|
> **服务器 / 无桌面环境(xiaohongshu-mcp):**
|
||||||
|
> 1. 从 https://github.com/xpzouying/xiaohongshu-mcp/releases 下载对应平台 binary 到 `~/.agent-reach/tools/`
|
||||||
|
> 2. 启动服务(首次运行会自动下载约 150MB 无头浏览器,耐心等完成)
|
||||||
|
> 3. 让用户扫码登录(agent 调 `get_login_qrcode` 工具取二维码)
|
||||||
|
> 4. 接入:`mcporter config add xiaohongshu http://localhost:18060/mcp`
|
||||||
|
> 5. 调用时务必带 `--timeout 120000`
|
||||||
>
|
>
|
||||||
> **备选方案:Docker MCP**
|
> **存量用户(xhs-cli):** 已装好的 xhs-cli 继续作为备选后端工作(上游 2026-03 起停更,不推荐新装)。`xhs login` 自动提取浏览器 Cookie;失败时用 Cookie-Editor 导出后:
|
||||||
> 如果你已经在使用 [xiaohongshu-mcp](https://github.com/xpzouying/xiaohongshu-mcp) Docker 方案,它也能正常工作:
|
|
||||||
> ```bash
|
> ```bash
|
||||||
> docker run -d --name xiaohongshu-mcp -p 18060:18060 xpzouying/xiaohongshu-mcp
|
> agent-reach configure xhs-cookies "key1=val1; key2=val2; ..."
|
||||||
> mcporter config add xiaohongshu http://localhost:18060/mcp
|
|
||||||
> ```
|
> ```
|
||||||
|
|
||||||
**雪球 / Xueqiu (股票行情 + 热门帖子):**
|
**雪球 / Xueqiu (股票行情 + 热门帖子):**
|
||||||
@@ -292,7 +292,7 @@ If the user agrees, create a **cron job** (daily, `sessionTarget: "isolated"`, `
|
|||||||
运行 agent-reach watch 命令。
|
运行 agent-reach watch 命令。
|
||||||
如果输出包含"全部正常",不需要通知用户,静默结束。
|
如果输出包含"全部正常",不需要通知用户,静默结束。
|
||||||
如果输出包含问题(❌ ⚠️)或新版本(🆕),把完整报告发给用户,并建议修复方案。
|
如果输出包含问题(❌ ⚠️)或新版本(🆕),把完整报告发给用户,并建议修复方案。
|
||||||
如果有新版本可用,问用户是否要升级(升级命令:pip install --upgrade https://github.com/Panniantong/agent-reach/archive/main.zip)。
|
如果有新版本可用,问用户是否要升级(把这句话发给用户的 Agent 即可完整更新:帮我更新 Agent Reach:https://raw.githubusercontent.com/Panniantong/agent-reach/main/docs/update.md)。
|
||||||
```
|
```
|
||||||
|
|
||||||
If the user wants a different agent to handle it, let them choose.
|
If the user wants a different agent to handle it, let them choose.
|
||||||
@@ -319,14 +319,16 @@ After installation, use upstream tools directly. See SKILL.md for the full comma
|
|||||||
|
|
||||||
| Platform | Upstream Tool | Example |
|
| Platform | Upstream Tool | Example |
|
||||||
|----------|--------------|---------|
|
|----------|--------------|---------|
|
||||||
| Twitter/X | `twitter` | `twitter search "query" -n 10` |
|
| Twitter/X | `twitter`(备选 `opencli`) | `twitter search "query" -n 10` |
|
||||||
| YouTube | `yt-dlp` | `yt-dlp --dump-json URL` |
|
| YouTube | `yt-dlp` | `yt-dlp --dump-json URL` |
|
||||||
| Bilibili | `yt-dlp` + `bili` | `bili hot` / `bili search "query" --type video` |
|
| Bilibili | `bili`(字幕走 `opencli`) | `bili search "query" --type video` / `opencli bilibili subtitle BVxxx` |
|
||||||
| Reddit | `rdt` | `rdt search "query"` / `rdt read POST_ID` |
|
| Reddit | `opencli`(备选 `rdt`) | `opencli reddit search "query" -f yaml` / `rdt read POST_ID` |
|
||||||
| GitHub | `gh` | `gh search repos "query"` |
|
| GitHub | `gh` | `gh search repos "query"` |
|
||||||
| Web | `curl` + Jina | `curl -s "https://r.jina.ai/URL"` |
|
| Web | `curl` + Jina | `curl -s "https://r.jina.ai/URL"` |
|
||||||
| Exa Search | `mcporter` | `mcporter call 'exa.web_search_exa(...)'` |
|
| Exa Search | `mcporter` | `mcporter call 'exa.web_search_exa(...)'` |
|
||||||
| 小红书 | `mcporter` | `mcporter call 'xiaohongshu.search_feeds(...)'` |
|
| 小红书 | `opencli`(服务器 `mcporter`) | `opencli xiaohongshu search "query" -f yaml` |
|
||||||
| 小宇宙播客 | `transcribe.sh` | `bash ~/.agent-reach/tools/xiaoyuzhou/transcribe.sh <URL>` |
|
| 小宇宙播客 | `transcribe.sh` | `bash ~/.agent-reach/tools/xiaoyuzhou/transcribe.sh <URL>` |
|
||||||
| LinkedIn | `mcporter` | `mcporter call 'linkedin.get_person_profile(...)'` |
|
| LinkedIn | `mcporter` | `mcporter call 'linkedin.get_person_profile(...)'` |
|
||||||
| RSS | `feedparser` | `python3 -c "import feedparser; ..."` |
|
| RSS | `feedparser` | `python3 -c "import feedparser; ..."` |
|
||||||
|
|
||||||
|
> 多后端平台以 `agent-reach doctor --json` 的 `active_backend` 为准。
|
||||||
|
|||||||
+51
-68
@@ -24,7 +24,7 @@ Update Agent Reach: https://raw.githubusercontent.com/Panniantong/agent-reach/ma
|
|||||||
|
|
||||||
### Goal
|
### Goal
|
||||||
|
|
||||||
Update Agent Reach to the latest version, install any new upstream tools, migrate from deprecated tools, and verify everything works. The user should not need to do anything manually.
|
Update Agent Reach to the latest version, refresh upstream tools, migrate from retired backends, and verify everything works. The user should not need to do anything manually (except things only a human can do, like clicking a browser-extension install button).
|
||||||
|
|
||||||
### Step 1: Check current version
|
### Step 1: Check current version
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ Update Agent Reach to the latest version, install any new upstream tools, migrat
|
|||||||
agent-reach check-update
|
agent-reach check-update
|
||||||
```
|
```
|
||||||
|
|
||||||
If it says "已是最新版本", skip to Step 5 (verify). Otherwise continue.
|
If it says "已是最新版本", skip to Step 4 (verify). Otherwise continue.
|
||||||
|
|
||||||
### Step 2: Update Agent Reach package
|
### Step 2: Update Agent Reach package
|
||||||
|
|
||||||
@@ -40,40 +40,47 @@ If it says "已是最新版本", skip to Step 5 (verify). Otherwise continue.
|
|||||||
pip install --upgrade https://github.com/Panniantong/agent-reach/archive/main.zip
|
pip install --upgrade https://github.com/Panniantong/agent-reach/archive/main.zip
|
||||||
```
|
```
|
||||||
|
|
||||||
### Step 3: Install / migrate upstream tools
|
> If pip complains about `externally-managed-environment` (PEP 668), the user
|
||||||
|
> originally installed via pipx or a venv — use the matching command:
|
||||||
|
> `pipx install --force https://github.com/Panniantong/agent-reach/archive/main.zip`
|
||||||
|
> or activate `~/.agent-reach-venv` first.
|
||||||
|
|
||||||
Run these commands to ensure all upstream CLI tools are installed. Skip any that are already installed.
|
### Step 3: Refresh upstream tools
|
||||||
|
|
||||||
|
Run these to keep installed tools current. **Only upgrade what is already
|
||||||
|
installed — do not install new tools the user never asked for** (the one
|
||||||
|
exception: OpenCLI on desktop, see below).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# === Required tools (core functionality) ===
|
# Python-based CLIs the user already has (upgrade keeps signatures fresh)
|
||||||
|
which twitter >/dev/null 2>&1 && { pipx upgrade twitter-cli 2>/dev/null || uv tool upgrade twitter-cli 2>/dev/null; }
|
||||||
|
which bili >/dev/null 2>&1 && { pipx upgrade bilibili-cli 2>/dev/null || uv tool upgrade bilibili-cli 2>/dev/null; }
|
||||||
|
which xhs >/dev/null 2>&1 && { pipx upgrade xiaohongshu-cli 2>/dev/null || uv tool upgrade xiaohongshu-cli 2>/dev/null; }
|
||||||
|
which yt-dlp >/dev/null 2>&1 && { pipx upgrade yt-dlp 2>/dev/null || uv tool upgrade yt-dlp 2>/dev/null || pip install -U yt-dlp 2>/dev/null; }
|
||||||
|
|
||||||
# Twitter/X — twitter-cli (replaces deprecated bird CLI)
|
# rdt-cli is pinned to a git source (PyPI lags upstream)
|
||||||
which twitter >/dev/null 2>&1 || pipx install twitter-cli 2>/dev/null || uv tool install twitter-cli 2>/dev/null
|
which rdt >/dev/null 2>&1 && pipx install --force 'git+https://github.com/public-clis/rdt-cli.git' 2>/dev/null
|
||||||
|
|
||||||
# Reddit — rdt-cli (replaces Exa-based approach; PyPI lags, install from GitHub)
|
# npm-based
|
||||||
which rdt >/dev/null 2>&1 || pipx install 'git+https://github.com/public-clis/rdt-cli.git' 2>/dev/null || uv tool install --from 'git+https://github.com/public-clis/rdt-cli.git' rdt-cli 2>/dev/null
|
which mcporter >/dev/null 2>&1 && npm update -g mcporter 2>/dev/null
|
||||||
|
which opencli >/dev/null 2>&1 && npm update -g @jackwener/opencli 2>/dev/null
|
||||||
# XiaoHongShu — xhs-cli (replaces Docker MCP)
|
|
||||||
which xhs >/dev/null 2>&1 || pipx install xiaohongshu-cli 2>/dev/null || uv tool install xiaohongshu-cli 2>/dev/null
|
|
||||||
|
|
||||||
# === Optional enhancements ===
|
|
||||||
|
|
||||||
# Bilibili — bili-cli (adds hot/rank/search on top of yt-dlp)
|
|
||||||
which bili >/dev/null 2>&1 || pipx install bilibili-cli 2>/dev/null || uv tool install bilibili-cli 2>/dev/null
|
|
||||||
|
|
||||||
# mcporter + Exa (for WeChat, web search)
|
|
||||||
which mcporter >/dev/null 2>&1 || npm install -g mcporter 2>/dev/null
|
|
||||||
|
|
||||||
# yt-dlp (YouTube + Bilibili video)
|
|
||||||
which yt-dlp >/dev/null 2>&1 || pip install yt-dlp 2>/dev/null
|
|
||||||
|
|
||||||
# gh CLI (GitHub)
|
|
||||||
which gh >/dev/null 2>&1 || echo "GitHub CLI not installed — see https://cli.github.com"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Desktop users without OpenCLI**: since v1.5.0 OpenCLI is the preferred
|
||||||
|
backend for 小红书/Reddit (and adds B站 subtitles) by riding the user's
|
||||||
|
browser session. Offer it once:
|
||||||
|
|
||||||
|
> "这次更新引入了 OpenCLI 后端(复用你的浏览器登录态,小红书/Reddit 零配置)。要装吗?装完只需你在 Chrome 商店点一次『添加扩展』。"
|
||||||
|
|
||||||
|
If yes: `agent-reach install --channels opencli` and guide them through the
|
||||||
|
extension click. If no, everything keeps working on existing backends.
|
||||||
|
|
||||||
### Step 4: Coexistence (DO NOT uninstall old tools)
|
### Step 4: Coexistence (DO NOT uninstall old tools)
|
||||||
|
|
||||||
**IMPORTANT: Never uninstall any existing tools the user already has installed.** Old tools (bird, browser_cookie3, miku_ai, etc.) may still be working on the user's machine even if their upstream repos are archived or deleted. Agent Reach supports both old and new tools as fallback. Only install new tools alongside existing ones.
|
**Never uninstall tools the user already has.** Retired backends (e.g. yt-dlp
|
||||||
|
no longer serves Bilibili; xhs-cli is no longer installed by default) keep
|
||||||
|
working as fallbacks where they still function. Agent Reach routes around
|
||||||
|
them automatically — removal is the user's call, not yours.
|
||||||
|
|
||||||
### Step 5: Verify
|
### Step 5: Verify
|
||||||
|
|
||||||
@@ -82,51 +89,27 @@ agent-reach version
|
|||||||
agent-reach doctor
|
agent-reach doctor
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Running `agent-reach doctor` (text mode) also auto-syncs the bundled skill
|
||||||
|
(SKILL.md + references) into every detected agent skill directory — no
|
||||||
|
separate skill-update step is needed.
|
||||||
|
|
||||||
Check the doctor output:
|
Check the doctor output:
|
||||||
- All channels should show ✅ or ⚠️ (with clear instructions)
|
|
||||||
- If any channel that was working before now shows ❌, investigate:
|
|
||||||
- Twitter: needs `twitter-cli` + browser cookies (run `xhs login` pattern)
|
|
||||||
- Reddit: needs `rdt-cli` (should be installed in Step 3)
|
|
||||||
- XiaoHongShu: needs `xhs-cli` + login (run `xhs login`)
|
|
||||||
- WeChat: should work via Exa (zero config)
|
|
||||||
|
|
||||||
### Step 6: Update SKILL.md (if installed)
|
- Every channel shows ✅ / [!] with a clear message, and multi-backend
|
||||||
|
channels (小红书/Reddit/B站/Twitter) report `当前后端:…`
|
||||||
|
- If a previously-working channel now shows [X]/error, the message contains
|
||||||
|
the exact fix (e.g. a venv-reinstall prescription) — run it, then re-check
|
||||||
|
- `--json` gives the same data machine-readably (`active_backend` per channel)
|
||||||
|
|
||||||
```bash
|
### Step 6: Report to user
|
||||||
agent-reach install --skill-only 2>/dev/null || python3 -c "
|
|
||||||
import importlib.resources, os
|
|
||||||
try:
|
|
||||||
skill_pkg = importlib.resources.files('agent_reach').joinpath('skill')
|
|
||||||
except Exception:
|
|
||||||
from pathlib import Path
|
|
||||||
skill_pkg = Path(os.path.dirname(os.path.abspath(__file__))).parent / 'agent_reach' / 'skill'
|
|
||||||
|
|
||||||
skill_md = skill_pkg.joinpath('SKILL.md').read_text(encoding='utf-8')
|
|
||||||
refs_pkg = skill_pkg.joinpath('references')
|
|
||||||
|
|
||||||
for base in [os.path.expanduser('~/.openclaw/skills/agent-reach'),
|
|
||||||
os.path.expanduser('~/.claude/skills/agent-reach'),
|
|
||||||
os.path.expanduser('~/.agents/skills/agent-reach')]:
|
|
||||||
if os.path.isdir(base):
|
|
||||||
with open(os.path.join(base, 'SKILL.md'), 'w', encoding='utf-8') as f:
|
|
||||||
f.write(skill_md)
|
|
||||||
refs_dir = os.path.join(base, 'references')
|
|
||||||
os.makedirs(refs_dir, exist_ok=True)
|
|
||||||
for ref in refs_pkg.iterdir():
|
|
||||||
name = ref.name if hasattr(ref, 'name') else str(ref).split('/')[-1]
|
|
||||||
if name.endswith('.md'):
|
|
||||||
with open(os.path.join(refs_dir, name), 'w', encoding='utf-8') as f:
|
|
||||||
f.write(ref.read_text(encoding='utf-8'))
|
|
||||||
print(f'✅ Updated skill: {base}')
|
|
||||||
"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 7: Report to user
|
|
||||||
|
|
||||||
Tell the user:
|
Tell the user:
|
||||||
1. What version they're now on (`agent-reach version`)
|
|
||||||
2. How many channels are available (count ✅ in doctor output)
|
1. What version they're on now (`agent-reach version`)
|
||||||
3. Any channels that need their action (e.g., `xhs login` for XiaoHongShu, browser cookies for Twitter)
|
2. How many channels are available, and which backend each multi-backend
|
||||||
4. What changed in this update (major: Twitter/Reddit/XiaoHongShu upstream tools migrated for better stability)
|
platform is using (from doctor)
|
||||||
|
3. Anything that needs their action (e.g. Chrome extension click, `xhs login`,
|
||||||
|
QR scan for xiaohongshu-mcp on servers)
|
||||||
|
4. What changed in this update (release notes shown by `check-update`)
|
||||||
|
|
||||||
Done.
|
Done.
|
||||||
|
|||||||
@@ -183,3 +183,19 @@ class TestCheckUpdateRetry:
|
|||||||
assert result == "error"
|
assert result == "error"
|
||||||
assert "网络超时" in captured.out
|
assert "网络超时" in captured.out
|
||||||
assert "已重试 3 次" in captured.out
|
assert "已重试 3 次" in captured.out
|
||||||
|
|
||||||
|
|
||||||
|
class TestVersionCompare:
|
||||||
|
def test_newer_remote_triggers_update(self):
|
||||||
|
assert cli._is_newer_version("1.5.0", "1.4.2") is True
|
||||||
|
|
||||||
|
def test_equal_versions_no_update(self):
|
||||||
|
assert cli._is_newer_version("1.5.0", "1.5.0") is False
|
||||||
|
|
||||||
|
def test_local_ahead_of_release_no_downgrade_prompt(self):
|
||||||
|
"""发版窗口期本地装了 main(更新)时,不能提示"有更新"诱导降级。"""
|
||||||
|
assert cli._is_newer_version("1.4.2", "1.5.0") is False
|
||||||
|
|
||||||
|
def test_unparseable_falls_back_to_inequality(self):
|
||||||
|
assert cli._is_newer_version("2026.06-beta", "1.5.0") is True
|
||||||
|
assert cli._is_newer_version("1.5.0", "1.5.0-dev") is True
|
||||||
|
|||||||
Reference in New Issue
Block a user