Spaces:
Sleeping
Sleeping
Download app/services/convention_service.py from CodeCommunity/gitgud-ai: direct link, hf CLI and curl.
- Browser
- Download file 3.96 kB
-
https://huggingface.co/spaces/CodeCommunity/gitgud-ai/resolve/main/app/services/convention_service.py
- Command line
-
hf download hf://spaces/CodeCommunity/gitgud-ai/app/services/convention_service.py
-
curl -L -o convention_service.py https://huggingface.co/spaces/CodeCommunity/gitgud-ai/resolve/main/app/services/convention_service.py
3.96 kB
| import logging | |
| import re | |
| import json | |
| from typing import Dict, Any, Optional | |
| import httpx | |
| from app.core.model_loader import llm_engine | |
| logger = logging.getLogger(__name__) | |
| class ConventionService: | |
| def __init__(self): | |
| self.cache: Dict[str, Dict[str, Any]] = {} | |
| async def get_conventions(self, owner: str, repo: str) -> Dict[str, Any]: | |
| key = f"{owner}/{repo}" | |
| if key in self.cache: | |
| return self.cache[key] | |
| # 1. Fetch recent commits from GitHub | |
| commits = await self._fetch_recent_commits(owner, repo, limit=40) | |
| if not commits: | |
| return self._default_conventions() | |
| commit_text = "\n".join([c.get("message", "")[:200] for c in commits[:30]]) | |
| # 2. Ask the LLM to infer conventions | |
| prompt = f"""Analyze these recent commit messages and return ONLY a valid JSON object with these keys: | |
| - "commit_style": either "conventional_commits" or "plain" | |
| - "branch_naming_pattern": a short regex or example pattern (e.g. "feat/.*", "feature/*") | |
| - "merge_policy": "squash", "merge", "rebase" or "unknown" | |
| - "exampleGoodCommit": one good example from the history | |
| Commit history: | |
| {commit_text} | |
| """ | |
| try: | |
| raw = llm_engine.generate(prompt, max_tokens=250) | |
| conventions = self._parse_json(raw) | |
| except Exception as e: | |
| logger.warning(f"LLM convention inference failed: {e}") | |
| conventions = self._default_conventions() | |
| # Enrich | |
| if commits: | |
| conventions["exampleGoodCommit"] = commits[0].get("message", "")[:120] | |
| conventions.setdefault("commit_style", "plain") | |
| conventions.setdefault("branch_naming_pattern", "feature/*") | |
| conventions.setdefault("merge_policy", "unknown") | |
| self.cache[key] = conventions | |
| return conventions | |
| async def _fetch_recent_commits(self, owner: str, repo: str, limit: int = 30) -> list: | |
| url = f"https://api.github.com/repos/{owner}/{repo}/commits" | |
| params = {"per_page": min(limit, 100)} | |
| headers = {"Accept": "application/vnd.github.v3+json"} | |
| # Optional: add a GitHub token if you have one in env for higher rate limits | |
| token = None # os.getenv("GITHUB_TOKEN") | |
| if token: | |
| headers["Authorization"] = f"token {token}" | |
| try: | |
| async with httpx.AsyncClient(timeout=15.0) as client: | |
| resp = await client.get(url, params=params, headers=headers) | |
| if resp.status_code != 200: | |
| logger.warning(f"GitHub commits API {resp.status_code}") | |
| return [] | |
| data = resp.json() | |
| return [ | |
| { | |
| "message": c.get("commit", {}).get("message", ""), | |
| "sha": c.get("sha", ""), | |
| "author": c.get("commit", {}).get("author", {}).get("name", ""), | |
| } | |
| for c in data | |
| ] | |
| except Exception as e: | |
| logger.error(f"Failed to fetch commits: {e}") | |
| return [] | |
| def _parse_json(self, text: str) -> dict: | |
| text = text.strip() | |
| text = re.sub(r"```(?:json)?", "", text, flags=re.IGNORECASE).strip() | |
| try: | |
| return json.loads(text) | |
| except json.JSONDecodeError: | |
| start = text.find("{") | |
| end = text.rfind("}") | |
| if start != -1 and end > start: | |
| try: | |
| return json.loads(text[start : end + 1]) | |
| except Exception: | |
| pass | |
| return self._default_conventions() | |
| def _default_conventions(self) -> dict: | |
| return { | |
| "commit_style": "plain", | |
| "branch_naming_pattern": "feature/*", | |
| "merge_policy": "unknown", | |
| "exampleGoodCommit": "Update something", | |
| } | |
| # Singleton-style instance | |
| convention_service = ConventionService() |