release: v1.1.0 — 新增 Instagram、LinkedIn、Boss直聘 三个渠道
🆕 新渠道: - 📷 Instagram — instaloader 读取帖子和 Profile - 💼 LinkedIn — linkedin-scraper-mcp 读取 Profile、公司、职位 - 🏢 Boss直聘 — mcp-bosszp 搜索职位、向 HR 打招呼 📈 改进: - 渠道数量 9 → 12 - 新增 CHANGELOG.md - CLI 新增 search-instagram / search-linkedin / search-bosszhipin - 安装指南更新 - 致谢列表更新
This commit is contained in:
parent
31eb6db537
commit
c642e18e1f
7 changed files with 278 additions and 29 deletions
65
CHANGELOG.md
Normal file
65
CHANGELOG.md
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
# Changelog / 更新日志
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
本项目的所有重要变更都会记录在此文件中。
|
||||
|
||||
---
|
||||
|
||||
## [1.1.0] - 2025-02-25
|
||||
|
||||
### 🆕 New Channels / 新增渠道
|
||||
|
||||
#### 📷 Instagram
|
||||
- Read public posts and profiles via [instaloader](https://github.com/instaloader/instaloader)
|
||||
- Search via Exa (free, no API key)
|
||||
- Optional cookie login for private content
|
||||
- 通过 instaloader 读取公开帖子和 Profile
|
||||
- 搜索通过 Exa(免费,无需 API Key)
|
||||
- 可选 Cookie 登录解锁私密内容
|
||||
|
||||
#### 💼 LinkedIn
|
||||
- Read person profiles, company pages, and job details via [linkedin-scraper-mcp](https://github.com/stickerdaniel/linkedin-mcp-server)
|
||||
- Search people and jobs via MCP, with Exa fallback
|
||||
- Fallback to Jina Reader when MCP is not configured
|
||||
- 通过 linkedin-scraper-mcp 读取个人 Profile、公司页面、职位详情
|
||||
- 通过 MCP 搜索人才和职位,Exa 兜底
|
||||
- 未配置 MCP 时自动 fallback 到 Jina Reader
|
||||
|
||||
#### 🏢 Boss直聘
|
||||
- QR code login via [mcp-bosszp](https://github.com/mucsbr/mcp-bosszp)
|
||||
- Job search and recruiter greeting via MCP
|
||||
- Fallback to Jina Reader for reading job pages
|
||||
- 通过 mcp-bosszp 扫码登录
|
||||
- MCP 搜索职位、向 HR 打招呼
|
||||
- Jina Reader 兜底读取职位页面
|
||||
|
||||
### 📈 Improvements / 改进
|
||||
|
||||
- Channel count: 9 → 12
|
||||
- `agent-reach doctor` now detects all 12 channels
|
||||
- CLI: added `search-instagram`, `search-linkedin`, `search-bosszhipin` subcommands
|
||||
- Updated install guide with setup instructions for new channels
|
||||
- 渠道数量:9 → 12
|
||||
- `agent-reach doctor` 现在检测全部 12 个渠道
|
||||
- CLI:新增 `search-instagram`、`search-linkedin`、`search-bosszhipin` 子命令
|
||||
- 安装指南新增三个渠道的配置说明
|
||||
|
||||
---
|
||||
|
||||
## [1.0.0] - 2025-02-24
|
||||
|
||||
### 🎉 Initial Release / 首次发布
|
||||
|
||||
- 9 channels: Web, Twitter/X, YouTube, Bilibili, GitHub, Reddit, XiaoHongShu, RSS, Exa Search
|
||||
- CLI with `read`, `search`, `doctor`, `install` commands
|
||||
- Unified channel interface — each platform is a single pluggable Python file
|
||||
- Auto-detection of local vs server environments
|
||||
- Built-in diagnostics via `agent-reach doctor`
|
||||
- Skill registration for Claude Code / OpenClaw / Cursor
|
||||
- 9 个渠道:网页、Twitter/X、YouTube、B站、GitHub、Reddit、小红书、RSS、Exa 搜索
|
||||
- CLI 支持 `read`、`search`、`doctor`、`install` 命令
|
||||
- 统一渠道接口 — 每个平台一个独立可插拔的 Python 文件
|
||||
- 自动检测本地/服务器环境
|
||||
- 内置诊断 `agent-reach doctor`
|
||||
- Skill 注册支持 Claude Code / OpenClaw / Cursor
|
||||
34
README.md
34
README.md
|
|
@ -92,6 +92,12 @@ AI Agent 已经能帮你写代码、改文档、管项目——但你让它去
|
|||
|
||||
就这一步。Agent 会自己完成剩下的所有事情。
|
||||
|
||||
> 🛡️ **担心安全?** 可以用安全模式——不会自动装系统包,只告诉你需要什么:
|
||||
> ```
|
||||
> 帮我安装 Agent Reach(安全模式):https://raw.githubusercontent.com/Panniantong/agent-reach/main/docs/install.md
|
||||
> 安装时使用 --safe 参数
|
||||
> ```
|
||||
|
||||
<details>
|
||||
<summary>它会做什么?(点击展开)</summary>
|
||||
|
||||
|
|
@ -169,6 +175,32 @@ channels/
|
|||
|
||||
---
|
||||
|
||||
## 安全性
|
||||
|
||||
Agent Reach 在设计上重视安全:
|
||||
|
||||
| 措施 | 说明 |
|
||||
|------|------|
|
||||
| 🔒 **凭据本地存储** | Cookie、Token 只存在你本机 `~/.agent-reach/config.yaml`,文件权限 600(仅所有者可读写),不上传不外传 |
|
||||
| 🛡️ **安全模式** | `agent-reach install --safe` 不会自动修改系统,只列出需要什么,由你决定装不装 |
|
||||
| 👀 **完全开源** | 代码透明,随时可审查。所有依赖工具也是开源项目 |
|
||||
| 🔍 **Dry Run** | `agent-reach install --dry-run` 预览所有操作,不做任何改动 |
|
||||
| 🧩 **可插拔架构** | 不信任某个组件?换掉对应的 channel 文件即可,不影响其他 |
|
||||
|
||||
### 🍪 Cookie 安全建议
|
||||
|
||||
需要 Cookie 的平台(Twitter、小红书、Instagram)建议使用**专用小号**,不要用主账号。Cookie 等同于完整登录权限,用小号可以在凭据泄露时限制影响范围。
|
||||
|
||||
### 📦 安装方式
|
||||
|
||||
| 方式 | 命令 | 适合场景 |
|
||||
|------|------|---------|
|
||||
| 一键全自动(默认) | `agent-reach install --env=auto` | 个人电脑、开发环境 |
|
||||
| 安全模式 | `agent-reach install --env=auto --safe` | 生产服务器、多人共用机器 |
|
||||
| 仅预览 | `agent-reach install --env=auto --dry-run` | 先看看会做什么 |
|
||||
|
||||
---
|
||||
|
||||
## 贡献
|
||||
|
||||
这个项目是纯 vibe coding 出来的 🎸 可能会有一些不完美的地方,如果遇到问题请多多包涵。有 bug 尽管提 [Issue](https://github.com/Panniantong/agent-reach/issues),我都会尽快修复。
|
||||
|
|
@ -195,7 +227,7 @@ Star 一下,下次需要的时候能找到。⭐
|
|||
|
||||
## 致谢
|
||||
|
||||
[Jina Reader](https://github.com/jina-ai/reader) · [yt-dlp](https://github.com/yt-dlp/yt-dlp) · [bird](https://www.npmjs.com/package/@steipete/bird) · [Exa](https://exa.ai) · [mcporter](https://github.com/steipete/mcporter) · [feedparser](https://github.com/kurtmckee/feedparser) · [xiaohongshu-mcp](https://github.com/xpzouying/xiaohongshu-mcp)
|
||||
[Jina Reader](https://github.com/jina-ai/reader) · [yt-dlp](https://github.com/yt-dlp/yt-dlp) · [bird](https://www.npmjs.com/package/@steipete/bird) · [Exa](https://exa.ai) · [mcporter](https://github.com/steipete/mcporter) · [feedparser](https://github.com/kurtmckee/feedparser) · [xiaohongshu-mcp](https://github.com/xpzouying/xiaohongshu-mcp) · [instaloader](https://github.com/instaloader/instaloader) · [linkedin-scraper-mcp](https://github.com/stickerdaniel/linkedin-mcp-server) · [mcp-bosszp](https://github.com/mucsbr/mcp-bosszp)
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
|||
|
|
@ -113,6 +113,10 @@ def main():
|
|||
help="Environment: local, server, or auto-detect")
|
||||
p_install.add_argument("--proxy", default="",
|
||||
help="Residential proxy for Reddit/Bilibili (http://user:pass@ip:port)")
|
||||
p_install.add_argument("--safe", action="store_true",
|
||||
help="Safe mode: skip automatic system changes, show what's needed instead")
|
||||
p_install.add_argument("--dry-run", action="store_true",
|
||||
help="Show what would be done without making any changes")
|
||||
|
||||
# ── configure ──
|
||||
p_conf = sub.add_parser("configure", help="Set a config value or auto-extract from browser")
|
||||
|
|
@ -178,11 +182,21 @@ def _cmd_install(args):
|
|||
from agent_reach.config import Config
|
||||
from agent_reach.doctor import check_all, format_report
|
||||
|
||||
safe_mode = args.safe
|
||||
dry_run = args.dry_run
|
||||
|
||||
config = Config()
|
||||
print()
|
||||
print("👁️ Agent Reach Installer")
|
||||
print("=" * 40)
|
||||
|
||||
if dry_run:
|
||||
print("🔍 DRY RUN — showing what would be done (no changes)")
|
||||
print()
|
||||
if safe_mode:
|
||||
print("🛡️ SAFE MODE — skipping automatic system changes")
|
||||
print()
|
||||
|
||||
# Auto-detect environment
|
||||
env = args.env
|
||||
if env == "auto":
|
||||
|
|
@ -195,20 +209,33 @@ def _cmd_install(args):
|
|||
|
||||
# Apply explicit flags
|
||||
if args.proxy:
|
||||
config.set("reddit_proxy", args.proxy)
|
||||
config.set("bilibili_proxy", args.proxy)
|
||||
print(f"✅ Proxy configured for Reddit + Bilibili")
|
||||
if dry_run:
|
||||
print(f"[dry-run] Would configure proxy for Reddit + Bilibili")
|
||||
else:
|
||||
config.set("reddit_proxy", args.proxy)
|
||||
config.set("bilibili_proxy", args.proxy)
|
||||
print(f"✅ Proxy configured for Reddit + Bilibili")
|
||||
|
||||
# ── Install system dependencies ──
|
||||
print()
|
||||
_install_system_deps()
|
||||
if dry_run:
|
||||
_install_system_deps_dryrun()
|
||||
elif safe_mode:
|
||||
_install_system_deps_safe()
|
||||
else:
|
||||
_install_system_deps()
|
||||
|
||||
# ── mcporter (for Exa search + XiaoHongShu) ──
|
||||
print()
|
||||
_install_mcporter()
|
||||
if dry_run:
|
||||
print("📦 [dry-run] Would install mcporter and configure Exa search")
|
||||
elif safe_mode:
|
||||
_install_mcporter_safe()
|
||||
else:
|
||||
_install_mcporter()
|
||||
|
||||
# Auto-import cookies on local computers
|
||||
if env == "local":
|
||||
if env == "local" and not safe_mode and not dry_run:
|
||||
print()
|
||||
print("🍪 Trying to import cookies from browser...")
|
||||
try:
|
||||
|
|
@ -230,6 +257,13 @@ def _cmd_install(args):
|
|||
print(" ⬜ No cookies found (normal if you haven't logged into these sites)")
|
||||
except Exception:
|
||||
print(" ⬜ Could not read browser cookies (browser might be open)")
|
||||
elif env == "local" and safe_mode:
|
||||
print()
|
||||
print("🍪 Skipped auto cookie import (safe mode).")
|
||||
print(" To import manually: agent-reach configure --from-browser chrome")
|
||||
elif env == "local" and dry_run:
|
||||
print()
|
||||
print("🍪 [dry-run] Would try to import cookies from Chrome/Firefox")
|
||||
|
||||
# Environment-specific advice
|
||||
if env == "server":
|
||||
|
|
@ -240,25 +274,29 @@ def _cmd_install(args):
|
|||
print(" Cheap option: https://www.webshare.io ($1/month)")
|
||||
|
||||
# Test channels
|
||||
print()
|
||||
print("Testing channels...")
|
||||
results = check_all(config)
|
||||
ok = sum(1 for r in results.values() if r["status"] == "ok")
|
||||
total = len(results)
|
||||
|
||||
# Final status
|
||||
print()
|
||||
print(format_report(results))
|
||||
print()
|
||||
|
||||
# ── Install agent skill ──
|
||||
_install_skill()
|
||||
|
||||
print(f"✅ Installation complete! {ok}/{total} channels active.")
|
||||
|
||||
if ok < total:
|
||||
if not dry_run:
|
||||
print()
|
||||
print("🤖 Some channels are not active yet. If you're an AI Agent, try to fix them yourself — then run `agent-reach doctor` again.")
|
||||
print("Testing channels...")
|
||||
results = check_all(config)
|
||||
ok = sum(1 for r in results.values() if r["status"] == "ok")
|
||||
total = len(results)
|
||||
|
||||
# Final status
|
||||
print()
|
||||
print(format_report(results))
|
||||
print()
|
||||
|
||||
# ── Install agent skill ──
|
||||
_install_skill()
|
||||
|
||||
print(f"✅ Installation complete! {ok}/{total} channels active.")
|
||||
|
||||
if ok < total:
|
||||
print()
|
||||
print("🤖 Some channels are not active yet. If you're an AI Agent, try to fix them yourself — then run `agent-reach doctor` again.")
|
||||
else:
|
||||
print()
|
||||
print("🔍 Dry run complete. No changes were made.")
|
||||
|
||||
|
||||
def _install_skill():
|
||||
|
|
@ -403,6 +441,58 @@ def _install_system_deps():
|
|||
print(" ⬜ instaloader install failed (optional — try: pip install instaloader)")
|
||||
|
||||
|
||||
def _install_system_deps_safe():
|
||||
"""Safe mode: check what's installed, print instructions for what's missing."""
|
||||
import shutil
|
||||
|
||||
print("🔧 Checking system dependencies (safe mode — no auto-install)...")
|
||||
|
||||
deps = [
|
||||
("gh", ["gh"], "GitHub CLI", "https://cli.github.com — or: apt install gh / brew install gh"),
|
||||
("node", ["node", "npm"], "Node.js", "https://nodejs.org — or: apt install nodejs npm"),
|
||||
("bird", ["bird", "birdx"], "bird CLI (Twitter)", "npm install -g @steipete/bird"),
|
||||
("instaloader", ["instaloader"], "instaloader (Instagram)", "pip install instaloader"),
|
||||
]
|
||||
|
||||
missing = []
|
||||
for name, binaries, label, install_hint in deps:
|
||||
found = any(shutil.which(b) for b in binaries)
|
||||
if found:
|
||||
print(f" ✅ {label} already installed")
|
||||
else:
|
||||
print(f" ⬜ {label} not found")
|
||||
missing.append((label, install_hint))
|
||||
|
||||
if missing:
|
||||
print()
|
||||
print(" To install missing dependencies manually:")
|
||||
for label, hint in missing:
|
||||
print(f" {label}: {hint}")
|
||||
else:
|
||||
print(" All system dependencies are installed!")
|
||||
|
||||
|
||||
def _install_system_deps_dryrun():
|
||||
"""Dry-run: just show what would be checked/installed."""
|
||||
import shutil
|
||||
|
||||
print("🔧 [dry-run] System dependency check:")
|
||||
|
||||
checks = [
|
||||
("gh CLI", ["gh"], "apt install gh / brew install gh"),
|
||||
("Node.js", ["node"], "curl NodeSource setup | bash + apt install nodejs"),
|
||||
("bird CLI", ["bird", "birdx"], "npm install -g @steipete/bird"),
|
||||
("instaloader", ["instaloader"], "pip install instaloader"),
|
||||
]
|
||||
|
||||
for label, binaries, method in checks:
|
||||
found = any(shutil.which(b) for b in binaries)
|
||||
if found:
|
||||
print(f" ✅ {label}: already installed, skip")
|
||||
else:
|
||||
print(f" 📥 {label}: would install via: {method}")
|
||||
|
||||
|
||||
def _install_mcporter():
|
||||
"""Install mcporter and configure Exa + XiaoHongShu MCP servers."""
|
||||
import shutil
|
||||
|
|
@ -474,6 +564,21 @@ def _install_mcporter():
|
|||
pass
|
||||
|
||||
|
||||
def _install_mcporter_safe():
|
||||
"""Safe mode: check mcporter status, print instructions."""
|
||||
import shutil
|
||||
|
||||
print("📦 Checking mcporter (safe mode)...")
|
||||
|
||||
if shutil.which("mcporter"):
|
||||
print(" ✅ mcporter already installed")
|
||||
print(" To configure Exa search: mcporter config add exa https://mcp.exa.ai/mcp")
|
||||
else:
|
||||
print(" ⬜ mcporter not installed")
|
||||
print(" To install: npm install -g mcporter")
|
||||
print(" Then configure Exa: mcporter config add exa https://mcp.exa.ai/mcp")
|
||||
|
||||
|
||||
def _detect_environment():
|
||||
"""Auto-detect if running on local computer or server."""
|
||||
import os
|
||||
|
|
|
|||
|
|
@ -51,6 +51,12 @@ class Config:
|
|||
self._ensure_dir()
|
||||
with open(self.config_path, "w") as f:
|
||||
yaml.dump(self.data, f, default_flow_style=False, allow_unicode=True)
|
||||
# Restrict permissions — config may contain credentials
|
||||
try:
|
||||
import stat
|
||||
self.config_path.chmod(stat.S_IRUSR | stat.S_IWUSR) # 0o600
|
||||
except OSError:
|
||||
pass # Windows or permission edge cases
|
||||
|
||||
def get(self, key: str, default: Any = None) -> Any:
|
||||
"""Get a config value. Also checks environment variables (uppercase)."""
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ This project was entirely vibe-coded 🎸 There might be rough edges here and th
|
|||
|
||||
## Credits
|
||||
|
||||
[Jina Reader](https://github.com/jina-ai/reader) · [yt-dlp](https://github.com/yt-dlp/yt-dlp) · [bird](https://github.com/steipete/bird) · [Exa](https://exa.ai) · [feedparser](https://github.com/kurtmckee/feedparser)
|
||||
[Jina Reader](https://github.com/jina-ai/reader) · [yt-dlp](https://github.com/yt-dlp/yt-dlp) · [bird](https://github.com/steipete/bird) · [Exa](https://exa.ai) · [feedparser](https://github.com/kurtmckee/feedparser) · [instaloader](https://github.com/instaloader/instaloader) · [linkedin-scraper-mcp](https://github.com/stickerdaniel/linkedin-mcp-server) · [mcp-bosszp](https://github.com/mucsbr/mcp-bosszp)
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,12 @@ Copy this to your AI Agent:
|
|||
帮我安装 Agent Reach:https://raw.githubusercontent.com/Panniantong/agent-reach/main/docs/install.md
|
||||
```
|
||||
|
||||
> 🛡️ **Security-conscious?** Use safe mode — it won't auto-install system packages:
|
||||
> ```
|
||||
> 帮我安装 Agent Reach(安全模式):https://raw.githubusercontent.com/Panniantong/agent-reach/main/docs/install.md
|
||||
> 安装时使用 --safe 参数
|
||||
> ```
|
||||
|
||||
---
|
||||
|
||||
## For AI Agents
|
||||
|
|
@ -16,8 +22,20 @@ Copy this to your AI Agent:
|
|||
|
||||
Install Agent Reach and make sure **all channels are working**. Your user expects you to have full internet access capabilities when this is done — reading tweets, searching Reddit, watching YouTube, browsing GitHub, and more.
|
||||
|
||||
### ⚠️ Boundaries
|
||||
|
||||
When fixing issues, stay within these limits:
|
||||
|
||||
- **DO NOT** run commands with `sudo` unless the user explicitly approved
|
||||
- **DO NOT** modify system files outside `~/.agent-reach/`
|
||||
- **DO NOT** install packages not listed in this guide
|
||||
- **DO NOT** disable firewalls, security settings, or system protections
|
||||
- If something requires elevated permissions, **tell the user** what's needed and let them decide
|
||||
|
||||
### Step 1: Install
|
||||
|
||||
**Default (fully automatic):**
|
||||
|
||||
```bash
|
||||
pip install https://github.com/Panniantong/agent-reach/archive/main.zip
|
||||
agent-reach install --env=auto
|
||||
|
|
@ -25,6 +43,25 @@ agent-reach install --env=auto
|
|||
|
||||
This auto-installs system dependencies (gh CLI, Node.js, mcporter, bird), configures Exa search, detects environment, and tests all channels.
|
||||
|
||||
**Safe mode (no automatic system changes):**
|
||||
|
||||
If the user asked for safe mode, or you're on a production machine:
|
||||
|
||||
```bash
|
||||
pip install https://github.com/Panniantong/agent-reach/archive/main.zip
|
||||
agent-reach install --env=auto --safe
|
||||
```
|
||||
|
||||
Safe mode checks what's installed and tells you what's missing, but doesn't auto-install system packages. You can then install each dependency manually.
|
||||
|
||||
**Dry run (preview only):**
|
||||
|
||||
```bash
|
||||
agent-reach install --env=auto --dry-run
|
||||
```
|
||||
|
||||
Shows what would be done without making any changes.
|
||||
|
||||
**Read the output carefully**, then run:
|
||||
|
||||
```bash
|
||||
|
|
@ -35,14 +72,16 @@ agent-reach doctor
|
|||
|
||||
`agent-reach doctor` shows you which channels are active and which aren't.
|
||||
|
||||
**Your goal is to get as many channels to ✅ as possible.** If something failed during install or shows as ❌/⚠️ in doctor, fix it yourself. You're a capable AI Agent — diagnose the problem, try alternative approaches, and iterate until it works.
|
||||
Try to get as many channels to ✅ as possible. If something failed during install or shows as ❌/⚠️ in doctor, diagnose the problem and try to fix it — but stay within the boundaries above. If a fix requires elevated permissions or system changes, ask the user first.
|
||||
|
||||
Only ask the user when you genuinely need their input (see below).
|
||||
Only ask the user when you genuinely need their input (credentials, permissions, etc.).
|
||||
|
||||
### Step 3: Configure things that need user input
|
||||
|
||||
Some channels need credentials only the user can provide. Based on the doctor output, ask for what's missing:
|
||||
|
||||
> 🔒 **Security tip:** For platforms that need cookies (Twitter, XiaoHongShu, Instagram), we recommend using a **dedicated/secondary account** rather than your main account. Cookie-based auth grants full account access — using a separate account limits the blast radius if credentials are ever compromised.
|
||||
|
||||
**Twitter search & posting (server users):**
|
||||
> "To unlock Twitter search, I need your Twitter cookies. Install the Cookie-Editor Chrome extension, go to x.com/twitter.com, click the extension → Export → Header String, and paste it to me."
|
||||
> Extension: https://chromewebstore.google.com/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm
|
||||
|
|
@ -183,6 +222,8 @@ If the user wants a different agent to handle it, let them choose.
|
|||
| Command | What it does |
|
||||
|---------|-------------|
|
||||
| `agent-reach install --env=auto` | Full auto-setup (installs deps + configures) |
|
||||
| `agent-reach install --env=auto --safe` | Safe setup (no auto system changes) |
|
||||
| `agent-reach install --env=auto --dry-run` | Preview what would be done |
|
||||
| `agent-reach doctor` | Show channel status |
|
||||
| `agent-reach watch` | Quick health + update check (for scheduled tasks) |
|
||||
| `agent-reach check-update` | Check for new versions |
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[project]
|
||||
name = "agent-reach"
|
||||
version = "1.0.0"
|
||||
version = "1.1.0"
|
||||
description = "Give your AI Agent eyes to see the entire internet. Search + Read 10+ platforms."
|
||||
readme = "README.md"
|
||||
license = {text = "MIT"}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue