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/tools/docker.py
ADDED
|
@@ -0,0 +1,716 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
from typing import Any, Dict, List, Optional, Union
|
|
5
|
+
|
|
6
|
+
from agno.tools import Toolkit
|
|
7
|
+
from agno.utils.log import logger
|
|
8
|
+
|
|
9
|
+
if sys.version_info >= (3, 12):
|
|
10
|
+
# Apply more comprehensive monkey patch for Python 3.12 compatibility
|
|
11
|
+
try:
|
|
12
|
+
import inspect
|
|
13
|
+
|
|
14
|
+
from docker import auth
|
|
15
|
+
|
|
16
|
+
# Create a more comprehensive patched version that ignores any unknown parameters
|
|
17
|
+
original_load_config = auth.load_config
|
|
18
|
+
|
|
19
|
+
def patched_load_config(*args, **kwargs):
|
|
20
|
+
# Get the original function's parameters
|
|
21
|
+
try:
|
|
22
|
+
sig = inspect.signature(original_load_config)
|
|
23
|
+
# Filter out any kwargs that aren't in the signature
|
|
24
|
+
valid_kwargs = {k: v for k, v in kwargs.items() if k in sig.parameters}
|
|
25
|
+
return original_load_config(*args, **valid_kwargs)
|
|
26
|
+
except Exception as e:
|
|
27
|
+
logger.warning(f"Error in patched_load_config: {e}")
|
|
28
|
+
return {}
|
|
29
|
+
|
|
30
|
+
# Replace the original function with our patched version
|
|
31
|
+
auth.load_config = patched_load_config
|
|
32
|
+
|
|
33
|
+
# Add the missing get_config_header function
|
|
34
|
+
if not hasattr(auth, "get_config_header"):
|
|
35
|
+
|
|
36
|
+
def get_config_header(client, registry=None):
|
|
37
|
+
"""
|
|
38
|
+
Replacement for missing get_config_header function.
|
|
39
|
+
Returns empty auth headers to avoid authentication errors.
|
|
40
|
+
"""
|
|
41
|
+
return {}
|
|
42
|
+
|
|
43
|
+
# Add the function to the auth module
|
|
44
|
+
auth.get_config_header = get_config_header
|
|
45
|
+
logger.info("Added missing get_config_header function for Docker auth compatibility")
|
|
46
|
+
|
|
47
|
+
logger.info("Applied comprehensive compatibility patch for Docker client on Python 3.12")
|
|
48
|
+
except Exception as e:
|
|
49
|
+
logger.warning(f"Failed to apply Docker client compatibility patch: {e}")
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
import docker
|
|
53
|
+
from docker.errors import DockerException, ImageNotFound
|
|
54
|
+
except ImportError:
|
|
55
|
+
raise ImportError("The `docker` package is not installed. Please install it via `pip install docker`.")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class DockerTools(Toolkit):
|
|
59
|
+
def __init__(
|
|
60
|
+
self,
|
|
61
|
+
**kwargs,
|
|
62
|
+
):
|
|
63
|
+
self._check_docker_availability()
|
|
64
|
+
|
|
65
|
+
try:
|
|
66
|
+
os.environ["DOCKER_CONFIG"] = ""
|
|
67
|
+
|
|
68
|
+
if hasattr(self, "socket_path"):
|
|
69
|
+
socket_url = f"unix://{self.socket_path}"
|
|
70
|
+
self.client = docker.DockerClient(base_url=socket_url)
|
|
71
|
+
else:
|
|
72
|
+
self.client = docker.DockerClient()
|
|
73
|
+
|
|
74
|
+
self.client.ping()
|
|
75
|
+
logger.info("Successfully connected to Docker daemon")
|
|
76
|
+
except Exception as e:
|
|
77
|
+
logger.error(f"Error connecting to Docker: {e}")
|
|
78
|
+
|
|
79
|
+
tools: List[Any] = [
|
|
80
|
+
# Container management
|
|
81
|
+
self.list_containers,
|
|
82
|
+
self.start_container,
|
|
83
|
+
self.stop_container,
|
|
84
|
+
self.remove_container,
|
|
85
|
+
self.get_container_logs,
|
|
86
|
+
self.inspect_container,
|
|
87
|
+
self.run_container,
|
|
88
|
+
self.exec_in_container,
|
|
89
|
+
# Image management
|
|
90
|
+
self.list_images,
|
|
91
|
+
self.pull_image,
|
|
92
|
+
self.remove_image,
|
|
93
|
+
self.build_image,
|
|
94
|
+
self.tag_image,
|
|
95
|
+
self.inspect_image,
|
|
96
|
+
# Volume management
|
|
97
|
+
self.list_volumes,
|
|
98
|
+
self.create_volume,
|
|
99
|
+
self.remove_volume,
|
|
100
|
+
self.inspect_volume,
|
|
101
|
+
# Network management
|
|
102
|
+
self.list_networks,
|
|
103
|
+
self.create_network,
|
|
104
|
+
self.remove_network,
|
|
105
|
+
self.inspect_network,
|
|
106
|
+
self.connect_container_to_network,
|
|
107
|
+
self.disconnect_container_from_network,
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
super().__init__(name="docker_tools", tools=tools, **kwargs)
|
|
111
|
+
|
|
112
|
+
def _check_docker_availability(self):
|
|
113
|
+
"""Check if Docker socket exists and is accessible."""
|
|
114
|
+
# Common Docker socket paths
|
|
115
|
+
socket_paths = [
|
|
116
|
+
# Linux/macOS
|
|
117
|
+
"/var/run/docker.sock",
|
|
118
|
+
# macOS Docker Desktop
|
|
119
|
+
os.path.expanduser("~/.docker/run/docker.sock"),
|
|
120
|
+
# macOS newer versions
|
|
121
|
+
os.path.join(os.path.expanduser("~"), ".docker", "desktop", "docker.sock"),
|
|
122
|
+
# macOS alternative
|
|
123
|
+
os.path.expanduser("~/Library/Containers/com.docker.docker/Data/docker.sock"),
|
|
124
|
+
# Windows
|
|
125
|
+
os.path.join("\\", "\\", ".", "pipe", "docker_engine"),
|
|
126
|
+
]
|
|
127
|
+
|
|
128
|
+
# Check if any socket exists
|
|
129
|
+
socket_exists = any(os.path.exists(path) for path in socket_paths)
|
|
130
|
+
if not socket_exists:
|
|
131
|
+
logger.error("Docker socket not found. Is Docker installed and running?")
|
|
132
|
+
raise ValueError(
|
|
133
|
+
"Docker socket not found. Please make sure Docker is installed and running.\n"
|
|
134
|
+
"On macOS: Start Docker Desktop application.\n"
|
|
135
|
+
"On Linux: Run 'sudo systemctl start docker'."
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
# Find the first available socket path
|
|
139
|
+
for path in socket_paths:
|
|
140
|
+
if os.path.exists(path):
|
|
141
|
+
logger.info(f"Found Docker socket at {path}")
|
|
142
|
+
self.socket_path = path
|
|
143
|
+
return
|
|
144
|
+
|
|
145
|
+
def list_containers(self, all: bool = False) -> str:
|
|
146
|
+
"""
|
|
147
|
+
List Docker containers.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
all (bool): If True, show all containers (default shows just running).
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
str: A JSON string containing the list of containers.
|
|
154
|
+
"""
|
|
155
|
+
try:
|
|
156
|
+
containers = self.client.containers.list(all=all)
|
|
157
|
+
container_list = []
|
|
158
|
+
|
|
159
|
+
for container in containers:
|
|
160
|
+
# Handle cases where container image might not have tags
|
|
161
|
+
image_info = container.image.tags[0] if container.image.tags else container.image.id
|
|
162
|
+
|
|
163
|
+
container_list.append(
|
|
164
|
+
{
|
|
165
|
+
"id": container.id,
|
|
166
|
+
"name": container.name,
|
|
167
|
+
"image": image_info,
|
|
168
|
+
"status": container.status,
|
|
169
|
+
"created": container.attrs.get("Created"),
|
|
170
|
+
"ports": container.ports,
|
|
171
|
+
"labels": container.labels,
|
|
172
|
+
}
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
return json.dumps(container_list, indent=2)
|
|
176
|
+
except DockerException as e:
|
|
177
|
+
error_msg = f"Error listing containers: {str(e)}"
|
|
178
|
+
logger.error(error_msg)
|
|
179
|
+
return error_msg
|
|
180
|
+
|
|
181
|
+
def start_container(self, container_id: str) -> str:
|
|
182
|
+
"""
|
|
183
|
+
Start a Docker container.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
container_id (str): The ID or name of the container to start.
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
str: A success message or error message.
|
|
190
|
+
"""
|
|
191
|
+
try:
|
|
192
|
+
container = self.client.containers.get(container_id)
|
|
193
|
+
container.start()
|
|
194
|
+
return f"Container {container_id} started successfully"
|
|
195
|
+
except DockerException as e:
|
|
196
|
+
error_msg = f"Error starting container: {str(e)}"
|
|
197
|
+
logger.error(error_msg)
|
|
198
|
+
return error_msg
|
|
199
|
+
|
|
200
|
+
def stop_container(self, container_id: str, timeout: int = 10) -> str:
|
|
201
|
+
"""
|
|
202
|
+
Stop a Docker container.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
container_id (str): The ID or name of the container to stop.
|
|
206
|
+
timeout (int): Timeout in seconds to wait for container to stop.
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
str: A success message or error message.
|
|
210
|
+
"""
|
|
211
|
+
try:
|
|
212
|
+
container = self.client.containers.get(container_id)
|
|
213
|
+
container.stop(timeout=timeout)
|
|
214
|
+
return f"Container {container_id} stopped successfully"
|
|
215
|
+
except DockerException as e:
|
|
216
|
+
error_msg = f"Error stopping container: {str(e)}"
|
|
217
|
+
logger.error(error_msg)
|
|
218
|
+
return error_msg
|
|
219
|
+
|
|
220
|
+
def remove_container(self, container_id: str, force: bool = False, volumes: bool = False) -> str:
|
|
221
|
+
"""
|
|
222
|
+
Remove a Docker container.
|
|
223
|
+
|
|
224
|
+
Args:
|
|
225
|
+
container_id (str): The ID or name of the container to remove.
|
|
226
|
+
force (bool): If True, force the removal of a running container.
|
|
227
|
+
volumes (bool): If True, remove anonymous volumes associated with the container.
|
|
228
|
+
|
|
229
|
+
Returns:
|
|
230
|
+
str: A success message or error message.
|
|
231
|
+
"""
|
|
232
|
+
try:
|
|
233
|
+
container = self.client.containers.get(container_id)
|
|
234
|
+
container.remove(force=force, v=volumes)
|
|
235
|
+
return f"Container {container_id} removed successfully"
|
|
236
|
+
except DockerException as e:
|
|
237
|
+
error_msg = f"Error removing container: {str(e)}"
|
|
238
|
+
logger.error(error_msg)
|
|
239
|
+
return error_msg
|
|
240
|
+
|
|
241
|
+
def get_container_logs(self, container_id: str, tail: int = 100, stream: bool = False) -> str:
|
|
242
|
+
"""
|
|
243
|
+
Get logs from a Docker container.
|
|
244
|
+
|
|
245
|
+
Args:
|
|
246
|
+
container_id (str): The ID or name of the container.
|
|
247
|
+
tail (int): Number of lines to show from the end of the logs.
|
|
248
|
+
stream (bool): If True, return a generator that yields log lines.
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
str: The container logs or an error message.
|
|
252
|
+
"""
|
|
253
|
+
try:
|
|
254
|
+
container = self.client.containers.get(container_id)
|
|
255
|
+
logs = container.logs(tail=tail, stream=stream)
|
|
256
|
+
if isinstance(logs, bytes):
|
|
257
|
+
return logs.decode("utf-8", errors="replace")
|
|
258
|
+
# If streaming, we can't meaningfully return this as a string
|
|
259
|
+
if stream:
|
|
260
|
+
return "Logs are being streamed. This function returns data when stream=False."
|
|
261
|
+
return "No logs found"
|
|
262
|
+
except DockerException as e:
|
|
263
|
+
error_msg = f"Error getting container logs: {str(e)}"
|
|
264
|
+
logger.error(error_msg)
|
|
265
|
+
return error_msg
|
|
266
|
+
|
|
267
|
+
def inspect_container(self, container_id: str) -> str:
|
|
268
|
+
"""
|
|
269
|
+
Inspect a Docker container.
|
|
270
|
+
|
|
271
|
+
Args:
|
|
272
|
+
container_id (str): The ID or name of the container.
|
|
273
|
+
|
|
274
|
+
Returns:
|
|
275
|
+
str: A JSON string containing detailed information about the container.
|
|
276
|
+
"""
|
|
277
|
+
try:
|
|
278
|
+
container = self.client.containers.get(container_id)
|
|
279
|
+
return json.dumps(container.attrs, indent=2)
|
|
280
|
+
except DockerException as e:
|
|
281
|
+
error_msg = f"Error inspecting container: {str(e)}"
|
|
282
|
+
logger.error(error_msg)
|
|
283
|
+
return error_msg
|
|
284
|
+
|
|
285
|
+
def run_container(
|
|
286
|
+
self,
|
|
287
|
+
image: str,
|
|
288
|
+
command: Optional[str] = None,
|
|
289
|
+
name: Optional[str] = None,
|
|
290
|
+
detach: bool = True,
|
|
291
|
+
ports: Optional[Dict[str, Union[str, int]]] = None, # Updated type hint
|
|
292
|
+
volumes: Optional[Dict[str, Dict[str, str]]] = None,
|
|
293
|
+
environment: Optional[Dict[str, str]] = None,
|
|
294
|
+
network: Optional[str] = None,
|
|
295
|
+
) -> str:
|
|
296
|
+
"""
|
|
297
|
+
Run a Docker container.
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
image (str): The image to run.
|
|
301
|
+
command (str, optional): The command to run in the container.
|
|
302
|
+
name (str, optional): A name for the container.
|
|
303
|
+
detach (bool): Run container in the background.
|
|
304
|
+
ports (dict, optional): Port mappings {'container_port/protocol': host_port}.
|
|
305
|
+
volumes (dict, optional): Volume mappings.
|
|
306
|
+
environment (dict, optional): Environment variables.
|
|
307
|
+
network (str, optional): Network to connect the container to.
|
|
308
|
+
|
|
309
|
+
Returns:
|
|
310
|
+
str: Container ID or error message.
|
|
311
|
+
"""
|
|
312
|
+
try:
|
|
313
|
+
# Fix port mapping: convert integer values to strings
|
|
314
|
+
if ports:
|
|
315
|
+
fixed_ports = {}
|
|
316
|
+
for container_port, host_port in ports.items():
|
|
317
|
+
if isinstance(host_port, int):
|
|
318
|
+
host_port = str(host_port)
|
|
319
|
+
fixed_ports[container_port] = host_port
|
|
320
|
+
else:
|
|
321
|
+
fixed_ports = None
|
|
322
|
+
|
|
323
|
+
container = self.client.containers.run(
|
|
324
|
+
image=image,
|
|
325
|
+
command=command,
|
|
326
|
+
name=name,
|
|
327
|
+
detach=detach,
|
|
328
|
+
ports=fixed_ports, # Use the fixed ports
|
|
329
|
+
volumes=volumes,
|
|
330
|
+
environment=environment,
|
|
331
|
+
network=network,
|
|
332
|
+
)
|
|
333
|
+
return f"Container started with ID: {container.id}"
|
|
334
|
+
except DockerException as e:
|
|
335
|
+
error_msg = f"Error running container: {str(e)}"
|
|
336
|
+
logger.error(error_msg)
|
|
337
|
+
return error_msg
|
|
338
|
+
|
|
339
|
+
def exec_in_container(self, container_id: str, command: str) -> str:
|
|
340
|
+
"""
|
|
341
|
+
Execute a command in a running container.
|
|
342
|
+
|
|
343
|
+
Args:
|
|
344
|
+
container_id (str): The ID or name of the container.
|
|
345
|
+
command (str): The command to execute.
|
|
346
|
+
|
|
347
|
+
Returns:
|
|
348
|
+
str: Command output or error message.
|
|
349
|
+
"""
|
|
350
|
+
try:
|
|
351
|
+
container = self.client.containers.get(container_id)
|
|
352
|
+
exit_code, output = container.exec_run(command)
|
|
353
|
+
if isinstance(output, bytes):
|
|
354
|
+
output_str = output.decode("utf-8", errors="replace")
|
|
355
|
+
else:
|
|
356
|
+
output_str = str(output)
|
|
357
|
+
|
|
358
|
+
if exit_code == 0:
|
|
359
|
+
return output_str
|
|
360
|
+
else:
|
|
361
|
+
return f"Command failed with exit code {exit_code}: {output_str}"
|
|
362
|
+
except DockerException as e:
|
|
363
|
+
error_msg = f"Error executing command in container: {str(e)}"
|
|
364
|
+
logger.error(error_msg)
|
|
365
|
+
return error_msg
|
|
366
|
+
|
|
367
|
+
def list_images(self) -> str:
|
|
368
|
+
"""
|
|
369
|
+
List Docker images.
|
|
370
|
+
|
|
371
|
+
Returns:
|
|
372
|
+
str: A JSON string containing the list of images.
|
|
373
|
+
"""
|
|
374
|
+
try:
|
|
375
|
+
images = self.client.images.list()
|
|
376
|
+
image_list = []
|
|
377
|
+
|
|
378
|
+
for image in images:
|
|
379
|
+
image_list.append(
|
|
380
|
+
{
|
|
381
|
+
"id": image.id,
|
|
382
|
+
"tags": image.tags,
|
|
383
|
+
"created": image.attrs.get("Created"),
|
|
384
|
+
"size": image.attrs.get("Size"),
|
|
385
|
+
"labels": image.labels,
|
|
386
|
+
}
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
return json.dumps(image_list, indent=2)
|
|
390
|
+
except DockerException as e:
|
|
391
|
+
error_msg = f"Error listing images: {str(e)}"
|
|
392
|
+
logger.error(error_msg)
|
|
393
|
+
return error_msg # type: ignore
|
|
394
|
+
|
|
395
|
+
def pull_image(self, image_name: str, tag: str = "latest") -> str:
|
|
396
|
+
"""
|
|
397
|
+
Pull a Docker image.
|
|
398
|
+
|
|
399
|
+
Args:
|
|
400
|
+
image_name (str): The name of the image to pull.
|
|
401
|
+
tag (str): The tag to pull.
|
|
402
|
+
|
|
403
|
+
Returns:
|
|
404
|
+
str: A success message or error message.
|
|
405
|
+
"""
|
|
406
|
+
try:
|
|
407
|
+
logger.info(f"Starting to pull image {image_name}:{tag}")
|
|
408
|
+
for line in self.client.api.pull(image_name, tag=tag, stream=True, decode=True):
|
|
409
|
+
if "progress" in line:
|
|
410
|
+
logger.info(f"Pulling {image_name}:{tag} - {line.get('progress', '')}")
|
|
411
|
+
elif "status" in line:
|
|
412
|
+
logger.info(f"Pull status: {line.get('status', '')}")
|
|
413
|
+
|
|
414
|
+
logger.info(f"Successfully pulled image {image_name}:{tag}")
|
|
415
|
+
return f"Image {image_name}:{tag} pulled successfully"
|
|
416
|
+
except Exception as e:
|
|
417
|
+
error_msg = f"Error pulling image: {str(e)}"
|
|
418
|
+
logger.error(error_msg)
|
|
419
|
+
return error_msg
|
|
420
|
+
|
|
421
|
+
def remove_image(self, image_id: str, force: bool = False) -> str:
|
|
422
|
+
"""
|
|
423
|
+
Remove a Docker image.
|
|
424
|
+
|
|
425
|
+
Args:
|
|
426
|
+
image_id (str): The ID or name of the image to remove.
|
|
427
|
+
force (bool): If True, force removal of the image.
|
|
428
|
+
|
|
429
|
+
Returns:
|
|
430
|
+
str: A success message or error message.
|
|
431
|
+
"""
|
|
432
|
+
try:
|
|
433
|
+
self.client.images.remove(image_id, force=force)
|
|
434
|
+
return f"Image {image_id} removed successfully"
|
|
435
|
+
except ImageNotFound:
|
|
436
|
+
return f"Image {image_id} not found"
|
|
437
|
+
except DockerException as e:
|
|
438
|
+
error_msg = f"Error removing image: {str(e)}"
|
|
439
|
+
logger.error(error_msg)
|
|
440
|
+
return error_msg
|
|
441
|
+
|
|
442
|
+
def build_image(self, path: str, tag: str, dockerfile: str = "Dockerfile", rm: bool = True) -> str:
|
|
443
|
+
"""
|
|
444
|
+
Build a Docker image from a Dockerfile.
|
|
445
|
+
|
|
446
|
+
Args:
|
|
447
|
+
path (str): Path to the directory containing the Dockerfile.
|
|
448
|
+
tag (str): Tag to apply to the built image.
|
|
449
|
+
dockerfile (str): Name of the Dockerfile.
|
|
450
|
+
rm (bool): Remove intermediate containers.
|
|
451
|
+
|
|
452
|
+
Returns:
|
|
453
|
+
str: A success message or error message.
|
|
454
|
+
"""
|
|
455
|
+
try:
|
|
456
|
+
image, logs = self.client.images.build(path=path, tag=tag, dockerfile=dockerfile, rm=rm)
|
|
457
|
+
return f"Image built successfully with ID: {image.id}"
|
|
458
|
+
except DockerException as e:
|
|
459
|
+
error_msg = f"Error building image: {str(e)}"
|
|
460
|
+
logger.error(error_msg)
|
|
461
|
+
return error_msg
|
|
462
|
+
|
|
463
|
+
def tag_image(self, image_id: str, repository: str, tag: Optional[str] = None) -> str:
|
|
464
|
+
"""
|
|
465
|
+
Tag a Docker image.
|
|
466
|
+
|
|
467
|
+
Args:
|
|
468
|
+
image_id (str): The ID or name of the image to tag.
|
|
469
|
+
repository (str): The repository to tag in.
|
|
470
|
+
tag (str, optional): The tag name.
|
|
471
|
+
|
|
472
|
+
Returns:
|
|
473
|
+
str: A success message or error message.
|
|
474
|
+
"""
|
|
475
|
+
try:
|
|
476
|
+
image = self.client.images.get(image_id)
|
|
477
|
+
image.tag(repository, tag=tag)
|
|
478
|
+
return f"Image {image_id} tagged as {repository}:{tag or 'latest'}"
|
|
479
|
+
except DockerException as e:
|
|
480
|
+
error_msg = f"Error tagging image: {str(e)}"
|
|
481
|
+
logger.error(error_msg)
|
|
482
|
+
return error_msg
|
|
483
|
+
|
|
484
|
+
def inspect_image(self, image_id: str) -> str:
|
|
485
|
+
"""
|
|
486
|
+
Inspect a Docker image.
|
|
487
|
+
|
|
488
|
+
Args:
|
|
489
|
+
image_id (str): The ID or name of the image.
|
|
490
|
+
|
|
491
|
+
Returns:
|
|
492
|
+
str: A JSON string containing detailed information about the image.
|
|
493
|
+
"""
|
|
494
|
+
try:
|
|
495
|
+
image = self.client.images.get(image_id)
|
|
496
|
+
return json.dumps(image.attrs, indent=2)
|
|
497
|
+
except DockerException as e:
|
|
498
|
+
error_msg = f"Error inspecting image: {str(e)}"
|
|
499
|
+
logger.error(error_msg)
|
|
500
|
+
return error_msg
|
|
501
|
+
|
|
502
|
+
def list_volumes(self) -> str:
|
|
503
|
+
"""
|
|
504
|
+
List Docker volumes.
|
|
505
|
+
|
|
506
|
+
Returns:
|
|
507
|
+
str: A JSON string containing the list of volumes.
|
|
508
|
+
"""
|
|
509
|
+
try:
|
|
510
|
+
volumes = self.client.volumes.list()
|
|
511
|
+
volume_list = []
|
|
512
|
+
|
|
513
|
+
for volume in volumes:
|
|
514
|
+
volume_list.append(
|
|
515
|
+
{
|
|
516
|
+
"name": volume.name,
|
|
517
|
+
"driver": volume.attrs.get("Driver"),
|
|
518
|
+
"mountpoint": volume.attrs.get("Mountpoint"),
|
|
519
|
+
"created": volume.attrs.get("CreatedAt"),
|
|
520
|
+
"labels": volume.attrs.get("Labels", {}),
|
|
521
|
+
}
|
|
522
|
+
)
|
|
523
|
+
|
|
524
|
+
return json.dumps(volume_list, indent=2)
|
|
525
|
+
except DockerException as e:
|
|
526
|
+
error_msg = f"Error listing volumes: {str(e)}"
|
|
527
|
+
logger.error(error_msg)
|
|
528
|
+
return error_msg
|
|
529
|
+
|
|
530
|
+
def create_volume(self, volume_name: str, driver: str = "local", labels: Optional[Dict[str, str]] = None) -> str:
|
|
531
|
+
"""
|
|
532
|
+
Create a Docker volume.
|
|
533
|
+
|
|
534
|
+
Args:
|
|
535
|
+
volume_name (str): The name of the volume to create.
|
|
536
|
+
driver (str): The volume driver to use.
|
|
537
|
+
labels (dict, optional): Labels to apply to the volume.
|
|
538
|
+
|
|
539
|
+
Returns:
|
|
540
|
+
str: A success message or error message.
|
|
541
|
+
"""
|
|
542
|
+
try:
|
|
543
|
+
self.client.volumes.create(name=volume_name, driver=driver, labels=labels)
|
|
544
|
+
return f"Volume {volume_name} created successfully"
|
|
545
|
+
except DockerException as e:
|
|
546
|
+
error_msg = f"Error creating volume: {str(e)}"
|
|
547
|
+
logger.error(error_msg)
|
|
548
|
+
return error_msg
|
|
549
|
+
|
|
550
|
+
def remove_volume(self, volume_name: str, force: bool = False) -> str:
|
|
551
|
+
"""
|
|
552
|
+
Remove a Docker volume.
|
|
553
|
+
|
|
554
|
+
Args:
|
|
555
|
+
volume_name (str): The name of the volume to remove.
|
|
556
|
+
force (bool): Force removal of the volume.
|
|
557
|
+
|
|
558
|
+
Returns:
|
|
559
|
+
str: A success message or error message.
|
|
560
|
+
"""
|
|
561
|
+
try:
|
|
562
|
+
volume = self.client.volumes.get(volume_name)
|
|
563
|
+
volume.remove(force=force)
|
|
564
|
+
return f"Volume {volume_name} removed successfully"
|
|
565
|
+
except DockerException as e:
|
|
566
|
+
error_msg = f"Error removing volume: {str(e)}"
|
|
567
|
+
logger.error(error_msg)
|
|
568
|
+
return error_msg
|
|
569
|
+
|
|
570
|
+
def inspect_volume(self, volume_name: str) -> str:
|
|
571
|
+
"""
|
|
572
|
+
Inspect a Docker volume.
|
|
573
|
+
|
|
574
|
+
Args:
|
|
575
|
+
volume_name (str): The name of the volume.
|
|
576
|
+
|
|
577
|
+
Returns:
|
|
578
|
+
str: A JSON string containing detailed information about the volume.
|
|
579
|
+
"""
|
|
580
|
+
try:
|
|
581
|
+
volume = self.client.volumes.get(volume_name)
|
|
582
|
+
return json.dumps(volume.attrs, indent=2)
|
|
583
|
+
except DockerException as e:
|
|
584
|
+
error_msg = f"Error inspecting volume: {str(e)}"
|
|
585
|
+
logger.error(error_msg)
|
|
586
|
+
return error_msg
|
|
587
|
+
|
|
588
|
+
def list_networks(self) -> str:
|
|
589
|
+
"""
|
|
590
|
+
List Docker networks.
|
|
591
|
+
|
|
592
|
+
Returns:
|
|
593
|
+
str: A JSON string containing the list of networks.
|
|
594
|
+
"""
|
|
595
|
+
try:
|
|
596
|
+
networks = self.client.networks.list()
|
|
597
|
+
network_list = []
|
|
598
|
+
|
|
599
|
+
for network in networks:
|
|
600
|
+
network_list.append(
|
|
601
|
+
{
|
|
602
|
+
"id": network.id,
|
|
603
|
+
"name": network.name,
|
|
604
|
+
"driver": network.attrs.get("Driver"),
|
|
605
|
+
"scope": network.attrs.get("Scope"),
|
|
606
|
+
"created": network.attrs.get("Created"),
|
|
607
|
+
"internal": network.attrs.get("Internal", False),
|
|
608
|
+
"containers": list(network.attrs.get("Containers", {}).keys()),
|
|
609
|
+
}
|
|
610
|
+
)
|
|
611
|
+
|
|
612
|
+
return json.dumps(network_list, indent=2)
|
|
613
|
+
except DockerException as e:
|
|
614
|
+
error_msg = f"Error listing networks: {str(e)}"
|
|
615
|
+
logger.error(error_msg)
|
|
616
|
+
return error_msg
|
|
617
|
+
|
|
618
|
+
def create_network(
|
|
619
|
+
self, network_name: str, driver: str = "bridge", internal: bool = False, labels: Optional[Dict[str, str]] = None
|
|
620
|
+
) -> str:
|
|
621
|
+
"""
|
|
622
|
+
Create a Docker network.
|
|
623
|
+
|
|
624
|
+
Args:
|
|
625
|
+
network_name (str): The name of the network to create.
|
|
626
|
+
driver (str): The network driver to use.
|
|
627
|
+
internal (bool): If True, create an internal network.
|
|
628
|
+
labels (dict, optional): Labels to apply to the network.
|
|
629
|
+
|
|
630
|
+
Returns:
|
|
631
|
+
str: A success message or error message.
|
|
632
|
+
"""
|
|
633
|
+
try:
|
|
634
|
+
network = self.client.networks.create(name=network_name, driver=driver, internal=internal, labels=labels)
|
|
635
|
+
return f"Network {network_name} created successfully with ID: {network.id}"
|
|
636
|
+
except DockerException as e:
|
|
637
|
+
error_msg = f"Error creating network: {str(e)}"
|
|
638
|
+
logger.error(error_msg)
|
|
639
|
+
return error_msg
|
|
640
|
+
|
|
641
|
+
def remove_network(self, network_name: str) -> str:
|
|
642
|
+
"""
|
|
643
|
+
Remove a Docker network.
|
|
644
|
+
|
|
645
|
+
Args:
|
|
646
|
+
network_name (str): The name of the network to remove.
|
|
647
|
+
|
|
648
|
+
Returns:
|
|
649
|
+
str: A success message or error message.
|
|
650
|
+
"""
|
|
651
|
+
try:
|
|
652
|
+
network = self.client.networks.get(network_name)
|
|
653
|
+
network.remove()
|
|
654
|
+
return f"Network {network_name} removed successfully"
|
|
655
|
+
except DockerException as e:
|
|
656
|
+
error_msg = f"Error removing network: {str(e)}"
|
|
657
|
+
logger.error(error_msg)
|
|
658
|
+
return error_msg
|
|
659
|
+
|
|
660
|
+
def inspect_network(self, network_name: str) -> str:
|
|
661
|
+
"""
|
|
662
|
+
Inspect a Docker network.
|
|
663
|
+
|
|
664
|
+
Args:
|
|
665
|
+
network_name (str): The name of the network.
|
|
666
|
+
|
|
667
|
+
Returns:
|
|
668
|
+
str: A JSON string containing detailed information about the network.
|
|
669
|
+
"""
|
|
670
|
+
try:
|
|
671
|
+
network = self.client.networks.get(network_name)
|
|
672
|
+
return json.dumps(network.attrs, indent=2)
|
|
673
|
+
except DockerException as e:
|
|
674
|
+
error_msg = f"Error inspecting network: {str(e)}"
|
|
675
|
+
logger.error(error_msg)
|
|
676
|
+
return error_msg
|
|
677
|
+
|
|
678
|
+
def connect_container_to_network(self, container_id: str, network_name: str) -> str:
|
|
679
|
+
"""
|
|
680
|
+
Connect a container to a network.
|
|
681
|
+
|
|
682
|
+
Args:
|
|
683
|
+
container_id (str): The ID or name of the container.
|
|
684
|
+
network_name (str): The name of the network.
|
|
685
|
+
|
|
686
|
+
Returns:
|
|
687
|
+
str: A success message or error message.
|
|
688
|
+
"""
|
|
689
|
+
try:
|
|
690
|
+
network = self.client.networks.get(network_name)
|
|
691
|
+
network.connect(container_id)
|
|
692
|
+
return f"Container {container_id} connected to network {network_name}"
|
|
693
|
+
except DockerException as e:
|
|
694
|
+
error_msg = f"Error connecting container to network: {str(e)}"
|
|
695
|
+
logger.error(error_msg)
|
|
696
|
+
return error_msg
|
|
697
|
+
|
|
698
|
+
def disconnect_container_from_network(self, container_id: str, network_name: str) -> str:
|
|
699
|
+
"""
|
|
700
|
+
Disconnect a container from a network.
|
|
701
|
+
|
|
702
|
+
Args:
|
|
703
|
+
container_id (str): The ID or name of the container.
|
|
704
|
+
network_name (str): The name of the network.
|
|
705
|
+
|
|
706
|
+
Returns:
|
|
707
|
+
str: A success message or error message.
|
|
708
|
+
"""
|
|
709
|
+
try:
|
|
710
|
+
network = self.client.networks.get(network_name)
|
|
711
|
+
network.disconnect(container_id)
|
|
712
|
+
return f"Container {container_id} disconnected from network {network_name}"
|
|
713
|
+
except DockerException as e:
|
|
714
|
+
error_msg = f"Error disconnecting container from network: {str(e)}"
|
|
715
|
+
logger.error(error_msg)
|
|
716
|
+
return error_msg
|