Spaces:
Sleeping
Sleeping
| """ | |
| Error classifier - identifies error categories from tracebacks/output. | |
| Used by repair engine to produce targeted repair plans. | |
| """ | |
| from __future__ import annotations | |
| import re | |
| from dataclasses import dataclass | |
| from typing import Optional | |
| class ErrorClass: | |
| category: str | |
| detail: str | |
| suggested_fix: str | |
| RULES = [ | |
| # python module / pip | |
| (r"ModuleNotFoundError: No module named ['\"]([\w\.\-]+)['\"]", "missing_python_module"), | |
| (r"ImportError: No module named ([\w\.\-]+)", "missing_python_module"), | |
| (r"pip(?:3)?: command not found", "missing_pip"), | |
| # node / npm | |
| (r"command not found: (npm|node|npx)", "missing_node"), | |
| (r"npm ERR! code E?ENOENT", "npm_failure"), | |
| (r"npm ERR! code (E\w+)", "npm_failure"), | |
| # playwright | |
| (r"playwright[^\s]*: command not found", "missing_playwright"), | |
| (r"Executable doesn't exist at .+(chrom|firefox|webkit)", "playwright_browsers_missing"), | |
| (r"BrowserType\.launch:.*Host system is missing dependencies", "playwright_missing_deps"), | |
| # git | |
| (r"fatal: unable to auto-detect email address", "git_identity_missing"), | |
| (r"Please tell me who you are\.", "git_identity_missing"), | |
| (r"fatal: not a git repository", "not_a_git_repo"), | |
| (r"Authentication failed", "git_auth_failed"), | |
| # python version / build | |
| (r"greenlet[^\n]*failed to build", "greenlet_build_failure"), | |
| (r"Could not build wheels for ([\w\-]+)", "python_build_failure"), | |
| (r"requires Python ['\"][^'\"]+['\"]", "python_version_mismatch"), | |
| # network | |
| (r"Could not resolve host", "network_failure"), | |
| (r"Connection refused", "network_failure"), | |
| (r"Read timed out", "network_failure"), | |
| # http | |
| (r"\b429\b", "rate_limited"), | |
| (r"\b401\b|\b403\b", "auth_failure"), | |
| ] | |
| def classify(output: str) -> Optional[ErrorClass]: | |
| if not output: | |
| return None | |
| for pattern, category in RULES: | |
| m = re.search(pattern, output) | |
| if m: | |
| detail = m.group(0) | |
| return ErrorClass(category=category, detail=detail, suggested_fix=_fix_for(category, m)) | |
| # Generic exception detection | |
| if "Traceback (most recent call last):" in output: | |
| return ErrorClass(category="python_exception", detail="Unclassified Python exception", suggested_fix="inspect traceback and retry") | |
| return None | |
| def _fix_for(category: str, m: re.Match) -> str: | |
| if category == "missing_python_module": | |
| return f"pip install {m.group(1)}" | |
| if category == "missing_pip": | |
| return "ensure python3-pip is installed" | |
| if category == "missing_node": | |
| return "install node + npm" | |
| if category == "npm_failure": | |
| return "delete node_modules and reinstall" | |
| if category == "missing_playwright": | |
| return "pip install playwright && python -m playwright install" | |
| if category == "playwright_browsers_missing": | |
| return "python -m playwright install chromium" | |
| if category == "playwright_missing_deps": | |
| return "python -m playwright install-deps chromium" | |
| if category == "git_identity_missing": | |
| return "git config user.email and user.name" | |
| if category == "not_a_git_repo": | |
| return "git init or cd into repo" | |
| if category == "git_auth_failed": | |
| return "verify GITHUB_TOKEN and remote URL" | |
| if category == "greenlet_build_failure": | |
| return "pin Python 3.11 and install build essentials" | |
| if category == "python_build_failure": | |
| return "install build-essential and retry" | |
| if category == "python_version_mismatch": | |
| return "use Python 3.11" | |
| if category == "network_failure": | |
| return "retry after backoff" | |
| if category == "rate_limited": | |
| return "rotate provider key or wait" | |
| if category == "auth_failure": | |
| return "rotate API key" | |
| return "retry" | |