class PromptlockError(Exception):
    """Base exception for all promptlock errors."""
    pass


class ContractViolation(PromptlockError):
    """Raised when an LLM output fails contract validation."""

    def __init__(self, message: str, field: str = None):
        self.field = field
        super().__init__(f"[{field}] {message}" if field else message)


class PromptNotFound(PromptlockError):
    """Raised when a prompt name or version does not exist in the registry."""

    def __init__(self, name: str, version: str = None):
        self.name = name
        self.version = version
        msg = f"Prompt '{name}'"
        if version:
            msg += f" version '{version}'"
        super().__init__(f"{msg} not found in registry.")


class TemplateRenderError(PromptlockError):
    """Raised when a required variable is missing during prompt rendering."""

    def __init__(self, missing_vars: list[str]):
        self.missing_vars = missing_vars
        super().__init__(f"Missing required template variables: {missing_vars}")