""" GitHub -- REST API, free token, no scopes needed for public data. """ import httpx from supabase_client import require_tool_keys BASE = "https://api.github.com" def run(params: dict) -> dict: creds = require_tool_keys("github") token = creds["api_key"] headers = {"Authorization": f"token {token}", "Accept": "application/vnd.github+json"} mode = params.get("mode", "search") if mode == "org": org = params.get("org") if not org: raise ValueError("org is required for mode='org'") resp = httpx.get(f"{BASE}/orgs/{org}/repos", headers=headers, params={"per_page": 100}, timeout=15.0) resp.raise_for_status() repos = resp.json() results = [ {"name": r["name"], "stars": r["stargazers_count"], "forks": r["forks_count"], "language": r["language"], "updated_at": r["updated_at"]} for r in repos ] return {"mode": "org", "org": org, "count": len(results), "results": results} if mode == "commit_activity": owner = params.get("owner") repo = params.get("repo") if not (owner and repo): raise ValueError("owner and repo are required for mode='commit_activity'") resp = httpx.get(f"{BASE}/repos/{owner}/{repo}/stats/commit_activity", headers=headers, timeout=15.0) resp.raise_for_status() return {"mode": "commit_activity", "owner": owner, "repo": repo, "weeks": resp.json()} # default: keyword search query = params.get("query") if not query: raise ValueError("query is required for mode='search'") sort = params.get("sort", "stars") per_page = int(params.get("per_page", 30)) resp = httpx.get( f"{BASE}/search/repositories", headers=headers, params={"q": query, "sort": sort, "per_page": min(per_page, 100)}, timeout=15.0, ) resp.raise_for_status() items = resp.json().get("items", []) results = [ { "name": r["full_name"], "description": r["description"], "stars": r["stargazers_count"], "forks": r["forks_count"], "language": r["language"], "url": r["html_url"], } for r in items ] return {"mode": "search", "count": len(results), "results": results}