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
@@ -1,350 +0,0 @@
1
- import time
2
- from dataclasses import asdict
3
- from decimal import Decimal
4
- from typing import Any, Dict, List, Optional
5
-
6
- from agno.storage.agent.base import AgentStorage
7
- from agno.storage.agent.session import AgentSession
8
- from agno.utils.log import logger
9
-
10
- try:
11
- import boto3
12
- from boto3.dynamodb.conditions import Key
13
- from botocore.exceptions import ClientError
14
- except ImportError:
15
- raise ImportError("`boto3` not installed. Please install using `pip install boto3`.")
16
-
17
-
18
- class DynamoDbAgentStorage(AgentStorage):
19
- def __init__(
20
- self,
21
- table_name: str,
22
- region_name: Optional[str] = None,
23
- aws_access_key_id: Optional[str] = None,
24
- aws_secret_access_key: Optional[str] = None,
25
- endpoint_url: Optional[str] = None,
26
- create_table_if_not_exists: bool = True,
27
- ):
28
- """
29
- Initialize the DynamoDbAgentStorage.
30
-
31
- Args:
32
- table_name (str): The name of the DynamoDB table.
33
- region_name (Optional[str]): AWS region name.
34
- aws_access_key_id (Optional[str]): AWS access key ID.
35
- aws_secret_access_key (Optional[str]): AWS secret access key.
36
- endpoint_url (Optional[str]): The complete URL to use for the constructed client.
37
- create_table_if_not_exists (bool): Whether to create the table if it does not exist.
38
- """
39
- self.table_name = table_name
40
- self.region_name = region_name
41
- self.endpoint_url = endpoint_url
42
- self.aws_access_key_id = aws_access_key_id
43
- self.aws_secret_access_key = aws_secret_access_key
44
- self.create_table_if_not_exists = create_table_if_not_exists
45
-
46
- # Initialize DynamoDB resource
47
- self.dynamodb = boto3.resource(
48
- "dynamodb",
49
- region_name=self.region_name,
50
- aws_access_key_id=self.aws_access_key_id,
51
- aws_secret_access_key=self.aws_secret_access_key,
52
- endpoint_url=self.endpoint_url,
53
- )
54
-
55
- # Initialize table
56
- self.table = self.dynamodb.Table(self.table_name)
57
-
58
- # Optionally create table if it does not exist
59
- if self.create_table_if_not_exists:
60
- self.create()
61
- logger.debug(f"Initialized DynamoDbAgentStorage with table '{self.table_name}'")
62
-
63
- def create(self) -> None:
64
- """
65
- Create the DynamoDB table if it does not exist.
66
- """
67
- try:
68
- # Check if table exists
69
- self.dynamodb.meta.client.describe_table(TableName=self.table_name)
70
- logger.debug(f"Table '{self.table_name}' already exists.")
71
- except ClientError as e:
72
- if e.response["Error"]["Code"] == "ResourceNotFoundException":
73
- logger.debug(f"Creating table '{self.table_name}'.")
74
- # Create the table
75
- self.table = self.dynamodb.create_table(
76
- TableName=self.table_name,
77
- KeySchema=[{"AttributeName": "session_id", "KeyType": "HASH"}],
78
- AttributeDefinitions=[
79
- {"AttributeName": "session_id", "AttributeType": "S"},
80
- {"AttributeName": "user_id", "AttributeType": "S"},
81
- {"AttributeName": "agent_id", "AttributeType": "S"},
82
- {"AttributeName": "created_at", "AttributeType": "N"},
83
- ],
84
- GlobalSecondaryIndexes=[
85
- {
86
- "IndexName": "user_id-index",
87
- "KeySchema": [
88
- {"AttributeName": "user_id", "KeyType": "HASH"},
89
- {"AttributeName": "created_at", "KeyType": "RANGE"},
90
- ],
91
- "Projection": {"ProjectionType": "ALL"},
92
- "ProvisionedThroughput": {
93
- "ReadCapacityUnits": 5,
94
- "WriteCapacityUnits": 5,
95
- },
96
- },
97
- {
98
- "IndexName": "agent_id-index",
99
- "KeySchema": [
100
- {"AttributeName": "agent_id", "KeyType": "HASH"},
101
- {"AttributeName": "created_at", "KeyType": "RANGE"},
102
- ],
103
- "Projection": {"ProjectionType": "ALL"},
104
- "ProvisionedThroughput": {
105
- "ReadCapacityUnits": 5,
106
- "WriteCapacityUnits": 5,
107
- },
108
- },
109
- ],
110
- ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5},
111
- )
112
- # Wait until the table exists.
113
- self.table.wait_until_exists()
114
- logger.debug(f"Table '{self.table_name}' created successfully.")
115
- else:
116
- logger.error(f"Unable to create table '{self.table_name}': {e.response['Error']['Message']}")
117
- except Exception as e:
118
- logger.error(f"Exception during table creation: {e}")
119
-
120
- def read(self, session_id: str, user_id: Optional[str] = None) -> Optional[AgentSession]:
121
- """
122
- Read and return an AgentSession from the database.
123
-
124
- Args:
125
- session_id (str): ID of the session to read.
126
- user_id (Optional[str]): User ID to filter by. Defaults to None.
127
-
128
- Returns:
129
- Optional[AgentSession]: AgentSession object if found, None otherwise.
130
- """
131
- try:
132
- key = {"session_id": session_id}
133
- if user_id is not None:
134
- key["user_id"] = user_id
135
-
136
- response = self.table.get_item(Key=key)
137
- item = response.get("Item", None)
138
- if item is not None:
139
- # Convert Decimal to int or float
140
- item = self._deserialize_item(item)
141
- return AgentSession.from_dict(item)
142
- except Exception as e:
143
- logger.error(f"Error reading session_id '{session_id}' with user_id '{user_id}': {e}")
144
- return None
145
-
146
- def get_all_session_ids(self, user_id: Optional[str] = None, agent_id: Optional[str] = None) -> List[str]:
147
- """
148
- Retrieve all session IDs, optionally filtered by user_id and/or agent_id.
149
-
150
- Args:
151
- user_id (Optional[str], optional): User ID to filter by. Defaults to None.
152
- agent_id (Optional[str], optional): Agent ID to filter by. Defaults to None.
153
-
154
- Returns:
155
- List[str]: List of session IDs matching the criteria.
156
- """
157
- session_ids: List[str] = []
158
- try:
159
- if user_id is not None:
160
- # Query using user_id index
161
- response = self.table.query(
162
- IndexName="user_id-index",
163
- KeyConditionExpression=Key("user_id").eq(user_id),
164
- ProjectionExpression="session_id",
165
- )
166
- items = response.get("Items", [])
167
- session_ids.extend([item["session_id"] for item in items if "session_id" in item])
168
- elif agent_id is not None:
169
- # Query using agent_id index
170
- response = self.table.query(
171
- IndexName="agent_id-index",
172
- KeyConditionExpression=Key("agent_id").eq(agent_id),
173
- ProjectionExpression="session_id",
174
- )
175
- items = response.get("Items", [])
176
- session_ids.extend([item["session_id"] for item in items if "session_id" in item])
177
- else:
178
- # Scan the whole table
179
- response = self.table.scan(ProjectionExpression="session_id")
180
- items = response.get("Items", [])
181
- session_ids.extend([item["session_id"] for item in items if "session_id" in item])
182
- except Exception as e:
183
- logger.error(f"Error retrieving session IDs: {e}")
184
- return session_ids
185
-
186
- def get_all_sessions(self, user_id: Optional[str] = None, agent_id: Optional[str] = None) -> List[AgentSession]:
187
- """
188
- Retrieve all sessions, optionally filtered by user_id and/or agent_id.
189
-
190
- Args:
191
- user_id (Optional[str], optional): User ID to filter by. Defaults to None.
192
- agent_id (Optional[str], optional): Agent ID to filter by. Defaults to None.
193
-
194
- Returns:
195
- List[AgentSession]: List of AgentSession objects matching the criteria.
196
- """
197
- sessions: List[AgentSession] = []
198
- try:
199
- if user_id is not None:
200
- # Query using user_id index
201
- response = self.table.query(
202
- IndexName="user_id-index",
203
- KeyConditionExpression=Key("user_id").eq(user_id),
204
- ProjectionExpression="session_id, agent_id, user_id, memory, agent_data, session_data, extra_data, created_at, updated_at",
205
- )
206
- items = response.get("Items", [])
207
- for item in items:
208
- item = self._deserialize_item(item)
209
- _agent_session = AgentSession.from_dict(item)
210
- if _agent_session is not None:
211
- sessions.append(_agent_session)
212
- elif agent_id is not None:
213
- # Query using agent_id index
214
- response = self.table.query(
215
- IndexName="agent_id-index",
216
- KeyConditionExpression=Key("agent_id").eq(agent_id),
217
- ProjectionExpression="session_id, agent_id, user_id, memory, agent_data, session_data, extra_data, created_at, updated_at",
218
- )
219
- items = response.get("Items", [])
220
- for item in items:
221
- item = self._deserialize_item(item)
222
- _agent_session = AgentSession.from_dict(item)
223
- if _agent_session is not None:
224
- sessions.append(_agent_session)
225
- else:
226
- # Scan the whole table
227
- response = self.table.scan(
228
- ProjectionExpression="session_id, agent_id, user_id, memory, agent_data, session_data, extra_data, created_at, updated_at"
229
- )
230
- items = response.get("Items", [])
231
- for item in items:
232
- item = self._deserialize_item(item)
233
- _agent_session = AgentSession.from_dict(item)
234
- if _agent_session is not None:
235
- sessions.append(_agent_session)
236
- except Exception as e:
237
- logger.error(f"Error retrieving sessions: {e}")
238
- return sessions
239
-
240
- def upsert(self, session: AgentSession) -> Optional[AgentSession]:
241
- """
242
- Create or update an AgentSession in the database.
243
-
244
- Args:
245
- session (AgentSession): The session data to upsert.
246
-
247
- Returns:
248
- Optional[AgentSession]: The upserted AgentSession, or None if operation failed.
249
- """
250
- try:
251
- item = asdict(session)
252
-
253
- # Add timestamps
254
- current_time = int(time.time())
255
- if "created_at" not in item or item["created_at"] is None:
256
- item["created_at"] = current_time
257
- item["updated_at"] = current_time
258
-
259
- # Convert data to DynamoDB compatible format
260
- item = self._serialize_item(item)
261
-
262
- # Put item into DynamoDB
263
- self.table.put_item(Item=item)
264
- return self.read(session.session_id)
265
- except Exception as e:
266
- logger.error(f"Error upserting session: {e}")
267
- return None
268
-
269
- def delete_session(self, session_id: Optional[str] = None):
270
- """
271
- Delete a session from the database.
272
-
273
- Args:
274
- session_id (Optional[str], optional): ID of the session to delete. Defaults to None.
275
- """
276
- if session_id is None:
277
- logger.warning("No session_id provided for deletion.")
278
- return
279
- try:
280
- self.table.delete_item(Key={"session_id": session_id})
281
- logger.info(f"Successfully deleted session with session_id: {session_id}")
282
- except Exception as e:
283
- logger.error(f"Error deleting session: {e}")
284
-
285
- def drop(self) -> None:
286
- """
287
- Drop the table from the database if it exists.
288
- """
289
- try:
290
- self.table.delete()
291
- self.table.wait_until_not_exists()
292
- logger.debug(f"Table '{self.table_name}' deleted successfully.")
293
- except Exception as e:
294
- logger.error(f"Error deleting table '{self.table_name}': {e}")
295
-
296
- def upgrade_schema(self) -> None:
297
- """
298
- Upgrade the schema to the latest version.
299
- This method is currently a placeholder and does not perform any actions.
300
- """
301
- pass
302
-
303
- def _serialize_item(self, item: Dict[str, Any]) -> Dict[str, Any]:
304
- """
305
- Serialize item to be compatible with DynamoDB.
306
-
307
- Args:
308
- item (Dict[str, Any]): The item to serialize.
309
-
310
- Returns:
311
- Dict[str, Any]: The serialized item.
312
- """
313
-
314
- def serialize_value(value):
315
- if isinstance(value, float):
316
- return Decimal(str(value))
317
- elif isinstance(value, dict):
318
- return {k: serialize_value(v) for k, v in value.items()}
319
- elif isinstance(value, list):
320
- return [serialize_value(v) for v in value]
321
- else:
322
- return value
323
-
324
- return {k: serialize_value(v) for k, v in item.items() if v is not None}
325
-
326
- def _deserialize_item(self, item: Dict[str, Any]) -> Dict[str, Any]:
327
- """
328
- Deserialize item from DynamoDB format.
329
-
330
- Args:
331
- item (Dict[str, Any]): The item to deserialize.
332
-
333
- Returns:
334
- Dict[str, Any]: The deserialized item.
335
- """
336
-
337
- def deserialize_value(value):
338
- if isinstance(value, Decimal):
339
- if value % 1 == 0:
340
- return int(value)
341
- else:
342
- return float(value)
343
- elif isinstance(value, dict):
344
- return {k: deserialize_value(v) for k, v in value.items()}
345
- elif isinstance(value, list):
346
- return [deserialize_value(v) for v in value]
347
- else:
348
- return value
349
-
350
- return {k: deserialize_value(v) for k, v in item.items()}
@@ -1,92 +0,0 @@
1
- import json
2
- import time
3
- from dataclasses import asdict
4
- from pathlib import Path
5
- from typing import List, Optional, Union
6
-
7
- from agno.storage.agent.base import AgentStorage
8
- from agno.storage.agent.session import AgentSession
9
- from agno.utils.log import logger
10
-
11
-
12
- class JsonAgentStorage(AgentStorage):
13
- def __init__(self, dir_path: Union[str, Path]):
14
- self.dir_path = Path(dir_path)
15
- self.dir_path.mkdir(parents=True, exist_ok=True)
16
-
17
- def serialize(self, data: dict) -> str:
18
- return json.dumps(data, ensure_ascii=False, indent=4)
19
-
20
- def deserialize(self, data: str) -> dict:
21
- return json.loads(data)
22
-
23
- def create(self) -> None:
24
- """Create the storage if it doesn't exist."""
25
- if not self.dir_path.exists():
26
- self.dir_path.mkdir(parents=True, exist_ok=True)
27
-
28
- def read(self, session_id: str, user_id: Optional[str] = None) -> Optional[AgentSession]:
29
- """Read an AgentSession from storage."""
30
- try:
31
- with open(self.dir_path / f"{session_id}.json", "r", encoding="utf-8") as f:
32
- data = self.deserialize(f.read())
33
- if user_id and data["user_id"] != user_id:
34
- return None
35
- return AgentSession.from_dict(data)
36
- except FileNotFoundError:
37
- return None
38
-
39
- def get_all_session_ids(self, user_id: Optional[str] = None, agent_id: Optional[str] = None) -> List[str]:
40
- """Get all session IDs, optionally filtered by user_id and/or agent_id."""
41
- session_ids = []
42
- for file in self.dir_path.glob("*.json"):
43
- with open(file, "r", encoding="utf-8") as f:
44
- data = self.deserialize(f.read())
45
- if (not user_id or data["user_id"] == user_id) and (not agent_id or data["agent_id"] == agent_id):
46
- session_ids.append(data["session_id"])
47
- return session_ids
48
-
49
- def get_all_sessions(self, user_id: Optional[str] = None, agent_id: Optional[str] = None) -> List[AgentSession]:
50
- """Get all sessions, optionally filtered by user_id and/or agent_id."""
51
- sessions = []
52
- for file in self.dir_path.glob("*.json"):
53
- with open(file, "r", encoding="utf-8") as f:
54
- data = self.deserialize(f.read())
55
- if (not user_id or data["user_id"] == user_id) and (not agent_id or data["agent_id"] == agent_id):
56
- _agent_session = AgentSession.from_dict(data)
57
- if _agent_session is not None:
58
- sessions.append(_agent_session)
59
- return sessions
60
-
61
- def upsert(self, session: AgentSession) -> Optional[AgentSession]:
62
- """Insert or update an AgentSession in storage."""
63
- try:
64
- data = asdict(session)
65
- data["updated_at"] = int(time.time())
66
- if "created_at" not in data:
67
- data["created_at"] = data["updated_at"]
68
-
69
- with open(self.dir_path / f"{session.session_id}.json", "w", encoding="utf-8") as f:
70
- f.write(self.serialize(data))
71
- return session
72
- except Exception as e:
73
- logger.error(f"Error upserting session: {e}")
74
- return None
75
-
76
- def delete_session(self, session_id: Optional[str] = None):
77
- """Delete a session from storage."""
78
- if session_id is None:
79
- return
80
- try:
81
- (self.dir_path / f"{session_id}.json").unlink(missing_ok=True)
82
- except Exception as e:
83
- logger.error(f"Error deleting session: {e}")
84
-
85
- def drop(self) -> None:
86
- """Drop all sessions from storage."""
87
- for file in self.dir_path.glob("*.json"):
88
- file.unlink()
89
-
90
- def upgrade_schema(self) -> None:
91
- """Upgrade the schema of the storage."""
92
- pass
@@ -1,228 +0,0 @@
1
- from datetime import datetime, timezone
2
- from typing import List, Optional
3
- from uuid import UUID
4
-
5
- try:
6
- from pymongo import MongoClient
7
- from pymongo.collection import Collection
8
- from pymongo.database import Database
9
- from pymongo.errors import PyMongoError
10
- except ImportError:
11
- raise ImportError("`pymongo` not installed. Please install it with `pip install pymongo`")
12
-
13
- from agno.storage.agent.base import AgentStorage
14
- from agno.storage.agent.session import AgentSession
15
- from agno.utils.log import logger
16
-
17
-
18
- class MongoDbAgentStorage(AgentStorage):
19
- def __init__(
20
- self,
21
- collection_name: str,
22
- db_url: Optional[str] = None,
23
- db_name: str = "agno",
24
- client: Optional[MongoClient] = None,
25
- ):
26
- """
27
- This class provides agent storage using MongoDB.
28
-
29
- Args:
30
- collection_name: Name of the collection to store agent sessions
31
- db_url: MongoDB connection URL
32
- db_name: Name of the database
33
- client: Optional existing MongoDB client
34
- """
35
- self._client: Optional[MongoClient] = client
36
- if self._client is None and db_url is not None:
37
- self._client = MongoClient(db_url)
38
- elif self._client is None:
39
- self._client = MongoClient()
40
-
41
- if self._client is None:
42
- raise ValueError("Must provide either db_url or client")
43
-
44
- self.collection_name: str = collection_name
45
- self.db_name: str = db_name
46
- self.db: Database = self._client[self.db_name]
47
- self.collection: Collection = self.db[self.collection_name]
48
-
49
- def create(self) -> None:
50
- """Create necessary indexes for the collection"""
51
- try:
52
- # Create indexes
53
- self.collection.create_index("session_id", unique=True)
54
- self.collection.create_index("user_id")
55
- self.collection.create_index("agent_id")
56
- self.collection.create_index("created_at")
57
- except PyMongoError as e:
58
- logger.error(f"Error creating indexes: {e}")
59
- raise
60
-
61
- def read(self, session_id: str, user_id: Optional[str] = None) -> Optional[AgentSession]:
62
- """Read an agent session from MongoDB
63
- Args:
64
- session_id: ID of the session to read
65
- user_id: ID of the user to read
66
- Returns:
67
- AgentSession: The session if found, otherwise None
68
- """
69
- try:
70
- query = {"session_id": session_id}
71
- if user_id:
72
- query["user_id"] = user_id
73
-
74
- doc = self.collection.find_one(query)
75
- if doc:
76
- # Remove MongoDB _id before converting to AgentSession
77
- doc.pop("_id", None)
78
- return AgentSession.from_dict(doc)
79
- return None
80
- except PyMongoError as e:
81
- logger.error(f"Error reading session: {e}")
82
- return None
83
-
84
- def get_all_session_ids(self, user_id: Optional[str] = None, agent_id: Optional[str] = None) -> List[str]:
85
- """Get all session IDs matching the criteria
86
- Args:
87
- user_id: ID of the user to read
88
- agent_id: ID of the agent to read
89
- Returns:
90
- List[str]: List of session IDs
91
- """
92
- try:
93
- query = {}
94
- if user_id is not None:
95
- query["user_id"] = user_id
96
- if agent_id is not None:
97
- query["agent_id"] = agent_id
98
-
99
- cursor = self.collection.find(query, {"session_id": 1}).sort("created_at", -1)
100
-
101
- return [str(doc["session_id"]) for doc in cursor]
102
- except PyMongoError as e:
103
- logger.error(f"Error getting session IDs: {e}")
104
- return []
105
-
106
- def get_all_sessions(self, user_id: Optional[str] = None, agent_id: Optional[str] = None) -> List[AgentSession]:
107
- """Get all sessions matching the criteria
108
- Args:
109
- user_id: ID of the user to read
110
- agent_id: ID of the agent to read
111
- Returns:
112
- List[AgentSession]: List of sessions
113
- """
114
- try:
115
- query = {}
116
- if user_id is not None:
117
- query["user_id"] = user_id
118
- if agent_id is not None:
119
- query["agent_id"] = agent_id
120
-
121
- cursor = self.collection.find(query).sort("created_at", -1)
122
- sessions = []
123
- for doc in cursor:
124
- # Remove MongoDB _id before converting to AgentSession
125
- doc.pop("_id", None)
126
- _agent_session = AgentSession.from_dict(doc)
127
- if _agent_session is not None:
128
- sessions.append(_agent_session)
129
- return sessions
130
- except PyMongoError as e:
131
- logger.error(f"Error getting sessions: {e}")
132
- return []
133
-
134
- def upsert(self, session: AgentSession, create_and_retry: bool = True) -> Optional[AgentSession]:
135
- """Upsert an agent session
136
- Args:
137
- session: AgentSession to upsert
138
- create_and_retry: Whether to create a new session if the session_id already exists
139
- Returns:
140
- AgentSession: The session if upserted, otherwise None
141
- """
142
- try:
143
- # Convert session to dict and add timestamps
144
- session_dict = session.to_dict()
145
- now = datetime.now(timezone.utc)
146
- timestamp = int(now.timestamp())
147
-
148
- # Handle UUID serialization
149
- if isinstance(session.session_id, UUID):
150
- session_dict["session_id"] = str(session.session_id)
151
-
152
- # Add version field for optimistic locking
153
- if "_version" not in session_dict:
154
- session_dict["_version"] = 1
155
- else:
156
- session_dict["_version"] += 1
157
-
158
- update_data = {**session_dict, "updated_at": timestamp}
159
-
160
- # For new documents, set created_at
161
- query = {"session_id": session_dict["session_id"]}
162
-
163
- doc = self.collection.find_one(query)
164
- if not doc:
165
- update_data["created_at"] = timestamp
166
-
167
- result = self.collection.update_one(query, {"$set": update_data}, upsert=True)
168
-
169
- if result.acknowledged:
170
- return self.read(session_id=session_dict["session_id"])
171
- return None
172
-
173
- except PyMongoError as e:
174
- logger.error(f"Error upserting session: {e}")
175
- return None
176
-
177
- def delete_session(self, session_id: Optional[str] = None) -> None:
178
- """Delete an agent session
179
- Args:
180
- session_id: ID of the session to delete
181
- Returns:
182
- None
183
- """
184
- if session_id is None:
185
- logger.warning("No session_id provided for deletion")
186
- return
187
-
188
- try:
189
- result = self.collection.delete_one({"session_id": session_id})
190
- if result.deleted_count == 0:
191
- logger.debug(f"No session found with session_id: {session_id}")
192
- else:
193
- logger.debug(f"Successfully deleted session with session_id: {session_id}")
194
- except PyMongoError as e:
195
- logger.error(f"Error deleting session: {e}")
196
-
197
- def drop(self) -> None:
198
- """Drop the collection
199
- Returns:
200
- None
201
- """
202
- try:
203
- self.collection.drop()
204
- except PyMongoError as e:
205
- logger.error(f"Error dropping collection: {e}")
206
-
207
- def upgrade_schema(self) -> None:
208
- """Placeholder for schema upgrades"""
209
- pass
210
-
211
- def __deepcopy__(self, memo):
212
- """Create a deep copy of the MongoDbAgentStorage instance"""
213
- from copy import deepcopy
214
-
215
- # Create a new instance without calling __init__
216
- cls = self.__class__
217
- copied_obj = cls.__new__(cls)
218
- memo[id(self)] = copied_obj
219
-
220
- # Deep copy attributes
221
- for k, v in self.__dict__.items():
222
- if k in {"_client", "db", "collection"}:
223
- # Reuse MongoDB connections without copying
224
- setattr(copied_obj, k, v)
225
- else:
226
- setattr(copied_obj, k, deepcopy(v, memo))
227
-
228
- return copied_obj