Spaces:
Sleeping
Sleeping
| # main.py - Final Fixed Version | |
| from fastapi import FastAPI, HTTPException | |
| from pydantic import BaseModel | |
| from typing import List, Optional | |
| import re | |
| import logging | |
| from app.services.reviewer_service import AIReviewerService | |
| from app.predictor import classifier, guide_generator | |
| # 1. Setup Logging | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| # 2. Initialize FastAPI and Services | |
| app = FastAPI(title="GitGud AI Service") | |
| reviewer_service = AIReviewerService() | |
| # 3. Data Models (Order matters: ReviewRequest needs FileRequest) | |
| class FileRequest(BaseModel): | |
| fileName: str | |
| content: Optional[str] = None | |
| class ReviewRequest(BaseModel): | |
| files: List[FileRequest] | |
| class GuideRequest(BaseModel): | |
| repoName: str | |
| filePaths: List[str] | |
| # 4. Endpoints | |
| def health_check(): | |
| """Checks server status and GPU availability.""" | |
| return { | |
| "status": "online", | |
| "model": "microsoft/codebert-base", | |
| "device": classifier.device, | |
| } | |
| async def classify_file(request: FileRequest): | |
| """Classifies file into architectural layers.""" | |
| try: | |
| result = classifier.predict(request.fileName, request.content) | |
| return { | |
| "fileName": request.fileName, | |
| "layer": result["label"], | |
| "confidence": result["confidence"], | |
| "embedding": result["embedding"] | |
| } | |
| except Exception as e: | |
| logger.error(f"Classify failed: {e}") | |
| raise HTTPException(status_code=500, detail=str(e)) | |
| async def generate_guide(request: GuideRequest): | |
| """Generates markdown guides for repositories.""" | |
| try: | |
| markdown = guide_generator.generate_markdown(request.repoName, request.filePaths) | |
| return {"markdown": markdown} | |
| except Exception as e: | |
| logger.error(f"Guide generation failed: {e}") | |
| raise HTTPException(status_code=500, detail=str(e)) | |
| async def review_code(request: ReviewRequest): | |
| """Detects security and logic issues in batches of files.""" | |
| try: | |
| # Call the batch review logic from your service | |
| results = reviewer_service.review_batch_code(request.files) | |
| return {"reviews": results} | |
| except Exception as e: | |
| logger.error(f"Review endpoint failed: {e}") | |
| raise HTTPException(status_code=500, detail=str(e)) | |
| async def get_dashboard_stats(request: ReviewRequest): | |
| try: | |
| raw_reviews = reviewer_service.review_batch_code(request.files) | |
| # 1. Security Count | |
| total_vulns = sum(len(r.get("vulnerabilities", [])) for r in raw_reviews) | |
| # 2. Performance Ratio (Maintainability) | |
| # We use a default of 8 if the AI misses a file to avoid 0% scores | |
| scores = [r.get("metrics", {}).get("maintainability", 8) for r in raw_reviews] | |
| avg_maintainability = (sum(scores) / len(scores)) * 10 if scores else 0 | |
| # 3. API Sniffing | |
| found_apis = [] | |
| for f in request.files: | |
| if f.content: | |
| # Regex looks for common route decorators or methods | |
| matches = re.findall(r'(?:get|post|put|delete|patch)\([\'"]\/(.*?)[\'"]', f.content.lower()) | |
| for match in matches: | |
| found_apis.append(f"/{match}") | |
| # 4. Repo Health Calculation | |
| # Every security issue drops health by 10 points | |
| health_score = max(10, 100 - (total_vulns * 10)) | |
| return { | |
| "repo_health": health_score, | |
| "health_label": "Excellent Health" if health_score > 80 else "Needs Review", | |
| "security_issues": total_vulns, | |
| "performance_ratio": f"{int(avg_maintainability)}%", | |
| "exposed_apis": list(set(found_apis))[:10] | |
| } | |
| except Exception as e: | |
| logger.error(f"Dashboard stats failed: {e}") | |
| raise HTTPException(status_code=500, detail="Failed to aggregate repository stats") | |
| # 5. Application Entry Point | |
| if __name__ == "__main__": | |
| import uvicorn | |
| # Port 7860 is mandatory for Hugging Face Spaces | |
| uvicorn.run(app, host="0.0.0.0", port=7860) |