agno 0.1.2__py3-none-any.whl → 2.3.13__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/__init__.py +8 -0
- agno/agent/__init__.py +44 -5
- agno/agent/agent.py +10531 -2975
- agno/api/agent.py +14 -53
- agno/api/api.py +7 -46
- agno/api/evals.py +22 -0
- agno/api/os.py +17 -0
- agno/api/routes.py +6 -25
- agno/api/schemas/__init__.py +9 -0
- agno/api/schemas/agent.py +6 -9
- agno/api/schemas/evals.py +16 -0
- agno/api/schemas/os.py +14 -0
- agno/api/schemas/team.py +10 -10
- agno/api/schemas/utils.py +21 -0
- agno/api/schemas/workflows.py +16 -0
- agno/api/settings.py +53 -0
- agno/api/team.py +22 -26
- agno/api/workflow.py +28 -0
- agno/cloud/aws/base.py +214 -0
- agno/cloud/aws/s3/__init__.py +2 -0
- agno/cloud/aws/s3/api_client.py +43 -0
- agno/cloud/aws/s3/bucket.py +195 -0
- agno/cloud/aws/s3/object.py +57 -0
- agno/compression/__init__.py +3 -0
- agno/compression/manager.py +247 -0
- agno/culture/__init__.py +3 -0
- agno/culture/manager.py +956 -0
- agno/db/__init__.py +24 -0
- agno/db/async_postgres/__init__.py +3 -0
- agno/db/base.py +946 -0
- agno/db/dynamo/__init__.py +3 -0
- agno/db/dynamo/dynamo.py +2781 -0
- agno/db/dynamo/schemas.py +442 -0
- agno/db/dynamo/utils.py +743 -0
- agno/db/firestore/__init__.py +3 -0
- agno/db/firestore/firestore.py +2379 -0
- agno/db/firestore/schemas.py +181 -0
- agno/db/firestore/utils.py +376 -0
- agno/db/gcs_json/__init__.py +3 -0
- agno/db/gcs_json/gcs_json_db.py +1791 -0
- agno/db/gcs_json/utils.py +228 -0
- agno/db/in_memory/__init__.py +3 -0
- agno/db/in_memory/in_memory_db.py +1312 -0
- agno/db/in_memory/utils.py +230 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1777 -0
- agno/db/json/utils.py +230 -0
- agno/db/migrations/manager.py +199 -0
- agno/db/migrations/v1_to_v2.py +635 -0
- agno/db/migrations/versions/v2_3_0.py +938 -0
- agno/db/mongo/__init__.py +17 -0
- agno/db/mongo/async_mongo.py +2760 -0
- agno/db/mongo/mongo.py +2597 -0
- agno/db/mongo/schemas.py +119 -0
- agno/db/mongo/utils.py +276 -0
- agno/db/mysql/__init__.py +4 -0
- agno/db/mysql/async_mysql.py +2912 -0
- agno/db/mysql/mysql.py +2923 -0
- agno/db/mysql/schemas.py +186 -0
- agno/db/mysql/utils.py +488 -0
- agno/db/postgres/__init__.py +4 -0
- agno/db/postgres/async_postgres.py +2579 -0
- agno/db/postgres/postgres.py +2870 -0
- agno/db/postgres/schemas.py +187 -0
- agno/db/postgres/utils.py +442 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +2141 -0
- agno/db/redis/schemas.py +159 -0
- agno/db/redis/utils.py +346 -0
- agno/db/schemas/__init__.py +4 -0
- agno/db/schemas/culture.py +120 -0
- agno/db/schemas/evals.py +34 -0
- agno/db/schemas/knowledge.py +40 -0
- agno/db/schemas/memory.py +61 -0
- agno/db/singlestore/__init__.py +3 -0
- agno/db/singlestore/schemas.py +179 -0
- agno/db/singlestore/singlestore.py +2877 -0
- agno/db/singlestore/utils.py +384 -0
- agno/db/sqlite/__init__.py +4 -0
- agno/db/sqlite/async_sqlite.py +2911 -0
- agno/db/sqlite/schemas.py +181 -0
- agno/db/sqlite/sqlite.py +2908 -0
- agno/db/sqlite/utils.py +429 -0
- agno/db/surrealdb/__init__.py +3 -0
- agno/db/surrealdb/metrics.py +292 -0
- agno/db/surrealdb/models.py +334 -0
- agno/db/surrealdb/queries.py +71 -0
- agno/db/surrealdb/surrealdb.py +1908 -0
- agno/db/surrealdb/utils.py +147 -0
- agno/db/utils.py +118 -0
- agno/eval/__init__.py +24 -0
- agno/eval/accuracy.py +666 -276
- agno/eval/agent_as_judge.py +861 -0
- agno/eval/base.py +29 -0
- agno/eval/performance.py +779 -0
- agno/eval/reliability.py +241 -62
- agno/eval/utils.py +120 -0
- agno/exceptions.py +143 -1
- agno/filters.py +354 -0
- agno/guardrails/__init__.py +6 -0
- agno/guardrails/base.py +19 -0
- agno/guardrails/openai.py +144 -0
- agno/guardrails/pii.py +94 -0
- agno/guardrails/prompt_injection.py +52 -0
- agno/hooks/__init__.py +3 -0
- agno/hooks/decorator.py +164 -0
- agno/integrations/discord/__init__.py +3 -0
- agno/integrations/discord/client.py +203 -0
- agno/knowledge/__init__.py +5 -1
- agno/{document → knowledge}/chunking/agentic.py +22 -14
- agno/{document → knowledge}/chunking/document.py +2 -2
- agno/{document → knowledge}/chunking/fixed.py +7 -6
- agno/knowledge/chunking/markdown.py +151 -0
- agno/{document → knowledge}/chunking/recursive.py +15 -3
- agno/knowledge/chunking/row.py +39 -0
- agno/knowledge/chunking/semantic.py +91 -0
- agno/knowledge/chunking/strategy.py +165 -0
- agno/knowledge/content.py +74 -0
- agno/knowledge/document/__init__.py +5 -0
- agno/{document → knowledge/document}/base.py +12 -2
- agno/knowledge/embedder/__init__.py +5 -0
- agno/knowledge/embedder/aws_bedrock.py +343 -0
- agno/knowledge/embedder/azure_openai.py +210 -0
- agno/{embedder → knowledge/embedder}/base.py +8 -0
- agno/knowledge/embedder/cohere.py +323 -0
- agno/knowledge/embedder/fastembed.py +62 -0
- agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
- agno/knowledge/embedder/google.py +258 -0
- agno/knowledge/embedder/huggingface.py +94 -0
- agno/knowledge/embedder/jina.py +182 -0
- agno/knowledge/embedder/langdb.py +22 -0
- agno/knowledge/embedder/mistral.py +206 -0
- agno/knowledge/embedder/nebius.py +13 -0
- agno/knowledge/embedder/ollama.py +154 -0
- agno/knowledge/embedder/openai.py +195 -0
- agno/knowledge/embedder/sentence_transformer.py +63 -0
- agno/{embedder → knowledge/embedder}/together.py +1 -1
- agno/knowledge/embedder/vllm.py +262 -0
- agno/knowledge/embedder/voyageai.py +165 -0
- agno/knowledge/knowledge.py +3006 -0
- agno/knowledge/reader/__init__.py +7 -0
- agno/knowledge/reader/arxiv_reader.py +81 -0
- agno/knowledge/reader/base.py +95 -0
- agno/knowledge/reader/csv_reader.py +164 -0
- agno/knowledge/reader/docx_reader.py +82 -0
- agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
- agno/knowledge/reader/firecrawl_reader.py +201 -0
- agno/knowledge/reader/json_reader.py +88 -0
- agno/knowledge/reader/markdown_reader.py +137 -0
- agno/knowledge/reader/pdf_reader.py +431 -0
- agno/knowledge/reader/pptx_reader.py +101 -0
- agno/knowledge/reader/reader_factory.py +313 -0
- agno/knowledge/reader/s3_reader.py +89 -0
- agno/knowledge/reader/tavily_reader.py +193 -0
- agno/knowledge/reader/text_reader.py +127 -0
- agno/knowledge/reader/web_search_reader.py +325 -0
- agno/knowledge/reader/website_reader.py +455 -0
- agno/knowledge/reader/wikipedia_reader.py +91 -0
- agno/knowledge/reader/youtube_reader.py +78 -0
- agno/knowledge/remote_content/remote_content.py +88 -0
- agno/knowledge/reranker/__init__.py +3 -0
- agno/{reranker → knowledge/reranker}/base.py +1 -1
- agno/{reranker → knowledge/reranker}/cohere.py +2 -2
- agno/knowledge/reranker/infinity.py +195 -0
- agno/knowledge/reranker/sentence_transformer.py +54 -0
- agno/knowledge/types.py +39 -0
- agno/knowledge/utils.py +234 -0
- agno/media.py +439 -95
- agno/memory/__init__.py +16 -3
- agno/memory/manager.py +1474 -123
- 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/__init__.py +5 -0
- agno/models/aimlapi/aimlapi.py +62 -0
- agno/models/anthropic/__init__.py +4 -0
- agno/models/anthropic/claude.py +960 -496
- agno/models/aws/__init__.py +15 -0
- agno/models/aws/bedrock.py +686 -451
- agno/models/aws/claude.py +190 -183
- agno/models/azure/__init__.py +18 -1
- agno/models/azure/ai_foundry.py +489 -0
- agno/models/azure/openai_chat.py +89 -40
- agno/models/base.py +2477 -550
- agno/models/cerebras/__init__.py +12 -0
- agno/models/cerebras/cerebras.py +565 -0
- agno/models/cerebras/cerebras_openai.py +131 -0
- agno/models/cohere/__init__.py +4 -0
- agno/models/cohere/chat.py +306 -492
- agno/models/cometapi/__init__.py +5 -0
- agno/models/cometapi/cometapi.py +74 -0
- agno/models/dashscope/__init__.py +5 -0
- agno/models/dashscope/dashscope.py +90 -0
- agno/models/deepinfra/__init__.py +5 -0
- agno/models/deepinfra/deepinfra.py +45 -0
- agno/models/deepseek/__init__.py +4 -0
- agno/models/deepseek/deepseek.py +110 -9
- agno/models/fireworks/__init__.py +4 -0
- agno/models/fireworks/fireworks.py +19 -22
- agno/models/google/__init__.py +3 -7
- agno/models/google/gemini.py +1717 -662
- agno/models/google/utils.py +22 -0
- agno/models/groq/__init__.py +4 -0
- agno/models/groq/groq.py +391 -666
- agno/models/huggingface/__init__.py +4 -0
- agno/models/huggingface/huggingface.py +266 -538
- agno/models/ibm/__init__.py +5 -0
- agno/models/ibm/watsonx.py +432 -0
- agno/models/internlm/__init__.py +3 -0
- agno/models/internlm/internlm.py +20 -3
- agno/models/langdb/__init__.py +1 -0
- agno/models/langdb/langdb.py +60 -0
- agno/models/litellm/__init__.py +14 -0
- agno/models/litellm/chat.py +503 -0
- agno/models/litellm/litellm_openai.py +42 -0
- agno/models/llama_cpp/__init__.py +5 -0
- agno/models/llama_cpp/llama_cpp.py +22 -0
- agno/models/lmstudio/__init__.py +5 -0
- agno/models/lmstudio/lmstudio.py +25 -0
- agno/models/message.py +361 -39
- agno/models/meta/__init__.py +12 -0
- agno/models/meta/llama.py +502 -0
- agno/models/meta/llama_openai.py +79 -0
- agno/models/metrics.py +120 -0
- agno/models/mistral/__init__.py +4 -0
- agno/models/mistral/mistral.py +293 -393
- agno/models/nebius/__init__.py +3 -0
- agno/models/nebius/nebius.py +53 -0
- agno/models/nexus/__init__.py +3 -0
- agno/models/nexus/nexus.py +22 -0
- agno/models/nvidia/__init__.py +4 -0
- agno/models/nvidia/nvidia.py +22 -3
- agno/models/ollama/__init__.py +4 -2
- agno/models/ollama/chat.py +257 -492
- agno/models/openai/__init__.py +7 -0
- agno/models/openai/chat.py +725 -770
- agno/models/openai/like.py +16 -2
- agno/models/openai/responses.py +1121 -0
- agno/models/openrouter/__init__.py +4 -0
- agno/models/openrouter/openrouter.py +62 -5
- agno/models/perplexity/__init__.py +5 -0
- agno/models/perplexity/perplexity.py +203 -0
- agno/models/portkey/__init__.py +3 -0
- agno/models/portkey/portkey.py +82 -0
- agno/models/requesty/__init__.py +5 -0
- agno/models/requesty/requesty.py +69 -0
- agno/models/response.py +177 -7
- agno/models/sambanova/__init__.py +4 -0
- agno/models/sambanova/sambanova.py +23 -4
- agno/models/siliconflow/__init__.py +5 -0
- agno/models/siliconflow/siliconflow.py +42 -0
- agno/models/together/__init__.py +4 -0
- agno/models/together/together.py +21 -164
- agno/models/utils.py +266 -0
- agno/models/vercel/__init__.py +3 -0
- agno/models/vercel/v0.py +43 -0
- agno/models/vertexai/__init__.py +0 -1
- agno/models/vertexai/claude.py +190 -0
- agno/models/vllm/__init__.py +3 -0
- agno/models/vllm/vllm.py +83 -0
- agno/models/xai/__init__.py +2 -0
- agno/models/xai/xai.py +111 -7
- agno/os/__init__.py +3 -0
- agno/os/app.py +1027 -0
- agno/os/auth.py +244 -0
- agno/os/config.py +126 -0
- agno/os/interfaces/__init__.py +1 -0
- agno/os/interfaces/a2a/__init__.py +3 -0
- agno/os/interfaces/a2a/a2a.py +42 -0
- agno/os/interfaces/a2a/router.py +249 -0
- agno/os/interfaces/a2a/utils.py +924 -0
- agno/os/interfaces/agui/__init__.py +3 -0
- agno/os/interfaces/agui/agui.py +47 -0
- agno/os/interfaces/agui/router.py +147 -0
- agno/os/interfaces/agui/utils.py +574 -0
- agno/os/interfaces/base.py +25 -0
- agno/os/interfaces/slack/__init__.py +3 -0
- agno/os/interfaces/slack/router.py +148 -0
- agno/os/interfaces/slack/security.py +30 -0
- agno/os/interfaces/slack/slack.py +47 -0
- agno/os/interfaces/whatsapp/__init__.py +3 -0
- agno/os/interfaces/whatsapp/router.py +210 -0
- agno/os/interfaces/whatsapp/security.py +55 -0
- agno/os/interfaces/whatsapp/whatsapp.py +36 -0
- agno/os/mcp.py +293 -0
- agno/os/middleware/__init__.py +9 -0
- agno/os/middleware/jwt.py +797 -0
- agno/os/router.py +258 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/agents/__init__.py +3 -0
- agno/os/routers/agents/router.py +599 -0
- agno/os/routers/agents/schema.py +261 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +450 -0
- agno/os/routers/evals/schemas.py +174 -0
- agno/os/routers/evals/utils.py +231 -0
- agno/os/routers/health.py +31 -0
- agno/os/routers/home.py +52 -0
- agno/os/routers/knowledge/__init__.py +3 -0
- agno/os/routers/knowledge/knowledge.py +1008 -0
- agno/os/routers/knowledge/schemas.py +178 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +661 -0
- agno/os/routers/memory/schemas.py +88 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +190 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +997 -0
- agno/os/routers/teams/__init__.py +3 -0
- agno/os/routers/teams/router.py +512 -0
- agno/os/routers/teams/schema.py +257 -0
- agno/os/routers/traces/__init__.py +3 -0
- agno/os/routers/traces/schemas.py +414 -0
- agno/os/routers/traces/traces.py +499 -0
- agno/os/routers/workflows/__init__.py +3 -0
- agno/os/routers/workflows/router.py +624 -0
- agno/os/routers/workflows/schema.py +75 -0
- agno/os/schema.py +534 -0
- agno/os/scopes.py +469 -0
- agno/{playground → os}/settings.py +7 -15
- agno/os/utils.py +973 -0
- agno/reasoning/anthropic.py +80 -0
- agno/reasoning/azure_ai_foundry.py +67 -0
- agno/reasoning/deepseek.py +63 -0
- agno/reasoning/default.py +97 -0
- agno/reasoning/gemini.py +73 -0
- agno/reasoning/groq.py +71 -0
- agno/reasoning/helpers.py +24 -1
- agno/reasoning/ollama.py +67 -0
- agno/reasoning/openai.py +86 -0
- agno/reasoning/step.py +2 -1
- agno/reasoning/vertexai.py +76 -0
- agno/run/__init__.py +6 -0
- agno/run/agent.py +822 -0
- agno/run/base.py +247 -0
- agno/run/cancel.py +81 -0
- agno/run/requirement.py +181 -0
- agno/run/team.py +767 -0
- agno/run/workflow.py +708 -0
- agno/session/__init__.py +10 -0
- agno/session/agent.py +260 -0
- agno/session/summary.py +265 -0
- agno/session/team.py +342 -0
- agno/session/workflow.py +501 -0
- agno/table.py +10 -0
- agno/team/__init__.py +37 -0
- agno/team/team.py +9536 -0
- agno/tools/__init__.py +7 -0
- agno/tools/agentql.py +120 -0
- agno/tools/airflow.py +22 -12
- agno/tools/api.py +122 -0
- agno/tools/apify.py +276 -83
- agno/tools/{arxiv_toolkit.py → arxiv.py} +20 -12
- agno/tools/aws_lambda.py +28 -7
- agno/tools/aws_ses.py +66 -0
- agno/tools/baidusearch.py +11 -4
- agno/tools/bitbucket.py +292 -0
- agno/tools/brandfetch.py +213 -0
- agno/tools/bravesearch.py +106 -0
- agno/tools/brightdata.py +367 -0
- agno/tools/browserbase.py +209 -0
- agno/tools/calcom.py +32 -23
- agno/tools/calculator.py +24 -37
- agno/tools/cartesia.py +187 -0
- agno/tools/{clickup_tool.py → clickup.py} +17 -28
- agno/tools/confluence.py +91 -26
- agno/tools/crawl4ai.py +139 -43
- agno/tools/csv_toolkit.py +28 -22
- agno/tools/dalle.py +36 -22
- agno/tools/daytona.py +475 -0
- agno/tools/decorator.py +169 -14
- agno/tools/desi_vocal.py +23 -11
- agno/tools/discord.py +32 -29
- agno/tools/docker.py +716 -0
- agno/tools/duckdb.py +76 -81
- agno/tools/duckduckgo.py +43 -40
- agno/tools/e2b.py +703 -0
- agno/tools/eleven_labs.py +65 -54
- agno/tools/email.py +13 -5
- agno/tools/evm.py +129 -0
- agno/tools/exa.py +324 -42
- agno/tools/fal.py +39 -35
- agno/tools/file.py +196 -30
- agno/tools/file_generation.py +356 -0
- agno/tools/financial_datasets.py +288 -0
- agno/tools/firecrawl.py +108 -33
- agno/tools/function.py +960 -122
- agno/tools/giphy.py +34 -12
- agno/tools/github.py +1294 -97
- agno/tools/gmail.py +922 -0
- agno/tools/google_bigquery.py +117 -0
- agno/tools/google_drive.py +271 -0
- agno/tools/google_maps.py +253 -0
- agno/tools/googlecalendar.py +607 -107
- agno/tools/googlesheets.py +377 -0
- agno/tools/hackernews.py +20 -12
- agno/tools/jina.py +24 -14
- agno/tools/jira.py +48 -19
- agno/tools/knowledge.py +218 -0
- agno/tools/linear.py +82 -43
- agno/tools/linkup.py +58 -0
- agno/tools/local_file_system.py +15 -7
- agno/tools/lumalab.py +41 -26
- agno/tools/mcp/__init__.py +10 -0
- agno/tools/mcp/mcp.py +331 -0
- agno/tools/mcp/multi_mcp.py +347 -0
- agno/tools/mcp/params.py +24 -0
- agno/tools/mcp_toolbox.py +284 -0
- agno/tools/mem0.py +193 -0
- agno/tools/memory.py +419 -0
- agno/tools/mlx_transcribe.py +11 -9
- agno/tools/models/azure_openai.py +190 -0
- agno/tools/models/gemini.py +203 -0
- agno/tools/models/groq.py +158 -0
- agno/tools/models/morph.py +186 -0
- agno/tools/models/nebius.py +124 -0
- agno/tools/models_labs.py +163 -82
- agno/tools/moviepy_video.py +18 -13
- agno/tools/nano_banana.py +151 -0
- agno/tools/neo4j.py +134 -0
- agno/tools/newspaper.py +15 -4
- agno/tools/newspaper4k.py +19 -6
- agno/tools/notion.py +204 -0
- agno/tools/openai.py +181 -17
- agno/tools/openbb.py +27 -20
- agno/tools/opencv.py +321 -0
- agno/tools/openweather.py +233 -0
- agno/tools/oxylabs.py +385 -0
- agno/tools/pandas.py +25 -15
- agno/tools/parallel.py +314 -0
- agno/tools/postgres.py +238 -185
- agno/tools/pubmed.py +125 -13
- agno/tools/python.py +48 -35
- agno/tools/reasoning.py +283 -0
- agno/tools/reddit.py +207 -29
- agno/tools/redshift.py +406 -0
- agno/tools/replicate.py +69 -26
- agno/tools/resend.py +11 -6
- agno/tools/scrapegraph.py +179 -19
- agno/tools/searxng.py +23 -31
- agno/tools/serpapi.py +15 -10
- agno/tools/serper.py +255 -0
- agno/tools/shell.py +23 -12
- agno/tools/shopify.py +1519 -0
- agno/tools/slack.py +56 -14
- agno/tools/sleep.py +8 -6
- agno/tools/spider.py +35 -11
- agno/tools/spotify.py +919 -0
- agno/tools/sql.py +34 -19
- agno/tools/tavily.py +158 -8
- agno/tools/telegram.py +18 -8
- agno/tools/todoist.py +218 -0
- agno/tools/toolkit.py +134 -9
- agno/tools/trafilatura.py +388 -0
- agno/tools/trello.py +25 -28
- agno/tools/twilio.py +18 -9
- agno/tools/user_control_flow.py +78 -0
- agno/tools/valyu.py +228 -0
- agno/tools/visualization.py +467 -0
- agno/tools/webbrowser.py +28 -0
- agno/tools/webex.py +76 -0
- agno/tools/website.py +23 -19
- agno/tools/webtools.py +45 -0
- agno/tools/whatsapp.py +286 -0
- agno/tools/wikipedia.py +28 -19
- agno/tools/workflow.py +285 -0
- agno/tools/{twitter.py → x.py} +142 -46
- agno/tools/yfinance.py +41 -39
- agno/tools/youtube.py +34 -17
- agno/tools/zendesk.py +15 -5
- agno/tools/zep.py +454 -0
- agno/tools/zoom.py +86 -37
- agno/tracing/__init__.py +12 -0
- agno/tracing/exporter.py +157 -0
- agno/tracing/schemas.py +276 -0
- agno/tracing/setup.py +111 -0
- agno/utils/agent.py +938 -0
- agno/utils/audio.py +37 -1
- agno/utils/certs.py +27 -0
- agno/utils/code_execution.py +11 -0
- agno/utils/common.py +103 -20
- agno/utils/cryptography.py +22 -0
- agno/utils/dttm.py +33 -0
- agno/utils/events.py +700 -0
- agno/utils/functions.py +107 -37
- agno/utils/gemini.py +426 -0
- agno/utils/hooks.py +171 -0
- agno/utils/http.py +185 -0
- agno/utils/json_schema.py +159 -37
- agno/utils/knowledge.py +36 -0
- agno/utils/location.py +19 -0
- agno/utils/log.py +221 -8
- agno/utils/mcp.py +214 -0
- agno/utils/media.py +335 -14
- agno/utils/merge_dict.py +22 -1
- agno/utils/message.py +77 -2
- agno/utils/models/ai_foundry.py +50 -0
- agno/utils/models/claude.py +373 -0
- agno/utils/models/cohere.py +94 -0
- agno/utils/models/llama.py +85 -0
- agno/utils/models/mistral.py +100 -0
- agno/utils/models/openai_responses.py +140 -0
- agno/utils/models/schema_utils.py +153 -0
- agno/utils/models/watsonx.py +41 -0
- agno/utils/openai.py +257 -0
- agno/utils/pickle.py +1 -1
- agno/utils/pprint.py +124 -8
- agno/utils/print_response/agent.py +930 -0
- agno/utils/print_response/team.py +1914 -0
- agno/utils/print_response/workflow.py +1668 -0
- agno/utils/prompts.py +111 -0
- agno/utils/reasoning.py +108 -0
- agno/utils/response.py +163 -0
- agno/utils/serialize.py +32 -0
- agno/utils/shell.py +4 -4
- agno/utils/streamlit.py +487 -0
- agno/utils/string.py +204 -51
- agno/utils/team.py +139 -0
- agno/utils/timer.py +9 -2
- agno/utils/tokens.py +657 -0
- agno/utils/tools.py +19 -1
- agno/utils/whatsapp.py +305 -0
- agno/utils/yaml_io.py +3 -3
- agno/vectordb/__init__.py +2 -0
- agno/vectordb/base.py +87 -9
- agno/vectordb/cassandra/__init__.py +5 -1
- agno/vectordb/cassandra/cassandra.py +383 -27
- agno/vectordb/chroma/__init__.py +4 -0
- agno/vectordb/chroma/chromadb.py +748 -83
- agno/vectordb/clickhouse/__init__.py +7 -1
- agno/vectordb/clickhouse/clickhousedb.py +554 -53
- agno/vectordb/couchbase/__init__.py +3 -0
- agno/vectordb/couchbase/couchbase.py +1446 -0
- agno/vectordb/lancedb/__init__.py +5 -0
- agno/vectordb/lancedb/lance_db.py +730 -98
- agno/vectordb/langchaindb/__init__.py +5 -0
- agno/vectordb/langchaindb/langchaindb.py +163 -0
- agno/vectordb/lightrag/__init__.py +5 -0
- agno/vectordb/lightrag/lightrag.py +388 -0
- agno/vectordb/llamaindex/__init__.py +3 -0
- agno/vectordb/llamaindex/llamaindexdb.py +166 -0
- agno/vectordb/milvus/__init__.py +3 -0
- agno/vectordb/milvus/milvus.py +966 -78
- agno/vectordb/mongodb/__init__.py +9 -1
- agno/vectordb/mongodb/mongodb.py +1175 -172
- agno/vectordb/pgvector/__init__.py +8 -0
- agno/vectordb/pgvector/pgvector.py +599 -115
- agno/vectordb/pineconedb/__init__.py +5 -1
- agno/vectordb/pineconedb/pineconedb.py +406 -43
- agno/vectordb/qdrant/__init__.py +4 -0
- agno/vectordb/qdrant/qdrant.py +914 -61
- agno/vectordb/redis/__init__.py +9 -0
- agno/vectordb/redis/redisdb.py +682 -0
- agno/vectordb/singlestore/__init__.py +8 -1
- agno/vectordb/singlestore/singlestore.py +771 -0
- agno/vectordb/surrealdb/__init__.py +3 -0
- agno/vectordb/surrealdb/surrealdb.py +663 -0
- agno/vectordb/upstashdb/__init__.py +5 -0
- agno/vectordb/upstashdb/upstashdb.py +718 -0
- agno/vectordb/weaviate/__init__.py +8 -0
- agno/vectordb/weaviate/index.py +15 -0
- agno/vectordb/weaviate/weaviate.py +1009 -0
- agno/workflow/__init__.py +23 -1
- agno/workflow/agent.py +299 -0
- agno/workflow/condition.py +759 -0
- agno/workflow/loop.py +756 -0
- agno/workflow/parallel.py +853 -0
- agno/workflow/router.py +723 -0
- agno/workflow/step.py +1564 -0
- agno/workflow/steps.py +613 -0
- agno/workflow/types.py +556 -0
- agno/workflow/workflow.py +4327 -514
- agno-2.3.13.dist-info/METADATA +639 -0
- agno-2.3.13.dist-info/RECORD +613 -0
- {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/WHEEL +1 -1
- agno-2.3.13.dist-info/licenses/LICENSE +201 -0
- agno/api/playground.py +0 -91
- agno/api/schemas/playground.py +0 -22
- agno/api/schemas/user.py +0 -22
- agno/api/schemas/workspace.py +0 -46
- agno/api/user.py +0 -160
- agno/api/workspace.py +0 -151
- agno/cli/auth_server.py +0 -118
- agno/cli/config.py +0 -275
- agno/cli/console.py +0 -88
- agno/cli/credentials.py +0 -23
- agno/cli/entrypoint.py +0 -571
- agno/cli/operator.py +0 -355
- agno/cli/settings.py +0 -85
- agno/cli/ws/ws_cli.py +0 -817
- agno/constants.py +0 -13
- agno/document/__init__.py +0 -1
- agno/document/chunking/semantic.py +0 -47
- agno/document/chunking/strategy.py +0 -31
- agno/document/reader/__init__.py +0 -1
- agno/document/reader/arxiv_reader.py +0 -41
- agno/document/reader/base.py +0 -22
- agno/document/reader/csv_reader.py +0 -84
- agno/document/reader/docx_reader.py +0 -46
- agno/document/reader/firecrawl_reader.py +0 -99
- agno/document/reader/json_reader.py +0 -43
- agno/document/reader/pdf_reader.py +0 -219
- agno/document/reader/s3/pdf_reader.py +0 -46
- agno/document/reader/s3/text_reader.py +0 -51
- agno/document/reader/text_reader.py +0 -41
- agno/document/reader/website_reader.py +0 -175
- agno/document/reader/youtube_reader.py +0 -50
- agno/embedder/__init__.py +0 -1
- agno/embedder/azure_openai.py +0 -86
- agno/embedder/cohere.py +0 -72
- agno/embedder/fastembed.py +0 -37
- agno/embedder/google.py +0 -73
- agno/embedder/huggingface.py +0 -54
- agno/embedder/mistral.py +0 -80
- agno/embedder/ollama.py +0 -57
- agno/embedder/openai.py +0 -74
- agno/embedder/sentence_transformer.py +0 -38
- agno/embedder/voyageai.py +0 -64
- agno/eval/perf.py +0 -201
- agno/file/__init__.py +0 -1
- agno/file/file.py +0 -16
- agno/file/local/csv.py +0 -32
- agno/file/local/txt.py +0 -19
- agno/infra/app.py +0 -240
- agno/infra/base.py +0 -144
- agno/infra/context.py +0 -20
- agno/infra/db_app.py +0 -52
- agno/infra/resource.py +0 -205
- agno/infra/resources.py +0 -55
- agno/knowledge/agent.py +0 -230
- agno/knowledge/arxiv.py +0 -22
- agno/knowledge/combined.py +0 -22
- agno/knowledge/csv.py +0 -28
- agno/knowledge/csv_url.py +0 -19
- agno/knowledge/document.py +0 -20
- agno/knowledge/docx.py +0 -30
- agno/knowledge/json.py +0 -28
- agno/knowledge/langchain.py +0 -71
- agno/knowledge/llamaindex.py +0 -66
- agno/knowledge/pdf.py +0 -28
- agno/knowledge/pdf_url.py +0 -26
- agno/knowledge/s3/base.py +0 -60
- agno/knowledge/s3/pdf.py +0 -21
- agno/knowledge/s3/text.py +0 -23
- agno/knowledge/text.py +0 -30
- agno/knowledge/website.py +0 -88
- agno/knowledge/wikipedia.py +0 -31
- agno/knowledge/youtube.py +0 -22
- agno/memory/agent.py +0 -392
- agno/memory/classifier.py +0 -104
- agno/memory/db/__init__.py +0 -1
- agno/memory/db/base.py +0 -42
- agno/memory/db/mongodb.py +0 -189
- agno/memory/db/postgres.py +0 -203
- agno/memory/db/sqlite.py +0 -193
- agno/memory/memory.py +0 -15
- agno/memory/row.py +0 -36
- agno/memory/summarizer.py +0 -192
- agno/memory/summary.py +0 -19
- agno/memory/workflow.py +0 -38
- agno/models/google/gemini_openai.py +0 -26
- agno/models/ollama/hermes.py +0 -221
- agno/models/ollama/tools.py +0 -362
- agno/models/vertexai/gemini.py +0 -595
- agno/playground/__init__.py +0 -3
- agno/playground/async_router.py +0 -421
- agno/playground/deploy.py +0 -249
- agno/playground/operator.py +0 -92
- agno/playground/playground.py +0 -91
- agno/playground/schemas.py +0 -76
- agno/playground/serve.py +0 -55
- agno/playground/sync_router.py +0 -405
- agno/reasoning/agent.py +0 -68
- agno/run/response.py +0 -112
- agno/storage/agent/__init__.py +0 -0
- agno/storage/agent/base.py +0 -38
- agno/storage/agent/dynamodb.py +0 -350
- agno/storage/agent/json.py +0 -92
- agno/storage/agent/mongodb.py +0 -228
- agno/storage/agent/postgres.py +0 -367
- agno/storage/agent/session.py +0 -79
- agno/storage/agent/singlestore.py +0 -303
- agno/storage/agent/sqlite.py +0 -357
- agno/storage/agent/yaml.py +0 -93
- agno/storage/workflow/__init__.py +0 -0
- agno/storage/workflow/base.py +0 -40
- agno/storage/workflow/mongodb.py +0 -233
- agno/storage/workflow/postgres.py +0 -366
- agno/storage/workflow/session.py +0 -60
- agno/storage/workflow/sqlite.py +0 -359
- agno/tools/googlesearch.py +0 -88
- agno/utils/defaults.py +0 -57
- agno/utils/filesystem.py +0 -39
- agno/utils/git.py +0 -52
- agno/utils/json_io.py +0 -30
- agno/utils/load_env.py +0 -19
- agno/utils/py_io.py +0 -19
- agno/utils/pyproject.py +0 -18
- agno/utils/resource_filter.py +0 -31
- agno/vectordb/singlestore/s2vectordb.py +0 -390
- agno/vectordb/singlestore/s2vectordb2.py +0 -355
- agno/workspace/__init__.py +0 -0
- agno/workspace/config.py +0 -325
- agno/workspace/enums.py +0 -6
- agno/workspace/helpers.py +0 -48
- agno/workspace/operator.py +0 -758
- agno/workspace/settings.py +0 -63
- agno-0.1.2.dist-info/LICENSE +0 -375
- agno-0.1.2.dist-info/METADATA +0 -502
- agno-0.1.2.dist-info/RECORD +0 -352
- agno-0.1.2.dist-info/entry_points.txt +0 -3
- /agno/{cli → db/migrations}/__init__.py +0 -0
- /agno/{cli/ws → db/migrations/versions}/__init__.py +0 -0
- /agno/{document/chunking/__init__.py → db/schemas/metrics.py} +0 -0
- /agno/{document/reader/s3 → integrations}/__init__.py +0 -0
- /agno/{file/local → knowledge/chunking}/__init__.py +0 -0
- /agno/{infra → knowledge/remote_content}/__init__.py +0 -0
- /agno/{knowledge/s3 → tools/models}/__init__.py +0 -0
- /agno/{reranker → utils/models}/__init__.py +0 -0
- /agno/{storage → utils/print_response}/__init__.py +0 -0
- {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,930 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import warnings
|
|
3
|
+
from collections.abc import Set
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Union, cast, get_args
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
from rich.console import Group
|
|
8
|
+
from rich.json import JSON
|
|
9
|
+
from rich.live import Live
|
|
10
|
+
from rich.markdown import Markdown
|
|
11
|
+
from rich.status import Status
|
|
12
|
+
from rich.text import Text
|
|
13
|
+
|
|
14
|
+
from agno.filters import FilterExpr
|
|
15
|
+
from agno.media import Audio, File, Image, Video
|
|
16
|
+
from agno.models.message import Message
|
|
17
|
+
from agno.reasoning.step import ReasoningStep
|
|
18
|
+
from agno.run.agent import RunEvent, RunOutput, RunOutputEvent, RunPausedEvent
|
|
19
|
+
from agno.utils.log import log_warning
|
|
20
|
+
from agno.utils.message import get_text_from_message
|
|
21
|
+
from agno.utils.response import create_panel, create_paused_run_output_panel, escape_markdown_tags, format_tool_calls
|
|
22
|
+
from agno.utils.timer import Timer
|
|
23
|
+
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from agno.agent.agent import Agent
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def print_response_stream(
|
|
29
|
+
agent: "Agent",
|
|
30
|
+
input: Union[List, Dict, str, Message, BaseModel, List[Message]],
|
|
31
|
+
session_id: Optional[str] = None,
|
|
32
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
33
|
+
user_id: Optional[str] = None,
|
|
34
|
+
run_id: Optional[str] = None,
|
|
35
|
+
audio: Optional[Sequence[Audio]] = None,
|
|
36
|
+
images: Optional[Sequence[Image]] = None,
|
|
37
|
+
videos: Optional[Sequence[Video]] = None,
|
|
38
|
+
files: Optional[Sequence[File]] = None,
|
|
39
|
+
knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
|
|
40
|
+
debug_mode: Optional[bool] = None,
|
|
41
|
+
markdown: bool = False,
|
|
42
|
+
show_message: bool = True,
|
|
43
|
+
show_reasoning: bool = True,
|
|
44
|
+
show_full_reasoning: bool = False,
|
|
45
|
+
tags_to_include_in_markdown: Set[str] = {"think", "thinking"},
|
|
46
|
+
console: Optional[Any] = None,
|
|
47
|
+
add_history_to_context: Optional[bool] = None,
|
|
48
|
+
dependencies: Optional[Dict[str, Any]] = None,
|
|
49
|
+
add_dependencies_to_context: Optional[bool] = None,
|
|
50
|
+
add_session_state_to_context: Optional[bool] = None,
|
|
51
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
52
|
+
**kwargs: Any,
|
|
53
|
+
):
|
|
54
|
+
_response_content: str = ""
|
|
55
|
+
_response_reasoning_content: str = ""
|
|
56
|
+
response_content_batch: Union[str, JSON, Markdown] = ""
|
|
57
|
+
reasoning_steps: List[ReasoningStep] = []
|
|
58
|
+
accumulated_tool_calls: List = []
|
|
59
|
+
|
|
60
|
+
with Live(console=console) as live_log:
|
|
61
|
+
status = Status("Thinking...", spinner="aesthetic", speed=0.4, refresh_per_second=10)
|
|
62
|
+
live_log.update(status)
|
|
63
|
+
response_timer = Timer()
|
|
64
|
+
response_timer.start()
|
|
65
|
+
# Flag which indicates if the panels should be rendered
|
|
66
|
+
render = False
|
|
67
|
+
# Panels to be rendered
|
|
68
|
+
panels = [status]
|
|
69
|
+
# First render the message panel if the message is not None
|
|
70
|
+
if input and show_message:
|
|
71
|
+
render = True
|
|
72
|
+
# Convert message to a panel
|
|
73
|
+
message_content = get_text_from_message(input)
|
|
74
|
+
message_panel = create_panel(
|
|
75
|
+
content=Text(message_content, style="green"),
|
|
76
|
+
title="Message",
|
|
77
|
+
border_style="cyan",
|
|
78
|
+
)
|
|
79
|
+
panels.append(message_panel)
|
|
80
|
+
if render:
|
|
81
|
+
live_log.update(Group(*panels))
|
|
82
|
+
|
|
83
|
+
input_content = get_text_from_message(input)
|
|
84
|
+
|
|
85
|
+
for response_event in agent.run(
|
|
86
|
+
input=input,
|
|
87
|
+
session_id=session_id,
|
|
88
|
+
session_state=session_state,
|
|
89
|
+
user_id=user_id,
|
|
90
|
+
run_id=run_id,
|
|
91
|
+
audio=audio,
|
|
92
|
+
images=images,
|
|
93
|
+
videos=videos,
|
|
94
|
+
files=files,
|
|
95
|
+
stream=True,
|
|
96
|
+
knowledge_filters=knowledge_filters,
|
|
97
|
+
debug_mode=debug_mode,
|
|
98
|
+
add_history_to_context=add_history_to_context,
|
|
99
|
+
add_dependencies_to_context=add_dependencies_to_context,
|
|
100
|
+
add_session_state_to_context=add_session_state_to_context,
|
|
101
|
+
dependencies=dependencies,
|
|
102
|
+
metadata=metadata,
|
|
103
|
+
**kwargs,
|
|
104
|
+
):
|
|
105
|
+
if isinstance(response_event, tuple(get_args(RunOutputEvent))):
|
|
106
|
+
if response_event.is_paused: # type: ignore
|
|
107
|
+
response_event = cast(RunPausedEvent, response_event) # type: ignore
|
|
108
|
+
response_panel = create_paused_run_output_panel(response_event) # type: ignore
|
|
109
|
+
panels.append(response_panel)
|
|
110
|
+
live_log.update(Group(*panels))
|
|
111
|
+
return
|
|
112
|
+
|
|
113
|
+
if response_event.event == RunEvent.pre_hook_completed: # type: ignore
|
|
114
|
+
if response_event.run_input is not None: # type: ignore
|
|
115
|
+
input_content = get_text_from_message(response_event.run_input.input_content) # type: ignore
|
|
116
|
+
|
|
117
|
+
if (
|
|
118
|
+
response_event.event == RunEvent.tool_call_started # type: ignore
|
|
119
|
+
and hasattr(response_event, "tool")
|
|
120
|
+
and response_event.tool is not None
|
|
121
|
+
):
|
|
122
|
+
accumulated_tool_calls.append(response_event.tool)
|
|
123
|
+
|
|
124
|
+
if response_event.event == RunEvent.run_content: # type: ignore
|
|
125
|
+
if hasattr(response_event, "content"):
|
|
126
|
+
if isinstance(response_event.content, str):
|
|
127
|
+
# Don't accumulate text content, parser_model will replace it
|
|
128
|
+
if not (agent.parser_model is not None and agent.output_schema is not None):
|
|
129
|
+
_response_content += response_event.content
|
|
130
|
+
elif agent.output_schema is not None and isinstance(response_event.content, BaseModel):
|
|
131
|
+
try:
|
|
132
|
+
response_content_batch = JSON( # type: ignore
|
|
133
|
+
response_event.content.model_dump_json(exclude_none=True), indent=2
|
|
134
|
+
)
|
|
135
|
+
except Exception as e:
|
|
136
|
+
log_warning(f"Failed to convert response to JSON: {e}")
|
|
137
|
+
else:
|
|
138
|
+
try:
|
|
139
|
+
response_content_batch = JSON(json.dumps(response_event.content), indent=4)
|
|
140
|
+
except Exception as e:
|
|
141
|
+
log_warning(f"Failed to convert response to JSON: {e}")
|
|
142
|
+
if hasattr(response_event, "reasoning_content") and response_event.reasoning_content is not None: # type: ignore
|
|
143
|
+
_response_reasoning_content += response_event.reasoning_content # type: ignore
|
|
144
|
+
if hasattr(response_event, "reasoning_steps") and response_event.reasoning_steps is not None: # type: ignore
|
|
145
|
+
reasoning_steps = response_event.reasoning_steps # type: ignore
|
|
146
|
+
|
|
147
|
+
# Escape special tags before markdown conversion
|
|
148
|
+
if markdown:
|
|
149
|
+
escaped_content = escape_markdown_tags(_response_content, tags_to_include_in_markdown) # type: ignore
|
|
150
|
+
response_content_batch = Markdown(escaped_content)
|
|
151
|
+
|
|
152
|
+
response_content_stream: str = _response_content
|
|
153
|
+
|
|
154
|
+
# Check if we have any response content to display
|
|
155
|
+
if response_content_stream and not markdown:
|
|
156
|
+
response_content = response_content_stream
|
|
157
|
+
else:
|
|
158
|
+
response_content = response_content_batch # type: ignore
|
|
159
|
+
|
|
160
|
+
# Sanitize empty Markdown content
|
|
161
|
+
if isinstance(response_content, Markdown):
|
|
162
|
+
if not (response_content.markup and response_content.markup.strip()):
|
|
163
|
+
response_content = None # type: ignore
|
|
164
|
+
|
|
165
|
+
panels = [status]
|
|
166
|
+
if show_message:
|
|
167
|
+
# Convert message to a panel
|
|
168
|
+
message_panel = create_panel(
|
|
169
|
+
content=Text(input_content, style="green"),
|
|
170
|
+
title="Message",
|
|
171
|
+
border_style="cyan",
|
|
172
|
+
)
|
|
173
|
+
panels.append(message_panel)
|
|
174
|
+
|
|
175
|
+
additional_panels = build_panels_stream(
|
|
176
|
+
response_content=response_content,
|
|
177
|
+
response_event=response_event, # type: ignore
|
|
178
|
+
response_timer=response_timer,
|
|
179
|
+
response_reasoning_content_buffer=_response_reasoning_content,
|
|
180
|
+
reasoning_steps=reasoning_steps,
|
|
181
|
+
show_reasoning=show_reasoning,
|
|
182
|
+
show_full_reasoning=show_full_reasoning,
|
|
183
|
+
accumulated_tool_calls=accumulated_tool_calls,
|
|
184
|
+
compression_manager=agent.compression_manager,
|
|
185
|
+
)
|
|
186
|
+
panels.extend(additional_panels)
|
|
187
|
+
if panels:
|
|
188
|
+
live_log.update(Group(*panels))
|
|
189
|
+
|
|
190
|
+
if agent.memory_manager is not None and agent.memory_manager.memories_updated:
|
|
191
|
+
memory_panel = create_panel(
|
|
192
|
+
content=Text("Memories updated"),
|
|
193
|
+
title="Memories",
|
|
194
|
+
border_style="green",
|
|
195
|
+
)
|
|
196
|
+
panels.append(memory_panel)
|
|
197
|
+
live_log.update(Group(*panels))
|
|
198
|
+
agent.memory_manager.memories_updated = False
|
|
199
|
+
|
|
200
|
+
if agent.session_summary_manager is not None and agent.session_summary_manager.summaries_updated:
|
|
201
|
+
summary_panel = create_panel(
|
|
202
|
+
content=Text("Session summary updated"),
|
|
203
|
+
title="Session Summary",
|
|
204
|
+
border_style="green",
|
|
205
|
+
)
|
|
206
|
+
panels.append(summary_panel)
|
|
207
|
+
live_log.update(Group(*panels))
|
|
208
|
+
agent.session_summary_manager.summaries_updated = False
|
|
209
|
+
|
|
210
|
+
# Clear compression stats after final display
|
|
211
|
+
if agent.compression_manager is not None:
|
|
212
|
+
agent.compression_manager.stats.clear()
|
|
213
|
+
|
|
214
|
+
response_timer.stop()
|
|
215
|
+
|
|
216
|
+
# Final update to remove the "Thinking..." status
|
|
217
|
+
panels = [p for p in panels if not isinstance(p, Status)]
|
|
218
|
+
live_log.update(Group(*panels))
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
async def aprint_response_stream(
|
|
222
|
+
agent: "Agent",
|
|
223
|
+
input: Union[List, Dict, str, Message, BaseModel, List[Message]],
|
|
224
|
+
session_id: Optional[str] = None,
|
|
225
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
226
|
+
user_id: Optional[str] = None,
|
|
227
|
+
run_id: Optional[str] = None,
|
|
228
|
+
audio: Optional[Sequence[Audio]] = None,
|
|
229
|
+
images: Optional[Sequence[Image]] = None,
|
|
230
|
+
videos: Optional[Sequence[Video]] = None,
|
|
231
|
+
files: Optional[Sequence[File]] = None,
|
|
232
|
+
knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
|
|
233
|
+
debug_mode: Optional[bool] = None,
|
|
234
|
+
markdown: bool = False,
|
|
235
|
+
show_message: bool = True,
|
|
236
|
+
show_reasoning: bool = True,
|
|
237
|
+
show_full_reasoning: bool = False,
|
|
238
|
+
tags_to_include_in_markdown: Set[str] = {"think", "thinking"},
|
|
239
|
+
console: Optional[Any] = None,
|
|
240
|
+
add_history_to_context: Optional[bool] = None,
|
|
241
|
+
dependencies: Optional[Dict[str, Any]] = None,
|
|
242
|
+
add_dependencies_to_context: Optional[bool] = None,
|
|
243
|
+
add_session_state_to_context: Optional[bool] = None,
|
|
244
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
245
|
+
**kwargs: Any,
|
|
246
|
+
):
|
|
247
|
+
_response_content: str = ""
|
|
248
|
+
_response_reasoning_content: str = ""
|
|
249
|
+
reasoning_steps: List[ReasoningStep] = []
|
|
250
|
+
response_content_batch: Union[str, JSON, Markdown] = ""
|
|
251
|
+
accumulated_tool_calls: List = []
|
|
252
|
+
|
|
253
|
+
with Live(console=console) as live_log:
|
|
254
|
+
status = Status("Thinking...", spinner="aesthetic", speed=0.4, refresh_per_second=10)
|
|
255
|
+
live_log.update(status)
|
|
256
|
+
response_timer = Timer()
|
|
257
|
+
response_timer.start()
|
|
258
|
+
# Flag which indicates if the panels should be rendered
|
|
259
|
+
render = False
|
|
260
|
+
# Panels to be rendered
|
|
261
|
+
panels = [status]
|
|
262
|
+
# First render the message panel if the message is not None
|
|
263
|
+
if input and show_message:
|
|
264
|
+
render = True
|
|
265
|
+
# Convert message to a panel
|
|
266
|
+
message_content = get_text_from_message(input)
|
|
267
|
+
message_panel = create_panel(
|
|
268
|
+
content=Text(message_content, style="green"),
|
|
269
|
+
title="Message",
|
|
270
|
+
border_style="cyan",
|
|
271
|
+
)
|
|
272
|
+
panels.append(message_panel)
|
|
273
|
+
if render:
|
|
274
|
+
live_log.update(Group(*panels))
|
|
275
|
+
|
|
276
|
+
result = agent.arun(
|
|
277
|
+
input=input,
|
|
278
|
+
session_id=session_id,
|
|
279
|
+
session_state=session_state,
|
|
280
|
+
user_id=user_id,
|
|
281
|
+
run_id=run_id,
|
|
282
|
+
audio=audio,
|
|
283
|
+
images=images,
|
|
284
|
+
videos=videos,
|
|
285
|
+
files=files,
|
|
286
|
+
stream=True,
|
|
287
|
+
knowledge_filters=knowledge_filters,
|
|
288
|
+
debug_mode=debug_mode,
|
|
289
|
+
add_history_to_context=add_history_to_context,
|
|
290
|
+
add_dependencies_to_context=add_dependencies_to_context,
|
|
291
|
+
add_session_state_to_context=add_session_state_to_context,
|
|
292
|
+
dependencies=dependencies,
|
|
293
|
+
metadata=metadata,
|
|
294
|
+
**kwargs,
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
input_content = get_text_from_message(input)
|
|
298
|
+
|
|
299
|
+
async for resp in result: # type: ignore
|
|
300
|
+
if isinstance(resp, tuple(get_args(RunOutputEvent))):
|
|
301
|
+
if resp.is_paused:
|
|
302
|
+
response_panel = create_paused_run_output_panel(resp) # type: ignore
|
|
303
|
+
panels.append(response_panel)
|
|
304
|
+
live_log.update(Group(*panels))
|
|
305
|
+
break
|
|
306
|
+
|
|
307
|
+
if (
|
|
308
|
+
resp.event == RunEvent.tool_call_started # type: ignore
|
|
309
|
+
and hasattr(resp, "tool")
|
|
310
|
+
and resp.tool is not None
|
|
311
|
+
):
|
|
312
|
+
accumulated_tool_calls.append(resp.tool)
|
|
313
|
+
|
|
314
|
+
if resp.event == RunEvent.pre_hook_completed: # type: ignore
|
|
315
|
+
if resp.run_input is not None: # type: ignore
|
|
316
|
+
input_content = get_text_from_message(resp.run_input.input_content) # type: ignore
|
|
317
|
+
|
|
318
|
+
if resp.event == RunEvent.run_content: # type: ignore
|
|
319
|
+
if isinstance(resp.content, str):
|
|
320
|
+
# Don't accumulate text content, parser_model will replace it
|
|
321
|
+
if not (agent.parser_model is not None and agent.output_schema is not None):
|
|
322
|
+
_response_content += resp.content
|
|
323
|
+
elif agent.output_schema is not None and isinstance(resp.content, BaseModel):
|
|
324
|
+
try:
|
|
325
|
+
response_content_batch = JSON(resp.content.model_dump_json(exclude_none=True), indent=2) # type: ignore
|
|
326
|
+
except Exception as e:
|
|
327
|
+
log_warning(f"Failed to convert response to JSON: {e}")
|
|
328
|
+
else:
|
|
329
|
+
try:
|
|
330
|
+
response_content_batch = JSON(json.dumps(resp.content), indent=4)
|
|
331
|
+
except Exception as e:
|
|
332
|
+
log_warning(f"Failed to convert response to JSON: {e}")
|
|
333
|
+
if resp.reasoning_content is not None: # type: ignore
|
|
334
|
+
_response_reasoning_content += resp.reasoning_content # type: ignore
|
|
335
|
+
|
|
336
|
+
if hasattr(resp, "reasoning_steps") and resp.reasoning_steps is not None: # type: ignore
|
|
337
|
+
reasoning_steps = resp.reasoning_steps # type: ignore
|
|
338
|
+
|
|
339
|
+
response_content_stream: str = _response_content
|
|
340
|
+
|
|
341
|
+
# Escape special tags before markdown conversion
|
|
342
|
+
if markdown:
|
|
343
|
+
escaped_content = escape_markdown_tags(_response_content, tags_to_include_in_markdown) # type: ignore
|
|
344
|
+
response_content_batch = Markdown(escaped_content)
|
|
345
|
+
|
|
346
|
+
# Check if we have any response content to display
|
|
347
|
+
if response_content_stream and not markdown:
|
|
348
|
+
response_content = response_content_stream
|
|
349
|
+
else:
|
|
350
|
+
response_content = response_content_batch # type: ignore
|
|
351
|
+
|
|
352
|
+
# Sanitize empty Markdown content
|
|
353
|
+
if isinstance(response_content, Markdown):
|
|
354
|
+
if not (response_content.markup and response_content.markup.strip()):
|
|
355
|
+
response_content = None # type: ignore
|
|
356
|
+
|
|
357
|
+
panels = [status]
|
|
358
|
+
|
|
359
|
+
if input_content and show_message:
|
|
360
|
+
render = True
|
|
361
|
+
# Convert message to a panel
|
|
362
|
+
message_panel = create_panel(
|
|
363
|
+
content=Text(input_content, style="green"),
|
|
364
|
+
title="Message",
|
|
365
|
+
border_style="cyan",
|
|
366
|
+
)
|
|
367
|
+
panels.append(message_panel)
|
|
368
|
+
|
|
369
|
+
additional_panels = build_panels_stream(
|
|
370
|
+
response_content=response_content,
|
|
371
|
+
response_event=resp, # type: ignore
|
|
372
|
+
response_timer=response_timer,
|
|
373
|
+
response_reasoning_content_buffer=_response_reasoning_content,
|
|
374
|
+
reasoning_steps=reasoning_steps,
|
|
375
|
+
show_reasoning=show_reasoning,
|
|
376
|
+
show_full_reasoning=show_full_reasoning,
|
|
377
|
+
accumulated_tool_calls=accumulated_tool_calls,
|
|
378
|
+
compression_manager=agent.compression_manager,
|
|
379
|
+
)
|
|
380
|
+
panels.extend(additional_panels)
|
|
381
|
+
if panels:
|
|
382
|
+
live_log.update(Group(*panels))
|
|
383
|
+
|
|
384
|
+
if agent.memory_manager is not None and agent.memory_manager.memories_updated:
|
|
385
|
+
memory_panel = create_panel(
|
|
386
|
+
content=Text("Memories updated"),
|
|
387
|
+
title="Memories",
|
|
388
|
+
border_style="green",
|
|
389
|
+
)
|
|
390
|
+
panels.append(memory_panel)
|
|
391
|
+
live_log.update(Group(*panels))
|
|
392
|
+
agent.memory_manager.memories_updated = False
|
|
393
|
+
|
|
394
|
+
if agent.session_summary_manager is not None and agent.session_summary_manager.summaries_updated:
|
|
395
|
+
summary_panel = create_panel(
|
|
396
|
+
content=Text("Session summary updated"),
|
|
397
|
+
title="Session Summary",
|
|
398
|
+
border_style="green",
|
|
399
|
+
)
|
|
400
|
+
panels.append(summary_panel)
|
|
401
|
+
live_log.update(Group(*panels))
|
|
402
|
+
agent.session_summary_manager.summaries_updated = False
|
|
403
|
+
|
|
404
|
+
# Clear compression stats after final display
|
|
405
|
+
if agent.compression_manager is not None:
|
|
406
|
+
agent.compression_manager.stats.clear()
|
|
407
|
+
|
|
408
|
+
response_timer.stop()
|
|
409
|
+
|
|
410
|
+
# Final update to remove the "Thinking..." status
|
|
411
|
+
panels = [p for p in panels if not isinstance(p, Status)]
|
|
412
|
+
live_log.update(Group(*panels))
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
def build_panels_stream(
|
|
416
|
+
response_content: Union[str, JSON, Markdown],
|
|
417
|
+
response_event: RunOutputEvent,
|
|
418
|
+
response_timer: Timer,
|
|
419
|
+
response_reasoning_content_buffer: str,
|
|
420
|
+
reasoning_steps: List[ReasoningStep],
|
|
421
|
+
show_reasoning: bool = True,
|
|
422
|
+
show_full_reasoning: bool = False,
|
|
423
|
+
accumulated_tool_calls: Optional[List] = None,
|
|
424
|
+
compression_manager: Optional[Any] = None,
|
|
425
|
+
):
|
|
426
|
+
panels = []
|
|
427
|
+
|
|
428
|
+
if len(reasoning_steps) > 0 and show_reasoning:
|
|
429
|
+
# Create panels for reasoning steps
|
|
430
|
+
for i, step in enumerate(reasoning_steps, 1):
|
|
431
|
+
# Build step content
|
|
432
|
+
step_content = Text.assemble()
|
|
433
|
+
if step.title is not None:
|
|
434
|
+
step_content.append(f"{step.title}\n", "bold")
|
|
435
|
+
if step.action is not None:
|
|
436
|
+
step_content.append(Text.from_markup(f"[bold]Action:[/bold] {step.action}\n", style="dim"))
|
|
437
|
+
if step.result is not None:
|
|
438
|
+
step_content.append(Text.from_markup(step.result, style="dim"))
|
|
439
|
+
|
|
440
|
+
if show_full_reasoning:
|
|
441
|
+
# Add detailed reasoning information if available
|
|
442
|
+
if step.reasoning is not None:
|
|
443
|
+
step_content.append(Text.from_markup(f"\n[bold]Reasoning:[/bold] {step.reasoning}", style="dim"))
|
|
444
|
+
if step.confidence is not None:
|
|
445
|
+
step_content.append(Text.from_markup(f"\n[bold]Confidence:[/bold] {step.confidence}", style="dim"))
|
|
446
|
+
reasoning_panel = create_panel(content=step_content, title=f"Reasoning step {i}", border_style="green")
|
|
447
|
+
panels.append(reasoning_panel)
|
|
448
|
+
|
|
449
|
+
if len(response_reasoning_content_buffer) > 0 and show_reasoning:
|
|
450
|
+
# Create panel for thinking
|
|
451
|
+
thinking_panel = create_panel(
|
|
452
|
+
content=Text(response_reasoning_content_buffer),
|
|
453
|
+
title=f"Thinking ({response_timer.elapsed:.1f}s)",
|
|
454
|
+
border_style="green",
|
|
455
|
+
)
|
|
456
|
+
panels.append(thinking_panel)
|
|
457
|
+
|
|
458
|
+
if accumulated_tool_calls: # Use accumulated tool calls instead of just current event
|
|
459
|
+
# Create bullet points for each tool call
|
|
460
|
+
tool_calls_content = Text()
|
|
461
|
+
formatted_tool_calls = format_tool_calls(accumulated_tool_calls)
|
|
462
|
+
for formatted_tool_call in formatted_tool_calls:
|
|
463
|
+
tool_calls_content.append(f"• {formatted_tool_call}\n")
|
|
464
|
+
|
|
465
|
+
tool_calls_text = tool_calls_content.plain.rstrip()
|
|
466
|
+
|
|
467
|
+
# Add compression stats if available (don't clear - caller will clear after final display)
|
|
468
|
+
if compression_manager is not None and compression_manager.stats:
|
|
469
|
+
stats = compression_manager.stats
|
|
470
|
+
saved = stats.get("original_size", 0) - stats.get("compressed_size", 0)
|
|
471
|
+
orig = stats.get("original_size", 1)
|
|
472
|
+
if stats.get("tool_results_compressed", 0) > 0:
|
|
473
|
+
tool_calls_text += f"\n\ncompressed: {stats.get('tool_results_compressed', 0)} | Saved: {saved:,} chars ({saved / orig * 100:.0f}%)"
|
|
474
|
+
|
|
475
|
+
tool_calls_panel = create_panel(
|
|
476
|
+
content=tool_calls_text,
|
|
477
|
+
title="Tool Calls",
|
|
478
|
+
border_style="yellow",
|
|
479
|
+
)
|
|
480
|
+
panels.append(tool_calls_panel)
|
|
481
|
+
|
|
482
|
+
response_panel = None
|
|
483
|
+
if response_content:
|
|
484
|
+
response_panel = create_panel(
|
|
485
|
+
content=response_content,
|
|
486
|
+
title=f"Response ({response_timer.elapsed:.1f}s)",
|
|
487
|
+
border_style="blue",
|
|
488
|
+
)
|
|
489
|
+
panels.append(response_panel)
|
|
490
|
+
|
|
491
|
+
if (
|
|
492
|
+
isinstance(response_event, tuple(get_args(RunOutputEvent)))
|
|
493
|
+
and hasattr(response_event, "citations")
|
|
494
|
+
and response_event.citations is not None
|
|
495
|
+
and response_event.citations.urls is not None
|
|
496
|
+
):
|
|
497
|
+
md_lines = []
|
|
498
|
+
|
|
499
|
+
# Add search queries if present
|
|
500
|
+
if response_event.citations.search_queries:
|
|
501
|
+
md_lines.append("**Search Queries:**")
|
|
502
|
+
for query in response_event.citations.search_queries:
|
|
503
|
+
md_lines.append(f"- {query}")
|
|
504
|
+
md_lines.append("") # Empty line before URLs
|
|
505
|
+
|
|
506
|
+
# Add URL citations
|
|
507
|
+
md_lines.extend(
|
|
508
|
+
f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
|
|
509
|
+
for i, citation in enumerate(response_event.citations.urls)
|
|
510
|
+
if citation.url # Only include citations with valid URLs
|
|
511
|
+
)
|
|
512
|
+
|
|
513
|
+
md_content = "\n".join(md_lines)
|
|
514
|
+
if md_content: # Only create panel if there are citations
|
|
515
|
+
citations_panel = create_panel(
|
|
516
|
+
content=Markdown(md_content),
|
|
517
|
+
title="Citations",
|
|
518
|
+
border_style="green",
|
|
519
|
+
)
|
|
520
|
+
panels.append(citations_panel)
|
|
521
|
+
|
|
522
|
+
return panels
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
def print_response(
|
|
526
|
+
agent: "Agent",
|
|
527
|
+
input: Union[List, Dict, str, Message, BaseModel, List[Message]],
|
|
528
|
+
session_id: Optional[str] = None,
|
|
529
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
530
|
+
user_id: Optional[str] = None,
|
|
531
|
+
run_id: Optional[str] = None,
|
|
532
|
+
audio: Optional[Sequence[Audio]] = None,
|
|
533
|
+
images: Optional[Sequence[Image]] = None,
|
|
534
|
+
videos: Optional[Sequence[Video]] = None,
|
|
535
|
+
files: Optional[Sequence[File]] = None,
|
|
536
|
+
knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
|
|
537
|
+
stream_events: Optional[bool] = None,
|
|
538
|
+
stream_intermediate_steps: Optional[bool] = None,
|
|
539
|
+
debug_mode: Optional[bool] = None,
|
|
540
|
+
markdown: bool = False,
|
|
541
|
+
show_message: bool = True,
|
|
542
|
+
show_reasoning: bool = True,
|
|
543
|
+
show_full_reasoning: bool = False,
|
|
544
|
+
tags_to_include_in_markdown: Set[str] = {"think", "thinking"},
|
|
545
|
+
console: Optional[Any] = None,
|
|
546
|
+
add_history_to_context: Optional[bool] = None,
|
|
547
|
+
dependencies: Optional[Dict[str, Any]] = None,
|
|
548
|
+
add_dependencies_to_context: Optional[bool] = None,
|
|
549
|
+
add_session_state_to_context: Optional[bool] = None,
|
|
550
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
551
|
+
**kwargs: Any,
|
|
552
|
+
):
|
|
553
|
+
if stream_events is not None:
|
|
554
|
+
warnings.warn(
|
|
555
|
+
"The 'stream_events' parameter is deprecated and will be removed in future versions. Event streaming is always enabled using the print_response function.",
|
|
556
|
+
DeprecationWarning,
|
|
557
|
+
stacklevel=2,
|
|
558
|
+
)
|
|
559
|
+
if stream_intermediate_steps is not None:
|
|
560
|
+
warnings.warn(
|
|
561
|
+
"The 'stream_intermediate_steps' parameter is deprecated and will be removed in future versions. Event streaming is always enabled using the print_response function.",
|
|
562
|
+
DeprecationWarning,
|
|
563
|
+
stacklevel=2,
|
|
564
|
+
)
|
|
565
|
+
|
|
566
|
+
with Live(console=console) as live_log:
|
|
567
|
+
status = Status("Thinking...", spinner="aesthetic", speed=0.4, refresh_per_second=10)
|
|
568
|
+
live_log.update(status)
|
|
569
|
+
response_timer = Timer()
|
|
570
|
+
response_timer.start()
|
|
571
|
+
# Panels to be rendered
|
|
572
|
+
panels = [status]
|
|
573
|
+
# First render the message panel if the message is not None
|
|
574
|
+
if input and show_message:
|
|
575
|
+
# Convert message to a panel
|
|
576
|
+
message_content = get_text_from_message(input)
|
|
577
|
+
message_panel = create_panel(
|
|
578
|
+
content=Text(message_content, style="green"),
|
|
579
|
+
title="Message",
|
|
580
|
+
border_style="cyan",
|
|
581
|
+
)
|
|
582
|
+
panels.append(message_panel) # type: ignore
|
|
583
|
+
live_log.update(Group(*panels))
|
|
584
|
+
|
|
585
|
+
# Run the agent
|
|
586
|
+
run_response = agent.run(
|
|
587
|
+
input=input,
|
|
588
|
+
session_id=session_id,
|
|
589
|
+
session_state=session_state,
|
|
590
|
+
user_id=user_id,
|
|
591
|
+
run_id=run_id,
|
|
592
|
+
audio=audio,
|
|
593
|
+
images=images,
|
|
594
|
+
videos=videos,
|
|
595
|
+
files=files,
|
|
596
|
+
stream=False,
|
|
597
|
+
stream_events=True,
|
|
598
|
+
knowledge_filters=knowledge_filters,
|
|
599
|
+
debug_mode=debug_mode,
|
|
600
|
+
add_history_to_context=add_history_to_context,
|
|
601
|
+
add_dependencies_to_context=add_dependencies_to_context,
|
|
602
|
+
add_session_state_to_context=add_session_state_to_context,
|
|
603
|
+
dependencies=dependencies,
|
|
604
|
+
metadata=metadata,
|
|
605
|
+
**kwargs,
|
|
606
|
+
)
|
|
607
|
+
response_timer.stop()
|
|
608
|
+
|
|
609
|
+
if run_response.input is not None and run_response.input.input_content != input:
|
|
610
|
+
# Input was modified during the run
|
|
611
|
+
panels = [status]
|
|
612
|
+
if show_message:
|
|
613
|
+
# Convert message to a panel
|
|
614
|
+
message_content = get_text_from_message(run_response.input.input_content)
|
|
615
|
+
message_panel = create_panel(
|
|
616
|
+
content=Text(message_content, style="green"),
|
|
617
|
+
title="Message",
|
|
618
|
+
border_style="cyan",
|
|
619
|
+
)
|
|
620
|
+
panels.append(message_panel) # type: ignore
|
|
621
|
+
live_log.update(Group(*panels))
|
|
622
|
+
|
|
623
|
+
additional_panels = build_panels(
|
|
624
|
+
run_response=run_response,
|
|
625
|
+
output_schema=agent.output_schema, # type: ignore
|
|
626
|
+
response_timer=response_timer,
|
|
627
|
+
show_reasoning=show_reasoning,
|
|
628
|
+
show_full_reasoning=show_full_reasoning,
|
|
629
|
+
tags_to_include_in_markdown=tags_to_include_in_markdown,
|
|
630
|
+
markdown=markdown,
|
|
631
|
+
compression_manager=agent.compression_manager,
|
|
632
|
+
)
|
|
633
|
+
panels.extend(additional_panels)
|
|
634
|
+
|
|
635
|
+
if agent.memory_manager is not None and agent.memory_manager.memories_updated:
|
|
636
|
+
memory_panel = create_panel(
|
|
637
|
+
content=Text("Memories updated"),
|
|
638
|
+
title="Memories",
|
|
639
|
+
border_style="green",
|
|
640
|
+
)
|
|
641
|
+
panels.append(memory_panel)
|
|
642
|
+
live_log.update(Group(*panels))
|
|
643
|
+
agent.memory_manager.memories_updated = False
|
|
644
|
+
|
|
645
|
+
if agent.session_summary_manager is not None and agent.session_summary_manager.summaries_updated:
|
|
646
|
+
summary_panel = create_panel(
|
|
647
|
+
content=Text("Session summary updated"),
|
|
648
|
+
title="Session Summary",
|
|
649
|
+
border_style="green",
|
|
650
|
+
)
|
|
651
|
+
panels.append(summary_panel)
|
|
652
|
+
live_log.update(Group(*panels))
|
|
653
|
+
agent.session_summary_manager.summaries_updated = False
|
|
654
|
+
|
|
655
|
+
# Final update to remove the "Thinking..." status
|
|
656
|
+
panels = [p for p in panels if not isinstance(p, Status)]
|
|
657
|
+
live_log.update(Group(*panels))
|
|
658
|
+
|
|
659
|
+
|
|
660
|
+
async def aprint_response(
|
|
661
|
+
agent: "Agent",
|
|
662
|
+
input: Union[List, Dict, str, Message, BaseModel, List[Message]],
|
|
663
|
+
session_id: Optional[str] = None,
|
|
664
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
665
|
+
user_id: Optional[str] = None,
|
|
666
|
+
run_id: Optional[str] = None,
|
|
667
|
+
audio: Optional[Sequence[Audio]] = None,
|
|
668
|
+
images: Optional[Sequence[Image]] = None,
|
|
669
|
+
videos: Optional[Sequence[Video]] = None,
|
|
670
|
+
files: Optional[Sequence[File]] = None,
|
|
671
|
+
knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
|
|
672
|
+
debug_mode: Optional[bool] = None,
|
|
673
|
+
markdown: bool = False,
|
|
674
|
+
show_message: bool = True,
|
|
675
|
+
show_reasoning: bool = True,
|
|
676
|
+
show_full_reasoning: bool = False,
|
|
677
|
+
stream_events: Optional[bool] = None,
|
|
678
|
+
stream_intermediate_steps: Optional[bool] = None,
|
|
679
|
+
tags_to_include_in_markdown: Set[str] = {"think", "thinking"},
|
|
680
|
+
console: Optional[Any] = None,
|
|
681
|
+
add_history_to_context: Optional[bool] = None,
|
|
682
|
+
dependencies: Optional[Dict[str, Any]] = None,
|
|
683
|
+
add_dependencies_to_context: Optional[bool] = None,
|
|
684
|
+
add_session_state_to_context: Optional[bool] = None,
|
|
685
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
686
|
+
**kwargs: Any,
|
|
687
|
+
):
|
|
688
|
+
if stream_events is not None:
|
|
689
|
+
warnings.warn(
|
|
690
|
+
"The 'stream_events' parameter is deprecated and will be removed in future versions. Event streaming is always enabled using the aprint_response function.",
|
|
691
|
+
DeprecationWarning,
|
|
692
|
+
stacklevel=2,
|
|
693
|
+
)
|
|
694
|
+
if stream_intermediate_steps is not None:
|
|
695
|
+
warnings.warn(
|
|
696
|
+
"The 'stream_intermediate_steps' parameter is deprecated and will be removed in future versions. Event streaming is always enabled using the aprint_response function.",
|
|
697
|
+
DeprecationWarning,
|
|
698
|
+
stacklevel=2,
|
|
699
|
+
)
|
|
700
|
+
|
|
701
|
+
with Live(console=console) as live_log:
|
|
702
|
+
status = Status("Thinking...", spinner="aesthetic", speed=0.4, refresh_per_second=10)
|
|
703
|
+
live_log.update(status)
|
|
704
|
+
response_timer = Timer()
|
|
705
|
+
response_timer.start()
|
|
706
|
+
# Panels to be rendered
|
|
707
|
+
panels = [status]
|
|
708
|
+
# First render the message panel if the message is not None
|
|
709
|
+
if input and show_message:
|
|
710
|
+
# Convert message to a panel
|
|
711
|
+
message_content = get_text_from_message(input)
|
|
712
|
+
message_panel = create_panel(
|
|
713
|
+
content=Text(message_content, style="green"),
|
|
714
|
+
title="Message",
|
|
715
|
+
border_style="cyan",
|
|
716
|
+
)
|
|
717
|
+
panels.append(message_panel)
|
|
718
|
+
live_log.update(Group(*panels))
|
|
719
|
+
|
|
720
|
+
# Run the agent
|
|
721
|
+
run_response = await agent.arun(
|
|
722
|
+
input=input,
|
|
723
|
+
session_id=session_id,
|
|
724
|
+
session_state=session_state,
|
|
725
|
+
user_id=user_id,
|
|
726
|
+
run_id=run_id,
|
|
727
|
+
audio=audio,
|
|
728
|
+
images=images,
|
|
729
|
+
videos=videos,
|
|
730
|
+
files=files,
|
|
731
|
+
stream=False,
|
|
732
|
+
stream_events=True,
|
|
733
|
+
knowledge_filters=knowledge_filters,
|
|
734
|
+
debug_mode=debug_mode,
|
|
735
|
+
add_history_to_context=add_history_to_context,
|
|
736
|
+
add_dependencies_to_context=add_dependencies_to_context,
|
|
737
|
+
add_session_state_to_context=add_session_state_to_context,
|
|
738
|
+
dependencies=dependencies,
|
|
739
|
+
metadata=metadata,
|
|
740
|
+
**kwargs,
|
|
741
|
+
)
|
|
742
|
+
response_timer.stop()
|
|
743
|
+
|
|
744
|
+
if run_response.input is not None and run_response.input.input_content != input:
|
|
745
|
+
# Input was modified during the run
|
|
746
|
+
panels = [status]
|
|
747
|
+
if show_message:
|
|
748
|
+
# Convert message to a panel
|
|
749
|
+
message_content = get_text_from_message(run_response.input.input_content)
|
|
750
|
+
message_panel = create_panel(
|
|
751
|
+
content=Text(message_content, style="green"),
|
|
752
|
+
title="Message",
|
|
753
|
+
border_style="cyan",
|
|
754
|
+
)
|
|
755
|
+
panels.append(message_panel) # type: ignore
|
|
756
|
+
live_log.update(Group(*panels))
|
|
757
|
+
|
|
758
|
+
additional_panels = build_panels(
|
|
759
|
+
run_response=run_response,
|
|
760
|
+
output_schema=agent.output_schema, # type: ignore
|
|
761
|
+
response_timer=response_timer,
|
|
762
|
+
show_reasoning=show_reasoning,
|
|
763
|
+
show_full_reasoning=show_full_reasoning,
|
|
764
|
+
tags_to_include_in_markdown=tags_to_include_in_markdown,
|
|
765
|
+
markdown=markdown,
|
|
766
|
+
compression_manager=agent.compression_manager,
|
|
767
|
+
)
|
|
768
|
+
panels.extend(additional_panels)
|
|
769
|
+
|
|
770
|
+
if agent.memory_manager is not None and agent.memory_manager.memories_updated:
|
|
771
|
+
memory_panel = create_panel(
|
|
772
|
+
content=Text("Memories updated"),
|
|
773
|
+
title="Memories",
|
|
774
|
+
border_style="green",
|
|
775
|
+
)
|
|
776
|
+
panels.append(memory_panel)
|
|
777
|
+
live_log.update(Group(*panels))
|
|
778
|
+
agent.memory_manager.memories_updated = False
|
|
779
|
+
|
|
780
|
+
if agent.session_summary_manager is not None and agent.session_summary_manager.summaries_updated is not None:
|
|
781
|
+
summary_panel = create_panel(
|
|
782
|
+
content=Text("Session summary updated"),
|
|
783
|
+
title="Session Summary",
|
|
784
|
+
border_style="green",
|
|
785
|
+
)
|
|
786
|
+
agent.session_summary_manager.summaries_updated = False
|
|
787
|
+
panels.append(summary_panel)
|
|
788
|
+
live_log.update(Group(*panels))
|
|
789
|
+
|
|
790
|
+
# Final update to remove the "Thinking..." status
|
|
791
|
+
panels = [p for p in panels if not isinstance(p, Status)]
|
|
792
|
+
live_log.update(Group(*panels))
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
def build_panels(
|
|
796
|
+
run_response: RunOutput,
|
|
797
|
+
response_timer: Timer,
|
|
798
|
+
output_schema: Optional[BaseModel] = None,
|
|
799
|
+
show_reasoning: bool = True,
|
|
800
|
+
show_full_reasoning: bool = False,
|
|
801
|
+
tags_to_include_in_markdown: Optional[Set[str]] = None,
|
|
802
|
+
markdown: bool = False,
|
|
803
|
+
compression_manager: Optional[Any] = None,
|
|
804
|
+
):
|
|
805
|
+
panels = []
|
|
806
|
+
|
|
807
|
+
reasoning_steps = []
|
|
808
|
+
|
|
809
|
+
if isinstance(run_response, RunOutput) and run_response.is_paused:
|
|
810
|
+
response_panel = create_paused_run_output_panel(run_response)
|
|
811
|
+
panels.append(response_panel)
|
|
812
|
+
return panels
|
|
813
|
+
|
|
814
|
+
if isinstance(run_response, RunOutput) and run_response.reasoning_steps is not None:
|
|
815
|
+
reasoning_steps = run_response.reasoning_steps
|
|
816
|
+
|
|
817
|
+
if len(reasoning_steps) > 0 and show_reasoning:
|
|
818
|
+
# Create panels for reasoning steps
|
|
819
|
+
for i, step in enumerate(reasoning_steps, 1):
|
|
820
|
+
# Build step content
|
|
821
|
+
step_content = Text.assemble()
|
|
822
|
+
if step.title is not None:
|
|
823
|
+
step_content.append(f"{step.title}\n", "bold")
|
|
824
|
+
if step.action is not None:
|
|
825
|
+
step_content.append(Text.from_markup(f"[bold]Action:[/bold] {step.action}\n", style="dim"))
|
|
826
|
+
if step.result is not None:
|
|
827
|
+
step_content.append(Text.from_markup(step.result, style="dim"))
|
|
828
|
+
|
|
829
|
+
if show_full_reasoning:
|
|
830
|
+
# Add detailed reasoning information if available
|
|
831
|
+
if step.reasoning is not None:
|
|
832
|
+
step_content.append(Text.from_markup(f"\n[bold]Reasoning:[/bold] {step.reasoning}", style="dim"))
|
|
833
|
+
if step.confidence is not None:
|
|
834
|
+
step_content.append(Text.from_markup(f"\n[bold]Confidence:[/bold] {step.confidence}", style="dim"))
|
|
835
|
+
reasoning_panel = create_panel(content=step_content, title=f"Reasoning step {i}", border_style="green")
|
|
836
|
+
panels.append(reasoning_panel)
|
|
837
|
+
|
|
838
|
+
if isinstance(run_response, RunOutput) and run_response.reasoning_content is not None and show_reasoning:
|
|
839
|
+
# Create panel for thinking
|
|
840
|
+
thinking_panel = create_panel(
|
|
841
|
+
content=Text(run_response.reasoning_content),
|
|
842
|
+
title=f"Thinking ({response_timer.elapsed:.1f}s)",
|
|
843
|
+
border_style="green",
|
|
844
|
+
)
|
|
845
|
+
panels.append(thinking_panel)
|
|
846
|
+
|
|
847
|
+
# Add tool calls panel if available
|
|
848
|
+
if isinstance(run_response, RunOutput) and run_response.tools:
|
|
849
|
+
# Create bullet points for each tool call
|
|
850
|
+
tool_calls_content = Text()
|
|
851
|
+
formatted_tool_calls = format_tool_calls(run_response.tools)
|
|
852
|
+
for formatted_tool_call in formatted_tool_calls:
|
|
853
|
+
tool_calls_content.append(f"• {formatted_tool_call}\n")
|
|
854
|
+
|
|
855
|
+
tool_calls_text = tool_calls_content.plain.rstrip()
|
|
856
|
+
|
|
857
|
+
# Add compression stats if available
|
|
858
|
+
if compression_manager is not None and compression_manager.stats:
|
|
859
|
+
stats = compression_manager.stats
|
|
860
|
+
saved = stats.get("original_size", 0) - stats.get("compressed_size", 0)
|
|
861
|
+
orig = stats.get("original_size", 1)
|
|
862
|
+
if stats.get("tool_results_compressed", 0) > 0:
|
|
863
|
+
tool_calls_text += f"\n\ncompressed: {stats.get('tool_results_compressed', 0)} | Saved: {saved:,} chars ({saved / orig * 100:.0f}%)"
|
|
864
|
+
compression_manager.stats.clear()
|
|
865
|
+
|
|
866
|
+
tool_calls_panel = create_panel(
|
|
867
|
+
content=tool_calls_text,
|
|
868
|
+
title="Tool Calls",
|
|
869
|
+
border_style="yellow",
|
|
870
|
+
)
|
|
871
|
+
panels.append(tool_calls_panel)
|
|
872
|
+
|
|
873
|
+
response_content_batch: Union[str, JSON, Markdown] = "" # type: ignore
|
|
874
|
+
if isinstance(run_response, RunOutput):
|
|
875
|
+
if isinstance(run_response.content, str):
|
|
876
|
+
if markdown:
|
|
877
|
+
escaped_content = escape_markdown_tags(run_response.content, tags_to_include_in_markdown) # type: ignore
|
|
878
|
+
response_content_batch = Markdown(escaped_content)
|
|
879
|
+
else:
|
|
880
|
+
response_content_batch = run_response.get_content_as_string(indent=4)
|
|
881
|
+
elif output_schema is not None and isinstance(run_response.content, BaseModel):
|
|
882
|
+
try:
|
|
883
|
+
response_content_batch = JSON(run_response.content.model_dump_json(exclude_none=True), indent=2)
|
|
884
|
+
except Exception as e:
|
|
885
|
+
log_warning(f"Failed to convert response to JSON: {e}")
|
|
886
|
+
else:
|
|
887
|
+
try:
|
|
888
|
+
response_content_batch = JSON(json.dumps(run_response.content), indent=4)
|
|
889
|
+
except Exception as e:
|
|
890
|
+
log_warning(f"Failed to convert response to JSON: {e}")
|
|
891
|
+
|
|
892
|
+
# Create panel for response
|
|
893
|
+
response_panel = create_panel(
|
|
894
|
+
content=response_content_batch,
|
|
895
|
+
title=f"Response ({response_timer.elapsed:.1f}s)",
|
|
896
|
+
border_style="blue",
|
|
897
|
+
)
|
|
898
|
+
panels.append(response_panel)
|
|
899
|
+
|
|
900
|
+
if (
|
|
901
|
+
isinstance(run_response, RunOutput)
|
|
902
|
+
and run_response.citations is not None
|
|
903
|
+
and run_response.citations.urls is not None
|
|
904
|
+
):
|
|
905
|
+
md_lines = []
|
|
906
|
+
|
|
907
|
+
# Add search queries if present
|
|
908
|
+
if run_response.citations.search_queries:
|
|
909
|
+
md_lines.append("**Search Queries:**")
|
|
910
|
+
for query in run_response.citations.search_queries:
|
|
911
|
+
md_lines.append(f"- {query}")
|
|
912
|
+
md_lines.append("") # Empty line before URLs
|
|
913
|
+
|
|
914
|
+
# Add URL citations
|
|
915
|
+
md_lines.extend(
|
|
916
|
+
f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
|
|
917
|
+
for i, citation in enumerate(run_response.citations.urls)
|
|
918
|
+
if citation.url # Only include citations with valid URLs
|
|
919
|
+
)
|
|
920
|
+
|
|
921
|
+
md_content = "\n".join(md_lines)
|
|
922
|
+
if md_content: # Only create panel if there are citations
|
|
923
|
+
citations_panel = create_panel(
|
|
924
|
+
content=Markdown(md_content),
|
|
925
|
+
title="Citations",
|
|
926
|
+
border_style="green",
|
|
927
|
+
)
|
|
928
|
+
panels.append(citations_panel)
|
|
929
|
+
|
|
930
|
+
return panels
|