From f603323ca84cdeabfa471569fccdaf72aa6b6736 Mon Sep 17 00:00:00 2001 From: Matt Van Horn Date: Fri, 23 Jan 2026 13:41:55 -0800 Subject: [PATCH] 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 --- SKILL.md | 7 ++++++- scripts/last30days.py | 29 ++++++++++++++++++++++++++++- scripts/lib/openai_reddit.py | 20 +++++++++++++++++--- scripts/lib/xai_x.py | 20 ++++++++++++++++++-- 4 files changed, 69 insertions(+), 7 deletions(-) diff --git a/SKILL.md b/SKILL.md index d6f6e5d..9f9b24f 100644 --- a/SKILL.md +++ b/SKILL.md @@ -84,7 +84,12 @@ echo "Please edit it to add your API keys, then run the skill again." ## 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 python3 ~/.claude/skills/last30days/scripts/last30days.py "$ARGUMENTS" --emit=compact 2>&1 diff --git a/scripts/last30days.py b/scripts/last30days.py index 2c1e2f9..bcd482d 100644 --- a/scripts/last30days.py +++ b/scripts/last30days.py @@ -10,6 +10,8 @@ Options: --mock Use fixtures instead of real API calls --emit=MODE Output mode: compact|json|md|context|path (default: compact) --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 @@ -54,6 +56,7 @@ def run_research( selected_models: dict, from_date: str, to_date: str, + depth: str = "default", mock: bool = False, ) -> tuple: """Run the research pipeline. @@ -76,6 +79,7 @@ def run_research( config["OPENAI_API_KEY"], selected_models["openai"], topic, + depth=depth, ) # Parse response @@ -102,6 +106,7 @@ def run_research( topic, from_date, to_date, + depth=depth, ) # Parse response @@ -129,9 +134,30 @@ def main(): default="auto", 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() + # 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: print("Error: Please provide a topic to research.", file=sys.stderr) print("Usage: python3 last30days.py [options]", file=sys.stderr) @@ -166,7 +192,7 @@ def main(): from_date, to_date = dates.get_date_range(30) # 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: cached = cache.load_cache(cache_key) if cached: @@ -208,6 +234,7 @@ def main(): selected_models, from_date, to_date, + depth, args.mock, ) diff --git a/scripts/lib/openai_reddit.py b/scripts/lib/openai_reddit.py index 82fbf6b..a19db89 100644 --- a/scripts/lib/openai_reddit.py +++ b/scripts/lib/openai_reddit.py @@ -8,9 +8,16 @@ from . import http 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} -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: {{ @@ -38,6 +45,7 @@ def search_reddit( api_key: str, model: str, topic: str, + depth: str = "default", mock_response: Optional[Dict] = None, ) -> Dict[str, Any]: """Search Reddit for relevant threads using OpenAI Responses API. @@ -46,6 +54,7 @@ def search_reddit( api_key: OpenAI API key model: Model to use topic: Search topic + depth: Research depth - "quick", "default", or "deep" mock_response: Mock response for testing Returns: @@ -54,11 +63,16 @@ def search_reddit( if mock_response is not None: return mock_response + min_items, max_items = DEPTH_CONFIG.get(depth, DEPTH_CONFIG["default"]) + headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", } + # Adjust timeout based on depth + timeout = 60 if depth == "quick" else 90 if depth == "default" else 120 + payload = { "model": model, "tools": [ @@ -70,10 +84,10 @@ def search_reddit( } ], "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]]: diff --git a/scripts/lib/xai_x.py b/scripts/lib/xai_x.py index 331ea0f..a0e9dd2 100644 --- a/scripts/lib/xai_x.py +++ b/scripts/lib/xai_x.py @@ -9,9 +9,16 @@ from . import http # xAI uses chat completions endpoint 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} -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: {{ @@ -47,6 +54,7 @@ def search_x( topic: str, from_date: str, to_date: str, + depth: str = "default", mock_response: Optional[Dict] = None, ) -> Dict[str, Any]: """Search X for relevant posts using xAI API with live search. @@ -57,6 +65,7 @@ def search_x( topic: Search topic from_date: Start date (YYYY-MM-DD) to_date: End date (YYYY-MM-DD) + depth: Research depth - "quick", "default", or "deep" mock_response: Mock response for testing Returns: @@ -65,11 +74,16 @@ def search_x( if mock_response is not None: return mock_response + min_items, max_items = DEPTH_CONFIG.get(depth, DEPTH_CONFIG["default"]) + headers = { "Authorization": f"Bearer {api_key}", "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 payload = { "model": model, @@ -84,6 +98,8 @@ def search_x( topic=topic, from_date=from_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]]: