"""Typed adapter exceptions. Core catches these specifically.""" class AdapterError(Exception): """Base for all adapter errors.""" pass class ConfigWriteError(AdapterError): """Atomic file write failed. Temp files are already cleaned up.""" def __init__(self, path: str, detail: str): self.path = path self.detail = detail super().__init__(f"Config write failed at {path}: {detail}") class ConfigValidationError(AdapterError): """Adapter Pydantic model rejected the config values.""" def __init__(self, section: str, errors: list[dict]): self.section = section self.errors = errors super().__init__(f"Config validation failed for section '{section}': {errors}") class ConfigMigrationError(AdapterError): """migrate_config() could not transform old schema. Core keeps original.""" def __init__(self, from_version: str, detail: str): self.from_version = from_version self.detail = detail super().__init__(f"Config migration from {from_version} failed: {detail}") class LaunchArgsError(AdapterError): """build_launch_args() failed (missing mod path, bad config value).""" def __init__(self, detail: str): self.detail = detail super().__init__(f"Launch args error: {detail}") class RemoteAdminError(AdapterError): """Remote admin connection or command failed.""" def __init__(self, detail: str, recoverable: bool = True): self.detail = detail self.recoverable = recoverable super().__init__(f"Remote admin error: {detail}") class ExeNotAllowedError(AdapterError): """Executable not in adapter allowlist.""" def __init__(self, exe: str, allowed: list[str]): self.exe = exe self.allowed = allowed super().__init__(f"Executable '{exe}' not allowed. Allowed: {allowed}")