Manim-Agent / ai_engine /rag /log_parser.py
github-actions[bot]
[API] Cuong2004/Manim-Agent @ 1d7c417 (run 25583057312)
9bed109
from __future__ import annotations
import re
from dataclasses import dataclass
@dataclass
class ParsedError:
error_type: (
str # "AttributeError", "TypeError", "ImportError", "NameError", "SyntaxError", etc.
)
symbol: str | None # Extracted symbol: "play_text", "ShowCreation", etc.
invalid_arg: str | None # For TypeError: what arg was wrong
traceback_tail: str # Last few lines of traceback
line_number: int | None # Extracted from "line XX" in traceback
raw_message: str
def parse_render_error(error_logs: str) -> ParsedError:
"""Extract structured error info from Manim render logs."""
# 1. Get the last line (the error message itself)
lines = [line.strip() for line in error_logs.strip().split("\n") if line.strip()]
if not lines:
return ParsedError("UnknownError", None, None, "", None, error_logs)
last_line = lines[-1]
# 2. Extract Traceback Tail
traceback_tail = "\n".join(lines[-5:]) if len(lines) >= 5 else "\n".join(lines)
# 3. Extract Line Number
line_match = re.search(r'File ".*", line (\d+)', error_logs)
line_number = int(line_match.group(1)) if line_match else None
# 4. Classification & Symbol Extraction
error_type = "UnknownError"
symbol = None
invalid_arg = None
# AttributeError: 'Scene' object has no attribute 'play_text'
if "AttributeError" in last_line:
error_type = "AttributeError"
match = re.search(r"has no attribute '([^']+)'", last_line)
if match:
symbol = match.group(1)
# NameError: name 'ShowCreation' is not defined
elif "NameError" in last_line:
error_type = "NameError"
match = re.search(r"name '([^']+)' is not defined", last_line)
if match:
symbol = match.group(1)
# TypeError: play() got an unexpected keyword argument 'run_time_extra'
elif "TypeError" in last_line:
error_type = "TypeError"
# Function/Class match: "TypeError: play() got..."
match_func = re.search(r"(?:TypeError:\s*)?(\w+)\(\)", last_line)
if match_func:
symbol = match_func.group(1)
# Arg match
match_arg = re.search(r"unexpected keyword argument '([^']+)'", last_line)
if match_arg:
invalid_arg = match_arg.group(1)
# ImportError: cannot import name 'X' from 'Y'
elif "ImportError" in last_line or "ModuleNotFoundError" in last_line:
error_type = "ImportError"
match = re.search(r"cannot import name '([^']+)'", last_line)
if not match:
match = re.search(r"No module named '([^']+)'", last_line)
if match:
symbol = match.group(1)
# SyntaxError: invalid syntax (file, line N)
elif "SyntaxError" in last_line:
error_type = "SyntaxError"
# LaTeX compilation error
elif "LaTeX compilation" in error_logs or "Missing $" in error_logs:
error_type = "LatexError"
symbol = "LaTeX"
# Generic catch-all for ErrorName: Message
if error_type == "UnknownError":
match = re.search(r"^(\w+Error):", last_line)
if match:
error_type = match.group(1)
return ParsedError(
error_type=error_type,
symbol=symbol,
invalid_arg=invalid_arg,
traceback_tail=traceback_tail,
line_number=line_number,
raw_message=last_line,
)