Initial upload: CLI Explain Fix project with CI/CD workflow
Some checks failed
CI / test (push) Has been cancelled
CI / build (push) Has been cancelled

This commit is contained in:
2026-01-30 23:35:13 +00:00
parent e4e0097554
commit d2e86de1e1

View File

@@ -0,0 +1,156 @@
"""Knowledge base module for error explanations."""
import re
from dataclasses import dataclass
from typing import Dict, List, Optional, Any
from pathlib import Path
import yaml
@dataclass
class ErrorExplanation:
"""Container for error explanation data."""
error_type: str
language: str
what_happened: str
why_happened: str
how_to_fix: List[str]
code_snippets: Optional[List[Dict[str, str]]] = None
documentation_url: Optional[str] = None
severity: str = "medium"
def __post_init__(self):
if self.code_snippets is None:
self.code_snippets = []
class KnowledgeBase:
"""Knowledge base for error explanations."""
base_path: Path
def __init__(self, base_path: Optional[str] = None):
"""Initialize knowledge base with error definitions."""
self._errors: Dict[str, Dict[str, Any]] = {}
self._patterns: Dict[str, List[Dict[str, Any]]] = {}
if base_path is None:
self.base_path = Path(__file__).parent.parent.parent / 'knowledge_base'
else:
self.base_path = Path(base_path)
self._load_knowledge_base()
def _load_knowledge_base(self) -> None:
"""Load all YAML files from knowledge base directory."""
errors_file = self.base_path / 'errors.yaml'
patterns_file = self.base_path / 'patterns.yaml'
if errors_file.exists():
try:
with open(errors_file, 'r', encoding='utf-8') as f:
data = yaml.safe_load(f) or {}
if 'errors' in data:
for error_def in data['errors']:
key = f"{error_def.get('language', 'unknown')}_{error_def.get('error_type', 'Unknown')}"
self._errors[key] = error_def
except (yaml.YAMLError, OSError):
pass
if patterns_file.exists():
try:
with open(patterns_file, 'r', encoding='utf-8') as f:
data = yaml.safe_load(f) or {}
if 'patterns' in data:
self._patterns = data['patterns']
except (yaml.YAMLError, OSError):
pass
def get_explanation(self, error_type: str, language: str) -> Optional[ErrorExplanation]:
"""Get explanation for a specific error type and language."""
key = f"{language}_{error_type}"
if key in self._errors:
error_def = self._errors[key]
return ErrorExplanation(
error_type=error_type,
language=language,
what_happened=error_def.get('what_happened', 'An error occurred.'),
why_happened=error_def.get('why_happened', 'Unknown reason.'),
how_to_fix=error_def.get('how_to_fix', []),
code_snippets=error_def.get('code_snippets', []),
documentation_url=error_def.get('documentation_url'),
severity=error_def.get('severity', 'medium'),
)
generic_key = f"{language}_Generic"
if generic_key in self._errors:
error_def = self._errors[generic_key]
return ErrorExplanation(
error_type=error_type,
language=language,
what_happened=f"Received a {error_type} error.",
why_happened=error_def.get('why_happened', 'The operation failed due to an error.'),
how_to_fix=error_def.get('how_to_fix', []),
code_snippets=error_def.get('code_snippets', []),
documentation_url=error_def.get('documentation_url'),
severity=error_def.get('severity', 'medium'),
)
return None
def find_by_pattern(self, message: str, language: str) -> Optional[ErrorExplanation]:
"""Find explanation by matching error message against patterns."""
if language not in self._patterns:
return None
for pattern_def in self._patterns[language]:
pattern = pattern_def.get('pattern', '')
if re.search(pattern, message, re.IGNORECASE):
return ErrorExplanation(
error_type=pattern_def.get('error_type', 'Unknown'),
language=language,
what_happened=pattern_def.get('what_happened', ''),
why_happened=pattern_def.get('why_happened', ''),
how_to_fix=pattern_def.get('how_to_fix', []),
code_snippets=pattern_def.get('code_snippets', []),
documentation_url=pattern_def.get('documentation_url'),
severity=pattern_def.get('severity', 'medium'),
)
return None
def list_languages(self) -> List[str]:
"""List all supported languages."""
languages = set()
for key in self._errors:
parts = key.split('_', 1)
if len(parts) >= 1:
languages.add(parts[0])
return sorted(languages)
def list_errors(self, language: Optional[str] = None) -> List[Dict[str, str]]:
"""List all known errors, optionally filtered by language."""
errors = []
for key, error_def in self._errors.items():
if language is None or key.startswith(f"{language}_"):
errors.append({
'error_type': error_def.get('error_type', key),
'language': error_def.get('language', 'unknown'),
'description': error_def.get('what_happened', '')[:100],
})
return errors
def get_fallback_explanation(self, error_type: str, language: str) -> ErrorExplanation:
"""Generate a fallback explanation for unknown errors."""
return ErrorExplanation(
error_type=error_type,
language=language,
what_happened=f"A {error_type} error was encountered.",
why_happened="The specific cause of this error is not in the knowledge base.",
how_to_fix=[
"Check the error message for specific details about what went wrong.",
"Search for the exact error message online.",
f"Ensure you're using the correct syntax for {language}.",
"Verify that all required dependencies are installed.",
],
severity="unknown",
)