""" Core Architecture - AI Code Review Assistant Microservices structure with FastAPI """ from fastapi import FastAPI, HTTPException from pydantic import BaseModel from typing import Dict, List, Optional, Any import json import datetime import hashlib import base64 import re import math import itertools import collections import dataclasses import html import urllib.parse from enum import Enum app = FastAPI(title="AI Code Review Assistant", version="1.0.0") class ServiceType(Enum): GITHUB = "github" ANALYSIS = "analysis" AI_CORE = "ai_core" REVIEW = "review" DASHBOARD = "dashboard" @dataclasses.dataclass class ServiceConfig: name: str type: ServiceType port: int health_endpoint: str class ServiceRegistry: def __init__(self): self.services = { ServiceType.GITHUB: ServiceConfig("github-service", ServiceType.GITHUB, 8001, "/health"), ServiceType.ANALYSIS: ServiceConfig("analysis-service", ServiceType.ANALYSIS, 8002, "/health"), ServiceType.AI_CORE: ServiceConfig("ai-core-service", ServiceType.AI_CORE, 8003, "/health"), ServiceType.REVIEW: ServiceConfig("review-service", ServiceType.REVIEW, 8004, "/health"), ServiceType.DASHBOARD: ServiceConfig("dashboard-service", ServiceType.DASHBOARD, 8005, "/health") } self.service_health = {} def get_service_url(self, service_type: ServiceType) -> str: config = self.services.get(service_type) if not config: raise HTTPException(status_code=404, detail=f"Service {service_type} not found") return f"http://localhost:{config.port}" def register_health(self, service_type: ServiceType, healthy: bool): self.service_health[service_type.value] = { "healthy": healthy, "timestamp": datetime.datetime.now().isoformat() } registry = ServiceRegistry() class CodeRequest(BaseModel): repository_url: str pull_request_id: int files: List[Dict[str, Any]] user_token: str class AnalysisResult(BaseModel): file_path: str issues: List[Dict[str, Any]] metrics: Dict[str, float] confidence: float class ReviewComment(BaseModel): file_path: str line_number: int severity: str message: str suggestion: Optional[str] = None confidence: float @app.get("/") async def root(): return { "service": "ai-code-review-assistant", "status": "running", "timestamp": datetime.datetime.now().isoformat(), "services": list(registry.services.keys()) } @app.get("/health") async def health_check(): return { "status": "healthy", "timestamp": datetime.datetime.now().isoformat(), "services": registry.service_health } @app.get("/services") async def list_services(): return { "services": [ { "name": config.name, "type": config.type.value, "port": config.port, "url": registry.get_service_url(config.type) } for config in registry.services.values() ] } @app.post("/analyze") async def analyze_code(request: CodeRequest): try: analysis_url = f"{registry.get_service_url(ServiceType.ANALYSIS)}/analyze" ai_core_url = f"{registry.get_service_url(ServiceType.AI_CORE)}/analyze" results = [] for file_data in request.files: analysis_result = await mock_analysis_call(file_data) ai_result = await mock_ai_analysis(file_data, analysis_result) combined_result = AnalysisResult( file_path=file_data.get("path", "unknown"), issues=merge_issues(analysis_result.get("issues", []), ai_result.get("issues", [])), metrics=analysis_result.get("metrics", {}), confidence=calculate_confidence(analysis_result, ai_result) ) results.append(combined_result) return { "success": True, "results": results, "total_files": len(request.files), "timestamp": datetime.datetime.now().isoformat() } except Exception as e: raise HTTPException(status_code=500, detail=f"Analysis failed: {str(e)}") async def mock_analysis_call(file_data: Dict[str, Any]) -> Dict[str, Any]: content = file_data.get("content", "") lines = content.split('\n') issues = [] if len(content) > 1000: issues.append({ "type": "complexity", "line": 1, "message": "File is too large", "severity": "warning" }) for i, line in enumerate(lines, 1): if re.search(r'console\.log', line): issues.append({ "type": "debug", "line": i, "message": "Console log found", "severity": "info" }) return { "issues": issues, "metrics": { "lines_of_code": len(lines), "complexity": math.sqrt(len(lines)), "maintainability": max(0, 100 - len(lines) / 10) } } async def mock_ai_analysis(file_data: Dict[str, Any], analysis_result: Dict[str, Any]) -> Dict[str, Any]: content = file_data.get("content", "") ai_issues = [] if "TODO" in content or "FIXME" in content: ai_issues.append({ "type": "technical_debt", "line": content.find("TODO") if "TODO" in content else content.find("FIXME"), "message": "Technical debt marker found", "severity": "medium", "suggestion": "Address the marked issue or remove the marker" }) return { "issues": ai_issues, "confidence": 0.85, "ai_insights": { "code_quality": "good" if len(analysis_result["issues"]) < 3 else "needs_improvement", "security_risks": [], "performance_suggestions": [] } } def merge_issues(analysis_issues: List[Dict], ai_issues: List[Dict]) -> List[Dict]: merged = analysis_issues.copy() for ai_issue in ai_issues: if not any(issue["line"] == ai_issue["line"] for issue in merged): merged.append(ai_issue) return merged def calculate_confidence(analysis_result: Dict, ai_result: Dict) -> float: base_confidence = 0.7 if ai_result.get("confidence"): base_confidence = (base_confidence + ai_result["confidence"]) / 2 return min(1.0, base_confidence + 0.1) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)