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
@@ -0,0 +1,186 @@
1
+ import os
2
+ from os import getenv
3
+ from textwrap import dedent
4
+ from typing import Optional
5
+
6
+ from agno.tools import Toolkit
7
+ from agno.utils.log import log_debug, log_error
8
+
9
+ try:
10
+ from openai import OpenAI
11
+ except ImportError:
12
+ raise ImportError("`openai` not installed. Please install using `pip install openai`")
13
+
14
+
15
+ class MorphTools(Toolkit):
16
+ """Tools for interacting with Morph's Fast Apply API for code editing"""
17
+
18
+ def __init__(
19
+ self,
20
+ api_key: Optional[str] = None,
21
+ base_url: str = "https://api.morphllm.com/v1",
22
+ instructions: Optional[str] = None,
23
+ add_instructions: bool = True,
24
+ model: str = "morph-v3-large",
25
+ **kwargs,
26
+ ):
27
+ """Initialize Morph Fast Apply tools.
28
+
29
+ Args:
30
+ api_key: Morph API key. If not provided, will look for MORPH_API_KEY environment variable.
31
+ base_url: The base URL for the Morph API.
32
+ model: The Morph model to use. Options:
33
+ - "morph-v3-fast" (4500+ tok/sec, 96% accuracy)
34
+ - "morph-v3-large" (2500+ tok/sec, 98% accuracy)
35
+ - "auto" (automatic selection)
36
+ **kwargs: Additional arguments to pass to Toolkit.
37
+ """
38
+ # Set up instructions
39
+ if instructions is None:
40
+ self.instructions = self.DEFAULT_INSTRUCTIONS
41
+ else:
42
+ self.instructions = instructions
43
+
44
+ super().__init__(
45
+ name="morph_tools",
46
+ tools=[self.edit_file],
47
+ instructions=self.instructions,
48
+ add_instructions=add_instructions,
49
+ **kwargs,
50
+ )
51
+
52
+ self.api_key = api_key or getenv("MORPH_API_KEY")
53
+ if not self.api_key:
54
+ raise ValueError("MORPH_API_KEY not set. Please set the MORPH_API_KEY environment variable.")
55
+
56
+ self.base_url = base_url
57
+ self.model = model
58
+ self._morph_client: Optional[OpenAI] = None
59
+
60
+ def _get_client(self):
61
+ """Get or create the Morph OpenAI client."""
62
+ if self._morph_client is None:
63
+ self._morph_client = OpenAI(
64
+ api_key=self.api_key,
65
+ base_url=self.base_url,
66
+ )
67
+ return self._morph_client
68
+
69
+ def edit_file(
70
+ self,
71
+ target_file: str,
72
+ instructions: str,
73
+ code_edit: str,
74
+ original_code: Optional[str] = None,
75
+ ) -> str:
76
+ """
77
+ Apply code edits to a target file using Morph's Fast Apply API.
78
+
79
+ This function reads the specified file, sends its content along with
80
+ editing instructions and code edits to Morph's API, and writes the
81
+ resulting code back to the file. A backup of the original file is
82
+ created before writing changes.
83
+
84
+ Args:
85
+ target_file (str): Path to the file to be edited.
86
+ instructions (str): High-level instructions describing the intended change.
87
+ code_edit (str): Specific code edit or change to apply.
88
+ original_code (Optional[str], optional): Original content of the file.
89
+ If not provided, the function reads from target_file.
90
+
91
+ Returns:
92
+ str: Result message indicating success or failure, and details about
93
+ the backup and any errors encountered.
94
+ """
95
+ try:
96
+ # Always read the actual file content for backup purposes
97
+ actual_file_content = None
98
+ if os.path.exists(target_file):
99
+ try:
100
+ with open(target_file, "r", encoding="utf-8") as f:
101
+ actual_file_content = f.read()
102
+ except Exception as e:
103
+ return f"Error reading {target_file} for backup: {e}"
104
+ else:
105
+ return f"Error: File {target_file} does not exist."
106
+
107
+ # Use provided original_code or fall back to file content
108
+ code_to_process = original_code if original_code is not None else actual_file_content
109
+
110
+ # Format the message for Morph's Fast Apply API
111
+ content = f"<instruction>{instructions}</instruction>\n<code>{code_to_process}</code>\n<update>{code_edit}</update>"
112
+
113
+ log_debug(f"Input to Morph: {content}")
114
+
115
+ client = self._get_client()
116
+
117
+ response = client.chat.completions.create(
118
+ model=self.model,
119
+ messages=[
120
+ {
121
+ "role": "user",
122
+ "content": content,
123
+ }
124
+ ],
125
+ )
126
+
127
+ if response.choices and response.choices[0].message.content:
128
+ final_code = response.choices[0].message.content
129
+
130
+ try:
131
+ backup_file = f"{target_file}.backup"
132
+ with open(backup_file, "w", encoding="utf-8") as f:
133
+ f.write(actual_file_content)
134
+
135
+ # Write the new code
136
+ with open(target_file, "w", encoding="utf-8") as f:
137
+ f.write(final_code)
138
+ return f"Successfully applied edit to {target_file} using Morph Fast Apply! Original content backed up as {backup_file}"
139
+
140
+ except Exception as e:
141
+ return f"Successfully applied edit but failed to write back to {target_file}: {e}"
142
+
143
+ else:
144
+ return f"Failed to apply edit to {target_file}: No response from Morph API"
145
+
146
+ except Exception as e:
147
+ log_error(f"Failed to apply edit using Morph Fast Apply: {e}")
148
+ return f"Failed to apply edit to {target_file}: {e}"
149
+
150
+ DEFAULT_INSTRUCTIONS = dedent("""\
151
+ You have access to Morph Fast Apply for ultra-fast code editing with 98% accuracy at 2500+ tokens/second.
152
+
153
+ ## How to use the edit_file tool:
154
+
155
+ **Critical Requirements:**
156
+ 1. **Instructions Parameter**: Generate clear first-person instructions describing what you're doing
157
+ - Example: "I am adding type hints to all functions and methods"
158
+ - Example: "I am refactoring the error handling to use try-catch blocks"
159
+
160
+ 2. **Code Edit Parameter**: Specify ONLY the lines you want to change
161
+ - Use `# ... existing code ...` (or `// ... existing code ...` for JS/Java) to represent unchanged sections
162
+ - NEVER write out unchanged code in the code_edit parameter
163
+ - Include sufficient context around changes to resolve ambiguity
164
+
165
+ 3. **Single Edit Call**: Make ALL edits to a file in a single edit_file call. The apply model can handle many distinct edits at once.
166
+
167
+ **Example Format:**
168
+ ```
169
+ # ... existing code ...
170
+ def add(a: int, b: int) -> int:
171
+ \"\"\"Add two numbers together.\"\"\"
172
+ return a + b
173
+ # ... existing code ...
174
+ def multiply(x: int, y: int) -> int:
175
+ \"\"\"Multiply two numbers.\"\"\"
176
+ return x * y
177
+ # ... existing code ...
178
+ ```
179
+
180
+ **Important Guidelines:**
181
+ - Bias towards repeating as few lines as possible while conveying the change clearly
182
+ - Each edit should contain sufficient context of unchanged lines around the code you're editing
183
+ - DO NOT omit spans of pre-existing code without using the `# ... existing code ...` comment
184
+ - If deleting a section, provide context before and after to clearly indicate the deletion
185
+ - The tool automatically creates backup files before applying changes\
186
+ """)
@@ -0,0 +1,124 @@
1
+ import base64
2
+ from os import getenv
3
+ from typing import Optional
4
+ from uuid import uuid4
5
+
6
+ from agno.agent import Agent
7
+ from agno.media import Image
8
+ from agno.models.nebius import Nebius
9
+ from agno.tools import Toolkit
10
+ from agno.tools.function import ToolResult
11
+ from agno.utils.log import log_error, log_warning
12
+
13
+
14
+ class NebiusTools(Toolkit):
15
+ """Tools for interacting with Nebius Token Factory's text-to-image API"""
16
+
17
+ def __init__(
18
+ self,
19
+ api_key: Optional[str] = None,
20
+ base_url: str = "https://api.tokenfactory.nebius.com/v1",
21
+ image_model: str = "black-forest-labs/flux-schnell",
22
+ image_quality: Optional[str] = "standard",
23
+ image_size: Optional[str] = "1024x1024",
24
+ image_style: Optional[str] = None,
25
+ enable_generate_image: bool = True,
26
+ all: bool = False,
27
+ **kwargs,
28
+ ):
29
+ """Initialize Nebius Token Factory text-to-image tools.
30
+
31
+ Args:
32
+ api_key: Nebius API key. If not provided, will look for NEBIUS_API_KEY environment variable.
33
+ base_url: The base URL for the Nebius Token Factory API. This should be configured according to Nebius's documentation.
34
+ image_model: The model to use for generation. Options include:
35
+ - "black-forest-labs/flux-schnell" (fastest)
36
+ - "black-forest-labs/flux-dev" (balanced)
37
+ - "stability-ai/sdxl" (highest quality)
38
+ image_quality: Image quality. Options: "standard", "hd".
39
+ image_size: Image size in format "WIDTHxHEIGHT". Max supported: 2000x2000.
40
+ image_style: Optional style preset to apply.
41
+ enable_generate_image: Enable image generation functionality.
42
+ all: Enable all functions.
43
+ **kwargs: Additional arguments to pass to Toolkit.
44
+ """
45
+ tools = []
46
+ if all or enable_generate_image:
47
+ tools.append(self.generate_image)
48
+
49
+ super().__init__(name="nebius_tools", tools=tools, **kwargs)
50
+
51
+ self.api_key = api_key or getenv("NEBIUS_API_KEY")
52
+ if not self.api_key:
53
+ raise ValueError("NEBIUS_API_KEY not set. Please set the NEBIUS_API_KEY environment variable.")
54
+
55
+ self.base_url = base_url
56
+ self.image_model = image_model
57
+ self.image_quality = image_quality
58
+ self.image_size = image_size
59
+ self.image_style = image_style
60
+ self._nebius_client: Optional[Nebius] = None
61
+
62
+ def _get_client(self):
63
+ if self._nebius_client is None:
64
+ self._nebius_client = Nebius(api_key=self.api_key, base_url=self.base_url, id=self.image_model).get_client() # type: ignore
65
+ return self._nebius_client
66
+
67
+ def generate_image(
68
+ self,
69
+ agent: Agent,
70
+ prompt: str,
71
+ ) -> ToolResult:
72
+ """Generate images based on a text prompt using Nebius Token Factory.
73
+
74
+ Args:
75
+ agent: The agent instance for adding images
76
+ prompt: The text prompt to generate images from.
77
+
78
+ Returns:
79
+ ToolResult: A ToolResult containing the generated image or error message.
80
+ """
81
+ try:
82
+ extra_params = {
83
+ "size": self.image_size,
84
+ "quality": self.image_quality,
85
+ "style": self.image_style,
86
+ }
87
+ extra_params = {k: v for k, v in extra_params.items() if v is not None}
88
+
89
+ client = self._get_client()
90
+
91
+ response = client.images.generate(
92
+ model=self.image_model,
93
+ prompt=prompt,
94
+ response_format="b64_json",
95
+ **extra_params,
96
+ )
97
+
98
+ data = None
99
+ if hasattr(response, "data") and response.data:
100
+ data = response.data[0]
101
+ if data is None:
102
+ log_warning("Nebius API did not return any data.")
103
+ return ToolResult(content="Failed to generate image: No data received from API.")
104
+
105
+ if hasattr(data, "b64_json") and data.b64_json:
106
+ image_base64 = data.b64_json
107
+ image_content_bytes = base64.b64decode(image_base64)
108
+ media_id = str(uuid4())
109
+
110
+ # Create ImageArtifact with raw bytes
111
+ image_artifact = Image(
112
+ id=media_id, content=image_content_bytes, mime_type="image/png", original_prompt=prompt
113
+ )
114
+
115
+ return ToolResult(
116
+ content="Image generated successfully.",
117
+ images=[image_artifact],
118
+ )
119
+
120
+ return ToolResult(content="Failed to generate image: No content received from API.")
121
+
122
+ except Exception as e:
123
+ log_error(f"Failed to generate image using {self.image_model}: {e}")
124
+ return ToolResult(content=f"Failed to generate image: {e}")
agno/tools/models_labs.py CHANGED
@@ -1,124 +1,205 @@
1
1
  import json
2
2
  import time
3
3
  from os import getenv
4
- from typing import Optional
4
+ from typing import Any, Dict, List, Optional, Union
5
5
  from uuid import uuid4
6
6
 
7
- from agno.agent import Agent
8
- from agno.media import ImageArtifact, VideoArtifact
7
+ from agno.media import Audio, Image, Video
9
8
  from agno.models.response import FileType
10
9
  from agno.tools import Toolkit
11
- from agno.utils.log import logger
10
+ from agno.tools.function import ToolResult
11
+ from agno.utils.log import log_debug, log_info, logger
12
12
 
13
13
  try:
14
14
  import requests
15
+ from requests.exceptions import RequestException
15
16
  except ImportError:
16
17
  raise ImportError("`requests` not installed. Please install using `pip install requests`")
17
18
 
19
+ MODELS_LAB_URLS = {
20
+ "MP4": "https://modelslab.com/api/v6/video/text2video",
21
+ "MP3": "https://modelslab.com/api/v6/voice/music_gen",
22
+ "GIF": "https://modelslab.com/api/v6/video/text2video",
23
+ "WAV": "https://modelslab.com/api/v6/voice/sfx",
24
+ }
25
+
26
+ MODELS_LAB_FETCH_URLS = {
27
+ "MP4": "https://modelslab.com/api/v6/video/fetch",
28
+ "MP3": "https://modelslab.com/api/v6/voice/fetch",
29
+ "GIF": "https://modelslab.com/api/v6/video/fetch",
30
+ "WAV": "https://modelslab.com/api/v6/voice/fetch",
31
+ }
32
+
18
33
 
19
34
  class ModelsLabTools(Toolkit):
20
35
  def __init__(
21
36
  self,
22
37
  api_key: Optional[str] = None,
23
- url: str = "https://modelslab.com/api/v6/video/text2video",
24
- fetch_url: str = "https://modelslab.com/api/v6/video/fetch",
25
- # Whether to wait for the video to be ready
26
38
  wait_for_completion: bool = False,
27
- # Time to add to the ETA to account for the time it takes to fetch the video
28
39
  add_to_eta: int = 15,
29
- # Maximum time to wait for the video to be ready
30
40
  max_wait_time: int = 60,
31
41
  file_type: FileType = FileType.MP4,
42
+ **kwargs,
32
43
  ):
33
- super().__init__(name="models_labs")
34
-
35
- self.url = url
36
- self.fetch_url = fetch_url
44
+ file_type_str = file_type.value.upper()
45
+ self.url = MODELS_LAB_URLS[file_type_str]
46
+ self.fetch_url = MODELS_LAB_FETCH_URLS[file_type_str]
37
47
  self.wait_for_completion = wait_for_completion
38
48
  self.add_to_eta = add_to_eta
39
49
  self.max_wait_time = max_wait_time
40
50
  self.file_type = file_type
41
51
  self.api_key = api_key or getenv("MODELS_LAB_API_KEY")
52
+
42
53
  if not self.api_key:
43
54
  logger.error("MODELS_LAB_API_KEY not set. Please set the MODELS_LAB_API_KEY environment variable.")
44
55
 
45
- self.register(self.generate_media)
46
-
47
- def generate_media(self, agent: Agent, prompt: str) -> str:
48
- """Use this function to generate a video or image given a prompt.
49
-
50
- Args:
51
- prompt (str): A text description of the desired video.
52
-
53
- Returns:
54
- str: A message indicating if the video has been generated successfully or an error message.
55
- """
56
+ tools: List[Any] = []
57
+ tools.append(self.generate_media)
58
+
59
+ super().__init__(name="models_labs", tools=tools, **kwargs)
60
+
61
+ def _create_payload(self, prompt: str) -> Dict[str, Any]:
62
+ """Create payload based on file type."""
63
+ base_payload: Dict[str, Any] = {
64
+ "key": self.api_key,
65
+ "prompt": prompt,
66
+ "webhook": None,
67
+ "track_id": None,
68
+ }
69
+
70
+ if self.file_type in [FileType.MP4, FileType.GIF]:
71
+ video_template = {
72
+ "height": 512,
73
+ "width": 512,
74
+ "num_frames": 25,
75
+ "negative_prompt": "low quality",
76
+ "model_id": "cogvideox",
77
+ "instant_response": False,
78
+ "output_type": self.file_type.value,
79
+ }
80
+ base_payload |= video_template # Use |= instead of update()
81
+ elif self.file_type == FileType.WAV:
82
+ sfx_template = {
83
+ "duration": 10,
84
+ "output_format": "wav",
85
+ "temp": False,
86
+ }
87
+ base_payload |= sfx_template # Use |= instead of update()
88
+ else:
89
+ audio_template = {
90
+ "base64": False,
91
+ "temp": False,
92
+ }
93
+ base_payload |= audio_template # Use |= instead of update()
94
+
95
+ return base_payload
96
+
97
+ def _create_media_artifacts(self, media_id: str, media_url: str, eta: Optional[str] = None) -> Dict[str, List]:
98
+ """Create appropriate media artifacts based on file type."""
99
+ artifacts: Dict[str, List[Union[Image, Video, Audio]]] = {
100
+ "images": [],
101
+ "videos": [],
102
+ "audios": [],
103
+ }
104
+
105
+ if self.file_type == FileType.MP4:
106
+ video_artifact = Video(id=str(media_id), url=media_url, eta=str(eta))
107
+ artifacts["videos"].append(video_artifact)
108
+ elif self.file_type == FileType.GIF:
109
+ image_artifact = Image(id=str(media_id), url=media_url)
110
+ artifacts["images"].append(image_artifact)
111
+ elif self.file_type in [FileType.MP3, FileType.WAV]:
112
+ audio_artifact = Audio(id=str(media_id), url=media_url)
113
+ artifacts["audios"].append(audio_artifact)
114
+
115
+ return artifacts
116
+
117
+ def _wait_for_media(self, media_id: str, eta: int) -> bool:
118
+ """Wait for media generation to complete."""
119
+ time_to_wait = min(eta + self.add_to_eta, self.max_wait_time)
120
+ log_info(f"Waiting for {time_to_wait} seconds for {self.file_type.value} to be ready")
121
+
122
+ for seconds_waited in range(time_to_wait):
123
+ try:
124
+ fetch_response = requests.post(
125
+ f"{self.fetch_url}/{media_id}",
126
+ json={"key": self.api_key},
127
+ headers={"Content-Type": "application/json"},
128
+ )
129
+ fetch_result = fetch_response.json()
130
+
131
+ if fetch_result.get("status") == "success":
132
+ return True
133
+
134
+ time.sleep(1)
135
+
136
+ except RequestException as e:
137
+ logger.warning(f"Error during fetch attempt {seconds_waited}: {e}")
138
+
139
+ return False
140
+
141
+ def generate_media(self, prompt: str) -> ToolResult:
142
+ """Generate media (video, image, or audio) given a prompt."""
56
143
  if not self.api_key:
57
- return "Please set the MODELS_LAB_API_KEY"
144
+ return ToolResult(content="Please set the MODELS_LAB_API_KEY")
58
145
 
59
146
  try:
60
- payload = json.dumps(
61
- {
62
- "key": self.api_key,
63
- "prompt": prompt,
64
- "height": 512,
65
- "width": 512,
66
- "num_frames": 25,
67
- "webhook": None,
68
- "output_type": self.file_type.value,
69
- "track_id": None,
70
- "negative_prompt": "low quality",
71
- "model_id": "cogvideox",
72
- "instant_response": False,
73
- }
74
- )
75
-
147
+ payload = json.dumps(self._create_payload(prompt))
76
148
  headers = {"Content-Type": "application/json"}
77
- logger.debug(f"Generating video for prompt: {prompt}")
78
- response = requests.request("POST", self.url, data=payload, headers=headers)
149
+
150
+ log_debug(f"Generating {self.file_type.value} for prompt: {prompt}")
151
+ response = requests.post(self.url, data=payload, headers=headers)
79
152
  response.raise_for_status()
80
153
 
81
154
  result = response.json()
82
- if "error" in result:
83
- logger.error(f"Failed to generate video: {result['error']}")
84
- return f"Error: {result['error']}"
85
-
86
- eta = result["eta"]
87
- url_links = result["future_links"]
88
- logger.info(f"Media will be ready in {eta} seconds")
89
- logger.info(f"Media URLs: {url_links}")
90
155
 
91
- video_id = str(uuid4())
156
+ status = result.get("status")
157
+ if status == "error":
158
+ logger.error(f"Error in response: {result.get('message')}")
159
+ return ToolResult(content=f"Error: {result.get('message')}")
92
160
 
93
- logger.debug(f"Result: {result}")
161
+ if "error" in result:
162
+ error_msg = f"Failed to generate {self.file_type.value}: {result['error']}"
163
+ logger.error(error_msg)
164
+ return ToolResult(content=f"Error: {result['error']}")
165
+
166
+ eta = result.get("eta")
167
+ media_id = str(uuid4())
168
+
169
+ # Collect all media artifacts
170
+ all_images = []
171
+ all_videos = []
172
+ all_audios = []
173
+
174
+ if self.file_type == FileType.WAV:
175
+ url_links = result.get("output", [])
176
+ else:
177
+ url_links = result.get("future_links")
94
178
  for media_url in url_links:
95
- if self.file_type == FileType.MP4:
96
- agent.add_video(VideoArtifact(id=str(video_id), url=media_url, eta=str(eta)))
97
- elif self.file_type == FileType.GIF:
98
- agent.add_image(ImageArtifact(id=str(video_id), url=media_url))
99
-
100
- if self.wait_for_completion and isinstance(eta, int):
101
- video_ready = False
102
- seconds_waited = 0
103
- time_to_wait = min(eta + self.add_to_eta, self.max_wait_time)
104
- logger.info(f"Waiting for {time_to_wait} seconds for video to be ready")
105
- while not video_ready and seconds_waited < time_to_wait:
106
- time.sleep(1)
107
- seconds_waited += 1
108
- # Fetch the video from the ModelsLabs API
109
- fetch_payload = json.dumps({"key": self.api_key})
110
- fetch_headers = {"Content-Type": "application/json"}
111
- logger.debug(f"Fetching video from {self.fetch_url}/{video_id}")
112
- fetch_response = requests.request(
113
- "POST", f"{self.fetch_url}/{video_id}", data=fetch_payload, headers=fetch_headers
114
- )
115
- fetch_result = fetch_response.json()
116
- logger.debug(f"Fetch result: {fetch_result}")
117
- if fetch_result.get("status") == "success":
118
- video_ready = True
119
- break
120
-
121
- return f"Video has been generated successfully and will be ready in {eta} seconds"
179
+ artifacts = self._create_media_artifacts(media_id, media_url, str(eta))
180
+ all_images.extend(artifacts["images"])
181
+ all_videos.extend(artifacts["videos"])
182
+ all_audios.extend(artifacts["audios"])
183
+
184
+ if self.wait_for_completion and isinstance(eta, int):
185
+ if self._wait_for_media(media_id, eta):
186
+ log_info("Media generation completed successfully")
187
+ else:
188
+ logger.warning("Media generation timed out")
189
+
190
+ # Return ToolResult with appropriate media artifacts
191
+ return ToolResult(
192
+ content=f"{self.file_type.value.capitalize()} has been generated successfully and will be ready in {eta} seconds",
193
+ images=all_images if all_images else None,
194
+ videos=all_videos if all_videos else None,
195
+ audios=all_audios if all_audios else None,
196
+ )
197
+
198
+ except RequestException as e:
199
+ error_msg = f"Network error while generating {self.file_type.value}: {e}"
200
+ logger.error(error_msg)
201
+ return ToolResult(content=f"Error: {error_msg}")
122
202
  except Exception as e:
123
- logger.error(f"Failed to generate video: {e}")
124
- return f"Error: {e}"
203
+ error_msg = f"Unexpected error while generating {self.file_type.value}: {e}"
204
+ logger.error(error_msg)
205
+ return ToolResult(content=f"Error: {error_msg}")
@@ -1,7 +1,7 @@
1
- from typing import Dict, List, Optional
1
+ from typing import Any, Dict, List, Optional
2
2
 
3
3
  from agno.tools import Toolkit
4
- from agno.utils.log import logger
4
+ from agno.utils.log import log_debug, log_info, logger
5
5
 
6
6
  try:
7
7
  from moviepy import ColorClip, CompositeVideoClip, TextClip, VideoFileClip # type: ignore
@@ -14,18 +14,21 @@ class MoviePyVideoTools(Toolkit):
14
14
 
15
15
  def __init__(
16
16
  self,
17
- process_video: bool = True,
18
- generate_captions: bool = True,
19
- embed_captions: bool = True,
17
+ enable_process_video: bool = True,
18
+ enable_generate_captions: bool = True,
19
+ enable_embed_captions: bool = True,
20
+ all: bool = False,
21
+ **kwargs,
20
22
  ):
21
- super().__init__(name="video_tools")
23
+ tools: List[Any] = []
24
+ if enable_process_video or all:
25
+ tools.append(self.extract_audio)
26
+ if enable_generate_captions or all:
27
+ tools.append(self.create_srt)
28
+ if enable_embed_captions or all:
29
+ tools.append(self.embed_captions)
22
30
 
23
- if process_video:
24
- self.register(self.extract_audio)
25
- if generate_captions:
26
- self.register(self.create_srt)
27
- if embed_captions:
28
- self.register(self.embed_captions)
31
+ super().__init__(name="video_tools", tools=tools, **kwargs)
29
32
 
30
33
  def split_text_into_lines(self, words: List[Dict]) -> List[Dict]:
31
34
  """Split transcribed words into lines based on duration and length constraints
@@ -227,9 +230,10 @@ class MoviePyVideoTools(Toolkit):
227
230
  str: Path to the extracted audio file
228
231
  """
229
232
  try:
233
+ log_debug(f"Extracting audio from {video_path}")
230
234
  video = VideoFileClip(video_path)
231
235
  video.audio.write_audiofile(output_path)
232
- logger.info(f"Audio extracted to {output_path}")
236
+ log_info(f"Audio extracted to {output_path}")
233
237
  return output_path
234
238
  except Exception as e:
235
239
  logger.error(f"Failed to extract audio: {str(e)}")
@@ -244,6 +248,7 @@ class MoviePyVideoTools(Toolkit):
244
248
  str: Path to the created SRT file, or error message if failed
245
249
  """
246
250
  try:
251
+ log_debug(f"Creating SRT file at {output_path}")
247
252
  # Since we're getting SRT format from Whisper API now,
248
253
  # we can just write it directly to file
249
254
  with open(output_path, "w", encoding="utf-8") as f: