"""GitHub Repository Analyzer Agent.""" from __future__ import annotations from researchlink.agents.base import BaseAgent from researchlink.providers.base import AgentRole from researchlink.schemas.repository import RepoAnalysis from researchlink.services.github_client import ( detect_language_and_frameworks, fetch_readme, fetch_repo_metadata, fetch_tree, parse_github_url, ) class GitHubRepoAnalyzerAgent(BaseAgent): name = "GitHubRepoAnalyzerAgent" task_role = AgentRole.analysis def run(self, github_url: str | None) -> RepoAnalysis: analysis = RepoAnalysis(url=github_url) if not github_url: analysis.analysis_notes.append("No GitHub URL provided.") return analysis owner, repo_name = parse_github_url(github_url) if not owner or not repo_name: analysis.analysis_notes.append(f"Could not parse owner/repo from URL: {github_url}") return analysis analysis.owner = owner analysis.repo_name = repo_name self.log(f"Analyzing {owner}/{repo_name}...") # Fetch metadata meta = fetch_repo_metadata(owner, repo_name) if "error" in meta: analysis.repo_accessible = False analysis.access_error = meta["error"] analysis.analysis_notes.append(f"GitHub API error: {meta['error']}") self.warn(f"GitHub API error: {meta['error']}") return analysis analysis.repo_accessible = True # Fetch README readme = fetch_readme(owner, repo_name) analysis.readme_content = readme[:3000] if readme else None # Fetch tree tree = fetch_tree(owner, repo_name) analysis.top_level_folders = [ item["path"] for item in tree if item.get("type") == "tree" ] analysis.top_level_files = [ item["path"] for item in tree if item.get("type") == "blob" ] # Detect language/frameworks detected = detect_language_and_frameworks(tree, readme) analysis.detected_language = detected["languages"][0] if detected["languages"] else None analysis.detected_frameworks = detected["frameworks"] analysis.setup_commands = detected["setup_commands"] analysis.has_tests = detected["has_tests"] analysis.test_paths = detected["test_paths"] # Heuristic: is this likely the official implementation? readme_lower = (readme or "").lower() analysis.is_likely_official_impl = any( kw in readme_lower for kw in ["official", "paper", "implementation", "code for"] ) analysis.official_impl_confidence = "medium" if analysis.is_likely_official_impl else "low" analysis.analysis_notes.append( "Repository analysis based on GitHub API (public access, unauthenticated). " "Exact reproducibility has NOT been verified." ) self.log( f"Repo analysis done. Language: {analysis.detected_language}, " f"frameworks: {analysis.detected_frameworks}" ) return analysis