xpander-sdk 2.0.179__py3-none-any.whl → 2.0.180__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.
- xpander_sdk/__init__.py +4 -0
- xpander_sdk/modules/events/decorators/__init__.py +3 -0
- xpander_sdk/modules/events/decorators/on_tool.py +384 -0
- xpander_sdk/modules/tools_repository/sub_modules/tool.py +37 -8
- {xpander_sdk-2.0.179.dist-info → xpander_sdk-2.0.180.dist-info}/METADATA +1 -1
- {xpander_sdk-2.0.179.dist-info → xpander_sdk-2.0.180.dist-info}/RECORD +9 -8
- {xpander_sdk-2.0.179.dist-info → xpander_sdk-2.0.180.dist-info}/WHEEL +0 -0
- {xpander_sdk-2.0.179.dist-info → xpander_sdk-2.0.180.dist-info}/licenses/LICENSE +0 -0
- {xpander_sdk-2.0.179.dist-info → xpander_sdk-2.0.180.dist-info}/top_level.txt +0 -0
xpander_sdk/__init__.py
CHANGED
|
@@ -28,6 +28,7 @@ from .modules.tasks.tasks_module import Tasks, Task, TasksListItem, AgentExecuti
|
|
|
28
28
|
from xpander_sdk.modules.events.decorators.on_task import on_task
|
|
29
29
|
from xpander_sdk.modules.events.decorators.on_boot import on_boot
|
|
30
30
|
from xpander_sdk.modules.events.decorators.on_shutdown import on_shutdown
|
|
31
|
+
from xpander_sdk.modules.events.decorators.on_tool import on_tool_before, on_tool_after, on_tool_error
|
|
31
32
|
|
|
32
33
|
# Tools and repository imports
|
|
33
34
|
from .modules.tools_repository.tools_repository_module import ToolsRepository, Tool
|
|
@@ -77,6 +78,9 @@ __all__ = [
|
|
|
77
78
|
"MCPServerAuthType",
|
|
78
79
|
"register_tool",
|
|
79
80
|
"build_model_from_schema",
|
|
81
|
+
"on_tool_before",
|
|
82
|
+
"on_tool_after",
|
|
83
|
+
"on_tool_error",
|
|
80
84
|
# Knowledge bases
|
|
81
85
|
"KnowledgeBases",
|
|
82
86
|
"KnowledgeBase",
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
"""
|
|
2
|
+
xpander_sdk.decorators.on_tool
|
|
3
|
+
|
|
4
|
+
This module provides decorators for tool invocation lifecycle hooks:
|
|
5
|
+
- `@on_tool_before`: Execute before tool invocation
|
|
6
|
+
- `@on_tool_after`: Execute after successful tool invocation
|
|
7
|
+
- `@on_tool_error`: Execute when tool invocation fails
|
|
8
|
+
|
|
9
|
+
The decorators ensure that registered functions:
|
|
10
|
+
- Accept parameters: Tool, payload, payload_extension, tool_call_id, agent_version
|
|
11
|
+
- Can be either synchronous or asynchronous
|
|
12
|
+
- Are called at the appropriate lifecycle stage during tool execution
|
|
13
|
+
|
|
14
|
+
Execution Notes:
|
|
15
|
+
- Before-hooks execute before tool invocation and can perform validation or logging
|
|
16
|
+
- After-hooks execute after successful invocation with access to the result
|
|
17
|
+
- Error-hooks execute when an exception occurs during invocation
|
|
18
|
+
- Multiple hooks of the same type can be registered and will execute in registration order
|
|
19
|
+
- Exceptions in hooks are logged but don't prevent tool execution
|
|
20
|
+
|
|
21
|
+
Example usage:
|
|
22
|
+
--------------
|
|
23
|
+
>>> @on_tool_before
|
|
24
|
+
... async def log_tool_invocation(tool, payload, payload_extension, tool_call_id, agent_version):
|
|
25
|
+
... logger.info(f"Invoking tool {tool.name} with payload: {payload}")
|
|
26
|
+
|
|
27
|
+
>>> @on_tool_after
|
|
28
|
+
... def record_tool_result(tool, payload, payload_extension, tool_call_id, agent_version, result):
|
|
29
|
+
... logger.info(f"Tool {tool.name} completed with result: {result}")
|
|
30
|
+
|
|
31
|
+
>>> @on_tool_error
|
|
32
|
+
... async def handle_tool_error(tool, payload, payload_extension, tool_call_id, agent_version, error):
|
|
33
|
+
... logger.error(f"Tool {tool.name} failed: {error}")
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
import asyncio
|
|
37
|
+
from functools import wraps
|
|
38
|
+
from inspect import iscoroutinefunction
|
|
39
|
+
from typing import Optional, Callable, Any, Dict, List
|
|
40
|
+
|
|
41
|
+
from xpander_sdk.models.configuration import Configuration
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class ToolHooksRegistry:
|
|
45
|
+
"""
|
|
46
|
+
Registry for tool invocation lifecycle hooks.
|
|
47
|
+
|
|
48
|
+
This class maintains class-level lists of hooks that are executed at different
|
|
49
|
+
stages of tool invocation: before, after, and on error.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
_before_hooks: List[Callable] = []
|
|
53
|
+
_after_hooks: List[Callable] = []
|
|
54
|
+
_error_hooks: List[Callable] = []
|
|
55
|
+
|
|
56
|
+
@classmethod
|
|
57
|
+
def register_before_hook(cls, hook: Callable) -> None:
|
|
58
|
+
"""
|
|
59
|
+
Register a before-invocation hook.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
hook (Callable): The hook function to execute before tool invocation.
|
|
63
|
+
"""
|
|
64
|
+
cls._before_hooks.append(hook)
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
def register_after_hook(cls, hook: Callable) -> None:
|
|
68
|
+
"""
|
|
69
|
+
Register an after-invocation hook.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
hook (Callable): The hook function to execute after successful tool invocation.
|
|
73
|
+
"""
|
|
74
|
+
cls._after_hooks.append(hook)
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def register_error_hook(cls, hook: Callable) -> None:
|
|
78
|
+
"""
|
|
79
|
+
Register an error hook.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
hook (Callable): The hook function to execute when tool invocation fails.
|
|
83
|
+
"""
|
|
84
|
+
cls._error_hooks.append(hook)
|
|
85
|
+
|
|
86
|
+
@classmethod
|
|
87
|
+
async def execute_before_hooks(
|
|
88
|
+
cls,
|
|
89
|
+
tool: Any,
|
|
90
|
+
payload: Any,
|
|
91
|
+
payload_extension: Optional[Dict[str, Any]] = None,
|
|
92
|
+
tool_call_id: Optional[str] = None,
|
|
93
|
+
agent_version: Optional[str] = None
|
|
94
|
+
) -> None:
|
|
95
|
+
"""
|
|
96
|
+
Execute all registered before-invocation hooks.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
tool: The Tool object being invoked.
|
|
100
|
+
payload: The payload being sent to the tool.
|
|
101
|
+
payload_extension: Additional payload data.
|
|
102
|
+
tool_call_id: Unique ID of the tool call.
|
|
103
|
+
agent_version: Version of the agent making the call.
|
|
104
|
+
"""
|
|
105
|
+
from loguru import logger
|
|
106
|
+
|
|
107
|
+
for hook in cls._before_hooks:
|
|
108
|
+
try:
|
|
109
|
+
if asyncio.iscoroutinefunction(hook):
|
|
110
|
+
await hook(tool, payload, payload_extension, tool_call_id, agent_version)
|
|
111
|
+
else:
|
|
112
|
+
hook(tool, payload, payload_extension, tool_call_id, agent_version)
|
|
113
|
+
except Exception as e:
|
|
114
|
+
logger.error(f"Before-hook {hook.__name__} failed: {e}")
|
|
115
|
+
|
|
116
|
+
@classmethod
|
|
117
|
+
async def execute_after_hooks(
|
|
118
|
+
cls,
|
|
119
|
+
tool: Any,
|
|
120
|
+
payload: Any,
|
|
121
|
+
payload_extension: Optional[Dict[str, Any]] = None,
|
|
122
|
+
tool_call_id: Optional[str] = None,
|
|
123
|
+
agent_version: Optional[str] = None,
|
|
124
|
+
result: Any = None
|
|
125
|
+
) -> None:
|
|
126
|
+
"""
|
|
127
|
+
Execute all registered after-invocation hooks.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
tool: The Tool object that was invoked.
|
|
131
|
+
payload: The payload sent to the tool.
|
|
132
|
+
payload_extension: Additional payload data.
|
|
133
|
+
tool_call_id: Unique ID of the tool call.
|
|
134
|
+
agent_version: Version of the agent that made the call.
|
|
135
|
+
result: The result returned by the tool invocation.
|
|
136
|
+
"""
|
|
137
|
+
from loguru import logger
|
|
138
|
+
|
|
139
|
+
for hook in cls._after_hooks:
|
|
140
|
+
try:
|
|
141
|
+
if asyncio.iscoroutinefunction(hook):
|
|
142
|
+
await hook(tool, payload, payload_extension, tool_call_id, agent_version, result)
|
|
143
|
+
else:
|
|
144
|
+
hook(tool, payload, payload_extension, tool_call_id, agent_version, result)
|
|
145
|
+
except Exception as e:
|
|
146
|
+
logger.error(f"After-hook {hook.__name__} failed: {e}")
|
|
147
|
+
|
|
148
|
+
@classmethod
|
|
149
|
+
async def execute_error_hooks(
|
|
150
|
+
cls,
|
|
151
|
+
tool: Any,
|
|
152
|
+
payload: Any,
|
|
153
|
+
payload_extension: Optional[Dict[str, Any]] = None,
|
|
154
|
+
tool_call_id: Optional[str] = None,
|
|
155
|
+
agent_version: Optional[str] = None,
|
|
156
|
+
error: Optional[Exception] = None
|
|
157
|
+
) -> None:
|
|
158
|
+
"""
|
|
159
|
+
Execute all registered error hooks.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
tool: The Tool object that failed.
|
|
163
|
+
payload: The payload sent to the tool.
|
|
164
|
+
payload_extension: Additional payload data.
|
|
165
|
+
tool_call_id: Unique ID of the tool call.
|
|
166
|
+
agent_version: Version of the agent that made the call.
|
|
167
|
+
error: The exception that occurred during invocation.
|
|
168
|
+
"""
|
|
169
|
+
from loguru import logger
|
|
170
|
+
|
|
171
|
+
for hook in cls._error_hooks:
|
|
172
|
+
try:
|
|
173
|
+
if asyncio.iscoroutinefunction(hook):
|
|
174
|
+
await hook(tool, payload, payload_extension, tool_call_id, agent_version, error)
|
|
175
|
+
else:
|
|
176
|
+
hook(tool, payload, payload_extension, tool_call_id, agent_version, error)
|
|
177
|
+
except Exception as e:
|
|
178
|
+
logger.error(f"Error-hook {hook.__name__} failed: {e}")
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def on_tool_before(
|
|
182
|
+
_func: Optional[Callable] = None,
|
|
183
|
+
*,
|
|
184
|
+
configuration: Optional[Configuration] = None
|
|
185
|
+
):
|
|
186
|
+
"""
|
|
187
|
+
Decorator to register a handler as a before-invocation hook for tool calls.
|
|
188
|
+
|
|
189
|
+
The decorated function will be executed before any tool invocation. The function:
|
|
190
|
+
- Must accept parameters: tool, payload, payload_extension, tool_call_id, agent_version
|
|
191
|
+
- Can be either synchronous or asynchronous
|
|
192
|
+
- Can perform validation, logging, or modification of invocation context
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
_func (Optional[Callable]):
|
|
196
|
+
The function to decorate (for direct usage like `@on_tool_before`).
|
|
197
|
+
configuration (Optional[Configuration]):
|
|
198
|
+
An optional configuration object (reserved for future use).
|
|
199
|
+
|
|
200
|
+
Example:
|
|
201
|
+
>>> from typing import Optional, Dict, Any
|
|
202
|
+
>>> from xpander_sdk import Tool
|
|
203
|
+
>>>
|
|
204
|
+
>>> @on_tool_before
|
|
205
|
+
... async def validate_tool_input(
|
|
206
|
+
... tool: Tool,
|
|
207
|
+
... payload: Any,
|
|
208
|
+
... payload_extension: Optional[Dict[str, Any]] = None,
|
|
209
|
+
... tool_call_id: Optional[str] = None,
|
|
210
|
+
... agent_version: Optional[str] = None
|
|
211
|
+
... ):
|
|
212
|
+
... logger.info(f"Pre-invoking tool: {tool.name}")
|
|
213
|
+
... if not payload:
|
|
214
|
+
... logger.warning("Empty payload provided")
|
|
215
|
+
|
|
216
|
+
>>> @on_tool_before
|
|
217
|
+
... def log_tool_metrics(
|
|
218
|
+
... tool: Tool,
|
|
219
|
+
... payload: Any,
|
|
220
|
+
... payload_extension: Optional[Dict[str, Any]] = None,
|
|
221
|
+
... tool_call_id: Optional[str] = None,
|
|
222
|
+
... agent_version: Optional[str] = None
|
|
223
|
+
... ):
|
|
224
|
+
... metrics.record_tool_invocation(tool.name, tool_call_id)
|
|
225
|
+
"""
|
|
226
|
+
|
|
227
|
+
def decorator(func: Callable) -> Callable:
|
|
228
|
+
@wraps(func)
|
|
229
|
+
async def async_wrapper(*args, **kwargs):
|
|
230
|
+
return await func(*args, **kwargs)
|
|
231
|
+
|
|
232
|
+
@wraps(func)
|
|
233
|
+
def sync_wrapper(*args, **kwargs):
|
|
234
|
+
return func(*args, **kwargs)
|
|
235
|
+
|
|
236
|
+
wrapped = async_wrapper if iscoroutinefunction(func) else sync_wrapper
|
|
237
|
+
|
|
238
|
+
# Register hook in the registry
|
|
239
|
+
ToolHooksRegistry.register_before_hook(wrapped)
|
|
240
|
+
|
|
241
|
+
return wrapped
|
|
242
|
+
|
|
243
|
+
if _func and callable(_func):
|
|
244
|
+
return decorator(_func)
|
|
245
|
+
|
|
246
|
+
return decorator
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def on_tool_after(
|
|
250
|
+
_func: Optional[Callable] = None,
|
|
251
|
+
*,
|
|
252
|
+
configuration: Optional[Configuration] = None
|
|
253
|
+
):
|
|
254
|
+
"""
|
|
255
|
+
Decorator to register a handler as an after-invocation hook for tool calls.
|
|
256
|
+
|
|
257
|
+
The decorated function will be executed after successful tool invocation. The function:
|
|
258
|
+
- Must accept parameters: tool, payload, payload_extension, tool_call_id, agent_version, result
|
|
259
|
+
- Can be either synchronous or asynchronous
|
|
260
|
+
- Can perform logging, analytics, or result processing
|
|
261
|
+
|
|
262
|
+
Args:
|
|
263
|
+
_func (Optional[Callable]):
|
|
264
|
+
The function to decorate (for direct usage like `@on_tool_after`).
|
|
265
|
+
configuration (Optional[Configuration]):
|
|
266
|
+
An optional configuration object (reserved for future use).
|
|
267
|
+
|
|
268
|
+
Example:
|
|
269
|
+
>>> from typing import Optional, Dict, Any
|
|
270
|
+
>>> from xpander_sdk import Tool
|
|
271
|
+
>>>
|
|
272
|
+
>>> @on_tool_after
|
|
273
|
+
... async def log_tool_success(
|
|
274
|
+
... tool: Tool,
|
|
275
|
+
... payload: Any,
|
|
276
|
+
... payload_extension: Optional[Dict[str, Any]] = None,
|
|
277
|
+
... tool_call_id: Optional[str] = None,
|
|
278
|
+
... agent_version: Optional[str] = None,
|
|
279
|
+
... result: Any = None
|
|
280
|
+
... ):
|
|
281
|
+
... logger.info(f"Tool {tool.name} succeeded with result: {result}")
|
|
282
|
+
... analytics.record_success(tool.name, tool_call_id)
|
|
283
|
+
|
|
284
|
+
>>> @on_tool_after
|
|
285
|
+
... def cache_tool_result(
|
|
286
|
+
... tool: Tool,
|
|
287
|
+
... payload: Any,
|
|
288
|
+
... payload_extension: Optional[Dict[str, Any]] = None,
|
|
289
|
+
... tool_call_id: Optional[str] = None,
|
|
290
|
+
... agent_version: Optional[str] = None,
|
|
291
|
+
... result: Any = None
|
|
292
|
+
... ):
|
|
293
|
+
... cache.set(f"tool_{tool.id}_{hash(payload)}", result)
|
|
294
|
+
"""
|
|
295
|
+
|
|
296
|
+
def decorator(func: Callable) -> Callable:
|
|
297
|
+
@wraps(func)
|
|
298
|
+
async def async_wrapper(*args, **kwargs):
|
|
299
|
+
return await func(*args, **kwargs)
|
|
300
|
+
|
|
301
|
+
@wraps(func)
|
|
302
|
+
def sync_wrapper(*args, **kwargs):
|
|
303
|
+
return func(*args, **kwargs)
|
|
304
|
+
|
|
305
|
+
wrapped = async_wrapper if iscoroutinefunction(func) else sync_wrapper
|
|
306
|
+
|
|
307
|
+
# Register hook in the registry
|
|
308
|
+
ToolHooksRegistry.register_after_hook(wrapped)
|
|
309
|
+
|
|
310
|
+
return wrapped
|
|
311
|
+
|
|
312
|
+
if _func and callable(_func):
|
|
313
|
+
return decorator(_func)
|
|
314
|
+
|
|
315
|
+
return decorator
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def on_tool_error(
|
|
319
|
+
_func: Optional[Callable] = None,
|
|
320
|
+
*,
|
|
321
|
+
configuration: Optional[Configuration] = None
|
|
322
|
+
):
|
|
323
|
+
"""
|
|
324
|
+
Decorator to register a handler as an error hook for tool calls.
|
|
325
|
+
|
|
326
|
+
The decorated function will be executed when tool invocation fails. The function:
|
|
327
|
+
- Must accept parameters: tool, payload, payload_extension, tool_call_id, agent_version, error
|
|
328
|
+
- Can be either synchronous or asynchronous
|
|
329
|
+
- Can perform error logging, alerting, or recovery actions
|
|
330
|
+
|
|
331
|
+
Args:
|
|
332
|
+
_func (Optional[Callable]):
|
|
333
|
+
The function to decorate (for direct usage like `@on_tool_error`).
|
|
334
|
+
configuration (Optional[Configuration]):
|
|
335
|
+
An optional configuration object (reserved for future use).
|
|
336
|
+
|
|
337
|
+
Example:
|
|
338
|
+
>>> from typing import Optional, Dict, Any
|
|
339
|
+
>>> from xpander_sdk import Tool
|
|
340
|
+
>>>
|
|
341
|
+
>>> @on_tool_error
|
|
342
|
+
... async def alert_on_tool_failure(
|
|
343
|
+
... tool: Tool,
|
|
344
|
+
... payload: Any,
|
|
345
|
+
... payload_extension: Optional[Dict[str, Any]] = None,
|
|
346
|
+
... tool_call_id: Optional[str] = None,
|
|
347
|
+
... agent_version: Optional[str] = None,
|
|
348
|
+
... error: Optional[Exception] = None
|
|
349
|
+
... ):
|
|
350
|
+
... logger.error(f"Tool {tool.name} failed: {error}")
|
|
351
|
+
... await send_alert(f"Tool failure: {tool.name}", str(error))
|
|
352
|
+
|
|
353
|
+
>>> @on_tool_error
|
|
354
|
+
... def log_tool_failure(
|
|
355
|
+
... tool: Tool,
|
|
356
|
+
... payload: Any,
|
|
357
|
+
... payload_extension: Optional[Dict[str, Any]] = None,
|
|
358
|
+
... tool_call_id: Optional[str] = None,
|
|
359
|
+
... agent_version: Optional[str] = None,
|
|
360
|
+
... error: Optional[Exception] = None
|
|
361
|
+
... ):
|
|
362
|
+
... error_log.write(f"{tool.name},{tool_call_id},{str(error)}\n")
|
|
363
|
+
"""
|
|
364
|
+
|
|
365
|
+
def decorator(func: Callable) -> Callable:
|
|
366
|
+
@wraps(func)
|
|
367
|
+
async def async_wrapper(*args, **kwargs):
|
|
368
|
+
return await func(*args, **kwargs)
|
|
369
|
+
|
|
370
|
+
@wraps(func)
|
|
371
|
+
def sync_wrapper(*args, **kwargs):
|
|
372
|
+
return func(*args, **kwargs)
|
|
373
|
+
|
|
374
|
+
wrapped = async_wrapper if iscoroutinefunction(func) else sync_wrapper
|
|
375
|
+
|
|
376
|
+
# Register hook in the registry
|
|
377
|
+
ToolHooksRegistry.register_error_hook(wrapped)
|
|
378
|
+
|
|
379
|
+
return wrapped
|
|
380
|
+
|
|
381
|
+
if _func and callable(_func):
|
|
382
|
+
return decorator(_func)
|
|
383
|
+
|
|
384
|
+
return decorator
|
|
@@ -41,6 +41,7 @@ from xpander_sdk.modules.tools_repository.utils.schemas import (
|
|
|
41
41
|
schema_enforcement_block_and_descriptions,
|
|
42
42
|
)
|
|
43
43
|
from xpander_sdk.utils.event_loop import run_sync
|
|
44
|
+
from xpander_sdk.modules.events.decorators.on_tool import ToolHooksRegistry
|
|
44
45
|
|
|
45
46
|
|
|
46
47
|
class Tool(XPanderSharedModel):
|
|
@@ -376,6 +377,15 @@ class Tool(XPanderSharedModel):
|
|
|
376
377
|
task_id=task_id,
|
|
377
378
|
)
|
|
378
379
|
|
|
380
|
+
# Execute before hooks
|
|
381
|
+
await ToolHooksRegistry.execute_before_hooks(
|
|
382
|
+
tool=self,
|
|
383
|
+
payload=payload,
|
|
384
|
+
payload_extension=payload_extension,
|
|
385
|
+
tool_call_id=tool_call_id,
|
|
386
|
+
agent_version=agent_version
|
|
387
|
+
)
|
|
388
|
+
|
|
379
389
|
try:
|
|
380
390
|
if self.schema and payload:
|
|
381
391
|
try:
|
|
@@ -403,17 +413,26 @@ class Tool(XPanderSharedModel):
|
|
|
403
413
|
|
|
404
414
|
tool_invocation_result.result = result
|
|
405
415
|
tool_invocation_result.is_success = True
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
416
|
+
else:
|
|
417
|
+
tool_invocation_result.result = await self.acall_remote_tool(
|
|
418
|
+
agent_id=agent_id,
|
|
419
|
+
agent_version=agent_version,
|
|
420
|
+
payload=payload,
|
|
421
|
+
payload_extension=payload_extension,
|
|
422
|
+
configuration=configuration,
|
|
423
|
+
task_id=task_id,
|
|
424
|
+
)
|
|
425
|
+
tool_invocation_result.is_success = True
|
|
426
|
+
|
|
427
|
+
# Execute after hooks on success
|
|
428
|
+
await ToolHooksRegistry.execute_after_hooks(
|
|
429
|
+
tool=self,
|
|
411
430
|
payload=payload,
|
|
412
431
|
payload_extension=payload_extension,
|
|
413
|
-
|
|
414
|
-
|
|
432
|
+
tool_call_id=tool_call_id,
|
|
433
|
+
agent_version=agent_version,
|
|
434
|
+
result=tool_invocation_result.result
|
|
415
435
|
)
|
|
416
|
-
tool_invocation_result.is_success = True
|
|
417
436
|
|
|
418
437
|
except Exception as e:
|
|
419
438
|
tool_invocation_result.is_error = True
|
|
@@ -423,6 +442,16 @@ class Tool(XPanderSharedModel):
|
|
|
423
442
|
else:
|
|
424
443
|
tool_invocation_result.status_code = 500
|
|
425
444
|
tool_invocation_result.result = str(e)
|
|
445
|
+
|
|
446
|
+
# Execute error hooks on failure
|
|
447
|
+
await ToolHooksRegistry.execute_error_hooks(
|
|
448
|
+
tool=self,
|
|
449
|
+
payload=payload,
|
|
450
|
+
payload_extension=payload_extension,
|
|
451
|
+
tool_call_id=tool_call_id,
|
|
452
|
+
agent_version=agent_version,
|
|
453
|
+
error=e
|
|
454
|
+
)
|
|
426
455
|
|
|
427
456
|
return tool_invocation_result
|
|
428
457
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
xpander_sdk/__init__.py,sha256=
|
|
1
|
+
xpander_sdk/__init__.py,sha256=34l3YcvIdkj81DTfMp_bgZgXpj2U1lTKpHQ0shwnc_8,2927
|
|
2
2
|
xpander_sdk/consts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
xpander_sdk/consts/api_routes.py,sha256=dKUruLanvprTxZO15fR4OWe6ck8JQ8y64XmUJxsbeJY,2278
|
|
4
4
|
xpander_sdk/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -39,10 +39,11 @@ xpander_sdk/modules/backend/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeR
|
|
|
39
39
|
xpander_sdk/modules/backend/utils/mcp_oauth.py,sha256=K80bLjFW66TXm-wz5mbtZEeKjpeYr6ezhMFb5r3bhXA,5468
|
|
40
40
|
xpander_sdk/modules/events/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
41
41
|
xpander_sdk/modules/events/events_module.py,sha256=DVlho7JxT6Jy8GeyuSakswmYwR18xqO2JcCJ-8Zc3s8,25317
|
|
42
|
-
xpander_sdk/modules/events/decorators/__init__.py,sha256=
|
|
42
|
+
xpander_sdk/modules/events/decorators/__init__.py,sha256=8GhR9afoLiS83a0OMLpn7TN2W6iTnlcVqos6bM34nac,129
|
|
43
43
|
xpander_sdk/modules/events/decorators/on_boot.py,sha256=VGtoQcgs3g5bmx3Ze4QB_-ZwBESATYYVR0oZe35eCww,3076
|
|
44
44
|
xpander_sdk/modules/events/decorators/on_shutdown.py,sha256=rFgChspnLDnZm9FS1K636dvZSQDkeugf2e3M83SDgAY,3127
|
|
45
45
|
xpander_sdk/modules/events/decorators/on_task.py,sha256=G3jk0xzi3pqH96Bbut_GMJKExIlyyMYk4PbKfc6koa4,8551
|
|
46
|
+
xpander_sdk/modules/events/decorators/on_tool.py,sha256=ZacZ6tADjvl79ISqKxTSH1P0nZUS8C3mRwOL2SyLeZE,13750
|
|
46
47
|
xpander_sdk/modules/events/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
47
48
|
xpander_sdk/modules/events/models/deployments.py,sha256=6uwxFsybrZ-eHeohJzkm2RtQq4Eo_0xjHk7QouvszxU,1335
|
|
48
49
|
xpander_sdk/modules/events/models/events.py,sha256=T_89pq48e7fMIbJcCbtM9Ocb6YKXQP7pbF6VbECiGcI,1550
|
|
@@ -74,7 +75,7 @@ xpander_sdk/modules/tools_repository/models/__init__.py,sha256=47DEQpj8HBSa-_TIm
|
|
|
74
75
|
xpander_sdk/modules/tools_repository/models/mcp.py,sha256=qGpaiXKiuXw6gAcK8CW6ek6FkZNbBxDXUf1PWF6Tenw,1863
|
|
75
76
|
xpander_sdk/modules/tools_repository/models/tool_invocation_result.py,sha256=Dhowt_fv8v8xWv7xMRJxo6hA8DawXKbWIrsJFMpt5H4,447
|
|
76
77
|
xpander_sdk/modules/tools_repository/sub_modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
77
|
-
xpander_sdk/modules/tools_repository/sub_modules/tool.py,sha256=
|
|
78
|
+
xpander_sdk/modules/tools_repository/sub_modules/tool.py,sha256=rivnznxi6CrrOWE1rukkBRmad2H-rthhrelC7ei1IXM,23617
|
|
78
79
|
xpander_sdk/modules/tools_repository/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
79
80
|
xpander_sdk/modules/tools_repository/utils/generic.py,sha256=m9FRaVGzRUj23tB52rP9K4O-nTsMSt9iwMxMcYsqfiY,1770
|
|
80
81
|
xpander_sdk/modules/tools_repository/utils/local_tools.py,sha256=zp5P8hVnRUJQb-w-2jCEMV5eUB_awmvYfY_rin5qvEw,1875
|
|
@@ -86,8 +87,8 @@ xpander_sdk/utils/generic.py,sha256=XrRj2-L8c0YWpfPdDyXE-pVL-6lKF9VpyZzKHQ4wuCc,
|
|
|
86
87
|
xpander_sdk/utils/tools.py,sha256=lyFkq2yP7DxBkyXYVlnFRwDhQCvf0fZZMDm5fBycze4,1244
|
|
87
88
|
xpander_sdk/utils/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
88
89
|
xpander_sdk/utils/agents/compactization_agent.py,sha256=pqaf7LVSyPFaeXU62dMPY6iQ160TFga1KJ0Kgu1dIgg,14449
|
|
89
|
-
xpander_sdk-2.0.
|
|
90
|
-
xpander_sdk-2.0.
|
|
91
|
-
xpander_sdk-2.0.
|
|
92
|
-
xpander_sdk-2.0.
|
|
93
|
-
xpander_sdk-2.0.
|
|
90
|
+
xpander_sdk-2.0.180.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
91
|
+
xpander_sdk-2.0.180.dist-info/METADATA,sha256=NfaTIonGkunIZxzmX3C82qiGcKeewspcwnJhHcqIYOM,17880
|
|
92
|
+
xpander_sdk-2.0.180.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
93
|
+
xpander_sdk-2.0.180.dist-info/top_level.txt,sha256=UCjnxQpsMy5Zoe7lmRuVDO6DI2V_6PgRFfm4oizRbVs,12
|
|
94
|
+
xpander_sdk-2.0.180.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|