Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,9 @@ GOOGLE_SEARCH_ENGINE_ID=<YOUR_SEARCH_ENGINE_ID_HERE>
# Additional configuration
# LOG_LEVEL=INFO
# DISABLE_TOOLS=false
# TOOL_TIMEOUT=30
# 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=
23 changes: 21 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```
Expand Down Expand Up @@ -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)
[![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.
50 changes: 44 additions & 6 deletions cursor_agent_tools/tools/search_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
Expand All @@ -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")
Expand Down Expand Up @@ -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.
Expand Down