jaf-py 2.5.10__py3-none-any.whl → 2.5.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jaf/__init__.py +154 -57
- jaf/a2a/__init__.py +42 -21
- jaf/a2a/agent.py +79 -126
- jaf/a2a/agent_card.py +87 -78
- jaf/a2a/client.py +30 -66
- jaf/a2a/examples/client_example.py +12 -12
- jaf/a2a/examples/integration_example.py +38 -47
- jaf/a2a/examples/server_example.py +56 -53
- jaf/a2a/memory/__init__.py +0 -4
- jaf/a2a/memory/cleanup.py +28 -21
- jaf/a2a/memory/factory.py +155 -133
- jaf/a2a/memory/providers/composite.py +21 -26
- jaf/a2a/memory/providers/in_memory.py +89 -83
- jaf/a2a/memory/providers/postgres.py +117 -115
- jaf/a2a/memory/providers/redis.py +128 -121
- jaf/a2a/memory/serialization.py +77 -87
- jaf/a2a/memory/tests/run_comprehensive_tests.py +112 -83
- jaf/a2a/memory/tests/test_cleanup.py +211 -94
- jaf/a2a/memory/tests/test_serialization.py +73 -68
- jaf/a2a/memory/tests/test_stress_concurrency.py +186 -133
- jaf/a2a/memory/tests/test_task_lifecycle.py +138 -120
- jaf/a2a/memory/types.py +91 -53
- jaf/a2a/protocol.py +95 -125
- jaf/a2a/server.py +90 -118
- jaf/a2a/standalone_client.py +30 -43
- jaf/a2a/tests/__init__.py +16 -33
- jaf/a2a/tests/run_tests.py +17 -53
- jaf/a2a/tests/test_agent.py +40 -140
- jaf/a2a/tests/test_client.py +54 -117
- jaf/a2a/tests/test_integration.py +28 -82
- jaf/a2a/tests/test_protocol.py +54 -139
- jaf/a2a/tests/test_types.py +50 -136
- jaf/a2a/types.py +58 -34
- jaf/cli.py +21 -41
- jaf/core/__init__.py +7 -1
- jaf/core/agent_tool.py +93 -72
- jaf/core/analytics.py +257 -207
- jaf/core/checkpoint.py +223 -0
- jaf/core/composition.py +249 -235
- jaf/core/engine.py +817 -519
- jaf/core/errors.py +55 -42
- jaf/core/guardrails.py +276 -202
- jaf/core/handoff.py +47 -31
- jaf/core/parallel_agents.py +69 -75
- jaf/core/performance.py +75 -73
- jaf/core/proxy.py +43 -44
- jaf/core/proxy_helpers.py +24 -27
- jaf/core/regeneration.py +220 -129
- jaf/core/state.py +68 -66
- jaf/core/streaming.py +115 -108
- jaf/core/tool_results.py +111 -101
- jaf/core/tools.py +114 -116
- jaf/core/tracing.py +269 -210
- jaf/core/types.py +371 -151
- jaf/core/workflows.py +209 -168
- jaf/exceptions.py +46 -38
- jaf/memory/__init__.py +1 -6
- jaf/memory/approval_storage.py +54 -77
- jaf/memory/factory.py +4 -4
- jaf/memory/providers/in_memory.py +216 -180
- jaf/memory/providers/postgres.py +216 -146
- jaf/memory/providers/redis.py +173 -116
- jaf/memory/types.py +70 -51
- jaf/memory/utils.py +36 -34
- jaf/plugins/__init__.py +12 -12
- jaf/plugins/base.py +105 -96
- jaf/policies/__init__.py +0 -1
- jaf/policies/handoff.py +37 -46
- jaf/policies/validation.py +76 -52
- jaf/providers/__init__.py +6 -3
- jaf/providers/mcp.py +97 -51
- jaf/providers/model.py +360 -279
- jaf/server/__init__.py +1 -1
- jaf/server/main.py +7 -11
- jaf/server/server.py +514 -359
- jaf/server/types.py +208 -52
- jaf/utils/__init__.py +17 -18
- jaf/utils/attachments.py +111 -116
- jaf/utils/document_processor.py +175 -174
- jaf/visualization/__init__.py +1 -1
- jaf/visualization/example.py +111 -110
- jaf/visualization/functional_core.py +46 -71
- jaf/visualization/graphviz.py +154 -189
- jaf/visualization/imperative_shell.py +7 -16
- jaf/visualization/types.py +8 -4
- {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/METADATA +2 -2
- jaf_py-2.5.11.dist-info/RECORD +97 -0
- jaf_py-2.5.10.dist-info/RECORD +0 -96
- {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/WHEEL +0 -0
- {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/entry_points.txt +0 -0
- {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/licenses/LICENSE +0 -0
- {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/top_level.txt +0 -0
jaf/plugins/base.py
CHANGED
|
@@ -16,28 +16,31 @@ from ..core.types import Tool, ModelProvider, Agent
|
|
|
16
16
|
|
|
17
17
|
class PluginStatus(str, Enum):
|
|
18
18
|
"""Plugin lifecycle status."""
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
|
|
20
|
+
UNLOADED = "unloaded"
|
|
21
|
+
LOADING = "loading"
|
|
22
|
+
LOADED = "loaded"
|
|
23
|
+
ACTIVE = "active"
|
|
24
|
+
ERROR = "error"
|
|
25
|
+
DISABLED = "disabled"
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
class PluginType(str, Enum):
|
|
28
29
|
"""Types of plugins supported by JAF."""
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
|
|
31
|
+
TOOL_PROVIDER = "tool_provider"
|
|
32
|
+
MODEL_PROVIDER = "model_provider"
|
|
33
|
+
MEMORY_PROVIDER = "memory_provider"
|
|
34
|
+
AGENT_EXTENSION = "agent_extension"
|
|
35
|
+
MIDDLEWARE = "middleware"
|
|
36
|
+
INTEGRATION = "integration"
|
|
37
|
+
CUSTOM = "custom"
|
|
36
38
|
|
|
37
39
|
|
|
38
40
|
@dataclass(frozen=True)
|
|
39
41
|
class PluginDependency:
|
|
40
42
|
"""Represents a plugin dependency."""
|
|
43
|
+
|
|
41
44
|
name: str
|
|
42
45
|
version_constraint: str = "*" # Semantic version constraint
|
|
43
46
|
optional: bool = False
|
|
@@ -47,6 +50,7 @@ class PluginDependency:
|
|
|
47
50
|
@dataclass(frozen=True)
|
|
48
51
|
class PluginMetadata:
|
|
49
52
|
"""Comprehensive metadata for a JAF plugin."""
|
|
53
|
+
|
|
50
54
|
name: str
|
|
51
55
|
version: str
|
|
52
56
|
description: str
|
|
@@ -61,48 +65,49 @@ class PluginMetadata:
|
|
|
61
65
|
keywords: List[str] = field(default_factory=list)
|
|
62
66
|
configuration_schema: Optional[Dict[str, Any]] = None
|
|
63
67
|
created_at: datetime = field(default_factory=datetime.now)
|
|
64
|
-
|
|
68
|
+
|
|
65
69
|
def to_dict(self) -> Dict[str, Any]:
|
|
66
70
|
"""Convert metadata to dictionary for serialization."""
|
|
67
71
|
return {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
"name": self.name,
|
|
73
|
+
"version": self.version,
|
|
74
|
+
"description": self.description,
|
|
75
|
+
"author": self.author,
|
|
76
|
+
"plugin_type": self.plugin_type.value,
|
|
77
|
+
"entry_point": self.entry_point,
|
|
78
|
+
"dependencies": [
|
|
75
79
|
{
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
"name": dep.name,
|
|
81
|
+
"version_constraint": dep.version_constraint,
|
|
82
|
+
"optional": dep.optional,
|
|
83
|
+
"description": dep.description,
|
|
80
84
|
}
|
|
81
85
|
for dep in self.dependencies
|
|
82
86
|
],
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
"jaf_version_constraint": self.jaf_version_constraint,
|
|
88
|
+
"license": self.license,
|
|
89
|
+
"homepage": self.homepage,
|
|
90
|
+
"repository": self.repository,
|
|
91
|
+
"keywords": self.keywords,
|
|
92
|
+
"configuration_schema": self.configuration_schema,
|
|
93
|
+
"created_at": self.created_at.isoformat(),
|
|
90
94
|
}
|
|
91
95
|
|
|
92
96
|
|
|
93
97
|
@dataclass
|
|
94
98
|
class PluginContext:
|
|
95
99
|
"""Context provided to plugins during lifecycle operations."""
|
|
100
|
+
|
|
96
101
|
plugin_metadata: PluginMetadata
|
|
97
102
|
configuration: Dict[str, Any]
|
|
98
103
|
jaf_version: str
|
|
99
104
|
plugin_directory: Optional[str] = None
|
|
100
105
|
logger: Optional[Any] = None
|
|
101
|
-
|
|
106
|
+
|
|
102
107
|
def get_config(self, key: str, default: Any = None) -> Any:
|
|
103
108
|
"""Get configuration value with optional default."""
|
|
104
109
|
return self.configuration.get(key, default)
|
|
105
|
-
|
|
110
|
+
|
|
106
111
|
def has_config(self, key: str) -> bool:
|
|
107
112
|
"""Check if configuration key exists."""
|
|
108
113
|
return key in self.configuration
|
|
@@ -112,53 +117,53 @@ class PluginContext:
|
|
|
112
117
|
class JAFPlugin(Protocol):
|
|
113
118
|
"""
|
|
114
119
|
Base protocol for all JAF plugins.
|
|
115
|
-
|
|
120
|
+
|
|
116
121
|
Plugins must implement this interface to be compatible with the JAF plugin system.
|
|
117
122
|
The plugin system provides lifecycle management, dependency resolution, and
|
|
118
123
|
configuration management.
|
|
119
124
|
"""
|
|
120
|
-
|
|
125
|
+
|
|
121
126
|
@property
|
|
122
127
|
def metadata(self) -> PluginMetadata:
|
|
123
128
|
"""Get plugin metadata."""
|
|
124
129
|
...
|
|
125
|
-
|
|
130
|
+
|
|
126
131
|
async def initialize(self, context: PluginContext) -> None:
|
|
127
132
|
"""
|
|
128
133
|
Initialize the plugin with the provided context.
|
|
129
|
-
|
|
134
|
+
|
|
130
135
|
This method is called once when the plugin is loaded. Use this for
|
|
131
136
|
one-time setup operations like establishing connections, loading
|
|
132
137
|
configuration, or preparing resources.
|
|
133
|
-
|
|
138
|
+
|
|
134
139
|
Args:
|
|
135
140
|
context: Plugin context with configuration and metadata
|
|
136
141
|
"""
|
|
137
142
|
...
|
|
138
|
-
|
|
143
|
+
|
|
139
144
|
async def activate(self) -> None:
|
|
140
145
|
"""
|
|
141
146
|
Activate the plugin and make it available for use.
|
|
142
|
-
|
|
147
|
+
|
|
143
148
|
This method is called after initialization to activate the plugin's
|
|
144
149
|
functionality. Register tools, providers, or other extensions here.
|
|
145
150
|
"""
|
|
146
151
|
...
|
|
147
|
-
|
|
152
|
+
|
|
148
153
|
async def deactivate(self) -> None:
|
|
149
154
|
"""
|
|
150
155
|
Deactivate the plugin and clean up resources.
|
|
151
|
-
|
|
156
|
+
|
|
152
157
|
This method is called when the plugin is being unloaded or the
|
|
153
158
|
system is shutting down. Clean up connections, unregister handlers,
|
|
154
159
|
and release resources here.
|
|
155
160
|
"""
|
|
156
161
|
...
|
|
157
|
-
|
|
162
|
+
|
|
158
163
|
def get_health_status(self) -> Dict[str, Any]:
|
|
159
164
|
"""
|
|
160
165
|
Get the current health status of the plugin.
|
|
161
|
-
|
|
166
|
+
|
|
162
167
|
Returns:
|
|
163
168
|
Dictionary containing health information including status,
|
|
164
169
|
last check time, and any relevant metrics or error information.
|
|
@@ -169,133 +174,133 @@ class JAFPlugin(Protocol):
|
|
|
169
174
|
class BaseJAFPlugin:
|
|
170
175
|
"""
|
|
171
176
|
Base implementation of JAFPlugin with common functionality.
|
|
172
|
-
|
|
177
|
+
|
|
173
178
|
This class provides a foundation for creating JAF plugins with standard
|
|
174
179
|
lifecycle management, health checking, and error handling.
|
|
175
180
|
"""
|
|
176
|
-
|
|
181
|
+
|
|
177
182
|
def __init__(self, metadata: PluginMetadata):
|
|
178
183
|
self._metadata = metadata
|
|
179
184
|
self._status = PluginStatus.UNLOADED
|
|
180
185
|
self._context: Optional[PluginContext] = None
|
|
181
186
|
self._last_health_check = datetime.now()
|
|
182
|
-
self._health_status = {
|
|
187
|
+
self._health_status = {"status": "unknown", "message": "Not initialized"}
|
|
183
188
|
self._error_count = 0
|
|
184
189
|
self._last_error: Optional[str] = None
|
|
185
|
-
|
|
190
|
+
|
|
186
191
|
@property
|
|
187
192
|
def metadata(self) -> PluginMetadata:
|
|
188
193
|
"""Get plugin metadata."""
|
|
189
194
|
return self._metadata
|
|
190
|
-
|
|
195
|
+
|
|
191
196
|
@property
|
|
192
197
|
def status(self) -> PluginStatus:
|
|
193
198
|
"""Get current plugin status."""
|
|
194
199
|
return self._status
|
|
195
|
-
|
|
200
|
+
|
|
196
201
|
@property
|
|
197
202
|
def context(self) -> Optional[PluginContext]:
|
|
198
203
|
"""Get plugin context (available after initialization)."""
|
|
199
204
|
return self._context
|
|
200
|
-
|
|
205
|
+
|
|
201
206
|
async def initialize(self, context: PluginContext) -> None:
|
|
202
207
|
"""Initialize the plugin with context."""
|
|
203
208
|
try:
|
|
204
209
|
self._status = PluginStatus.LOADING
|
|
205
210
|
self._context = context
|
|
206
|
-
|
|
211
|
+
|
|
207
212
|
# Validate configuration against schema if provided
|
|
208
213
|
if self._metadata.configuration_schema:
|
|
209
214
|
self._validate_configuration(context.configuration)
|
|
210
|
-
|
|
215
|
+
|
|
211
216
|
# Call plugin-specific initialization
|
|
212
217
|
await self._on_initialize(context)
|
|
213
|
-
|
|
218
|
+
|
|
214
219
|
self._status = PluginStatus.LOADED
|
|
215
|
-
self._health_status = {
|
|
216
|
-
|
|
220
|
+
self._health_status = {"status": "healthy", "message": "Plugin loaded successfully"}
|
|
221
|
+
|
|
217
222
|
except Exception as e:
|
|
218
223
|
self._status = PluginStatus.ERROR
|
|
219
224
|
self._error_count += 1
|
|
220
225
|
self._last_error = str(e)
|
|
221
|
-
self._health_status = {
|
|
226
|
+
self._health_status = {"status": "error", "message": f"Initialization failed: {e}"}
|
|
222
227
|
raise
|
|
223
|
-
|
|
228
|
+
|
|
224
229
|
async def activate(self) -> None:
|
|
225
230
|
"""Activate the plugin."""
|
|
226
231
|
try:
|
|
227
232
|
if self._status != PluginStatus.LOADED:
|
|
228
233
|
raise RuntimeError(f"Cannot activate plugin in status: {self._status}")
|
|
229
|
-
|
|
234
|
+
|
|
230
235
|
await self._on_activate()
|
|
231
236
|
self._status = PluginStatus.ACTIVE
|
|
232
|
-
self._health_status = {
|
|
233
|
-
|
|
237
|
+
self._health_status = {"status": "healthy", "message": "Plugin active"}
|
|
238
|
+
|
|
234
239
|
except Exception as e:
|
|
235
240
|
self._status = PluginStatus.ERROR
|
|
236
241
|
self._error_count += 1
|
|
237
242
|
self._last_error = str(e)
|
|
238
|
-
self._health_status = {
|
|
243
|
+
self._health_status = {"status": "error", "message": f"Activation failed: {e}"}
|
|
239
244
|
raise
|
|
240
|
-
|
|
245
|
+
|
|
241
246
|
async def deactivate(self) -> None:
|
|
242
247
|
"""Deactivate the plugin."""
|
|
243
248
|
try:
|
|
244
249
|
await self._on_deactivate()
|
|
245
250
|
self._status = PluginStatus.LOADED
|
|
246
|
-
self._health_status = {
|
|
247
|
-
|
|
251
|
+
self._health_status = {"status": "inactive", "message": "Plugin deactivated"}
|
|
252
|
+
|
|
248
253
|
except Exception as e:
|
|
249
254
|
self._error_count += 1
|
|
250
255
|
self._last_error = str(e)
|
|
251
256
|
# Don't change status on deactivation error, but log it
|
|
252
257
|
raise
|
|
253
|
-
|
|
258
|
+
|
|
254
259
|
def get_health_status(self) -> Dict[str, Any]:
|
|
255
260
|
"""Get comprehensive health status."""
|
|
256
261
|
self._last_health_check = datetime.now()
|
|
257
|
-
|
|
262
|
+
|
|
258
263
|
# Get plugin-specific health info
|
|
259
264
|
plugin_health = self._get_plugin_health()
|
|
260
|
-
|
|
265
|
+
|
|
261
266
|
return {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
267
|
+
"plugin_name": self._metadata.name,
|
|
268
|
+
"plugin_version": self._metadata.version,
|
|
269
|
+
"status": self._status.value,
|
|
270
|
+
"health": self._health_status,
|
|
271
|
+
"last_check": self._last_health_check.isoformat(),
|
|
272
|
+
"error_count": self._error_count,
|
|
273
|
+
"last_error": self._last_error,
|
|
274
|
+
"plugin_specific": plugin_health,
|
|
270
275
|
}
|
|
271
|
-
|
|
276
|
+
|
|
272
277
|
# Abstract methods for plugin-specific implementation
|
|
273
|
-
|
|
278
|
+
|
|
274
279
|
async def _on_initialize(self, context: PluginContext) -> None:
|
|
275
280
|
"""Plugin-specific initialization logic. Override in subclasses."""
|
|
276
281
|
pass
|
|
277
|
-
|
|
282
|
+
|
|
278
283
|
async def _on_activate(self) -> None:
|
|
279
284
|
"""Plugin-specific activation logic. Override in subclasses."""
|
|
280
285
|
pass
|
|
281
|
-
|
|
286
|
+
|
|
282
287
|
async def _on_deactivate(self) -> None:
|
|
283
288
|
"""Plugin-specific deactivation logic. Override in subclasses."""
|
|
284
289
|
pass
|
|
285
|
-
|
|
290
|
+
|
|
286
291
|
def _get_plugin_health(self) -> Dict[str, Any]:
|
|
287
292
|
"""Get plugin-specific health information. Override in subclasses."""
|
|
288
|
-
return {
|
|
289
|
-
|
|
293
|
+
return {"status": "ok"}
|
|
294
|
+
|
|
290
295
|
def _validate_configuration(self, config: Dict[str, Any]) -> None:
|
|
291
296
|
"""Validate configuration against schema. Override for custom validation."""
|
|
292
297
|
# Basic validation - could be enhanced with jsonschema
|
|
293
298
|
if not self._metadata.configuration_schema:
|
|
294
299
|
return
|
|
295
|
-
|
|
300
|
+
|
|
296
301
|
schema = self._metadata.configuration_schema
|
|
297
|
-
required_fields = schema.get(
|
|
298
|
-
|
|
302
|
+
required_fields = schema.get("required", [])
|
|
303
|
+
|
|
299
304
|
for field in required_fields:
|
|
300
305
|
if field not in config:
|
|
301
306
|
raise ValueError(f"Required configuration field '{field}' is missing")
|
|
@@ -304,11 +309,11 @@ class BaseJAFPlugin:
|
|
|
304
309
|
@runtime_checkable
|
|
305
310
|
class ToolProvider(Protocol):
|
|
306
311
|
"""Protocol for plugins that provide tools."""
|
|
307
|
-
|
|
312
|
+
|
|
308
313
|
def get_tools(self) -> List[Tool[Any, Any]]:
|
|
309
314
|
"""Get list of tools provided by this plugin."""
|
|
310
315
|
...
|
|
311
|
-
|
|
316
|
+
|
|
312
317
|
def get_tool_by_name(self, name: str) -> Optional[Tool[Any, Any]]:
|
|
313
318
|
"""Get a specific tool by name."""
|
|
314
319
|
...
|
|
@@ -317,11 +322,11 @@ class ToolProvider(Protocol):
|
|
|
317
322
|
@runtime_checkable
|
|
318
323
|
class ModelProviderPlugin(Protocol):
|
|
319
324
|
"""Protocol for plugins that provide model providers."""
|
|
320
|
-
|
|
325
|
+
|
|
321
326
|
def get_model_provider(self) -> ModelProvider[Any]:
|
|
322
327
|
"""Get the model provider instance."""
|
|
323
328
|
...
|
|
324
|
-
|
|
329
|
+
|
|
325
330
|
def get_supported_models(self) -> List[str]:
|
|
326
331
|
"""Get list of supported model names."""
|
|
327
332
|
...
|
|
@@ -330,11 +335,11 @@ class ModelProviderPlugin(Protocol):
|
|
|
330
335
|
@runtime_checkable
|
|
331
336
|
class MemoryProviderPlugin(Protocol):
|
|
332
337
|
"""Protocol for plugins that provide memory providers."""
|
|
333
|
-
|
|
338
|
+
|
|
334
339
|
def get_memory_provider(self) -> Any: # MemoryProvider type
|
|
335
340
|
"""Get the memory provider instance."""
|
|
336
341
|
...
|
|
337
|
-
|
|
342
|
+
|
|
338
343
|
def get_provider_capabilities(self) -> Dict[str, Any]:
|
|
339
344
|
"""Get capabilities and configuration options for the memory provider."""
|
|
340
345
|
...
|
|
@@ -343,11 +348,11 @@ class MemoryProviderPlugin(Protocol):
|
|
|
343
348
|
@runtime_checkable
|
|
344
349
|
class AgentExtension(Protocol):
|
|
345
350
|
"""Protocol for plugins that extend agent functionality."""
|
|
346
|
-
|
|
351
|
+
|
|
347
352
|
def extend_agent(self, agent: Agent[Any, Any]) -> Agent[Any, Any]:
|
|
348
353
|
"""Extend an agent with additional functionality."""
|
|
349
354
|
...
|
|
350
|
-
|
|
355
|
+
|
|
351
356
|
def get_extension_info(self) -> Dict[str, Any]:
|
|
352
357
|
"""Get information about what this extension provides."""
|
|
353
358
|
...
|
|
@@ -355,7 +360,7 @@ class AgentExtension(Protocol):
|
|
|
355
360
|
|
|
356
361
|
class PluginError(Exception):
|
|
357
362
|
"""Base exception for plugin-related errors."""
|
|
358
|
-
|
|
363
|
+
|
|
359
364
|
def __init__(self, message: str, plugin_name: str = "", error_code: str = ""):
|
|
360
365
|
super().__init__(message)
|
|
361
366
|
self.plugin_name = plugin_name
|
|
@@ -364,19 +369,23 @@ class PluginError(Exception):
|
|
|
364
369
|
|
|
365
370
|
class PluginLoadError(PluginError):
|
|
366
371
|
"""Exception raised when a plugin fails to load."""
|
|
372
|
+
|
|
367
373
|
pass
|
|
368
374
|
|
|
369
375
|
|
|
370
376
|
class PluginDependencyError(PluginError):
|
|
371
377
|
"""Exception raised when plugin dependencies cannot be resolved."""
|
|
378
|
+
|
|
372
379
|
pass
|
|
373
380
|
|
|
374
381
|
|
|
375
382
|
class PluginConfigurationError(PluginError):
|
|
376
383
|
"""Exception raised when plugin configuration is invalid."""
|
|
384
|
+
|
|
377
385
|
pass
|
|
378
386
|
|
|
379
387
|
|
|
380
388
|
class PluginVersionError(PluginError):
|
|
381
389
|
"""Exception raised when plugin version constraints are not met."""
|
|
390
|
+
|
|
382
391
|
pass
|