agno 2.2.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 (575) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +51 -0
  3. agno/agent/agent.py +10405 -0
  4. agno/api/__init__.py +0 -0
  5. agno/api/agent.py +28 -0
  6. agno/api/api.py +40 -0
  7. agno/api/evals.py +22 -0
  8. agno/api/os.py +17 -0
  9. agno/api/routes.py +13 -0
  10. agno/api/schemas/__init__.py +9 -0
  11. agno/api/schemas/agent.py +16 -0
  12. agno/api/schemas/evals.py +16 -0
  13. agno/api/schemas/os.py +14 -0
  14. agno/api/schemas/response.py +6 -0
  15. agno/api/schemas/team.py +16 -0
  16. agno/api/schemas/utils.py +21 -0
  17. agno/api/schemas/workflows.py +16 -0
  18. agno/api/settings.py +53 -0
  19. agno/api/team.py +30 -0
  20. agno/api/workflow.py +28 -0
  21. agno/cloud/aws/base.py +214 -0
  22. agno/cloud/aws/s3/__init__.py +2 -0
  23. agno/cloud/aws/s3/api_client.py +43 -0
  24. agno/cloud/aws/s3/bucket.py +195 -0
  25. agno/cloud/aws/s3/object.py +57 -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 +598 -0
  31. agno/db/dynamo/__init__.py +3 -0
  32. agno/db/dynamo/dynamo.py +2042 -0
  33. agno/db/dynamo/schemas.py +314 -0
  34. agno/db/dynamo/utils.py +743 -0
  35. agno/db/firestore/__init__.py +3 -0
  36. agno/db/firestore/firestore.py +1795 -0
  37. agno/db/firestore/schemas.py +140 -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 +1335 -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 +1160 -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 +1328 -0
  47. agno/db/json/utils.py +230 -0
  48. agno/db/migrations/__init__.py +0 -0
  49. agno/db/migrations/v1_to_v2.py +635 -0
  50. agno/db/mongo/__init__.py +17 -0
  51. agno/db/mongo/async_mongo.py +2026 -0
  52. agno/db/mongo/mongo.py +1982 -0
  53. agno/db/mongo/schemas.py +87 -0
  54. agno/db/mongo/utils.py +259 -0
  55. agno/db/mysql/__init__.py +3 -0
  56. agno/db/mysql/mysql.py +2308 -0
  57. agno/db/mysql/schemas.py +138 -0
  58. agno/db/mysql/utils.py +355 -0
  59. agno/db/postgres/__init__.py +4 -0
  60. agno/db/postgres/async_postgres.py +1927 -0
  61. agno/db/postgres/postgres.py +2260 -0
  62. agno/db/postgres/schemas.py +139 -0
  63. agno/db/postgres/utils.py +442 -0
  64. agno/db/redis/__init__.py +3 -0
  65. agno/db/redis/redis.py +1660 -0
  66. agno/db/redis/schemas.py +123 -0
  67. agno/db/redis/utils.py +346 -0
  68. agno/db/schemas/__init__.py +4 -0
  69. agno/db/schemas/culture.py +120 -0
  70. agno/db/schemas/evals.py +33 -0
  71. agno/db/schemas/knowledge.py +40 -0
  72. agno/db/schemas/memory.py +46 -0
  73. agno/db/schemas/metrics.py +0 -0
  74. agno/db/singlestore/__init__.py +3 -0
  75. agno/db/singlestore/schemas.py +130 -0
  76. agno/db/singlestore/singlestore.py +2272 -0
  77. agno/db/singlestore/utils.py +384 -0
  78. agno/db/sqlite/__init__.py +4 -0
  79. agno/db/sqlite/async_sqlite.py +2293 -0
  80. agno/db/sqlite/schemas.py +133 -0
  81. agno/db/sqlite/sqlite.py +2288 -0
  82. agno/db/sqlite/utils.py +431 -0
  83. agno/db/surrealdb/__init__.py +3 -0
  84. agno/db/surrealdb/metrics.py +292 -0
  85. agno/db/surrealdb/models.py +309 -0
  86. agno/db/surrealdb/queries.py +71 -0
  87. agno/db/surrealdb/surrealdb.py +1353 -0
  88. agno/db/surrealdb/utils.py +147 -0
  89. agno/db/utils.py +116 -0
  90. agno/debug.py +18 -0
  91. agno/eval/__init__.py +14 -0
  92. agno/eval/accuracy.py +834 -0
  93. agno/eval/performance.py +773 -0
  94. agno/eval/reliability.py +306 -0
  95. agno/eval/utils.py +119 -0
  96. agno/exceptions.py +161 -0
  97. agno/filters.py +354 -0
  98. agno/guardrails/__init__.py +6 -0
  99. agno/guardrails/base.py +19 -0
  100. agno/guardrails/openai.py +144 -0
  101. agno/guardrails/pii.py +94 -0
  102. agno/guardrails/prompt_injection.py +52 -0
  103. agno/integrations/__init__.py +0 -0
  104. agno/integrations/discord/__init__.py +3 -0
  105. agno/integrations/discord/client.py +203 -0
  106. agno/knowledge/__init__.py +5 -0
  107. agno/knowledge/chunking/__init__.py +0 -0
  108. agno/knowledge/chunking/agentic.py +79 -0
  109. agno/knowledge/chunking/document.py +91 -0
  110. agno/knowledge/chunking/fixed.py +57 -0
  111. agno/knowledge/chunking/markdown.py +151 -0
  112. agno/knowledge/chunking/recursive.py +63 -0
  113. agno/knowledge/chunking/row.py +39 -0
  114. agno/knowledge/chunking/semantic.py +86 -0
  115. agno/knowledge/chunking/strategy.py +165 -0
  116. agno/knowledge/content.py +74 -0
  117. agno/knowledge/document/__init__.py +5 -0
  118. agno/knowledge/document/base.py +58 -0
  119. agno/knowledge/embedder/__init__.py +5 -0
  120. agno/knowledge/embedder/aws_bedrock.py +343 -0
  121. agno/knowledge/embedder/azure_openai.py +210 -0
  122. agno/knowledge/embedder/base.py +23 -0
  123. agno/knowledge/embedder/cohere.py +323 -0
  124. agno/knowledge/embedder/fastembed.py +62 -0
  125. agno/knowledge/embedder/fireworks.py +13 -0
  126. agno/knowledge/embedder/google.py +258 -0
  127. agno/knowledge/embedder/huggingface.py +94 -0
  128. agno/knowledge/embedder/jina.py +182 -0
  129. agno/knowledge/embedder/langdb.py +22 -0
  130. agno/knowledge/embedder/mistral.py +206 -0
  131. agno/knowledge/embedder/nebius.py +13 -0
  132. agno/knowledge/embedder/ollama.py +154 -0
  133. agno/knowledge/embedder/openai.py +195 -0
  134. agno/knowledge/embedder/sentence_transformer.py +63 -0
  135. agno/knowledge/embedder/together.py +13 -0
  136. agno/knowledge/embedder/vllm.py +262 -0
  137. agno/knowledge/embedder/voyageai.py +165 -0
  138. agno/knowledge/knowledge.py +1988 -0
  139. agno/knowledge/reader/__init__.py +7 -0
  140. agno/knowledge/reader/arxiv_reader.py +81 -0
  141. agno/knowledge/reader/base.py +95 -0
  142. agno/knowledge/reader/csv_reader.py +166 -0
  143. agno/knowledge/reader/docx_reader.py +82 -0
  144. agno/knowledge/reader/field_labeled_csv_reader.py +292 -0
  145. agno/knowledge/reader/firecrawl_reader.py +201 -0
  146. agno/knowledge/reader/json_reader.py +87 -0
  147. agno/knowledge/reader/markdown_reader.py +137 -0
  148. agno/knowledge/reader/pdf_reader.py +431 -0
  149. agno/knowledge/reader/pptx_reader.py +101 -0
  150. agno/knowledge/reader/reader_factory.py +313 -0
  151. agno/knowledge/reader/s3_reader.py +89 -0
  152. agno/knowledge/reader/tavily_reader.py +194 -0
  153. agno/knowledge/reader/text_reader.py +115 -0
  154. agno/knowledge/reader/web_search_reader.py +372 -0
  155. agno/knowledge/reader/website_reader.py +455 -0
  156. agno/knowledge/reader/wikipedia_reader.py +59 -0
  157. agno/knowledge/reader/youtube_reader.py +78 -0
  158. agno/knowledge/remote_content/__init__.py +0 -0
  159. agno/knowledge/remote_content/remote_content.py +88 -0
  160. agno/knowledge/reranker/__init__.py +3 -0
  161. agno/knowledge/reranker/base.py +14 -0
  162. agno/knowledge/reranker/cohere.py +64 -0
  163. agno/knowledge/reranker/infinity.py +195 -0
  164. agno/knowledge/reranker/sentence_transformer.py +54 -0
  165. agno/knowledge/types.py +39 -0
  166. agno/knowledge/utils.py +189 -0
  167. agno/media.py +462 -0
  168. agno/memory/__init__.py +3 -0
  169. agno/memory/manager.py +1327 -0
  170. agno/models/__init__.py +0 -0
  171. agno/models/aimlapi/__init__.py +5 -0
  172. agno/models/aimlapi/aimlapi.py +45 -0
  173. agno/models/anthropic/__init__.py +5 -0
  174. agno/models/anthropic/claude.py +757 -0
  175. agno/models/aws/__init__.py +15 -0
  176. agno/models/aws/bedrock.py +701 -0
  177. agno/models/aws/claude.py +378 -0
  178. agno/models/azure/__init__.py +18 -0
  179. agno/models/azure/ai_foundry.py +485 -0
  180. agno/models/azure/openai_chat.py +131 -0
  181. agno/models/base.py +2175 -0
  182. agno/models/cerebras/__init__.py +12 -0
  183. agno/models/cerebras/cerebras.py +501 -0
  184. agno/models/cerebras/cerebras_openai.py +112 -0
  185. agno/models/cohere/__init__.py +5 -0
  186. agno/models/cohere/chat.py +389 -0
  187. agno/models/cometapi/__init__.py +5 -0
  188. agno/models/cometapi/cometapi.py +57 -0
  189. agno/models/dashscope/__init__.py +5 -0
  190. agno/models/dashscope/dashscope.py +91 -0
  191. agno/models/deepinfra/__init__.py +5 -0
  192. agno/models/deepinfra/deepinfra.py +28 -0
  193. agno/models/deepseek/__init__.py +5 -0
  194. agno/models/deepseek/deepseek.py +61 -0
  195. agno/models/defaults.py +1 -0
  196. agno/models/fireworks/__init__.py +5 -0
  197. agno/models/fireworks/fireworks.py +26 -0
  198. agno/models/google/__init__.py +5 -0
  199. agno/models/google/gemini.py +1085 -0
  200. agno/models/groq/__init__.py +5 -0
  201. agno/models/groq/groq.py +556 -0
  202. agno/models/huggingface/__init__.py +5 -0
  203. agno/models/huggingface/huggingface.py +491 -0
  204. agno/models/ibm/__init__.py +5 -0
  205. agno/models/ibm/watsonx.py +422 -0
  206. agno/models/internlm/__init__.py +3 -0
  207. agno/models/internlm/internlm.py +26 -0
  208. agno/models/langdb/__init__.py +1 -0
  209. agno/models/langdb/langdb.py +48 -0
  210. agno/models/litellm/__init__.py +14 -0
  211. agno/models/litellm/chat.py +468 -0
  212. agno/models/litellm/litellm_openai.py +25 -0
  213. agno/models/llama_cpp/__init__.py +5 -0
  214. agno/models/llama_cpp/llama_cpp.py +22 -0
  215. agno/models/lmstudio/__init__.py +5 -0
  216. agno/models/lmstudio/lmstudio.py +25 -0
  217. agno/models/message.py +434 -0
  218. agno/models/meta/__init__.py +12 -0
  219. agno/models/meta/llama.py +475 -0
  220. agno/models/meta/llama_openai.py +78 -0
  221. agno/models/metrics.py +120 -0
  222. agno/models/mistral/__init__.py +5 -0
  223. agno/models/mistral/mistral.py +432 -0
  224. agno/models/nebius/__init__.py +3 -0
  225. agno/models/nebius/nebius.py +54 -0
  226. agno/models/nexus/__init__.py +3 -0
  227. agno/models/nexus/nexus.py +22 -0
  228. agno/models/nvidia/__init__.py +5 -0
  229. agno/models/nvidia/nvidia.py +28 -0
  230. agno/models/ollama/__init__.py +5 -0
  231. agno/models/ollama/chat.py +441 -0
  232. agno/models/openai/__init__.py +9 -0
  233. agno/models/openai/chat.py +883 -0
  234. agno/models/openai/like.py +27 -0
  235. agno/models/openai/responses.py +1050 -0
  236. agno/models/openrouter/__init__.py +5 -0
  237. agno/models/openrouter/openrouter.py +66 -0
  238. agno/models/perplexity/__init__.py +5 -0
  239. agno/models/perplexity/perplexity.py +187 -0
  240. agno/models/portkey/__init__.py +3 -0
  241. agno/models/portkey/portkey.py +81 -0
  242. agno/models/requesty/__init__.py +5 -0
  243. agno/models/requesty/requesty.py +52 -0
  244. agno/models/response.py +199 -0
  245. agno/models/sambanova/__init__.py +5 -0
  246. agno/models/sambanova/sambanova.py +28 -0
  247. agno/models/siliconflow/__init__.py +5 -0
  248. agno/models/siliconflow/siliconflow.py +25 -0
  249. agno/models/together/__init__.py +5 -0
  250. agno/models/together/together.py +25 -0
  251. agno/models/utils.py +266 -0
  252. agno/models/vercel/__init__.py +3 -0
  253. agno/models/vercel/v0.py +26 -0
  254. agno/models/vertexai/__init__.py +0 -0
  255. agno/models/vertexai/claude.py +70 -0
  256. agno/models/vllm/__init__.py +3 -0
  257. agno/models/vllm/vllm.py +78 -0
  258. agno/models/xai/__init__.py +3 -0
  259. agno/models/xai/xai.py +113 -0
  260. agno/os/__init__.py +3 -0
  261. agno/os/app.py +876 -0
  262. agno/os/auth.py +57 -0
  263. agno/os/config.py +104 -0
  264. agno/os/interfaces/__init__.py +1 -0
  265. agno/os/interfaces/a2a/__init__.py +3 -0
  266. agno/os/interfaces/a2a/a2a.py +42 -0
  267. agno/os/interfaces/a2a/router.py +250 -0
  268. agno/os/interfaces/a2a/utils.py +924 -0
  269. agno/os/interfaces/agui/__init__.py +3 -0
  270. agno/os/interfaces/agui/agui.py +47 -0
  271. agno/os/interfaces/agui/router.py +144 -0
  272. agno/os/interfaces/agui/utils.py +534 -0
  273. agno/os/interfaces/base.py +25 -0
  274. agno/os/interfaces/slack/__init__.py +3 -0
  275. agno/os/interfaces/slack/router.py +148 -0
  276. agno/os/interfaces/slack/security.py +30 -0
  277. agno/os/interfaces/slack/slack.py +47 -0
  278. agno/os/interfaces/whatsapp/__init__.py +3 -0
  279. agno/os/interfaces/whatsapp/router.py +211 -0
  280. agno/os/interfaces/whatsapp/security.py +53 -0
  281. agno/os/interfaces/whatsapp/whatsapp.py +36 -0
  282. agno/os/mcp.py +292 -0
  283. agno/os/middleware/__init__.py +7 -0
  284. agno/os/middleware/jwt.py +233 -0
  285. agno/os/router.py +1763 -0
  286. agno/os/routers/__init__.py +3 -0
  287. agno/os/routers/evals/__init__.py +3 -0
  288. agno/os/routers/evals/evals.py +430 -0
  289. agno/os/routers/evals/schemas.py +142 -0
  290. agno/os/routers/evals/utils.py +162 -0
  291. agno/os/routers/health.py +31 -0
  292. agno/os/routers/home.py +52 -0
  293. agno/os/routers/knowledge/__init__.py +3 -0
  294. agno/os/routers/knowledge/knowledge.py +997 -0
  295. agno/os/routers/knowledge/schemas.py +178 -0
  296. agno/os/routers/memory/__init__.py +3 -0
  297. agno/os/routers/memory/memory.py +515 -0
  298. agno/os/routers/memory/schemas.py +62 -0
  299. agno/os/routers/metrics/__init__.py +3 -0
  300. agno/os/routers/metrics/metrics.py +190 -0
  301. agno/os/routers/metrics/schemas.py +47 -0
  302. agno/os/routers/session/__init__.py +3 -0
  303. agno/os/routers/session/session.py +997 -0
  304. agno/os/schema.py +1055 -0
  305. agno/os/settings.py +43 -0
  306. agno/os/utils.py +630 -0
  307. agno/py.typed +0 -0
  308. agno/reasoning/__init__.py +0 -0
  309. agno/reasoning/anthropic.py +80 -0
  310. agno/reasoning/azure_ai_foundry.py +67 -0
  311. agno/reasoning/deepseek.py +63 -0
  312. agno/reasoning/default.py +97 -0
  313. agno/reasoning/gemini.py +73 -0
  314. agno/reasoning/groq.py +71 -0
  315. agno/reasoning/helpers.py +63 -0
  316. agno/reasoning/ollama.py +67 -0
  317. agno/reasoning/openai.py +86 -0
  318. agno/reasoning/step.py +31 -0
  319. agno/reasoning/vertexai.py +76 -0
  320. agno/run/__init__.py +6 -0
  321. agno/run/agent.py +787 -0
  322. agno/run/base.py +229 -0
  323. agno/run/cancel.py +81 -0
  324. agno/run/messages.py +32 -0
  325. agno/run/team.py +753 -0
  326. agno/run/workflow.py +708 -0
  327. agno/session/__init__.py +10 -0
  328. agno/session/agent.py +295 -0
  329. agno/session/summary.py +265 -0
  330. agno/session/team.py +392 -0
  331. agno/session/workflow.py +205 -0
  332. agno/team/__init__.py +37 -0
  333. agno/team/team.py +8793 -0
  334. agno/tools/__init__.py +10 -0
  335. agno/tools/agentql.py +120 -0
  336. agno/tools/airflow.py +69 -0
  337. agno/tools/api.py +122 -0
  338. agno/tools/apify.py +314 -0
  339. agno/tools/arxiv.py +127 -0
  340. agno/tools/aws_lambda.py +53 -0
  341. agno/tools/aws_ses.py +66 -0
  342. agno/tools/baidusearch.py +89 -0
  343. agno/tools/bitbucket.py +292 -0
  344. agno/tools/brandfetch.py +213 -0
  345. agno/tools/bravesearch.py +106 -0
  346. agno/tools/brightdata.py +367 -0
  347. agno/tools/browserbase.py +209 -0
  348. agno/tools/calcom.py +255 -0
  349. agno/tools/calculator.py +151 -0
  350. agno/tools/cartesia.py +187 -0
  351. agno/tools/clickup.py +244 -0
  352. agno/tools/confluence.py +240 -0
  353. agno/tools/crawl4ai.py +158 -0
  354. agno/tools/csv_toolkit.py +185 -0
  355. agno/tools/dalle.py +110 -0
  356. agno/tools/daytona.py +475 -0
  357. agno/tools/decorator.py +262 -0
  358. agno/tools/desi_vocal.py +108 -0
  359. agno/tools/discord.py +161 -0
  360. agno/tools/docker.py +716 -0
  361. agno/tools/duckdb.py +379 -0
  362. agno/tools/duckduckgo.py +91 -0
  363. agno/tools/e2b.py +703 -0
  364. agno/tools/eleven_labs.py +196 -0
  365. agno/tools/email.py +67 -0
  366. agno/tools/evm.py +129 -0
  367. agno/tools/exa.py +396 -0
  368. agno/tools/fal.py +127 -0
  369. agno/tools/file.py +240 -0
  370. agno/tools/file_generation.py +350 -0
  371. agno/tools/financial_datasets.py +288 -0
  372. agno/tools/firecrawl.py +143 -0
  373. agno/tools/function.py +1187 -0
  374. agno/tools/giphy.py +93 -0
  375. agno/tools/github.py +1760 -0
  376. agno/tools/gmail.py +922 -0
  377. agno/tools/google_bigquery.py +117 -0
  378. agno/tools/google_drive.py +270 -0
  379. agno/tools/google_maps.py +253 -0
  380. agno/tools/googlecalendar.py +674 -0
  381. agno/tools/googlesearch.py +98 -0
  382. agno/tools/googlesheets.py +377 -0
  383. agno/tools/hackernews.py +77 -0
  384. agno/tools/jina.py +101 -0
  385. agno/tools/jira.py +170 -0
  386. agno/tools/knowledge.py +218 -0
  387. agno/tools/linear.py +426 -0
  388. agno/tools/linkup.py +58 -0
  389. agno/tools/local_file_system.py +90 -0
  390. agno/tools/lumalab.py +183 -0
  391. agno/tools/mcp/__init__.py +10 -0
  392. agno/tools/mcp/mcp.py +331 -0
  393. agno/tools/mcp/multi_mcp.py +347 -0
  394. agno/tools/mcp/params.py +24 -0
  395. agno/tools/mcp_toolbox.py +284 -0
  396. agno/tools/mem0.py +193 -0
  397. agno/tools/memori.py +339 -0
  398. agno/tools/memory.py +419 -0
  399. agno/tools/mlx_transcribe.py +139 -0
  400. agno/tools/models/__init__.py +0 -0
  401. agno/tools/models/azure_openai.py +190 -0
  402. agno/tools/models/gemini.py +203 -0
  403. agno/tools/models/groq.py +158 -0
  404. agno/tools/models/morph.py +186 -0
  405. agno/tools/models/nebius.py +124 -0
  406. agno/tools/models_labs.py +195 -0
  407. agno/tools/moviepy_video.py +349 -0
  408. agno/tools/neo4j.py +134 -0
  409. agno/tools/newspaper.py +46 -0
  410. agno/tools/newspaper4k.py +93 -0
  411. agno/tools/notion.py +204 -0
  412. agno/tools/openai.py +202 -0
  413. agno/tools/openbb.py +160 -0
  414. agno/tools/opencv.py +321 -0
  415. agno/tools/openweather.py +233 -0
  416. agno/tools/oxylabs.py +385 -0
  417. agno/tools/pandas.py +102 -0
  418. agno/tools/parallel.py +314 -0
  419. agno/tools/postgres.py +257 -0
  420. agno/tools/pubmed.py +188 -0
  421. agno/tools/python.py +205 -0
  422. agno/tools/reasoning.py +283 -0
  423. agno/tools/reddit.py +467 -0
  424. agno/tools/replicate.py +117 -0
  425. agno/tools/resend.py +62 -0
  426. agno/tools/scrapegraph.py +222 -0
  427. agno/tools/searxng.py +152 -0
  428. agno/tools/serpapi.py +116 -0
  429. agno/tools/serper.py +255 -0
  430. agno/tools/shell.py +53 -0
  431. agno/tools/slack.py +136 -0
  432. agno/tools/sleep.py +20 -0
  433. agno/tools/spider.py +116 -0
  434. agno/tools/sql.py +154 -0
  435. agno/tools/streamlit/__init__.py +0 -0
  436. agno/tools/streamlit/components.py +113 -0
  437. agno/tools/tavily.py +254 -0
  438. agno/tools/telegram.py +48 -0
  439. agno/tools/todoist.py +218 -0
  440. agno/tools/tool_registry.py +1 -0
  441. agno/tools/toolkit.py +146 -0
  442. agno/tools/trafilatura.py +388 -0
  443. agno/tools/trello.py +274 -0
  444. agno/tools/twilio.py +186 -0
  445. agno/tools/user_control_flow.py +78 -0
  446. agno/tools/valyu.py +228 -0
  447. agno/tools/visualization.py +467 -0
  448. agno/tools/webbrowser.py +28 -0
  449. agno/tools/webex.py +76 -0
  450. agno/tools/website.py +54 -0
  451. agno/tools/webtools.py +45 -0
  452. agno/tools/whatsapp.py +286 -0
  453. agno/tools/wikipedia.py +63 -0
  454. agno/tools/workflow.py +278 -0
  455. agno/tools/x.py +335 -0
  456. agno/tools/yfinance.py +257 -0
  457. agno/tools/youtube.py +184 -0
  458. agno/tools/zendesk.py +82 -0
  459. agno/tools/zep.py +454 -0
  460. agno/tools/zoom.py +382 -0
  461. agno/utils/__init__.py +0 -0
  462. agno/utils/agent.py +820 -0
  463. agno/utils/audio.py +49 -0
  464. agno/utils/certs.py +27 -0
  465. agno/utils/code_execution.py +11 -0
  466. agno/utils/common.py +132 -0
  467. agno/utils/dttm.py +13 -0
  468. agno/utils/enum.py +22 -0
  469. agno/utils/env.py +11 -0
  470. agno/utils/events.py +696 -0
  471. agno/utils/format_str.py +16 -0
  472. agno/utils/functions.py +166 -0
  473. agno/utils/gemini.py +426 -0
  474. agno/utils/hooks.py +57 -0
  475. agno/utils/http.py +74 -0
  476. agno/utils/json_schema.py +234 -0
  477. agno/utils/knowledge.py +36 -0
  478. agno/utils/location.py +19 -0
  479. agno/utils/log.py +255 -0
  480. agno/utils/mcp.py +214 -0
  481. agno/utils/media.py +352 -0
  482. agno/utils/merge_dict.py +41 -0
  483. agno/utils/message.py +118 -0
  484. agno/utils/models/__init__.py +0 -0
  485. agno/utils/models/ai_foundry.py +43 -0
  486. agno/utils/models/claude.py +358 -0
  487. agno/utils/models/cohere.py +87 -0
  488. agno/utils/models/llama.py +78 -0
  489. agno/utils/models/mistral.py +98 -0
  490. agno/utils/models/openai_responses.py +140 -0
  491. agno/utils/models/schema_utils.py +153 -0
  492. agno/utils/models/watsonx.py +41 -0
  493. agno/utils/openai.py +257 -0
  494. agno/utils/pickle.py +32 -0
  495. agno/utils/pprint.py +178 -0
  496. agno/utils/print_response/__init__.py +0 -0
  497. agno/utils/print_response/agent.py +842 -0
  498. agno/utils/print_response/team.py +1724 -0
  499. agno/utils/print_response/workflow.py +1668 -0
  500. agno/utils/prompts.py +111 -0
  501. agno/utils/reasoning.py +108 -0
  502. agno/utils/response.py +163 -0
  503. agno/utils/response_iterator.py +17 -0
  504. agno/utils/safe_formatter.py +24 -0
  505. agno/utils/serialize.py +32 -0
  506. agno/utils/shell.py +22 -0
  507. agno/utils/streamlit.py +487 -0
  508. agno/utils/string.py +231 -0
  509. agno/utils/team.py +139 -0
  510. agno/utils/timer.py +41 -0
  511. agno/utils/tools.py +102 -0
  512. agno/utils/web.py +23 -0
  513. agno/utils/whatsapp.py +305 -0
  514. agno/utils/yaml_io.py +25 -0
  515. agno/vectordb/__init__.py +3 -0
  516. agno/vectordb/base.py +127 -0
  517. agno/vectordb/cassandra/__init__.py +5 -0
  518. agno/vectordb/cassandra/cassandra.py +501 -0
  519. agno/vectordb/cassandra/extra_param_mixin.py +11 -0
  520. agno/vectordb/cassandra/index.py +13 -0
  521. agno/vectordb/chroma/__init__.py +5 -0
  522. agno/vectordb/chroma/chromadb.py +929 -0
  523. agno/vectordb/clickhouse/__init__.py +9 -0
  524. agno/vectordb/clickhouse/clickhousedb.py +835 -0
  525. agno/vectordb/clickhouse/index.py +9 -0
  526. agno/vectordb/couchbase/__init__.py +3 -0
  527. agno/vectordb/couchbase/couchbase.py +1442 -0
  528. agno/vectordb/distance.py +7 -0
  529. agno/vectordb/lancedb/__init__.py +6 -0
  530. agno/vectordb/lancedb/lance_db.py +995 -0
  531. agno/vectordb/langchaindb/__init__.py +5 -0
  532. agno/vectordb/langchaindb/langchaindb.py +163 -0
  533. agno/vectordb/lightrag/__init__.py +5 -0
  534. agno/vectordb/lightrag/lightrag.py +388 -0
  535. agno/vectordb/llamaindex/__init__.py +3 -0
  536. agno/vectordb/llamaindex/llamaindexdb.py +166 -0
  537. agno/vectordb/milvus/__init__.py +4 -0
  538. agno/vectordb/milvus/milvus.py +1182 -0
  539. agno/vectordb/mongodb/__init__.py +9 -0
  540. agno/vectordb/mongodb/mongodb.py +1417 -0
  541. agno/vectordb/pgvector/__init__.py +12 -0
  542. agno/vectordb/pgvector/index.py +23 -0
  543. agno/vectordb/pgvector/pgvector.py +1462 -0
  544. agno/vectordb/pineconedb/__init__.py +5 -0
  545. agno/vectordb/pineconedb/pineconedb.py +747 -0
  546. agno/vectordb/qdrant/__init__.py +5 -0
  547. agno/vectordb/qdrant/qdrant.py +1134 -0
  548. agno/vectordb/redis/__init__.py +9 -0
  549. agno/vectordb/redis/redisdb.py +694 -0
  550. agno/vectordb/search.py +7 -0
  551. agno/vectordb/singlestore/__init__.py +10 -0
  552. agno/vectordb/singlestore/index.py +41 -0
  553. agno/vectordb/singlestore/singlestore.py +763 -0
  554. agno/vectordb/surrealdb/__init__.py +3 -0
  555. agno/vectordb/surrealdb/surrealdb.py +699 -0
  556. agno/vectordb/upstashdb/__init__.py +5 -0
  557. agno/vectordb/upstashdb/upstashdb.py +718 -0
  558. agno/vectordb/weaviate/__init__.py +8 -0
  559. agno/vectordb/weaviate/index.py +15 -0
  560. agno/vectordb/weaviate/weaviate.py +1005 -0
  561. agno/workflow/__init__.py +23 -0
  562. agno/workflow/agent.py +299 -0
  563. agno/workflow/condition.py +738 -0
  564. agno/workflow/loop.py +735 -0
  565. agno/workflow/parallel.py +824 -0
  566. agno/workflow/router.py +702 -0
  567. agno/workflow/step.py +1432 -0
  568. agno/workflow/steps.py +592 -0
  569. agno/workflow/types.py +520 -0
  570. agno/workflow/workflow.py +4321 -0
  571. agno-2.2.13.dist-info/METADATA +614 -0
  572. agno-2.2.13.dist-info/RECORD +575 -0
  573. agno-2.2.13.dist-info/WHEEL +5 -0
  574. agno-2.2.13.dist-info/licenses/LICENSE +201 -0
  575. agno-2.2.13.dist-info/top_level.txt +1 -0
agno/tools/cartesia.py ADDED
@@ -0,0 +1,187 @@
1
+ import json
2
+ from os import getenv
3
+ from typing import Any, Dict, List, Optional, Union
4
+ from uuid import uuid4
5
+
6
+ from agno.agent import Agent
7
+ from agno.media import Audio
8
+ from agno.team.team import Team
9
+ from agno.tools import Toolkit
10
+ from agno.tools.function import ToolResult
11
+ from agno.utils.log import log_debug, log_error, log_info
12
+
13
+ try:
14
+ import cartesia # type: ignore
15
+ except ImportError:
16
+ raise ImportError("`cartesia` not installed. Please install using `pip install cartesia`")
17
+
18
+
19
+ class CartesiaTools(Toolkit):
20
+ def __init__(
21
+ self,
22
+ api_key: Optional[str] = None,
23
+ model_id: str = "sonic-2",
24
+ default_voice_id: str = "78ab82d5-25be-4f7d-82b3-7ad64e5b85b2",
25
+ enable_text_to_speech: bool = True,
26
+ enable_list_voices: bool = True,
27
+ enable_localize_voice: bool = False,
28
+ all: bool = False,
29
+ **kwargs,
30
+ ):
31
+ self.api_key = api_key or getenv("CARTESIA_API_KEY")
32
+
33
+ if not self.api_key:
34
+ raise ValueError("CARTESIA_API_KEY not set. Please set the CARTESIA_API_KEY environment variable.")
35
+
36
+ self.client = cartesia.Cartesia(api_key=self.api_key)
37
+ self.model_id = model_id
38
+ self.default_voice_id = default_voice_id
39
+
40
+ tools: List[Any] = []
41
+ if all or enable_localize_voice:
42
+ tools.append(self.localize_voice)
43
+ if all or enable_text_to_speech:
44
+ tools.append(self.text_to_speech)
45
+ if all or enable_list_voices:
46
+ tools.append(self.list_voices)
47
+
48
+ super().__init__(name="cartesia_tools", tools=tools, **kwargs)
49
+
50
+ def list_voices(self) -> str:
51
+ """List available voices from Cartesia (first page).
52
+
53
+ Returns:
54
+ str: JSON string containing a list of voices, each with id, name, description, and language.
55
+ """
56
+ try:
57
+ voices = self.client.voices.list()
58
+
59
+ voice_objects = voices.items if voices else None
60
+
61
+ filtered_result = []
62
+ if voice_objects:
63
+ for voice in voice_objects:
64
+ try:
65
+ # Extract desired attributes from the Voice object
66
+ voice_data = {
67
+ "id": voice.id if hasattr(voice, "id") else None,
68
+ "name": voice.name if hasattr(voice, "name") else None,
69
+ "description": voice.description if hasattr(voice, "description") else None,
70
+ "language": voice.language if hasattr(voice, "language") else None,
71
+ }
72
+
73
+ if voice_data["id"]: # Only add if we could get an ID
74
+ filtered_result.append(voice_data)
75
+ else:
76
+ log_info(f"Could not extract 'id' from voice object: {voice}")
77
+ except AttributeError as ae:
78
+ log_error(f"AttributeError accessing voice data: {ae}. Voice data: {voice}")
79
+ continue
80
+ except Exception as inner_e:
81
+ log_error(f"Unexpected error processing voice: {inner_e}. Voice data: {voice}")
82
+ continue
83
+
84
+ return json.dumps(filtered_result, indent=4)
85
+ except Exception as e:
86
+ log_error(f"Error listing voices from Cartesia: {e}", exc_info=True)
87
+ return json.dumps({"error": str(e), "detail": "Error occurred in list_voices function."})
88
+
89
+ def localize_voice(
90
+ self,
91
+ name: str,
92
+ description: str,
93
+ language: str,
94
+ original_speaker_gender: str,
95
+ voice_id: Optional[str] = None,
96
+ ) -> str:
97
+ """Create a new voice localized to a different language.
98
+
99
+ Args:
100
+ name (str): The desired name for the new localized voice.
101
+ description (str): The description for the new localized voice.
102
+ language (str): The target language code (e.g., 'fr', 'es').
103
+ original_speaker_gender (str): The gender of the original speaker ("male" or "female").
104
+ voice_id (optional): The ID of an existing voice to use as the base. If None, uses the default voice ID configured in the tool. Defaults to None.
105
+
106
+ Returns:
107
+ str: JSON string containing the information of the newly created localized voice, including its 'id'.
108
+ """
109
+ localize_voice_id = voice_id or self.default_voice_id
110
+ log_debug(f"Using voice_id '{localize_voice_id}' for localization.")
111
+
112
+ try:
113
+ result = self.client.voices.localize(
114
+ voice_id=localize_voice_id,
115
+ name=name,
116
+ description=description,
117
+ language=language,
118
+ original_speaker_gender=original_speaker_gender,
119
+ )
120
+
121
+ if isinstance(result, dict):
122
+ return json.dumps(result, indent=4)
123
+ else:
124
+ return result.model_dump_json(indent=4)
125
+
126
+ except Exception as e:
127
+ log_error(f"Error localizing voice with Cartesia: {e}", exc_info=True)
128
+ return json.dumps({"error": str(e), "type": type(e).__name__})
129
+
130
+ def text_to_speech(
131
+ self,
132
+ agent: Union[Agent, Team],
133
+ transcript: str,
134
+ voice_id: Optional[str] = None,
135
+ ) -> ToolResult:
136
+ """
137
+ Convert text to speech.
138
+ Args:
139
+ transcript: The text to convert to speech
140
+ voice_id (optional): The ID of the voice to use for the text-to-speech. If None, uses the default voice ID configured in the tool. Defaults to None.
141
+
142
+ Returns:
143
+ ToolResult: A ToolResult containing the generated audio or error message.
144
+ """
145
+
146
+ try:
147
+ effective_voice_id = voice_id or self.default_voice_id
148
+
149
+ log_info(f"Using voice_id: {effective_voice_id} for text_to_speech.")
150
+ log_info(f"Using model_id: {self.model_id} for text_to_speech.")
151
+
152
+ output_format_sample_rate = 44100
153
+ requested_bit_rate = 128000
154
+ mime_type = "audio/mpeg"
155
+
156
+ output_format = {
157
+ "container": "mp3",
158
+ "sample_rate": output_format_sample_rate,
159
+ "bit_rate": requested_bit_rate,
160
+ "encoding": "mp3",
161
+ }
162
+
163
+ params: Dict[str, Any] = {
164
+ "model_id": self.model_id,
165
+ "transcript": transcript,
166
+ "voice": {"mode": "id", "id": effective_voice_id},
167
+ "output_format": output_format,
168
+ }
169
+
170
+ audio_iterator = self.client.tts.bytes(**params)
171
+ audio_data = b"".join(chunk for chunk in audio_iterator)
172
+
173
+ # Create AudioArtifact
174
+ audio_artifact = Audio(
175
+ id=str(uuid4()),
176
+ content=audio_data,
177
+ mime_type=mime_type, # Hardcoded to audio/mpeg
178
+ )
179
+
180
+ return ToolResult(
181
+ content="Audio generated and attached successfully.",
182
+ audios=[audio_artifact],
183
+ )
184
+
185
+ except Exception as e:
186
+ log_error(f"Error generating speech with Cartesia: {e}", exc_info=True)
187
+ return ToolResult(content=f"Error generating speech: {e}")
agno/tools/clickup.py ADDED
@@ -0,0 +1,244 @@
1
+ import json
2
+ import re
3
+ from os import getenv
4
+ from typing import Any, Dict, List, Optional
5
+
6
+ from agno.tools import Toolkit
7
+ from agno.utils.log import log_debug, logger
8
+
9
+ try:
10
+ import requests
11
+ except ImportError:
12
+ raise ImportError("`requests` not installed. Please install using `pip install requests`")
13
+
14
+
15
+ class ClickUpTools(Toolkit):
16
+ def __init__(
17
+ self,
18
+ api_key: Optional[str] = None,
19
+ master_space_id: Optional[str] = None,
20
+ **kwargs,
21
+ ):
22
+ self.api_key = api_key or getenv("CLICKUP_API_KEY")
23
+ self.master_space_id = master_space_id or getenv("MASTER_SPACE_ID")
24
+ self.base_url = "https://api.clickup.com/api/v2"
25
+ self.headers = {"Authorization": self.api_key}
26
+
27
+ if not self.api_key:
28
+ raise ValueError("CLICKUP_API_KEY not set. Please set the CLICKUP_API_KEY environment variable.")
29
+ if not self.master_space_id:
30
+ raise ValueError("MASTER_SPACE_ID not set. Please set the MASTER_SPACE_ID environment variable.")
31
+
32
+ tools: List[Any] = [
33
+ self.list_tasks,
34
+ self.create_task,
35
+ self.get_task,
36
+ self.update_task,
37
+ self.delete_task,
38
+ self.list_spaces,
39
+ self.list_lists,
40
+ ]
41
+
42
+ super().__init__(name="clickup", tools=tools, **kwargs)
43
+
44
+ def _make_request(
45
+ self, method: str, endpoint: str, params: Optional[Dict] = None, data: Optional[Dict] = None
46
+ ) -> Dict[str, Any]:
47
+ """Make a request to the ClickUp API."""
48
+ url = f"{self.base_url}/{endpoint}"
49
+ try:
50
+ response = requests.request(method=method, url=url, headers=self.headers, params=params, json=data)
51
+ response.raise_for_status()
52
+ return response.json()
53
+ except requests.exceptions.RequestException as e:
54
+ logger.error(f"Error making request to {url}: {e}")
55
+ return {"error": str(e)}
56
+
57
+ def _find_by_name(self, items: List[Dict[str, Any]], name: str) -> Optional[Dict[str, Any]]:
58
+ """Find an item in a list by name using exact match or regex pattern.
59
+
60
+ Args:
61
+ items: List of items to search through
62
+ name: Name to search for
63
+
64
+ Returns:
65
+ Matching item or None if not found
66
+ """
67
+ if not name:
68
+ return items[0] if items else None
69
+
70
+ pattern = re.compile(name, re.IGNORECASE)
71
+ for item in items:
72
+ # Try exact match first (case-insensitive)
73
+ if item["name"].lower() == name.lower():
74
+ return item
75
+ # Then try regex pattern match
76
+ if pattern.search(item["name"]):
77
+ return item
78
+ return None
79
+
80
+ def _get_space(self, space_name: str) -> Dict[str, Any]:
81
+ """Get space information by name."""
82
+ spaces = self._make_request("GET", f"team/{self.master_space_id}/space")
83
+ if "error" in spaces:
84
+ return spaces
85
+
86
+ spaces_list = spaces.get("spaces", [])
87
+ if not spaces_list:
88
+ return {"error": "No spaces found"}
89
+
90
+ space = self._find_by_name(spaces_list, space_name)
91
+ if not space:
92
+ return {"error": f"Space '{space_name}' not found"}
93
+ return space
94
+
95
+ def _get_list(self, space_id: str, list_name: str) -> Dict[str, Any]:
96
+ """Get list information by name."""
97
+ lists = self._make_request("GET", f"space/{space_id}/list")
98
+ if "error" in lists:
99
+ return lists
100
+
101
+ lists_data = lists.get("lists", [])
102
+ if not lists_data:
103
+ return {"error": "No lists found in space"}
104
+
105
+ list_item = self._find_by_name(lists_data, list_name)
106
+ if not list_item:
107
+ return {"error": f"List '{list_name}' not found"}
108
+ return list_item
109
+
110
+ def _get_tasks(self, list_id: str) -> List[Dict[str, Any]]:
111
+ """Get tasks in a list, optionally filtered by name."""
112
+ tasks = self._make_request("GET", f"list/{list_id}/task")
113
+ if "error" in tasks:
114
+ return []
115
+
116
+ tasks_data = tasks.get("tasks", [])
117
+ return tasks_data
118
+
119
+ def list_tasks(self, space_name: str) -> str:
120
+ """List all tasks in a space.
121
+
122
+ Args:
123
+ space_name (str): Name of the space to list tasks from
124
+
125
+ Returns:
126
+ str: JSON string containing tasks
127
+ """
128
+ # Get space
129
+ space = self._get_space(space_name)
130
+ if "error" in space:
131
+ return json.dumps(space, indent=2)
132
+
133
+ # Get lists
134
+ lists = self._make_request("GET", f"space/{space['id']}/list")
135
+ lists_data = lists.get("lists", [])
136
+ if not lists_data:
137
+ return json.dumps({"error": f"No lists found in space '{space_name}'"}, indent=2)
138
+
139
+ # Get tasks from all lists
140
+ all_tasks = []
141
+ for list_info in lists_data:
142
+ tasks = self._get_tasks(list_info["id"])
143
+ for task in tasks:
144
+ task["list_name"] = list_info["name"] # Add list name for context
145
+ all_tasks.extend(tasks)
146
+
147
+ return json.dumps({"tasks": all_tasks}, indent=2)
148
+
149
+ def create_task(self, space_name: str, task_name: str, task_description: str) -> str:
150
+ """Create a new task in a space.
151
+
152
+ Args:
153
+ space_name (str): Name of the space to create task in
154
+ task_name (str): Name of the task
155
+ task_description (str): Description of the task
156
+
157
+ Returns:
158
+ str: JSON string containing created task details
159
+ """
160
+ # Get space
161
+ space = self._get_space(space_name)
162
+ if "error" in space:
163
+ return json.dumps(space, indent=2)
164
+
165
+ # Get first list in space
166
+ response = self._make_request("GET", f"space/{space['id']}/list")
167
+ log_debug(f"Lists: {response}")
168
+ lists_data = response.get("lists", [])
169
+ if not lists_data:
170
+ return json.dumps({"error": f"No lists found in space '{space_name}'"}, indent=2)
171
+
172
+ list_info = lists_data[0] # Use first list
173
+
174
+ # Create task
175
+ data = {"name": task_name, "description": task_description}
176
+
177
+ task = self._make_request("POST", f"list/{list_info['id']}/task", data=data)
178
+ return json.dumps(task, indent=2)
179
+
180
+ def list_spaces(self) -> str:
181
+ """List all spaces in the workspace.
182
+
183
+ Returns:
184
+ str: JSON string containing list of spaces
185
+ """
186
+ spaces = self._make_request("GET", f"team/{self.master_space_id}/space")
187
+ return json.dumps(spaces, indent=2)
188
+
189
+ def list_lists(self, space_name: str) -> str:
190
+ """List all lists in a space.
191
+
192
+ Args:
193
+ space_name (str): Name of the space to list lists from
194
+
195
+ Returns:
196
+ str: JSON string containing list of lists
197
+ """
198
+ # Get space
199
+ space = self._get_space(space_name)
200
+ if "error" in space:
201
+ return json.dumps(space, indent=2)
202
+
203
+ # Get lists
204
+ lists = self._make_request("GET", f"space/{space['id']}/list")
205
+ return json.dumps(lists, indent=2)
206
+
207
+ def get_task(self, task_id: str) -> str:
208
+ """Get details of a specific task.
209
+
210
+ Args:
211
+ task_id (str): The ID of the task
212
+
213
+ Returns:
214
+ str: JSON string containing task details
215
+ """
216
+ task = self._make_request("GET", f"task/{task_id}")
217
+ return json.dumps(task, indent=2)
218
+
219
+ def update_task(self, task_id: str, **kwargs) -> str:
220
+ """Update a specific task.
221
+
222
+ Args:
223
+ task_id (str): The ID of the task
224
+ **kwargs: Task fields to update (name, description, status, priority, etc.)
225
+
226
+ Returns:
227
+ str: JSON string containing updated task details
228
+ """
229
+ task = self._make_request("PUT", f"task/{task_id}", data=kwargs)
230
+ return json.dumps(task, indent=2)
231
+
232
+ def delete_task(self, task_id: str) -> str:
233
+ """Delete a specific task.
234
+
235
+ Args:
236
+ task_id (str): The ID of the task
237
+
238
+ Returns:
239
+ str: JSON string containing deletion status
240
+ """
241
+ result = self._make_request("DELETE", f"task/{task_id}")
242
+ if "error" not in result:
243
+ result = {"success": True, "message": f"Task {task_id} deleted successfully"}
244
+ return json.dumps(result, indent=2)
@@ -0,0 +1,240 @@
1
+ import json
2
+ from os import getenv
3
+ from typing import Any, List, Optional
4
+
5
+ import requests
6
+
7
+ from agno.tools import Toolkit
8
+ from agno.utils.log import log_info, logger
9
+
10
+ try:
11
+ from atlassian import Confluence
12
+ except (ModuleNotFoundError, ImportError):
13
+ raise ImportError("atlassian-python-api not install . Please install using `pip install atlassian-python-api`")
14
+
15
+
16
+ class ConfluenceTools(Toolkit):
17
+ def __init__(
18
+ self,
19
+ username: Optional[str] = None,
20
+ password: Optional[str] = None,
21
+ url: Optional[str] = None,
22
+ api_key: Optional[str] = None,
23
+ verify_ssl: bool = True,
24
+ **kwargs,
25
+ ):
26
+ """Initialize Confluence Tools with authentication credentials.
27
+
28
+ Args:
29
+ username (str, optional): Confluence username. Defaults to None.
30
+ password (str, optional): Confluence password. Defaults to None.
31
+ url (str, optional): Confluence instance URL. Defaults to None.
32
+ api_key (str, optional): Confluence API key. Defaults to None.
33
+ verify_ssl (bool, optional): Whether to verify SSL certificates. Defaults to True.
34
+
35
+ Notes:
36
+ Credentials can be provided either through method arguments or environment variables:
37
+ - CONFLUENCE_URL
38
+ - CONFLUENCE_USERNAME
39
+ - CONFLUENCE_API_KEY
40
+ """
41
+
42
+ self.url = url or getenv("CONFLUENCE_URL")
43
+ self.username = username or getenv("CONFLUENCE_USERNAME")
44
+ self.password = api_key or getenv("CONFLUENCE_API_KEY") or password or getenv("CONFLUENCE_PASSWORD")
45
+
46
+ if not self.url:
47
+ raise ValueError(
48
+ "Confluence URL not provided. Pass it in the constructor or set CONFLUENCE_URL in environment variable"
49
+ )
50
+
51
+ if not self.username:
52
+ raise ValueError(
53
+ "Confluence username not provided. Pass it in the constructor or set CONFLUENCE_USERNAME in environment variable"
54
+ )
55
+
56
+ if not self.password:
57
+ raise ValueError("Confluence API KEY or password not provided")
58
+
59
+ session = requests.Session()
60
+ session.verify = verify_ssl
61
+
62
+ if not verify_ssl:
63
+ import urllib3
64
+
65
+ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
66
+
67
+ self.confluence = Confluence(
68
+ url=self.url,
69
+ username=self.username,
70
+ password=self.password,
71
+ verify_ssl=verify_ssl,
72
+ session=session,
73
+ )
74
+
75
+ tools: List[Any] = [
76
+ self.get_page_content,
77
+ self.get_space_key,
78
+ self.create_page,
79
+ self.update_page,
80
+ self.get_all_space_detail,
81
+ self.get_all_page_from_space,
82
+ ]
83
+
84
+ super().__init__(name="confluence_tools", tools=tools, **kwargs)
85
+
86
+ def get_page_content(self, space_name: str, page_title: str, expand: Optional[str] = "body.storage"):
87
+ """Retrieve the content of a specific page in a Confluence space.
88
+
89
+ Args:
90
+ space_name (str): Name of the Confluence space.
91
+ page_title (str): Title of the page to retrieve.
92
+ expand (str, optional): Fields to expand in the page response. Defaults to "body.storage".
93
+
94
+ Returns:
95
+ str: JSON-encoded page content or error message.
96
+ """
97
+ try:
98
+ log_info(f"Retrieving page content from space '{space_name}'")
99
+ key = self.get_space_key(space_name=space_name)
100
+ if key == "No space found":
101
+ return json.dumps({"error": f"Space '{space_name}' not found"})
102
+
103
+ page = self.confluence.get_page_by_title(key, page_title, expand=expand)
104
+ if page:
105
+ log_info(f"Successfully retrieved page '{page_title}' from space '{space_name}'")
106
+ return json.dumps(page)
107
+
108
+ logger.warning(f"Page '{page_title}' not found in space '{space_name}'")
109
+ return json.dumps({"error": f"Page '{page_title}' not found in space '{space_name}'"})
110
+
111
+ except Exception as e:
112
+ logger.error(f"Error retrieving page '{page_title}': {e}")
113
+ return json.dumps({"error": str(e)})
114
+
115
+ def get_all_space_detail(self):
116
+ """Retrieve details about all Confluence spaces.
117
+
118
+ Returns:
119
+ str: List of space details as a string.
120
+ """
121
+ log_info("Retrieving details for all Confluence spaces")
122
+ results = []
123
+ start = 0
124
+ limit = 50
125
+
126
+ while True:
127
+ spaces_data = self.confluence.get_all_spaces(start=start, limit=limit)
128
+ if not spaces_data.get("results"):
129
+ break
130
+ results.extend(spaces_data["results"])
131
+
132
+ if len(spaces_data["results"]) < limit:
133
+ break
134
+ start += limit
135
+
136
+ return str(results)
137
+
138
+ def get_space_key(self, space_name: str):
139
+ """Get the space key for a particular Confluence space.
140
+
141
+ Args:
142
+ space_name (str): Name of the space whose key is required.
143
+
144
+ Returns:
145
+ str: Space key or "No space found" if space doesn't exist.
146
+ """
147
+ start = 0
148
+ limit = 50
149
+
150
+ while True:
151
+ result = self.confluence.get_all_spaces(start=start, limit=limit)
152
+ if not result.get("results"):
153
+ break
154
+
155
+ spaces = result["results"]
156
+
157
+ for space in spaces:
158
+ if space["name"].lower() == space_name.lower():
159
+ log_info(f"Found space key for '{space_name}': {space['key']}")
160
+ return space["key"]
161
+
162
+ for space in spaces:
163
+ if space["key"] == space_name:
164
+ log_info(f"'{space_name}' is already a space key")
165
+ return space_name
166
+
167
+ if len(spaces) < limit:
168
+ break
169
+ start += limit
170
+
171
+ logger.warning(f"No space named {space_name} found")
172
+ return "No space found"
173
+
174
+ def get_all_page_from_space(self, space_name: str):
175
+ """Retrieve all pages from a specific Confluence space.
176
+
177
+ Args:
178
+ space_name (str): Name of the Confluence space.
179
+
180
+ Returns:
181
+ list: Details of pages in the specified space.
182
+ """
183
+ log_info(f"Retrieving all pages from space '{space_name}'")
184
+ space_key = self.get_space_key(space_name)
185
+
186
+ if space_key == "No space found":
187
+ return json.dumps({"error": f"Space '{space_name}' not found"})
188
+
189
+ page_details = self.confluence.get_all_pages_from_space(
190
+ space_key, status=None, expand=None, content_type="page"
191
+ )
192
+
193
+ if not page_details:
194
+ return json.dumps({"error": f"No pages found in space '{space_name}'"})
195
+
196
+ page_details = str([{"id": page["id"], "title": page["title"]} for page in page_details])
197
+ return page_details
198
+
199
+ def create_page(self, space_name: str, title: str, body: str, parent_id: Optional[str] = None) -> str:
200
+ """Create a new page in Confluence.
201
+
202
+ Args:
203
+ space_name (str): Name of the Confluence space.
204
+ title (str): Title of the new page.
205
+ body (str): Content of the new page.
206
+ parent_id (str, optional): ID of the parent page if creating a child page. Defaults to None.
207
+
208
+ Returns:
209
+ str: JSON-encoded page ID and title or error message.
210
+ """
211
+ try:
212
+ space_key = self.get_space_key(space_name=space_name)
213
+ if space_key == "No space found":
214
+ return json.dumps({"error": f"Space '{space_name}' not found"})
215
+
216
+ page = self.confluence.create_page(space_key, title, body, parent_id=parent_id)
217
+ log_info(f"Page created: {title} with ID {page['id']}")
218
+ return json.dumps({"id": page["id"], "title": title})
219
+ except Exception as e:
220
+ logger.error(f"Error creating page '{title}': {e}")
221
+ return json.dumps({"error": str(e)})
222
+
223
+ def update_page(self, page_id: str, title: str, body: str) -> str:
224
+ """Update an existing Confluence page.
225
+
226
+ Args:
227
+ page_id (str): ID of the page to update.
228
+ title (str): New title for the page.
229
+ body (str): Updated content for the page.
230
+
231
+ Returns:
232
+ str: JSON-encoded status and ID of the updated page or error message.
233
+ """
234
+ try:
235
+ updated_page = self.confluence.update_page(page_id, title, body)
236
+ log_info(f"Page updated: {title} with ID {updated_page['id']}")
237
+ return json.dumps({"status": "success", "id": updated_page["id"]})
238
+ except Exception as e:
239
+ logger.error(f"Error updating page '{title}': {e}")
240
+ return json.dumps({"error": str(e)})