| import re |
| import traceback |
| import asyncio |
| from typing import Literal |
|
|
|
|
| def handle_error(e: Exception): |
| |
| if isinstance(e, asyncio.CancelledError): |
| raise e |
|
|
|
|
| def error_text(e: Exception): |
| return str(e) |
|
|
|
|
| def format_error( |
| e: Exception, |
| start_entries=20, |
| end_entries=15, |
| error_message_position: Literal["top", "bottom", "none"] = "top", |
| ): |
| |
| traceback_text = "".join(traceback.format_exception(type(e), e, e.__traceback__)) |
| |
| lines = traceback_text.split("\n") |
|
|
| if not start_entries and not end_entries: |
| trimmed_lines = [] |
| else: |
|
|
| |
| file_indices = [ |
| i for i, line in enumerate(lines) if line.strip().startswith("File ") |
| ] |
|
|
| |
| if len(file_indices) > start_entries + end_entries: |
| start_index = max(0, len(file_indices) - start_entries - end_entries) |
| trimmed_lines = ( |
| lines[: file_indices[start_index]] |
| + [ |
| f"\n>>> {len(file_indices) - start_entries - end_entries} stack lines skipped <<<\n" |
| ] |
| + lines[file_indices[start_index + end_entries] :] |
| ) |
| else: |
| |
| trimmed_lines = lines |
|
|
| |
| error_message = "" |
| for line in reversed(lines): |
| |
| if re.match(r"[\w\.]+Error:\s*", line): |
| error_message = line |
| break |
|
|
| if error_message and error_message_position in ("top", "bottom", "none"): |
| for i in range(len(trimmed_lines) - 1, -1, -1): |
| if trimmed_lines[i].strip() == error_message.strip(): |
| trimmed_lines = trimmed_lines[:i] + trimmed_lines[i + 1 :] |
| break |
|
|
| |
| if not trimmed_lines: |
| result = "" if error_message_position == "none" else error_message |
| else: |
| result = "Traceback (most recent call last):\n" + "\n".join(trimmed_lines) |
|
|
| if error_message and error_message_position == "top": |
| result = f"{error_message}\n\n{result}" if result else error_message |
| elif error_message and error_message_position == "bottom": |
| result = f"{result}\n\n{error_message}" if result else error_message |
|
|
| |
| if not result: |
| result = str(e) |
|
|
| return result |
|
|
|
|
| class RepairableException(Exception): |
| """An exception type indicating errors that can be surfaced to the LLM for potential self-repair.""" |
|
|
| pass |
|
|
|
|
| class InterventionException(Exception): |
| """An exception type raised on user intervention, skipping rest of message loop iteration.""" |
|
|
| pass |
|
|
|
|
| class HandledException(Exception): |
| pass |
|
|