agno 2.2.13__py3-none-any.whl → 2.4.3__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/__init__.py +6 -0
- agno/agent/agent.py +5252 -3145
- agno/agent/remote.py +525 -0
- agno/api/api.py +2 -0
- agno/client/__init__.py +3 -0
- agno/client/a2a/__init__.py +10 -0
- agno/client/a2a/client.py +554 -0
- agno/client/a2a/schemas.py +112 -0
- agno/client/a2a/utils.py +369 -0
- agno/client/os.py +2669 -0
- agno/compression/__init__.py +3 -0
- agno/compression/manager.py +247 -0
- agno/culture/manager.py +2 -2
- agno/db/base.py +927 -6
- agno/db/dynamo/dynamo.py +788 -2
- agno/db/dynamo/schemas.py +128 -0
- agno/db/dynamo/utils.py +26 -3
- agno/db/firestore/firestore.py +674 -50
- agno/db/firestore/schemas.py +41 -0
- agno/db/firestore/utils.py +25 -10
- agno/db/gcs_json/gcs_json_db.py +506 -3
- agno/db/gcs_json/utils.py +14 -2
- agno/db/in_memory/in_memory_db.py +203 -4
- agno/db/in_memory/utils.py +14 -2
- agno/db/json/json_db.py +498 -2
- agno/db/json/utils.py +14 -2
- agno/db/migrations/manager.py +199 -0
- agno/db/migrations/utils.py +19 -0
- agno/db/migrations/v1_to_v2.py +54 -16
- agno/db/migrations/versions/__init__.py +0 -0
- agno/db/migrations/versions/v2_3_0.py +977 -0
- agno/db/mongo/async_mongo.py +1013 -39
- agno/db/mongo/mongo.py +684 -4
- agno/db/mongo/schemas.py +48 -0
- agno/db/mongo/utils.py +17 -0
- agno/db/mysql/__init__.py +2 -1
- agno/db/mysql/async_mysql.py +2958 -0
- agno/db/mysql/mysql.py +722 -53
- agno/db/mysql/schemas.py +77 -11
- agno/db/mysql/utils.py +151 -8
- agno/db/postgres/async_postgres.py +1254 -137
- agno/db/postgres/postgres.py +2316 -93
- agno/db/postgres/schemas.py +153 -21
- agno/db/postgres/utils.py +22 -7
- agno/db/redis/redis.py +531 -3
- agno/db/redis/schemas.py +36 -0
- agno/db/redis/utils.py +31 -15
- agno/db/schemas/evals.py +1 -0
- agno/db/schemas/memory.py +20 -9
- agno/db/singlestore/schemas.py +70 -1
- agno/db/singlestore/singlestore.py +737 -74
- agno/db/singlestore/utils.py +13 -3
- agno/db/sqlite/async_sqlite.py +1069 -89
- agno/db/sqlite/schemas.py +133 -1
- agno/db/sqlite/sqlite.py +2203 -165
- agno/db/sqlite/utils.py +21 -11
- agno/db/surrealdb/models.py +25 -0
- agno/db/surrealdb/surrealdb.py +603 -1
- agno/db/utils.py +60 -0
- agno/eval/__init__.py +26 -3
- agno/eval/accuracy.py +25 -12
- agno/eval/agent_as_judge.py +871 -0
- agno/eval/base.py +29 -0
- agno/eval/performance.py +10 -4
- agno/eval/reliability.py +22 -13
- agno/eval/utils.py +2 -1
- agno/exceptions.py +42 -0
- agno/hooks/__init__.py +3 -0
- agno/hooks/decorator.py +164 -0
- agno/integrations/discord/client.py +13 -2
- agno/knowledge/__init__.py +4 -0
- agno/knowledge/chunking/code.py +90 -0
- agno/knowledge/chunking/document.py +65 -4
- agno/knowledge/chunking/fixed.py +4 -1
- agno/knowledge/chunking/markdown.py +102 -11
- agno/knowledge/chunking/recursive.py +2 -2
- agno/knowledge/chunking/semantic.py +130 -48
- agno/knowledge/chunking/strategy.py +18 -0
- agno/knowledge/embedder/azure_openai.py +0 -1
- agno/knowledge/embedder/google.py +1 -1
- agno/knowledge/embedder/mistral.py +1 -1
- agno/knowledge/embedder/nebius.py +1 -1
- agno/knowledge/embedder/openai.py +16 -12
- agno/knowledge/filesystem.py +412 -0
- agno/knowledge/knowledge.py +4261 -1199
- agno/knowledge/protocol.py +134 -0
- agno/knowledge/reader/arxiv_reader.py +3 -2
- agno/knowledge/reader/base.py +9 -7
- agno/knowledge/reader/csv_reader.py +91 -42
- agno/knowledge/reader/docx_reader.py +9 -10
- agno/knowledge/reader/excel_reader.py +225 -0
- agno/knowledge/reader/field_labeled_csv_reader.py +38 -48
- agno/knowledge/reader/firecrawl_reader.py +3 -2
- agno/knowledge/reader/json_reader.py +16 -22
- agno/knowledge/reader/markdown_reader.py +15 -14
- agno/knowledge/reader/pdf_reader.py +33 -28
- agno/knowledge/reader/pptx_reader.py +9 -10
- agno/knowledge/reader/reader_factory.py +135 -1
- agno/knowledge/reader/s3_reader.py +8 -16
- agno/knowledge/reader/tavily_reader.py +3 -3
- agno/knowledge/reader/text_reader.py +15 -14
- agno/knowledge/reader/utils/__init__.py +17 -0
- agno/knowledge/reader/utils/spreadsheet.py +114 -0
- agno/knowledge/reader/web_search_reader.py +8 -65
- agno/knowledge/reader/website_reader.py +16 -13
- agno/knowledge/reader/wikipedia_reader.py +36 -3
- agno/knowledge/reader/youtube_reader.py +3 -2
- agno/knowledge/remote_content/__init__.py +33 -0
- agno/knowledge/remote_content/config.py +266 -0
- agno/knowledge/remote_content/remote_content.py +105 -17
- agno/knowledge/utils.py +76 -22
- agno/learn/__init__.py +71 -0
- agno/learn/config.py +463 -0
- agno/learn/curate.py +185 -0
- agno/learn/machine.py +725 -0
- agno/learn/schemas.py +1114 -0
- agno/learn/stores/__init__.py +38 -0
- agno/learn/stores/decision_log.py +1156 -0
- agno/learn/stores/entity_memory.py +3275 -0
- agno/learn/stores/learned_knowledge.py +1583 -0
- agno/learn/stores/protocol.py +117 -0
- agno/learn/stores/session_context.py +1217 -0
- agno/learn/stores/user_memory.py +1495 -0
- agno/learn/stores/user_profile.py +1220 -0
- agno/learn/utils.py +209 -0
- agno/media.py +22 -6
- agno/memory/__init__.py +14 -1
- agno/memory/manager.py +223 -8
- agno/memory/strategies/__init__.py +15 -0
- agno/memory/strategies/base.py +66 -0
- agno/memory/strategies/summarize.py +196 -0
- agno/memory/strategies/types.py +37 -0
- agno/models/aimlapi/aimlapi.py +17 -0
- agno/models/anthropic/claude.py +434 -59
- agno/models/aws/bedrock.py +121 -20
- agno/models/aws/claude.py +131 -274
- agno/models/azure/ai_foundry.py +10 -6
- agno/models/azure/openai_chat.py +33 -10
- agno/models/base.py +1162 -561
- agno/models/cerebras/cerebras.py +120 -24
- agno/models/cerebras/cerebras_openai.py +21 -2
- agno/models/cohere/chat.py +65 -6
- agno/models/cometapi/cometapi.py +18 -1
- agno/models/dashscope/dashscope.py +2 -3
- agno/models/deepinfra/deepinfra.py +18 -1
- agno/models/deepseek/deepseek.py +69 -3
- agno/models/fireworks/fireworks.py +18 -1
- agno/models/google/gemini.py +959 -89
- agno/models/google/utils.py +22 -0
- agno/models/groq/groq.py +48 -18
- agno/models/huggingface/huggingface.py +17 -6
- agno/models/ibm/watsonx.py +16 -6
- agno/models/internlm/internlm.py +18 -1
- agno/models/langdb/langdb.py +13 -1
- agno/models/litellm/chat.py +88 -9
- agno/models/litellm/litellm_openai.py +18 -1
- agno/models/message.py +24 -5
- agno/models/meta/llama.py +40 -13
- agno/models/meta/llama_openai.py +22 -21
- agno/models/metrics.py +12 -0
- agno/models/mistral/mistral.py +8 -4
- agno/models/n1n/__init__.py +3 -0
- agno/models/n1n/n1n.py +57 -0
- agno/models/nebius/nebius.py +6 -7
- agno/models/nvidia/nvidia.py +20 -3
- agno/models/ollama/__init__.py +2 -0
- agno/models/ollama/chat.py +17 -6
- agno/models/ollama/responses.py +100 -0
- agno/models/openai/__init__.py +2 -0
- agno/models/openai/chat.py +117 -26
- agno/models/openai/open_responses.py +46 -0
- agno/models/openai/responses.py +110 -32
- agno/models/openrouter/__init__.py +2 -0
- agno/models/openrouter/openrouter.py +67 -2
- agno/models/openrouter/responses.py +146 -0
- agno/models/perplexity/perplexity.py +19 -1
- agno/models/portkey/portkey.py +7 -6
- agno/models/requesty/requesty.py +19 -2
- agno/models/response.py +20 -2
- agno/models/sambanova/sambanova.py +20 -3
- agno/models/siliconflow/siliconflow.py +19 -2
- agno/models/together/together.py +20 -3
- agno/models/vercel/v0.py +20 -3
- agno/models/vertexai/claude.py +124 -4
- agno/models/vllm/vllm.py +19 -14
- agno/models/xai/xai.py +19 -2
- agno/os/app.py +467 -137
- agno/os/auth.py +253 -5
- agno/os/config.py +22 -0
- agno/os/interfaces/a2a/a2a.py +7 -6
- agno/os/interfaces/a2a/router.py +635 -26
- agno/os/interfaces/a2a/utils.py +32 -33
- agno/os/interfaces/agui/agui.py +5 -3
- agno/os/interfaces/agui/router.py +26 -16
- agno/os/interfaces/agui/utils.py +97 -57
- agno/os/interfaces/base.py +7 -7
- agno/os/interfaces/slack/router.py +16 -7
- agno/os/interfaces/slack/slack.py +7 -7
- agno/os/interfaces/whatsapp/router.py +35 -7
- agno/os/interfaces/whatsapp/security.py +3 -1
- agno/os/interfaces/whatsapp/whatsapp.py +11 -8
- agno/os/managers.py +326 -0
- agno/os/mcp.py +652 -79
- agno/os/middleware/__init__.py +4 -0
- agno/os/middleware/jwt.py +718 -115
- agno/os/middleware/trailing_slash.py +27 -0
- agno/os/router.py +105 -1558
- agno/os/routers/agents/__init__.py +3 -0
- agno/os/routers/agents/router.py +655 -0
- agno/os/routers/agents/schema.py +288 -0
- agno/os/routers/components/__init__.py +3 -0
- agno/os/routers/components/components.py +475 -0
- agno/os/routers/database.py +155 -0
- agno/os/routers/evals/evals.py +111 -18
- agno/os/routers/evals/schemas.py +38 -5
- agno/os/routers/evals/utils.py +80 -11
- agno/os/routers/health.py +3 -3
- agno/os/routers/knowledge/knowledge.py +284 -35
- agno/os/routers/knowledge/schemas.py +14 -2
- agno/os/routers/memory/memory.py +274 -11
- agno/os/routers/memory/schemas.py +44 -3
- agno/os/routers/metrics/metrics.py +30 -15
- agno/os/routers/metrics/schemas.py +10 -6
- agno/os/routers/registry/__init__.py +3 -0
- agno/os/routers/registry/registry.py +337 -0
- agno/os/routers/session/session.py +143 -14
- agno/os/routers/teams/__init__.py +3 -0
- agno/os/routers/teams/router.py +550 -0
- agno/os/routers/teams/schema.py +280 -0
- agno/os/routers/traces/__init__.py +3 -0
- agno/os/routers/traces/schemas.py +414 -0
- agno/os/routers/traces/traces.py +549 -0
- agno/os/routers/workflows/__init__.py +3 -0
- agno/os/routers/workflows/router.py +757 -0
- agno/os/routers/workflows/schema.py +139 -0
- agno/os/schema.py +157 -584
- agno/os/scopes.py +469 -0
- agno/os/settings.py +3 -0
- agno/os/utils.py +574 -185
- agno/reasoning/anthropic.py +85 -1
- agno/reasoning/azure_ai_foundry.py +93 -1
- agno/reasoning/deepseek.py +102 -2
- agno/reasoning/default.py +6 -7
- agno/reasoning/gemini.py +87 -3
- agno/reasoning/groq.py +109 -2
- agno/reasoning/helpers.py +6 -7
- agno/reasoning/manager.py +1238 -0
- agno/reasoning/ollama.py +93 -1
- agno/reasoning/openai.py +115 -1
- agno/reasoning/vertexai.py +85 -1
- agno/registry/__init__.py +3 -0
- agno/registry/registry.py +68 -0
- agno/remote/__init__.py +3 -0
- agno/remote/base.py +581 -0
- agno/run/__init__.py +2 -4
- agno/run/agent.py +134 -19
- agno/run/base.py +49 -1
- agno/run/cancel.py +65 -52
- agno/run/cancellation_management/__init__.py +9 -0
- agno/run/cancellation_management/base.py +78 -0
- agno/run/cancellation_management/in_memory_cancellation_manager.py +100 -0
- agno/run/cancellation_management/redis_cancellation_manager.py +236 -0
- agno/run/requirement.py +181 -0
- agno/run/team.py +111 -19
- agno/run/workflow.py +2 -1
- agno/session/agent.py +57 -92
- agno/session/summary.py +1 -1
- agno/session/team.py +62 -115
- agno/session/workflow.py +353 -57
- agno/skills/__init__.py +17 -0
- agno/skills/agent_skills.py +377 -0
- agno/skills/errors.py +32 -0
- agno/skills/loaders/__init__.py +4 -0
- agno/skills/loaders/base.py +27 -0
- agno/skills/loaders/local.py +216 -0
- agno/skills/skill.py +65 -0
- agno/skills/utils.py +107 -0
- agno/skills/validator.py +277 -0
- agno/table.py +10 -0
- agno/team/__init__.py +5 -1
- agno/team/remote.py +447 -0
- agno/team/team.py +3769 -2202
- agno/tools/brandfetch.py +27 -18
- agno/tools/browserbase.py +225 -16
- agno/tools/crawl4ai.py +3 -0
- agno/tools/duckduckgo.py +25 -71
- agno/tools/exa.py +0 -21
- agno/tools/file.py +14 -13
- agno/tools/file_generation.py +12 -6
- agno/tools/firecrawl.py +15 -7
- agno/tools/function.py +94 -113
- agno/tools/google_bigquery.py +11 -2
- agno/tools/google_drive.py +4 -3
- agno/tools/knowledge.py +9 -4
- agno/tools/mcp/mcp.py +301 -18
- agno/tools/mcp/multi_mcp.py +269 -14
- agno/tools/mem0.py +11 -10
- agno/tools/memory.py +47 -46
- agno/tools/mlx_transcribe.py +10 -7
- agno/tools/models/nebius.py +5 -5
- agno/tools/models_labs.py +20 -10
- agno/tools/nano_banana.py +151 -0
- agno/tools/parallel.py +0 -7
- agno/tools/postgres.py +76 -36
- agno/tools/python.py +14 -6
- agno/tools/reasoning.py +30 -23
- agno/tools/redshift.py +406 -0
- agno/tools/shopify.py +1519 -0
- agno/tools/spotify.py +919 -0
- agno/tools/tavily.py +4 -1
- agno/tools/toolkit.py +253 -18
- agno/tools/websearch.py +93 -0
- agno/tools/website.py +1 -1
- agno/tools/wikipedia.py +1 -1
- agno/tools/workflow.py +56 -48
- agno/tools/yfinance.py +12 -11
- agno/tracing/__init__.py +12 -0
- agno/tracing/exporter.py +161 -0
- agno/tracing/schemas.py +276 -0
- agno/tracing/setup.py +112 -0
- agno/utils/agent.py +251 -10
- agno/utils/cryptography.py +22 -0
- agno/utils/dttm.py +33 -0
- agno/utils/events.py +264 -7
- agno/utils/hooks.py +111 -3
- agno/utils/http.py +161 -2
- agno/utils/mcp.py +49 -8
- agno/utils/media.py +22 -1
- agno/utils/models/ai_foundry.py +9 -2
- agno/utils/models/claude.py +20 -5
- agno/utils/models/cohere.py +9 -2
- agno/utils/models/llama.py +9 -2
- agno/utils/models/mistral.py +4 -2
- agno/utils/os.py +0 -0
- agno/utils/print_response/agent.py +99 -16
- agno/utils/print_response/team.py +223 -24
- agno/utils/print_response/workflow.py +0 -2
- agno/utils/prompts.py +8 -6
- agno/utils/remote.py +23 -0
- agno/utils/response.py +1 -13
- agno/utils/string.py +91 -2
- agno/utils/team.py +62 -12
- agno/utils/tokens.py +657 -0
- agno/vectordb/base.py +15 -2
- agno/vectordb/cassandra/cassandra.py +1 -1
- agno/vectordb/chroma/__init__.py +2 -1
- agno/vectordb/chroma/chromadb.py +468 -23
- agno/vectordb/clickhouse/clickhousedb.py +1 -1
- agno/vectordb/couchbase/couchbase.py +6 -2
- agno/vectordb/lancedb/lance_db.py +7 -38
- agno/vectordb/lightrag/lightrag.py +7 -6
- agno/vectordb/milvus/milvus.py +118 -84
- agno/vectordb/mongodb/__init__.py +2 -1
- agno/vectordb/mongodb/mongodb.py +14 -31
- agno/vectordb/pgvector/pgvector.py +120 -66
- agno/vectordb/pineconedb/pineconedb.py +2 -19
- agno/vectordb/qdrant/__init__.py +2 -1
- agno/vectordb/qdrant/qdrant.py +33 -56
- agno/vectordb/redis/__init__.py +2 -1
- agno/vectordb/redis/redisdb.py +19 -31
- agno/vectordb/singlestore/singlestore.py +17 -9
- agno/vectordb/surrealdb/surrealdb.py +2 -38
- agno/vectordb/weaviate/__init__.py +2 -1
- agno/vectordb/weaviate/weaviate.py +7 -3
- agno/workflow/__init__.py +5 -1
- agno/workflow/agent.py +2 -2
- agno/workflow/condition.py +12 -10
- agno/workflow/loop.py +28 -9
- agno/workflow/parallel.py +21 -13
- agno/workflow/remote.py +362 -0
- agno/workflow/router.py +12 -9
- agno/workflow/step.py +261 -36
- agno/workflow/steps.py +12 -8
- agno/workflow/types.py +40 -77
- agno/workflow/workflow.py +939 -213
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/METADATA +134 -181
- agno-2.4.3.dist-info/RECORD +677 -0
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/WHEEL +1 -1
- agno/tools/googlesearch.py +0 -98
- agno/tools/memori.py +0 -339
- agno-2.2.13.dist-info/RECORD +0 -575
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/licenses/LICENSE +0 -0
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/top_level.txt +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import json
|
|
1
2
|
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Set, Union, get_args
|
|
2
3
|
|
|
3
4
|
from pydantic import BaseModel
|
|
@@ -25,10 +26,12 @@ def print_response(
|
|
|
25
26
|
show_message: bool = True,
|
|
26
27
|
show_reasoning: bool = True,
|
|
27
28
|
show_full_reasoning: bool = False,
|
|
29
|
+
show_member_responses: Optional[bool] = None,
|
|
28
30
|
tags_to_include_in_markdown: Optional[Set[str]] = None,
|
|
29
31
|
session_id: Optional[str] = None,
|
|
30
32
|
session_state: Optional[Dict[str, Any]] = None,
|
|
31
33
|
user_id: Optional[str] = None,
|
|
34
|
+
run_id: Optional[str] = None,
|
|
32
35
|
audio: Optional[Sequence[Audio]] = None,
|
|
33
36
|
images: Optional[Sequence[Image]] = None,
|
|
34
37
|
videos: Optional[Sequence[Video]] = None,
|
|
@@ -80,11 +83,13 @@ def print_response(
|
|
|
80
83
|
# Run the agent
|
|
81
84
|
run_response: TeamRunOutput = team.run( # type: ignore
|
|
82
85
|
input=input,
|
|
86
|
+
run_id=run_id,
|
|
83
87
|
images=images,
|
|
84
88
|
audio=audio,
|
|
85
89
|
videos=videos,
|
|
86
90
|
files=files,
|
|
87
91
|
stream=False,
|
|
92
|
+
stream_events=True,
|
|
88
93
|
session_id=session_id,
|
|
89
94
|
session_state=session_state,
|
|
90
95
|
user_id=user_id,
|
|
@@ -152,7 +157,7 @@ def print_response(
|
|
|
152
157
|
|
|
153
158
|
if isinstance(run_response, TeamRunOutput):
|
|
154
159
|
# Handle member responses
|
|
155
|
-
if
|
|
160
|
+
if show_member_responses:
|
|
156
161
|
for member_response in run_response.member_responses:
|
|
157
162
|
# Handle member reasoning
|
|
158
163
|
reasoning_steps = []
|
|
@@ -225,11 +230,23 @@ def print_response(
|
|
|
225
230
|
panels.append(member_response_panel)
|
|
226
231
|
|
|
227
232
|
if member_response.citations is not None and member_response.citations.urls is not None:
|
|
228
|
-
|
|
233
|
+
md_lines = []
|
|
234
|
+
|
|
235
|
+
# Add search queries if present
|
|
236
|
+
if member_response.citations.search_queries:
|
|
237
|
+
md_lines.append("**Search Queries:**")
|
|
238
|
+
for query in member_response.citations.search_queries:
|
|
239
|
+
md_lines.append(f"- {query}")
|
|
240
|
+
md_lines.append("") # Empty line before URLs
|
|
241
|
+
|
|
242
|
+
# Add URL citations
|
|
243
|
+
md_lines.extend(
|
|
229
244
|
f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
|
|
230
245
|
for i, citation in enumerate(member_response.citations.urls)
|
|
231
246
|
if citation.url # Only include citations with valid URLs
|
|
232
247
|
)
|
|
248
|
+
|
|
249
|
+
md_content = "\n".join(md_lines)
|
|
233
250
|
if md_content: # Only create panel if there are citations
|
|
234
251
|
citations_panel = create_panel(
|
|
235
252
|
content=Markdown(md_content),
|
|
@@ -258,6 +275,15 @@ def print_response(
|
|
|
258
275
|
# Join with blank lines between items
|
|
259
276
|
tool_calls_text = "\n\n".join(lines)
|
|
260
277
|
|
|
278
|
+
# Add compression stats at end of tool calls
|
|
279
|
+
if team.compression_manager is not None and team.compression_manager.stats:
|
|
280
|
+
stats = team.compression_manager.stats
|
|
281
|
+
saved = stats.get("original_size", 0) - stats.get("compressed_size", 0)
|
|
282
|
+
orig = stats.get("original_size", 1)
|
|
283
|
+
if stats.get("tool_results_compressed", 0) > 0:
|
|
284
|
+
tool_calls_text += f"\n\ncompressed: {stats.get('tool_results_compressed', 0)} | Saved: {saved:,} chars ({saved / orig * 100:.0f}%)"
|
|
285
|
+
team.compression_manager.stats.clear()
|
|
286
|
+
|
|
261
287
|
team_tool_calls_panel = create_panel(
|
|
262
288
|
content=tool_calls_text,
|
|
263
289
|
title="Team Tool Calls",
|
|
@@ -280,11 +306,23 @@ def print_response(
|
|
|
280
306
|
|
|
281
307
|
# Add citations
|
|
282
308
|
if run_response.citations is not None and run_response.citations.urls is not None:
|
|
283
|
-
|
|
309
|
+
md_lines = []
|
|
310
|
+
|
|
311
|
+
# Add search queries if present
|
|
312
|
+
if run_response.citations.search_queries:
|
|
313
|
+
md_lines.append("**Search Queries:**")
|
|
314
|
+
for query in run_response.citations.search_queries:
|
|
315
|
+
md_lines.append(f"- {query}")
|
|
316
|
+
md_lines.append("") # Empty line before URLs
|
|
317
|
+
|
|
318
|
+
# Add URL citations
|
|
319
|
+
md_lines.extend(
|
|
284
320
|
f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
|
|
285
321
|
for i, citation in enumerate(run_response.citations.urls)
|
|
286
322
|
if citation.url # Only include citations with valid URLs
|
|
287
323
|
)
|
|
324
|
+
|
|
325
|
+
md_content = "\n".join(md_lines)
|
|
288
326
|
if md_content: # Only create panel if there are citations
|
|
289
327
|
citations_panel = create_panel(
|
|
290
328
|
content=Markdown(md_content),
|
|
@@ -323,17 +361,18 @@ def print_response_stream(
|
|
|
323
361
|
show_message: bool = True,
|
|
324
362
|
show_reasoning: bool = True,
|
|
325
363
|
show_full_reasoning: bool = False,
|
|
364
|
+
show_member_responses: Optional[bool] = None,
|
|
326
365
|
tags_to_include_in_markdown: Optional[Set[str]] = None,
|
|
327
366
|
session_id: Optional[str] = None,
|
|
328
367
|
session_state: Optional[Dict[str, Any]] = None,
|
|
329
368
|
user_id: Optional[str] = None,
|
|
369
|
+
run_id: Optional[str] = None,
|
|
330
370
|
audio: Optional[Sequence[Audio]] = None,
|
|
331
371
|
images: Optional[Sequence[Image]] = None,
|
|
332
372
|
videos: Optional[Sequence[Video]] = None,
|
|
333
373
|
files: Optional[Sequence[File]] = None,
|
|
334
374
|
markdown: bool = False,
|
|
335
375
|
stream_events: bool = False,
|
|
336
|
-
stream_intermediate_steps: bool = False, # type: ignore
|
|
337
376
|
knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
|
|
338
377
|
add_history_to_context: Optional[bool] = None,
|
|
339
378
|
dependencies: Optional[Dict[str, Any]] = None,
|
|
@@ -405,6 +444,7 @@ def print_response_stream(
|
|
|
405
444
|
session_id=session_id,
|
|
406
445
|
session_state=session_state,
|
|
407
446
|
user_id=user_id,
|
|
447
|
+
run_id=run_id,
|
|
408
448
|
knowledge_filters=knowledge_filters,
|
|
409
449
|
add_history_to_context=add_history_to_context,
|
|
410
450
|
dependencies=dependencies,
|
|
@@ -412,7 +452,7 @@ def print_response_stream(
|
|
|
412
452
|
add_session_state_to_context=add_session_state_to_context,
|
|
413
453
|
metadata=metadata,
|
|
414
454
|
debug_mode=debug_mode,
|
|
415
|
-
|
|
455
|
+
yield_run_output=True,
|
|
416
456
|
**kwargs,
|
|
417
457
|
)
|
|
418
458
|
|
|
@@ -448,6 +488,11 @@ def print_response_stream(
|
|
|
448
488
|
_response_content = JSON(resp.content.model_dump_json(exclude_none=True), indent=2) # type: ignore
|
|
449
489
|
except Exception as e:
|
|
450
490
|
log_warning(f"Failed to convert response to JSON: {e}")
|
|
491
|
+
elif team.output_schema is not None and isinstance(resp.content, dict):
|
|
492
|
+
try:
|
|
493
|
+
_response_content = JSON(json.dumps(resp.content), indent=2) # type: ignore
|
|
494
|
+
except Exception as e:
|
|
495
|
+
log_warning(f"Failed to convert response to JSON: {e}")
|
|
451
496
|
if hasattr(resp, "reasoning_content") and resp.reasoning_content is not None: # type: ignore
|
|
452
497
|
_response_reasoning_content += resp.reasoning_content # type: ignore
|
|
453
498
|
if hasattr(resp, "reasoning_steps") and resp.reasoning_steps is not None: # type: ignore
|
|
@@ -470,7 +515,7 @@ def print_response_stream(
|
|
|
470
515
|
team_tool_calls.append(tool)
|
|
471
516
|
|
|
472
517
|
# Collect member tool calls, avoiding duplicates
|
|
473
|
-
if hasattr(resp, "member_responses") and resp.member_responses:
|
|
518
|
+
if show_member_responses and hasattr(resp, "member_responses") and resp.member_responses:
|
|
474
519
|
for member_response in resp.member_responses:
|
|
475
520
|
member_id = None
|
|
476
521
|
if isinstance(member_response, RunOutput) and member_response.agent_id is not None:
|
|
@@ -532,7 +577,9 @@ def print_response_stream(
|
|
|
532
577
|
panels.append(status)
|
|
533
578
|
|
|
534
579
|
# Process member responses and their tool calls
|
|
535
|
-
for member_response in
|
|
580
|
+
for member_response in (
|
|
581
|
+
resp.member_responses if show_member_responses and hasattr(resp, "member_responses") else []
|
|
582
|
+
):
|
|
536
583
|
member_id = None
|
|
537
584
|
member_name = "Team Member"
|
|
538
585
|
if isinstance(member_response, RunOutput) and member_response.agent_id is not None:
|
|
@@ -565,7 +612,7 @@ def print_response_stream(
|
|
|
565
612
|
panels.append(member_tool_calls_panel)
|
|
566
613
|
|
|
567
614
|
# Process member response content
|
|
568
|
-
if
|
|
615
|
+
if show_member_responses and member_id is not None:
|
|
569
616
|
show_markdown = False
|
|
570
617
|
if markdown:
|
|
571
618
|
show_markdown = True
|
|
@@ -608,6 +655,14 @@ def print_response_stream(
|
|
|
608
655
|
# Join with blank lines between items
|
|
609
656
|
tool_calls_text = "\n\n".join(lines)
|
|
610
657
|
|
|
658
|
+
# Add compression stats if available (don't clear - will be cleared in final_panels)
|
|
659
|
+
if team.compression_manager is not None and team.compression_manager.stats:
|
|
660
|
+
stats = team.compression_manager.stats
|
|
661
|
+
saved = stats.get("original_size", 0) - stats.get("compressed_size", 0)
|
|
662
|
+
orig = stats.get("original_size", 1)
|
|
663
|
+
if stats.get("tool_results_compressed", 0) > 0:
|
|
664
|
+
tool_calls_text += f"\n\ncompressed: {stats.get('tool_results_compressed', 0)} | Saved: {saved:,} chars ({saved / orig * 100:.0f}%)"
|
|
665
|
+
|
|
611
666
|
team_tool_calls_panel = create_panel(
|
|
612
667
|
content=tool_calls_text,
|
|
613
668
|
title="Team Tool Calls",
|
|
@@ -634,11 +689,23 @@ def print_response_stream(
|
|
|
634
689
|
|
|
635
690
|
# Add citations
|
|
636
691
|
if hasattr(resp, "citations") and resp.citations is not None and resp.citations.urls is not None:
|
|
637
|
-
|
|
692
|
+
md_lines = []
|
|
693
|
+
|
|
694
|
+
# Add search queries if present
|
|
695
|
+
if resp.citations.search_queries:
|
|
696
|
+
md_lines.append("**Search Queries:**")
|
|
697
|
+
for query in resp.citations.search_queries:
|
|
698
|
+
md_lines.append(f"- {query}")
|
|
699
|
+
md_lines.append("") # Empty line before URLs
|
|
700
|
+
|
|
701
|
+
# Add URL citations
|
|
702
|
+
md_lines.extend(
|
|
638
703
|
f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
|
|
639
704
|
for i, citation in enumerate(resp.citations.urls)
|
|
640
705
|
if citation.url # Only include citations with valid URLs
|
|
641
706
|
)
|
|
707
|
+
|
|
708
|
+
md_content = "\n".join(md_lines)
|
|
642
709
|
if md_content: # Only create panel if there are citations
|
|
643
710
|
citations_panel = create_panel(
|
|
644
711
|
content=Markdown(md_content),
|
|
@@ -708,7 +775,7 @@ def print_response_stream(
|
|
|
708
775
|
final_panels.append(thinking_panel)
|
|
709
776
|
|
|
710
777
|
# Add member tool calls and responses in correct order
|
|
711
|
-
if run_response is not None and hasattr(run_response, "member_responses"):
|
|
778
|
+
if show_member_responses and run_response is not None and hasattr(run_response, "member_responses"):
|
|
712
779
|
for i, member_response in enumerate(run_response.member_responses): # type: ignore
|
|
713
780
|
member_id = None
|
|
714
781
|
if isinstance(member_response, RunOutput) and member_response.agent_id is not None:
|
|
@@ -778,11 +845,23 @@ def print_response_stream(
|
|
|
778
845
|
|
|
779
846
|
# Add citations if any
|
|
780
847
|
if member_response.citations is not None and member_response.citations.urls is not None:
|
|
781
|
-
|
|
848
|
+
md_lines = []
|
|
849
|
+
|
|
850
|
+
# Add search queries if present
|
|
851
|
+
if member_response.citations.search_queries:
|
|
852
|
+
md_lines.append("**Search Queries:**")
|
|
853
|
+
for query in member_response.citations.search_queries:
|
|
854
|
+
md_lines.append(f"- {query}")
|
|
855
|
+
md_lines.append("") # Empty line before URLs
|
|
856
|
+
|
|
857
|
+
# Add URL citations
|
|
858
|
+
md_lines.extend(
|
|
782
859
|
f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
|
|
783
860
|
for i, citation in enumerate(member_response.citations.urls)
|
|
784
861
|
if citation.url # Only include citations with valid URLs
|
|
785
862
|
)
|
|
863
|
+
|
|
864
|
+
md_content = "\n".join(md_lines)
|
|
786
865
|
if md_content: # Only create panel if there are citations
|
|
787
866
|
citations_panel = create_panel(
|
|
788
867
|
content=Markdown(md_content),
|
|
@@ -810,6 +889,15 @@ def print_response_stream(
|
|
|
810
889
|
|
|
811
890
|
tool_calls_text = "\n\n".join(lines)
|
|
812
891
|
|
|
892
|
+
# Add compression stats at end of tool calls
|
|
893
|
+
if team.compression_manager is not None and team.compression_manager.stats:
|
|
894
|
+
stats = team.compression_manager.stats
|
|
895
|
+
saved = stats.get("original_size", 0) - stats.get("compressed_size", 0)
|
|
896
|
+
orig = stats.get("original_size", 1)
|
|
897
|
+
if stats.get("tool_results_compressed", 0) > 0:
|
|
898
|
+
tool_calls_text += f"\n\ncompressed: {stats.get('tool_results_compressed', 0)} | Saved: {saved:,} chars ({saved / orig * 100:.0f}%)"
|
|
899
|
+
team.compression_manager.stats.clear()
|
|
900
|
+
|
|
813
901
|
team_tool_calls_panel = create_panel(
|
|
814
902
|
content=tool_calls_text,
|
|
815
903
|
title="Team Tool Calls",
|
|
@@ -833,11 +921,23 @@ def print_response_stream(
|
|
|
833
921
|
|
|
834
922
|
# Add team citations
|
|
835
923
|
if hasattr(resp, "citations") and resp.citations is not None and resp.citations.urls is not None:
|
|
836
|
-
|
|
924
|
+
md_lines = []
|
|
925
|
+
|
|
926
|
+
# Add search queries if present
|
|
927
|
+
if resp.citations.search_queries:
|
|
928
|
+
md_lines.append("**Search Queries:**")
|
|
929
|
+
for query in resp.citations.search_queries:
|
|
930
|
+
md_lines.append(f"- {query}")
|
|
931
|
+
md_lines.append("") # Empty line before URLs
|
|
932
|
+
|
|
933
|
+
# Add URL citations
|
|
934
|
+
md_lines.extend(
|
|
837
935
|
f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
|
|
838
936
|
for i, citation in enumerate(resp.citations.urls)
|
|
839
937
|
if citation.url # Only include citations with valid URLs
|
|
840
938
|
)
|
|
939
|
+
|
|
940
|
+
md_content = "\n".join(md_lines)
|
|
841
941
|
if md_content: # Only create panel if there are citations
|
|
842
942
|
citations_panel = create_panel(
|
|
843
943
|
content=Markdown(md_content),
|
|
@@ -857,10 +957,12 @@ async def aprint_response(
|
|
|
857
957
|
show_message: bool = True,
|
|
858
958
|
show_reasoning: bool = True,
|
|
859
959
|
show_full_reasoning: bool = False,
|
|
960
|
+
show_member_responses: Optional[bool] = None,
|
|
860
961
|
tags_to_include_in_markdown: Optional[Set[str]] = None,
|
|
861
962
|
session_id: Optional[str] = None,
|
|
862
963
|
session_state: Optional[Dict[str, Any]] = None,
|
|
863
964
|
user_id: Optional[str] = None,
|
|
965
|
+
run_id: Optional[str] = None,
|
|
864
966
|
audio: Optional[Sequence[Audio]] = None,
|
|
865
967
|
images: Optional[Sequence[Image]] = None,
|
|
866
968
|
videos: Optional[Sequence[Video]] = None,
|
|
@@ -912,11 +1014,13 @@ async def aprint_response(
|
|
|
912
1014
|
# Run the agent
|
|
913
1015
|
run_response: TeamRunOutput = await team.arun( # type: ignore
|
|
914
1016
|
input=input,
|
|
1017
|
+
run_id=run_id,
|
|
915
1018
|
images=images,
|
|
916
1019
|
audio=audio,
|
|
917
1020
|
videos=videos,
|
|
918
1021
|
files=files,
|
|
919
1022
|
stream=False,
|
|
1023
|
+
stream_events=True,
|
|
920
1024
|
session_id=session_id,
|
|
921
1025
|
session_state=session_state,
|
|
922
1026
|
user_id=user_id,
|
|
@@ -984,7 +1088,7 @@ async def aprint_response(
|
|
|
984
1088
|
|
|
985
1089
|
if isinstance(run_response, TeamRunOutput):
|
|
986
1090
|
# Handle member responses
|
|
987
|
-
if
|
|
1091
|
+
if show_member_responses:
|
|
988
1092
|
for member_response in run_response.member_responses:
|
|
989
1093
|
# Handle member reasoning
|
|
990
1094
|
reasoning_steps = []
|
|
@@ -1057,11 +1161,23 @@ async def aprint_response(
|
|
|
1057
1161
|
panels.append(member_response_panel)
|
|
1058
1162
|
|
|
1059
1163
|
if member_response.citations is not None and member_response.citations.urls is not None:
|
|
1060
|
-
|
|
1164
|
+
md_lines = []
|
|
1165
|
+
|
|
1166
|
+
# Add search queries if present
|
|
1167
|
+
if member_response.citations.search_queries:
|
|
1168
|
+
md_lines.append("**Search Queries:**")
|
|
1169
|
+
for query in member_response.citations.search_queries:
|
|
1170
|
+
md_lines.append(f"- {query}")
|
|
1171
|
+
md_lines.append("") # Empty line before URLs
|
|
1172
|
+
|
|
1173
|
+
# Add URL citations
|
|
1174
|
+
md_lines.extend(
|
|
1061
1175
|
f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
|
|
1062
1176
|
for i, citation in enumerate(member_response.citations.urls)
|
|
1063
1177
|
if citation.url # Only include citations with valid URLs
|
|
1064
1178
|
)
|
|
1179
|
+
|
|
1180
|
+
md_content = "\n".join(md_lines)
|
|
1065
1181
|
if md_content:
|
|
1066
1182
|
citations_panel = create_panel(
|
|
1067
1183
|
content=Markdown(md_content),
|
|
@@ -1088,6 +1204,15 @@ async def aprint_response(
|
|
|
1088
1204
|
|
|
1089
1205
|
tool_calls_text = "\n\n".join(lines)
|
|
1090
1206
|
|
|
1207
|
+
# Add compression stats at end of tool calls
|
|
1208
|
+
if team.compression_manager is not None and team.compression_manager.stats:
|
|
1209
|
+
stats = team.compression_manager.stats
|
|
1210
|
+
saved = stats.get("original_size", 0) - stats.get("compressed_size", 0)
|
|
1211
|
+
orig = stats.get("original_size", 1)
|
|
1212
|
+
if stats.get("tool_results_compressed", 0) > 0:
|
|
1213
|
+
tool_calls_text += f"\n\ncompressed: {stats.get('tool_results_compressed', 0)} | Saved: {saved:,} chars ({saved / orig * 100:.0f}%)"
|
|
1214
|
+
team.compression_manager.stats.clear()
|
|
1215
|
+
|
|
1091
1216
|
team_tool_calls_panel = create_panel(
|
|
1092
1217
|
content=tool_calls_text,
|
|
1093
1218
|
title="Team Tool Calls",
|
|
@@ -1110,11 +1235,23 @@ async def aprint_response(
|
|
|
1110
1235
|
|
|
1111
1236
|
# Add citations
|
|
1112
1237
|
if run_response.citations is not None and run_response.citations.urls is not None:
|
|
1113
|
-
|
|
1238
|
+
md_lines = []
|
|
1239
|
+
|
|
1240
|
+
# Add search queries if present
|
|
1241
|
+
if run_response.citations.search_queries:
|
|
1242
|
+
md_lines.append("**Search Queries:**")
|
|
1243
|
+
for query in run_response.citations.search_queries:
|
|
1244
|
+
md_lines.append(f"- {query}")
|
|
1245
|
+
md_lines.append("") # Empty line before URLs
|
|
1246
|
+
|
|
1247
|
+
# Add URL citations
|
|
1248
|
+
md_lines.extend(
|
|
1114
1249
|
f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
|
|
1115
1250
|
for i, citation in enumerate(run_response.citations.urls)
|
|
1116
1251
|
if citation.url # Only include citations with valid URLs
|
|
1117
1252
|
)
|
|
1253
|
+
|
|
1254
|
+
md_content = "\n".join(md_lines)
|
|
1118
1255
|
if md_content: # Only create panel if there are citations
|
|
1119
1256
|
citations_panel = create_panel(
|
|
1120
1257
|
content=Markdown(md_content),
|
|
@@ -1153,17 +1290,18 @@ async def aprint_response_stream(
|
|
|
1153
1290
|
show_message: bool = True,
|
|
1154
1291
|
show_reasoning: bool = True,
|
|
1155
1292
|
show_full_reasoning: bool = False,
|
|
1293
|
+
show_member_responses: Optional[bool] = None,
|
|
1156
1294
|
tags_to_include_in_markdown: Optional[Set[str]] = None,
|
|
1157
1295
|
session_id: Optional[str] = None,
|
|
1158
1296
|
session_state: Optional[Dict[str, Any]] = None,
|
|
1159
1297
|
user_id: Optional[str] = None,
|
|
1298
|
+
run_id: Optional[str] = None,
|
|
1160
1299
|
audio: Optional[Sequence[Audio]] = None,
|
|
1161
1300
|
images: Optional[Sequence[Image]] = None,
|
|
1162
1301
|
videos: Optional[Sequence[Video]] = None,
|
|
1163
1302
|
files: Optional[Sequence[File]] = None,
|
|
1164
1303
|
markdown: bool = False,
|
|
1165
1304
|
stream_events: bool = False,
|
|
1166
|
-
stream_intermediate_steps: bool = False, # type: ignore
|
|
1167
1305
|
knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
|
|
1168
1306
|
add_history_to_context: Optional[bool] = None,
|
|
1169
1307
|
dependencies: Optional[Dict[str, Any]] = None,
|
|
@@ -1245,6 +1383,7 @@ async def aprint_response_stream(
|
|
|
1245
1383
|
session_id=session_id,
|
|
1246
1384
|
session_state=session_state,
|
|
1247
1385
|
user_id=user_id,
|
|
1386
|
+
run_id=run_id,
|
|
1248
1387
|
knowledge_filters=knowledge_filters,
|
|
1249
1388
|
add_history_to_context=add_history_to_context,
|
|
1250
1389
|
add_dependencies_to_context=add_dependencies_to_context,
|
|
@@ -1252,7 +1391,7 @@ async def aprint_response_stream(
|
|
|
1252
1391
|
dependencies=dependencies,
|
|
1253
1392
|
metadata=metadata,
|
|
1254
1393
|
debug_mode=debug_mode,
|
|
1255
|
-
|
|
1394
|
+
yield_run_output=True,
|
|
1256
1395
|
**kwargs,
|
|
1257
1396
|
):
|
|
1258
1397
|
if team_markdown is None:
|
|
@@ -1277,6 +1416,11 @@ async def aprint_response_stream(
|
|
|
1277
1416
|
_response_content = JSON(resp.content.model_dump_json(exclude_none=True), indent=2) # type: ignore
|
|
1278
1417
|
except Exception as e:
|
|
1279
1418
|
log_warning(f"Failed to convert response to JSON: {e}")
|
|
1419
|
+
elif team.output_schema is not None and isinstance(resp.content, dict):
|
|
1420
|
+
try:
|
|
1421
|
+
_response_content = JSON(json.dumps(resp.content), indent=2) # type: ignore
|
|
1422
|
+
except Exception as e:
|
|
1423
|
+
log_warning(f"Failed to convert response to JSON: {e}")
|
|
1280
1424
|
if hasattr(resp, "reasoning_content") and resp.reasoning_content is not None: # type: ignore
|
|
1281
1425
|
_response_reasoning_content += resp.reasoning_content # type: ignore
|
|
1282
1426
|
if hasattr(resp, "reasoning_steps") and resp.reasoning_steps is not None: # type: ignore
|
|
@@ -1299,7 +1443,7 @@ async def aprint_response_stream(
|
|
|
1299
1443
|
team_tool_calls.append(tool)
|
|
1300
1444
|
|
|
1301
1445
|
# Collect member tool calls, avoiding duplicates
|
|
1302
|
-
if hasattr(resp, "member_responses") and resp.member_responses:
|
|
1446
|
+
if show_member_responses and hasattr(resp, "member_responses") and resp.member_responses:
|
|
1303
1447
|
for member_response in resp.member_responses:
|
|
1304
1448
|
member_id = None
|
|
1305
1449
|
if isinstance(member_response, RunOutput) and member_response.agent_id is not None:
|
|
@@ -1360,7 +1504,9 @@ async def aprint_response_stream(
|
|
|
1360
1504
|
panels.append(status)
|
|
1361
1505
|
|
|
1362
1506
|
# Process member responses and their tool calls
|
|
1363
|
-
for member_response in
|
|
1507
|
+
for member_response in (
|
|
1508
|
+
resp.member_responses if show_member_responses and hasattr(resp, "member_responses") else []
|
|
1509
|
+
):
|
|
1364
1510
|
member_id = None
|
|
1365
1511
|
member_name = "Team Member"
|
|
1366
1512
|
if isinstance(member_response, RunOutput) and member_response.agent_id is not None:
|
|
@@ -1393,7 +1539,7 @@ async def aprint_response_stream(
|
|
|
1393
1539
|
panels.append(member_tool_calls_panel)
|
|
1394
1540
|
|
|
1395
1541
|
# Process member response content
|
|
1396
|
-
if
|
|
1542
|
+
if show_member_responses and member_id is not None:
|
|
1397
1543
|
show_markdown = False
|
|
1398
1544
|
if markdown:
|
|
1399
1545
|
show_markdown = True
|
|
@@ -1436,6 +1582,14 @@ async def aprint_response_stream(
|
|
|
1436
1582
|
# Join with blank lines between items
|
|
1437
1583
|
tool_calls_text = "\n\n".join(lines)
|
|
1438
1584
|
|
|
1585
|
+
# Add compression stats if available (don't clear - will be cleared in final_panels)
|
|
1586
|
+
if team.compression_manager is not None and team.compression_manager.stats:
|
|
1587
|
+
stats = team.compression_manager.stats
|
|
1588
|
+
saved = stats.get("original_size", 0) - stats.get("compressed_size", 0)
|
|
1589
|
+
orig = stats.get("original_size", 1)
|
|
1590
|
+
if stats.get("tool_results_compressed", 0) > 0:
|
|
1591
|
+
tool_calls_text += f"\n\ncompressed: {stats.get('tool_results_compressed', 0)} | Saved: {saved:,} chars ({saved / orig * 100:.0f}%)"
|
|
1592
|
+
|
|
1439
1593
|
team_tool_calls_panel = create_panel(
|
|
1440
1594
|
content=tool_calls_text,
|
|
1441
1595
|
title="Team Tool Calls",
|
|
@@ -1463,11 +1617,23 @@ async def aprint_response_stream(
|
|
|
1463
1617
|
|
|
1464
1618
|
# Add citations
|
|
1465
1619
|
if hasattr(resp, "citations") and resp.citations is not None and resp.citations.urls is not None:
|
|
1466
|
-
|
|
1620
|
+
md_lines = []
|
|
1621
|
+
|
|
1622
|
+
# Add search queries if present
|
|
1623
|
+
if resp.citations.search_queries:
|
|
1624
|
+
md_lines.append("**Search Queries:**")
|
|
1625
|
+
for query in resp.citations.search_queries:
|
|
1626
|
+
md_lines.append(f"- {query}")
|
|
1627
|
+
md_lines.append("") # Empty line before URLs
|
|
1628
|
+
|
|
1629
|
+
# Add URL citations
|
|
1630
|
+
md_lines.extend(
|
|
1467
1631
|
f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
|
|
1468
1632
|
for i, citation in enumerate(resp.citations.urls)
|
|
1469
1633
|
if citation.url # Only include citations with valid URLs
|
|
1470
1634
|
)
|
|
1635
|
+
|
|
1636
|
+
md_content = "\n".join(md_lines)
|
|
1471
1637
|
if md_content: # Only create panel if there are citations
|
|
1472
1638
|
citations_panel = create_panel(
|
|
1473
1639
|
content=Markdown(md_content),
|
|
@@ -1537,7 +1703,7 @@ async def aprint_response_stream(
|
|
|
1537
1703
|
final_panels.append(thinking_panel)
|
|
1538
1704
|
|
|
1539
1705
|
# Add member tool calls and responses in correct order
|
|
1540
|
-
if run_response is not None and hasattr(run_response, "member_responses"):
|
|
1706
|
+
if show_member_responses and run_response is not None and hasattr(run_response, "member_responses"):
|
|
1541
1707
|
for i, member_response in enumerate(run_response.member_responses):
|
|
1542
1708
|
member_id = None
|
|
1543
1709
|
if isinstance(member_response, RunOutput) and member_response.agent_id is not None:
|
|
@@ -1624,11 +1790,23 @@ async def aprint_response_stream(
|
|
|
1624
1790
|
|
|
1625
1791
|
# Add citations if any
|
|
1626
1792
|
if member_response.citations is not None and member_response.citations.urls is not None:
|
|
1627
|
-
|
|
1793
|
+
md_lines = []
|
|
1794
|
+
|
|
1795
|
+
# Add search queries if present
|
|
1796
|
+
if member_response.citations.search_queries:
|
|
1797
|
+
md_lines.append("**Search Queries:**")
|
|
1798
|
+
for query in member_response.citations.search_queries:
|
|
1799
|
+
md_lines.append(f"- {query}")
|
|
1800
|
+
md_lines.append("") # Empty line before URLs
|
|
1801
|
+
|
|
1802
|
+
# Add URL citations
|
|
1803
|
+
md_lines.extend(
|
|
1628
1804
|
f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
|
|
1629
1805
|
for i, citation in enumerate(member_response.citations.urls)
|
|
1630
1806
|
if citation.url # Only include citations with valid URLs
|
|
1631
1807
|
)
|
|
1808
|
+
|
|
1809
|
+
md_content = "\n".join(md_lines)
|
|
1632
1810
|
if md_content: # Only create panel if there are citations
|
|
1633
1811
|
citations_panel = create_panel(
|
|
1634
1812
|
content=Markdown(md_content),
|
|
@@ -1656,6 +1834,15 @@ async def aprint_response_stream(
|
|
|
1656
1834
|
|
|
1657
1835
|
tool_calls_text = "\n\n".join(lines)
|
|
1658
1836
|
|
|
1837
|
+
# Add compression stats at end of tool calls
|
|
1838
|
+
if team.compression_manager is not None and team.compression_manager.stats:
|
|
1839
|
+
stats = team.compression_manager.stats
|
|
1840
|
+
saved = stats.get("original_size", 0) - stats.get("compressed_size", 0)
|
|
1841
|
+
orig = stats.get("original_size", 1)
|
|
1842
|
+
if stats.get("tool_results_compressed", 0) > 0:
|
|
1843
|
+
tool_calls_text += f"\n\ncompressed: {stats.get('tool_results_compressed', 0)} | Saved: {saved:,} chars ({saved / orig * 100:.0f}%)"
|
|
1844
|
+
team.compression_manager.stats.clear()
|
|
1845
|
+
|
|
1659
1846
|
team_tool_calls_panel = create_panel(
|
|
1660
1847
|
content=tool_calls_text,
|
|
1661
1848
|
title="Team Tool Calls",
|
|
@@ -1679,11 +1866,23 @@ async def aprint_response_stream(
|
|
|
1679
1866
|
|
|
1680
1867
|
# Add team citations
|
|
1681
1868
|
if hasattr(resp, "citations") and resp.citations is not None and resp.citations.urls is not None:
|
|
1682
|
-
|
|
1869
|
+
md_lines = []
|
|
1870
|
+
|
|
1871
|
+
# Add search queries if present
|
|
1872
|
+
if resp.citations.search_queries:
|
|
1873
|
+
md_lines.append("**Search Queries:**")
|
|
1874
|
+
for query in resp.citations.search_queries:
|
|
1875
|
+
md_lines.append(f"- {query}")
|
|
1876
|
+
md_lines.append("") # Empty line before URLs
|
|
1877
|
+
|
|
1878
|
+
# Add URL citations
|
|
1879
|
+
md_lines.extend(
|
|
1683
1880
|
f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
|
|
1684
1881
|
for i, citation in enumerate(resp.citations.urls)
|
|
1685
1882
|
if citation.url # Only include citations with valid URLs
|
|
1686
1883
|
)
|
|
1884
|
+
|
|
1885
|
+
md_content = "\n".join(md_lines)
|
|
1687
1886
|
if md_content: # Only create panel if there are citations
|
|
1688
1887
|
citations_panel = create_panel(
|
|
1689
1888
|
content=Markdown(md_content),
|
|
@@ -203,7 +203,6 @@ def print_response_stream(
|
|
|
203
203
|
videos: Optional[List[Video]] = None,
|
|
204
204
|
files: Optional[List[File]] = None,
|
|
205
205
|
stream_events: bool = False,
|
|
206
|
-
stream_intermediate_steps: bool = False,
|
|
207
206
|
markdown: bool = True,
|
|
208
207
|
show_time: bool = True,
|
|
209
208
|
show_step_details: bool = True,
|
|
@@ -1042,7 +1041,6 @@ async def aprint_response_stream(
|
|
|
1042
1041
|
videos: Optional[List[Video]] = None,
|
|
1043
1042
|
files: Optional[List[File]] = None,
|
|
1044
1043
|
stream_events: bool = False,
|
|
1045
|
-
stream_intermediate_steps: bool = False,
|
|
1046
1044
|
markdown: bool = True,
|
|
1047
1045
|
show_time: bool = True,
|
|
1048
1046
|
show_step_details: bool = True,
|
agno/utils/prompts.py
CHANGED
|
@@ -6,7 +6,7 @@ from pydantic import BaseModel
|
|
|
6
6
|
from agno.utils.log import log_warning
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
def get_json_output_prompt(output_schema: Union[str, list, BaseModel]) -> str:
|
|
9
|
+
def get_json_output_prompt(output_schema: Union[str, list, dict, BaseModel]) -> str:
|
|
10
10
|
"""Return the JSON output prompt for the Agent.
|
|
11
11
|
|
|
12
12
|
This is added to the system prompt when the output_schema is set and structured_outputs is False.
|
|
@@ -22,11 +22,13 @@ def get_json_output_prompt(output_schema: Union[str, list, BaseModel]) -> str:
|
|
|
22
22
|
json_output_prompt += "\n<json_fields>"
|
|
23
23
|
json_output_prompt += f"\n{json.dumps(output_schema)}"
|
|
24
24
|
json_output_prompt += "\n</json_fields>"
|
|
25
|
-
elif (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
elif isinstance(output_schema, dict):
|
|
26
|
+
json_output_prompt += "\n<json_fields>"
|
|
27
|
+
json_output_prompt += f"\n{json.dumps(output_schema)}"
|
|
28
|
+
json_output_prompt += "\n</json_fields>"
|
|
29
|
+
elif (isinstance(output_schema, type) and issubclass(output_schema, BaseModel)) or isinstance(
|
|
30
|
+
output_schema, BaseModel
|
|
31
|
+
):
|
|
30
32
|
json_schema = output_schema.model_json_schema()
|
|
31
33
|
if json_schema is not None:
|
|
32
34
|
response_model_properties = {}
|
agno/utils/remote.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Any, Dict, List, Union
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel
|
|
5
|
+
|
|
6
|
+
from agno.models.message import Message
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def serialize_input(
|
|
10
|
+
input: Union[str, Dict[str, Any], List[Any], BaseModel, List[Message]],
|
|
11
|
+
) -> str:
|
|
12
|
+
"""Serialize the input to a string."""
|
|
13
|
+
if isinstance(input, str):
|
|
14
|
+
return input
|
|
15
|
+
elif isinstance(input, dict):
|
|
16
|
+
return json.dumps(input)
|
|
17
|
+
elif isinstance(input, list):
|
|
18
|
+
if any(isinstance(item, Message) for item in input):
|
|
19
|
+
return json.dumps([item.to_dict() for item in input])
|
|
20
|
+
else:
|
|
21
|
+
return json.dumps(input)
|
|
22
|
+
elif isinstance(input, BaseModel):
|
|
23
|
+
return input.model_dump_json()
|
agno/utils/response.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import List, Set, Union
|
|
2
2
|
|
|
3
3
|
from agno.exceptions import RunCancelledException
|
|
4
4
|
from agno.models.response import ToolExecution
|
|
@@ -149,15 +149,3 @@ def get_paused_content(run_output: RunOutput) -> str:
|
|
|
149
149
|
elif external_execution_required:
|
|
150
150
|
paused_content = "I have tools to execute, but it needs external execution."
|
|
151
151
|
return paused_content
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
def generator_wrapper(
|
|
155
|
-
event: Union[RunOutputEvent, TeamRunOutputEvent],
|
|
156
|
-
) -> Iterator[Union[RunOutputEvent, TeamRunOutputEvent]]:
|
|
157
|
-
yield event
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
async def async_generator_wrapper(
|
|
161
|
-
event: Union[RunOutputEvent, TeamRunOutputEvent],
|
|
162
|
-
) -> AsyncIterator[Union[RunOutputEvent, TeamRunOutputEvent]]:
|
|
163
|
-
yield event
|