Spaces:
Sleeping
Sleeping
| """Gradio demo for the AI Code Reviewer, published as a HuggingFace Space. | |
| Reuses the same prompt templates and Qwen endpoint as the MCP server. | |
| """ | |
| from __future__ import annotations | |
| import os | |
| from collections.abc import Iterator | |
| import gradio as gr | |
| from reviewer import ( | |
| ANALYSIS_LABELS, | |
| GitHubRepo, | |
| build_context, | |
| check_llm_health, | |
| parse_target, | |
| render_result, | |
| run_analysis, | |
| ) | |
| GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN") | |
| CHOICES = [(label, key) for key, label in ANALYSIS_LABELS.items()] | |
| DEFAULT = ["review", "bugs"] | |
| def review(target: str, analyses: list[str]) -> Iterator[str]: | |
| yield "_Starting review..._" | |
| target = (target or "").strip() | |
| if not target: | |
| yield "Please enter a GitHub repository (e.g. `owner/repo` or a repo URL)." | |
| return | |
| if not analyses: | |
| yield "Please select at least one analysis." | |
| return | |
| try: | |
| yield "_Checking Qwen endpoint..._" | |
| check_llm_health() | |
| ref = parse_target(target) | |
| repo = GitHubRepo(ref, token=GITHUB_TOKEN) | |
| yield f"Fetching `{repo.describe()}`..." | |
| context, included = build_context(repo) | |
| except Exception as exc: # noqa: BLE001 - surface any fetch error to the UI | |
| yield f"Failed to load repository: {exc}" | |
| return | |
| report = [f"# AI Code Review Report\n\n_Target: {repo.describe()}_"] | |
| for analysis_type in analyses: | |
| label = ANALYSIS_LABELS.get(analysis_type, analysis_type) | |
| yield "\n\n---\n\n".join(report) + f"\n\n---\n\n_Running {label} analysis..._" | |
| try: | |
| result = run_analysis(repo, analysis_type, context) | |
| report.append(render_result(analysis_type, repo.describe(), result, len(included))) | |
| except Exception as exc: # noqa: BLE001 | |
| report.append(f"## {label}\n\n_Analysis failed: {exc}_") | |
| yield "\n\n---\n\n".join(report) | |
| def _setup_banner() -> str: | |
| base_url = os.environ.get("QWEN_BASE_URL", "").strip() | |
| api_key = os.environ.get("QWEN_API_KEY", "").strip() | |
| if base_url and api_key: | |
| return ( | |
| "**Endpoint configured.** Enter a public GitHub repo below. " | |
| "Each analysis takes ~30–90 s on your GPU server." | |
| ) | |
| missing = [] | |
| if not base_url: | |
| missing.append("`QWEN_BASE_URL`") | |
| if not api_key: | |
| missing.append("`QWEN_API_KEY`") | |
| return ( | |
| "> **Setup required** — this Space calls a **self-hosted** Qwen endpoint. " | |
| f"Add Space secrets: {', '.join(missing)}. " | |
| "See the [README](https://huggingface.co/spaces/ImTamsi/ai-code-reviewer) " | |
| "and [deployment config](https://huggingface.co/ImTamsi/qwen3.6-27b-code-reviewer)." | |
| ) | |
| with gr.Blocks(title="AI Code Reviewer", theme=gr.themes.Soft()) as demo: | |
| gr.Markdown( | |
| """ | |
| # AI Code Reviewer | |
| Analyze any public GitHub repository with **Qwen3.6-27B** (self-hosted): | |
| code review, potential bugs, technical debt, security, performance and | |
| missing tests. | |
| """ | |
| ) | |
| gr.Markdown(_setup_banner()) | |
| with gr.Row(): | |
| target = gr.Textbox( | |
| label="GitHub repository", | |
| placeholder="owner/repo or https://github.com/owner/repo", | |
| scale=3, | |
| ) | |
| run_btn = gr.Button("Review", variant="primary", scale=1) | |
| analyses = gr.CheckboxGroup( | |
| choices=CHOICES, value=DEFAULT, label="Analyses to run" | |
| ) | |
| output = gr.Markdown(label="Report") | |
| gr.Examples( | |
| examples=[["psf/requests", DEFAULT], ["tiangolo/fastapi", ["security", "bugs"]]], | |
| inputs=[target, analyses], | |
| ) | |
| run_btn.click( | |
| fn=review, | |
| inputs=[target, analyses], | |
| outputs=output, | |
| show_progress="full", | |
| ) | |
| target.submit( | |
| fn=review, | |
| inputs=[target, analyses], | |
| outputs=output, | |
| show_progress="full", | |
| ) | |
| # Required for generator/streaming handlers on HuggingFace Spaces and locally. | |
| demo.queue(max_size=8) | |
| if __name__ == "__main__": | |
| demo.launch() | |