Initial commit with translated description
This commit is contained in:
69
SKILL.md
Normal file
69
SKILL.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
---
|
||||||
|
name: gemini-deep-research
|
||||||
|
description: "使用Gemini深度研究代理执行复杂、长期的研究任务。在被要求研究需要多源综合、竞争分析、市场调研或全面技术调查的主题时使用,这些主题受益于系统的网络搜索和分析。"
|
||||||
|
metadata: {"clawdbot":{"emoji":"🔬","requires":{"env":["GEMINI_API_KEY"]},"primaryEnv":"GEMINI_API_KEY"}}
|
||||||
|
---
|
||||||
|
|
||||||
|
# Gemini Deep Research
|
||||||
|
|
||||||
|
Use Gemini's Deep Research Agent to perform complex, long-running context gathering and synthesis tasks.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- `GEMINI_API_KEY` environment variable (from Google AI Studio)
|
||||||
|
- **Note**: This does NOT work with Antigravity OAuth tokens. Requires a direct Gemini API key.
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
Deep Research is an agent that:
|
||||||
|
1. Breaks down complex queries into sub-questions
|
||||||
|
2. Searches the web systematically
|
||||||
|
3. Synthesizes findings into comprehensive reports
|
||||||
|
4. Provides streaming progress updates
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Basic Research
|
||||||
|
|
||||||
|
```bash
|
||||||
|
scripts/deep_research.py --query "Research the history of Google TPUs"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Output Format
|
||||||
|
|
||||||
|
```bash
|
||||||
|
scripts/deep_research.py --query "Research the competitive landscape of EV batteries" \
|
||||||
|
--format "1. Executive Summary\n2. Key Players (include data table)\n3. Supply Chain Risks"
|
||||||
|
```
|
||||||
|
|
||||||
|
### With File Search (optional)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
scripts/deep_research.py --query "Compare our 2025 fiscal year report against current public web news" \
|
||||||
|
--file-search-store "fileSearchStores/my-store-name"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stream Progress
|
||||||
|
|
||||||
|
```bash
|
||||||
|
scripts/deep_research.py --query "Your research topic" --stream
|
||||||
|
```
|
||||||
|
|
||||||
|
## Output
|
||||||
|
|
||||||
|
The script saves results to timestamped files:
|
||||||
|
- `deep-research-YYYY-MM-DD-HH-MM-SS.md` - Final report in markdown
|
||||||
|
- `deep-research-YYYY-MM-DD-HH-MM-SS.json` - Full interaction metadata
|
||||||
|
|
||||||
|
## API Details
|
||||||
|
|
||||||
|
- **Endpoint**: `https://generativelanguage.googleapis.com/v1beta/interactions`
|
||||||
|
- **Agent**: `deep-research-pro-preview-12-2025`
|
||||||
|
- **Auth**: `x-goog-api-key` header (NOT OAuth Bearer token)
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
- Requires Gemini API key (get from [Google AI Studio](https://aistudio.google.com/apikey))
|
||||||
|
- Does NOT work with Antigravity OAuth authentication
|
||||||
|
- Long-running tasks (minutes to hours depending on complexity)
|
||||||
|
- May incur API costs depending on your quota
|
||||||
6
_meta.json
Normal file
6
_meta.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"ownerId": "kn7azq5e6sw0fbwwzdpcwvvjzd7z0x4z",
|
||||||
|
"slug": "gemini-deep-research",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"publishedAt": 1768845281114
|
||||||
|
}
|
||||||
176
scripts/deep_research.py
Normal file
176
scripts/deep_research.py
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Gemini Deep Research API client
|
||||||
|
Performs complex, long-running research tasks via Gemini's Deep Research Agent
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
from datetime import datetime
|
||||||
|
from pathlib import Path
|
||||||
|
import requests
|
||||||
|
|
||||||
|
API_BASE = "https://generativelanguage.googleapis.com/v1beta"
|
||||||
|
AGENT_MODEL = "deep-research-pro-preview-12-2025"
|
||||||
|
|
||||||
|
|
||||||
|
def create_interaction(api_key, query, output_format=None, file_search_store=None):
|
||||||
|
"""Start a new deep research interaction"""
|
||||||
|
headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"x-goog-api-key": api_key
|
||||||
|
}
|
||||||
|
|
||||||
|
payload = {
|
||||||
|
"input": query,
|
||||||
|
"agent": AGENT_MODEL,
|
||||||
|
"background": True
|
||||||
|
}
|
||||||
|
|
||||||
|
if output_format:
|
||||||
|
payload["input"] = f"{query}\n\nFormat the output as follows:\n{output_format}"
|
||||||
|
|
||||||
|
if file_search_store:
|
||||||
|
payload["tools"] = [{
|
||||||
|
"type": "file_search",
|
||||||
|
"file_search_store_names": [file_search_store]
|
||||||
|
}]
|
||||||
|
|
||||||
|
response = requests.post(
|
||||||
|
f"{API_BASE}/interactions",
|
||||||
|
headers=headers,
|
||||||
|
json=payload
|
||||||
|
)
|
||||||
|
|
||||||
|
if response.status_code != 200:
|
||||||
|
print(f"Error creating interaction: {response.status_code}", file=sys.stderr)
|
||||||
|
print(response.text, file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
|
||||||
|
def poll_interaction(api_key, interaction_id, stream=False):
|
||||||
|
"""Poll for interaction updates"""
|
||||||
|
headers = {
|
||||||
|
"x-goog-api-key": api_key
|
||||||
|
}
|
||||||
|
|
||||||
|
while True:
|
||||||
|
response = requests.get(
|
||||||
|
f"{API_BASE}/interactions/{interaction_id}",
|
||||||
|
headers=headers
|
||||||
|
)
|
||||||
|
|
||||||
|
if response.status_code != 200:
|
||||||
|
print(f"Error polling interaction: {response.status_code}", file=sys.stderr)
|
||||||
|
print(response.text, file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
data = response.json()
|
||||||
|
status = data.get("status", "UNKNOWN")
|
||||||
|
|
||||||
|
if stream:
|
||||||
|
# Show progress updates
|
||||||
|
if "statusMessage" in data:
|
||||||
|
print(f"[{status}] {data['statusMessage']}", file=sys.stderr)
|
||||||
|
|
||||||
|
if status == "completed":
|
||||||
|
return data
|
||||||
|
elif status == "failed":
|
||||||
|
print(f"Research failed: {data.get('error', 'Unknown error')}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
time.sleep(10) # Poll every 10 seconds
|
||||||
|
|
||||||
|
|
||||||
|
def extract_report(interaction_data):
|
||||||
|
"""Extract the final report from interaction data"""
|
||||||
|
if "output" in interaction_data:
|
||||||
|
output = interaction_data["output"]
|
||||||
|
if isinstance(output, dict) and "text" in output:
|
||||||
|
return output["text"]
|
||||||
|
elif isinstance(output, str):
|
||||||
|
return output
|
||||||
|
|
||||||
|
# Fallback: look in messages
|
||||||
|
messages = interaction_data.get("messages", [])
|
||||||
|
for msg in reversed(messages):
|
||||||
|
if msg.get("role") == "model" and "parts" in msg:
|
||||||
|
for part in msg["parts"]:
|
||||||
|
if "text" in part:
|
||||||
|
return part["text"]
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description="Gemini Deep Research API Client")
|
||||||
|
parser.add_argument("--query", required=True, help="Research query")
|
||||||
|
parser.add_argument("--format", help="Custom output format instructions")
|
||||||
|
parser.add_argument("--file-search-store", help="File search store name (optional)")
|
||||||
|
parser.add_argument("--stream", action="store_true", help="Show streaming progress updates")
|
||||||
|
parser.add_argument("--output-dir", default=".", help="Output directory for results")
|
||||||
|
parser.add_argument("--api-key", help="Gemini API key (overrides GEMINI_API_KEY env var)")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Get API key
|
||||||
|
api_key = args.api_key or os.environ.get("GEMINI_API_KEY")
|
||||||
|
if not api_key:
|
||||||
|
print("Error: No API key provided.", file=sys.stderr)
|
||||||
|
print("Please either:", file=sys.stderr)
|
||||||
|
print(" 1. Provide --api-key argument", file=sys.stderr)
|
||||||
|
print(" 2. Set GEMINI_API_KEY environment variable", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Start research
|
||||||
|
print(f"Starting deep research: {args.query}", file=sys.stderr)
|
||||||
|
interaction = create_interaction(
|
||||||
|
api_key,
|
||||||
|
args.query,
|
||||||
|
output_format=args.format,
|
||||||
|
file_search_store=args.file_search_store
|
||||||
|
)
|
||||||
|
|
||||||
|
interaction_id = interaction.get("id")
|
||||||
|
if not interaction_id:
|
||||||
|
print(f"Error: No interaction ID in response: {interaction}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
print(f"Interaction started: {interaction_id}", file=sys.stderr)
|
||||||
|
|
||||||
|
# Poll for completion
|
||||||
|
print("Polling for results (this may take several minutes)...", file=sys.stderr)
|
||||||
|
result = poll_interaction(api_key, interaction_id, stream=args.stream)
|
||||||
|
|
||||||
|
# Extract report
|
||||||
|
report = extract_report(result)
|
||||||
|
|
||||||
|
if not report:
|
||||||
|
print("Warning: Could not extract report text from response", file=sys.stderr)
|
||||||
|
report = json.dumps(result, indent=2)
|
||||||
|
|
||||||
|
# Save results
|
||||||
|
timestamp = datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
|
||||||
|
output_dir = Path(args.output_dir)
|
||||||
|
output_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
md_path = output_dir / f"deep-research-{timestamp}.md"
|
||||||
|
json_path = output_dir / f"deep-research-{timestamp}.json"
|
||||||
|
|
||||||
|
md_path.write_text(report)
|
||||||
|
json_path.write_text(json.dumps(result, indent=2))
|
||||||
|
|
||||||
|
print(f"\nResearch complete!", file=sys.stderr)
|
||||||
|
print(f"Report saved: {md_path}", file=sys.stderr)
|
||||||
|
print(f"Full data saved: {json_path}", file=sys.stderr)
|
||||||
|
|
||||||
|
# Print report to stdout
|
||||||
|
print(report)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user