xpander-sdk 2.0.150__tar.gz → 2.0.151__tar.gz
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-2.0.150 → xpander_sdk-2.0.151}/PKG-INFO +35 -1
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/README.md +34 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/setup.py +1 -1
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/consts/api_routes.py +1 -0
- xpander_sdk-2.0.151/src/xpander_sdk/models/activity.py +65 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tasks/sub_modules/task.py +163 -78
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk.egg-info/PKG-INFO +35 -1
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk.egg-info/SOURCES.txt +1 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/LICENSE +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/pyproject.toml +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/setup.cfg +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/consts/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/core/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/core/module_base.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/core/state.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/core/xpander_api_client.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/exceptions/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/exceptions/module_exception.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/models/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/models/configuration.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/models/events.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/models/frameworks.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/models/shared.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/models/user.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/agents/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/agents/agents_module.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/agents/models/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/agents/models/agent.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/agents/models/agent_list.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/agents/models/knowledge_bases.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/agents/sub_modules/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/agents/sub_modules/agent.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/agents/utils/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/agents/utils/generic.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/backend/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/backend/backend_module.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/backend/frameworks/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/backend/frameworks/agno.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/backend/frameworks/dispatch.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/backend/utils/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/backend/utils/mcp_oauth.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/decorators/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/decorators/on_boot.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/decorators/on_shutdown.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/decorators/on_task.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/events_module.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/models/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/models/deployments.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/models/events.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/utils/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/utils/generic.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/utils/git_init.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/knowledge_bases/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/knowledge_bases/knowledge_bases_module.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/knowledge_bases/models/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/knowledge_bases/models/knowledge_bases.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/knowledge_bases/sub_modules/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/knowledge_bases/sub_modules/knowledge_base.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/knowledge_bases/sub_modules/knowledge_base_document_item.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/knowledge_bases/utils/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tasks/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tasks/models/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tasks/models/task.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tasks/models/tasks_list.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tasks/sub_modules/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tasks/tasks_module.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tasks/utils/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tasks/utils/files.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tools_repository/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tools_repository/decorators/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tools_repository/decorators/register_tool.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tools_repository/models/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tools_repository/models/mcp.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tools_repository/models/tool_invocation_result.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tools_repository/sub_modules/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tools_repository/sub_modules/tool.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tools_repository/tools_repository_module.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tools_repository/utils/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tools_repository/utils/generic.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tools_repository/utils/local_tools.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tools_repository/utils/schemas.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/utils/__init__.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/utils/env.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/utils/event_loop.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/utils/tools.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk.egg-info/dependency_links.txt +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk.egg-info/requires.txt +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk.egg-info/top_level.txt +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/tests/test_agents_module.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/tests/test_api_client.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/tests/test_backend_module.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/tests/test_boot_shutdown_handlers.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/tests/test_configuration.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/tests/test_knowledge_bases_module.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/tests/test_tasks_module.py +0 -0
- {xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/tests/test_tools_repository.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xpander-sdk
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.151
|
|
4
4
|
Summary: xpander.ai Backend-as-a-service for AI Agents - SDK
|
|
5
5
|
Home-page: https://www.xpander.ai
|
|
6
6
|
Author: xpanderAI
|
|
@@ -131,6 +131,11 @@ tasks = Tasks(configuration=config)
|
|
|
131
131
|
task = await tasks.aget("task-id")
|
|
132
132
|
await task.aset_status(AgentExecutionStatus.Running)
|
|
133
133
|
await task.asave()
|
|
134
|
+
|
|
135
|
+
# Retrieve task activity log
|
|
136
|
+
activity_log = await task.aget_activity_log()
|
|
137
|
+
for message in activity_log.messages:
|
|
138
|
+
print(f"{message.role}: {message.content.text}")
|
|
134
139
|
```
|
|
135
140
|
|
|
136
141
|
### 4. Tools Integration
|
|
@@ -287,6 +292,35 @@ async for event in task.aevents():
|
|
|
287
292
|
print(f"Event Data: {event.data}")
|
|
288
293
|
```
|
|
289
294
|
|
|
295
|
+
### Task Activity Monitoring
|
|
296
|
+
|
|
297
|
+
```python
|
|
298
|
+
from xpander_sdk import Task
|
|
299
|
+
|
|
300
|
+
# Load a completed task
|
|
301
|
+
task = await Task.aload("task-id")
|
|
302
|
+
|
|
303
|
+
# Get detailed activity log
|
|
304
|
+
activity_log = await task.aget_activity_log()
|
|
305
|
+
|
|
306
|
+
# Analyze messages between user and agent
|
|
307
|
+
for message in activity_log.messages:
|
|
308
|
+
if hasattr(message, 'role'):
|
|
309
|
+
print(f"{message.role}: {message.content.text}")
|
|
310
|
+
elif hasattr(message, 'tool_name'):
|
|
311
|
+
# Tool call
|
|
312
|
+
print(f"Tool: {message.tool_name}")
|
|
313
|
+
print(f"Payload: {message.payload}")
|
|
314
|
+
print(f"Result: {message.result}")
|
|
315
|
+
elif hasattr(message, 'type'):
|
|
316
|
+
# Reasoning step
|
|
317
|
+
print(f"Reasoning ({message.type}): {message.thought}")
|
|
318
|
+
|
|
319
|
+
# Synchronous version
|
|
320
|
+
task = Task.load("task-id")
|
|
321
|
+
activity_log = task.get_activity_log()
|
|
322
|
+
```
|
|
323
|
+
|
|
290
324
|
### Local Task Testing
|
|
291
325
|
|
|
292
326
|
```python
|
|
@@ -82,6 +82,11 @@ tasks = Tasks(configuration=config)
|
|
|
82
82
|
task = await tasks.aget("task-id")
|
|
83
83
|
await task.aset_status(AgentExecutionStatus.Running)
|
|
84
84
|
await task.asave()
|
|
85
|
+
|
|
86
|
+
# Retrieve task activity log
|
|
87
|
+
activity_log = await task.aget_activity_log()
|
|
88
|
+
for message in activity_log.messages:
|
|
89
|
+
print(f"{message.role}: {message.content.text}")
|
|
85
90
|
```
|
|
86
91
|
|
|
87
92
|
### 4. Tools Integration
|
|
@@ -238,6 +243,35 @@ async for event in task.aevents():
|
|
|
238
243
|
print(f"Event Data: {event.data}")
|
|
239
244
|
```
|
|
240
245
|
|
|
246
|
+
### Task Activity Monitoring
|
|
247
|
+
|
|
248
|
+
```python
|
|
249
|
+
from xpander_sdk import Task
|
|
250
|
+
|
|
251
|
+
# Load a completed task
|
|
252
|
+
task = await Task.aload("task-id")
|
|
253
|
+
|
|
254
|
+
# Get detailed activity log
|
|
255
|
+
activity_log = await task.aget_activity_log()
|
|
256
|
+
|
|
257
|
+
# Analyze messages between user and agent
|
|
258
|
+
for message in activity_log.messages:
|
|
259
|
+
if hasattr(message, 'role'):
|
|
260
|
+
print(f"{message.role}: {message.content.text}")
|
|
261
|
+
elif hasattr(message, 'tool_name'):
|
|
262
|
+
# Tool call
|
|
263
|
+
print(f"Tool: {message.tool_name}")
|
|
264
|
+
print(f"Payload: {message.payload}")
|
|
265
|
+
print(f"Result: {message.result}")
|
|
266
|
+
elif hasattr(message, 'type'):
|
|
267
|
+
# Reasoning step
|
|
268
|
+
print(f"Reasoning ({message.type}): {message.thought}")
|
|
269
|
+
|
|
270
|
+
# Synchronous version
|
|
271
|
+
task = Task.load("task-id")
|
|
272
|
+
activity_log = task.get_activity_log()
|
|
273
|
+
```
|
|
274
|
+
|
|
241
275
|
### Local Task Testing
|
|
242
276
|
|
|
243
277
|
```python
|
|
@@ -35,6 +35,7 @@ and deleting resources.
|
|
|
35
35
|
ListTasks = "/agent-execution/executions/history/{agent_id}"
|
|
36
36
|
ListUserTasks = "/agent-execution/executions/history/user/{user_id}"
|
|
37
37
|
GetTask = "/agent-execution/{task_id}/status"
|
|
38
|
+
GetTaskActivityLog = "/activity/{agent_id}/{task_id}"
|
|
38
39
|
TaskCrud = "/agent-execution/{agent_or_task_id}"
|
|
39
40
|
UpdateTask = "/agent-execution/{task_id}/update"
|
|
40
41
|
ReportExternalTask = "/agent-execution/{agent_id}/report_task"
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import Any, List, Literal, Optional, Union
|
|
4
|
+
|
|
5
|
+
from xpander_sdk.models.events import ToolCallRequestReasoning
|
|
6
|
+
from xpander_sdk.models.shared import XPanderSharedModel
|
|
7
|
+
from xpander_sdk.models.user import User
|
|
8
|
+
from xpander_sdk.modules.tools_repository.models.mcp import MCPOAuthGetTokenResponse
|
|
9
|
+
|
|
10
|
+
class AgentActivityThreadMessageContent(XPanderSharedModel):
|
|
11
|
+
text: Optional[str] = None
|
|
12
|
+
files: Optional[List[str]] = []
|
|
13
|
+
|
|
14
|
+
class AgentActivityThreadMessage(XPanderSharedModel):
|
|
15
|
+
id: str
|
|
16
|
+
created_at: datetime
|
|
17
|
+
role: Literal["user","agent"]
|
|
18
|
+
content: AgentActivityThreadMessageContent
|
|
19
|
+
|
|
20
|
+
class AgentActivityThreadToolCall(XPanderSharedModel):
|
|
21
|
+
id: str
|
|
22
|
+
created_at: datetime
|
|
23
|
+
tool_name: str
|
|
24
|
+
payload: Any
|
|
25
|
+
is_error: Optional[bool] = False
|
|
26
|
+
reasoning: Optional[ToolCallRequestReasoning] = None
|
|
27
|
+
result: Optional[Any] = None
|
|
28
|
+
|
|
29
|
+
class AgentActivityThreadReasoningType(str, Enum):
|
|
30
|
+
Think = "think"
|
|
31
|
+
Analyze = "analyze"
|
|
32
|
+
|
|
33
|
+
class AgentActivityThreadReasoning(XPanderSharedModel):
|
|
34
|
+
id: str
|
|
35
|
+
created_at: datetime
|
|
36
|
+
type: AgentActivityThreadReasoningType
|
|
37
|
+
title: str
|
|
38
|
+
confidence: float
|
|
39
|
+
thought: Optional[str] = None
|
|
40
|
+
action: Optional[str] = None
|
|
41
|
+
result: Optional[str] = None
|
|
42
|
+
analysis: Optional[str] = None
|
|
43
|
+
|
|
44
|
+
class AgentActivityThreadSubAgentTrigger(XPanderSharedModel):
|
|
45
|
+
id: str
|
|
46
|
+
created_at: datetime
|
|
47
|
+
agent_id: str
|
|
48
|
+
query: Optional[str] = None
|
|
49
|
+
files: Optional[List[str]] = []
|
|
50
|
+
reasoning: ToolCallRequestReasoning
|
|
51
|
+
|
|
52
|
+
class AgentActivityThreadAuth(MCPOAuthGetTokenResponse):
|
|
53
|
+
id: str
|
|
54
|
+
created_at: datetime
|
|
55
|
+
|
|
56
|
+
AgentActivityThreadMessageType = Union[AgentActivityThreadMessage, AgentActivityThreadToolCall, AgentActivityThreadReasoning, AgentActivityThreadSubAgentTrigger, AgentActivityThreadAuth]
|
|
57
|
+
class AgentActivityThread(XPanderSharedModel):
|
|
58
|
+
id: str
|
|
59
|
+
created_at: datetime
|
|
60
|
+
messages: List[AgentActivityThreadMessageType]
|
|
61
|
+
user: Optional[User] = None
|
|
62
|
+
|
|
63
|
+
class AgentActivityThreadListItem(XPanderSharedModel):
|
|
64
|
+
id: str
|
|
65
|
+
created_at: datetime
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tasks/sub_modules/task.py
RENAMED
|
@@ -28,7 +28,17 @@ Typical usage example:
|
|
|
28
28
|
"""
|
|
29
29
|
|
|
30
30
|
from datetime import datetime
|
|
31
|
-
from typing import
|
|
31
|
+
from typing import (
|
|
32
|
+
Any,
|
|
33
|
+
AsyncGenerator,
|
|
34
|
+
Dict,
|
|
35
|
+
Generator,
|
|
36
|
+
List,
|
|
37
|
+
Optional,
|
|
38
|
+
Type,
|
|
39
|
+
TypeVar,
|
|
40
|
+
Union,
|
|
41
|
+
)
|
|
32
42
|
from httpx import HTTPStatusError
|
|
33
43
|
import httpx
|
|
34
44
|
import json
|
|
@@ -37,13 +47,20 @@ from httpx_sse import aconnect_sse
|
|
|
37
47
|
from xpander_sdk.consts.api_routes import APIRoute
|
|
38
48
|
from xpander_sdk.core.xpander_api_client import APIClient
|
|
39
49
|
from xpander_sdk.exceptions.module_exception import ModuleException
|
|
50
|
+
from xpander_sdk.models.activity import AgentActivityThread
|
|
40
51
|
from xpander_sdk.models.configuration import Configuration
|
|
41
52
|
from xpander_sdk.models.events import (
|
|
42
53
|
TaskUpdateEventType,
|
|
43
54
|
ToolCallRequest,
|
|
44
55
|
ToolCallResult,
|
|
45
56
|
)
|
|
46
|
-
from xpander_sdk.models.shared import
|
|
57
|
+
from xpander_sdk.models.shared import (
|
|
58
|
+
ExecutionTokens,
|
|
59
|
+
OutputFormat,
|
|
60
|
+
ThinkMode,
|
|
61
|
+
Tokens,
|
|
62
|
+
XPanderSharedModel,
|
|
63
|
+
)
|
|
47
64
|
from xpander_sdk.modules.events.utils.generic import get_events_base, get_events_headers
|
|
48
65
|
from xpander_sdk.modules.tasks.models.task import (
|
|
49
66
|
AgentExecutionInput,
|
|
@@ -51,16 +68,25 @@ from xpander_sdk.modules.tasks.models.task import (
|
|
|
51
68
|
HumanInTheLoop,
|
|
52
69
|
ExecutionMetricsReport,
|
|
53
70
|
PendingECARequest,
|
|
54
|
-
TaskReportRequest
|
|
71
|
+
TaskReportRequest,
|
|
72
|
+
)
|
|
73
|
+
from xpander_sdk.modules.tasks.utils.files import (
|
|
74
|
+
categorize_files,
|
|
75
|
+
fetch_urls,
|
|
76
|
+
fetch_file,
|
|
77
|
+
)
|
|
78
|
+
from xpander_sdk.modules.tools_repository.models.mcp import (
|
|
79
|
+
MCPOAuthGetTokenResponse,
|
|
80
|
+
MCPServerDetails,
|
|
55
81
|
)
|
|
56
|
-
from xpander_sdk.modules.tasks.utils.files import categorize_files, fetch_urls, fetch_file
|
|
57
|
-
from xpander_sdk.modules.tools_repository.models.mcp import MCPOAuthGetTokenResponse, MCPServerDetails
|
|
58
82
|
from xpander_sdk.utils.event_loop import run_sync
|
|
59
83
|
|
|
60
84
|
# Type variable for Task class methods
|
|
61
85
|
T = TypeVar("T", bound="Task")
|
|
62
86
|
|
|
63
|
-
TaskUpdateEventData = Union[
|
|
87
|
+
TaskUpdateEventData = Union[
|
|
88
|
+
T, ToolCallRequest, ToolCallResult, MCPOAuthGetTokenResponse
|
|
89
|
+
]
|
|
64
90
|
|
|
65
91
|
|
|
66
92
|
class TaskUpdateEvent(XPanderSharedModel):
|
|
@@ -112,7 +138,7 @@ class Task(XPanderSharedModel):
|
|
|
112
138
|
>>> task = Task.load(task_id="task_123")
|
|
113
139
|
>>> task.set_status(AgentExecutionStatus.Running)
|
|
114
140
|
>>> task.save()
|
|
115
|
-
>>>
|
|
141
|
+
>>>
|
|
116
142
|
>>> # Get files for Agno integration
|
|
117
143
|
>>> files = task.get_files() # PDF files as Agno File objects
|
|
118
144
|
>>> images = task.get_images() # Image files as Agno Image objects
|
|
@@ -148,13 +174,13 @@ class Task(XPanderSharedModel):
|
|
|
148
174
|
output_schema: Optional[Dict] = None
|
|
149
175
|
events_streaming: Optional[bool] = False
|
|
150
176
|
additional_context: Optional[str] = None
|
|
151
|
-
expected_output: Optional[str] = None,
|
|
152
|
-
mcp_servers: Optional[List[MCPServerDetails]] = [],
|
|
153
|
-
triggering_agent_id: Optional[str] = None,
|
|
154
|
-
title: Optional[str] = None,
|
|
177
|
+
expected_output: Optional[str] = (None,)
|
|
178
|
+
mcp_servers: Optional[List[MCPServerDetails]] = ([],)
|
|
179
|
+
triggering_agent_id: Optional[str] = (None,)
|
|
180
|
+
title: Optional[str] = (None,)
|
|
155
181
|
think_mode: Optional[ThinkMode] = ThinkMode.Default
|
|
156
182
|
disable_attachment_injection: Optional[bool] = False
|
|
157
|
-
|
|
183
|
+
|
|
158
184
|
# metrics
|
|
159
185
|
tokens: Optional[Tokens] = None
|
|
160
186
|
used_tools: Optional[List[str]] = []
|
|
@@ -202,7 +228,6 @@ class Task(XPanderSharedModel):
|
|
|
202
228
|
self.__dict__.update(new_obj.__dict__)
|
|
203
229
|
return self
|
|
204
230
|
|
|
205
|
-
|
|
206
231
|
def reload(self):
|
|
207
232
|
"""
|
|
208
233
|
Reload the current object synchronously.
|
|
@@ -217,7 +242,6 @@ class Task(XPanderSharedModel):
|
|
|
217
242
|
"""
|
|
218
243
|
run_sync(self.areload())
|
|
219
244
|
|
|
220
|
-
|
|
221
245
|
@classmethod
|
|
222
246
|
async def aload(
|
|
223
247
|
cls: Type[T], task_id: str, configuration: Optional[Configuration] = None
|
|
@@ -243,7 +267,9 @@ class Task(XPanderSharedModel):
|
|
|
243
267
|
response_data = await client.make_request(
|
|
244
268
|
path=APIRoute.GetTask.format(task_id=task_id)
|
|
245
269
|
)
|
|
246
|
-
task = cls.model_validate(
|
|
270
|
+
task = cls.model_validate(
|
|
271
|
+
{**response_data, "configuration": configuration or Configuration()}
|
|
272
|
+
)
|
|
247
273
|
return task
|
|
248
274
|
except HTTPStatusError as e:
|
|
249
275
|
raise ModuleException(
|
|
@@ -382,15 +408,15 @@ class Task(XPanderSharedModel):
|
|
|
382
408
|
def get_files(self) -> list[Any]:
|
|
383
409
|
"""
|
|
384
410
|
Get PDF files from task input, formatted for Agno integration.
|
|
385
|
-
|
|
411
|
+
|
|
386
412
|
Returns PDF files as Agno File objects when the Agno framework is available,
|
|
387
413
|
or as URL strings otherwise. This method is designed for seamless integration
|
|
388
414
|
with Agno agents.
|
|
389
|
-
|
|
415
|
+
|
|
390
416
|
Returns:
|
|
391
417
|
list[Any]: List of File objects (when Agno is available) or URL strings.
|
|
392
418
|
Returns empty list if no PDF files are present in task input.
|
|
393
|
-
|
|
419
|
+
|
|
394
420
|
Example:
|
|
395
421
|
>>> files = task.get_files()
|
|
396
422
|
>>> result = await agno_agent.arun(
|
|
@@ -398,33 +424,34 @@ class Task(XPanderSharedModel):
|
|
|
398
424
|
... files=files
|
|
399
425
|
... )
|
|
400
426
|
"""
|
|
401
|
-
|
|
427
|
+
|
|
402
428
|
if not self.input.files or len(self.input.files) == 0:
|
|
403
429
|
return []
|
|
404
|
-
|
|
430
|
+
|
|
405
431
|
categorized_files = categorize_files(file_urls=self.input.files)
|
|
406
|
-
|
|
432
|
+
|
|
407
433
|
if not categorized_files.pdfs or len(categorized_files.pdfs) == 0:
|
|
408
434
|
return []
|
|
409
435
|
|
|
410
436
|
try:
|
|
411
|
-
from agno.media import File
|
|
437
|
+
from agno.media import File # test import
|
|
438
|
+
|
|
412
439
|
return [fetch_file(url=url) for url in categorized_files.pdfs]
|
|
413
440
|
except Exception:
|
|
414
441
|
return categorized_files.pdfs
|
|
415
|
-
|
|
442
|
+
|
|
416
443
|
def get_images(self) -> list[Any]:
|
|
417
444
|
"""
|
|
418
445
|
Get image files from task input, formatted for Agno integration.
|
|
419
|
-
|
|
446
|
+
|
|
420
447
|
Returns image files as Agno Image objects when the Agno framework is available,
|
|
421
448
|
or as URL strings otherwise. This method is designed for seamless integration
|
|
422
449
|
with Agno agents that support image processing.
|
|
423
|
-
|
|
450
|
+
|
|
424
451
|
Returns:
|
|
425
452
|
list[Any]: List of Image objects (when Agno is available) or URL strings.
|
|
426
453
|
Returns empty list if no image files are present in task input.
|
|
427
|
-
|
|
454
|
+
|
|
428
455
|
Example:
|
|
429
456
|
>>> images = task.get_images()
|
|
430
457
|
>>> result = await agno_agent.arun(
|
|
@@ -434,30 +461,31 @@ class Task(XPanderSharedModel):
|
|
|
434
461
|
"""
|
|
435
462
|
if not self.input.files or len(self.input.files) == 0:
|
|
436
463
|
return []
|
|
437
|
-
|
|
464
|
+
|
|
438
465
|
categorized_files = categorize_files(file_urls=self.input.files)
|
|
439
|
-
|
|
466
|
+
|
|
440
467
|
if not categorized_files.images or len(categorized_files.images) == 0:
|
|
441
468
|
return []
|
|
442
469
|
|
|
443
470
|
try:
|
|
444
471
|
from agno.media import Image
|
|
472
|
+
|
|
445
473
|
return [Image(url=url) for url in categorized_files.images]
|
|
446
474
|
except Exception:
|
|
447
475
|
return categorized_files.images
|
|
448
|
-
|
|
476
|
+
|
|
449
477
|
def get_human_readable_files(self) -> list[Any]:
|
|
450
478
|
"""
|
|
451
479
|
Get human-readable files from task input with their content.
|
|
452
|
-
|
|
480
|
+
|
|
453
481
|
Returns text-based files (like .txt, .csv, .json, .py, etc.) with their content
|
|
454
482
|
fetched and parsed. This method is automatically used by to_message() to include
|
|
455
483
|
file contents in the task message.
|
|
456
|
-
|
|
484
|
+
|
|
457
485
|
Returns:
|
|
458
486
|
list[dict[str, str]]: List of dictionaries with 'url' and 'content' keys.
|
|
459
487
|
Returns empty list if no human-readable files are present.
|
|
460
|
-
|
|
488
|
+
|
|
461
489
|
Example:
|
|
462
490
|
>>> readable_files = task.get_human_readable_files()
|
|
463
491
|
>>> for file_data in readable_files:
|
|
@@ -466,14 +494,19 @@ class Task(XPanderSharedModel):
|
|
|
466
494
|
"""
|
|
467
495
|
if not self.input.files or len(self.input.files) == 0:
|
|
468
496
|
return []
|
|
469
|
-
|
|
497
|
+
|
|
470
498
|
categorized_files = categorize_files(file_urls=self.input.files)
|
|
471
|
-
|
|
499
|
+
|
|
472
500
|
if not categorized_files.files or len(categorized_files.files) == 0:
|
|
473
501
|
return []
|
|
474
502
|
|
|
475
|
-
return run_sync(
|
|
476
|
-
|
|
503
|
+
return run_sync(
|
|
504
|
+
fetch_urls(
|
|
505
|
+
urls=categorized_files.files,
|
|
506
|
+
disable_attachment_injection=self.disable_attachment_injection,
|
|
507
|
+
)
|
|
508
|
+
)
|
|
509
|
+
|
|
477
510
|
def to_message(self) -> str:
|
|
478
511
|
"""
|
|
479
512
|
Converts the input data into a formatted message string.
|
|
@@ -495,7 +528,7 @@ class Task(XPanderSharedModel):
|
|
|
495
528
|
if len(message) != 0:
|
|
496
529
|
message += "\n"
|
|
497
530
|
message += "Files: " + (", ".join(self.input.files))
|
|
498
|
-
|
|
531
|
+
|
|
499
532
|
# append human readable content like csv and such
|
|
500
533
|
readable_files = self.get_human_readable_files()
|
|
501
534
|
if readable_files and len(readable_files) != 0:
|
|
@@ -505,6 +538,70 @@ class Task(XPanderSharedModel):
|
|
|
505
538
|
|
|
506
539
|
return message
|
|
507
540
|
|
|
541
|
+
async def aget_activity_log(self) -> AgentActivityThread:
|
|
542
|
+
"""
|
|
543
|
+
Asynchronously retrieves the activity log for this task.
|
|
544
|
+
|
|
545
|
+
Fetches a detailed activity thread containing all messages, tool calls,
|
|
546
|
+
reasoning steps, sub-agent triggers, and authentication events that
|
|
547
|
+
occurred during the task execution.
|
|
548
|
+
|
|
549
|
+
Returns:
|
|
550
|
+
AgentActivityThread: Complete activity log including messages,
|
|
551
|
+
tool calls, reasoning, and other execution events.
|
|
552
|
+
|
|
553
|
+
Raises:
|
|
554
|
+
ModuleException: If the activity log cannot be retrieved or doesn't exist.
|
|
555
|
+
|
|
556
|
+
Example:
|
|
557
|
+
>>> task = await Task.aload(task_id="task_123")
|
|
558
|
+
>>> activity_log = await task.aget_activity_log()
|
|
559
|
+
>>> for message in activity_log.messages:
|
|
560
|
+
... print(f"{message.role}: {message.content.text}")
|
|
561
|
+
"""
|
|
562
|
+
try:
|
|
563
|
+
client = APIClient(configuration=self.configuration)
|
|
564
|
+
activity_log: AgentActivityThread = await client.make_request(
|
|
565
|
+
path=APIRoute.GetTaskActivityLog.format(
|
|
566
|
+
agent_id=self.agent_id, task_id=self.id
|
|
567
|
+
),
|
|
568
|
+
model=AgentActivityThread,
|
|
569
|
+
)
|
|
570
|
+
if not activity_log:
|
|
571
|
+
raise HTTPStatusError(404, "Log not found")
|
|
572
|
+
|
|
573
|
+
return activity_log
|
|
574
|
+
except HTTPStatusError as e:
|
|
575
|
+
raise ModuleException(
|
|
576
|
+
status_code=e.response.status_code, description=e.response.text
|
|
577
|
+
)
|
|
578
|
+
except Exception as e:
|
|
579
|
+
raise ModuleException(
|
|
580
|
+
status_code=500, description=f"Failed to get activity log - {str(e)}"
|
|
581
|
+
)
|
|
582
|
+
|
|
583
|
+
def get_activity_log(self) -> AgentActivityThread:
|
|
584
|
+
"""
|
|
585
|
+
Retrieves the activity log for this task synchronously.
|
|
586
|
+
|
|
587
|
+
This method wraps the asynchronous aget_activity_log method for use
|
|
588
|
+
in synchronous environments.
|
|
589
|
+
|
|
590
|
+
Returns:
|
|
591
|
+
AgentActivityThread: Complete activity log including messages,
|
|
592
|
+
tool calls, reasoning, and other execution events.
|
|
593
|
+
|
|
594
|
+
Raises:
|
|
595
|
+
ModuleException: If the activity log cannot be retrieved or doesn't exist.
|
|
596
|
+
|
|
597
|
+
Example:
|
|
598
|
+
>>> task = Task.load(task_id="task_123")
|
|
599
|
+
>>> activity_log = task.get_activity_log()
|
|
600
|
+
>>> for message in activity_log.messages:
|
|
601
|
+
... print(f"{message.role}: {message.content.text}")
|
|
602
|
+
"""
|
|
603
|
+
return run_sync(self.aget_activity_log())
|
|
604
|
+
|
|
508
605
|
async def aevents(self) -> AsyncGenerator[TaskUpdateEvent, None]:
|
|
509
606
|
"""
|
|
510
607
|
Asynchronously streams task events.
|
|
@@ -541,10 +638,12 @@ class Task(XPanderSharedModel):
|
|
|
541
638
|
json_event_data: dict = json.loads(event.data)
|
|
542
639
|
if json_event_data.get("type", None).startswith("task"):
|
|
543
640
|
task_data = json_event_data.get("data")
|
|
544
|
-
json_event_data.pop("data")
|
|
641
|
+
json_event_data.pop("data") # delete data
|
|
545
642
|
yield TaskUpdateEvent(
|
|
546
643
|
**json_event_data,
|
|
547
|
-
data=Task(
|
|
644
|
+
data=Task(
|
|
645
|
+
**task_data, configuration=self.configuration
|
|
646
|
+
),
|
|
548
647
|
)
|
|
549
648
|
continue
|
|
550
649
|
except Exception:
|
|
@@ -585,16 +684,13 @@ class Task(XPanderSharedModel):
|
|
|
585
684
|
|
|
586
685
|
while queue:
|
|
587
686
|
yield queue.pop(0)
|
|
588
|
-
|
|
589
|
-
async def areport_metrics(
|
|
590
|
-
self,
|
|
591
|
-
configuration: Optional[Configuration] = None
|
|
592
|
-
):
|
|
687
|
+
|
|
688
|
+
async def areport_metrics(self, configuration: Optional[Configuration] = None):
|
|
593
689
|
"""
|
|
594
690
|
Asynchronously report LLM task metrics to xpander.ai.
|
|
595
691
|
|
|
596
692
|
Args:
|
|
597
|
-
configuration (Optional[Configuration], optional):
|
|
693
|
+
configuration (Optional[Configuration], optional):
|
|
598
694
|
API client configuration. If not provided, a new instance is created. Defaults to None.
|
|
599
695
|
|
|
600
696
|
Raises:
|
|
@@ -606,10 +702,10 @@ class Task(XPanderSharedModel):
|
|
|
606
702
|
try:
|
|
607
703
|
configuration = configuration or Configuration()
|
|
608
704
|
client = APIClient(configuration=configuration)
|
|
609
|
-
|
|
705
|
+
|
|
610
706
|
if not self.tokens:
|
|
611
707
|
raise ValueError("tokens must be provided. task.tokens = Tokens()")
|
|
612
|
-
|
|
708
|
+
|
|
613
709
|
task_report_request = ExecutionMetricsReport(
|
|
614
710
|
execution_id=self.id,
|
|
615
711
|
source=self.source,
|
|
@@ -621,38 +717,30 @@ class Task(XPanderSharedModel):
|
|
|
621
717
|
ai_model="xpander",
|
|
622
718
|
api_calls_made=self.used_tools,
|
|
623
719
|
result=self.result or None,
|
|
624
|
-
llm_tokens=ExecutionTokens(worker=self.tokens)
|
|
720
|
+
llm_tokens=ExecutionTokens(worker=self.tokens),
|
|
625
721
|
)
|
|
626
722
|
|
|
627
723
|
await client.make_request(
|
|
628
|
-
path=APIRoute.ReportExecutionMetrics.format(
|
|
629
|
-
agent_id=self.agent_id
|
|
630
|
-
),
|
|
724
|
+
path=APIRoute.ReportExecutionMetrics.format(agent_id=self.agent_id),
|
|
631
725
|
method="POST",
|
|
632
726
|
payload=task_report_request.model_dump_safe(),
|
|
633
727
|
)
|
|
634
728
|
|
|
635
729
|
except HTTPStatusError as e:
|
|
636
730
|
raise ModuleException(
|
|
637
|
-
status_code=e.response.status_code,
|
|
638
|
-
description=e.response.text
|
|
731
|
+
status_code=e.response.status_code, description=e.response.text
|
|
639
732
|
)
|
|
640
733
|
except Exception as e:
|
|
641
734
|
raise ModuleException(
|
|
642
|
-
status_code=500,
|
|
643
|
-
description=f"Failed to report metrics - {str(e)}"
|
|
735
|
+
status_code=500, description=f"Failed to report metrics - {str(e)}"
|
|
644
736
|
)
|
|
645
737
|
|
|
646
|
-
|
|
647
|
-
def report_metrics(
|
|
648
|
-
self,
|
|
649
|
-
configuration: Optional[Configuration] = None
|
|
650
|
-
):
|
|
738
|
+
def report_metrics(self, configuration: Optional[Configuration] = None):
|
|
651
739
|
"""
|
|
652
740
|
Report LLM task metrics to xpander.ai.
|
|
653
741
|
|
|
654
742
|
Args:
|
|
655
|
-
configuration (Optional[Configuration], optional):
|
|
743
|
+
configuration (Optional[Configuration], optional):
|
|
656
744
|
API client configuration. If not provided, a new instance is created. Defaults to None.
|
|
657
745
|
|
|
658
746
|
Raises:
|
|
@@ -661,15 +749,11 @@ class Task(XPanderSharedModel):
|
|
|
661
749
|
Returns:
|
|
662
750
|
None
|
|
663
751
|
"""
|
|
664
|
-
return run_sync(
|
|
665
|
-
|
|
666
|
-
configuration=configuration
|
|
667
|
-
)
|
|
668
|
-
)
|
|
669
|
-
|
|
752
|
+
return run_sync(self.areport_metrics(configuration=configuration))
|
|
753
|
+
|
|
670
754
|
@classmethod
|
|
671
755
|
async def areport_external_task(
|
|
672
|
-
cls: Type[T],
|
|
756
|
+
cls: Type[T],
|
|
673
757
|
configuration: Optional[Configuration] = None,
|
|
674
758
|
agent_id: Optional[str] = None,
|
|
675
759
|
id: Optional[str] = None,
|
|
@@ -679,7 +763,7 @@ class Task(XPanderSharedModel):
|
|
|
679
763
|
is_success: Optional[bool] = True,
|
|
680
764
|
result: Optional[str] = None,
|
|
681
765
|
duration: Optional[float] = 0,
|
|
682
|
-
used_tools: Optional[List[str]] = []
|
|
766
|
+
used_tools: Optional[List[str]] = [],
|
|
683
767
|
) -> T:
|
|
684
768
|
"""
|
|
685
769
|
Asynchronously reports an external task to the xpander.ai backend.
|
|
@@ -687,7 +771,7 @@ class Task(XPanderSharedModel):
|
|
|
687
771
|
This method is used to report the result of a task that was executed
|
|
688
772
|
externally (outside the xpander.ai platform). It submits execution details,
|
|
689
773
|
including inputs, outputs, success status, and resource usage, to the backend.
|
|
690
|
-
|
|
774
|
+
|
|
691
775
|
Args:
|
|
692
776
|
configuration (Optional[Configuration]): Optional configuration for API calls.
|
|
693
777
|
agent_id (Optional[str]): Identifier of the agent associated with the task.
|
|
@@ -699,13 +783,13 @@ class Task(XPanderSharedModel):
|
|
|
699
783
|
result (Optional[str]): String representation of the final result.
|
|
700
784
|
duration (Optional[float]): Task execution duration, in seconds. Defaults to 0.
|
|
701
785
|
used_tools (Optional[List[str]]): List of tools used during the execution. Defaults to empty list.
|
|
702
|
-
|
|
786
|
+
|
|
703
787
|
Returns:
|
|
704
788
|
T: Instance of the Task class, representing the reported task.
|
|
705
|
-
|
|
789
|
+
|
|
706
790
|
Raises:
|
|
707
791
|
ModuleException: Raised on backend or network errors.
|
|
708
|
-
|
|
792
|
+
|
|
709
793
|
Example:
|
|
710
794
|
>>> task = await Task.areport_external_task(
|
|
711
795
|
... agent_id="agent_xyz",
|
|
@@ -725,7 +809,7 @@ class Task(XPanderSharedModel):
|
|
|
725
809
|
is_success=is_success,
|
|
726
810
|
result=result,
|
|
727
811
|
duration=duration,
|
|
728
|
-
used_tools=used_tools
|
|
812
|
+
used_tools=used_tools,
|
|
729
813
|
)
|
|
730
814
|
response_data = await client.make_request(
|
|
731
815
|
path=APIRoute.ReportExternalTask.format(agent_id=agent_id),
|
|
@@ -739,12 +823,13 @@ class Task(XPanderSharedModel):
|
|
|
739
823
|
)
|
|
740
824
|
except Exception as e:
|
|
741
825
|
raise ModuleException(
|
|
742
|
-
status_code=500,
|
|
826
|
+
status_code=500,
|
|
827
|
+
description=f"Failed to report external task - {str(e)}",
|
|
743
828
|
)
|
|
744
829
|
|
|
745
830
|
@classmethod
|
|
746
831
|
def report_external_task(
|
|
747
|
-
cls: Type[T],
|
|
832
|
+
cls: Type[T],
|
|
748
833
|
configuration: Optional[Configuration] = None,
|
|
749
834
|
agent_id: Optional[str] = None,
|
|
750
835
|
id: Optional[str] = None,
|
|
@@ -754,7 +839,7 @@ class Task(XPanderSharedModel):
|
|
|
754
839
|
is_success: Optional[bool] = True,
|
|
755
840
|
result: Optional[str] = None,
|
|
756
841
|
duration: Optional[float] = 0,
|
|
757
|
-
used_tools: Optional[List[str]] = []
|
|
842
|
+
used_tools: Optional[List[str]] = [],
|
|
758
843
|
) -> T:
|
|
759
844
|
"""
|
|
760
845
|
Synchronously reports an external task to the xpander.ai backend.
|
|
@@ -799,4 +884,4 @@ class Task(XPanderSharedModel):
|
|
|
799
884
|
duration=duration,
|
|
800
885
|
used_tools=used_tools,
|
|
801
886
|
)
|
|
802
|
-
)
|
|
887
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xpander-sdk
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.151
|
|
4
4
|
Summary: xpander.ai Backend-as-a-service for AI Agents - SDK
|
|
5
5
|
Home-page: https://www.xpander.ai
|
|
6
6
|
Author: xpanderAI
|
|
@@ -131,6 +131,11 @@ tasks = Tasks(configuration=config)
|
|
|
131
131
|
task = await tasks.aget("task-id")
|
|
132
132
|
await task.aset_status(AgentExecutionStatus.Running)
|
|
133
133
|
await task.asave()
|
|
134
|
+
|
|
135
|
+
# Retrieve task activity log
|
|
136
|
+
activity_log = await task.aget_activity_log()
|
|
137
|
+
for message in activity_log.messages:
|
|
138
|
+
print(f"{message.role}: {message.content.text}")
|
|
134
139
|
```
|
|
135
140
|
|
|
136
141
|
### 4. Tools Integration
|
|
@@ -287,6 +292,35 @@ async for event in task.aevents():
|
|
|
287
292
|
print(f"Event Data: {event.data}")
|
|
288
293
|
```
|
|
289
294
|
|
|
295
|
+
### Task Activity Monitoring
|
|
296
|
+
|
|
297
|
+
```python
|
|
298
|
+
from xpander_sdk import Task
|
|
299
|
+
|
|
300
|
+
# Load a completed task
|
|
301
|
+
task = await Task.aload("task-id")
|
|
302
|
+
|
|
303
|
+
# Get detailed activity log
|
|
304
|
+
activity_log = await task.aget_activity_log()
|
|
305
|
+
|
|
306
|
+
# Analyze messages between user and agent
|
|
307
|
+
for message in activity_log.messages:
|
|
308
|
+
if hasattr(message, 'role'):
|
|
309
|
+
print(f"{message.role}: {message.content.text}")
|
|
310
|
+
elif hasattr(message, 'tool_name'):
|
|
311
|
+
# Tool call
|
|
312
|
+
print(f"Tool: {message.tool_name}")
|
|
313
|
+
print(f"Payload: {message.payload}")
|
|
314
|
+
print(f"Result: {message.result}")
|
|
315
|
+
elif hasattr(message, 'type'):
|
|
316
|
+
# Reasoning step
|
|
317
|
+
print(f"Reasoning ({message.type}): {message.thought}")
|
|
318
|
+
|
|
319
|
+
# Synchronous version
|
|
320
|
+
task = Task.load("task-id")
|
|
321
|
+
activity_log = task.get_activity_log()
|
|
322
|
+
```
|
|
323
|
+
|
|
290
324
|
### Local Task Testing
|
|
291
325
|
|
|
292
326
|
```python
|
|
@@ -17,6 +17,7 @@ src/xpander_sdk/core/xpander_api_client.py
|
|
|
17
17
|
src/xpander_sdk/exceptions/__init__.py
|
|
18
18
|
src/xpander_sdk/exceptions/module_exception.py
|
|
19
19
|
src/xpander_sdk/models/__init__.py
|
|
20
|
+
src/xpander_sdk/models/activity.py
|
|
20
21
|
src/xpander_sdk/models/configuration.py
|
|
21
22
|
src/xpander_sdk/models/events.py
|
|
22
23
|
src/xpander_sdk/models/frameworks.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/agents/models/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/agents/models/agent_list.py
RENAMED
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/agents/models/knowledge_bases.py
RENAMED
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/agents/sub_modules/__init__.py
RENAMED
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/agents/sub_modules/agent.py
RENAMED
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/agents/utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/backend/backend_module.py
RENAMED
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/backend/frameworks/__init__.py
RENAMED
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/backend/frameworks/agno.py
RENAMED
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/backend/frameworks/dispatch.py
RENAMED
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/backend/utils/__init__.py
RENAMED
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/backend/utils/mcp_oauth.py
RENAMED
|
File without changes
|
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/decorators/__init__.py
RENAMED
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/decorators/on_boot.py
RENAMED
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/decorators/on_shutdown.py
RENAMED
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/decorators/on_task.py
RENAMED
|
File without changes
|
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/models/__init__.py
RENAMED
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/models/deployments.py
RENAMED
|
File without changes
|
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/events/utils/git_init.py
RENAMED
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/knowledge_bases/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tasks/models/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tasks/models/tasks_list.py
RENAMED
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tasks/sub_modules/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tools_repository/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xpander_sdk-2.0.150 → xpander_sdk-2.0.151}/src/xpander_sdk/modules/tools_repository/models/mcp.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|