Coverage for /home/admin/Documents/AI/applications/lexigram-dev/lexigram/experimental/ai/lexigram-ai-skills/src/lexigram/ai/skills/exceptions.py: 63%
38 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
1"""Exceptions for lexigram-ai-skills."""
3from __future__ import annotations
5from lexigram.contracts.ai.skills import SkillError
8class SkillNotFoundError(SkillError):
9 """Raised when a requested skill is not registered."""
11 _code: str = "LEX_ERR_SKILL_002"
13 def __init__(self, skill_name: str) -> None:
14 """Initialise with the missing skill name.
16 Args:
17 skill_name: Name of the skill that was not found.
18 """
19 super().__init__(f"Skill not found: {skill_name!r}", skill_name=skill_name)
20 self.skill_name = skill_name
23class SkillAlreadyRegisteredError(SkillError):
24 """Raised when a skill is registered under a name that already exists."""
26 _code: str = "LEX_ERR_SKILL_003"
28 def __init__(self, skill_name: str) -> None:
29 """Initialise with the duplicate skill name.
31 Args:
32 skill_name: Name of the skill that was already registered.
33 """
34 super().__init__(
35 f"Skill already registered: {skill_name!r}", skill_name=skill_name
36 )
39class SkillValidationError(SkillError):
40 """Raised when skill parameter validation fails."""
42 _code: str = "LEX_ERR_SKILL_004"
44 def __init__(self, skill_name: str, errors: list[str]) -> None:
45 """Initialise with validation error details.
47 Args:
48 skill_name: Name of the skill that failed validation.
49 errors: List of human-readable validation error messages.
50 """
51 super().__init__(
52 f"Validation failed for {skill_name!r}: {'; '.join(errors)}",
53 skill_name=skill_name,
54 )
55 self.errors = errors
58class SkillPermissionDeniedError(SkillError):
59 """Raised when the caller lacks required permissions for a skill."""
61 _code: str = "LEX_ERR_SKILL_005"
63 def __init__(self, skill_name: str, required: list[str]) -> None:
64 """Initialise with permission details.
66 Args:
67 skill_name: Name of the skill that requires permissions.
68 required: Required permission strings.
69 """
70 super().__init__(
71 f"Permission denied for {skill_name!r}. Required: {required}",
72 skill_name=skill_name,
73 )
74 self.required = required
77class SkillTimeoutError(SkillError):
78 """Raised when skill execution exceeds the configured timeout."""
80 _code: str = "LEX_ERR_SKILL_006"
82 def __init__(self, skill_name: str, timeout_seconds: float) -> None:
83 """Initialise with timeout context.
85 Args:
86 skill_name: Name of the skill that timed out.
87 timeout_seconds: The timeout that was exceeded.
88 """
89 super().__init__(
90 f"Skill {skill_name!r} timed out after {timeout_seconds}s",
91 skill_name=skill_name,
92 )
93 self.skill_name = skill_name
94 self.timeout_seconds = timeout_seconds
97class SkillRoutingError(SkillError):
98 """Raised when a SkillRouter finds no matching route."""
100 _code: str = "LEX_ERR_SKILL_007"
102 def __init__(self, message: str = "No matching route") -> None:
103 """Initialise with an optional detail message.
105 Args:
106 message: Human-readable description of the routing failure.
107 """
108 super().__init__(message)
111class SkillExecutionError(SkillError):
112 """Raised when a skill execution fails after all retry attempts."""
114 _code: str = "LEX_ERR_SKILL_008"
116 def __init__(
117 self,
118 message: str,
119 cause: Exception | None = None,
120 skill_name: str | None = None,
121 ) -> None:
122 """Initialise with an error message and optional cause.
124 Args:
125 message: Human-readable error description.
126 cause: The underlying exception, if any.
127 skill_name: Name of the skill that failed (optional).
128 """
129 super().__init__(message, skill_name=skill_name)
130 self.skill_name = skill_name
131 self.cause = cause
134__all__ = [
135 "SkillAlreadyRegisteredError",
136 "SkillExecutionError",
137 "SkillNotFoundError",
138 "SkillPermissionDeniedError",
139 "SkillRoutingError",
140 "SkillTimeoutError",
141 "SkillValidationError",
142]