From 1c961996c49dfbf71fdc56042d3a5932b4420910 Mon Sep 17 00:00:00 2001 From: Mouse Date: Mon, 11 May 2026 13:58:09 -0700 Subject: [PATCH] feat: add you.com search provider --- .env.example | 7 +++- README.md | 23 ++++++++++- cursor_agent_tools/tools/search_tools.py | 50 +++++++++++++++++++++--- 3 files changed, 71 insertions(+), 9 deletions(-) diff --git a/.env.example b/.env.example index d734b26..270f7a4 100644 --- a/.env.example +++ b/.env.example @@ -18,4 +18,9 @@ GOOGLE_SEARCH_ENGINE_ID= # Additional configuration # LOG_LEVEL=INFO # DISABLE_TOOLS=false -# TOOL_TIMEOUT=30 \ No newline at end of file +# TOOL_TIMEOUT=30 + +# Web search provider: google (default) or you +WEB_SEARCH_PROVIDER=google +# You.com Search API key (optional for up to 100 free searches/day) +YDC_API_KEY= diff --git a/README.md b/README.md index bc04f44..a2715e5 100644 --- a/README.md +++ b/README.md @@ -110,10 +110,17 @@ ANTHROPIC_API_KEY=your_anthropic_api_key_here ANTHROPIC_API_MODEL=claude-3-5-sonnet-latest ANTHROPIC_TEMPERATURE=0.0 -# Google Search API (for web_search tool) +# Web search provider for web_search tool +# google (default) or you +WEB_SEARCH_PROVIDER=google + +# Google Search API (required when WEB_SEARCH_PROVIDER=google) GOOGLE_API_KEY=your_google_api_key_here GOOGLE_SEARCH_ENGINE_ID=your_search_engine_id_here +# You.com Search API (optional key, supports free tier for Search API) +YDC_API_KEY=your_ydc_api_key_here + # Ollama configuration (for local models) OLLAMA_HOST=http://localhost:11434 ``` @@ -824,4 +831,16 @@ Femi Amoo (Nifemi Alpine) Founder of [CIVAI TECHNOLOGIES](https://civai.co) -[![Twitter](https://img.shields.io/twitter/follow/usecodenaija?style=social)](https://twitter.com/usecodenaija) \ No newline at end of file +[![Twitter](https://img.shields.io/twitter/follow/usecodenaija?style=social)](https://twitter.com/usecodenaija) + +### Use You.com Search API with `web_search` + +Set the provider and optional API key: + +```bash +export WEB_SEARCH_PROVIDER=you +# Optional: up to 100 free searches/day without key +export YDC_API_KEY=your_key_here +``` + +The `web_search` tool will then query `https://api.you.com/v1/agents/search` and return normalized results in the same response shape used by existing integrations. diff --git a/cursor_agent_tools/tools/search_tools.py b/cursor_agent_tools/tools/search_tools.py index 629db7f..6dc80ac 100644 --- a/cursor_agent_tools/tools/search_tools.py +++ b/cursor_agent_tools/tools/search_tools.py @@ -318,11 +318,16 @@ def web_search( try: logger.info(f"Performing web search for: {search_term}") - # Get API keys from environment + # Provider selection: default to Google for backward compatibility + search_provider = os.environ.get("WEB_SEARCH_PROVIDER", "google").strip().lower() google_api_key = os.environ.get("GOOGLE_API_KEY") google_search_engine_id = os.environ.get("GOOGLE_SEARCH_ENGINE_ID") + ydc_api_key = os.environ.get("YDC_API_KEY") - if not google_api_key or not google_search_engine_id: + if search_provider not in ["google", "you"]: + return {"error": "Unsupported WEB_SEARCH_PROVIDER. Use 'google' or 'you'.", "results": []} + + if search_provider == "google" and (not google_api_key or not google_search_engine_id): logger.error("Missing Google API key or Search Engine ID in environment variables") return { "error": "Missing API keys. Please set GOOGLE_API_KEY and GOOGLE_SEARCH_ENGINE_ID environment variables.", @@ -347,10 +352,12 @@ def web_search( "message": "This query doesn't require up-to-date information. Set force=True to force a web search." } - # Perform Google search - logger.info("Performing internet search using Google Custom Search API...") - # Call google_search synchronously - search_results = google_search_sync(search_term, google_api_key, google_search_engine_id, max_results=max_results) + if search_provider == "you": + logger.info("Performing internet search using You.com Search API...") + search_results = you_search_sync(search_term, ydc_api_key, max_results=max_results) + else: + logger.info("Performing internet search using Google Custom Search API...") + search_results = google_search_sync(search_term, google_api_key, google_search_engine_id, max_results=max_results) if not search_results: logger.warning("No search results found") @@ -478,6 +485,37 @@ def google_search_sync(query: str, api_key: str, search_engine_id: str, max_resu return {} +def you_search_sync(query: str, api_key: Optional[str], max_results: int = 5) -> Dict[str, Dict[str, Any]]: + """Perform a search using You.com Search API synchronously.""" + try: + logger.info(f"Performing You.com Search for: {query} (max_results: {max_results})") + params = {"query": query, "count": str(max_results)} + headers: Dict[str, str] = {} + if api_key: + headers["X-API-Key"] = api_key + + response = requests.get("https://api.you.com/v1/agents/search", params=params, headers=headers, timeout=20) + if response.status_code != 200: + logger.error(f"You.com Search API error {response.status_code}: {response.text}") + return {} + + data = response.json() + results: Dict[str, Dict[str, Any]] = {} + for section in ["web", "news"]: + for item in data.get("results", {}).get(section, [])[:max_results]: + url = item.get("url") + if not url: + continue + results[url] = { + "title": item.get("title", "Unknown Title"), + "snippet": item.get("description", ""), + } + return results + except Exception as e: + logger.error(f"Unexpected error during You.com search: {e}") + return {} + + def scrape_content_sync(search_results: Dict[str, Dict[str, Any]]) -> Dict[str, str]: """ Scrape and summarize content from search result URLs synchronously.