Add --quick and --deep flags for research depth
- quick: 8-12 sources each, faster response - default: 20-30 sources each (unchanged behavior) - deep: 50-70 Reddit, 40-60 X for comprehensive research Adjusts API timeouts based on depth. Cache keys include depth so different depths are cached separately. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -84,7 +84,12 @@ echo "Please edit it to add your API keys, then run the skill again."
|
|||||||
|
|
||||||
## Research Execution
|
## Research Execution
|
||||||
|
|
||||||
Run the research orchestrator with the TOPIC:
|
Run the research orchestrator with the TOPIC.
|
||||||
|
|
||||||
|
**Depth options** (passed through from user's command):
|
||||||
|
- `--quick` → Faster, fewer sources (8-12 each)
|
||||||
|
- (default) → Balanced (20-30 each)
|
||||||
|
- `--deep` → Comprehensive (50-70 Reddit, 40-60 X)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 ~/.claude/skills/last30days/scripts/last30days.py "$ARGUMENTS" --emit=compact 2>&1
|
python3 ~/.claude/skills/last30days/scripts/last30days.py "$ARGUMENTS" --emit=compact 2>&1
|
||||||
|
|||||||
+28
-1
@@ -10,6 +10,8 @@ Options:
|
|||||||
--mock Use fixtures instead of real API calls
|
--mock Use fixtures instead of real API calls
|
||||||
--emit=MODE Output mode: compact|json|md|context|path (default: compact)
|
--emit=MODE Output mode: compact|json|md|context|path (default: compact)
|
||||||
--sources=MODE Source selection: auto|reddit|x|both (default: auto)
|
--sources=MODE Source selection: auto|reddit|x|both (default: auto)
|
||||||
|
--quick Faster research with fewer sources (8-12 each)
|
||||||
|
--deep Comprehensive research with more sources (50-70 Reddit, 40-60 X)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
@@ -54,6 +56,7 @@ def run_research(
|
|||||||
selected_models: dict,
|
selected_models: dict,
|
||||||
from_date: str,
|
from_date: str,
|
||||||
to_date: str,
|
to_date: str,
|
||||||
|
depth: str = "default",
|
||||||
mock: bool = False,
|
mock: bool = False,
|
||||||
) -> tuple:
|
) -> tuple:
|
||||||
"""Run the research pipeline.
|
"""Run the research pipeline.
|
||||||
@@ -76,6 +79,7 @@ def run_research(
|
|||||||
config["OPENAI_API_KEY"],
|
config["OPENAI_API_KEY"],
|
||||||
selected_models["openai"],
|
selected_models["openai"],
|
||||||
topic,
|
topic,
|
||||||
|
depth=depth,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Parse response
|
# Parse response
|
||||||
@@ -102,6 +106,7 @@ def run_research(
|
|||||||
topic,
|
topic,
|
||||||
from_date,
|
from_date,
|
||||||
to_date,
|
to_date,
|
||||||
|
depth=depth,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Parse response
|
# Parse response
|
||||||
@@ -129,9 +134,30 @@ def main():
|
|||||||
default="auto",
|
default="auto",
|
||||||
help="Source selection",
|
help="Source selection",
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--quick",
|
||||||
|
action="store_true",
|
||||||
|
help="Faster research with fewer sources (8-12 each)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--deep",
|
||||||
|
action="store_true",
|
||||||
|
help="Comprehensive research with more sources (50-70 Reddit, 40-60 X)",
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Determine depth
|
||||||
|
if args.quick and args.deep:
|
||||||
|
print("Error: Cannot use both --quick and --deep", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
elif args.quick:
|
||||||
|
depth = "quick"
|
||||||
|
elif args.deep:
|
||||||
|
depth = "deep"
|
||||||
|
else:
|
||||||
|
depth = "default"
|
||||||
|
|
||||||
if not args.topic:
|
if not args.topic:
|
||||||
print("Error: Please provide a topic to research.", file=sys.stderr)
|
print("Error: Please provide a topic to research.", file=sys.stderr)
|
||||||
print("Usage: python3 last30days.py <topic> [options]", file=sys.stderr)
|
print("Usage: python3 last30days.py <topic> [options]", file=sys.stderr)
|
||||||
@@ -166,7 +192,7 @@ def main():
|
|||||||
from_date, to_date = dates.get_date_range(30)
|
from_date, to_date = dates.get_date_range(30)
|
||||||
|
|
||||||
# Check cache (unless refresh or mock)
|
# Check cache (unless refresh or mock)
|
||||||
cache_key = cache.get_cache_key(args.topic, from_date, to_date, sources)
|
cache_key = cache.get_cache_key(args.topic, from_date, to_date, f"{sources}:{depth}")
|
||||||
if not args.refresh and not args.mock:
|
if not args.refresh and not args.mock:
|
||||||
cached = cache.load_cache(cache_key)
|
cached = cache.load_cache(cache_key)
|
||||||
if cached:
|
if cached:
|
||||||
@@ -208,6 +234,7 @@ def main():
|
|||||||
selected_models,
|
selected_models,
|
||||||
from_date,
|
from_date,
|
||||||
to_date,
|
to_date,
|
||||||
|
depth,
|
||||||
args.mock,
|
args.mock,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,16 @@ from . import http
|
|||||||
|
|
||||||
OPENAI_RESPONSES_URL = "https://api.openai.com/v1/responses"
|
OPENAI_RESPONSES_URL = "https://api.openai.com/v1/responses"
|
||||||
|
|
||||||
|
# Depth configurations: (min, max) threads to request
|
||||||
|
DEPTH_CONFIG = {
|
||||||
|
"quick": (8, 12),
|
||||||
|
"default": (20, 30),
|
||||||
|
"deep": (50, 70),
|
||||||
|
}
|
||||||
|
|
||||||
REDDIT_SEARCH_PROMPT = """Search Reddit for discussions about: {topic}
|
REDDIT_SEARCH_PROMPT = """Search Reddit for discussions about: {topic}
|
||||||
|
|
||||||
Focus on threads from the last 30 days. Find 15-30 high-quality, relevant threads.
|
Focus on threads from the last 30 days. Find {min_items}-{max_items} high-quality, relevant threads.
|
||||||
|
|
||||||
IMPORTANT: Return ONLY valid JSON in this exact format, no other text:
|
IMPORTANT: Return ONLY valid JSON in this exact format, no other text:
|
||||||
{{
|
{{
|
||||||
@@ -38,6 +45,7 @@ def search_reddit(
|
|||||||
api_key: str,
|
api_key: str,
|
||||||
model: str,
|
model: str,
|
||||||
topic: str,
|
topic: str,
|
||||||
|
depth: str = "default",
|
||||||
mock_response: Optional[Dict] = None,
|
mock_response: Optional[Dict] = None,
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""Search Reddit for relevant threads using OpenAI Responses API.
|
"""Search Reddit for relevant threads using OpenAI Responses API.
|
||||||
@@ -46,6 +54,7 @@ def search_reddit(
|
|||||||
api_key: OpenAI API key
|
api_key: OpenAI API key
|
||||||
model: Model to use
|
model: Model to use
|
||||||
topic: Search topic
|
topic: Search topic
|
||||||
|
depth: Research depth - "quick", "default", or "deep"
|
||||||
mock_response: Mock response for testing
|
mock_response: Mock response for testing
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -54,11 +63,16 @@ def search_reddit(
|
|||||||
if mock_response is not None:
|
if mock_response is not None:
|
||||||
return mock_response
|
return mock_response
|
||||||
|
|
||||||
|
min_items, max_items = DEPTH_CONFIG.get(depth, DEPTH_CONFIG["default"])
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
"Authorization": f"Bearer {api_key}",
|
"Authorization": f"Bearer {api_key}",
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Adjust timeout based on depth
|
||||||
|
timeout = 60 if depth == "quick" else 90 if depth == "default" else 120
|
||||||
|
|
||||||
payload = {
|
payload = {
|
||||||
"model": model,
|
"model": model,
|
||||||
"tools": [
|
"tools": [
|
||||||
@@ -70,10 +84,10 @@ def search_reddit(
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"include": ["web_search_call.action.sources"],
|
"include": ["web_search_call.action.sources"],
|
||||||
"input": REDDIT_SEARCH_PROMPT.format(topic=topic),
|
"input": REDDIT_SEARCH_PROMPT.format(topic=topic, min_items=min_items, max_items=max_items),
|
||||||
}
|
}
|
||||||
|
|
||||||
return http.post(OPENAI_RESPONSES_URL, payload, headers=headers, timeout=60)
|
return http.post(OPENAI_RESPONSES_URL, payload, headers=headers, timeout=timeout)
|
||||||
|
|
||||||
|
|
||||||
def parse_reddit_response(response: Dict[str, Any]) -> List[Dict[str, Any]]:
|
def parse_reddit_response(response: Dict[str, Any]) -> List[Dict[str, Any]]:
|
||||||
|
|||||||
+18
-2
@@ -9,9 +9,16 @@ from . import http
|
|||||||
# xAI uses chat completions endpoint
|
# xAI uses chat completions endpoint
|
||||||
XAI_CHAT_URL = "https://api.x.ai/v1/chat/completions"
|
XAI_CHAT_URL = "https://api.x.ai/v1/chat/completions"
|
||||||
|
|
||||||
|
# Depth configurations: (min, max) posts to request
|
||||||
|
DEPTH_CONFIG = {
|
||||||
|
"quick": (8, 12),
|
||||||
|
"default": (20, 30),
|
||||||
|
"deep": (40, 60),
|
||||||
|
}
|
||||||
|
|
||||||
X_SEARCH_PROMPT = """You have access to real-time X (Twitter) data. Search for posts about: {topic}
|
X_SEARCH_PROMPT = """You have access to real-time X (Twitter) data. Search for posts about: {topic}
|
||||||
|
|
||||||
Focus on posts from {from_date} to {to_date}. Find 15-30 high-quality, relevant posts.
|
Focus on posts from {from_date} to {to_date}. Find {min_items}-{max_items} high-quality, relevant posts.
|
||||||
|
|
||||||
IMPORTANT: Return ONLY valid JSON in this exact format, no other text:
|
IMPORTANT: Return ONLY valid JSON in this exact format, no other text:
|
||||||
{{
|
{{
|
||||||
@@ -47,6 +54,7 @@ def search_x(
|
|||||||
topic: str,
|
topic: str,
|
||||||
from_date: str,
|
from_date: str,
|
||||||
to_date: str,
|
to_date: str,
|
||||||
|
depth: str = "default",
|
||||||
mock_response: Optional[Dict] = None,
|
mock_response: Optional[Dict] = None,
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""Search X for relevant posts using xAI API with live search.
|
"""Search X for relevant posts using xAI API with live search.
|
||||||
@@ -57,6 +65,7 @@ def search_x(
|
|||||||
topic: Search topic
|
topic: Search topic
|
||||||
from_date: Start date (YYYY-MM-DD)
|
from_date: Start date (YYYY-MM-DD)
|
||||||
to_date: End date (YYYY-MM-DD)
|
to_date: End date (YYYY-MM-DD)
|
||||||
|
depth: Research depth - "quick", "default", or "deep"
|
||||||
mock_response: Mock response for testing
|
mock_response: Mock response for testing
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -65,11 +74,16 @@ def search_x(
|
|||||||
if mock_response is not None:
|
if mock_response is not None:
|
||||||
return mock_response
|
return mock_response
|
||||||
|
|
||||||
|
min_items, max_items = DEPTH_CONFIG.get(depth, DEPTH_CONFIG["default"])
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
"Authorization": f"Bearer {api_key}",
|
"Authorization": f"Bearer {api_key}",
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Adjust timeout based on depth
|
||||||
|
timeout = 60 if depth == "quick" else 90 if depth == "default" else 120
|
||||||
|
|
||||||
# Use chat completions format with search enabled
|
# Use chat completions format with search enabled
|
||||||
payload = {
|
payload = {
|
||||||
"model": model,
|
"model": model,
|
||||||
@@ -84,6 +98,8 @@ def search_x(
|
|||||||
topic=topic,
|
topic=topic,
|
||||||
from_date=from_date,
|
from_date=from_date,
|
||||||
to_date=to_date,
|
to_date=to_date,
|
||||||
|
min_items=min_items,
|
||||||
|
max_items=max_items,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -95,7 +111,7 @@ def search_x(
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return http.post(XAI_CHAT_URL, payload, headers=headers, timeout=90)
|
return http.post(XAI_CHAT_URL, payload, headers=headers, timeout=timeout)
|
||||||
|
|
||||||
|
|
||||||
def parse_x_response(response: Dict[str, Any]) -> List[Dict[str, Any]]:
|
def parse_x_response(response: Dict[str, Any]) -> List[Dict[str, Any]]:
|
||||||
|
|||||||
Reference in New Issue
Block a user