From 15cb154a19cabb5c3c66491a61f215ef104d5280 Mon Sep 17 00:00:00 2001
From: TevinClaw <510129976@qq.com>
Date: Sat, 14 Mar 2026 13:03:06 +0800
Subject: [PATCH] feat(早报): 增加昨日总结模块

---
 workspace/skills/tavily-search/scripts/tavily_search.py |  152 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 152 insertions(+), 0 deletions(-)

diff --git a/workspace/skills/tavily-search/scripts/tavily_search.py b/workspace/skills/tavily-search/scripts/tavily_search.py
new file mode 100755
index 0000000..fe5b65b
--- /dev/null
+++ b/workspace/skills/tavily-search/scripts/tavily_search.py
@@ -0,0 +1,152 @@
+#!/usr/bin/env python3
+"""
+Tavily AI Search API Client
+Usage: python tavily_search.py "your search query" [--max-results 5] [--depth basic|advanced]
+"""
+
+import os
+import sys
+import json
+import argparse
+from typing import List, Dict, Any, Optional
+
+
+def get_api_key(api_key: Optional[str] = None) -> str:
+    """Get Tavily API key from environment variable or parameter."""
+    # Priority: parameter > environment variable
+    if api_key:
+        return api_key
+    
+    env_key = os.environ.get("TAVILY_API_KEY")
+    if env_key:
+        return env_key
+    
+    raise ValueError(
+        "Tavily API key required. Set via:\n"
+        "  1. Environment variable: export TAVILY_API_KEY=your_key\n"
+        "     (Add to ~/.bashrc or ~/.zshrc for persistence)\n"
+        "  2. Direct parameter: pass api_key when calling the function\n"
+        "\nGet your API key at: https://tavily.com"
+    )
+
+
+def tavily_search(
+    query: str,
+    max_results: int = 5,
+    search_depth: str = "basic",
+    include_answer: bool = False,
+    include_images: bool = False,
+    api_key: Optional[str] = None
+) -> Dict[str, Any]:
+    """
+    Search using Tavily AI Search API.
+    
+    Args:
+        query: Search query string
+        max_results: Number of results to return (1-20)
+        search_depth: "basic" or "advanced"
+        include_answer: Include AI-generated answer
+        include_images: Include image URLs
+        api_key: Tavily API key (optional, auto-detected from env/config)
+    
+    Returns:
+        Dictionary containing search results
+    """
+    api_key = get_api_key(api_key)
+    
+    try:
+        import requests
+    except ImportError:
+        raise ImportError("requests package required. Install with: pip install requests")
+    
+    url = "https://api.tavily.com/search"
+    
+    payload = {
+        "api_key": api_key,
+        "query": query,
+        "max_results": min(max(max_results, 1), 20),
+        "search_depth": search_depth,
+        "include_answer": include_answer,
+        "include_images": include_images,
+    }
+    
+    response = requests.post(url, json=payload, timeout=30)
+    response.raise_for_status()
+    
+    return response.json()
+
+
+def format_results(results: Dict[str, Any]) -> str:
+    """Format search results for display."""
+    output = []
+    
+    if "answer" in results and results["answer"]:
+        output.append("=" * 60)
+        output.append("AI ANSWER")
+        output.append("=" * 60)
+        output.append(results["answer"])
+        output.append("")
+    
+    output.append("=" * 60)
+    output.append("SEARCH RESULTS")
+    output.append("=" * 60)
+    output.append(f"Query: {results.get('query', 'N/A')}")
+    output.append("")
+    
+    for i, result in enumerate(results.get("results", []), 1):
+        output.append(f"{i}. {result.get('title', 'No title')}")
+        output.append(f"   URL: {result.get('url', 'N/A')}")
+        
+        if result.get('published_date'):
+            output.append(f"   Published: {result['published_date']}")
+        
+        if result.get('score'):
+            output.append(f"   Relevance: {result['score']:.2f}")
+        
+        content = result.get('content', '')
+        if content:
+            # Truncate long content
+            if len(content) > 300:
+                content = content[:297] + "..."
+            output.append(f"   {content}")
+        
+        output.append("")
+    
+    return "\n".join(output)
+
+
+def main():
+    parser = argparse.ArgumentParser(description="Tavily AI Search")
+    parser.add_argument("query", help="Search query")
+    parser.add_argument("--max-results", type=int, default=5, help="Number of results (1-20)")
+    parser.add_argument("--depth", choices=["basic", "advanced"], default="basic", help="Search depth")
+    parser.add_argument("--answer", action="store_true", help="Include AI-generated answer")
+    parser.add_argument("--images", action="store_true", help="Include images")
+    parser.add_argument("--json", action="store_true", help="Output raw JSON")
+    
+    args = parser.parse_args()
+    
+    try:
+        results = tavily_search(
+            query=args.query,
+            max_results=args.max_results,
+            search_depth=args.depth,
+            include_answer=args.answer,
+            include_images=args.images
+        )
+        
+        if args.json:
+            print(json.dumps(results, indent=2, ensure_ascii=False))
+        else:
+            print(format_results(results))
+    
+    except ValueError as e:
+        print(f"Error: {e}", file=sys.stderr)
+        sys.exit(1)
+    except Exception as e:
+        print(f"Search failed: {e}", file=sys.stderr)
+        sys.exit(1)
+
+
+if __name__ == "__main__":
+    main()

--
Gitblit v1.9.1