feat: deterministic install & configure commands
New commands: - agent-eyes install --env=<local|server> --search=<yes|no> [--proxy=URL] [--exa-key=KEY] One-shot installer with explicit flags. No ambiguity. - agent-eyes configure <key> <value> Set exa-key/proxy/github-token/groq-key with auto-testing. e.g. 'agent-eyes configure exa-key xxx' → saves + tests API Rewrote install.md as strict decision tree: 1. Ask 3 questions → get flags 2. pip install 3. Run ONE install command with flags 4. Configure keys with configure command (auto-tests each) 5. Verify with doctor Inspired by oh-my-opencode's deterministic installer pattern.
This commit is contained in:
@@ -68,6 +68,23 @@ def main():
|
|||||||
# ── setup ──
|
# ── setup ──
|
||||||
sub.add_parser("setup", help="Interactive configuration wizard")
|
sub.add_parser("setup", help="Interactive configuration wizard")
|
||||||
|
|
||||||
|
# ── install ──
|
||||||
|
p_install = sub.add_parser("install", help="One-shot installer with flags")
|
||||||
|
p_install.add_argument("--env", choices=["local", "server"], default="local",
|
||||||
|
help="Environment: local computer or server/VPS")
|
||||||
|
p_install.add_argument("--search", choices=["yes", "no"], default="yes",
|
||||||
|
help="Enable web search (needs free Exa API key)")
|
||||||
|
p_install.add_argument("--proxy", default="",
|
||||||
|
help="Residential proxy for Reddit/Bilibili (http://user:pass@ip:port)")
|
||||||
|
p_install.add_argument("--exa-key", default="",
|
||||||
|
help="Exa API key (get free at https://exa.ai)")
|
||||||
|
|
||||||
|
# ── configure ──
|
||||||
|
p_conf = sub.add_parser("configure", help="Set a config value")
|
||||||
|
p_conf.add_argument("key", choices=["exa-key", "proxy", "github-token", "groq-key"],
|
||||||
|
help="What to configure")
|
||||||
|
p_conf.add_argument("value", help="The value to set")
|
||||||
|
|
||||||
# ── doctor ──
|
# ── doctor ──
|
||||||
sub.add_parser("doctor", help="Check platform availability")
|
sub.add_parser("doctor", help="Check platform availability")
|
||||||
|
|
||||||
@@ -91,6 +108,10 @@ def main():
|
|||||||
_cmd_doctor()
|
_cmd_doctor()
|
||||||
elif args.command == "setup":
|
elif args.command == "setup":
|
||||||
_cmd_setup()
|
_cmd_setup()
|
||||||
|
elif args.command == "install":
|
||||||
|
_cmd_install(args)
|
||||||
|
elif args.command == "configure":
|
||||||
|
_cmd_configure(args)
|
||||||
elif args.command == "read":
|
elif args.command == "read":
|
||||||
asyncio.run(_cmd_read(args))
|
asyncio.run(_cmd_read(args))
|
||||||
elif args.command.startswith("search"):
|
elif args.command.startswith("search"):
|
||||||
@@ -100,6 +121,116 @@ def main():
|
|||||||
# ── Command handlers ────────────────────────────────
|
# ── Command handlers ────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
|
def _cmd_install(args):
|
||||||
|
"""One-shot deterministic installer."""
|
||||||
|
from agent_eyes.config import Config
|
||||||
|
from agent_eyes.doctor import check_all, format_report
|
||||||
|
|
||||||
|
config = Config()
|
||||||
|
print()
|
||||||
|
print("👁️ Agent Eyes Installer")
|
||||||
|
print("=" * 40)
|
||||||
|
|
||||||
|
# Apply flags
|
||||||
|
if args.exa_key:
|
||||||
|
config.set("exa_api_key", args.exa_key)
|
||||||
|
print(f"✅ Exa search key configured")
|
||||||
|
|
||||||
|
if args.proxy:
|
||||||
|
config.set("reddit_proxy", args.proxy)
|
||||||
|
config.set("bilibili_proxy", args.proxy)
|
||||||
|
print(f"✅ Proxy configured for Reddit + Bilibili")
|
||||||
|
|
||||||
|
# Environment-specific advice
|
||||||
|
if args.env == "server":
|
||||||
|
print(f"📡 Environment: Server/VPS")
|
||||||
|
if not args.proxy:
|
||||||
|
print(f"⚠️ Reddit and Bilibili block server IPs.")
|
||||||
|
print(f" To unlock: agent-eyes configure proxy http://user:pass@ip:port")
|
||||||
|
print(f" Recommend: https://www.webshare.io ($1/month)")
|
||||||
|
else:
|
||||||
|
print(f"💻 Environment: Local computer")
|
||||||
|
|
||||||
|
# Test zero-config features
|
||||||
|
print()
|
||||||
|
print("Testing channels...")
|
||||||
|
results = check_all(config)
|
||||||
|
ok = sum(1 for r in results.values() if r["status"] == "ok")
|
||||||
|
total = len(results)
|
||||||
|
print(f"✅ {ok}/{total} channels active")
|
||||||
|
|
||||||
|
# What's missing
|
||||||
|
if args.search == "yes" and not args.exa_key:
|
||||||
|
print()
|
||||||
|
print("🔍 Search not yet configured. Run:")
|
||||||
|
print(" agent-eyes configure exa-key YOUR_KEY")
|
||||||
|
print(" (Get free key: https://exa.ai)")
|
||||||
|
|
||||||
|
# Final status
|
||||||
|
print()
|
||||||
|
print(format_report(results))
|
||||||
|
print()
|
||||||
|
print("✅ Installation complete!")
|
||||||
|
if ok < total:
|
||||||
|
print(f" Run `agent-eyes configure` to unlock remaining channels.")
|
||||||
|
|
||||||
|
|
||||||
|
def _cmd_configure(args):
|
||||||
|
"""Set a config value and test it."""
|
||||||
|
from agent_eyes.config import Config
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
config = Config()
|
||||||
|
|
||||||
|
key_map = {
|
||||||
|
"exa-key": "exa_api_key",
|
||||||
|
"proxy": ("reddit_proxy", "bilibili_proxy"),
|
||||||
|
"github-token": "github_token",
|
||||||
|
"groq-key": "groq_api_key",
|
||||||
|
}
|
||||||
|
|
||||||
|
config_key = key_map.get(args.key)
|
||||||
|
if isinstance(config_key, tuple):
|
||||||
|
for k in config_key:
|
||||||
|
config.set(k, args.value)
|
||||||
|
else:
|
||||||
|
config.set(config_key, args.value)
|
||||||
|
|
||||||
|
print(f"✅ {args.key} configured!")
|
||||||
|
|
||||||
|
# Auto-test
|
||||||
|
if args.key == "exa-key":
|
||||||
|
print("Testing search...", end=" ")
|
||||||
|
try:
|
||||||
|
import asyncio
|
||||||
|
from agent_eyes.core import AgentEyes
|
||||||
|
eyes = AgentEyes(config)
|
||||||
|
results = asyncio.run(eyes.search("test", num_results=1))
|
||||||
|
if results:
|
||||||
|
print("✅ Search works!")
|
||||||
|
else:
|
||||||
|
print("⚠️ No results, but API connected.")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Failed: {e}")
|
||||||
|
|
||||||
|
elif args.key == "proxy":
|
||||||
|
print("Testing Reddit access...", end=" ")
|
||||||
|
try:
|
||||||
|
import requests
|
||||||
|
resp = requests.get(
|
||||||
|
"https://www.reddit.com/r/test.json?limit=1",
|
||||||
|
headers={"User-Agent": "Mozilla/5.0"},
|
||||||
|
proxies={"http": args.value, "https": args.value},
|
||||||
|
timeout=10,
|
||||||
|
)
|
||||||
|
if resp.status_code == 200:
|
||||||
|
print("✅ Reddit accessible!")
|
||||||
|
else:
|
||||||
|
print(f"❌ Reddit returned {resp.status_code}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Failed: {e}")
|
||||||
|
|
||||||
|
|
||||||
def _cmd_doctor():
|
def _cmd_doctor():
|
||||||
from agent_eyes.config import Config
|
from agent_eyes.config import Config
|
||||||
from agent_eyes.doctor import check_all, format_report
|
from agent_eyes.doctor import check_all, format_report
|
||||||
|
|||||||
+80
-202
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## For Humans
|
## For Humans
|
||||||
|
|
||||||
Copy and paste this to your AI Agent (Claude Code, OpenClaw, Cursor, ChatGPT, etc.):
|
Copy and paste this to your AI Agent (Claude Code, OpenClaw, Cursor, etc.):
|
||||||
|
|
||||||
```
|
```
|
||||||
Install and configure Agent Eyes by following the instructions here:
|
Install and configure Agent Eyes by following the instructions here:
|
||||||
@@ -15,235 +15,113 @@ That's it. Your Agent will handle the rest.
|
|||||||
|
|
||||||
## For AI Agents
|
## For AI Agents
|
||||||
|
|
||||||
Welcome! You're about to give your user's Agent (that's you!) eyes to see the entire internet.
|
You are installing Agent Eyes — a tool that gives you (the Agent) eyes to see the entire internet.
|
||||||
Agent Eyes lets you search and read content across 10+ platforms with one install.
|
Follow this decision tree exactly. Do not skip steps.
|
||||||
|
|
||||||
### Step 0: Ask About Environment
|
### Step 1: Ask user 3 questions
|
||||||
|
|
||||||
Before installing, ask the user ONE question:
|
Ask the user these questions to determine install flags:
|
||||||
|
|
||||||
> "你是在自己的电脑上用,还是在服务器上用?(Are you running on your local computer or a server?)"
|
**Q1: Are you on a local computer or a server/VPS?**
|
||||||
|
- Local → `--env=local`
|
||||||
|
- Server/VPS → `--env=server`
|
||||||
|
|
||||||
**Why this matters:**
|
**Q2: Do you want web search? (free, recommended)**
|
||||||
- **Local computer** → Everything works out of the box. No extra setup needed.
|
- Yes → `--search=yes`
|
||||||
- **Server (VPS/cloud)** → Most things work fine, but **Reddit and Bilibili** block server IPs. They'll need a cheap residential proxy ($1/month) to access these two platforms. This is optional — everything else works without it.
|
- No → `--search=no`
|
||||||
|
|
||||||
Remember their answer for Step 5.
|
**Q3: (Only if server) Do you have a residential proxy for Reddit/Bilibili?**
|
||||||
|
- Yes → `--proxy=http://user:pass@ip:port` (ask user for the proxy URL)
|
||||||
|
- No / Don't know → omit `--proxy`
|
||||||
|
- Tell user: "Reddit and Bilibili block server IPs. You can get a proxy at https://www.webshare.io for $1/month. Want to set it up later?"
|
||||||
|
|
||||||
### Step 1: Install Agent Eyes
|
### Step 2: Install
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install git+https://github.com/Panniantong/agent-eyes.git
|
pip install git+https://github.com/Panniantong/agent-eyes.git
|
||||||
```
|
```
|
||||||
|
|
||||||
If `pip` fails, try:
|
If fails, try `pip3` or add `--user`.
|
||||||
```bash
|
|
||||||
pip3 install git+https://github.com/Panniantong/agent-eyes.git
|
|
||||||
```
|
|
||||||
|
|
||||||
If permission error, try:
|
### Step 3: Run installer with flags
|
||||||
```bash
|
|
||||||
pip install --user git+https://github.com/Panniantong/agent-eyes.git
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 2: Verify Installation
|
Based on answers from Step 1, construct and run ONE command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
agent-eyes version
|
agent-eyes install --env=<local|server> --search=<yes|no> [--proxy=<proxy_url>]
|
||||||
```
|
```
|
||||||
|
|
||||||
Expected output: `Agent Eyes v1.0.0` (or higher)
|
**Examples:**
|
||||||
|
- Local, wants search: `agent-eyes install --env=local --search=yes`
|
||||||
|
- Server, wants search, has proxy: `agent-eyes install --env=server --search=yes --proxy=http://user:pass@ip:port`
|
||||||
|
- Server, wants search, no proxy: `agent-eyes install --env=server --search=yes`
|
||||||
|
- Local, no search: `agent-eyes install --env=local --search=no`
|
||||||
|
|
||||||
If this works, run a health check:
|
### Step 4: Configure Exa key (only if --search=yes)
|
||||||
|
|
||||||
|
The installer will tell you search needs a key. Ask the user:
|
||||||
|
|
||||||
|
> "Web search needs a free API key. Go to https://exa.ai, sign up, copy your API Key, and send it to me."
|
||||||
|
|
||||||
|
When user provides the key, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
agent-eyes configure exa-key THE_KEY_USER_PROVIDED
|
||||||
|
```
|
||||||
|
|
||||||
|
This automatically tests the key and confirms it works.
|
||||||
|
|
||||||
|
### Step 5: Configure proxy (only if --env=server and user wants Reddit/Bilibili)
|
||||||
|
|
||||||
|
If the user wants to set up a proxy (now or later), they need to:
|
||||||
|
1. Go to https://www.webshare.io and sign up ($1/month for residential proxy)
|
||||||
|
2. Get their proxy URL (format: `http://username:password@ip:port`)
|
||||||
|
3. Send it to you
|
||||||
|
|
||||||
|
Then run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
agent-eyes configure proxy THE_PROXY_URL
|
||||||
|
```
|
||||||
|
|
||||||
|
This automatically tests the proxy against Reddit and confirms it works.
|
||||||
|
|
||||||
|
### Step 6: Final verification
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
agent-eyes doctor
|
agent-eyes doctor
|
||||||
```
|
```
|
||||||
|
|
||||||
This shows which platforms are already available (many work with zero configuration).
|
Report results to the user. Example:
|
||||||
|
|
||||||
### Step 3: Test Zero-Config Features
|
> "✅ Agent Eyes is ready! Here's what I can do:
|
||||||
|
> - 📖 Read: Web, GitHub, YouTube, Bilibili, RSS, Tweets
|
||||||
|
> - 🔍 Search: Web, GitHub, Reddit, Twitter
|
||||||
|
>
|
||||||
|
> Try it: ask me to search or read anything!"
|
||||||
|
|
||||||
These work immediately without any setup:
|
### Summary of commands
|
||||||
|
|
||||||
```bash
|
| Action | Command |
|
||||||
# Read a web page
|
|--------|---------|
|
||||||
agent-eyes read "https://example.com"
|
| Install | `pip install git+https://github.com/Panniantong/agent-eyes.git` |
|
||||||
|
| One-shot setup | `agent-eyes install --env=local --search=yes` |
|
||||||
# Read a GitHub repo
|
| Add Exa key | `agent-eyes configure exa-key YOUR_KEY` |
|
||||||
agent-eyes read "https://github.com/Panniantong/agent-eyes"
|
| Add proxy | `agent-eyes configure proxy http://user:pass@ip:port` |
|
||||||
|
| Add GitHub token | `agent-eyes configure github-token YOUR_TOKEN` |
|
||||||
# Search GitHub
|
| Health check | `agent-eyes doctor` |
|
||||||
agent-eyes search-github "AI agent framework" -n 3
|
| Read URL | `agent-eyes read <url>` |
|
||||||
```
|
| Search web | `agent-eyes search "query"` |
|
||||||
|
| Search GitHub | `agent-eyes search-github "query"` |
|
||||||
Tell the user: "✅ Agent Eyes installed! I can now read web pages, GitHub, YouTube, Bilibili, RSS, and tweets. Want me to unlock search too? (free, takes 30 seconds)"
|
| Search Reddit | `agent-eyes search-reddit "query"` |
|
||||||
|
| Search Twitter | `agent-eyes search-twitter "query"` |
|
||||||
### Step 4: Unlock Search (Optional, Recommended)
|
|
||||||
|
|
||||||
Ask the user:
|
|
||||||
|
|
||||||
> "I can unlock full web search, Reddit search, and Twitter search with one free API key. Want to set it up? It takes 30 seconds."
|
|
||||||
|
|
||||||
If the user says yes:
|
|
||||||
|
|
||||||
> "Please go to https://exa.ai, sign up (free), and copy your API key. Then send it to me."
|
|
||||||
|
|
||||||
When the user provides the key:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Write the key to config
|
|
||||||
python3 -c "
|
|
||||||
from agent_eyes.config import Config
|
|
||||||
c = Config()
|
|
||||||
c.set('exa_api_key', 'THE_KEY_USER_PROVIDED')
|
|
||||||
print('✅ Exa API key saved!')
|
|
||||||
"
|
|
||||||
```
|
|
||||||
|
|
||||||
Test it:
|
|
||||||
```bash
|
|
||||||
agent-eyes search "AI agent infrastructure" -n 3
|
|
||||||
```
|
|
||||||
|
|
||||||
Tell the user: "✅ Search unlocked! I can now search the entire web, Reddit, and Twitter for you."
|
|
||||||
|
|
||||||
### Step 5: Server Proxy Setup (Only if user said "server" in Step 0)
|
|
||||||
|
|
||||||
If the user is on a **server/VPS**, proactively tell them:
|
|
||||||
|
|
||||||
> "因为你在服务器上,Reddit 和 B站会封服务器 IP。要解锁这两个平台,需要一个住宅代理(residential proxy)。推荐用 Webshare,$1/月,非常便宜。要配吗?"
|
|
||||||
|
|
||||||
If the user says yes:
|
|
||||||
|
|
||||||
> "步骤:
|
|
||||||
> 1. 去 https://www.webshare.io 注册(有免费试用)
|
|
||||||
> 2. 买一个 Residential Proxy($1/月的套餐就够了)
|
|
||||||
> 3. 在 Dashboard 里找到代理地址,格式类似:http://用户名:密码@IP:端口
|
|
||||||
> 4. 把代理地址发给我"
|
|
||||||
|
|
||||||
When the user provides the proxy:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python3 -c "
|
|
||||||
from agent_eyes.config import Config
|
|
||||||
c = Config()
|
|
||||||
c.set('reddit_proxy', 'THE_PROXY_USER_PROVIDED')
|
|
||||||
c.set('bilibili_proxy', 'THE_PROXY_USER_PROVIDED')
|
|
||||||
print('✅ Proxy configured for Reddit and Bilibili!')
|
|
||||||
"
|
|
||||||
```
|
|
||||||
|
|
||||||
Test it:
|
|
||||||
```bash
|
|
||||||
agent-eyes read "https://www.reddit.com/r/test" 2>&1 | head -5
|
|
||||||
```
|
|
||||||
|
|
||||||
If it works: "✅ Reddit 和 B站都可以用了!"
|
|
||||||
If it fails: "代理可能有问题,请检查格式是否正确。不配也没关系——其他平台都正常工作,Reddit 内容也可以通过搜索引擎间接获取。"
|
|
||||||
|
|
||||||
If the user is on a **local computer**, skip this step entirely.
|
|
||||||
|
|
||||||
### Step 6: Optional — Advanced Channels
|
|
||||||
|
|
||||||
Only offer these if the user asks or if relevant to their needs.
|
|
||||||
|
|
||||||
#### Twitter Advanced (search timelines, read threads)
|
|
||||||
|
|
||||||
Check if birdx is available:
|
|
||||||
```bash
|
|
||||||
which birdx && echo "already installed" || pip install birdx
|
|
||||||
```
|
|
||||||
|
|
||||||
If birdx is installed, it works automatically. If the user wants to configure cookie auth for deeper access, read the guide:
|
|
||||||
`agent_eyes/guides/setup-twitter.md`
|
|
||||||
|
|
||||||
#### Reddit Full Reader (read complete posts + comments)
|
|
||||||
|
|
||||||
Reddit blocks many server IPs. Full reading requires a proxy.
|
|
||||||
Read the guide: `agent_eyes/guides/setup-reddit.md`
|
|
||||||
|
|
||||||
Without a proxy, you can still SEARCH Reddit content via Exa (Step 4).
|
|
||||||
|
|
||||||
#### WeChat / XiaoHongShu (Chinese platforms)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install agent-eyes[browser]
|
|
||||||
playwright install chromium
|
|
||||||
```
|
|
||||||
|
|
||||||
For XiaoHongShu, the user needs to log in once. Read: `agent_eyes/guides/setup-xiaohongshu.md`
|
|
||||||
|
|
||||||
### Step 7: Final Health Check
|
|
||||||
|
|
||||||
```bash
|
|
||||||
agent-eyes doctor
|
|
||||||
```
|
|
||||||
|
|
||||||
Report the results to the user in a friendly way. Example:
|
|
||||||
|
|
||||||
> "Here's what I can do now:
|
|
||||||
> ✅ Read: Web, GitHub, YouTube, Bilibili, RSS, Tweets
|
|
||||||
> ✅ Search: Web, GitHub, Reddit, Twitter
|
|
||||||
> ⬜ Not configured: Reddit full reader, WeChat, XiaoHongShu
|
|
||||||
>
|
|
||||||
> I'm ready to help! Ask me to search or read anything."
|
|
||||||
|
|
||||||
### Using Agent Eyes
|
|
||||||
|
|
||||||
After installation, you can use these commands anytime:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Read any URL
|
|
||||||
agent-eyes read "<url>"
|
|
||||||
|
|
||||||
# Search the web
|
|
||||||
agent-eyes search "<query>"
|
|
||||||
|
|
||||||
# Search specific platforms
|
|
||||||
agent-eyes search-github "<query>"
|
|
||||||
agent-eyes search-reddit "<query>" --sub "<subreddit>"
|
|
||||||
agent-eyes search-twitter "<query>"
|
|
||||||
|
|
||||||
# Check status
|
|
||||||
agent-eyes doctor
|
|
||||||
```
|
|
||||||
|
|
||||||
Or use the Python API:
|
|
||||||
```python
|
|
||||||
from agent_eyes import AgentEyes
|
|
||||||
import asyncio
|
|
||||||
|
|
||||||
eyes = AgentEyes()
|
|
||||||
result = asyncio.run(eyes.read("https://any-url.com"))
|
|
||||||
results = asyncio.run(eyes.search("any query"))
|
|
||||||
```
|
|
||||||
|
|
||||||
### MCP Server (for Claude Code, Cursor, etc.)
|
|
||||||
|
|
||||||
If your platform supports MCP:
|
|
||||||
```bash
|
|
||||||
pip install agent-eyes[mcp]
|
|
||||||
```
|
|
||||||
|
|
||||||
Add to MCP config:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"mcpServers": {
|
|
||||||
"agent-eyes": {
|
|
||||||
"command": "python3",
|
|
||||||
"args": ["-m", "agent_eyes.integrations.mcp_server"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Troubleshooting
|
### Troubleshooting
|
||||||
|
|
||||||
| Problem | Solution |
|
| Problem | Solution |
|
||||||
|---------|----------|
|
|---------|----------|
|
||||||
| `pip: command not found` | Try `pip3` instead |
|
| `pip: command not found` | Try `pip3` |
|
||||||
| `Permission denied` | Add `--user` flag or use `sudo` |
|
| `Permission denied` | Add `--user` flag |
|
||||||
| `agent-eyes: command not found` | Run `python3 -m agent_eyes.cli doctor` instead |
|
| `agent-eyes: command not found` | Use `python3 -m agent_eyes.cli` instead |
|
||||||
| Search returns "Exa API key not configured" | Run Step 4 above |
|
| Search returns "Exa API key not configured" | `agent-eyes configure exa-key YOUR_KEY` |
|
||||||
| Reddit returns 403 | Need proxy (see `guides/setup-reddit.md`) |
|
| Reddit returns 403 | `agent-eyes configure proxy http://user:pass@ip:port` |
|
||||||
|
|||||||
Reference in New Issue
Block a user