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/cloud/aws/base.py
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
from typing import Any, Optional
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, ConfigDict
|
|
4
|
+
|
|
5
|
+
from agno.cloud.aws.s3.api_client import AwsApiClient
|
|
6
|
+
from agno.utils.log import logger
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AwsResource(BaseModel):
|
|
10
|
+
"""Base class for AWS Resources."""
|
|
11
|
+
|
|
12
|
+
# Resource name (required)
|
|
13
|
+
name: str
|
|
14
|
+
|
|
15
|
+
# Resource type
|
|
16
|
+
resource_type: Optional[str] = None
|
|
17
|
+
active_resource: Optional[Any] = None
|
|
18
|
+
|
|
19
|
+
skip_delete: bool = False
|
|
20
|
+
skip_create: bool = False
|
|
21
|
+
skip_read: bool = False
|
|
22
|
+
skip_update: bool = False
|
|
23
|
+
|
|
24
|
+
wait_for_create: bool = True
|
|
25
|
+
wait_for_update: bool = True
|
|
26
|
+
wait_for_delete: bool = True
|
|
27
|
+
waiter_delay: int = 30
|
|
28
|
+
waiter_max_attempts: int = 50
|
|
29
|
+
save_output: bool = False
|
|
30
|
+
use_cache: bool = True
|
|
31
|
+
|
|
32
|
+
service_name: str
|
|
33
|
+
service_client: Optional[Any] = None
|
|
34
|
+
service_resource: Optional[Any] = None
|
|
35
|
+
|
|
36
|
+
aws_region: Optional[str] = None
|
|
37
|
+
aws_profile: Optional[str] = None
|
|
38
|
+
|
|
39
|
+
aws_client: Optional[AwsApiClient] = None
|
|
40
|
+
|
|
41
|
+
model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True)
|
|
42
|
+
|
|
43
|
+
def get_resource_name(self) -> str:
|
|
44
|
+
return self.name or self.__class__.__name__
|
|
45
|
+
|
|
46
|
+
def get_resource_type(self) -> str:
|
|
47
|
+
if self.resource_type is None:
|
|
48
|
+
return self.__class__.__name__
|
|
49
|
+
return self.resource_type
|
|
50
|
+
|
|
51
|
+
def get_service_client(self, aws_client: AwsApiClient):
|
|
52
|
+
from boto3 import session
|
|
53
|
+
|
|
54
|
+
if self.service_client is None:
|
|
55
|
+
boto3_session: session = aws_client.boto3_session
|
|
56
|
+
self.service_client = boto3_session.client(service_name=self.service_name)
|
|
57
|
+
return self.service_client
|
|
58
|
+
|
|
59
|
+
def get_service_resource(self, aws_client: AwsApiClient):
|
|
60
|
+
from boto3 import session
|
|
61
|
+
|
|
62
|
+
if self.service_resource is None:
|
|
63
|
+
boto3_session: session = aws_client.boto3_session
|
|
64
|
+
self.service_resource = boto3_session.resource(service_name=self.service_name)
|
|
65
|
+
return self.service_resource
|
|
66
|
+
|
|
67
|
+
def get_aws_region(self) -> Optional[str]:
|
|
68
|
+
if self.aws_region:
|
|
69
|
+
return self.aws_region
|
|
70
|
+
|
|
71
|
+
from os import getenv
|
|
72
|
+
|
|
73
|
+
aws_region_env = getenv("AWS_REGION")
|
|
74
|
+
if aws_region_env is not None:
|
|
75
|
+
logger.debug(f"{'AWS_REGION'}: {aws_region_env}")
|
|
76
|
+
self.aws_region = aws_region_env
|
|
77
|
+
return self.aws_region
|
|
78
|
+
|
|
79
|
+
def get_aws_profile(self) -> Optional[str]:
|
|
80
|
+
if self.aws_profile:
|
|
81
|
+
return self.aws_profile
|
|
82
|
+
|
|
83
|
+
from os import getenv
|
|
84
|
+
|
|
85
|
+
aws_profile_env = getenv("AWS_PROFILE")
|
|
86
|
+
if aws_profile_env is not None:
|
|
87
|
+
logger.debug(f"{'AWS_PROFILE'}: {aws_profile_env}")
|
|
88
|
+
self.aws_profile = aws_profile_env
|
|
89
|
+
return self.aws_profile
|
|
90
|
+
|
|
91
|
+
def get_aws_client(self) -> AwsApiClient:
|
|
92
|
+
if self.aws_client is not None:
|
|
93
|
+
return self.aws_client
|
|
94
|
+
self.aws_client = AwsApiClient(aws_region=self.get_aws_region(), aws_profile=self.get_aws_profile())
|
|
95
|
+
return self.aws_client
|
|
96
|
+
|
|
97
|
+
def _read(self, aws_client: AwsApiClient) -> Any:
|
|
98
|
+
logger.warning(f"@_read method not defined for {self.get_resource_name()}")
|
|
99
|
+
return True
|
|
100
|
+
|
|
101
|
+
def read(self, aws_client: Optional[AwsApiClient] = None) -> Any:
|
|
102
|
+
"""Reads the resource from Aws"""
|
|
103
|
+
# Step 1: Use cached value if available
|
|
104
|
+
if self.use_cache and self.active_resource is not None:
|
|
105
|
+
return self.active_resource
|
|
106
|
+
|
|
107
|
+
# Step 2: Skip resource creation if skip_read = True
|
|
108
|
+
if self.skip_read:
|
|
109
|
+
print(f"Skipping read: {self.get_resource_name()}")
|
|
110
|
+
return True
|
|
111
|
+
|
|
112
|
+
# Step 3: Read resource
|
|
113
|
+
client: AwsApiClient = aws_client or self.get_aws_client()
|
|
114
|
+
return self._read(client)
|
|
115
|
+
|
|
116
|
+
def is_active(self, aws_client: AwsApiClient) -> bool:
|
|
117
|
+
"""Returns True if the resource is active on Aws"""
|
|
118
|
+
_resource = self.read(aws_client=aws_client)
|
|
119
|
+
return True if _resource is not None else False
|
|
120
|
+
|
|
121
|
+
def _create(self, aws_client: AwsApiClient) -> bool:
|
|
122
|
+
logger.warning(f"@_create method not defined for {self.get_resource_name()}")
|
|
123
|
+
return True
|
|
124
|
+
|
|
125
|
+
def create(self, aws_client: Optional[AwsApiClient] = None) -> bool:
|
|
126
|
+
"""Creates the resource on Aws"""
|
|
127
|
+
|
|
128
|
+
# Step 1: Skip resource creation if skip_create = True
|
|
129
|
+
if self.skip_create:
|
|
130
|
+
print(f"Skipping create: {self.get_resource_name()}")
|
|
131
|
+
return True
|
|
132
|
+
|
|
133
|
+
# Step 2: Check if resource is active and use_cache = True
|
|
134
|
+
client: AwsApiClient = aws_client or self.get_aws_client()
|
|
135
|
+
if self.use_cache and self.is_active(client):
|
|
136
|
+
self.resource_created = True
|
|
137
|
+
print(f"{self.get_resource_type()}: {self.get_resource_name()} already exists")
|
|
138
|
+
# Step 3: Create the resource
|
|
139
|
+
else:
|
|
140
|
+
self.resource_created = self._create(client)
|
|
141
|
+
if self.resource_created:
|
|
142
|
+
print(f"{self.get_resource_type()}: {self.get_resource_name()} created")
|
|
143
|
+
|
|
144
|
+
# Step 4: Run post create steps
|
|
145
|
+
if self.resource_created:
|
|
146
|
+
logger.debug(f"Running post-create for {self.get_resource_type()}: {self.get_resource_name()}")
|
|
147
|
+
return self.post_create(client)
|
|
148
|
+
logger.error(f"Failed to create {self.get_resource_type()}: {self.get_resource_name()}")
|
|
149
|
+
return self.resource_created
|
|
150
|
+
|
|
151
|
+
def post_create(self, aws_client: AwsApiClient) -> bool:
|
|
152
|
+
return True
|
|
153
|
+
|
|
154
|
+
def _update(self, aws_client: AwsApiClient) -> Any:
|
|
155
|
+
logger.warning(f"@_update method not defined for {self.get_resource_name()}")
|
|
156
|
+
return True
|
|
157
|
+
|
|
158
|
+
def update(self, aws_client: Optional[AwsApiClient] = None) -> bool:
|
|
159
|
+
"""Updates the resource on Aws"""
|
|
160
|
+
|
|
161
|
+
# Step 1: Skip resource update if skip_update = True
|
|
162
|
+
if self.skip_update:
|
|
163
|
+
print(f"Skipping update: {self.get_resource_name()}")
|
|
164
|
+
return True
|
|
165
|
+
|
|
166
|
+
# Step 2: Update the resource
|
|
167
|
+
client: AwsApiClient = aws_client or self.get_aws_client()
|
|
168
|
+
if self.is_active(client):
|
|
169
|
+
self.resource_updated = self._update(client)
|
|
170
|
+
else:
|
|
171
|
+
print(f"{self.get_resource_type()}: {self.get_resource_name()} does not exist")
|
|
172
|
+
return True
|
|
173
|
+
|
|
174
|
+
# Step 3: Run post update steps
|
|
175
|
+
if self.resource_updated:
|
|
176
|
+
print(f"{self.get_resource_type()}: {self.get_resource_name()} updated")
|
|
177
|
+
logger.debug(f"Running post-update for {self.get_resource_type()}: {self.get_resource_name()}")
|
|
178
|
+
return self.post_update(client)
|
|
179
|
+
logger.error(f"Failed to update {self.get_resource_type()}: {self.get_resource_name()}")
|
|
180
|
+
return self.resource_updated
|
|
181
|
+
|
|
182
|
+
def post_update(self, aws_client: AwsApiClient) -> bool:
|
|
183
|
+
return True
|
|
184
|
+
|
|
185
|
+
def _delete(self, aws_client: AwsApiClient) -> Any:
|
|
186
|
+
logger.warning(f"@_delete method not defined for {self.get_resource_name()}")
|
|
187
|
+
return True
|
|
188
|
+
|
|
189
|
+
def delete(self, aws_client: Optional[AwsApiClient] = None) -> bool:
|
|
190
|
+
"""Deletes the resource from Aws"""
|
|
191
|
+
|
|
192
|
+
# Step 1: Skip resource deletion if skip_delete = True
|
|
193
|
+
if self.skip_delete:
|
|
194
|
+
print(f"Skipping delete: {self.get_resource_name()}")
|
|
195
|
+
return True
|
|
196
|
+
|
|
197
|
+
# Step 2: Delete the resource
|
|
198
|
+
client: AwsApiClient = aws_client or self.get_aws_client()
|
|
199
|
+
if self.is_active(client):
|
|
200
|
+
self.resource_deleted = self._delete(client)
|
|
201
|
+
else:
|
|
202
|
+
print(f"{self.get_resource_type()}: {self.get_resource_name()} does not exist")
|
|
203
|
+
return True
|
|
204
|
+
|
|
205
|
+
# Step 3: Run post delete steps
|
|
206
|
+
if self.resource_deleted:
|
|
207
|
+
print(f"{self.get_resource_type()}: {self.get_resource_name()} deleted")
|
|
208
|
+
logger.debug(f"Running post-delete for {self.get_resource_type()}: {self.get_resource_name()}.")
|
|
209
|
+
return self.post_delete(client)
|
|
210
|
+
logger.error(f"Failed to delete {self.get_resource_type()}: {self.get_resource_name()}")
|
|
211
|
+
return self.resource_deleted
|
|
212
|
+
|
|
213
|
+
def post_delete(self, aws_client: AwsApiClient) -> bool:
|
|
214
|
+
return True
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from typing import Any, Optional
|
|
2
|
+
|
|
3
|
+
from agno.utils.log import logger
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AwsApiClient:
|
|
7
|
+
def __init__(
|
|
8
|
+
self,
|
|
9
|
+
aws_region: Optional[str] = None,
|
|
10
|
+
aws_profile: Optional[str] = None,
|
|
11
|
+
):
|
|
12
|
+
super().__init__()
|
|
13
|
+
self.aws_region: Optional[str] = aws_region
|
|
14
|
+
self.aws_profile: Optional[str] = aws_profile
|
|
15
|
+
|
|
16
|
+
# aws boto3 session
|
|
17
|
+
self._boto3_session: Optional[Any] = None
|
|
18
|
+
logger.debug("**-+-** AwsApiClient created")
|
|
19
|
+
|
|
20
|
+
def create_boto3_session(self) -> Optional[Any]:
|
|
21
|
+
"""Create a boto3 session"""
|
|
22
|
+
import boto3
|
|
23
|
+
|
|
24
|
+
logger.debug("Creating boto3.Session")
|
|
25
|
+
try:
|
|
26
|
+
self._boto3_session = boto3.Session(
|
|
27
|
+
region_name=self.aws_region,
|
|
28
|
+
profile_name=self.aws_profile,
|
|
29
|
+
)
|
|
30
|
+
logger.debug("**-+-** boto3.Session created")
|
|
31
|
+
logger.debug(f"\taws_region: {self._boto3_session.region_name}")
|
|
32
|
+
logger.debug(f"\taws_profile: {self._boto3_session.profile_name}")
|
|
33
|
+
except Exception as e:
|
|
34
|
+
logger.error("Could not connect to aws. Please confirm aws cli is installed and configured")
|
|
35
|
+
logger.error(e)
|
|
36
|
+
exit(0)
|
|
37
|
+
return self._boto3_session
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def boto3_session(self) -> Optional[Any]:
|
|
41
|
+
if self._boto3_session is None:
|
|
42
|
+
self._boto3_session = self.create_boto3_session()
|
|
43
|
+
return self._boto3_session
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
from typing import Any, Dict, List, Optional
|
|
2
|
+
|
|
3
|
+
from typing_extensions import Literal
|
|
4
|
+
|
|
5
|
+
from agno.cloud.aws.base import AwsResource
|
|
6
|
+
from agno.cloud.aws.s3.api_client import AwsApiClient
|
|
7
|
+
from agno.cloud.aws.s3.object import S3Object
|
|
8
|
+
from agno.utils.log import logger
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class S3Bucket(AwsResource):
|
|
12
|
+
"""
|
|
13
|
+
Reference:
|
|
14
|
+
- https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#service-resource
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
resource_type: str = "s3"
|
|
18
|
+
service_name: str = "s3"
|
|
19
|
+
|
|
20
|
+
# Name of the bucket
|
|
21
|
+
name: str
|
|
22
|
+
# The canned ACL to apply to the bucket.
|
|
23
|
+
acl: Optional[Literal["private", "public-read", "public-read-write", "authenticated-read"]] = None
|
|
24
|
+
grant_full_control: Optional[str] = None
|
|
25
|
+
grant_read: Optional[str] = None
|
|
26
|
+
grant_read_ACP: Optional[str] = None
|
|
27
|
+
grant_write: Optional[str] = None
|
|
28
|
+
grant_write_ACP: Optional[str] = None
|
|
29
|
+
object_lock_enabled_for_bucket: Optional[bool] = None
|
|
30
|
+
object_ownership: Optional[Literal["BucketOwnerPreferred", "ObjectWriter", "BucketOwnerEnforced"]] = None
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def uri(self) -> str:
|
|
34
|
+
"""Returns the URI of the s3.Bucket
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
str: The URI of the s3.Bucket
|
|
38
|
+
"""
|
|
39
|
+
return f"s3://{self.name}"
|
|
40
|
+
|
|
41
|
+
def get_resource(self, aws_client: Optional[AwsApiClient] = None) -> Optional[Any]:
|
|
42
|
+
"""Returns the s3.Bucket
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
aws_client: The AwsApiClient for the current cluster
|
|
46
|
+
"""
|
|
47
|
+
client: AwsApiClient = aws_client or self.get_aws_client()
|
|
48
|
+
service_resource = self.get_service_resource(client)
|
|
49
|
+
return service_resource.Bucket(name=self.name)
|
|
50
|
+
|
|
51
|
+
def _create(self, aws_client: AwsApiClient) -> bool:
|
|
52
|
+
"""Creates the s3.Bucket
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
aws_client: The AwsApiClient for the current cluster
|
|
56
|
+
"""
|
|
57
|
+
print(f"Creating {self.get_resource_type()}: {self.get_resource_name()}")
|
|
58
|
+
|
|
59
|
+
# Step 1: Build bucket configuration
|
|
60
|
+
# Bucket names are GLOBALLY unique!
|
|
61
|
+
# AWS will give you the IllegalLocationConstraintException if you collide
|
|
62
|
+
# with an already existing bucket if you've specified a region different than
|
|
63
|
+
# the region of the already existing bucket. If you happen to guess the correct region of the
|
|
64
|
+
# existing bucket it will give you the BucketAlreadyExists exception.
|
|
65
|
+
bucket_configuration = None
|
|
66
|
+
if aws_client.aws_region is not None and aws_client.aws_region != "us-east-1":
|
|
67
|
+
bucket_configuration = {"LocationConstraint": aws_client.aws_region}
|
|
68
|
+
|
|
69
|
+
# create a dict of args which are not null, otherwise aws type validation fails
|
|
70
|
+
not_null_args: Dict[str, Any] = {}
|
|
71
|
+
if bucket_configuration:
|
|
72
|
+
not_null_args["CreateBucketConfiguration"] = bucket_configuration
|
|
73
|
+
if self.acl:
|
|
74
|
+
not_null_args["ACL"] = self.acl
|
|
75
|
+
if self.grant_full_control:
|
|
76
|
+
not_null_args["GrantFullControl"] = self.grant_full_control
|
|
77
|
+
if self.grant_read:
|
|
78
|
+
not_null_args["GrantRead"] = self.grant_read
|
|
79
|
+
if self.grant_read_ACP:
|
|
80
|
+
not_null_args["GrantReadACP"] = self.grant_read_ACP
|
|
81
|
+
if self.grant_write:
|
|
82
|
+
not_null_args["GrantWrite"] = self.grant_write
|
|
83
|
+
if self.grant_write_ACP:
|
|
84
|
+
not_null_args["GrantWriteACP"] = self.grant_write_ACP
|
|
85
|
+
if self.object_lock_enabled_for_bucket:
|
|
86
|
+
not_null_args["ObjectLockEnabledForBucket"] = self.object_lock_enabled_for_bucket
|
|
87
|
+
if self.object_ownership:
|
|
88
|
+
not_null_args["ObjectOwnership"] = self.object_ownership
|
|
89
|
+
|
|
90
|
+
# Step 2: Create Bucket
|
|
91
|
+
service_client = self.get_service_client(aws_client)
|
|
92
|
+
try:
|
|
93
|
+
response = service_client.create_bucket(
|
|
94
|
+
Bucket=self.name,
|
|
95
|
+
**not_null_args,
|
|
96
|
+
)
|
|
97
|
+
logger.debug(f"Response: {response}")
|
|
98
|
+
bucket_location = response.get("Location")
|
|
99
|
+
if bucket_location is not None:
|
|
100
|
+
logger.debug(f"Bucket created: {bucket_location}")
|
|
101
|
+
self.active_resource = response
|
|
102
|
+
return True
|
|
103
|
+
except Exception as e:
|
|
104
|
+
logger.error(f"{self.get_resource_type()} could not be created.")
|
|
105
|
+
logger.error(e)
|
|
106
|
+
return False
|
|
107
|
+
|
|
108
|
+
def post_create(self, aws_client: AwsApiClient) -> bool:
|
|
109
|
+
# Wait for Bucket to be created
|
|
110
|
+
if self.wait_for_create:
|
|
111
|
+
try:
|
|
112
|
+
print(f"Waiting for {self.get_resource_type()} to be created.")
|
|
113
|
+
waiter = self.get_service_client(aws_client).get_waiter("bucket_exists")
|
|
114
|
+
waiter.wait(
|
|
115
|
+
Bucket=self.name,
|
|
116
|
+
WaiterConfig={
|
|
117
|
+
"Delay": self.waiter_delay,
|
|
118
|
+
"MaxAttempts": self.waiter_max_attempts,
|
|
119
|
+
},
|
|
120
|
+
)
|
|
121
|
+
except Exception as e:
|
|
122
|
+
logger.error("Waiter failed.")
|
|
123
|
+
logger.error(e)
|
|
124
|
+
return True
|
|
125
|
+
|
|
126
|
+
def _read(self, aws_client: AwsApiClient) -> Optional[Any]:
|
|
127
|
+
"""Returns the s3.Bucket
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
aws_client: The AwsApiClient for the current cluster
|
|
131
|
+
"""
|
|
132
|
+
logger.debug(f"Reading {self.get_resource_type()}: {self.get_resource_name()}")
|
|
133
|
+
|
|
134
|
+
from botocore.exceptions import ClientError
|
|
135
|
+
|
|
136
|
+
try:
|
|
137
|
+
service_resource = self.get_service_resource(aws_client)
|
|
138
|
+
bucket = service_resource.Bucket(name=self.name)
|
|
139
|
+
bucket.load()
|
|
140
|
+
creation_date = bucket.creation_date
|
|
141
|
+
logger.debug(f"Bucket creation_date: {creation_date}")
|
|
142
|
+
if creation_date is not None:
|
|
143
|
+
logger.debug(f"Bucket found: {bucket.name}")
|
|
144
|
+
self.active_resource = {
|
|
145
|
+
"name": bucket.name,
|
|
146
|
+
"creation_date": creation_date,
|
|
147
|
+
}
|
|
148
|
+
except ClientError as ce:
|
|
149
|
+
logger.debug(f"ClientError: {ce}")
|
|
150
|
+
except Exception as e:
|
|
151
|
+
logger.error(f"Error reading {self.get_resource_type()}.")
|
|
152
|
+
logger.error(e)
|
|
153
|
+
return self.active_resource
|
|
154
|
+
|
|
155
|
+
def _delete(self, aws_client: AwsApiClient) -> bool:
|
|
156
|
+
"""Deletes the s3.Bucket
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
aws_client: The AwsApiClient for the current cluster
|
|
160
|
+
"""
|
|
161
|
+
print(f"Deleting {self.get_resource_type()}: {self.get_resource_name()}")
|
|
162
|
+
|
|
163
|
+
service_client = self.get_service_client(aws_client)
|
|
164
|
+
self.active_resource = None
|
|
165
|
+
try:
|
|
166
|
+
response = service_client.delete_bucket(Bucket=self.name)
|
|
167
|
+
logger.debug(f"Response: {response}")
|
|
168
|
+
return True
|
|
169
|
+
except Exception as e:
|
|
170
|
+
logger.error(f"{self.get_resource_type()} could not be deleted.")
|
|
171
|
+
logger.error("Please try again or delete resources manually.")
|
|
172
|
+
logger.error(e)
|
|
173
|
+
return False
|
|
174
|
+
|
|
175
|
+
def get_objects(self, aws_client: Optional[AwsApiClient] = None, prefix: Optional[str] = None) -> List[Any]:
|
|
176
|
+
"""Returns a list of s3.Object objects for the s3.Bucket
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
aws_client: The AwsApiClient for the current cluster
|
|
180
|
+
prefix: Prefix to filter objects by
|
|
181
|
+
"""
|
|
182
|
+
bucket = self.get_resource(aws_client)
|
|
183
|
+
if bucket is None:
|
|
184
|
+
logger.warning(f"Could not get bucket: {self.name}")
|
|
185
|
+
return []
|
|
186
|
+
|
|
187
|
+
logger.debug(f"Getting objects for bucket: {bucket.name}")
|
|
188
|
+
# Get all objects in bucket
|
|
189
|
+
object_summaries = bucket.objects.all()
|
|
190
|
+
all_objects: List[S3Object] = []
|
|
191
|
+
for object_summary in object_summaries:
|
|
192
|
+
if prefix is not None and not object_summary.key.startswith(prefix):
|
|
193
|
+
continue
|
|
194
|
+
all_objects.append(S3Object(bucket_name=bucket.name, name=object_summary.key))
|
|
195
|
+
return all_objects
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Any, Optional
|
|
3
|
+
|
|
4
|
+
from agno.cloud.aws.base import AwsResource
|
|
5
|
+
from agno.cloud.aws.s3.api_client import AwsApiClient
|
|
6
|
+
from agno.utils.log import logger
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class S3Object(AwsResource):
|
|
10
|
+
"""
|
|
11
|
+
Reference:
|
|
12
|
+
- https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3/object/index.html
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
resource_type: str = "s3"
|
|
16
|
+
service_name: str = "s3"
|
|
17
|
+
|
|
18
|
+
# The Object’s bucket_name identifier. This must be set.
|
|
19
|
+
bucket_name: str
|
|
20
|
+
|
|
21
|
+
@property
|
|
22
|
+
def uri(self) -> str:
|
|
23
|
+
"""Returns the URI of the s3.Object
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
str: The URI of the s3.Object
|
|
27
|
+
"""
|
|
28
|
+
return f"s3://{self.bucket_name}/{self.name}"
|
|
29
|
+
|
|
30
|
+
def get_resource(self, aws_client: Optional[AwsApiClient] = None) -> Any:
|
|
31
|
+
"""Returns the s3.Object
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
aws_client: The AwsApiClient for the current cluster
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
The s3.Object
|
|
38
|
+
"""
|
|
39
|
+
client: AwsApiClient = aws_client or self.get_aws_client()
|
|
40
|
+
service_resource = self.get_service_resource(client)
|
|
41
|
+
return service_resource.Object(
|
|
42
|
+
bucket_name=self.bucket_name,
|
|
43
|
+
key=self.name,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
def download(self, path: Path, aws_client: Optional[AwsApiClient] = None) -> None:
|
|
47
|
+
"""Downloads the s3.Object to the specified path
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
path: The path to download the s3.Object to
|
|
51
|
+
aws_client: The AwsApiClient for the current cluster
|
|
52
|
+
"""
|
|
53
|
+
logger.info(f"Downloading {self.uri} to {path}")
|
|
54
|
+
object_resource = self.get_resource(aws_client=aws_client)
|
|
55
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
56
|
+
with path.open(mode="wb") as f:
|
|
57
|
+
object_resource.download_fileobj(f)
|