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
agno/utils/string.py
CHANGED
|
@@ -1,6 +1,51 @@
|
|
|
1
1
|
import hashlib
|
|
2
2
|
import json
|
|
3
|
-
|
|
3
|
+
import re
|
|
4
|
+
import uuid
|
|
5
|
+
from typing import Optional, Type
|
|
6
|
+
from uuid import uuid4
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel, ValidationError
|
|
9
|
+
|
|
10
|
+
from agno.utils.log import logger
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def is_valid_uuid(uuid_str: str) -> bool:
|
|
14
|
+
"""
|
|
15
|
+
Check if a string is a valid UUID
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
uuid_str: String to check
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
bool: True if string is a valid UUID, False otherwise
|
|
22
|
+
"""
|
|
23
|
+
from uuid import UUID
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
UUID(str(uuid_str))
|
|
27
|
+
return True
|
|
28
|
+
except (ValueError, AttributeError, TypeError):
|
|
29
|
+
return False
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def url_safe_string(input_string):
|
|
33
|
+
# Replace spaces with dashes
|
|
34
|
+
safe_string = input_string.replace(" ", "-")
|
|
35
|
+
|
|
36
|
+
# Convert camelCase to kebab-case
|
|
37
|
+
safe_string = re.sub(r"([a-z0-9])([A-Z])", r"\1-\2", safe_string).lower()
|
|
38
|
+
|
|
39
|
+
# Convert snake_case to kebab-case
|
|
40
|
+
safe_string = safe_string.replace("_", "-")
|
|
41
|
+
|
|
42
|
+
# Remove special characters, keeping alphanumeric, dashes, and dots
|
|
43
|
+
safe_string = re.sub(r"[^\w\-.]", "", safe_string)
|
|
44
|
+
|
|
45
|
+
# Ensure no consecutive dashes
|
|
46
|
+
safe_string = re.sub(r"-+", "-", safe_string)
|
|
47
|
+
|
|
48
|
+
return safe_string
|
|
4
49
|
|
|
5
50
|
|
|
6
51
|
def hash_string_sha256(input_string):
|
|
@@ -19,60 +64,168 @@ def hash_string_sha256(input_string):
|
|
|
19
64
|
return hex_digest
|
|
20
65
|
|
|
21
66
|
|
|
22
|
-
def
|
|
67
|
+
def _extract_json_objects(text: str) -> list[str]:
|
|
68
|
+
objs: list[str] = []
|
|
69
|
+
brace_depth = 0
|
|
70
|
+
start_idx: Optional[int] = None
|
|
71
|
+
for idx, ch in enumerate(text):
|
|
72
|
+
if ch == "{" and brace_depth == 0:
|
|
73
|
+
start_idx = idx
|
|
74
|
+
if ch == "{":
|
|
75
|
+
brace_depth += 1
|
|
76
|
+
elif ch == "}":
|
|
77
|
+
brace_depth -= 1
|
|
78
|
+
if brace_depth == 0 and start_idx is not None:
|
|
79
|
+
objs.append(text[start_idx : idx + 1])
|
|
80
|
+
start_idx = None
|
|
81
|
+
return objs
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _clean_json_content(content: str) -> str:
|
|
85
|
+
"""Clean and prepare JSON content for parsing."""
|
|
86
|
+
# Handle code blocks
|
|
87
|
+
if "```json" in content:
|
|
88
|
+
content = content.split("```json")[-1].strip()
|
|
89
|
+
parts = content.split("```")
|
|
90
|
+
parts.pop(-1)
|
|
91
|
+
content = "".join(parts)
|
|
92
|
+
elif "```" in content:
|
|
93
|
+
content = content.split("```")[1].strip()
|
|
94
|
+
|
|
95
|
+
# Replace markdown formatting like *"name"* or `"name"` with "name"
|
|
96
|
+
content = re.sub(r'[*`#]?"([A-Za-z0-9_]+)"[*`#]?', r'"\1"', content)
|
|
97
|
+
|
|
98
|
+
# Handle newlines and control characters
|
|
99
|
+
content = content.replace("\n", " ").replace("\r", "")
|
|
100
|
+
content = re.sub(r"[\x00-\x1F\x7F]", "", content)
|
|
101
|
+
|
|
102
|
+
# Escape quotes only in values, not keys
|
|
103
|
+
def escape_quotes_in_values(match):
|
|
104
|
+
key = match.group(1)
|
|
105
|
+
value = match.group(2)
|
|
106
|
+
|
|
107
|
+
if '\\"' in value:
|
|
108
|
+
unescaped_value = value.replace('\\"', '"')
|
|
109
|
+
escaped_value = unescaped_value.replace('"', '\\"')
|
|
110
|
+
else:
|
|
111
|
+
escaped_value = value.replace('"', '\\"')
|
|
112
|
+
|
|
113
|
+
return f'"{key}": "{escaped_value}'
|
|
114
|
+
|
|
115
|
+
# Find and escape quotes in field values
|
|
116
|
+
content = re.sub(r'"(?P<key>[^"]+)"\s*:\s*"(?P<value>.*?)(?="\s*(?:,|\}))', escape_quotes_in_values, content)
|
|
117
|
+
|
|
118
|
+
return content
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _parse_individual_json(content: str, output_schema: Type[BaseModel]) -> Optional[BaseModel]:
|
|
122
|
+
"""Parse individual JSON objects from content and merge them based on response model fields."""
|
|
123
|
+
candidate_jsons = _extract_json_objects(content)
|
|
124
|
+
merged_data: dict = {}
|
|
125
|
+
|
|
126
|
+
# Get the expected fields from the response model
|
|
127
|
+
model_fields = output_schema.model_fields if hasattr(output_schema, "model_fields") else {}
|
|
128
|
+
|
|
129
|
+
for candidate in candidate_jsons:
|
|
130
|
+
try:
|
|
131
|
+
candidate_obj = json.loads(candidate)
|
|
132
|
+
except json.JSONDecodeError:
|
|
133
|
+
continue
|
|
134
|
+
|
|
135
|
+
if isinstance(candidate_obj, dict):
|
|
136
|
+
# Merge data based on model fields
|
|
137
|
+
for field_name, field_info in model_fields.items():
|
|
138
|
+
if field_name in candidate_obj:
|
|
139
|
+
field_value = candidate_obj[field_name]
|
|
140
|
+
# If field is a list, extend it; otherwise, use the latest value
|
|
141
|
+
if isinstance(field_value, list):
|
|
142
|
+
if field_name not in merged_data:
|
|
143
|
+
merged_data[field_name] = []
|
|
144
|
+
merged_data[field_name].extend(field_value)
|
|
145
|
+
else:
|
|
146
|
+
merged_data[field_name] = field_value
|
|
147
|
+
|
|
148
|
+
if not merged_data:
|
|
149
|
+
return None
|
|
150
|
+
|
|
151
|
+
try:
|
|
152
|
+
return output_schema.model_validate(merged_data)
|
|
153
|
+
except ValidationError as e:
|
|
154
|
+
logger.warning("Validation failed on merged data: %s", e)
|
|
155
|
+
return None
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def parse_response_model_str(content: str, output_schema: Type[BaseModel]) -> Optional[BaseModel]:
|
|
159
|
+
structured_output = None
|
|
160
|
+
|
|
161
|
+
# Extract thinking content first to prevent <think> tags from corrupting JSON
|
|
162
|
+
from agno.utils.reasoning import extract_thinking_content
|
|
163
|
+
|
|
164
|
+
# handle thinking content b/w <think> tags
|
|
165
|
+
if "</think>" in content:
|
|
166
|
+
reasoning_content, output_content = extract_thinking_content(content)
|
|
167
|
+
if reasoning_content:
|
|
168
|
+
content = output_content
|
|
169
|
+
|
|
170
|
+
# Clean content first to simplify all parsing attempts
|
|
171
|
+
cleaned_content = _clean_json_content(content)
|
|
172
|
+
|
|
173
|
+
try:
|
|
174
|
+
# First attempt: direct JSON validation on cleaned content
|
|
175
|
+
structured_output = output_schema.model_validate_json(cleaned_content)
|
|
176
|
+
except (ValidationError, json.JSONDecodeError):
|
|
177
|
+
try:
|
|
178
|
+
# Second attempt: Parse as Python dict
|
|
179
|
+
data = json.loads(cleaned_content)
|
|
180
|
+
structured_output = output_schema.model_validate(data)
|
|
181
|
+
except (ValidationError, json.JSONDecodeError) as e:
|
|
182
|
+
logger.warning(f"Failed to parse cleaned JSON: {e}")
|
|
183
|
+
|
|
184
|
+
# Third attempt: Extract individual JSON objects
|
|
185
|
+
candidate_jsons = _extract_json_objects(cleaned_content)
|
|
186
|
+
|
|
187
|
+
if len(candidate_jsons) == 1:
|
|
188
|
+
# Single JSON object - try to parse it directly
|
|
189
|
+
try:
|
|
190
|
+
data = json.loads(candidate_jsons[0])
|
|
191
|
+
structured_output = output_schema.model_validate(data)
|
|
192
|
+
except (ValidationError, json.JSONDecodeError):
|
|
193
|
+
pass
|
|
194
|
+
|
|
195
|
+
if structured_output is None:
|
|
196
|
+
# Final attempt: Handle concatenated JSON objects with field merging
|
|
197
|
+
structured_output = _parse_individual_json(cleaned_content, output_schema)
|
|
198
|
+
if structured_output is None:
|
|
199
|
+
logger.warning("All parsing attempts failed.")
|
|
200
|
+
|
|
201
|
+
return structured_output
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def generate_id(seed: Optional[str] = None) -> str:
|
|
23
205
|
"""
|
|
24
|
-
|
|
25
|
-
|
|
206
|
+
Generate a deterministic UUID5 based on a seed string.
|
|
207
|
+
If no seed is provided, generate a random UUID4.
|
|
26
208
|
|
|
27
209
|
Args:
|
|
28
|
-
|
|
210
|
+
seed (str): The seed string to generate the UUID from.
|
|
29
211
|
|
|
30
212
|
Returns:
|
|
31
|
-
|
|
32
|
-
- Extracted JSON dictionary if valid, else None.
|
|
33
|
-
- The rest of the string without the extracted JSON.
|
|
213
|
+
str: A deterministic UUID5 string.
|
|
34
214
|
"""
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if start_idx == -1:
|
|
40
|
-
# No more '{' found; stop searching
|
|
41
|
-
return None
|
|
42
|
-
|
|
43
|
-
# Track brace depth
|
|
44
|
-
brace_depth = 0
|
|
45
|
-
# This will store the end of the matching closing brace once found
|
|
46
|
-
end_idx = None
|
|
47
|
-
|
|
48
|
-
for i in range(start_idx, len(content)):
|
|
49
|
-
char = content[i]
|
|
50
|
-
if char == "{":
|
|
51
|
-
brace_depth += 1
|
|
52
|
-
elif char == "}":
|
|
53
|
-
brace_depth -= 1
|
|
54
|
-
|
|
55
|
-
# If brace_depth returns to 0, we’ve found a potential JSON substring
|
|
56
|
-
if brace_depth == 0:
|
|
57
|
-
end_idx = i
|
|
58
|
-
break
|
|
59
|
-
|
|
60
|
-
# If we never returned to depth 0, it means we couldn't find a matching '}'
|
|
61
|
-
if end_idx is None:
|
|
62
|
-
return None
|
|
63
|
-
|
|
64
|
-
# Extract the candidate substring
|
|
65
|
-
candidate = content[start_idx : end_idx + 1]
|
|
66
|
-
|
|
67
|
-
# Try to parse it
|
|
68
|
-
try:
|
|
69
|
-
parsed = json.loads(candidate)
|
|
70
|
-
# If parsed successfully, check if it's a dict
|
|
71
|
-
if isinstance(parsed, dict):
|
|
72
|
-
return parsed
|
|
73
|
-
except json.JSONDecodeError:
|
|
74
|
-
# Not valid JSON, keep going
|
|
75
|
-
pass
|
|
215
|
+
if seed is None:
|
|
216
|
+
return str(uuid4())
|
|
217
|
+
return str(uuid.uuid5(uuid.NAMESPACE_DNS, seed))
|
|
218
|
+
|
|
76
219
|
|
|
77
|
-
|
|
78
|
-
|
|
220
|
+
def generate_id_from_name(name: Optional[str] = None) -> str:
|
|
221
|
+
"""
|
|
222
|
+
Generate a deterministic ID from a name string.
|
|
223
|
+
If no name is provided, generate a random UUID4.
|
|
224
|
+
|
|
225
|
+
Args:
|
|
226
|
+
name (str): The name string to generate the ID from.
|
|
227
|
+
"""
|
|
228
|
+
if name:
|
|
229
|
+
return name.lower().replace(" ", "-").replace("_", "-")
|
|
230
|
+
else:
|
|
231
|
+
return str(uuid4())
|
agno/utils/team.py
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
|
|
2
|
+
|
|
3
|
+
from agno.agent import Agent
|
|
4
|
+
from agno.media import Audio, File, Image, Video
|
|
5
|
+
from agno.run.agent import RunOutput
|
|
6
|
+
from agno.run.team import TeamRunOutput
|
|
7
|
+
from agno.utils.log import log_debug
|
|
8
|
+
from agno.utils.string import is_valid_uuid, url_safe_string
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from agno.team.team import Team
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def format_member_agent_task(
|
|
15
|
+
task_description: str,
|
|
16
|
+
team_member_interactions_str: Optional[str] = None,
|
|
17
|
+
team_history_str: Optional[str] = None,
|
|
18
|
+
) -> str:
|
|
19
|
+
member_task_str = ""
|
|
20
|
+
|
|
21
|
+
if team_member_interactions_str:
|
|
22
|
+
member_task_str += f"{team_member_interactions_str}\n\n"
|
|
23
|
+
|
|
24
|
+
if team_history_str:
|
|
25
|
+
member_task_str += f"{team_history_str}\n\n"
|
|
26
|
+
|
|
27
|
+
member_task_str += f"{task_description}"
|
|
28
|
+
|
|
29
|
+
return member_task_str
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_member_id(member: Union[Agent, "Team"]) -> str:
|
|
33
|
+
"""
|
|
34
|
+
Get the ID of a member
|
|
35
|
+
|
|
36
|
+
If the member has an agent_id or team_id, use that if it is not a valid UUID.
|
|
37
|
+
Then if the member has a name, convert that to a URL safe string.
|
|
38
|
+
Then if the member has the default UUID ID, use that.
|
|
39
|
+
Otherwise, return None.
|
|
40
|
+
"""
|
|
41
|
+
from agno.team.team import Team
|
|
42
|
+
|
|
43
|
+
if isinstance(member, Agent) and member.id is not None and (not is_valid_uuid(member.id)):
|
|
44
|
+
url_safe_member_id = url_safe_string(member.id)
|
|
45
|
+
elif isinstance(member, Team) and member.id is not None and (not is_valid_uuid(member.id)):
|
|
46
|
+
url_safe_member_id = url_safe_string(member.id)
|
|
47
|
+
elif member.name is not None:
|
|
48
|
+
url_safe_member_id = url_safe_string(member.name)
|
|
49
|
+
elif isinstance(member, Agent) and member.id is not None:
|
|
50
|
+
url_safe_member_id = member.id
|
|
51
|
+
elif isinstance(member, Team) and member.id is not None:
|
|
52
|
+
url_safe_member_id = member.id
|
|
53
|
+
else:
|
|
54
|
+
url_safe_member_id = None
|
|
55
|
+
return url_safe_member_id
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def add_interaction_to_team_run_context(
|
|
59
|
+
team_run_context: Dict[str, Any],
|
|
60
|
+
member_name: str,
|
|
61
|
+
task: str,
|
|
62
|
+
run_response: Union[RunOutput, TeamRunOutput],
|
|
63
|
+
) -> None:
|
|
64
|
+
if "member_responses" not in team_run_context:
|
|
65
|
+
team_run_context["member_responses"] = []
|
|
66
|
+
team_run_context["member_responses"].append(
|
|
67
|
+
{
|
|
68
|
+
"member_name": member_name,
|
|
69
|
+
"task": task,
|
|
70
|
+
"run_response": run_response,
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
log_debug(f"Updated team run context with member name: {member_name}")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def get_team_member_interactions_str(team_run_context: Dict[str, Any]) -> str:
|
|
77
|
+
if not team_run_context:
|
|
78
|
+
return ""
|
|
79
|
+
team_member_interactions_str = ""
|
|
80
|
+
if "member_responses" in team_run_context:
|
|
81
|
+
team_member_interactions_str += "<member_interaction_context>\nSee below interactions wit other team members.\n"
|
|
82
|
+
|
|
83
|
+
for interaction in team_run_context["member_responses"]:
|
|
84
|
+
response_dict = interaction["run_response"].to_dict()
|
|
85
|
+
response_content = (
|
|
86
|
+
response_dict.get("content")
|
|
87
|
+
or ",".join([tool.get("content", "") for tool in response_dict.get("tools", [])])
|
|
88
|
+
or ""
|
|
89
|
+
)
|
|
90
|
+
team_member_interactions_str += f"Member: {interaction['member_name']}\n"
|
|
91
|
+
team_member_interactions_str += f"Task: {interaction['task']}\n"
|
|
92
|
+
team_member_interactions_str += f"Response: {response_content}\n"
|
|
93
|
+
team_member_interactions_str += "\n"
|
|
94
|
+
team_member_interactions_str += "</member_interaction_context>\n"
|
|
95
|
+
return team_member_interactions_str
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def get_team_run_context_images(team_run_context: Dict[str, Any]) -> List[Image]:
|
|
99
|
+
if not team_run_context:
|
|
100
|
+
return []
|
|
101
|
+
images = []
|
|
102
|
+
if "member_responses" in team_run_context:
|
|
103
|
+
for interaction in team_run_context["member_responses"]:
|
|
104
|
+
if interaction["run_response"].images:
|
|
105
|
+
images.extend(interaction["run_response"].images)
|
|
106
|
+
return images
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def get_team_run_context_videos(team_run_context: Dict[str, Any]) -> List[Video]:
|
|
110
|
+
if not team_run_context:
|
|
111
|
+
return []
|
|
112
|
+
videos = []
|
|
113
|
+
if "member_responses" in team_run_context:
|
|
114
|
+
for interaction in team_run_context["member_responses"]:
|
|
115
|
+
if interaction["run_response"].videos:
|
|
116
|
+
videos.extend(interaction["run_response"].videos)
|
|
117
|
+
return videos
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def get_team_run_context_audio(team_run_context: Dict[str, Any]) -> List[Audio]:
|
|
121
|
+
if not team_run_context:
|
|
122
|
+
return []
|
|
123
|
+
audio = []
|
|
124
|
+
if "member_responses" in team_run_context:
|
|
125
|
+
for interaction in team_run_context["member_responses"]:
|
|
126
|
+
if interaction["run_response"].audio:
|
|
127
|
+
audio.extend(interaction["run_response"].audio)
|
|
128
|
+
return audio
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def get_team_run_context_files(team_run_context: Dict[str, Any]) -> List[File]:
|
|
132
|
+
if not team_run_context:
|
|
133
|
+
return []
|
|
134
|
+
files = []
|
|
135
|
+
if "member_responses" in team_run_context:
|
|
136
|
+
for interaction in team_run_context["member_responses"]:
|
|
137
|
+
if interaction["run_response"].files:
|
|
138
|
+
files.extend(interaction["run_response"].files)
|
|
139
|
+
return files
|
agno/utils/timer.py
CHANGED
|
@@ -24,11 +24,18 @@ class Timer:
|
|
|
24
24
|
self.elapsed_time = self.end_time - self.start_time
|
|
25
25
|
return self.end_time
|
|
26
26
|
|
|
27
|
-
def __enter__(self):
|
|
27
|
+
def __enter__(self) -> "Timer":
|
|
28
28
|
self.start_time = perf_counter()
|
|
29
29
|
return self
|
|
30
30
|
|
|
31
|
-
def __exit__(self, *args):
|
|
31
|
+
def __exit__(self, *args) -> None:
|
|
32
32
|
self.end_time = perf_counter()
|
|
33
33
|
if self.start_time is not None:
|
|
34
34
|
self.elapsed_time = self.end_time - self.start_time
|
|
35
|
+
|
|
36
|
+
def to_dict(self):
|
|
37
|
+
return {
|
|
38
|
+
"start_time": str(self.start_time) if self.start_time is not None else None,
|
|
39
|
+
"end_time": str(self.end_time) if self.end_time is not None else None,
|
|
40
|
+
"elapsed": self.elapsed,
|
|
41
|
+
}
|