Spaces:
Sleeping
Sleeping
| """ | |
| utils/error_cache.py | |
| -------------------- | |
| Error classification cache for AutoDevAgent. | |
| Tracks error fingerprints (cache_keys) across debug iterations within | |
| a single pipeline run. When the same error appears in consecutive | |
| iterations, the debug agent has already tried one fix that did not work | |
| β continuing with the same strategy is pointless. | |
| When a repeated error is detected, the DebugAgent escalates to a | |
| fundamentally different fix strategy rather than patching the same line. | |
| Design: | |
| - Keyed by the normalised error fingerprint (cache_key from | |
| ErrorClassification, e.g. "NameError:x_not_defined"). | |
| - Records the count of how many times each key has been seen. | |
| - "Repeated" means seen more than once β i.e. the same error | |
| appeared in at least two consecutive iterations. | |
| - Reset between pipeline runs so state does not bleed across tasks. | |
| Usage: | |
| from utils.error_cache import ErrorCache | |
| cache = ErrorCache() | |
| cache.record("NameError:x_not_defined") | |
| cache.is_repeated("NameError:x_not_defined") # False (seen once) | |
| cache.record("NameError:x_not_defined") | |
| cache.is_repeated("NameError:x_not_defined") # True (seen twice) | |
| cache.reset() | |
| """ | |
| import logging | |
| from collections import defaultdict | |
| logger = logging.getLogger(__name__) | |
| class ErrorCache: | |
| """ | |
| Tracks how many times each error fingerprint has been seen. | |
| One instance is created per module (in debug_agent.py) and shared | |
| across all DebugAgent calls within a session. Call reset() at the | |
| start of each new pipeline run to clear stale state. | |
| Attributes: | |
| _counts: Dict mapping cache_key β number of times seen. | |
| """ | |
| def __init__(self) -> None: | |
| """Initialise an empty cache.""" | |
| self._counts: dict[str, int] = defaultdict(int) | |
| def record(self, cache_key: str) -> None: | |
| """ | |
| Record one occurrence of an error fingerprint. | |
| Args: | |
| cache_key: Normalised error fingerprint from ErrorClassification. | |
| e.g. "NameError:x_not_defined" | |
| """ | |
| self._counts[cache_key] += 1 | |
| logger.debug( | |
| "ErrorCache recorded '%s' (count: %d)", | |
| cache_key, | |
| self._counts[cache_key], | |
| ) | |
| def is_repeated(self, cache_key: str) -> bool: | |
| """ | |
| Return True if this error has been seen more than once. | |
| A count of 1 means it appeared this iteration for the first time. | |
| A count of 2+ means a previous fix attempt did not resolve it. | |
| Args: | |
| cache_key: Normalised error fingerprint to check. | |
| Returns: | |
| True if seen more than once, False otherwise. | |
| """ | |
| return self._counts[cache_key] > 1 | |
| def count(self, cache_key: str) -> int: | |
| """ | |
| Return how many times an error fingerprint has been seen. | |
| Args: | |
| cache_key: Normalised error fingerprint to look up. | |
| Returns: | |
| Integer count, 0 if never seen. | |
| """ | |
| return self._counts[cache_key] | |
| def reset(self) -> None: | |
| """ | |
| Clear all recorded error counts. | |
| Call this at the start of each new pipeline run to prevent | |
| error state from one task bleeding into the next. | |
| """ | |
| cleared = len(self._counts) | |
| self._counts.clear() | |
| logger.debug("ErrorCache reset β cleared %d entries", cleared) | |
| def summary(self) -> dict[str, int]: | |
| """ | |
| Return a snapshot of all recorded error counts. | |
| Useful for session history logging and debugging. | |
| Returns: | |
| Dict of cache_key β count for all recorded errors. | |
| """ | |
| return dict(self._counts) | |