agno 2.0.8__py3-none-any.whl → 2.0.9__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.
- agno/agent/agent.py +2 -2
- agno/db/base.py +14 -0
- agno/db/dynamo/dynamo.py +107 -27
- agno/db/firestore/firestore.py +109 -33
- agno/db/gcs_json/gcs_json_db.py +100 -20
- agno/db/in_memory/in_memory_db.py +95 -20
- agno/db/json/json_db.py +101 -21
- agno/db/migrations/v1_to_v2.py +181 -35
- agno/db/mongo/mongo.py +251 -26
- agno/db/mysql/mysql.py +307 -6
- agno/db/postgres/postgres.py +279 -33
- agno/db/redis/redis.py +99 -22
- agno/db/singlestore/singlestore.py +319 -38
- agno/db/sqlite/sqlite.py +339 -23
- agno/models/anthropic/claude.py +0 -20
- agno/models/huggingface/huggingface.py +2 -1
- agno/models/ollama/chat.py +28 -2
- agno/models/openai/chat.py +7 -0
- agno/models/openai/responses.py +8 -8
- agno/os/interfaces/base.py +2 -0
- agno/os/interfaces/slack/router.py +50 -10
- agno/os/interfaces/slack/slack.py +6 -4
- agno/os/interfaces/whatsapp/router.py +7 -4
- agno/os/router.py +18 -0
- agno/os/utils.py +2 -2
- agno/reasoning/azure_ai_foundry.py +2 -2
- agno/reasoning/deepseek.py +2 -2
- agno/reasoning/groq.py +2 -2
- agno/reasoning/ollama.py +2 -2
- agno/reasoning/openai.py +2 -2
- agno/run/base.py +15 -2
- agno/team/team.py +0 -7
- agno/tools/mcp_toolbox.py +284 -0
- agno/tools/scrapegraph.py +58 -31
- agno/tools/whatsapp.py +1 -1
- agno/utils/print_response/agent.py +2 -2
- agno/utils/print_response/team.py +6 -6
- agno/utils/reasoning.py +22 -1
- agno/utils/string.py +9 -0
- agno/workflow/workflow.py +0 -1
- {agno-2.0.8.dist-info → agno-2.0.9.dist-info}/METADATA +4 -1
- {agno-2.0.8.dist-info → agno-2.0.9.dist-info}/RECORD +45 -44
- {agno-2.0.8.dist-info → agno-2.0.9.dist-info}/WHEEL +0 -0
- {agno-2.0.8.dist-info → agno-2.0.9.dist-info}/licenses/LICENSE +0 -0
- {agno-2.0.8.dist-info → agno-2.0.9.dist-info}/top_level.txt +0 -0
agno/models/openai/responses.py
CHANGED
|
@@ -406,25 +406,25 @@ class OpenAIResponses(Model):
|
|
|
406
406
|
|
|
407
407
|
messages_to_format = messages
|
|
408
408
|
previous_response_id: Optional[str] = None
|
|
409
|
-
|
|
409
|
+
|
|
410
410
|
if self._using_reasoning_model() and self.store is not False:
|
|
411
411
|
# Detect whether we're chaining via previous_response_id. If so, we should NOT
|
|
412
412
|
# re-send prior function_call items; the Responses API already has the state and
|
|
413
413
|
# expects only the corresponding function_call_output items.
|
|
414
|
-
|
|
414
|
+
|
|
415
415
|
for msg in reversed(messages):
|
|
416
416
|
if (
|
|
417
|
-
msg.role == "assistant"
|
|
418
|
-
and hasattr(msg, "provider_data")
|
|
419
|
-
and msg.provider_data
|
|
417
|
+
msg.role == "assistant"
|
|
418
|
+
and hasattr(msg, "provider_data")
|
|
419
|
+
and msg.provider_data
|
|
420
420
|
and "response_id" in msg.provider_data
|
|
421
421
|
):
|
|
422
422
|
previous_response_id = msg.provider_data["response_id"]
|
|
423
423
|
msg_index = messages.index(msg)
|
|
424
|
-
|
|
424
|
+
|
|
425
425
|
# Include messages after this assistant message
|
|
426
|
-
messages_to_format = messages[msg_index + 1:]
|
|
427
|
-
|
|
426
|
+
messages_to_format = messages[msg_index + 1 :]
|
|
427
|
+
|
|
428
428
|
break
|
|
429
429
|
|
|
430
430
|
# Build a mapping from function_call id (fc_*) → call_id (call_*) from prior assistant tool_calls
|
agno/os/interfaces/base.py
CHANGED
|
@@ -5,6 +5,7 @@ from fastapi import APIRouter
|
|
|
5
5
|
|
|
6
6
|
from agno.agent import Agent
|
|
7
7
|
from agno.team import Team
|
|
8
|
+
from agno.workflow.workflow import Workflow
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class BaseInterface(ABC):
|
|
@@ -13,6 +14,7 @@ class BaseInterface(ABC):
|
|
|
13
14
|
router_prefix: str = ""
|
|
14
15
|
agent: Optional[Agent] = None
|
|
15
16
|
team: Optional[Team] = None
|
|
17
|
+
workflow: Optional[Workflow] = None
|
|
16
18
|
|
|
17
19
|
router: APIRouter
|
|
18
20
|
|
|
@@ -1,16 +1,49 @@
|
|
|
1
1
|
from typing import Optional
|
|
2
2
|
|
|
3
3
|
from fastapi import APIRouter, BackgroundTasks, HTTPException, Request
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
4
5
|
|
|
5
6
|
from agno.agent.agent import Agent
|
|
6
7
|
from agno.os.interfaces.slack.security import verify_slack_signature
|
|
7
8
|
from agno.team.team import Team
|
|
8
9
|
from agno.tools.slack import SlackTools
|
|
9
10
|
from agno.utils.log import log_info
|
|
11
|
+
from agno.workflow.workflow import Workflow
|
|
10
12
|
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
class SlackEventResponse(BaseModel):
|
|
15
|
+
"""Response model for Slack event processing"""
|
|
16
|
+
|
|
17
|
+
status: str = Field(default="ok", description="Processing status")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SlackChallengeResponse(BaseModel):
|
|
21
|
+
"""Response model for Slack URL verification challenge"""
|
|
22
|
+
|
|
23
|
+
challenge: str = Field(description="Challenge string to echo back to Slack")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def attach_routes(
|
|
27
|
+
router: APIRouter, agent: Optional[Agent] = None, team: Optional[Team] = None, workflow: Optional[Workflow] = None
|
|
28
|
+
) -> APIRouter:
|
|
29
|
+
# Determine entity type for documentation
|
|
30
|
+
entity_type = "agent" if agent else "team" if team else "workflow" if workflow else "unknown"
|
|
31
|
+
entity_name = getattr(agent or team or workflow, "name", f"Unnamed {entity_type}")
|
|
32
|
+
|
|
33
|
+
@router.post(
|
|
34
|
+
"/events",
|
|
35
|
+
operation_id=f"slack_events_{entity_type}",
|
|
36
|
+
summary=f"Process Slack Events for {entity_type.title()}",
|
|
37
|
+
description=f"Process incoming Slack events and route them to the configured {entity_type}: {entity_name}",
|
|
38
|
+
tags=["Slack", f"Slack-{entity_type.title()}"],
|
|
39
|
+
response_model=SlackEventResponse,
|
|
40
|
+
response_model_exclude_none=True,
|
|
41
|
+
responses={
|
|
42
|
+
200: {"description": "Event processed successfully"},
|
|
43
|
+
400: {"description": "Missing Slack headers"},
|
|
44
|
+
403: {"description": "Invalid Slack signature"},
|
|
45
|
+
},
|
|
46
|
+
)
|
|
14
47
|
async def slack_events(request: Request, background_tasks: BackgroundTasks):
|
|
15
48
|
body = await request.body()
|
|
16
49
|
timestamp = request.headers.get("X-Slack-Request-Timestamp")
|
|
@@ -26,7 +59,7 @@ def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Option
|
|
|
26
59
|
|
|
27
60
|
# Handle URL verification
|
|
28
61
|
if data.get("type") == "url_verification":
|
|
29
|
-
return
|
|
62
|
+
return SlackChallengeResponse(challenge=data.get("challenge"))
|
|
30
63
|
|
|
31
64
|
# Process other event types (e.g., message events) asynchronously
|
|
32
65
|
if "event" in data:
|
|
@@ -37,7 +70,7 @@ def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Option
|
|
|
37
70
|
else:
|
|
38
71
|
background_tasks.add_task(_process_slack_event, event)
|
|
39
72
|
|
|
40
|
-
return
|
|
73
|
+
return SlackEventResponse(status="ok")
|
|
41
74
|
|
|
42
75
|
async def _process_slack_event(event: dict):
|
|
43
76
|
if event.get("type") == "message":
|
|
@@ -57,12 +90,19 @@ def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Option
|
|
|
57
90
|
response = await agent.arun(message_text, user_id=user if user else None, session_id=session_id)
|
|
58
91
|
elif team:
|
|
59
92
|
response = await team.arun(message_text, user_id=user if user else None, session_id=session_id) # type: ignore
|
|
93
|
+
elif workflow:
|
|
94
|
+
response = await workflow.arun(message_text, user_id=user if user else None, session_id=session_id) # type: ignore
|
|
60
95
|
|
|
61
|
-
if response
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
96
|
+
if response:
|
|
97
|
+
if hasattr(response, "reasoning_content") and response.reasoning_content:
|
|
98
|
+
_send_slack_message(
|
|
99
|
+
channel=channel_id,
|
|
100
|
+
message=f"Reasoning: \n{response.reasoning_content}",
|
|
101
|
+
thread_ts=ts,
|
|
102
|
+
italics=True,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
_send_slack_message(channel=channel_id, message=response.content or "", thread_ts=ts)
|
|
66
106
|
|
|
67
107
|
def _send_slack_message(channel: str, thread_ts: str, message: str, italics: bool = False):
|
|
68
108
|
if len(message) <= 40000:
|
|
@@ -85,6 +125,6 @@ def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Option
|
|
|
85
125
|
formatted_batch = "\n".join([f"_{line}_" for line in batch_message.split("\n")])
|
|
86
126
|
SlackTools().send_message_thread(channel=channel, text=formatted_batch or "", thread_ts=thread_ts)
|
|
87
127
|
else:
|
|
88
|
-
SlackTools().send_message_thread(channel=channel, text=
|
|
128
|
+
SlackTools().send_message_thread(channel=channel, text=batch_message or "", thread_ts=thread_ts)
|
|
89
129
|
|
|
90
130
|
return router
|
|
@@ -7,6 +7,7 @@ from agno.agent.agent import Agent
|
|
|
7
7
|
from agno.os.interfaces.base import BaseInterface
|
|
8
8
|
from agno.os.interfaces.slack.router import attach_routes
|
|
9
9
|
from agno.team.team import Team
|
|
10
|
+
from agno.workflow.workflow import Workflow
|
|
10
11
|
|
|
11
12
|
logger = logging.getLogger(__name__)
|
|
12
13
|
|
|
@@ -16,17 +17,18 @@ class Slack(BaseInterface):
|
|
|
16
17
|
|
|
17
18
|
router: APIRouter
|
|
18
19
|
|
|
19
|
-
def __init__(self, agent: Optional[Agent] = None, team: Optional[Team] = None):
|
|
20
|
+
def __init__(self, agent: Optional[Agent] = None, team: Optional[Team] = None, workflow: Optional[Workflow] = None):
|
|
20
21
|
self.agent = agent
|
|
21
22
|
self.team = team
|
|
23
|
+
self.workflow = workflow
|
|
22
24
|
|
|
23
|
-
if not (self.agent or self.team):
|
|
24
|
-
raise ValueError("Slack requires an agent or
|
|
25
|
+
if not (self.agent or self.team or self.workflow):
|
|
26
|
+
raise ValueError("Slack requires an agent, team or workflow")
|
|
25
27
|
|
|
26
28
|
def get_router(self, **kwargs) -> APIRouter:
|
|
27
29
|
# Cannot be overridden
|
|
28
30
|
self.router = APIRouter(prefix="/slack", tags=["Slack"])
|
|
29
31
|
|
|
30
|
-
self.router = attach_routes(router=self.router, agent=self.agent, team=self.team)
|
|
32
|
+
self.router = attach_routes(router=self.router, agent=self.agent, team=self.team, workflow=self.workflow)
|
|
31
33
|
|
|
32
34
|
return self.router
|
|
@@ -19,6 +19,9 @@ def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Option
|
|
|
19
19
|
if agent is None and team is None:
|
|
20
20
|
raise ValueError("Either agent or team must be provided.")
|
|
21
21
|
|
|
22
|
+
# Create WhatsApp tools instance once for reuse
|
|
23
|
+
whatsapp_tools = WhatsAppTools(async_mode=True)
|
|
24
|
+
|
|
22
25
|
@router.get("/status")
|
|
23
26
|
async def status():
|
|
24
27
|
return {"status": "available"}
|
|
@@ -185,9 +188,9 @@ def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Option
|
|
|
185
188
|
if italics:
|
|
186
189
|
# Handle multi-line messages by making each line italic
|
|
187
190
|
formatted_message = "\n".join([f"_{line}_" for line in message.split("\n")])
|
|
188
|
-
await
|
|
191
|
+
await whatsapp_tools.send_text_message_async(recipient=recipient, text=formatted_message)
|
|
189
192
|
else:
|
|
190
|
-
await
|
|
193
|
+
await whatsapp_tools.send_text_message_async(recipient=recipient, text=message)
|
|
191
194
|
return
|
|
192
195
|
|
|
193
196
|
# Split message into batches of 4000 characters (WhatsApp message limit is 4096)
|
|
@@ -199,8 +202,8 @@ def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Option
|
|
|
199
202
|
if italics:
|
|
200
203
|
# Handle multi-line messages by making each line italic
|
|
201
204
|
formatted_batch = "\n".join([f"_{line}_" for line in batch_message.split("\n")])
|
|
202
|
-
await
|
|
205
|
+
await whatsapp_tools.send_text_message_async(recipient=recipient, text=formatted_batch)
|
|
203
206
|
else:
|
|
204
|
-
await
|
|
207
|
+
await whatsapp_tools.send_text_message_async(recipient=recipient, text=batch_message)
|
|
205
208
|
|
|
206
209
|
return router
|
agno/os/router.py
CHANGED
|
@@ -72,6 +72,24 @@ async def _get_request_kwargs(request: Request, endpoint_func: Callable) -> Dict
|
|
|
72
72
|
sig = inspect.signature(endpoint_func)
|
|
73
73
|
known_fields = set(sig.parameters.keys())
|
|
74
74
|
kwargs = {key: value for key, value in form_data.items() if key not in known_fields}
|
|
75
|
+
|
|
76
|
+
# Handle JSON parameters. They are passed as strings and need to be deserialized.
|
|
77
|
+
|
|
78
|
+
if session_state := kwargs.get("session_state"):
|
|
79
|
+
try:
|
|
80
|
+
session_state_dict = json.loads(session_state) # type: ignore
|
|
81
|
+
kwargs["session_state"] = session_state_dict
|
|
82
|
+
except json.JSONDecodeError:
|
|
83
|
+
kwargs.pop("session_state")
|
|
84
|
+
log_warning(f"Invalid session_state parameter couldn't be loaded: {session_state}")
|
|
85
|
+
if dependencies := kwargs.get("dependencies"):
|
|
86
|
+
try:
|
|
87
|
+
dependencies_dict = json.loads(dependencies) # type: ignore
|
|
88
|
+
kwargs["dependencies"] = dependencies_dict
|
|
89
|
+
except json.JSONDecodeError:
|
|
90
|
+
kwargs.pop("dependencies")
|
|
91
|
+
log_warning(f"Invalid dependencies parameter couldn't be loaded: {dependencies}")
|
|
92
|
+
|
|
75
93
|
return kwargs
|
|
76
94
|
|
|
77
95
|
|
agno/os/utils.py
CHANGED
|
@@ -57,7 +57,7 @@ def get_run_input(run_dict: Dict[str, Any], is_workflow_run: bool = False) -> st
|
|
|
57
57
|
if is_workflow_run:
|
|
58
58
|
step_executor_runs = run_dict.get("step_executor_runs", [])
|
|
59
59
|
if step_executor_runs:
|
|
60
|
-
for message in step_executor_runs[0].get("messages", []):
|
|
60
|
+
for message in reversed(step_executor_runs[0].get("messages", [])):
|
|
61
61
|
if message.get("role") == "user":
|
|
62
62
|
return message.get("content", "")
|
|
63
63
|
|
|
@@ -70,7 +70,7 @@ def get_run_input(run_dict: Dict[str, Any], is_workflow_run: bool = False) -> st
|
|
|
70
70
|
return str(input_value)
|
|
71
71
|
|
|
72
72
|
if run_dict.get("messages") is not None:
|
|
73
|
-
for message in run_dict["messages"]:
|
|
73
|
+
for message in reversed(run_dict["messages"]):
|
|
74
74
|
if message.get("role") == "user":
|
|
75
75
|
return message.get("content", "")
|
|
76
76
|
|
|
@@ -20,7 +20,7 @@ def get_ai_foundry_reasoning(reasoning_agent: "Agent", messages: List[Message])
|
|
|
20
20
|
from agno.run.agent import RunOutput
|
|
21
21
|
|
|
22
22
|
try:
|
|
23
|
-
reasoning_agent_response: RunOutput = reasoning_agent.run(
|
|
23
|
+
reasoning_agent_response: RunOutput = reasoning_agent.run(input=messages)
|
|
24
24
|
except Exception as e:
|
|
25
25
|
logger.warning(f"Reasoning error: {e}")
|
|
26
26
|
return None
|
|
@@ -46,7 +46,7 @@ async def aget_ai_foundry_reasoning(reasoning_agent: "Agent", messages: List[Mes
|
|
|
46
46
|
from agno.run.agent import RunOutput
|
|
47
47
|
|
|
48
48
|
try:
|
|
49
|
-
reasoning_agent_response: RunOutput = await reasoning_agent.arun(
|
|
49
|
+
reasoning_agent_response: RunOutput = await reasoning_agent.arun(input=messages)
|
|
50
50
|
except Exception as e:
|
|
51
51
|
logger.warning(f"Reasoning error: {e}")
|
|
52
52
|
return None
|
agno/reasoning/deepseek.py
CHANGED
|
@@ -20,7 +20,7 @@ def get_deepseek_reasoning(reasoning_agent: "Agent", messages: List[Message]) ->
|
|
|
20
20
|
message.role = "system"
|
|
21
21
|
|
|
22
22
|
try:
|
|
23
|
-
reasoning_agent_response: RunOutput = reasoning_agent.run(
|
|
23
|
+
reasoning_agent_response: RunOutput = reasoning_agent.run(input=messages)
|
|
24
24
|
except Exception as e:
|
|
25
25
|
logger.warning(f"Reasoning error: {e}")
|
|
26
26
|
return None
|
|
@@ -46,7 +46,7 @@ async def aget_deepseek_reasoning(reasoning_agent: "Agent", messages: List[Messa
|
|
|
46
46
|
message.role = "system"
|
|
47
47
|
|
|
48
48
|
try:
|
|
49
|
-
reasoning_agent_response: RunOutput = await reasoning_agent.arun(
|
|
49
|
+
reasoning_agent_response: RunOutput = await reasoning_agent.arun(input=messages)
|
|
50
50
|
except Exception as e:
|
|
51
51
|
logger.warning(f"Reasoning error: {e}")
|
|
52
52
|
return None
|
agno/reasoning/groq.py
CHANGED
|
@@ -20,7 +20,7 @@ def get_groq_reasoning(reasoning_agent: "Agent", messages: List[Message]) -> Opt
|
|
|
20
20
|
message.role = "system"
|
|
21
21
|
|
|
22
22
|
try:
|
|
23
|
-
reasoning_agent_response: RunOutput = reasoning_agent.run(
|
|
23
|
+
reasoning_agent_response: RunOutput = reasoning_agent.run(input=messages)
|
|
24
24
|
except Exception as e:
|
|
25
25
|
logger.warning(f"Reasoning error: {e}")
|
|
26
26
|
return None
|
|
@@ -50,7 +50,7 @@ async def aget_groq_reasoning(reasoning_agent: "Agent", messages: List[Message])
|
|
|
50
50
|
message.role = "system"
|
|
51
51
|
|
|
52
52
|
try:
|
|
53
|
-
reasoning_agent_response: RunOutput = await reasoning_agent.arun(
|
|
53
|
+
reasoning_agent_response: RunOutput = await reasoning_agent.arun(input=messages)
|
|
54
54
|
except Exception as e:
|
|
55
55
|
logger.warning(f"Reasoning error: {e}")
|
|
56
56
|
return None
|
agno/reasoning/ollama.py
CHANGED
|
@@ -20,7 +20,7 @@ def get_ollama_reasoning(reasoning_agent: "Agent", messages: List[Message]) -> O
|
|
|
20
20
|
from agno.run.agent import RunOutput
|
|
21
21
|
|
|
22
22
|
try:
|
|
23
|
-
reasoning_agent_response: RunOutput = reasoning_agent.run(
|
|
23
|
+
reasoning_agent_response: RunOutput = reasoning_agent.run(input=messages)
|
|
24
24
|
except Exception as e:
|
|
25
25
|
logger.warning(f"Reasoning error: {e}")
|
|
26
26
|
return None
|
|
@@ -46,7 +46,7 @@ async def aget_ollama_reasoning(reasoning_agent: "Agent", messages: List[Message
|
|
|
46
46
|
from agno.run.agent import RunOutput
|
|
47
47
|
|
|
48
48
|
try:
|
|
49
|
-
reasoning_agent_response: RunOutput = await reasoning_agent.arun(
|
|
49
|
+
reasoning_agent_response: RunOutput = await reasoning_agent.arun(input=messages)
|
|
50
50
|
except Exception as e:
|
|
51
51
|
logger.warning(f"Reasoning error: {e}")
|
|
52
52
|
return None
|
agno/reasoning/openai.py
CHANGED
|
@@ -29,7 +29,7 @@ def get_openai_reasoning(reasoning_agent: "Agent", messages: List[Message]) -> O
|
|
|
29
29
|
from agno.run.agent import RunOutput
|
|
30
30
|
|
|
31
31
|
try:
|
|
32
|
-
reasoning_agent_response: RunOutput = reasoning_agent.run(
|
|
32
|
+
reasoning_agent_response: RunOutput = reasoning_agent.run(input=messages)
|
|
33
33
|
except Exception as e:
|
|
34
34
|
logger.warning(f"Reasoning error: {e}")
|
|
35
35
|
return None
|
|
@@ -60,7 +60,7 @@ async def aget_openai_reasoning(reasoning_agent: "Agent", messages: List[Message
|
|
|
60
60
|
message.role = "system"
|
|
61
61
|
|
|
62
62
|
try:
|
|
63
|
-
reasoning_agent_response: RunOutput = await reasoning_agent.arun(
|
|
63
|
+
reasoning_agent_response: RunOutput = await reasoning_agent.arun(input=messages)
|
|
64
64
|
except Exception as e:
|
|
65
65
|
logger.warning(f"Reasoning error: {e}")
|
|
66
66
|
return None
|
agno/run/base.py
CHANGED
|
@@ -117,6 +117,19 @@ class BaseRunOutputEvent:
|
|
|
117
117
|
|
|
118
118
|
def to_json(self, separators=(", ", ": "), indent: Optional[int] = 2) -> str:
|
|
119
119
|
import json
|
|
120
|
+
from datetime import date, datetime, time
|
|
121
|
+
from enum import Enum
|
|
122
|
+
|
|
123
|
+
def json_serializer(obj):
|
|
124
|
+
# Datetime like
|
|
125
|
+
if isinstance(obj, (datetime, date, time)):
|
|
126
|
+
return obj.isoformat()
|
|
127
|
+
# Enums
|
|
128
|
+
if isinstance(obj, Enum):
|
|
129
|
+
v = obj.value
|
|
130
|
+
return v if isinstance(v, (str, int, float, bool, type(None))) else obj.name
|
|
131
|
+
# Fallback to string
|
|
132
|
+
return str(obj)
|
|
120
133
|
|
|
121
134
|
try:
|
|
122
135
|
_dict = self.to_dict()
|
|
@@ -125,9 +138,9 @@ class BaseRunOutputEvent:
|
|
|
125
138
|
raise
|
|
126
139
|
|
|
127
140
|
if indent is None:
|
|
128
|
-
return json.dumps(_dict, separators=separators)
|
|
141
|
+
return json.dumps(_dict, separators=separators, default=json_serializer, ensure_ascii=False)
|
|
129
142
|
else:
|
|
130
|
-
return json.dumps(_dict, indent=indent, separators=separators)
|
|
143
|
+
return json.dumps(_dict, indent=indent, separators=separators, default=json_serializer, ensure_ascii=False)
|
|
131
144
|
|
|
132
145
|
@classmethod
|
|
133
146
|
def from_dict(cls, data: Dict[str, Any]):
|
agno/team/team.py
CHANGED
|
@@ -2037,9 +2037,6 @@ class Team:
|
|
|
2037
2037
|
if model_response.audio is not None:
|
|
2038
2038
|
run_response.response_audio = model_response.audio
|
|
2039
2039
|
|
|
2040
|
-
# Update the run_response created_at with the model response created_at
|
|
2041
|
-
run_response.created_at = model_response.created_at
|
|
2042
|
-
|
|
2043
2040
|
# Build a list of messages that should be added to the RunOutput
|
|
2044
2041
|
messages_for_run_response = [m for m in run_messages.messages if m.add_to_agent_memory]
|
|
2045
2042
|
|
|
@@ -2099,7 +2096,6 @@ class Team:
|
|
|
2099
2096
|
)
|
|
2100
2097
|
|
|
2101
2098
|
# 3. Update TeamRunOutput
|
|
2102
|
-
run_response.created_at = full_model_response.created_at
|
|
2103
2099
|
if full_model_response.content is not None:
|
|
2104
2100
|
run_response.content = full_model_response.content
|
|
2105
2101
|
if full_model_response.reasoning_content is not None:
|
|
@@ -2189,7 +2185,6 @@ class Team:
|
|
|
2189
2185
|
run_response.content = full_model_response.parsed
|
|
2190
2186
|
|
|
2191
2187
|
# Update TeamRunOutput
|
|
2192
|
-
run_response.created_at = full_model_response.created_at
|
|
2193
2188
|
if full_model_response.content is not None:
|
|
2194
2189
|
run_response.content = full_model_response.content
|
|
2195
2190
|
if full_model_response.reasoning_content is not None:
|
|
@@ -2851,7 +2846,6 @@ class Team:
|
|
|
2851
2846
|
|
|
2852
2847
|
# Update the TeamRunResponse content
|
|
2853
2848
|
run_response.content = model_response.content
|
|
2854
|
-
run_response.created_at = model_response.created_at
|
|
2855
2849
|
|
|
2856
2850
|
if stream_intermediate_steps:
|
|
2857
2851
|
yield self._handle_event(create_team_output_model_response_completed_event(run_response), run_response)
|
|
@@ -2909,7 +2903,6 @@ class Team:
|
|
|
2909
2903
|
|
|
2910
2904
|
# Update the TeamRunResponse content
|
|
2911
2905
|
run_response.content = model_response.content
|
|
2912
|
-
run_response.created_at = model_response.created_at
|
|
2913
2906
|
|
|
2914
2907
|
if stream_intermediate_steps:
|
|
2915
2908
|
yield self._handle_event(create_team_output_model_response_completed_event(run_response), run_response)
|