Agent-Reach/agent_eyes/core.py
Panniantong 8eab038cb9 v1.0.0 — Agent Eyes: search + read the entire internet
Major restructure from x-reader fork to independent project:

Architecture:
- readers/ — content extraction from 10+ platforms (based on x-reader, MIT)
- search/ — semantic search via Exa, GitHub API, birdx (NEW)
- config.py — configuration management (~/.agent-eyes/config.yaml) (NEW)
- doctor.py — environment health checker (NEW)
- core.py — AgentEyes unified entry point (NEW)
- cli.py — full CLI: read, search, setup, doctor (NEW)
- integrations/mcp_server.py — 8 MCP tools (NEW)
- guides/ — 6 Agent-readable setup guides (NEW)
- integrations/skill/ — OpenClaw Skill package (NEW)

Platforms (zero config):
- Web pages, GitHub, Bilibili, YouTube, RSS, single tweets

Platforms (one free API key):
- Web search, Reddit search, Twitter search (via Exa)

Platforms (optional setup):
- Reddit full reader, Twitter advanced, WeChat, XiaoHongShu

Tests: 34/34 passing

Credits: Built on x-reader by @runes_leo (MIT License)
2026-02-24 04:00:47 +01:00

133 lines
4.4 KiB
Python

# -*- coding: utf-8 -*-
"""
AgentEyes — the unified entry point.
Usage:
from agent_eyes import AgentEyes
eyes = AgentEyes()
content = await eyes.read("https://github.com/openai/gpt-4")
results = await eyes.search("AI agent framework")
"""
import asyncio
from typing import Any, Dict, List, Optional
from agent_eyes.config import Config
from agent_eyes.reader import UniversalReader
class AgentEyes:
"""Give your AI Agent eyes to see the entire internet."""
def __init__(self, config: Optional[Config] = None):
self.config = config or Config()
self.reader = UniversalReader()
# ── Reading ─────────────────────────────────────────
async def read(self, url: str) -> Dict[str, Any]:
"""
Read content from any URL. Auto-detects platform.
Supported: Web, GitHub, Reddit, Twitter, YouTube,
Bilibili, WeChat, XiaoHongShu, RSS, Telegram, etc.
Returns:
Dict with title, content, url, author, etc.
"""
content = await self.reader.read(url)
return content.to_dict()
async def read_batch(self, urls: List[str]) -> List[Dict[str, Any]]:
"""Read multiple URLs concurrently."""
contents = await self.reader.read_batch(urls)
return [c.to_dict() for c in contents]
def detect_platform(self, url: str) -> str:
"""Detect what platform a URL belongs to."""
return self.reader._detect_platform(url)
# ── Searching ───────────────────────────────────────
async def search(self, query: str, num_results: int = 5) -> List[Dict[str, Any]]:
"""
Semantic web search via Exa. Requires Exa API key.
Args:
query: Search query
num_results: Number of results (max 10)
"""
from agent_eyes.search.exa import search_web
return await search_web(query, num_results=num_results, config=self.config)
async def search_reddit(
self,
query: str,
subreddit: Optional[str] = None,
limit: int = 10,
) -> List[Dict[str, Any]]:
"""
Search Reddit via Exa (bypasses IP blocks).
Args:
query: Search query
subreddit: Optional subreddit filter
limit: Number of results
"""
from agent_eyes.search.reddit import search_reddit
return await search_reddit(query, subreddit=subreddit, num_results=limit, config=self.config)
async def search_github(
self,
query: str,
language: Optional[str] = None,
limit: int = 5,
) -> List[Dict[str, Any]]:
"""
Search GitHub repositories.
Args:
query: Search query
language: Filter by language
limit: Number of results
"""
from agent_eyes.search.github import search_github
return await search_github(query, language=language, limit=limit, config=self.config)
async def search_twitter(
self,
query: str,
limit: int = 10,
) -> List[Dict[str, Any]]:
"""
Search Twitter. Uses birdx if available, else Exa.
Args:
query: Search query
limit: Number of results
"""
from agent_eyes.search.twitter import search_twitter
return await search_twitter(query, limit=limit, config=self.config)
# ── Health ──────────────────────────────────────────
def doctor(self) -> Dict[str, dict]:
"""Check all platform/feature availability."""
from agent_eyes.doctor import check_all
return check_all(self.config)
def doctor_report(self) -> str:
"""Get formatted health report."""
from agent_eyes.doctor import check_all, format_report
return format_report(check_all(self.config))
# ── Sync wrappers ───────────────────────────────────
def read_sync(self, url: str) -> Dict[str, Any]:
"""Synchronous version of read()."""
return asyncio.run(self.read(url))
def search_sync(self, query: str, num_results: int = 5) -> List[Dict[str, Any]]:
"""Synchronous version of search()."""
return asyncio.run(self.search(query, num_results))