Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| from github_client import GitHubClient | |
| from models import SearchRequest, SearchResponse | |
| import os | |
| from typing import Optional, Dict, Any, List | |
| def search_pr_opportunities( | |
| keyword: Optional[str] = None, | |
| topic: Optional[str] = None, | |
| per_page: int = 5, | |
| page: int = 1, | |
| token: Optional[str] = None | |
| ) -> Dict[str, Any]: | |
| """Search GitHub for PR opportunities. | |
| Args: | |
| keyword: Keyword to search in repositories (optional) | |
| topic: Topic to filter repositories (optional) | |
| per_page: Number of results per page (default: 5) | |
| page: Page number (default: 1) | |
| token: GitHub token for authentication | |
| Returns: | |
| A dictionary containing opportunities and total count | |
| """ | |
| if not token: | |
| token = os.getenv("GITHUB_TOKEN") | |
| if not token: | |
| raise gr.Error("GitHub token required in Authorization header or .env") | |
| try: | |
| client: GitHubClient = GitHubClient(token) | |
| opportunities, total_count = client.find_pr_opportunities( | |
| keyword=keyword, | |
| topic=topic, | |
| per_page=per_page, | |
| page=page | |
| ) | |
| # The return structure matches a dictionary format, so we type it as Dict[str, Any] | |
| response: Dict[str, Any] = { | |
| "opportunities": [ | |
| { | |
| "repo_name": opp.repo_name, | |
| "repo_url": opp.repo_url, | |
| "issue_title": opp.issue_title, | |
| "issue_url": opp.issue_url, | |
| "issue_labels": opp.issue_labels, | |
| "issue_body": opp.issue_body | |
| } for opp in opportunities | |
| ], | |
| "total_count": total_count | |
| } | |
| return response | |
| except Exception as e: | |
| raise gr.Error(str(e)) | |
| # Create the Gradio interface | |
| demo: gr.Interface = gr.Interface( | |
| fn=search_pr_opportunities, | |
| inputs=[ | |
| gr.Textbox(label="Keyword", placeholder="e.g., fastapi"), | |
| gr.Textbox(label="Topic", placeholder="e.g., python"), | |
| gr.Slider(minimum=1, maximum=20, value=5, step=1, label="Results per page"), | |
| gr.Slider(minimum=1, maximum=10, value=1, step=1, label="Page number") | |
| ], | |
| outputs=gr.JSON(label="Search Results"), | |
| title="GitHub PR Opportunity Finder", | |
| description="Search GitHub repositories for PR opportunities (issues labeled 'good first issue' or 'help wanted')", | |
| examples=[ | |
| ["fastapi", "python", 5, 1, ""], | |
| ["react", "javascript", 3, 1, ""], | |
| ["machine-learning", None, 2, 1, ""], | |
| [None, "web-development", 4, 1, ""] | |
| ] | |
| ) | |
| # Launch with MCP server enabled | |
| if __name__ == "__main__": | |
| demo.launch(mcp_server=True) |