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/openai.py CHANGED
@@ -1,38 +1,202 @@
1
+ from os import getenv
2
+ from typing import Any, List, Literal, Optional, Union
3
+ from uuid import uuid4
4
+
5
+ from agno.agent import Agent
6
+ from agno.media import Audio, Image
7
+ from agno.team.team import Team
1
8
  from agno.tools import Toolkit
2
- from agno.utils.log import logger
9
+ from agno.tools.function import ToolResult
10
+ from agno.utils.log import log_debug, log_error, log_warning
3
11
 
4
12
  try:
5
13
  from openai import OpenAI as OpenAIClient
6
14
  except (ModuleNotFoundError, ImportError):
7
15
  raise ImportError("`openai` not installed. Please install using `pip install openai`")
8
16
 
9
-
10
- client = OpenAIClient()
17
+ # Define only types specifically needed by OpenAITools class
18
+ OpenAIVoice = Literal["alloy", "echo", "fable", "onyx", "nova", "shimmer"]
19
+ OpenAITTSModel = Literal["tts-1", "tts-1-hd"]
20
+ OpenAITTSFormat = Literal["mp3", "opus", "aac", "flac", "wav", "pcm"]
11
21
 
12
22
 
13
23
  class OpenAITools(Toolkit):
14
- """Tools for interacting with OpenAIChat API"""
24
+ """Tools for interacting with OpenAI API.
25
+
26
+ Args:
27
+ api_key (str, optional): OpenAI API key. Retrieved from OPENAI_API_KEY env variable if not provided.
28
+ enable_transcription (bool): Enable audio transcription functionality. Default is True.
29
+ enable_image_generation (bool): Enable image generation functionality. Default is True.
30
+ enable_speech_generation (bool): Enable speech generation functionality. Default is True.
31
+ all (bool): Enable all tools. Overrides individual flags when True. Default is False.
32
+ transcription_model (str): Model to use for transcription. Default is "whisper-1".
33
+ text_to_speech_voice (OpenAIVoice): Voice to use for TTS. Default is "alloy".
34
+ text_to_speech_model (OpenAITTSModel): Model to use for TTS. Default is "tts-1".
35
+ text_to_speech_format (OpenAITTSFormat): Audio format for TTS. Default is "mp3".
36
+ image_model (str, optional): Model to use for image generation. Default is "dall-e-3".
37
+ image_quality (str, optional): Quality setting for image generation.
38
+ image_size (str, optional): Size setting for image generation.
39
+ image_style (str, optional): Style setting for image generation.
40
+ """
41
+
42
+ def __init__(
43
+ self,
44
+ api_key: Optional[str] = None,
45
+ enable_transcription: bool = True,
46
+ enable_image_generation: bool = True,
47
+ enable_speech_generation: bool = True,
48
+ all: bool = False,
49
+ transcription_model: str = "whisper-1",
50
+ text_to_speech_voice: OpenAIVoice = "alloy",
51
+ text_to_speech_model: OpenAITTSModel = "tts-1",
52
+ text_to_speech_format: OpenAITTSFormat = "mp3",
53
+ image_model: Optional[str] = "dall-e-3",
54
+ image_quality: Optional[str] = None,
55
+ image_size: Optional[Literal["256x256", "512x512", "1024x1024", "1792x1024", "1024x1792"]] = None,
56
+ image_style: Optional[Literal["vivid", "natural"]] = None,
57
+ **kwargs,
58
+ ):
59
+ self.api_key = api_key or getenv("OPENAI_API_KEY")
60
+ if not self.api_key:
61
+ raise ValueError("OPENAI_API_KEY not set. Please set the OPENAI_API_KEY environment variable.")
15
62
 
16
- def __init__(self):
17
- super().__init__(name="openai_tools")
63
+ self.transcription_model = transcription_model
64
+ # Store TTS defaults
65
+ self.tts_voice = text_to_speech_voice
66
+ self.tts_model = text_to_speech_model
67
+ self.tts_format = text_to_speech_format
68
+ self.image_model = image_model
69
+ self.image_quality = image_quality
70
+ self.image_style = image_style
71
+ self.image_size = image_size
18
72
 
19
- self.register(self.transcribe_audio)
73
+ tools: List[Any] = []
74
+ if all or enable_transcription:
75
+ tools.append(self.transcribe_audio)
76
+ if all or enable_image_generation:
77
+ tools.append(self.generate_image)
78
+ if all or enable_speech_generation:
79
+ tools.append(self.generate_speech)
80
+
81
+ super().__init__(name="openai_tools", tools=tools, **kwargs)
20
82
 
21
83
  def transcribe_audio(self, audio_path: str) -> str:
22
84
  """Transcribe audio file using OpenAI's Whisper API
23
85
  Args:
24
86
  audio_path: Path to the audio file
25
- Returns:
26
- str: Transcribed text
27
87
  """
28
- logger.info(f"Transcribing audio from {audio_path}")
88
+ log_debug(f"Transcribing audio from {audio_path}")
89
+ try:
90
+ audio_file = open(audio_path, "rb")
91
+
92
+ transcript = OpenAIClient(api_key=self.api_key).audio.transcriptions.create(
93
+ model=self.transcription_model,
94
+ file=audio_file,
95
+ response_format="text",
96
+ )
97
+ except Exception as e: # type: ignore[return]
98
+ log_error(f"Failed to transcribe audio: {str(e)}")
99
+ return f"Failed to transcribe audio: {str(e)}"
100
+
101
+ log_debug(f"Transcript: {transcript}")
102
+ return transcript # type: ignore[return-value]
103
+
104
+ def generate_image(
105
+ self,
106
+ prompt: str,
107
+ ) -> ToolResult:
108
+ """Generate images based on a text prompt.
109
+ Args:
110
+ prompt (str): The text prompt to generate the image from.
111
+ """
29
112
  try:
30
- with open(audio_path, "rb") as audio_file:
31
- transcript = client.audio.transcriptions.create(
32
- model="whisper-1", file=audio_file, response_format="srt"
113
+ import base64
114
+
115
+ extra_params = {
116
+ "size": self.image_size,
117
+ "quality": self.image_quality,
118
+ "style": self.image_style,
119
+ }
120
+ extra_params = {k: v for k, v in extra_params.items() if v is not None}
121
+
122
+ # gpt-image-1 by default outputs a base64 encoded image but other models do not
123
+ # so we add a response_format parameter to have consistent output.
124
+ if self.image_model and self.image_model.startswith("gpt-image"):
125
+ response = OpenAIClient(api_key=self.api_key).images.generate(
126
+ model=self.image_model,
127
+ prompt=prompt,
128
+ **extra_params, # type: ignore
33
129
  )
34
- logger.info(f"Transcript: {transcript}")
35
- return transcript
130
+ else:
131
+ response = OpenAIClient(api_key=self.api_key).images.generate(
132
+ model=self.image_model,
133
+ prompt=prompt,
134
+ response_format="b64_json",
135
+ **extra_params, # type: ignore
136
+ )
137
+ data = None
138
+ if hasattr(response, "data") and response.data:
139
+ data = response.data[0]
140
+ if data is None:
141
+ log_warning("OpenAI API did not return any data.")
142
+ return ToolResult(content="Failed to generate image: No data received from API.")
143
+
144
+ if hasattr(data, "b64_json") and data.b64_json:
145
+ image_base64 = data.b64_json
146
+ media_id = str(uuid4())
147
+
148
+ # Decode base64 to bytes for proper storage
149
+ image_bytes = base64.b64decode(image_base64)
150
+
151
+ # Create ImageArtifact and return in ToolResult
152
+ image_artifact = Image(
153
+ id=media_id,
154
+ content=image_bytes, # ← Store as bytes, not encoded string
155
+ mime_type="image/png",
156
+ original_prompt=prompt,
157
+ )
158
+
159
+ return ToolResult(
160
+ content="Image generated successfully.",
161
+ images=[image_artifact],
162
+ )
163
+
164
+ return ToolResult(content="Failed to generate image: No content received from API.")
36
165
  except Exception as e:
37
- logger.error(f"Failed to transcribe audio: {str(e)}")
38
- return f"Failed to transcribe audio: {str(e)}"
166
+ log_error(f"Failed to generate image using {self.image_model}: {e}")
167
+ return ToolResult(content=f"Failed to generate image: {e}")
168
+
169
+ def generate_speech(
170
+ self,
171
+ agent: Union[Agent, Team],
172
+ text_input: str,
173
+ ) -> ToolResult: # Changed return type
174
+ """Generate speech from text using OpenAI's Text-to-Speech API.
175
+ Args:
176
+ text_input (str): The text to synthesize into speech.
177
+ """
178
+ try:
179
+ response = OpenAIClient(api_key=self.api_key).audio.speech.create(
180
+ model=self.tts_model,
181
+ voice=self.tts_voice,
182
+ input=text_input,
183
+ response_format=self.tts_format,
184
+ )
185
+
186
+ # Get raw audio data for artifact creation before potentially saving
187
+ audio_data: bytes = response.content
188
+
189
+ # Create AudioArtifact and return in ToolResult
190
+ media_id = str(uuid4())
191
+ audio_artifact = Audio(
192
+ id=media_id,
193
+ content=audio_data,
194
+ mime_type=f"audio/{self.tts_format}",
195
+ )
196
+
197
+ return ToolResult(
198
+ content=f"Speech generated successfully with ID: {media_id}",
199
+ audios=[audio_artifact],
200
+ )
201
+ except Exception as e:
202
+ return ToolResult(content=f"Failed to generate speech: {str(e)}")
agno/tools/openbb.py CHANGED
@@ -1,9 +1,9 @@
1
1
  import json
2
2
  from os import getenv
3
- from typing import Any, Literal, Optional
3
+ from typing import Any, List, Literal, Optional
4
4
 
5
5
  from agno.tools import Toolkit
6
- from agno.utils.log import logger
6
+ from agno.utils.log import log_debug, logger
7
7
 
8
8
  try:
9
9
  from openbb import obb as openbb_app
@@ -17,14 +17,14 @@ class OpenBBTools(Toolkit):
17
17
  obb: Optional[Any] = None,
18
18
  openbb_pat: Optional[str] = None,
19
19
  provider: Literal["benzinga", "fmp", "intrinio", "polygon", "tiingo", "tmx", "yfinance"] = "yfinance",
20
- stock_price: bool = True,
21
- search_symbols: bool = False,
22
- company_news: bool = False,
23
- company_profile: bool = False,
24
- price_targets: bool = False,
20
+ enable_get_stock_price: bool = True,
21
+ enable_search_company_symbol: bool = False,
22
+ enable_get_company_news: bool = False,
23
+ enable_get_company_profile: bool = False,
24
+ enable_get_price_targets: bool = False,
25
+ all: bool = False,
26
+ **kwargs,
25
27
  ):
26
- super().__init__(name="yfinance_tools")
27
-
28
28
  self.obb = obb or openbb_app
29
29
  try:
30
30
  if openbb_pat or getenv("OPENBB_PAT"):
@@ -34,16 +34,19 @@ class OpenBBTools(Toolkit):
34
34
 
35
35
  self.provider: Literal["benzinga", "fmp", "intrinio", "polygon", "tiingo", "tmx", "yfinance"] = provider
36
36
 
37
- if stock_price:
38
- self.register(self.get_stock_price)
39
- if search_symbols:
40
- self.register(self.search_company_symbol)
41
- if company_news:
42
- self.register(self.get_company_news)
43
- if company_profile:
44
- self.register(self.get_company_profile)
45
- if price_targets:
46
- self.register(self.get_price_targets)
37
+ tools: List[Any] = []
38
+ if enable_get_stock_price or all:
39
+ tools.append(self.get_stock_price)
40
+ if enable_search_company_symbol or all:
41
+ tools.append(self.search_company_symbol)
42
+ if enable_get_company_news or all:
43
+ tools.append(self.get_company_news)
44
+ if enable_get_company_profile or all:
45
+ tools.append(self.get_company_profile)
46
+ if enable_get_price_targets or all:
47
+ tools.append(self.get_price_targets)
48
+
49
+ super().__init__(name="openbb_tools", tools=tools, **kwargs)
47
50
 
48
51
  def get_stock_price(self, symbol: str) -> str:
49
52
  """Use this function to get the current stock price for a stock symbol or list of symbols.
@@ -56,6 +59,7 @@ class OpenBBTools(Toolkit):
56
59
  str: The current stock prices or error message.
57
60
  """
58
61
  try:
62
+ log_debug(f"Fetching current price for {symbol}")
59
63
  result = self.obb.equity.price.quote(symbol=symbol, provider=self.provider).to_polars() # type: ignore
60
64
  clean_results = []
61
65
  for row in result.to_dicts():
@@ -89,7 +93,7 @@ class OpenBBTools(Toolkit):
89
93
  str: A JSON string containing the ticker symbols.
90
94
  """
91
95
 
92
- logger.debug(f"Search ticker for {company_name}")
96
+ log_debug(f"Search ticker for {company_name}")
93
97
  result = self.obb.equity.search(company_name).to_polars() # type: ignore
94
98
  clean_results = []
95
99
  if len(result) > 0:
@@ -109,6 +113,7 @@ class OpenBBTools(Toolkit):
109
113
  str: JSON containing consensus price target and recommendations.
110
114
  """
111
115
  try:
116
+ log_debug(f"Fetching price targets for {symbol}")
112
117
  result = self.obb.equity.estimates.consensus(symbol=symbol, provider=self.provider).to_polars() # type: ignore
113
118
  return json.dumps(result.to_dicts(), indent=2, default=str)
114
119
  except Exception as e:
@@ -126,6 +131,7 @@ class OpenBBTools(Toolkit):
126
131
  str: JSON containing company news and press releases.
127
132
  """
128
133
  try:
134
+ log_debug(f"Fetching news for {symbol}")
129
135
  result = self.obb.news.company(symbol=symbol, provider=self.provider, limit=num_stories).to_polars() # type: ignore
130
136
  clean_results = []
131
137
  if len(result) > 0:
@@ -147,6 +153,7 @@ class OpenBBTools(Toolkit):
147
153
  str: JSON containing company profile and overview.
148
154
  """
149
155
  try:
156
+ log_debug(f"Fetching company profile for {symbol}")
150
157
  result = self.obb.equity.profile(symbol=symbol, provider=self.provider).to_polars() # type: ignore
151
158
  return json.dumps(result.to_dicts(), indent=2, default=str)
152
159
  except Exception as e:
agno/tools/opencv.py ADDED
@@ -0,0 +1,321 @@
1
+ import time
2
+ from pathlib import Path
3
+ from typing import Callable, List
4
+ from uuid import uuid4
5
+
6
+ from agno.agent import Agent
7
+ from agno.media import Image, Video
8
+ from agno.tools import Toolkit
9
+ from agno.tools.function import ToolResult
10
+ from agno.utils.log import log_debug, log_error, log_info
11
+
12
+ try:
13
+ import cv2
14
+ except ImportError:
15
+ raise ImportError("`opencv-python` package not found. Please install it with `pip install opencv-python`")
16
+
17
+
18
+ class OpenCVTools(Toolkit):
19
+ """Tools for capturing images and videos from the webcam using OpenCV"""
20
+
21
+ def __init__(
22
+ self,
23
+ show_preview=False,
24
+ enable_capture_image: bool = True,
25
+ enable_capture_video: bool = True,
26
+ all: bool = False,
27
+ **kwargs,
28
+ ):
29
+ self.show_preview = show_preview
30
+
31
+ tools: List[Callable] = []
32
+ if all or enable_capture_image:
33
+ tools.append(self.capture_image)
34
+ if all or enable_capture_video:
35
+ tools.append(self.capture_video)
36
+
37
+ super().__init__(
38
+ name="opencv_tools",
39
+ tools=tools,
40
+ **kwargs,
41
+ )
42
+
43
+ def capture_image(
44
+ self,
45
+ agent: Agent,
46
+ prompt: str = "Webcam capture",
47
+ ) -> ToolResult:
48
+ """Capture an image from the webcam.
49
+
50
+ Args:
51
+ prompt (str): Description of the image capture. Defaults to "Webcam capture".
52
+
53
+ Returns:
54
+ ToolResult: A ToolResult containing the captured image or error message.
55
+ """
56
+ try:
57
+ log_debug("Initializing webcam for image capture...")
58
+ cam = cv2.VideoCapture(0)
59
+
60
+ if not cam.isOpened():
61
+ cam = cv2.VideoCapture(0, cv2.CAP_AVFOUNDATION) # macOS
62
+ if not cam.isOpened():
63
+ cam = cv2.VideoCapture(0, cv2.CAP_DSHOW) # Windows
64
+ if not cam.isOpened():
65
+ cam = cv2.VideoCapture(0, cv2.CAP_V4L2) # Linux
66
+
67
+ if not cam.isOpened():
68
+ error_msg = "Could not open webcam. Please ensure your terminal has camera permissions and the camera is not being used by another application."
69
+ log_error(error_msg)
70
+ return ToolResult(content=error_msg)
71
+
72
+ try:
73
+ cam.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
74
+ cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
75
+ cam.set(cv2.CAP_PROP_FPS, 30)
76
+
77
+ log_debug("Camera initialized successfully")
78
+ captured_frame = None
79
+
80
+ if self.show_preview:
81
+ log_info("Live preview started. Press 'c' to capture image, 'q' to quit.")
82
+
83
+ while True:
84
+ ret, frame = cam.read()
85
+ if not ret:
86
+ error_msg = "Failed to read frame from webcam"
87
+ log_error(error_msg)
88
+ return ToolResult(content=error_msg)
89
+
90
+ cv2.imshow('Camera Preview - Press "c" to capture, "q" to quit', frame)
91
+
92
+ key = cv2.waitKey(1) & 0xFF
93
+ if key == ord("c"):
94
+ captured_frame = frame.copy()
95
+ log_info("Image captured!")
96
+ break
97
+ elif key == ord("q"):
98
+ log_info("Capture cancelled by user")
99
+ return ToolResult(content="Image capture cancelled by user")
100
+ else:
101
+ ret, captured_frame = cam.read()
102
+ if not ret:
103
+ error_msg = "Failed to capture image from webcam"
104
+ log_error(error_msg)
105
+ return ToolResult(content=error_msg)
106
+
107
+ if captured_frame is None:
108
+ error_msg = "No frame captured"
109
+ log_error(error_msg)
110
+ return ToolResult(content=error_msg)
111
+
112
+ success, encoded_image = cv2.imencode(".png", captured_frame)
113
+
114
+ if not success:
115
+ error_msg = "Failed to encode captured image"
116
+ log_error(error_msg)
117
+ return ToolResult(content=error_msg)
118
+
119
+ image_bytes = encoded_image.tobytes()
120
+ media_id = str(uuid4())
121
+
122
+ # Create ImageArtifact with raw bytes (not base64 encoded)
123
+ image_artifact = Image(
124
+ id=media_id,
125
+ content=image_bytes, # Store as raw bytes
126
+ original_prompt=prompt,
127
+ mime_type="image/png",
128
+ )
129
+
130
+ log_debug(f"Successfully captured and attached image {media_id}")
131
+ return ToolResult(
132
+ content="Image captured successfully",
133
+ images=[image_artifact],
134
+ )
135
+
136
+ finally:
137
+ # Release the camera and close windows
138
+ cam.release()
139
+ cv2.destroyAllWindows()
140
+ log_debug("Camera resources released")
141
+
142
+ except Exception as e:
143
+ error_msg = f"Error capturing image: {str(e)}"
144
+ log_error(error_msg)
145
+ return ToolResult(content=error_msg)
146
+
147
+ def capture_video(
148
+ self,
149
+ agent: Agent,
150
+ duration: int = 10,
151
+ prompt: str = "Webcam video capture",
152
+ ) -> ToolResult:
153
+ """Capture a video from the webcam.
154
+
155
+ Args:
156
+ duration (int): Duration in seconds to record video. Defaults to 10 seconds.
157
+ prompt (str): Description of the video capture. Defaults to "Webcam video capture".
158
+
159
+ Returns:
160
+ ToolResult: A ToolResult containing the captured video or error message.
161
+ """
162
+ try:
163
+ log_debug("Initializing webcam for video capture...")
164
+ cap = cv2.VideoCapture(0)
165
+
166
+ # Try different backends for better compatibility
167
+ if not cap.isOpened():
168
+ cap = cv2.VideoCapture(0, cv2.CAP_AVFOUNDATION) # macOS
169
+ if not cap.isOpened():
170
+ cap = cv2.VideoCapture(0, cv2.CAP_DSHOW) # Windows
171
+ if not cap.isOpened():
172
+ cap = cv2.VideoCapture(0, cv2.CAP_V4L2) # Linux
173
+
174
+ if not cap.isOpened():
175
+ error_msg = "Could not open webcam. Please ensure your terminal has camera permissions and the camera is not being used by another application."
176
+ log_error(error_msg)
177
+ return ToolResult(content=error_msg)
178
+
179
+ try:
180
+ frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
181
+ frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
182
+ actual_fps = cap.get(cv2.CAP_PROP_FPS)
183
+
184
+ # Use actual FPS or default to 30 if detection fails
185
+ if actual_fps <= 0 or actual_fps > 60:
186
+ actual_fps = 30.0
187
+
188
+ log_debug(f"Video properties: {frame_width}x{frame_height} at {actual_fps} FPS")
189
+
190
+ # Try different codecs in order of preference for compatibility
191
+ codecs_to_try = [
192
+ ("avc1", "H.264"), # Most compatible
193
+ ("mp4v", "MPEG-4"), # Fallback
194
+ ("XVID", "Xvid"), # Another fallback
195
+ ]
196
+
197
+ import os
198
+ import tempfile
199
+
200
+ with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as temp_file:
201
+ temp_filepath = temp_file.name
202
+
203
+ out = None
204
+ successful_codec = None
205
+
206
+ for codec_fourcc, codec_name in codecs_to_try:
207
+ try:
208
+ fourcc = getattr(cv2, "VideoWriter_fourcc")(*codec_fourcc)
209
+ out = cv2.VideoWriter(temp_filepath, fourcc, actual_fps, (frame_width, frame_height))
210
+
211
+ if out.isOpened():
212
+ successful_codec = codec_name
213
+ log_debug(f"Successfully initialized video writer with {codec_name} codec")
214
+ break
215
+ else:
216
+ out.release()
217
+ out = None
218
+ except Exception as e:
219
+ log_debug(f"Failed to initialize {codec_name} codec: {e}")
220
+ if out:
221
+ out.release()
222
+ out = None
223
+
224
+ if not out or not out.isOpened():
225
+ error_msg = "Failed to initialize video writer with any codec"
226
+ log_error(error_msg)
227
+ return ToolResult(content=error_msg)
228
+
229
+ start_time = time.time()
230
+ frame_count = 0
231
+
232
+ if self.show_preview:
233
+ log_info(f"Recording {duration}s video with live preview using {successful_codec} codec...")
234
+ else:
235
+ log_info(f"Recording {duration}s video using {successful_codec} codec...")
236
+
237
+ while True:
238
+ ret, frame = cap.read()
239
+
240
+ if not ret:
241
+ error_msg = "Failed to capture video frame"
242
+ log_error(error_msg)
243
+ return ToolResult(content=error_msg)
244
+
245
+ # Write the frame to the output file
246
+ out.write(frame)
247
+ frame_count += 1
248
+
249
+ # Show live preview if enabled
250
+ if self.show_preview:
251
+ # Add recording indicator
252
+ elapsed = time.time() - start_time
253
+ remaining = max(0, duration - elapsed)
254
+
255
+ # Draw recording info on frame
256
+ display_frame = frame.copy()
257
+ cv2.putText(
258
+ display_frame,
259
+ f"REC {remaining:.1f}s",
260
+ (10, 30),
261
+ cv2.FONT_HERSHEY_SIMPLEX,
262
+ 1,
263
+ (0, 0, 255),
264
+ 2,
265
+ )
266
+ cv2.circle(display_frame, (30, 60), 10, (0, 0, 255), -1) # Red dot
267
+
268
+ cv2.imshow(f"Recording Video - {remaining:.1f}s remaining", display_frame)
269
+ cv2.waitKey(1)
270
+
271
+ # Check if recording duration is reached
272
+ if time.time() - start_time >= duration:
273
+ break
274
+
275
+ # Release video writer
276
+ out.release()
277
+
278
+ # Verify the file was created and has content
279
+ temp_path = Path(temp_filepath)
280
+ if not temp_path.exists() or temp_path.stat().st_size == 0:
281
+ error_msg = "Video file was not created or is empty"
282
+ log_error(error_msg)
283
+ return ToolResult(content=error_msg)
284
+
285
+ # Read the video file and encode to base64
286
+ with open(temp_filepath, "rb") as video_file:
287
+ video_bytes = video_file.read()
288
+
289
+ # Clean up temporary file
290
+ os.unlink(temp_filepath)
291
+
292
+ media_id = str(uuid4())
293
+
294
+ # Create VideoArtifact with base64 encoded content
295
+ video_artifact = Video(
296
+ id=media_id,
297
+ content=video_bytes,
298
+ original_prompt=prompt,
299
+ mime_type="video/mp4",
300
+ )
301
+
302
+ actual_duration = time.time() - start_time
303
+ log_debug(
304
+ f"Successfully captured and attached video {media_id} ({actual_duration:.1f}s, {frame_count} frames)"
305
+ )
306
+
307
+ return ToolResult(
308
+ content=f"Video captured successfully and attached as artifact {media_id} ({actual_duration:.1f}s, {frame_count} frames, {successful_codec} codec)",
309
+ videos=[video_artifact],
310
+ )
311
+
312
+ finally:
313
+ if "cap" in locals():
314
+ cap.release()
315
+ cv2.destroyAllWindows()
316
+ log_debug("Video capture resources released")
317
+
318
+ except Exception as e:
319
+ error_msg = f"Error capturing video: {str(e)}"
320
+ log_error(error_msg)
321
+ return ToolResult(content=error_msg)