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.
Files changed (723) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +44 -5
  3. agno/agent/agent.py +10531 -2975
  4. agno/api/agent.py +14 -53
  5. agno/api/api.py +7 -46
  6. agno/api/evals.py +22 -0
  7. agno/api/os.py +17 -0
  8. agno/api/routes.py +6 -25
  9. agno/api/schemas/__init__.py +9 -0
  10. agno/api/schemas/agent.py +6 -9
  11. agno/api/schemas/evals.py +16 -0
  12. agno/api/schemas/os.py +14 -0
  13. agno/api/schemas/team.py +10 -10
  14. agno/api/schemas/utils.py +21 -0
  15. agno/api/schemas/workflows.py +16 -0
  16. agno/api/settings.py +53 -0
  17. agno/api/team.py +22 -26
  18. agno/api/workflow.py +28 -0
  19. agno/cloud/aws/base.py +214 -0
  20. agno/cloud/aws/s3/__init__.py +2 -0
  21. agno/cloud/aws/s3/api_client.py +43 -0
  22. agno/cloud/aws/s3/bucket.py +195 -0
  23. agno/cloud/aws/s3/object.py +57 -0
  24. agno/compression/__init__.py +3 -0
  25. agno/compression/manager.py +247 -0
  26. agno/culture/__init__.py +3 -0
  27. agno/culture/manager.py +956 -0
  28. agno/db/__init__.py +24 -0
  29. agno/db/async_postgres/__init__.py +3 -0
  30. agno/db/base.py +946 -0
  31. agno/db/dynamo/__init__.py +3 -0
  32. agno/db/dynamo/dynamo.py +2781 -0
  33. agno/db/dynamo/schemas.py +442 -0
  34. agno/db/dynamo/utils.py +743 -0
  35. agno/db/firestore/__init__.py +3 -0
  36. agno/db/firestore/firestore.py +2379 -0
  37. agno/db/firestore/schemas.py +181 -0
  38. agno/db/firestore/utils.py +376 -0
  39. agno/db/gcs_json/__init__.py +3 -0
  40. agno/db/gcs_json/gcs_json_db.py +1791 -0
  41. agno/db/gcs_json/utils.py +228 -0
  42. agno/db/in_memory/__init__.py +3 -0
  43. agno/db/in_memory/in_memory_db.py +1312 -0
  44. agno/db/in_memory/utils.py +230 -0
  45. agno/db/json/__init__.py +3 -0
  46. agno/db/json/json_db.py +1777 -0
  47. agno/db/json/utils.py +230 -0
  48. agno/db/migrations/manager.py +199 -0
  49. agno/db/migrations/v1_to_v2.py +635 -0
  50. agno/db/migrations/versions/v2_3_0.py +938 -0
  51. agno/db/mongo/__init__.py +17 -0
  52. agno/db/mongo/async_mongo.py +2760 -0
  53. agno/db/mongo/mongo.py +2597 -0
  54. agno/db/mongo/schemas.py +119 -0
  55. agno/db/mongo/utils.py +276 -0
  56. agno/db/mysql/__init__.py +4 -0
  57. agno/db/mysql/async_mysql.py +2912 -0
  58. agno/db/mysql/mysql.py +2923 -0
  59. agno/db/mysql/schemas.py +186 -0
  60. agno/db/mysql/utils.py +488 -0
  61. agno/db/postgres/__init__.py +4 -0
  62. agno/db/postgres/async_postgres.py +2579 -0
  63. agno/db/postgres/postgres.py +2870 -0
  64. agno/db/postgres/schemas.py +187 -0
  65. agno/db/postgres/utils.py +442 -0
  66. agno/db/redis/__init__.py +3 -0
  67. agno/db/redis/redis.py +2141 -0
  68. agno/db/redis/schemas.py +159 -0
  69. agno/db/redis/utils.py +346 -0
  70. agno/db/schemas/__init__.py +4 -0
  71. agno/db/schemas/culture.py +120 -0
  72. agno/db/schemas/evals.py +34 -0
  73. agno/db/schemas/knowledge.py +40 -0
  74. agno/db/schemas/memory.py +61 -0
  75. agno/db/singlestore/__init__.py +3 -0
  76. agno/db/singlestore/schemas.py +179 -0
  77. agno/db/singlestore/singlestore.py +2877 -0
  78. agno/db/singlestore/utils.py +384 -0
  79. agno/db/sqlite/__init__.py +4 -0
  80. agno/db/sqlite/async_sqlite.py +2911 -0
  81. agno/db/sqlite/schemas.py +181 -0
  82. agno/db/sqlite/sqlite.py +2908 -0
  83. agno/db/sqlite/utils.py +429 -0
  84. agno/db/surrealdb/__init__.py +3 -0
  85. agno/db/surrealdb/metrics.py +292 -0
  86. agno/db/surrealdb/models.py +334 -0
  87. agno/db/surrealdb/queries.py +71 -0
  88. agno/db/surrealdb/surrealdb.py +1908 -0
  89. agno/db/surrealdb/utils.py +147 -0
  90. agno/db/utils.py +118 -0
  91. agno/eval/__init__.py +24 -0
  92. agno/eval/accuracy.py +666 -276
  93. agno/eval/agent_as_judge.py +861 -0
  94. agno/eval/base.py +29 -0
  95. agno/eval/performance.py +779 -0
  96. agno/eval/reliability.py +241 -62
  97. agno/eval/utils.py +120 -0
  98. agno/exceptions.py +143 -1
  99. agno/filters.py +354 -0
  100. agno/guardrails/__init__.py +6 -0
  101. agno/guardrails/base.py +19 -0
  102. agno/guardrails/openai.py +144 -0
  103. agno/guardrails/pii.py +94 -0
  104. agno/guardrails/prompt_injection.py +52 -0
  105. agno/hooks/__init__.py +3 -0
  106. agno/hooks/decorator.py +164 -0
  107. agno/integrations/discord/__init__.py +3 -0
  108. agno/integrations/discord/client.py +203 -0
  109. agno/knowledge/__init__.py +5 -1
  110. agno/{document → knowledge}/chunking/agentic.py +22 -14
  111. agno/{document → knowledge}/chunking/document.py +2 -2
  112. agno/{document → knowledge}/chunking/fixed.py +7 -6
  113. agno/knowledge/chunking/markdown.py +151 -0
  114. agno/{document → knowledge}/chunking/recursive.py +15 -3
  115. agno/knowledge/chunking/row.py +39 -0
  116. agno/knowledge/chunking/semantic.py +91 -0
  117. agno/knowledge/chunking/strategy.py +165 -0
  118. agno/knowledge/content.py +74 -0
  119. agno/knowledge/document/__init__.py +5 -0
  120. agno/{document → knowledge/document}/base.py +12 -2
  121. agno/knowledge/embedder/__init__.py +5 -0
  122. agno/knowledge/embedder/aws_bedrock.py +343 -0
  123. agno/knowledge/embedder/azure_openai.py +210 -0
  124. agno/{embedder → knowledge/embedder}/base.py +8 -0
  125. agno/knowledge/embedder/cohere.py +323 -0
  126. agno/knowledge/embedder/fastembed.py +62 -0
  127. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  128. agno/knowledge/embedder/google.py +258 -0
  129. agno/knowledge/embedder/huggingface.py +94 -0
  130. agno/knowledge/embedder/jina.py +182 -0
  131. agno/knowledge/embedder/langdb.py +22 -0
  132. agno/knowledge/embedder/mistral.py +206 -0
  133. agno/knowledge/embedder/nebius.py +13 -0
  134. agno/knowledge/embedder/ollama.py +154 -0
  135. agno/knowledge/embedder/openai.py +195 -0
  136. agno/knowledge/embedder/sentence_transformer.py +63 -0
  137. agno/{embedder → knowledge/embedder}/together.py +1 -1
  138. agno/knowledge/embedder/vllm.py +262 -0
  139. agno/knowledge/embedder/voyageai.py +165 -0
  140. agno/knowledge/knowledge.py +3006 -0
  141. agno/knowledge/reader/__init__.py +7 -0
  142. agno/knowledge/reader/arxiv_reader.py +81 -0
  143. agno/knowledge/reader/base.py +95 -0
  144. agno/knowledge/reader/csv_reader.py +164 -0
  145. agno/knowledge/reader/docx_reader.py +82 -0
  146. agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
  147. agno/knowledge/reader/firecrawl_reader.py +201 -0
  148. agno/knowledge/reader/json_reader.py +88 -0
  149. agno/knowledge/reader/markdown_reader.py +137 -0
  150. agno/knowledge/reader/pdf_reader.py +431 -0
  151. agno/knowledge/reader/pptx_reader.py +101 -0
  152. agno/knowledge/reader/reader_factory.py +313 -0
  153. agno/knowledge/reader/s3_reader.py +89 -0
  154. agno/knowledge/reader/tavily_reader.py +193 -0
  155. agno/knowledge/reader/text_reader.py +127 -0
  156. agno/knowledge/reader/web_search_reader.py +325 -0
  157. agno/knowledge/reader/website_reader.py +455 -0
  158. agno/knowledge/reader/wikipedia_reader.py +91 -0
  159. agno/knowledge/reader/youtube_reader.py +78 -0
  160. agno/knowledge/remote_content/remote_content.py +88 -0
  161. agno/knowledge/reranker/__init__.py +3 -0
  162. agno/{reranker → knowledge/reranker}/base.py +1 -1
  163. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  164. agno/knowledge/reranker/infinity.py +195 -0
  165. agno/knowledge/reranker/sentence_transformer.py +54 -0
  166. agno/knowledge/types.py +39 -0
  167. agno/knowledge/utils.py +234 -0
  168. agno/media.py +439 -95
  169. agno/memory/__init__.py +16 -3
  170. agno/memory/manager.py +1474 -123
  171. agno/memory/strategies/__init__.py +15 -0
  172. agno/memory/strategies/base.py +66 -0
  173. agno/memory/strategies/summarize.py +196 -0
  174. agno/memory/strategies/types.py +37 -0
  175. agno/models/aimlapi/__init__.py +5 -0
  176. agno/models/aimlapi/aimlapi.py +62 -0
  177. agno/models/anthropic/__init__.py +4 -0
  178. agno/models/anthropic/claude.py +960 -496
  179. agno/models/aws/__init__.py +15 -0
  180. agno/models/aws/bedrock.py +686 -451
  181. agno/models/aws/claude.py +190 -183
  182. agno/models/azure/__init__.py +18 -1
  183. agno/models/azure/ai_foundry.py +489 -0
  184. agno/models/azure/openai_chat.py +89 -40
  185. agno/models/base.py +2477 -550
  186. agno/models/cerebras/__init__.py +12 -0
  187. agno/models/cerebras/cerebras.py +565 -0
  188. agno/models/cerebras/cerebras_openai.py +131 -0
  189. agno/models/cohere/__init__.py +4 -0
  190. agno/models/cohere/chat.py +306 -492
  191. agno/models/cometapi/__init__.py +5 -0
  192. agno/models/cometapi/cometapi.py +74 -0
  193. agno/models/dashscope/__init__.py +5 -0
  194. agno/models/dashscope/dashscope.py +90 -0
  195. agno/models/deepinfra/__init__.py +5 -0
  196. agno/models/deepinfra/deepinfra.py +45 -0
  197. agno/models/deepseek/__init__.py +4 -0
  198. agno/models/deepseek/deepseek.py +110 -9
  199. agno/models/fireworks/__init__.py +4 -0
  200. agno/models/fireworks/fireworks.py +19 -22
  201. agno/models/google/__init__.py +3 -7
  202. agno/models/google/gemini.py +1717 -662
  203. agno/models/google/utils.py +22 -0
  204. agno/models/groq/__init__.py +4 -0
  205. agno/models/groq/groq.py +391 -666
  206. agno/models/huggingface/__init__.py +4 -0
  207. agno/models/huggingface/huggingface.py +266 -538
  208. agno/models/ibm/__init__.py +5 -0
  209. agno/models/ibm/watsonx.py +432 -0
  210. agno/models/internlm/__init__.py +3 -0
  211. agno/models/internlm/internlm.py +20 -3
  212. agno/models/langdb/__init__.py +1 -0
  213. agno/models/langdb/langdb.py +60 -0
  214. agno/models/litellm/__init__.py +14 -0
  215. agno/models/litellm/chat.py +503 -0
  216. agno/models/litellm/litellm_openai.py +42 -0
  217. agno/models/llama_cpp/__init__.py +5 -0
  218. agno/models/llama_cpp/llama_cpp.py +22 -0
  219. agno/models/lmstudio/__init__.py +5 -0
  220. agno/models/lmstudio/lmstudio.py +25 -0
  221. agno/models/message.py +361 -39
  222. agno/models/meta/__init__.py +12 -0
  223. agno/models/meta/llama.py +502 -0
  224. agno/models/meta/llama_openai.py +79 -0
  225. agno/models/metrics.py +120 -0
  226. agno/models/mistral/__init__.py +4 -0
  227. agno/models/mistral/mistral.py +293 -393
  228. agno/models/nebius/__init__.py +3 -0
  229. agno/models/nebius/nebius.py +53 -0
  230. agno/models/nexus/__init__.py +3 -0
  231. agno/models/nexus/nexus.py +22 -0
  232. agno/models/nvidia/__init__.py +4 -0
  233. agno/models/nvidia/nvidia.py +22 -3
  234. agno/models/ollama/__init__.py +4 -2
  235. agno/models/ollama/chat.py +257 -492
  236. agno/models/openai/__init__.py +7 -0
  237. agno/models/openai/chat.py +725 -770
  238. agno/models/openai/like.py +16 -2
  239. agno/models/openai/responses.py +1121 -0
  240. agno/models/openrouter/__init__.py +4 -0
  241. agno/models/openrouter/openrouter.py +62 -5
  242. agno/models/perplexity/__init__.py +5 -0
  243. agno/models/perplexity/perplexity.py +203 -0
  244. agno/models/portkey/__init__.py +3 -0
  245. agno/models/portkey/portkey.py +82 -0
  246. agno/models/requesty/__init__.py +5 -0
  247. agno/models/requesty/requesty.py +69 -0
  248. agno/models/response.py +177 -7
  249. agno/models/sambanova/__init__.py +4 -0
  250. agno/models/sambanova/sambanova.py +23 -4
  251. agno/models/siliconflow/__init__.py +5 -0
  252. agno/models/siliconflow/siliconflow.py +42 -0
  253. agno/models/together/__init__.py +4 -0
  254. agno/models/together/together.py +21 -164
  255. agno/models/utils.py +266 -0
  256. agno/models/vercel/__init__.py +3 -0
  257. agno/models/vercel/v0.py +43 -0
  258. agno/models/vertexai/__init__.py +0 -1
  259. agno/models/vertexai/claude.py +190 -0
  260. agno/models/vllm/__init__.py +3 -0
  261. agno/models/vllm/vllm.py +83 -0
  262. agno/models/xai/__init__.py +2 -0
  263. agno/models/xai/xai.py +111 -7
  264. agno/os/__init__.py +3 -0
  265. agno/os/app.py +1027 -0
  266. agno/os/auth.py +244 -0
  267. agno/os/config.py +126 -0
  268. agno/os/interfaces/__init__.py +1 -0
  269. agno/os/interfaces/a2a/__init__.py +3 -0
  270. agno/os/interfaces/a2a/a2a.py +42 -0
  271. agno/os/interfaces/a2a/router.py +249 -0
  272. agno/os/interfaces/a2a/utils.py +924 -0
  273. agno/os/interfaces/agui/__init__.py +3 -0
  274. agno/os/interfaces/agui/agui.py +47 -0
  275. agno/os/interfaces/agui/router.py +147 -0
  276. agno/os/interfaces/agui/utils.py +574 -0
  277. agno/os/interfaces/base.py +25 -0
  278. agno/os/interfaces/slack/__init__.py +3 -0
  279. agno/os/interfaces/slack/router.py +148 -0
  280. agno/os/interfaces/slack/security.py +30 -0
  281. agno/os/interfaces/slack/slack.py +47 -0
  282. agno/os/interfaces/whatsapp/__init__.py +3 -0
  283. agno/os/interfaces/whatsapp/router.py +210 -0
  284. agno/os/interfaces/whatsapp/security.py +55 -0
  285. agno/os/interfaces/whatsapp/whatsapp.py +36 -0
  286. agno/os/mcp.py +293 -0
  287. agno/os/middleware/__init__.py +9 -0
  288. agno/os/middleware/jwt.py +797 -0
  289. agno/os/router.py +258 -0
  290. agno/os/routers/__init__.py +3 -0
  291. agno/os/routers/agents/__init__.py +3 -0
  292. agno/os/routers/agents/router.py +599 -0
  293. agno/os/routers/agents/schema.py +261 -0
  294. agno/os/routers/evals/__init__.py +3 -0
  295. agno/os/routers/evals/evals.py +450 -0
  296. agno/os/routers/evals/schemas.py +174 -0
  297. agno/os/routers/evals/utils.py +231 -0
  298. agno/os/routers/health.py +31 -0
  299. agno/os/routers/home.py +52 -0
  300. agno/os/routers/knowledge/__init__.py +3 -0
  301. agno/os/routers/knowledge/knowledge.py +1008 -0
  302. agno/os/routers/knowledge/schemas.py +178 -0
  303. agno/os/routers/memory/__init__.py +3 -0
  304. agno/os/routers/memory/memory.py +661 -0
  305. agno/os/routers/memory/schemas.py +88 -0
  306. agno/os/routers/metrics/__init__.py +3 -0
  307. agno/os/routers/metrics/metrics.py +190 -0
  308. agno/os/routers/metrics/schemas.py +47 -0
  309. agno/os/routers/session/__init__.py +3 -0
  310. agno/os/routers/session/session.py +997 -0
  311. agno/os/routers/teams/__init__.py +3 -0
  312. agno/os/routers/teams/router.py +512 -0
  313. agno/os/routers/teams/schema.py +257 -0
  314. agno/os/routers/traces/__init__.py +3 -0
  315. agno/os/routers/traces/schemas.py +414 -0
  316. agno/os/routers/traces/traces.py +499 -0
  317. agno/os/routers/workflows/__init__.py +3 -0
  318. agno/os/routers/workflows/router.py +624 -0
  319. agno/os/routers/workflows/schema.py +75 -0
  320. agno/os/schema.py +534 -0
  321. agno/os/scopes.py +469 -0
  322. agno/{playground → os}/settings.py +7 -15
  323. agno/os/utils.py +973 -0
  324. agno/reasoning/anthropic.py +80 -0
  325. agno/reasoning/azure_ai_foundry.py +67 -0
  326. agno/reasoning/deepseek.py +63 -0
  327. agno/reasoning/default.py +97 -0
  328. agno/reasoning/gemini.py +73 -0
  329. agno/reasoning/groq.py +71 -0
  330. agno/reasoning/helpers.py +24 -1
  331. agno/reasoning/ollama.py +67 -0
  332. agno/reasoning/openai.py +86 -0
  333. agno/reasoning/step.py +2 -1
  334. agno/reasoning/vertexai.py +76 -0
  335. agno/run/__init__.py +6 -0
  336. agno/run/agent.py +822 -0
  337. agno/run/base.py +247 -0
  338. agno/run/cancel.py +81 -0
  339. agno/run/requirement.py +181 -0
  340. agno/run/team.py +767 -0
  341. agno/run/workflow.py +708 -0
  342. agno/session/__init__.py +10 -0
  343. agno/session/agent.py +260 -0
  344. agno/session/summary.py +265 -0
  345. agno/session/team.py +342 -0
  346. agno/session/workflow.py +501 -0
  347. agno/table.py +10 -0
  348. agno/team/__init__.py +37 -0
  349. agno/team/team.py +9536 -0
  350. agno/tools/__init__.py +7 -0
  351. agno/tools/agentql.py +120 -0
  352. agno/tools/airflow.py +22 -12
  353. agno/tools/api.py +122 -0
  354. agno/tools/apify.py +276 -83
  355. agno/tools/{arxiv_toolkit.py → arxiv.py} +20 -12
  356. agno/tools/aws_lambda.py +28 -7
  357. agno/tools/aws_ses.py +66 -0
  358. agno/tools/baidusearch.py +11 -4
  359. agno/tools/bitbucket.py +292 -0
  360. agno/tools/brandfetch.py +213 -0
  361. agno/tools/bravesearch.py +106 -0
  362. agno/tools/brightdata.py +367 -0
  363. agno/tools/browserbase.py +209 -0
  364. agno/tools/calcom.py +32 -23
  365. agno/tools/calculator.py +24 -37
  366. agno/tools/cartesia.py +187 -0
  367. agno/tools/{clickup_tool.py → clickup.py} +17 -28
  368. agno/tools/confluence.py +91 -26
  369. agno/tools/crawl4ai.py +139 -43
  370. agno/tools/csv_toolkit.py +28 -22
  371. agno/tools/dalle.py +36 -22
  372. agno/tools/daytona.py +475 -0
  373. agno/tools/decorator.py +169 -14
  374. agno/tools/desi_vocal.py +23 -11
  375. agno/tools/discord.py +32 -29
  376. agno/tools/docker.py +716 -0
  377. agno/tools/duckdb.py +76 -81
  378. agno/tools/duckduckgo.py +43 -40
  379. agno/tools/e2b.py +703 -0
  380. agno/tools/eleven_labs.py +65 -54
  381. agno/tools/email.py +13 -5
  382. agno/tools/evm.py +129 -0
  383. agno/tools/exa.py +324 -42
  384. agno/tools/fal.py +39 -35
  385. agno/tools/file.py +196 -30
  386. agno/tools/file_generation.py +356 -0
  387. agno/tools/financial_datasets.py +288 -0
  388. agno/tools/firecrawl.py +108 -33
  389. agno/tools/function.py +960 -122
  390. agno/tools/giphy.py +34 -12
  391. agno/tools/github.py +1294 -97
  392. agno/tools/gmail.py +922 -0
  393. agno/tools/google_bigquery.py +117 -0
  394. agno/tools/google_drive.py +271 -0
  395. agno/tools/google_maps.py +253 -0
  396. agno/tools/googlecalendar.py +607 -107
  397. agno/tools/googlesheets.py +377 -0
  398. agno/tools/hackernews.py +20 -12
  399. agno/tools/jina.py +24 -14
  400. agno/tools/jira.py +48 -19
  401. agno/tools/knowledge.py +218 -0
  402. agno/tools/linear.py +82 -43
  403. agno/tools/linkup.py +58 -0
  404. agno/tools/local_file_system.py +15 -7
  405. agno/tools/lumalab.py +41 -26
  406. agno/tools/mcp/__init__.py +10 -0
  407. agno/tools/mcp/mcp.py +331 -0
  408. agno/tools/mcp/multi_mcp.py +347 -0
  409. agno/tools/mcp/params.py +24 -0
  410. agno/tools/mcp_toolbox.py +284 -0
  411. agno/tools/mem0.py +193 -0
  412. agno/tools/memory.py +419 -0
  413. agno/tools/mlx_transcribe.py +11 -9
  414. agno/tools/models/azure_openai.py +190 -0
  415. agno/tools/models/gemini.py +203 -0
  416. agno/tools/models/groq.py +158 -0
  417. agno/tools/models/morph.py +186 -0
  418. agno/tools/models/nebius.py +124 -0
  419. agno/tools/models_labs.py +163 -82
  420. agno/tools/moviepy_video.py +18 -13
  421. agno/tools/nano_banana.py +151 -0
  422. agno/tools/neo4j.py +134 -0
  423. agno/tools/newspaper.py +15 -4
  424. agno/tools/newspaper4k.py +19 -6
  425. agno/tools/notion.py +204 -0
  426. agno/tools/openai.py +181 -17
  427. agno/tools/openbb.py +27 -20
  428. agno/tools/opencv.py +321 -0
  429. agno/tools/openweather.py +233 -0
  430. agno/tools/oxylabs.py +385 -0
  431. agno/tools/pandas.py +25 -15
  432. agno/tools/parallel.py +314 -0
  433. agno/tools/postgres.py +238 -185
  434. agno/tools/pubmed.py +125 -13
  435. agno/tools/python.py +48 -35
  436. agno/tools/reasoning.py +283 -0
  437. agno/tools/reddit.py +207 -29
  438. agno/tools/redshift.py +406 -0
  439. agno/tools/replicate.py +69 -26
  440. agno/tools/resend.py +11 -6
  441. agno/tools/scrapegraph.py +179 -19
  442. agno/tools/searxng.py +23 -31
  443. agno/tools/serpapi.py +15 -10
  444. agno/tools/serper.py +255 -0
  445. agno/tools/shell.py +23 -12
  446. agno/tools/shopify.py +1519 -0
  447. agno/tools/slack.py +56 -14
  448. agno/tools/sleep.py +8 -6
  449. agno/tools/spider.py +35 -11
  450. agno/tools/spotify.py +919 -0
  451. agno/tools/sql.py +34 -19
  452. agno/tools/tavily.py +158 -8
  453. agno/tools/telegram.py +18 -8
  454. agno/tools/todoist.py +218 -0
  455. agno/tools/toolkit.py +134 -9
  456. agno/tools/trafilatura.py +388 -0
  457. agno/tools/trello.py +25 -28
  458. agno/tools/twilio.py +18 -9
  459. agno/tools/user_control_flow.py +78 -0
  460. agno/tools/valyu.py +228 -0
  461. agno/tools/visualization.py +467 -0
  462. agno/tools/webbrowser.py +28 -0
  463. agno/tools/webex.py +76 -0
  464. agno/tools/website.py +23 -19
  465. agno/tools/webtools.py +45 -0
  466. agno/tools/whatsapp.py +286 -0
  467. agno/tools/wikipedia.py +28 -19
  468. agno/tools/workflow.py +285 -0
  469. agno/tools/{twitter.py → x.py} +142 -46
  470. agno/tools/yfinance.py +41 -39
  471. agno/tools/youtube.py +34 -17
  472. agno/tools/zendesk.py +15 -5
  473. agno/tools/zep.py +454 -0
  474. agno/tools/zoom.py +86 -37
  475. agno/tracing/__init__.py +12 -0
  476. agno/tracing/exporter.py +157 -0
  477. agno/tracing/schemas.py +276 -0
  478. agno/tracing/setup.py +111 -0
  479. agno/utils/agent.py +938 -0
  480. agno/utils/audio.py +37 -1
  481. agno/utils/certs.py +27 -0
  482. agno/utils/code_execution.py +11 -0
  483. agno/utils/common.py +103 -20
  484. agno/utils/cryptography.py +22 -0
  485. agno/utils/dttm.py +33 -0
  486. agno/utils/events.py +700 -0
  487. agno/utils/functions.py +107 -37
  488. agno/utils/gemini.py +426 -0
  489. agno/utils/hooks.py +171 -0
  490. agno/utils/http.py +185 -0
  491. agno/utils/json_schema.py +159 -37
  492. agno/utils/knowledge.py +36 -0
  493. agno/utils/location.py +19 -0
  494. agno/utils/log.py +221 -8
  495. agno/utils/mcp.py +214 -0
  496. agno/utils/media.py +335 -14
  497. agno/utils/merge_dict.py +22 -1
  498. agno/utils/message.py +77 -2
  499. agno/utils/models/ai_foundry.py +50 -0
  500. agno/utils/models/claude.py +373 -0
  501. agno/utils/models/cohere.py +94 -0
  502. agno/utils/models/llama.py +85 -0
  503. agno/utils/models/mistral.py +100 -0
  504. agno/utils/models/openai_responses.py +140 -0
  505. agno/utils/models/schema_utils.py +153 -0
  506. agno/utils/models/watsonx.py +41 -0
  507. agno/utils/openai.py +257 -0
  508. agno/utils/pickle.py +1 -1
  509. agno/utils/pprint.py +124 -8
  510. agno/utils/print_response/agent.py +930 -0
  511. agno/utils/print_response/team.py +1914 -0
  512. agno/utils/print_response/workflow.py +1668 -0
  513. agno/utils/prompts.py +111 -0
  514. agno/utils/reasoning.py +108 -0
  515. agno/utils/response.py +163 -0
  516. agno/utils/serialize.py +32 -0
  517. agno/utils/shell.py +4 -4
  518. agno/utils/streamlit.py +487 -0
  519. agno/utils/string.py +204 -51
  520. agno/utils/team.py +139 -0
  521. agno/utils/timer.py +9 -2
  522. agno/utils/tokens.py +657 -0
  523. agno/utils/tools.py +19 -1
  524. agno/utils/whatsapp.py +305 -0
  525. agno/utils/yaml_io.py +3 -3
  526. agno/vectordb/__init__.py +2 -0
  527. agno/vectordb/base.py +87 -9
  528. agno/vectordb/cassandra/__init__.py +5 -1
  529. agno/vectordb/cassandra/cassandra.py +383 -27
  530. agno/vectordb/chroma/__init__.py +4 -0
  531. agno/vectordb/chroma/chromadb.py +748 -83
  532. agno/vectordb/clickhouse/__init__.py +7 -1
  533. agno/vectordb/clickhouse/clickhousedb.py +554 -53
  534. agno/vectordb/couchbase/__init__.py +3 -0
  535. agno/vectordb/couchbase/couchbase.py +1446 -0
  536. agno/vectordb/lancedb/__init__.py +5 -0
  537. agno/vectordb/lancedb/lance_db.py +730 -98
  538. agno/vectordb/langchaindb/__init__.py +5 -0
  539. agno/vectordb/langchaindb/langchaindb.py +163 -0
  540. agno/vectordb/lightrag/__init__.py +5 -0
  541. agno/vectordb/lightrag/lightrag.py +388 -0
  542. agno/vectordb/llamaindex/__init__.py +3 -0
  543. agno/vectordb/llamaindex/llamaindexdb.py +166 -0
  544. agno/vectordb/milvus/__init__.py +3 -0
  545. agno/vectordb/milvus/milvus.py +966 -78
  546. agno/vectordb/mongodb/__init__.py +9 -1
  547. agno/vectordb/mongodb/mongodb.py +1175 -172
  548. agno/vectordb/pgvector/__init__.py +8 -0
  549. agno/vectordb/pgvector/pgvector.py +599 -115
  550. agno/vectordb/pineconedb/__init__.py +5 -1
  551. agno/vectordb/pineconedb/pineconedb.py +406 -43
  552. agno/vectordb/qdrant/__init__.py +4 -0
  553. agno/vectordb/qdrant/qdrant.py +914 -61
  554. agno/vectordb/redis/__init__.py +9 -0
  555. agno/vectordb/redis/redisdb.py +682 -0
  556. agno/vectordb/singlestore/__init__.py +8 -1
  557. agno/vectordb/singlestore/singlestore.py +771 -0
  558. agno/vectordb/surrealdb/__init__.py +3 -0
  559. agno/vectordb/surrealdb/surrealdb.py +663 -0
  560. agno/vectordb/upstashdb/__init__.py +5 -0
  561. agno/vectordb/upstashdb/upstashdb.py +718 -0
  562. agno/vectordb/weaviate/__init__.py +8 -0
  563. agno/vectordb/weaviate/index.py +15 -0
  564. agno/vectordb/weaviate/weaviate.py +1009 -0
  565. agno/workflow/__init__.py +23 -1
  566. agno/workflow/agent.py +299 -0
  567. agno/workflow/condition.py +759 -0
  568. agno/workflow/loop.py +756 -0
  569. agno/workflow/parallel.py +853 -0
  570. agno/workflow/router.py +723 -0
  571. agno/workflow/step.py +1564 -0
  572. agno/workflow/steps.py +613 -0
  573. agno/workflow/types.py +556 -0
  574. agno/workflow/workflow.py +4327 -514
  575. agno-2.3.13.dist-info/METADATA +639 -0
  576. agno-2.3.13.dist-info/RECORD +613 -0
  577. {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/WHEEL +1 -1
  578. agno-2.3.13.dist-info/licenses/LICENSE +201 -0
  579. agno/api/playground.py +0 -91
  580. agno/api/schemas/playground.py +0 -22
  581. agno/api/schemas/user.py +0 -22
  582. agno/api/schemas/workspace.py +0 -46
  583. agno/api/user.py +0 -160
  584. agno/api/workspace.py +0 -151
  585. agno/cli/auth_server.py +0 -118
  586. agno/cli/config.py +0 -275
  587. agno/cli/console.py +0 -88
  588. agno/cli/credentials.py +0 -23
  589. agno/cli/entrypoint.py +0 -571
  590. agno/cli/operator.py +0 -355
  591. agno/cli/settings.py +0 -85
  592. agno/cli/ws/ws_cli.py +0 -817
  593. agno/constants.py +0 -13
  594. agno/document/__init__.py +0 -1
  595. agno/document/chunking/semantic.py +0 -47
  596. agno/document/chunking/strategy.py +0 -31
  597. agno/document/reader/__init__.py +0 -1
  598. agno/document/reader/arxiv_reader.py +0 -41
  599. agno/document/reader/base.py +0 -22
  600. agno/document/reader/csv_reader.py +0 -84
  601. agno/document/reader/docx_reader.py +0 -46
  602. agno/document/reader/firecrawl_reader.py +0 -99
  603. agno/document/reader/json_reader.py +0 -43
  604. agno/document/reader/pdf_reader.py +0 -219
  605. agno/document/reader/s3/pdf_reader.py +0 -46
  606. agno/document/reader/s3/text_reader.py +0 -51
  607. agno/document/reader/text_reader.py +0 -41
  608. agno/document/reader/website_reader.py +0 -175
  609. agno/document/reader/youtube_reader.py +0 -50
  610. agno/embedder/__init__.py +0 -1
  611. agno/embedder/azure_openai.py +0 -86
  612. agno/embedder/cohere.py +0 -72
  613. agno/embedder/fastembed.py +0 -37
  614. agno/embedder/google.py +0 -73
  615. agno/embedder/huggingface.py +0 -54
  616. agno/embedder/mistral.py +0 -80
  617. agno/embedder/ollama.py +0 -57
  618. agno/embedder/openai.py +0 -74
  619. agno/embedder/sentence_transformer.py +0 -38
  620. agno/embedder/voyageai.py +0 -64
  621. agno/eval/perf.py +0 -201
  622. agno/file/__init__.py +0 -1
  623. agno/file/file.py +0 -16
  624. agno/file/local/csv.py +0 -32
  625. agno/file/local/txt.py +0 -19
  626. agno/infra/app.py +0 -240
  627. agno/infra/base.py +0 -144
  628. agno/infra/context.py +0 -20
  629. agno/infra/db_app.py +0 -52
  630. agno/infra/resource.py +0 -205
  631. agno/infra/resources.py +0 -55
  632. agno/knowledge/agent.py +0 -230
  633. agno/knowledge/arxiv.py +0 -22
  634. agno/knowledge/combined.py +0 -22
  635. agno/knowledge/csv.py +0 -28
  636. agno/knowledge/csv_url.py +0 -19
  637. agno/knowledge/document.py +0 -20
  638. agno/knowledge/docx.py +0 -30
  639. agno/knowledge/json.py +0 -28
  640. agno/knowledge/langchain.py +0 -71
  641. agno/knowledge/llamaindex.py +0 -66
  642. agno/knowledge/pdf.py +0 -28
  643. agno/knowledge/pdf_url.py +0 -26
  644. agno/knowledge/s3/base.py +0 -60
  645. agno/knowledge/s3/pdf.py +0 -21
  646. agno/knowledge/s3/text.py +0 -23
  647. agno/knowledge/text.py +0 -30
  648. agno/knowledge/website.py +0 -88
  649. agno/knowledge/wikipedia.py +0 -31
  650. agno/knowledge/youtube.py +0 -22
  651. agno/memory/agent.py +0 -392
  652. agno/memory/classifier.py +0 -104
  653. agno/memory/db/__init__.py +0 -1
  654. agno/memory/db/base.py +0 -42
  655. agno/memory/db/mongodb.py +0 -189
  656. agno/memory/db/postgres.py +0 -203
  657. agno/memory/db/sqlite.py +0 -193
  658. agno/memory/memory.py +0 -15
  659. agno/memory/row.py +0 -36
  660. agno/memory/summarizer.py +0 -192
  661. agno/memory/summary.py +0 -19
  662. agno/memory/workflow.py +0 -38
  663. agno/models/google/gemini_openai.py +0 -26
  664. agno/models/ollama/hermes.py +0 -221
  665. agno/models/ollama/tools.py +0 -362
  666. agno/models/vertexai/gemini.py +0 -595
  667. agno/playground/__init__.py +0 -3
  668. agno/playground/async_router.py +0 -421
  669. agno/playground/deploy.py +0 -249
  670. agno/playground/operator.py +0 -92
  671. agno/playground/playground.py +0 -91
  672. agno/playground/schemas.py +0 -76
  673. agno/playground/serve.py +0 -55
  674. agno/playground/sync_router.py +0 -405
  675. agno/reasoning/agent.py +0 -68
  676. agno/run/response.py +0 -112
  677. agno/storage/agent/__init__.py +0 -0
  678. agno/storage/agent/base.py +0 -38
  679. agno/storage/agent/dynamodb.py +0 -350
  680. agno/storage/agent/json.py +0 -92
  681. agno/storage/agent/mongodb.py +0 -228
  682. agno/storage/agent/postgres.py +0 -367
  683. agno/storage/agent/session.py +0 -79
  684. agno/storage/agent/singlestore.py +0 -303
  685. agno/storage/agent/sqlite.py +0 -357
  686. agno/storage/agent/yaml.py +0 -93
  687. agno/storage/workflow/__init__.py +0 -0
  688. agno/storage/workflow/base.py +0 -40
  689. agno/storage/workflow/mongodb.py +0 -233
  690. agno/storage/workflow/postgres.py +0 -366
  691. agno/storage/workflow/session.py +0 -60
  692. agno/storage/workflow/sqlite.py +0 -359
  693. agno/tools/googlesearch.py +0 -88
  694. agno/utils/defaults.py +0 -57
  695. agno/utils/filesystem.py +0 -39
  696. agno/utils/git.py +0 -52
  697. agno/utils/json_io.py +0 -30
  698. agno/utils/load_env.py +0 -19
  699. agno/utils/py_io.py +0 -19
  700. agno/utils/pyproject.py +0 -18
  701. agno/utils/resource_filter.py +0 -31
  702. agno/vectordb/singlestore/s2vectordb.py +0 -390
  703. agno/vectordb/singlestore/s2vectordb2.py +0 -355
  704. agno/workspace/__init__.py +0 -0
  705. agno/workspace/config.py +0 -325
  706. agno/workspace/enums.py +0 -6
  707. agno/workspace/helpers.py +0 -48
  708. agno/workspace/operator.py +0 -758
  709. agno/workspace/settings.py +0 -63
  710. agno-0.1.2.dist-info/LICENSE +0 -375
  711. agno-0.1.2.dist-info/METADATA +0 -502
  712. agno-0.1.2.dist-info/RECORD +0 -352
  713. agno-0.1.2.dist-info/entry_points.txt +0 -3
  714. /agno/{cli → db/migrations}/__init__.py +0 -0
  715. /agno/{cli/ws → db/migrations/versions}/__init__.py +0 -0
  716. /agno/{document/chunking/__init__.py → db/schemas/metrics.py} +0 -0
  717. /agno/{document/reader/s3 → integrations}/__init__.py +0 -0
  718. /agno/{file/local → knowledge/chunking}/__init__.py +0 -0
  719. /agno/{infra → knowledge/remote_content}/__init__.py +0 -0
  720. /agno/{knowledge/s3 → tools/models}/__init__.py +0 -0
  721. /agno/{reranker → utils/models}/__init__.py +0 -0
  722. /agno/{storage → utils/print_response}/__init__.py +0 -0
  723. {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