agno 1.8.1__py3-none-any.whl → 2.0.0__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 +19 -27
- agno/agent/agent.py +3143 -4170
- agno/api/agent.py +11 -67
- agno/api/api.py +5 -46
- agno/api/evals.py +8 -19
- agno/api/os.py +17 -0
- agno/api/routes.py +6 -41
- agno/api/schemas/__init__.py +9 -0
- agno/api/schemas/agent.py +5 -21
- agno/api/schemas/evals.py +7 -16
- agno/api/schemas/os.py +14 -0
- agno/api/schemas/team.py +5 -21
- agno/api/schemas/utils.py +21 -0
- agno/api/schemas/workflows.py +11 -7
- agno/api/settings.py +53 -0
- agno/api/team.py +11 -66
- 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/db/__init__.py +24 -0
- agno/db/base.py +245 -0
- agno/db/dynamo/__init__.py +3 -0
- agno/db/dynamo/dynamo.py +1743 -0
- agno/db/dynamo/schemas.py +278 -0
- agno/db/dynamo/utils.py +684 -0
- agno/db/firestore/__init__.py +3 -0
- agno/db/firestore/firestore.py +1432 -0
- agno/db/firestore/schemas.py +130 -0
- agno/db/firestore/utils.py +278 -0
- agno/db/gcs_json/__init__.py +3 -0
- agno/db/gcs_json/gcs_json_db.py +1001 -0
- agno/db/gcs_json/utils.py +194 -0
- agno/db/in_memory/__init__.py +3 -0
- agno/db/in_memory/in_memory_db.py +882 -0
- agno/db/in_memory/utils.py +172 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1045 -0
- agno/db/json/utils.py +196 -0
- agno/db/migrations/v1_to_v2.py +162 -0
- agno/db/mongo/__init__.py +3 -0
- agno/db/mongo/mongo.py +1416 -0
- agno/db/mongo/schemas.py +77 -0
- agno/db/mongo/utils.py +204 -0
- agno/db/mysql/__init__.py +3 -0
- agno/db/mysql/mysql.py +1719 -0
- agno/db/mysql/schemas.py +124 -0
- agno/db/mysql/utils.py +297 -0
- agno/db/postgres/__init__.py +3 -0
- agno/db/postgres/postgres.py +1710 -0
- agno/db/postgres/schemas.py +124 -0
- agno/db/postgres/utils.py +280 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +1367 -0
- agno/db/redis/schemas.py +109 -0
- agno/db/redis/utils.py +288 -0
- agno/db/schemas/__init__.py +3 -0
- agno/db/schemas/evals.py +33 -0
- agno/db/schemas/knowledge.py +40 -0
- agno/db/schemas/memory.py +46 -0
- agno/db/singlestore/__init__.py +3 -0
- agno/db/singlestore/schemas.py +116 -0
- agno/db/singlestore/singlestore.py +1712 -0
- agno/db/singlestore/utils.py +326 -0
- agno/db/sqlite/__init__.py +3 -0
- agno/db/sqlite/schemas.py +119 -0
- agno/db/sqlite/sqlite.py +1676 -0
- agno/db/sqlite/utils.py +268 -0
- agno/db/utils.py +88 -0
- agno/eval/__init__.py +14 -0
- agno/eval/accuracy.py +154 -48
- agno/eval/performance.py +88 -23
- agno/eval/reliability.py +73 -20
- agno/eval/utils.py +23 -13
- agno/integrations/discord/__init__.py +3 -0
- agno/{app → integrations}/discord/client.py +15 -11
- agno/knowledge/__init__.py +2 -2
- agno/{document → knowledge}/chunking/agentic.py +2 -2
- agno/{document → knowledge}/chunking/document.py +2 -2
- agno/{document → knowledge}/chunking/fixed.py +3 -3
- agno/{document → knowledge}/chunking/markdown.py +2 -2
- agno/{document → knowledge}/chunking/recursive.py +2 -2
- agno/{document → knowledge}/chunking/row.py +2 -2
- agno/knowledge/chunking/semantic.py +59 -0
- agno/knowledge/chunking/strategy.py +121 -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/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
- agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
- agno/{embedder → knowledge/embedder}/base.py +6 -0
- agno/{embedder → knowledge/embedder}/cohere.py +72 -1
- agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
- agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
- agno/{embedder → knowledge/embedder}/google.py +74 -1
- agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
- agno/{embedder → knowledge/embedder}/jina.py +48 -2
- agno/knowledge/embedder/langdb.py +22 -0
- agno/knowledge/embedder/mistral.py +139 -0
- agno/{embedder → knowledge/embedder}/nebius.py +1 -1
- agno/{embedder → knowledge/embedder}/ollama.py +54 -3
- agno/knowledge/embedder/openai.py +223 -0
- agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
- agno/{embedder → knowledge/embedder}/together.py +1 -1
- agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
- agno/knowledge/knowledge.py +1551 -0
- agno/knowledge/reader/__init__.py +7 -0
- agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
- agno/knowledge/reader/base.py +88 -0
- agno/{document → knowledge}/reader/csv_reader.py +47 -65
- agno/knowledge/reader/docx_reader.py +83 -0
- agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
- agno/{document → knowledge}/reader/json_reader.py +30 -9
- agno/{document → knowledge}/reader/markdown_reader.py +58 -9
- agno/{document → knowledge}/reader/pdf_reader.py +71 -126
- agno/knowledge/reader/reader_factory.py +268 -0
- agno/knowledge/reader/s3_reader.py +101 -0
- agno/{document → knowledge}/reader/text_reader.py +31 -10
- agno/knowledge/reader/url_reader.py +128 -0
- agno/knowledge/reader/web_search_reader.py +366 -0
- agno/{document → knowledge}/reader/website_reader.py +37 -10
- agno/knowledge/reader/wikipedia_reader.py +59 -0
- agno/knowledge/reader/youtube_reader.py +78 -0
- agno/knowledge/remote_content/remote_content.py +88 -0
- agno/{reranker → knowledge/reranker}/base.py +1 -1
- agno/{reranker → knowledge/reranker}/cohere.py +2 -2
- agno/{reranker → knowledge/reranker}/infinity.py +2 -2
- agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
- agno/knowledge/types.py +30 -0
- agno/knowledge/utils.py +169 -0
- agno/media.py +269 -268
- agno/memory/__init__.py +2 -10
- agno/memory/manager.py +1003 -148
- agno/models/aimlapi/__init__.py +2 -2
- agno/models/aimlapi/aimlapi.py +6 -6
- agno/models/anthropic/claude.py +131 -131
- agno/models/aws/bedrock.py +110 -182
- agno/models/aws/claude.py +64 -18
- agno/models/azure/ai_foundry.py +73 -23
- agno/models/base.py +346 -290
- agno/models/cerebras/cerebras.py +84 -27
- agno/models/cohere/chat.py +106 -98
- agno/models/google/gemini.py +105 -46
- agno/models/groq/groq.py +97 -35
- agno/models/huggingface/huggingface.py +92 -27
- agno/models/ibm/watsonx.py +72 -13
- agno/models/litellm/chat.py +85 -13
- agno/models/message.py +46 -151
- agno/models/meta/llama.py +85 -49
- agno/models/metrics.py +120 -0
- agno/models/mistral/mistral.py +90 -21
- agno/models/ollama/__init__.py +0 -2
- agno/models/ollama/chat.py +85 -47
- agno/models/openai/chat.py +154 -37
- agno/models/openai/responses.py +178 -105
- agno/models/perplexity/perplexity.py +26 -2
- agno/models/portkey/portkey.py +0 -7
- agno/models/response.py +15 -9
- agno/models/utils.py +20 -0
- agno/models/vercel/__init__.py +2 -2
- agno/models/vercel/v0.py +1 -1
- agno/models/vllm/__init__.py +2 -2
- agno/models/vllm/vllm.py +3 -3
- agno/models/xai/xai.py +10 -10
- agno/os/__init__.py +3 -0
- agno/os/app.py +497 -0
- agno/os/auth.py +47 -0
- agno/os/config.py +103 -0
- agno/os/interfaces/agui/__init__.py +3 -0
- agno/os/interfaces/agui/agui.py +31 -0
- agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
- agno/{app → os/interfaces}/agui/utils.py +77 -33
- agno/os/interfaces/base.py +21 -0
- agno/os/interfaces/slack/__init__.py +3 -0
- agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
- agno/os/interfaces/slack/slack.py +32 -0
- agno/os/interfaces/whatsapp/__init__.py +3 -0
- agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
- agno/os/interfaces/whatsapp/whatsapp.py +29 -0
- agno/os/mcp.py +235 -0
- agno/os/router.py +1400 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +393 -0
- agno/os/routers/evals/schemas.py +142 -0
- agno/os/routers/evals/utils.py +161 -0
- agno/os/routers/knowledge/__init__.py +3 -0
- agno/os/routers/knowledge/knowledge.py +850 -0
- agno/os/routers/knowledge/schemas.py +118 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +410 -0
- agno/os/routers/memory/schemas.py +58 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +178 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +536 -0
- agno/os/schema.py +945 -0
- agno/{app/playground → os}/settings.py +7 -15
- agno/os/utils.py +270 -0
- agno/reasoning/azure_ai_foundry.py +4 -4
- agno/reasoning/deepseek.py +4 -4
- agno/reasoning/default.py +6 -11
- agno/reasoning/groq.py +4 -4
- agno/reasoning/helpers.py +4 -6
- agno/reasoning/ollama.py +4 -4
- agno/reasoning/openai.py +4 -4
- agno/run/agent.py +633 -0
- agno/run/base.py +53 -77
- agno/run/cancel.py +81 -0
- agno/run/team.py +243 -96
- agno/run/workflow.py +550 -12
- agno/session/__init__.py +10 -0
- agno/session/agent.py +244 -0
- agno/session/summary.py +225 -0
- agno/session/team.py +262 -0
- agno/{storage/session/v2 → session}/workflow.py +47 -24
- agno/team/__init__.py +15 -16
- agno/team/team.py +3260 -4824
- agno/tools/agentql.py +14 -5
- agno/tools/airflow.py +9 -4
- agno/tools/api.py +7 -3
- agno/tools/apify.py +2 -46
- agno/tools/arxiv.py +8 -3
- agno/tools/aws_lambda.py +7 -5
- agno/tools/aws_ses.py +7 -1
- agno/tools/baidusearch.py +4 -1
- agno/tools/bitbucket.py +4 -4
- agno/tools/brandfetch.py +14 -11
- agno/tools/bravesearch.py +4 -1
- agno/tools/brightdata.py +43 -23
- agno/tools/browserbase.py +13 -4
- agno/tools/calcom.py +12 -10
- agno/tools/calculator.py +10 -27
- agno/tools/cartesia.py +20 -17
- agno/tools/{clickup_tool.py → clickup.py} +12 -25
- agno/tools/confluence.py +8 -8
- agno/tools/crawl4ai.py +7 -1
- agno/tools/csv_toolkit.py +9 -8
- agno/tools/dalle.py +22 -12
- agno/tools/daytona.py +13 -16
- agno/tools/decorator.py +6 -3
- agno/tools/desi_vocal.py +17 -8
- agno/tools/discord.py +11 -8
- agno/tools/docker.py +30 -42
- agno/tools/duckdb.py +34 -53
- agno/tools/duckduckgo.py +8 -7
- agno/tools/e2b.py +62 -62
- agno/tools/eleven_labs.py +36 -29
- agno/tools/email.py +4 -1
- agno/tools/evm.py +7 -1
- agno/tools/exa.py +19 -14
- agno/tools/fal.py +30 -30
- agno/tools/file.py +9 -8
- agno/tools/financial_datasets.py +25 -44
- agno/tools/firecrawl.py +22 -22
- agno/tools/function.py +127 -18
- agno/tools/giphy.py +23 -11
- agno/tools/github.py +48 -126
- agno/tools/gmail.py +45 -61
- agno/tools/google_bigquery.py +7 -6
- agno/tools/google_maps.py +11 -26
- agno/tools/googlesearch.py +7 -2
- agno/tools/googlesheets.py +21 -17
- agno/tools/hackernews.py +9 -5
- agno/tools/jina.py +5 -4
- agno/tools/jira.py +18 -9
- agno/tools/knowledge.py +31 -32
- agno/tools/linear.py +19 -34
- agno/tools/linkup.py +5 -1
- agno/tools/local_file_system.py +8 -5
- agno/tools/lumalab.py +32 -20
- agno/tools/mcp.py +1 -2
- agno/tools/mem0.py +18 -12
- agno/tools/memori.py +14 -10
- agno/tools/mlx_transcribe.py +3 -2
- agno/tools/models/azure_openai.py +33 -15
- agno/tools/models/gemini.py +59 -32
- agno/tools/models/groq.py +30 -23
- agno/tools/models/nebius.py +28 -12
- agno/tools/models_labs.py +40 -16
- agno/tools/moviepy_video.py +7 -6
- agno/tools/neo4j.py +10 -8
- agno/tools/newspaper.py +7 -2
- agno/tools/newspaper4k.py +8 -3
- agno/tools/openai.py +58 -32
- agno/tools/openbb.py +12 -11
- agno/tools/opencv.py +63 -47
- agno/tools/openweather.py +14 -12
- agno/tools/pandas.py +11 -3
- agno/tools/postgres.py +4 -12
- agno/tools/pubmed.py +4 -1
- agno/tools/python.py +9 -22
- agno/tools/reasoning.py +35 -27
- agno/tools/reddit.py +11 -26
- agno/tools/replicate.py +55 -42
- agno/tools/resend.py +4 -1
- agno/tools/scrapegraph.py +15 -14
- agno/tools/searxng.py +10 -23
- agno/tools/serpapi.py +6 -3
- agno/tools/serper.py +13 -4
- agno/tools/shell.py +9 -2
- agno/tools/slack.py +12 -11
- agno/tools/sleep.py +3 -2
- agno/tools/spider.py +24 -4
- agno/tools/sql.py +7 -6
- agno/tools/tavily.py +6 -4
- agno/tools/telegram.py +12 -4
- agno/tools/todoist.py +11 -31
- agno/tools/toolkit.py +1 -1
- agno/tools/trafilatura.py +22 -6
- agno/tools/trello.py +9 -22
- agno/tools/twilio.py +10 -3
- agno/tools/user_control_flow.py +6 -1
- agno/tools/valyu.py +34 -5
- agno/tools/visualization.py +19 -28
- agno/tools/webbrowser.py +4 -3
- agno/tools/webex.py +11 -7
- agno/tools/website.py +15 -46
- agno/tools/webtools.py +12 -4
- agno/tools/whatsapp.py +5 -9
- agno/tools/wikipedia.py +20 -13
- agno/tools/x.py +14 -13
- agno/tools/yfinance.py +13 -40
- agno/tools/youtube.py +26 -20
- agno/tools/zendesk.py +7 -2
- agno/tools/zep.py +10 -7
- agno/tools/zoom.py +10 -9
- agno/utils/common.py +1 -19
- agno/utils/events.py +100 -123
- agno/utils/gemini.py +32 -2
- agno/utils/knowledge.py +29 -0
- agno/utils/log.py +54 -4
- agno/utils/mcp.py +68 -10
- agno/utils/media.py +39 -0
- agno/utils/message.py +12 -1
- agno/utils/models/aws_claude.py +1 -1
- agno/utils/models/claude.py +47 -4
- agno/utils/models/cohere.py +1 -1
- agno/utils/models/mistral.py +8 -7
- agno/utils/models/schema_utils.py +3 -3
- agno/utils/models/watsonx.py +1 -1
- agno/utils/openai.py +1 -1
- agno/utils/pprint.py +33 -32
- agno/utils/print_response/agent.py +779 -0
- agno/utils/print_response/team.py +1669 -0
- agno/utils/print_response/workflow.py +1451 -0
- agno/utils/prompts.py +14 -14
- agno/utils/reasoning.py +87 -0
- agno/utils/response.py +42 -42
- agno/utils/streamlit.py +481 -0
- agno/utils/string.py +8 -22
- agno/utils/team.py +50 -0
- agno/utils/timer.py +2 -2
- agno/vectordb/base.py +33 -21
- agno/vectordb/cassandra/cassandra.py +287 -23
- agno/vectordb/chroma/chromadb.py +482 -59
- agno/vectordb/clickhouse/clickhousedb.py +270 -63
- agno/vectordb/couchbase/couchbase.py +309 -29
- agno/vectordb/lancedb/lance_db.py +360 -21
- agno/vectordb/langchaindb/__init__.py +5 -0
- agno/vectordb/langchaindb/langchaindb.py +145 -0
- agno/vectordb/lightrag/__init__.py +5 -0
- agno/vectordb/lightrag/lightrag.py +374 -0
- agno/vectordb/llamaindex/llamaindexdb.py +127 -0
- agno/vectordb/milvus/milvus.py +242 -32
- agno/vectordb/mongodb/mongodb.py +200 -24
- agno/vectordb/pgvector/pgvector.py +319 -37
- agno/vectordb/pineconedb/pineconedb.py +221 -27
- agno/vectordb/qdrant/qdrant.py +334 -14
- agno/vectordb/singlestore/singlestore.py +286 -29
- agno/vectordb/surrealdb/surrealdb.py +187 -7
- agno/vectordb/upstashdb/upstashdb.py +342 -26
- agno/vectordb/weaviate/weaviate.py +227 -165
- agno/workflow/__init__.py +17 -13
- agno/workflow/{v2/condition.py → condition.py} +135 -32
- agno/workflow/{v2/loop.py → loop.py} +115 -28
- agno/workflow/{v2/parallel.py → parallel.py} +138 -108
- agno/workflow/{v2/router.py → router.py} +133 -32
- agno/workflow/{v2/step.py → step.py} +207 -49
- agno/workflow/{v2/steps.py → steps.py} +147 -66
- agno/workflow/types.py +482 -0
- agno/workflow/workflow.py +2410 -696
- agno-2.0.0.dist-info/METADATA +494 -0
- agno-2.0.0.dist-info/RECORD +515 -0
- agno-2.0.0.dist-info/licenses/LICENSE +201 -0
- agno/agent/metrics.py +0 -107
- agno/api/app.py +0 -35
- agno/api/playground.py +0 -92
- agno/api/schemas/app.py +0 -12
- agno/api/schemas/playground.py +0 -22
- agno/api/schemas/user.py +0 -35
- agno/api/schemas/workspace.py +0 -46
- agno/api/user.py +0 -160
- agno/api/workflows.py +0 -33
- agno/api/workspace.py +0 -175
- agno/app/agui/__init__.py +0 -3
- agno/app/agui/app.py +0 -17
- agno/app/agui/sync_router.py +0 -120
- agno/app/base.py +0 -186
- agno/app/discord/__init__.py +0 -3
- agno/app/fastapi/__init__.py +0 -3
- agno/app/fastapi/app.py +0 -107
- agno/app/fastapi/async_router.py +0 -457
- agno/app/fastapi/sync_router.py +0 -448
- agno/app/playground/app.py +0 -228
- agno/app/playground/async_router.py +0 -1050
- agno/app/playground/deploy.py +0 -249
- agno/app/playground/operator.py +0 -183
- agno/app/playground/schemas.py +0 -220
- agno/app/playground/serve.py +0 -55
- agno/app/playground/sync_router.py +0 -1042
- agno/app/playground/utils.py +0 -46
- agno/app/settings.py +0 -15
- agno/app/slack/__init__.py +0 -3
- agno/app/slack/app.py +0 -19
- agno/app/slack/sync_router.py +0 -92
- agno/app/utils.py +0 -54
- agno/app/whatsapp/__init__.py +0 -3
- agno/app/whatsapp/app.py +0 -15
- agno/app/whatsapp/sync_router.py +0 -197
- agno/cli/auth_server.py +0 -249
- agno/cli/config.py +0 -274
- agno/cli/console.py +0 -88
- agno/cli/credentials.py +0 -23
- agno/cli/entrypoint.py +0 -571
- agno/cli/operator.py +0 -357
- agno/cli/settings.py +0 -96
- agno/cli/ws/ws_cli.py +0 -817
- agno/constants.py +0 -13
- agno/document/__init__.py +0 -5
- agno/document/chunking/semantic.py +0 -45
- agno/document/chunking/strategy.py +0 -31
- agno/document/reader/__init__.py +0 -5
- agno/document/reader/base.py +0 -47
- agno/document/reader/docx_reader.py +0 -60
- agno/document/reader/gcs/pdf_reader.py +0 -44
- agno/document/reader/s3/pdf_reader.py +0 -59
- agno/document/reader/s3/text_reader.py +0 -63
- agno/document/reader/url_reader.py +0 -59
- agno/document/reader/youtube_reader.py +0 -58
- agno/embedder/__init__.py +0 -5
- agno/embedder/langdb.py +0 -80
- agno/embedder/mistral.py +0 -82
- agno/embedder/openai.py +0 -78
- agno/file/__init__.py +0 -5
- 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 -702
- agno/knowledge/arxiv.py +0 -33
- agno/knowledge/combined.py +0 -36
- agno/knowledge/csv.py +0 -144
- agno/knowledge/csv_url.py +0 -124
- agno/knowledge/document.py +0 -223
- agno/knowledge/docx.py +0 -137
- agno/knowledge/firecrawl.py +0 -34
- agno/knowledge/gcs/__init__.py +0 -0
- agno/knowledge/gcs/base.py +0 -39
- agno/knowledge/gcs/pdf.py +0 -125
- agno/knowledge/json.py +0 -137
- agno/knowledge/langchain.py +0 -71
- agno/knowledge/light_rag.py +0 -273
- agno/knowledge/llamaindex.py +0 -66
- agno/knowledge/markdown.py +0 -154
- agno/knowledge/pdf.py +0 -164
- agno/knowledge/pdf_bytes.py +0 -42
- agno/knowledge/pdf_url.py +0 -148
- agno/knowledge/s3/__init__.py +0 -0
- agno/knowledge/s3/base.py +0 -64
- agno/knowledge/s3/pdf.py +0 -33
- agno/knowledge/s3/text.py +0 -34
- agno/knowledge/text.py +0 -141
- agno/knowledge/url.py +0 -46
- agno/knowledge/website.py +0 -179
- agno/knowledge/wikipedia.py +0 -32
- agno/knowledge/youtube.py +0 -35
- agno/memory/agent.py +0 -423
- agno/memory/classifier.py +0 -104
- agno/memory/db/__init__.py +0 -5
- 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 -22
- agno/memory/row.py +0 -36
- agno/memory/summarizer.py +0 -201
- agno/memory/summary.py +0 -19
- agno/memory/team.py +0 -415
- agno/memory/v2/__init__.py +0 -2
- agno/memory/v2/db/__init__.py +0 -1
- agno/memory/v2/db/base.py +0 -42
- agno/memory/v2/db/firestore.py +0 -339
- agno/memory/v2/db/mongodb.py +0 -196
- agno/memory/v2/db/postgres.py +0 -214
- agno/memory/v2/db/redis.py +0 -187
- agno/memory/v2/db/schema.py +0 -54
- agno/memory/v2/db/sqlite.py +0 -209
- agno/memory/v2/manager.py +0 -437
- agno/memory/v2/memory.py +0 -1097
- agno/memory/v2/schema.py +0 -55
- agno/memory/v2/summarizer.py +0 -215
- agno/memory/workflow.py +0 -38
- agno/models/ollama/tools.py +0 -430
- agno/models/qwen/__init__.py +0 -5
- agno/playground/__init__.py +0 -10
- agno/playground/deploy.py +0 -3
- agno/playground/playground.py +0 -3
- agno/playground/serve.py +0 -3
- agno/playground/settings.py +0 -3
- agno/reranker/__init__.py +0 -0
- agno/run/response.py +0 -467
- agno/run/v2/__init__.py +0 -0
- agno/run/v2/workflow.py +0 -567
- agno/storage/__init__.py +0 -0
- agno/storage/agent/__init__.py +0 -0
- agno/storage/agent/dynamodb.py +0 -1
- agno/storage/agent/json.py +0 -1
- agno/storage/agent/mongodb.py +0 -1
- agno/storage/agent/postgres.py +0 -1
- agno/storage/agent/singlestore.py +0 -1
- agno/storage/agent/sqlite.py +0 -1
- agno/storage/agent/yaml.py +0 -1
- agno/storage/base.py +0 -60
- agno/storage/dynamodb.py +0 -673
- agno/storage/firestore.py +0 -297
- agno/storage/gcs_json.py +0 -261
- agno/storage/in_memory.py +0 -234
- agno/storage/json.py +0 -237
- agno/storage/mongodb.py +0 -328
- agno/storage/mysql.py +0 -685
- agno/storage/postgres.py +0 -682
- agno/storage/redis.py +0 -336
- agno/storage/session/__init__.py +0 -16
- agno/storage/session/agent.py +0 -64
- agno/storage/session/team.py +0 -63
- agno/storage/session/v2/__init__.py +0 -5
- agno/storage/session/workflow.py +0 -61
- agno/storage/singlestore.py +0 -606
- agno/storage/sqlite.py +0 -646
- agno/storage/workflow/__init__.py +0 -0
- agno/storage/workflow/mongodb.py +0 -1
- agno/storage/workflow/postgres.py +0 -1
- agno/storage/workflow/sqlite.py +0 -1
- agno/storage/yaml.py +0 -241
- agno/tools/thinking.py +0 -73
- 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/workflow/v2/__init__.py +0 -21
- agno/workflow/v2/types.py +0 -357
- agno/workflow/v2/workflow.py +0 -3312
- agno/workspace/__init__.py +0 -0
- agno/workspace/config.py +0 -325
- agno/workspace/enums.py +0 -6
- agno/workspace/helpers.py +0 -52
- agno/workspace/operator.py +0 -757
- agno/workspace/settings.py +0 -158
- agno-1.8.1.dist-info/METADATA +0 -982
- agno-1.8.1.dist-info/RECORD +0 -566
- agno-1.8.1.dist-info/entry_points.txt +0 -3
- agno-1.8.1.dist-info/licenses/LICENSE +0 -375
- /agno/{app → db/migrations}/__init__.py +0 -0
- /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
- /agno/{cli → integrations}/__init__.py +0 -0
- /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
- /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
- /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
- /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
- /agno/{app → os/interfaces}/slack/security.py +0 -0
- /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
- /agno/{file/local → utils/print_response}/__init__.py +0 -0
- /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
- {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
- {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/top_level.txt +0 -0
agno/utils/log.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
from functools import lru_cache
|
|
2
3
|
from os import getenv
|
|
3
4
|
from typing import Any, Literal, Optional
|
|
4
5
|
|
|
@@ -52,18 +53,23 @@ class AgnoLogger(logging.Logger):
|
|
|
52
53
|
def __init__(self, name: str, level: int = logging.NOTSET):
|
|
53
54
|
super().__init__(name, level)
|
|
54
55
|
|
|
55
|
-
def debug(self, msg: str, center: bool = False, symbol: str = "*", *args, **kwargs):
|
|
56
|
+
def debug(self, msg: str, center: bool = False, symbol: str = "*", *args, **kwargs): # type: ignore
|
|
56
57
|
if center:
|
|
57
58
|
msg = center_header(str(msg), symbol)
|
|
58
59
|
super().debug(msg, *args, **kwargs)
|
|
59
60
|
|
|
60
|
-
def info(self, msg: str, center: bool = False, symbol: str = "*", *args, **kwargs):
|
|
61
|
+
def info(self, msg: str, center: bool = False, symbol: str = "*", *args, **kwargs): # type: ignore
|
|
61
62
|
if center:
|
|
62
63
|
msg = center_header(str(msg), symbol)
|
|
63
64
|
super().info(msg, *args, **kwargs)
|
|
64
65
|
|
|
65
66
|
|
|
66
67
|
def build_logger(logger_name: str, source_type: Optional[str] = None) -> Any:
|
|
68
|
+
# If a logger with the name "agno.{source_type}" is already set, we want to use that one
|
|
69
|
+
_logger = logging.getLogger(f"agno.{logger_name}")
|
|
70
|
+
if _logger.handlers or _logger.level != logging.NOTSET:
|
|
71
|
+
return _logger
|
|
72
|
+
|
|
67
73
|
# Set the custom logger class as the default for this logger
|
|
68
74
|
logging.setLoggerClass(AgnoLogger)
|
|
69
75
|
|
|
@@ -174,6 +180,12 @@ def use_workflow_logger():
|
|
|
174
180
|
logger = workflow_logger
|
|
175
181
|
|
|
176
182
|
|
|
183
|
+
@lru_cache(maxsize=128)
|
|
184
|
+
def _using_default_logger(logger_instance: Any) -> bool:
|
|
185
|
+
"""Return True if the currently active logger is our default AgnoLogger"""
|
|
186
|
+
return isinstance(logger_instance, AgnoLogger)
|
|
187
|
+
|
|
188
|
+
|
|
177
189
|
def log_debug(msg, center: bool = False, symbol: str = "*", log_level: Literal[1, 2] = 1, *args, **kwargs):
|
|
178
190
|
global logger
|
|
179
191
|
global debug_on
|
|
@@ -181,12 +193,18 @@ def log_debug(msg, center: bool = False, symbol: str = "*", log_level: Literal[1
|
|
|
181
193
|
|
|
182
194
|
if debug_on:
|
|
183
195
|
if debug_level >= log_level:
|
|
184
|
-
logger
|
|
196
|
+
if _using_default_logger(logger):
|
|
197
|
+
logger.debug(msg, center, symbol, *args, **kwargs)
|
|
198
|
+
else:
|
|
199
|
+
logger.debug(msg, *args, **kwargs)
|
|
185
200
|
|
|
186
201
|
|
|
187
202
|
def log_info(msg, center: bool = False, symbol: str = "*", *args, **kwargs):
|
|
188
203
|
global logger
|
|
189
|
-
logger
|
|
204
|
+
if _using_default_logger(logger):
|
|
205
|
+
logger.info(msg, center, symbol, *args, **kwargs)
|
|
206
|
+
else:
|
|
207
|
+
logger.info(msg, *args, **kwargs)
|
|
190
208
|
|
|
191
209
|
|
|
192
210
|
def log_warning(msg, *args, **kwargs):
|
|
@@ -202,3 +220,35 @@ def log_error(msg, *args, **kwargs):
|
|
|
202
220
|
def log_exception(msg, *args, **kwargs):
|
|
203
221
|
global logger
|
|
204
222
|
logger.exception(msg, *args, **kwargs)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def configure_agno_logging(
|
|
226
|
+
custom_default_logger: Optional[Any] = None,
|
|
227
|
+
custom_agent_logger: Optional[Any] = None,
|
|
228
|
+
custom_team_logger: Optional[Any] = None,
|
|
229
|
+
custom_workflow_logger: Optional[Any] = None,
|
|
230
|
+
) -> None:
|
|
231
|
+
"""
|
|
232
|
+
Util to set custom loggers. These will be used everywhere across the Agno library.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
custom_default_logger: Default logger to use (overrides agent_logger for default)
|
|
236
|
+
custom_agent_logger: Custom logger for agent operations
|
|
237
|
+
custom_team_logger: Custom logger for team operations
|
|
238
|
+
custom_workflow_logger: Custom logger for workflow operations
|
|
239
|
+
"""
|
|
240
|
+
if custom_default_logger is not None:
|
|
241
|
+
global logger
|
|
242
|
+
logger = custom_default_logger
|
|
243
|
+
|
|
244
|
+
if custom_agent_logger is not None:
|
|
245
|
+
global agent_logger
|
|
246
|
+
agent_logger = custom_agent_logger
|
|
247
|
+
|
|
248
|
+
if custom_team_logger is not None:
|
|
249
|
+
global team_logger
|
|
250
|
+
team_logger = custom_team_logger
|
|
251
|
+
|
|
252
|
+
if custom_workflow_logger is not None:
|
|
253
|
+
global workflow_logger
|
|
254
|
+
workflow_logger = custom_workflow_logger
|
agno/utils/mcp.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import json
|
|
1
2
|
from functools import partial
|
|
2
3
|
from uuid import uuid4
|
|
3
4
|
|
|
@@ -11,7 +12,8 @@ except (ImportError, ModuleNotFoundError):
|
|
|
11
12
|
raise ImportError("`mcp` not installed. Please install using `pip install mcp`")
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
from agno.media import
|
|
15
|
+
from agno.media import Image
|
|
16
|
+
from agno.tools.function import ToolResult
|
|
15
17
|
|
|
16
18
|
|
|
17
19
|
def get_entrypoint_for_tool(tool: MCPTool, session: ClientSession):
|
|
@@ -27,29 +29,82 @@ def get_entrypoint_for_tool(tool: MCPTool, session: ClientSession):
|
|
|
27
29
|
"""
|
|
28
30
|
from agno.agent import Agent
|
|
29
31
|
|
|
30
|
-
async def call_tool(agent: Agent, tool_name: str, **kwargs) ->
|
|
32
|
+
async def call_tool(agent: Agent, tool_name: str, **kwargs) -> ToolResult:
|
|
31
33
|
try:
|
|
32
34
|
log_debug(f"Calling MCP Tool '{tool_name}' with args: {kwargs}")
|
|
33
35
|
result: CallToolResult = await session.call_tool(tool_name, kwargs) # type: ignore
|
|
34
36
|
|
|
35
37
|
# Return an error if the tool call failed
|
|
36
38
|
if result.isError:
|
|
37
|
-
|
|
39
|
+
return ToolResult(content=f"Error from MCP tool '{tool_name}': {result.content}")
|
|
38
40
|
|
|
39
41
|
# Process the result content
|
|
40
42
|
response_str = ""
|
|
43
|
+
images = []
|
|
44
|
+
|
|
41
45
|
for content_item in result.content:
|
|
42
46
|
if isinstance(content_item, TextContent):
|
|
43
|
-
|
|
47
|
+
text_content = content_item.text
|
|
48
|
+
|
|
49
|
+
# Parse as JSON to check for custom image format
|
|
50
|
+
try:
|
|
51
|
+
parsed_json = json.loads(text_content)
|
|
52
|
+
if (
|
|
53
|
+
isinstance(parsed_json, dict)
|
|
54
|
+
and parsed_json.get("type") == "image"
|
|
55
|
+
and "data" in parsed_json
|
|
56
|
+
):
|
|
57
|
+
log_debug("Found custom JSON image format in TextContent")
|
|
58
|
+
|
|
59
|
+
# Extract image data
|
|
60
|
+
image_data = parsed_json.get("data")
|
|
61
|
+
mime_type = parsed_json.get("mimeType", "image/png")
|
|
62
|
+
|
|
63
|
+
if image_data and isinstance(image_data, str):
|
|
64
|
+
import base64
|
|
65
|
+
|
|
66
|
+
try:
|
|
67
|
+
image_bytes = base64.b64decode(image_data)
|
|
68
|
+
except Exception as e:
|
|
69
|
+
log_debug(f"Failed to decode base64 image data: {e}")
|
|
70
|
+
image_bytes = None
|
|
71
|
+
|
|
72
|
+
if image_bytes:
|
|
73
|
+
img_artifact = Image(
|
|
74
|
+
id=str(uuid4()),
|
|
75
|
+
url=None,
|
|
76
|
+
content=image_bytes,
|
|
77
|
+
mime_type=mime_type,
|
|
78
|
+
)
|
|
79
|
+
images.append(img_artifact)
|
|
80
|
+
response_str += "Image has been generated and added to the response.\n"
|
|
81
|
+
continue
|
|
82
|
+
|
|
83
|
+
except (json.JSONDecodeError, TypeError):
|
|
84
|
+
pass
|
|
85
|
+
|
|
86
|
+
response_str += text_content + "\n"
|
|
87
|
+
|
|
44
88
|
elif isinstance(content_item, ImageContent):
|
|
45
|
-
# Handle
|
|
46
|
-
|
|
89
|
+
# Handle standard MCP ImageContent
|
|
90
|
+
image_data = getattr(content_item, "data", None)
|
|
91
|
+
|
|
92
|
+
if image_data and isinstance(image_data, str):
|
|
93
|
+
import base64
|
|
94
|
+
|
|
95
|
+
try:
|
|
96
|
+
image_data = base64.b64decode(image_data)
|
|
97
|
+
except Exception as e:
|
|
98
|
+
log_debug(f"Failed to decode base64 image data: {e}")
|
|
99
|
+
image_data = None
|
|
100
|
+
|
|
101
|
+
img_artifact = Image(
|
|
47
102
|
id=str(uuid4()),
|
|
48
103
|
url=getattr(content_item, "url", None),
|
|
49
|
-
content=
|
|
104
|
+
content=image_data,
|
|
50
105
|
mime_type=getattr(content_item, "mimeType", "image/png"),
|
|
51
106
|
)
|
|
52
|
-
|
|
107
|
+
images.append(img_artifact)
|
|
53
108
|
response_str += "Image has been generated and added to the response.\n"
|
|
54
109
|
elif isinstance(content_item, EmbeddedResource):
|
|
55
110
|
# Handle embedded resources
|
|
@@ -58,9 +113,12 @@ def get_entrypoint_for_tool(tool: MCPTool, session: ClientSession):
|
|
|
58
113
|
# Handle other content types
|
|
59
114
|
response_str += f"[Unsupported content type: {content_item.type}]\n"
|
|
60
115
|
|
|
61
|
-
return
|
|
116
|
+
return ToolResult(
|
|
117
|
+
content=response_str.strip(),
|
|
118
|
+
images=images if images else None,
|
|
119
|
+
)
|
|
62
120
|
except Exception as e:
|
|
63
121
|
log_exception(f"Failed to call MCP tool '{tool_name}': {e}")
|
|
64
|
-
return f"Error: {e}"
|
|
122
|
+
return ToolResult(content=f"Error: {e}")
|
|
65
123
|
|
|
66
124
|
return partial(call_tool, tool_name=tool.name)
|
agno/utils/media.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import base64
|
|
2
|
+
import time
|
|
2
3
|
from enum import Enum
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
from typing import List
|
|
@@ -114,6 +115,44 @@ def save_base64_data(base64_data: str, output_path: str) -> bool:
|
|
|
114
115
|
raise Exception(f"An unexpected error occurred while saving data to '{output_path}': {e}")
|
|
115
116
|
|
|
116
117
|
|
|
118
|
+
def wait_for_media_ready(url: str, timeout: int = 120, interval: int = 5, verbose: bool = True) -> bool:
|
|
119
|
+
"""
|
|
120
|
+
Wait for media to be ready at URL by polling with HEAD requests.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
url (str): The URL to check for media availability
|
|
124
|
+
timeout (int): Maximum time to wait in seconds (default: 120)
|
|
125
|
+
interval (int): Seconds between each check (default: 5)
|
|
126
|
+
verbose (bool): Whether to print progress messages (default: True)
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
bool: True if media is ready, False if timeout reached
|
|
130
|
+
"""
|
|
131
|
+
max_attempts = timeout // interval
|
|
132
|
+
|
|
133
|
+
if verbose:
|
|
134
|
+
print("Media generated! Waiting for upload to complete...")
|
|
135
|
+
|
|
136
|
+
for attempt in range(max_attempts):
|
|
137
|
+
try:
|
|
138
|
+
response = httpx.head(url, timeout=10)
|
|
139
|
+
response.raise_for_status()
|
|
140
|
+
if verbose:
|
|
141
|
+
print(f"Media ready: {url}")
|
|
142
|
+
return True
|
|
143
|
+
except httpx.HTTPError:
|
|
144
|
+
pass
|
|
145
|
+
|
|
146
|
+
if verbose and (attempt + 1) % 3 == 0:
|
|
147
|
+
print(f"Still processing... ({(attempt + 1) * interval}s elapsed)")
|
|
148
|
+
|
|
149
|
+
time.sleep(interval)
|
|
150
|
+
|
|
151
|
+
if verbose:
|
|
152
|
+
print(f"Timeout waiting for media. Try this URL later: {url}")
|
|
153
|
+
return False
|
|
154
|
+
|
|
155
|
+
|
|
117
156
|
def download_knowledge_filters_sample_data(
|
|
118
157
|
num_files: int = 5, file_extension: SampleDataFileExtension = SampleDataFileExtension.DOCX
|
|
119
158
|
) -> List[str]:
|
agno/utils/message.py
CHANGED
|
@@ -7,6 +7,7 @@ from agno.models.message import Message
|
|
|
7
7
|
|
|
8
8
|
def get_text_from_message(message: Union[List, Dict, str, Message, BaseModel]) -> str:
|
|
9
9
|
"""Return the user texts from the message"""
|
|
10
|
+
import json
|
|
10
11
|
|
|
11
12
|
if isinstance(message, str):
|
|
12
13
|
return message
|
|
@@ -17,7 +18,15 @@ def get_text_from_message(message: Union[List, Dict, str, Message, BaseModel]) -
|
|
|
17
18
|
if len(message) == 0:
|
|
18
19
|
return ""
|
|
19
20
|
|
|
20
|
-
if
|
|
21
|
+
# Check if it's a list of Message objects
|
|
22
|
+
if isinstance(message[0], Message):
|
|
23
|
+
for m in message:
|
|
24
|
+
if isinstance(m, Message) and m.role == "user" and m.content is not None:
|
|
25
|
+
# Recursively extract text from the message content
|
|
26
|
+
content_text = get_text_from_message(m.content)
|
|
27
|
+
if content_text:
|
|
28
|
+
text_messages.append(content_text)
|
|
29
|
+
elif "type" in message[0]:
|
|
21
30
|
for m in message:
|
|
22
31
|
m_type = m.get("type")
|
|
23
32
|
if m_type is not None and isinstance(m_type, str):
|
|
@@ -42,6 +51,8 @@ def get_text_from_message(message: Union[List, Dict, str, Message, BaseModel]) -
|
|
|
42
51
|
if isinstance(message, dict):
|
|
43
52
|
if "content" in message:
|
|
44
53
|
return get_text_from_message(message["content"])
|
|
54
|
+
else:
|
|
55
|
+
return json.dumps(message, indent=2)
|
|
45
56
|
if isinstance(message, Message) and message.content is not None:
|
|
46
57
|
return get_text_from_message(message.content)
|
|
47
58
|
return ""
|
agno/utils/models/aws_claude.py
CHANGED
|
@@ -53,7 +53,7 @@ def _format_image_for_message(image: Image) -> Optional[Dict[str, Any]]:
|
|
|
53
53
|
try:
|
|
54
54
|
# Case 1: Image is a URL
|
|
55
55
|
if image.url is not None:
|
|
56
|
-
content_bytes = image.
|
|
56
|
+
content_bytes = image.get_content_bytes() # type: ignore
|
|
57
57
|
|
|
58
58
|
# Case 2: Image is a local file path
|
|
59
59
|
elif image.filepath is not None:
|
agno/utils/models/claude.py
CHANGED
|
@@ -246,21 +246,23 @@ def format_messages(messages: List[Message]) -> Tuple[List[Dict[str, str]], str]
|
|
|
246
246
|
elif message.role == "assistant":
|
|
247
247
|
content = []
|
|
248
248
|
|
|
249
|
-
if message.
|
|
249
|
+
if message.reasoning_content is not None and message.provider_data is not None:
|
|
250
250
|
from anthropic.types import RedactedThinkingBlock, ThinkingBlock
|
|
251
251
|
|
|
252
252
|
content.append(
|
|
253
253
|
ThinkingBlock(
|
|
254
|
-
thinking=message.
|
|
254
|
+
thinking=message.reasoning_content,
|
|
255
255
|
signature=message.provider_data.get("signature"),
|
|
256
256
|
type="thinking",
|
|
257
257
|
)
|
|
258
258
|
)
|
|
259
259
|
|
|
260
|
-
if message.
|
|
260
|
+
if message.redacted_reasoning_content is not None:
|
|
261
261
|
from anthropic.types import RedactedThinkingBlock
|
|
262
262
|
|
|
263
|
-
content.append(
|
|
263
|
+
content.append(
|
|
264
|
+
RedactedThinkingBlock(data=message.redacted_reasoning_content, type="redacted_reasoning_content")
|
|
265
|
+
)
|
|
264
266
|
|
|
265
267
|
if isinstance(message.content, str) and message.content and len(message.content.strip()) > 0:
|
|
266
268
|
content.append(TextBlock(text=message.content, type="text"))
|
|
@@ -284,3 +286,44 @@ def format_messages(messages: List[Message]) -> Tuple[List[Dict[str, str]], str]
|
|
|
284
286
|
|
|
285
287
|
chat_messages.append({"role": ROLE_MAP[message.role], "content": content}) # type: ignore
|
|
286
288
|
return chat_messages, " ".join(system_messages)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def format_tools_for_model(tools: Optional[List[Dict[str, Any]]] = None) -> Optional[List[Dict[str, Any]]]:
|
|
292
|
+
"""
|
|
293
|
+
Transforms function definitions into a format accepted by the Anthropic API.
|
|
294
|
+
"""
|
|
295
|
+
if not tools:
|
|
296
|
+
return None
|
|
297
|
+
|
|
298
|
+
parsed_tools: List[Dict[str, Any]] = []
|
|
299
|
+
for tool_def in tools:
|
|
300
|
+
if tool_def.get("type", "") != "function":
|
|
301
|
+
parsed_tools.append(tool_def)
|
|
302
|
+
continue
|
|
303
|
+
|
|
304
|
+
func_def = tool_def.get("function", {})
|
|
305
|
+
parameters: Dict[str, Any] = func_def.get("parameters", {})
|
|
306
|
+
properties: Dict[str, Any] = parameters.get("properties", {})
|
|
307
|
+
required: List[str] = parameters.get("required", [])
|
|
308
|
+
required_params: List[str] = required
|
|
309
|
+
|
|
310
|
+
input_properties: Dict[str, Any] = {}
|
|
311
|
+
for param_name, param_info in properties.items():
|
|
312
|
+
# Preserve the complete schema structure for complex types
|
|
313
|
+
input_properties[param_name] = param_info.copy()
|
|
314
|
+
|
|
315
|
+
# Ensure description is present (default to empty if missing)
|
|
316
|
+
if "description" not in input_properties[param_name]:
|
|
317
|
+
input_properties[param_name]["description"] = ""
|
|
318
|
+
|
|
319
|
+
tool = {
|
|
320
|
+
"name": func_def.get("name") or "",
|
|
321
|
+
"description": func_def.get("description") or "",
|
|
322
|
+
"input_schema": {
|
|
323
|
+
"type": parameters.get("type", "object"),
|
|
324
|
+
"properties": input_properties,
|
|
325
|
+
"required": required_params,
|
|
326
|
+
},
|
|
327
|
+
}
|
|
328
|
+
parsed_tools.append(tool)
|
|
329
|
+
return parsed_tools
|
agno/utils/models/cohere.py
CHANGED
|
@@ -20,7 +20,7 @@ def _format_images_for_message(message: Message, images: Sequence[Image]) -> Lis
|
|
|
20
20
|
if image.content is not None:
|
|
21
21
|
image_content = image.content
|
|
22
22
|
elif image.url is not None:
|
|
23
|
-
image_content = image.
|
|
23
|
+
image_content = image.get_content_bytes() # type: ignore
|
|
24
24
|
elif image.filepath is not None:
|
|
25
25
|
if isinstance(image.filepath, Path):
|
|
26
26
|
image_content = image.filepath.read_bytes()
|
agno/utils/models/mistral.py
CHANGED
|
@@ -5,13 +5,14 @@ from agno.models.message import Message
|
|
|
5
5
|
from agno.utils.log import log_error, log_warning
|
|
6
6
|
|
|
7
7
|
try:
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
# TODO: Adapt these imports to the new Mistral SDK versions
|
|
9
|
+
from mistralai.models import ( # type: ignore
|
|
10
|
+
AssistantMessage, # type: ignore
|
|
11
|
+
ImageURLChunk, # type: ignore
|
|
12
|
+
SystemMessage, # type: ignore
|
|
13
|
+
TextChunk, # type: ignore
|
|
14
|
+
ToolMessage, # type: ignore
|
|
15
|
+
UserMessage, # type: ignore
|
|
15
16
|
)
|
|
16
17
|
|
|
17
18
|
MistralMessage = Union[UserMessage, AssistantMessage, SystemMessage, ToolMessage]
|
|
@@ -135,19 +135,19 @@ def _normalize_generic(schema: Dict[str, Any]) -> Dict[str, Any]:
|
|
|
135
135
|
return schema
|
|
136
136
|
|
|
137
137
|
|
|
138
|
-
def get_response_schema_for_provider(
|
|
138
|
+
def get_response_schema_for_provider(output_schema: Type[BaseModel], provider: str) -> Dict[str, Any]:
|
|
139
139
|
"""
|
|
140
140
|
Get a properly formatted response schema for a specific model provider.
|
|
141
141
|
|
|
142
142
|
Args:
|
|
143
|
-
|
|
143
|
+
output_schema: Pydantic BaseModel class
|
|
144
144
|
provider: Model provider name
|
|
145
145
|
|
|
146
146
|
Returns:
|
|
147
147
|
Dict[str, Any]: Provider-specific schema
|
|
148
148
|
"""
|
|
149
149
|
# Generate the base schema
|
|
150
|
-
base_schema =
|
|
150
|
+
base_schema = output_schema.model_json_schema()
|
|
151
151
|
|
|
152
152
|
# Normalize for the specific provider
|
|
153
153
|
return normalize_schema_for_provider(base_schema, provider)
|
agno/utils/models/watsonx.py
CHANGED
|
@@ -19,7 +19,7 @@ def format_images_for_message(message: Message, images: Sequence[Image]) -> Mess
|
|
|
19
19
|
if image.content is not None:
|
|
20
20
|
image_content = image.content
|
|
21
21
|
elif image.url is not None:
|
|
22
|
-
image_content = image.
|
|
22
|
+
image_content = image.get_content_bytes() # type: ignore
|
|
23
23
|
else:
|
|
24
24
|
log_warning(f"Unsupported image format: {image}")
|
|
25
25
|
continue
|
agno/utils/openai.py
CHANGED
|
@@ -39,7 +39,7 @@ def audio_to_message(audio: Sequence[Audio]) -> List[Dict[str, Any]]:
|
|
|
39
39
|
|
|
40
40
|
# The audio is a URL
|
|
41
41
|
elif audio_snippet.url:
|
|
42
|
-
audio_bytes = audio_snippet.
|
|
42
|
+
audio_bytes = audio_snippet.get_content_bytes()
|
|
43
43
|
if audio_bytes is not None:
|
|
44
44
|
encoded_string = base64.b64encode(audio_bytes).decode("utf-8")
|
|
45
45
|
if not audio_format:
|
agno/utils/pprint.py
CHANGED
|
@@ -3,39 +3,40 @@ from typing import AsyncIterable, Iterable, Union, get_args
|
|
|
3
3
|
|
|
4
4
|
from pydantic import BaseModel
|
|
5
5
|
|
|
6
|
-
from agno.run.
|
|
7
|
-
from agno.run.team import
|
|
8
|
-
from agno.run.
|
|
6
|
+
from agno.run.agent import RunOutput, RunOutputEvent
|
|
7
|
+
from agno.run.team import TeamRunOutput, TeamRunOutputEvent
|
|
8
|
+
from agno.run.workflow import WorkflowRunOutput, WorkflowRunOutputEvent
|
|
9
9
|
from agno.utils.log import logger
|
|
10
10
|
from agno.utils.timer import Timer
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def pprint_run_response(
|
|
14
14
|
run_response: Union[
|
|
15
|
-
|
|
16
|
-
Iterable[
|
|
17
|
-
|
|
18
|
-
Iterable[
|
|
19
|
-
|
|
20
|
-
Iterable[
|
|
15
|
+
RunOutput,
|
|
16
|
+
Iterable[RunOutputEvent],
|
|
17
|
+
TeamRunOutput,
|
|
18
|
+
Iterable[TeamRunOutputEvent],
|
|
19
|
+
WorkflowRunOutput,
|
|
20
|
+
Iterable[WorkflowRunOutputEvent],
|
|
21
21
|
],
|
|
22
22
|
markdown: bool = False,
|
|
23
23
|
show_time: bool = False,
|
|
24
24
|
) -> None:
|
|
25
25
|
from rich.box import ROUNDED
|
|
26
|
+
from rich.console import Console
|
|
26
27
|
from rich.json import JSON
|
|
27
28
|
from rich.live import Live
|
|
28
29
|
from rich.markdown import Markdown
|
|
29
30
|
from rich.status import Status
|
|
30
31
|
from rich.table import Table
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
console = Console()
|
|
33
34
|
|
|
34
|
-
# If run_response is a single
|
|
35
|
+
# If run_response is a single RunOutput, wrap it in a list to make it iterable
|
|
35
36
|
if (
|
|
36
|
-
isinstance(run_response,
|
|
37
|
-
or isinstance(run_response,
|
|
38
|
-
or isinstance(run_response,
|
|
37
|
+
isinstance(run_response, RunOutput)
|
|
38
|
+
or isinstance(run_response, TeamRunOutput)
|
|
39
|
+
or isinstance(run_response, WorkflowRunOutput)
|
|
39
40
|
):
|
|
40
41
|
single_response_content: Union[str, JSON, Markdown] = ""
|
|
41
42
|
if isinstance(run_response.content, str):
|
|
@@ -66,9 +67,9 @@ def pprint_run_response(
|
|
|
66
67
|
for resp in run_response:
|
|
67
68
|
if (
|
|
68
69
|
(
|
|
69
|
-
isinstance(resp, tuple(get_args(
|
|
70
|
-
or isinstance(resp, tuple(get_args(
|
|
71
|
-
or isinstance(resp, tuple(get_args(
|
|
70
|
+
isinstance(resp, tuple(get_args(RunOutputEvent)))
|
|
71
|
+
or isinstance(resp, tuple(get_args(TeamRunOutputEvent)))
|
|
72
|
+
or isinstance(resp, tuple(get_args(WorkflowRunOutputEvent)))
|
|
72
73
|
)
|
|
73
74
|
and hasattr(resp, "content")
|
|
74
75
|
and resp.content is not None
|
|
@@ -95,30 +96,30 @@ def pprint_run_response(
|
|
|
95
96
|
|
|
96
97
|
async def apprint_run_response(
|
|
97
98
|
run_response: Union[
|
|
98
|
-
|
|
99
|
-
AsyncIterable[
|
|
100
|
-
|
|
101
|
-
AsyncIterable[
|
|
102
|
-
|
|
103
|
-
AsyncIterable[
|
|
99
|
+
RunOutput,
|
|
100
|
+
AsyncIterable[RunOutput],
|
|
101
|
+
TeamRunOutput,
|
|
102
|
+
AsyncIterable[TeamRunOutput],
|
|
103
|
+
WorkflowRunOutput,
|
|
104
|
+
AsyncIterable[WorkflowRunOutputEvent],
|
|
104
105
|
],
|
|
105
106
|
markdown: bool = False,
|
|
106
107
|
show_time: bool = False,
|
|
107
108
|
) -> None:
|
|
108
109
|
from rich.box import ROUNDED
|
|
110
|
+
from rich.console import Console
|
|
109
111
|
from rich.json import JSON
|
|
110
112
|
from rich.live import Live
|
|
111
113
|
from rich.markdown import Markdown
|
|
112
114
|
from rich.status import Status
|
|
113
115
|
from rich.table import Table
|
|
114
116
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
# If run_response is a single RunResponse, wrap it in a list to make it iterable
|
|
117
|
+
console = Console()
|
|
118
|
+
# If run_response is a single RunOutput, wrap it in a list to make it iterable
|
|
118
119
|
if (
|
|
119
|
-
isinstance(run_response,
|
|
120
|
-
or isinstance(run_response,
|
|
121
|
-
or isinstance(run_response,
|
|
120
|
+
isinstance(run_response, RunOutput)
|
|
121
|
+
or isinstance(run_response, TeamRunOutput)
|
|
122
|
+
or isinstance(run_response, WorkflowRunOutput)
|
|
122
123
|
):
|
|
123
124
|
single_response_content: Union[str, JSON, Markdown] = ""
|
|
124
125
|
if isinstance(run_response.content, str):
|
|
@@ -150,9 +151,9 @@ async def apprint_run_response(
|
|
|
150
151
|
async for resp in run_response:
|
|
151
152
|
if (
|
|
152
153
|
(
|
|
153
|
-
isinstance(resp, tuple(get_args(
|
|
154
|
-
or isinstance(resp, tuple(get_args(
|
|
155
|
-
or isinstance(resp, tuple(get_args(
|
|
154
|
+
isinstance(resp, tuple(get_args(RunOutputEvent)))
|
|
155
|
+
or isinstance(resp, tuple(get_args(TeamRunOutputEvent)))
|
|
156
|
+
or isinstance(resp, tuple(get_args(WorkflowRunOutputEvent)))
|
|
156
157
|
)
|
|
157
158
|
and hasattr(resp, "content")
|
|
158
159
|
and resp.content is not None
|