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,117 @@
1
+ import json
2
+ from os import getenv
3
+ from typing import Any, List, Optional
4
+
5
+ from agno.tools import Toolkit
6
+ from agno.utils.log import log_debug, logger
7
+
8
+ try:
9
+ from google.cloud import bigquery
10
+ except ImportError:
11
+ raise ImportError("`bigquery` not installed. Please install using `pip install google-cloud-bigquery`")
12
+
13
+
14
+ class GoogleBigQueryTools(Toolkit):
15
+ def __init__(
16
+ self,
17
+ dataset: str,
18
+ project: Optional[str] = None,
19
+ location: Optional[str] = None,
20
+ credentials: Optional[Any] = None,
21
+ enable_list_tables: bool = True,
22
+ enable_describe_table: bool = True,
23
+ enable_run_sql_query: bool = True,
24
+ all: bool = False,
25
+ **kwargs,
26
+ ):
27
+ self.project = project or getenv("GOOGLE_CLOUD_PROJECT")
28
+ self.location = location or getenv("GOOGLE_CLOUD_LOCATION")
29
+
30
+ if not self.project:
31
+ raise ValueError("project is required")
32
+ if not self.location:
33
+ raise ValueError("location is required")
34
+
35
+ self.dataset = dataset
36
+
37
+ # Initialize the BQ CLient
38
+ self.client = bigquery.Client(project=self.project, credentials=credentials)
39
+
40
+ tools: List[Any] = []
41
+ if all or enable_list_tables:
42
+ tools.append(self.list_tables)
43
+ if all or enable_describe_table:
44
+ tools.append(self.describe_table)
45
+ if all or enable_run_sql_query:
46
+ tools.append(self.run_sql_query)
47
+
48
+ super().__init__(name="google_bigquery_tools", tools=tools, **kwargs)
49
+
50
+ def list_tables(self) -> str:
51
+ """Use this function to get a list of table names in the dataset.
52
+ Returns:
53
+ str: list of tables in the dataset.
54
+ """
55
+ try:
56
+ log_debug("listing tables in the database")
57
+ tables = self.client.list_tables(self.dataset)
58
+ tables_str = str([table.table_id for table in tables])
59
+ log_debug(f"table_names: {tables_str}")
60
+ return tables_str
61
+ except Exception as e:
62
+ logger.error(f"Error getting tables: {e}")
63
+ return f"Error getting tables: {e}"
64
+
65
+ def describe_table(self, table_id: str) -> str:
66
+ """Use this function to describe a table.
67
+ Args:
68
+ table_name (str): The name of the table to get the schema for.
69
+ Returns:
70
+ str: schema of a table
71
+ """
72
+ try:
73
+ table_id = f"{self.project}.{self.dataset}.{table_id}"
74
+ log_debug(f"Describing table: {table_id}")
75
+ api_response = self.client.get_table(table_id)
76
+ table_api_repr = api_response.to_api_repr()
77
+ desc = str(table_api_repr.get("description", ""))
78
+ col_names = str([column["name"] for column in table_api_repr["schema"]["fields"]]) # Columns in a table
79
+ result = json.dumps({"table_description": desc, "columns": col_names})
80
+ return result
81
+ except Exception as e:
82
+ logger.error(f"Error getting table schema: {e}")
83
+ return f"Error getting table schema: {e}"
84
+
85
+ def run_sql_query(self, query: str) -> str:
86
+ """Use this function to run a BigQuery SQL query and return the result.
87
+ Args:
88
+ query (str): The query to run.
89
+ Returns:
90
+ str: Result of the Google BigQuery SQL query.
91
+ Notes:
92
+ - The result may be empty if the query does not return any data.
93
+ """
94
+ try:
95
+ return json.dumps(self._run_sql(sql=query), default=str)
96
+ except Exception as e:
97
+ logger.error(f"Error running query: {e}")
98
+ return f"Error running query: {e}"
99
+
100
+ def _run_sql(self, sql: str) -> str:
101
+ """Internal function to run a sql query.
102
+ Args:
103
+ sql (str): The sql query to run.
104
+ Returns:
105
+ results (str): The result of the query.
106
+ """
107
+ try:
108
+ log_debug(f"Running Google SQL |\n{sql}")
109
+ cleaned_query = sql.replace("\\n", " ").replace("\n", "").replace("\\", "")
110
+ job_config = bigquery.QueryJobConfig(default_dataset=f"{self.project}.{self.dataset}")
111
+ query_job = self.client.query(cleaned_query, job_config)
112
+ results = query_job.result()
113
+ results_str = str([dict(row) for row in results])
114
+ return results_str.replace("\\", "").replace("\n", "")
115
+ except Exception as e:
116
+ logger.error(f"Error while executing SQL: {e}")
117
+ return ""
@@ -0,0 +1,271 @@
1
+ """
2
+ Google Drive API integration for file management and sharing.
3
+
4
+
5
+ This module provides functions to interact with Google Drive, including listing,
6
+ uploading, and downloading files.
7
+ It uses the Google Drive API and handles authentication via OAuth2.
8
+
9
+ Required Environment Variables:
10
+ -----------------------------
11
+ - GOOGLE_CLIENT_ID: Google OAuth client ID
12
+ - GOOGLE_CLIENT_SECRET: Google OAuth client secret
13
+ - GOOGLE_PROJECT_ID: Google Cloud project ID
14
+ - GOOGLE_REDIRECT_URI: Google OAuth redirect URI (default: http://localhost)
15
+ - GOOGLE_CLOUD_QUOTA_PROJECT_ID: Google Cloud quota project ID
16
+
17
+ How to Get These Credentials:
18
+ ---------------------------
19
+ 1. Go to Google Cloud Console (https://console.cloud.google.com)
20
+ 2. Create a new project or select an existing one
21
+ 3. Enable the Google Drive API:
22
+ - Go to "APIs & Services" > "Enable APIs and Services"
23
+ - Search for "Google Drive API"
24
+ - Click "Enable"
25
+
26
+ 4. Create OAuth 2.0 credentials:
27
+ - Go to "APIs & Services" > "Credentials"
28
+ - Click "Create Credentials" > "OAuth client ID"
29
+ - Enable the OAuth Consent Screen if you haven't already
30
+ - After enabling the Consent Screen, click on "Create Credentials" > "OAuth client ID"
31
+ - You'll receive:
32
+ * Client ID (GOOGLE_CLIENT_ID)
33
+ * Client Secret (GOOGLE_CLIENT_SECRET)
34
+ - The Project ID (GOOGLE_PROJECT_ID) is visible in the project dropdown at the top of the page
35
+
36
+ 5. Add auth redirect URI:
37
+ - Go to https://console.cloud.google.com/auth/clients
38
+ - Add `http://localhost:5050` as a recognized redirect URI OR with http://localhost:{PORT_NUMBER}
39
+
40
+
41
+ 6. Set up environment variables:
42
+ Create a .envrc file in your project root with:
43
+ ``
44
+ export GOOGLE_CLIENT_ID=your_client_id_here
45
+ export GOOGLE_CLIENT_SECRET=your_client_secret_here
46
+ export GOOGLE_PROJECT_ID=your_project_id_here
47
+ export GOOGLE_REDIRECT_URI=http://localhost/ # Default value
48
+ export GOOGLE_AUTHENTICATION_PORT=5050 # Port for OAuth redirect
49
+ export GOOGLE_CLOUD_QUOTA_PROJECT_ID=your_quota_project_id_here
50
+ ``
51
+
52
+ ---
53
+
54
+ Remember to install the dependencies using `pip install google google-auth-oauthlib`
55
+
56
+ Important Points to Note :
57
+ 1. The first time you run the application, it will open a browser window for OAuth authentication.
58
+ 2. A token.json file will be created to store the authentication credentials for future use.
59
+
60
+ You can customize the authentication port by setting the `GOOGLE_AUTHENTICATION_PORT` environment variable.
61
+ This will be used in the `run_local_server` method for OAuth authentication.
62
+
63
+ """
64
+
65
+ import mimetypes
66
+ from functools import wraps
67
+ from os import getenv
68
+ from pathlib import Path
69
+ from typing import Any, List, Optional, Union
70
+
71
+ from agno.tools import Toolkit
72
+ from agno.utils.log import log_error
73
+
74
+ try:
75
+ from google.auth.transport.requests import Request
76
+ from google.oauth2.credentials import Credentials
77
+ from google_auth_oauthlib.flow import InstalledAppFlow
78
+ from googleapiclient.discovery import Resource, build
79
+ from googleapiclient.http import MediaFileUpload, MediaIoBaseDownload
80
+ except ImportError:
81
+ raise ImportError(
82
+ "Google client library for Python not found , install it using `pip install google-api-python-client google-auth-httplib2 google-auth-oauthlib`"
83
+ )
84
+
85
+
86
+ def authenticate(func):
87
+ """Decorator to ensure authentication before executing a function."""
88
+
89
+ @wraps(func)
90
+ def wrapper(self, *args, **kwargs):
91
+ if not self.creds or not self.creds.valid:
92
+ self._auth()
93
+ if not self.service:
94
+ # Set quota project on credentials if available
95
+ creds_to_use = self.creds
96
+ if hasattr(self, "quota_project_id") and self.quota_project_id:
97
+ creds_to_use = self.creds.with_quota_project(self.quota_project_id)
98
+ self.service = build("drive", "v3", credentials=creds_to_use)
99
+ return func(self, *args, **kwargs)
100
+
101
+ return wrapper
102
+
103
+
104
+ class GoogleDriveTools(Toolkit):
105
+ # Default scopes for Google Drive API access
106
+ DEFAULT_SCOPES = ["https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/drive.readonly"]
107
+
108
+ def __init__(
109
+ self,
110
+ auth_port: Optional[int] = 5050,
111
+ creds: Optional[Credentials] = None,
112
+ scopes: Optional[List[str]] = None,
113
+ creds_path: Optional[str] = None,
114
+ token_path: Optional[str] = None,
115
+ quota_project_id: Optional[str] = None,
116
+ **kwargs,
117
+ ):
118
+ self.creds: Optional[Credentials] = creds
119
+ self.service: Optional[Resource] = None
120
+ self.credentials_path = creds_path
121
+ self.token_path = token_path
122
+ self.scopes = scopes or []
123
+ self.scopes.extend(self.DEFAULT_SCOPES)
124
+
125
+ self.quota_project_id = quota_project_id or getenv("GOOGLE_CLOUD_QUOTA_PROJECT_ID")
126
+ if not self.quota_project_id:
127
+ raise ValueError("GOOGLE_CLOUD_QUOTA_PROJECT_ID is not set")
128
+
129
+ self.auth_port: int = int(getenv("GOOGLE_AUTH_PORT", str(auth_port)))
130
+ if not self.auth_port:
131
+ raise ValueError("GOOGLE_AUTH_PORT is not set")
132
+
133
+ tools: List[Any] = [
134
+ self.list_files,
135
+ ]
136
+ super().__init__(name="google_drive_tools", tools=tools, **kwargs)
137
+ if not self.scopes:
138
+ # Add read permission by default
139
+ self.scopes.append(self.DEFAULT_SCOPES[1]) # 'drive.readonly'
140
+ # Add write permission if allow_update is True
141
+ if getattr(self, "allow_update", False):
142
+ self.scopes.append(self.DEFAULT_SCOPES[0]) # 'drive.file'
143
+
144
+ def _auth(self):
145
+ """
146
+ Authenticate and set up the Google Drive API client.
147
+ This method checks if credentials are valid and refreshes or requests them if needed.
148
+ """
149
+ if self.creds and self.creds.valid:
150
+ # Already authenticated
151
+ return
152
+
153
+ token_file = Path(self.token_path or "token.json")
154
+ creds_file = Path(self.credentials_path or "credentials.json")
155
+
156
+ if token_file.exists():
157
+ self.creds = Credentials.from_authorized_user_file(str(token_file), self.scopes)
158
+ if not self.creds or not self.creds.valid:
159
+ if self.creds and self.creds.expired and self.creds.refresh_token:
160
+ self.creds.refresh(Request())
161
+ else:
162
+ client_config = {
163
+ "installed": {
164
+ "client_id": getenv("GOOGLE_CLIENT_ID"),
165
+ "client_secret": getenv("GOOGLE_CLIENT_SECRET"),
166
+ "project_id": getenv("GOOGLE_PROJECT_ID"),
167
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
168
+ "token_uri": "https://oauth2.googleapis.com/token",
169
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
170
+ "redirect_uris": [getenv("GOOGLE_REDIRECT_URI", "http://localhost")],
171
+ }
172
+ }
173
+ # File based authentication
174
+ if creds_file.exists():
175
+ flow = InstalledAppFlow.from_client_secrets_file(str(creds_file), self.scopes)
176
+ else:
177
+ flow = InstalledAppFlow.from_client_config(client_config, self.scopes)
178
+ # Opens up a browser window for OAuth authentication
179
+ self.creds = flow.run_local_server(port=self.auth_port) # type: ignore
180
+
181
+ token_file.write_text(self.creds.to_json()) if self.creds else None
182
+
183
+ @authenticate
184
+ def list_files(self, query: Optional[str] = None, page_size: int = 10) -> List[dict]:
185
+ """
186
+ List files in your Google Drive.
187
+
188
+ Args:
189
+ query (Optional[str]): Optional search query to filter files (see Google Drive API docs).
190
+ page_size (int): Maximum number of files to return.
191
+
192
+ Returns:
193
+ List[dict]: List of file metadata dictionaries.
194
+ """
195
+ if not self.service:
196
+ raise ValueError("Google Drive service is not initialized. Please authenticate first.")
197
+ try:
198
+ results = (
199
+ self.service.files() # type: ignore
200
+ .list(q=query, pageSize=page_size, fields="nextPageToken, files(id, name, mimeType, modifiedTime)")
201
+ .execute()
202
+ )
203
+ items = results.get("files", [])
204
+ return items
205
+ except Exception as error:
206
+ log_error(f"Could not list files: {error}")
207
+ return []
208
+
209
+ @authenticate
210
+ def upload_file(self, file_path: Union[str, Path], mime_type: Optional[str] = None) -> Optional[dict]:
211
+ """
212
+ Upload a file to your Google Drive.
213
+
214
+ Args:
215
+ file_path (Union[str, Path]): Path to the file you want to upload.
216
+ mime_type (Optional[str]): MIME type of the file. If not provided, it will be guessed.
217
+
218
+ Returns:
219
+ Optional[dict]: Metadata of the uploaded file, or None if upload failed.
220
+ """
221
+ if not self.service:
222
+ raise ValueError("Google Drive service is not initialized. Please authenticate first.")
223
+ file_path = Path(file_path)
224
+ if not file_path.exists() or not file_path.is_file():
225
+ raise ValueError(f"The file '{file_path}' does not exist or is not a file.")
226
+ if mime_type is None:
227
+ mime_type, _ = mimetypes.guess_type(file_path.as_posix())
228
+ if mime_type is None:
229
+ mime_type = "application/octet-stream" # Default MIME type
230
+
231
+ file_metadata = {"name": file_path.name}
232
+ media = MediaFileUpload(file_path.as_posix(), mimetype=mime_type)
233
+
234
+ try:
235
+ uploaded_file = (
236
+ self.service.files() # type: ignore
237
+ .create(body=file_metadata, media_body=media, fields="id, name, mimeType, modifiedTime")
238
+ .execute()
239
+ )
240
+ return uploaded_file
241
+ except Exception as error:
242
+ log_error(f"Could not upload file '{file_path}': {error}")
243
+ return None
244
+
245
+ @authenticate
246
+ def download_file(self, file_id: str, dest_path: Union[str, Path]) -> Optional[Path]:
247
+ """
248
+ Download a file from your Google Drive.
249
+
250
+ Args:
251
+ file_id (str): The ID of the file you want to download.
252
+ dest_path (Union[str, Path]): Where to save the downloaded file.
253
+
254
+ Returns:
255
+ Optional[Path]: The path to the downloaded file, or None if download failed.
256
+ """
257
+ if not self.service:
258
+ raise ValueError("Google Drive service is not initialized. Please authenticate first.")
259
+ dest_path = Path(dest_path)
260
+ try:
261
+ request = self.service.files().get_media(fileId=file_id) # type: ignore
262
+ with open(dest_path, "wb") as fh:
263
+ downloader = MediaIoBaseDownload(fh, request)
264
+ done = False
265
+ while not done:
266
+ status, done = downloader.next_chunk()
267
+ print(f"Download progress: {int(status.progress() * 100)}%.")
268
+ return dest_path
269
+ except Exception as error:
270
+ log_error(f"Could not download file '{file_id}': {error}")
271
+ return None
@@ -0,0 +1,253 @@
1
+ """
2
+ This module provides tools for searching business information using the Google Maps API.
3
+
4
+ Prerequisites:
5
+ - Set the environment variable `GOOGLE_MAPS_API_KEY` with your Google Maps API key.
6
+ You can obtain the API key from the Google Cloud Console:
7
+ https://console.cloud.google.com/projectselector2/google/maps-apis/credentials
8
+
9
+ - You also need to activate the Address Validation API for your project.
10
+ https://console.developers.google.com/apis/api/addressvalidation.googleapis.com
11
+
12
+ """
13
+
14
+ import json
15
+ from datetime import datetime
16
+ from os import getenv
17
+ from typing import Any, List, Optional
18
+
19
+ from agno.tools import Toolkit
20
+
21
+ try:
22
+ import googlemaps
23
+ from google.maps import places_v1
24
+ except ImportError:
25
+ print("Error importing googlemaps. Please install the package using `pip install googlemaps google-maps-places`.")
26
+
27
+
28
+ class GoogleMapTools(Toolkit):
29
+ def __init__(
30
+ self,
31
+ key: Optional[str] = None,
32
+ **kwargs,
33
+ ):
34
+ self.api_key = key or getenv("GOOGLE_MAPS_API_KEY")
35
+ if not self.api_key:
36
+ raise ValueError("GOOGLE_MAPS_API_KEY is not set in the environment variables.")
37
+ self.client = googlemaps.Client(key=self.api_key)
38
+
39
+ self.places_client = places_v1.PlacesClient()
40
+
41
+ tools: List[Any] = [
42
+ self.search_places,
43
+ self.get_directions,
44
+ self.validate_address,
45
+ self.geocode_address,
46
+ self.reverse_geocode,
47
+ self.get_distance_matrix,
48
+ self.get_elevation,
49
+ self.get_timezone,
50
+ ]
51
+
52
+ super().__init__(name="google_maps", tools=tools, **kwargs)
53
+
54
+ def search_places(self, query: str) -> str:
55
+ """
56
+ Search for places using Google Maps Places API.
57
+ This tool takes a search query and returns detailed place information.
58
+
59
+ Args:
60
+ query (str): The query string to search for using Google Maps Search API. (e.g., "dental clinics in Noida")
61
+
62
+ Returns:
63
+ Stringified list of dictionaries containing business information like name, address, phone, website, rating, and reviews etc.
64
+ """
65
+ try:
66
+ # Perform places search
67
+ request = places_v1.SearchTextRequest(
68
+ text_query=query,
69
+ )
70
+ response = self.places_client.search_text(request=request, metadata=[("x-goog-fieldmask", "*")])
71
+
72
+ places = []
73
+ for place in response.places:
74
+ place_info = {
75
+ "name": place.display_name.text,
76
+ "address": place.formatted_address,
77
+ "rating": place.rating,
78
+ "reviews": [{"text": review.text.text, "rating": review.rating} for review in place.reviews],
79
+ "place_id": place.id,
80
+ "phone": place.international_phone_number,
81
+ "website": place.website_uri,
82
+ "hours": [description for description in place.regular_opening_hours.weekday_descriptions],
83
+ }
84
+
85
+ places.append(place_info)
86
+
87
+ return json.dumps(places)
88
+
89
+ except Exception as e:
90
+ print(f"Error searching Google Maps: {str(e)}")
91
+ return str([])
92
+
93
+ def get_directions(
94
+ self,
95
+ origin: str,
96
+ destination: str,
97
+ mode: str = "driving",
98
+ departure_time: Optional[datetime] = None,
99
+ avoid: Optional[List[str]] = None,
100
+ ) -> str:
101
+ """
102
+ Get directions between two locations using Google Maps Directions API.
103
+
104
+ Args:
105
+ origin (str): Starting point address or coordinates
106
+ destination (str): Destination address or coordinates
107
+ mode (str, optional): Travel mode. Options: "driving", "walking", "bicycling", "transit". Defaults to "driving"
108
+ departure_time (datetime, optional): Desired departure time for transit directions
109
+ avoid (List[str], optional): Features to avoid: "tolls", "highways", "ferries"
110
+
111
+ Returns:
112
+ str: Stringified dictionary containing route information including steps, distance, duration, etc.
113
+ """
114
+ try:
115
+ result = self.client.directions(origin, destination, mode=mode, departure_time=departure_time, avoid=avoid)
116
+ return str(result)
117
+ except Exception as e:
118
+ print(f"Error getting directions: {str(e)}")
119
+ return str([])
120
+
121
+ def validate_address(
122
+ self, address: str, region_code: str = "US", locality: Optional[str] = None, enable_usps_cass: bool = False
123
+ ) -> str:
124
+ """
125
+ Validate an address using Google Maps Address Validation API.
126
+
127
+ Args:
128
+ address (str): The address to validate
129
+ region_code (str): The region code (e.g., "US" for United States)
130
+ locality (str, optional): The locality (city) to help with validation
131
+ enable_usps_cass (bool): Whether to enable USPS CASS validation for US addresses
132
+
133
+ Returns:
134
+ str: Stringified dictionary containing address validation results
135
+ """
136
+ try:
137
+ result = self.client.addressvalidation(
138
+ [address], regionCode=region_code, locality=locality, enableUspsCass=enable_usps_cass
139
+ )
140
+ return str(result)
141
+ except Exception as e:
142
+ print(f"Error validating address: {str(e)}")
143
+ return str({})
144
+
145
+ def geocode_address(self, address: str, region: Optional[str] = None) -> str:
146
+ """
147
+ Convert an address into geographic coordinates using Google Maps Geocoding API.
148
+
149
+ Args:
150
+ address (str): The address to geocode
151
+ region (str, optional): The region code to bias results
152
+
153
+ Returns:
154
+ str: Stringified list of dictionaries containing location information
155
+ """
156
+ try:
157
+ result = self.client.geocode(address, region=region)
158
+ return str(result)
159
+ except Exception as e:
160
+ print(f"Error geocoding address: {str(e)}")
161
+ return str([])
162
+
163
+ def reverse_geocode(
164
+ self, lat: float, lng: float, result_type: Optional[List[str]] = None, location_type: Optional[List[str]] = None
165
+ ) -> str:
166
+ """
167
+ Convert geographic coordinates into an address using Google Maps Reverse Geocoding API.
168
+
169
+ Args:
170
+ lat (float): Latitude
171
+ lng (float): Longitude
172
+ result_type (List[str], optional): Array of address types to filter results
173
+ location_type (List[str], optional): Array of location types to filter results
174
+
175
+ Returns:
176
+ str: Stringified list of dictionaries containing address information
177
+ """
178
+ try:
179
+ result = self.client.reverse_geocode((lat, lng), result_type=result_type, location_type=location_type)
180
+ return str(result)
181
+ except Exception as e:
182
+ print(f"Error reverse geocoding: {str(e)}")
183
+ return str([])
184
+
185
+ def get_distance_matrix(
186
+ self,
187
+ origins: List[str],
188
+ destinations: List[str],
189
+ mode: str = "driving",
190
+ departure_time: Optional[datetime] = None,
191
+ avoid: Optional[List[str]] = None,
192
+ ) -> str:
193
+ """
194
+ Calculate distance and time for a matrix of origins and destinations.
195
+
196
+ Args:
197
+ origins (List[str]): List of addresses or coordinates
198
+ destinations (List[str]): List of addresses or coordinates
199
+ mode (str, optional): Travel mode. Options: "driving", "walking", "bicycling", "transit"
200
+ departure_time (datetime, optional): Desired departure time
201
+ avoid (List[str], optional): Features to avoid: "tolls", "highways", "ferries"
202
+
203
+ Returns:
204
+ str: Stringified dictionary containing distance and duration information
205
+ """
206
+ try:
207
+ result = self.client.distance_matrix(
208
+ origins, destinations, mode=mode, departure_time=departure_time, avoid=avoid
209
+ )
210
+ return str(result)
211
+ except Exception as e:
212
+ print(f"Error getting distance matrix: {str(e)}")
213
+ return str({})
214
+
215
+ def get_elevation(self, lat: float, lng: float) -> str:
216
+ """
217
+ Get the elevation for a specific location using Google Maps Elevation API.
218
+
219
+ Args:
220
+ lat (float): Latitude
221
+ lng (float): Longitude
222
+
223
+ Returns:
224
+ str: Stringified dictionary containing elevation data
225
+ """
226
+ try:
227
+ result = self.client.elevation((lat, lng))
228
+ return str(result)
229
+ except Exception as e:
230
+ print(f"Error getting elevation: {str(e)}")
231
+ return str([])
232
+
233
+ def get_timezone(self, lat: float, lng: float, timestamp: Optional[datetime] = None) -> str:
234
+ """
235
+ Get timezone information for a location using Google Maps Time Zone API.
236
+
237
+ Args:
238
+ lat (float): Latitude
239
+ lng (float): Longitude
240
+ timestamp (datetime, optional): The timestamp to use for timezone calculation
241
+
242
+ Returns:
243
+ str: Stringified dictionary containing timezone information
244
+ """
245
+ try:
246
+ if timestamp is None:
247
+ timestamp = datetime.now()
248
+
249
+ result = self.client.timezone(location=(lat, lng), timestamp=timestamp)
250
+ return str(result)
251
+ except Exception as e:
252
+ print(f"Error getting timezone: {str(e)}")
253
+ return str({})