From e4e009755463716969775012012312b4870cc3a1 Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Fri, 30 Jan 2026 23:35:12 +0000 Subject: [PATCH] Initial upload: CLI Explain Fix project with CI/CD workflow --- src/cli_explain_fix/explainer.py | 131 +++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/cli_explain_fix/explainer.py diff --git a/src/cli_explain_fix/explainer.py b/src/cli_explain_fix/explainer.py new file mode 100644 index 0000000..003ff7b --- /dev/null +++ b/src/cli_explain_fix/explainer.py @@ -0,0 +1,131 @@ +"""Explanation generation module.""" + +from typing import Dict, Any, Optional + +from cli_explain_fix.knowledge_base import KnowledgeBase, ErrorExplanation +from cli_explain_fix.parser import ParsedError + + +class Explainer: + """Generator for human-readable error explanations.""" + + def __init__(self, knowledge_base: Optional[KnowledgeBase] = None): + """Initialize explainer with optional knowledge base.""" + self.knowledge_base = knowledge_base or KnowledgeBase() + + def explain(self, parsed_error: ParsedError, verbose: bool = False) -> Dict[str, Any]: + """Generate a complete explanation for a parsed error.""" + explanation = self.knowledge_base.get_explanation( + parsed_error.error_type, + parsed_error.language + ) + + if not explanation: + explanation = self.knowledge_base.find_by_pattern( + parsed_error.message, + parsed_error.language + ) + + if not explanation: + explanation = self.knowledge_base.get_fallback_explanation( + parsed_error.error_type, + parsed_error.language + ) + + result: Dict[str, Any] = { + 'error_type': parsed_error.error_type, + 'language': parsed_error.language, + 'summary': self._generate_summary(explanation), + 'what_happened': explanation.what_happened, + 'why_happened': explanation.why_happened, + 'how_to_fix': explanation.how_to_fix, + 'severity': explanation.severity, + } + + if parsed_error.file_name: + result['location'] = { + 'file': parsed_error.file_name, + 'line': parsed_error.line_number, + } + + if parsed_error.stack_frames: + result['stack_trace'] = parsed_error.stack_frames + + if explanation.code_snippets: + code_examples = self._format_code_examples(explanation.code_snippets) + result['code_examples'] = code_examples + + if explanation.documentation_url: + result['documentation'] = explanation.documentation_url + + if verbose: + result['raw_error'] = parsed_error.raw_input + + return result + + def _generate_summary(self, explanation: ErrorExplanation) -> str: + """Generate a short summary of the explanation.""" + severity_icons = { + 'critical': '🔴', + 'high': '🟠', + 'medium': '🟡', + 'low': '🟢', + 'unknown': '⚪', + } + icon = severity_icons.get(explanation.severity, '⚪') + + return f"{icon} {explanation.error_type} in {explanation.language}" + + def _format_code_examples(self, code_snippets: list) -> list: + """Format code snippets for display.""" + formatted = [] + for snippet in code_snippets: + formatted.append({ + 'description': snippet.get('description', ''), + 'code': snippet.get('code', ''), + 'language': snippet.get('language', 'text'), + }) + return formatted + + def get_fix_steps(self, parsed_error: ParsedError) -> list: + """Get step-by-step fix instructions.""" + explanation = self.knowledge_base.get_explanation( + parsed_error.error_type, + parsed_error.language + ) + + if not explanation: + explanation = self.knowledge_base.get_fallback_explanation( + parsed_error.error_type, + parsed_error.language + ) + + return explanation.how_to_fix + + def explain_simple(self, error_type: str, message: str, language: str) -> str: + """Generate a simple text explanation.""" + explanation = self.knowledge_base.get_explanation(error_type, language) + + if not explanation: + explanation = self.knowledge_base.get_fallback_explanation( + error_type, + language + ) + + lines = [ + f"Error: {error_type}", + f"Language: {language}", + "", + "What happened:", + explanation.what_happened, + "", + "Why it happened:", + explanation.why_happened, + "", + "How to fix:", + ] + + for i, step in enumerate(explanation.how_to_fix, 1): + lines.append(f" {i}. {step}") + + return "\n".join(lines)