Spaces:
Sleeping
Sleeping
from typing import Any, Dict | |
import requests | |
from smolagents.tools import Tool | |
class GitHubAnalyzerTool(Tool): | |
name = "analyze_github_repository" | |
description = "Analyzes statistics such as issues, pull_requests, contributors, stars and forks of a public GitHub repository and return a synthesis in markdown string with the results." | |
inputs = { | |
'github_url': {'type': 'string', 'description': 'The URL of the public GitHub repository to analyze.'} | |
} | |
output_type = "string" | |
def __init__(self, *args, **kwargs): | |
self.is_initialized = False | |
def forward(self, github_url: str) -> str: | |
""" | |
Analyzes statistics such as issues, pull_requests, contributors, stars and forks of a public GitHub repository and return a synthesis in markdown string with the results. | |
Args: | |
github_url: The URL of the public GitHub repository to analyze. | |
Returns: | |
A synthesis of repository statistics in markdown string with the results. | |
""" | |
if not self.validate_github_url(github_url): | |
return "Please provide a valid GitHub repository URL." | |
user, repo = self.extract_repo_info(github_url) | |
api_url = f"https://api.github.com/repos/{user}/{repo}" | |
response = requests.get(api_url) | |
if response.status_code == 404: | |
return "Repository not found." | |
data = response.json() | |
metrics = { | |
"issues": data.get('open_issues_count', 'N/A'), | |
"contributors": self.fetch_contributors(github_url), | |
"last_commit": self.fetch_last_commit_date(github_url), | |
"stars": data.get('stargazers_count', 'N/A'), | |
"forks": data.get('forks_count', 'N/A'), | |
"pull_requests": self.fetch_pull_requests(github_url) | |
} | |
markdown_output = "\n".join([ | |
f"- **{key}**: {value}" for key, value in metrics.items() | |
]) | |
# Add the repository summary image | |
repo_image_url = f"https://github-readme-stats.vercel.app/api/pin/?username={user}&repo={repo}&theme=chartreuse-dark" | |
repo_image_markdown = f"" | |
return f"{repo_image_markdown}\n\n{markdown_output}" | |
def fetch_contributors(self, github_url: str) -> int: | |
"""Retrieves the number of contributors for a GitHub repository.""" | |
user, repo = self.extract_repo_info(github_url) | |
api_url = f"https://api.github.com/repos/{user}/{repo}/contributors" | |
response = requests.get(api_url) | |
if response.status_code != 200: | |
return "N/A" | |
contributors = response.json() | |
return len(contributors) | |
def fetch_last_commit_date(self, github_url: str) -> str: | |
"""Retrieves the date of the last commit for a GitHub repository.""" | |
user, repo = self.extract_repo_info(github_url) | |
api_url = f"https://api.github.com/repos/{user}/{repo}/commits" | |
response = requests.get(api_url) | |
if response.status_code != 200: | |
return "No commits found" | |
commits = response.json() | |
if commits: | |
return commits[0]['commit']['author']['date'] | |
return "No commits found" | |
def fetch_pull_requests(self, github_url: str) -> int: | |
"""Retrieves the number of open pull requests for a GitHub repository.""" | |
user, repo = self.extract_repo_info(github_url) | |
api_url = f"https://api.github.com/repos/{user}/{repo}/pulls" | |
response = requests.get(api_url) | |
if response.status_code != 200: | |
return "N/A" | |
pull_requests = response.json() | |
return len(pull_requests) | |
def extract_repo_info(self, github_url: str) -> tuple: | |
"""Extracts repository information from the GitHub URL.""" | |
parts = github_url.split('/') | |
if len(parts) < 5: | |
return "URL should be in the format: https://github.com/username/repository" | |
return parts[3], parts[4] | |
def validate_github_url(self, github_url: str) -> bool: | |
"""Validates if the provided URL is a valid GitHub repository URL.""" | |
return "github.com" in github_url | |