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,303 +0,0 @@
1
- import json
2
- from typing import Any, List, Optional
3
-
4
- try:
5
- from sqlalchemy.dialects import mysql
6
- from sqlalchemy.engine import Engine, create_engine
7
- from sqlalchemy.engine.row import Row
8
- from sqlalchemy.inspection import inspect
9
- from sqlalchemy.orm import Session, sessionmaker
10
- from sqlalchemy.schema import Column, MetaData, Table
11
- from sqlalchemy.sql.expression import select, text
12
- except ImportError:
13
- raise ImportError("`sqlalchemy` not installed")
14
-
15
- from agno.storage.agent.base import AgentStorage
16
- from agno.storage.agent.session import AgentSession
17
- from agno.utils.log import logger
18
-
19
-
20
- class SingleStoreAgentStorage(AgentStorage):
21
- def __init__(
22
- self,
23
- table_name: str,
24
- schema: Optional[str] = "ai",
25
- db_url: Optional[str] = None,
26
- db_engine: Optional[Engine] = None,
27
- schema_version: int = 1,
28
- auto_upgrade_schema: bool = False,
29
- ):
30
- """
31
- This class provides Agent storage using a singlestore table.
32
-
33
- The following order is used to determine the database connection:
34
- 1. Use the db_engine if provided
35
- 2. Use the db_url if provided
36
-
37
- Args:
38
- table_name (str): The name of the table to store the agent data.
39
- schema (Optional[str], optional): The schema of the table. Defaults to "ai".
40
- db_url (Optional[str], optional): The database URL. Defaults to None.
41
- db_engine (Optional[Engine], optional): The database engine. Defaults to None.
42
- schema_version (int, optional): The schema version. Defaults to 1.
43
- auto_upgrade_schema (bool, optional): Automatically upgrade the schema. Defaults to False.
44
- """
45
- _engine: Optional[Engine] = db_engine
46
- if _engine is None and db_url is not None:
47
- _engine = create_engine(db_url, connect_args={"charset": "utf8mb4"})
48
-
49
- if _engine is None:
50
- raise ValueError("Must provide either db_url or db_engine")
51
-
52
- # Database attributes
53
- self.table_name: str = table_name
54
- self.schema: Optional[str] = schema
55
- self.db_url: Optional[str] = db_url
56
- self.db_engine: Engine = _engine
57
- self.metadata: MetaData = MetaData(schema=self.schema)
58
-
59
- # Table schema version
60
- self.schema_version: int = schema_version
61
- # Automatically upgrade schema if True
62
- self.auto_upgrade_schema: bool = auto_upgrade_schema
63
-
64
- # Database session
65
- self.Session: sessionmaker[Session] = sessionmaker(bind=self.db_engine)
66
- # Database table for storage
67
- self.table: Table = self.get_table()
68
-
69
- def get_table_v1(self) -> Table:
70
- return Table(
71
- self.table_name,
72
- self.metadata,
73
- # Session UUID: Primary Key
74
- Column("session_id", mysql.TEXT, primary_key=True),
75
- # ID of the agent that this session is associated with
76
- Column("agent_id", mysql.TEXT),
77
- # ID of the user interacting with this agent
78
- Column("user_id", mysql.TEXT),
79
- # Agent memory
80
- Column("memory", mysql.JSON),
81
- # Agent Data
82
- Column("agent_data", mysql.JSON),
83
- # Session Data
84
- Column("session_data", mysql.JSON),
85
- # Extra Data stored with this agent
86
- Column("extra_data", mysql.JSON),
87
- # The Unix timestamp of when this session was created.
88
- Column("created_at", mysql.BIGINT),
89
- # The Unix timestamp of when this session was last updated.
90
- Column("updated_at", mysql.BIGINT),
91
- extend_existing=True,
92
- )
93
-
94
- def get_table(self) -> Table:
95
- if self.schema_version == 1:
96
- return self.get_table_v1()
97
- else:
98
- raise ValueError(f"Unsupported schema version: {self.schema_version}")
99
-
100
- def table_exists(self) -> bool:
101
- logger.debug(f"Checking if table exists: {self.table.name}")
102
- try:
103
- return inspect(self.db_engine).has_table(self.table.name, schema=self.schema)
104
- except Exception as e:
105
- logger.error(e)
106
- return False
107
-
108
- def create(self) -> None:
109
- if not self.table_exists():
110
- logger.info(f"\nCreating table: {self.table_name}\n")
111
- self.table.create(self.db_engine)
112
-
113
- def _read(self, session: Session, session_id: str, user_id: Optional[str] = None) -> Optional[Row[Any]]:
114
- stmt = select(self.table).where(self.table.c.session_id == session_id)
115
- if user_id is not None:
116
- stmt = stmt.where(self.table.c.user_id == user_id)
117
- try:
118
- return session.execute(stmt).first()
119
- except Exception as e:
120
- logger.debug(f"Exception reading from table: {e}")
121
- logger.debug(f"Table does not exist: {self.table.name}")
122
- logger.debug(f"Creating table: {self.table_name}")
123
- self.create()
124
- return None
125
-
126
- def read(self, session_id: str, user_id: Optional[str] = None) -> Optional[AgentSession]:
127
- with self.Session.begin() as sess:
128
- existing_row: Optional[Row[Any]] = self._read(session=sess, session_id=session_id, user_id=user_id)
129
- return AgentSession.from_dict(existing_row._mapping) if existing_row is not None else None # type: ignore
130
-
131
- def get_all_session_ids(self, user_id: Optional[str] = None, agent_id: Optional[str] = None) -> List[str]:
132
- session_ids: List[str] = []
133
- try:
134
- with self.Session.begin() as sess:
135
- # get all session_ids for this user
136
- stmt = select(self.table)
137
- if user_id is not None:
138
- stmt = stmt.where(self.table.c.user_id == user_id)
139
- if agent_id is not None:
140
- stmt = stmt.where(self.table.c.agent_id == agent_id)
141
- # order by created_at desc
142
- stmt = stmt.order_by(self.table.c.created_at.desc())
143
- # execute query
144
- rows = sess.execute(stmt).fetchall()
145
- for row in rows:
146
- if row is not None and row.session_id is not None:
147
- session_ids.append(row.session_id)
148
- except Exception as e:
149
- logger.error(f"An unexpected error occurred: {str(e)}")
150
- return session_ids
151
-
152
- def get_all_sessions(self, user_id: Optional[str] = None, agent_id: Optional[str] = None) -> List[AgentSession]:
153
- sessions: List[AgentSession] = []
154
- try:
155
- with self.Session.begin() as sess:
156
- # get all sessions for this user
157
- stmt = select(self.table)
158
- if user_id is not None:
159
- stmt = stmt.where(self.table.c.user_id == user_id)
160
- if agent_id is not None:
161
- stmt = stmt.where(self.table.c.agent_id == agent_id)
162
- # order by created_at desc
163
- stmt = stmt.order_by(self.table.c.created_at.desc())
164
- # execute query
165
- rows = sess.execute(stmt).fetchall()
166
- for row in rows:
167
- if row.session_id is not None:
168
- _agent_session = AgentSession.from_dict(row._mapping) # type: ignore
169
- if _agent_session is not None:
170
- sessions.append(_agent_session)
171
- except Exception:
172
- logger.debug(f"Table does not exist: {self.table.name}")
173
- return sessions
174
-
175
- def upsert(self, session: AgentSession) -> Optional[AgentSession]:
176
- """
177
- Create a new session if it does not exist, otherwise update the existing session.
178
- """
179
-
180
- with self.Session.begin() as sess:
181
- # Create an insert statement using MySQL's ON DUPLICATE KEY UPDATE syntax
182
- upsert_sql = text(
183
- f"""
184
- INSERT INTO {self.schema}.{self.table_name}
185
- (session_id, agent_id, user_id, memory, agent_data, session_data, extra_data, created_at, updated_at)
186
- VALUES
187
- (:session_id, :agent_id, :user_id, :memory, :agent_data, :session_data, :extra_data, UNIX_TIMESTAMP(), NULL)
188
- ON DUPLICATE KEY UPDATE
189
- agent_id = VALUES(agent_id),
190
- user_id = VALUES(user_id),
191
- memory = VALUES(memory),
192
- agent_data = VALUES(agent_data),
193
- session_data = VALUES(session_data),
194
- extra_data = VALUES(extra_data),
195
- updated_at = UNIX_TIMESTAMP();
196
- """
197
- )
198
-
199
- try:
200
- sess.execute(
201
- upsert_sql,
202
- {
203
- "session_id": session.session_id,
204
- "agent_id": session.agent_id,
205
- "user_id": session.user_id,
206
- "memory": json.dumps(session.memory, ensure_ascii=False)
207
- if session.memory is not None
208
- else None,
209
- "agent_data": json.dumps(session.agent_data, ensure_ascii=False)
210
- if session.agent_data is not None
211
- else None,
212
- "session_data": json.dumps(session.session_data, ensure_ascii=False)
213
- if session.session_data is not None
214
- else None,
215
- "extra_data": json.dumps(session.extra_data, ensure_ascii=False)
216
- if session.extra_data is not None
217
- else None,
218
- },
219
- )
220
- except Exception:
221
- # Create table and try again
222
- self.create()
223
- sess.execute(
224
- upsert_sql,
225
- {
226
- "session_id": session.session_id,
227
- "agent_id": session.agent_id,
228
- "user_id": session.user_id,
229
- "memory": json.dumps(session.memory, ensure_ascii=False)
230
- if session.memory is not None
231
- else None,
232
- "agent_data": json.dumps(session.agent_data, ensure_ascii=False)
233
- if session.agent_data is not None
234
- else None,
235
- "session_data": json.dumps(session.session_data, ensure_ascii=False)
236
- if session.session_data is not None
237
- else None,
238
- "extra_data": json.dumps(session.extra_data, ensure_ascii=False)
239
- if session.extra_data is not None
240
- else None,
241
- },
242
- )
243
- return self.read(session_id=session.session_id)
244
-
245
- def delete_session(self, session_id: Optional[str] = None):
246
- if session_id is None:
247
- logger.warning("No session_id provided for deletion.")
248
- return
249
-
250
- with self.Session() as sess, sess.begin():
251
- try:
252
- # Delete the session with the given session_id
253
- delete_stmt = self.table.delete().where(self.table.c.session_id == session_id)
254
- result = sess.execute(delete_stmt)
255
-
256
- if result.rowcount == 0:
257
- logger.warning(f"No session found with session_id: {session_id}")
258
- else:
259
- logger.info(f"Successfully deleted session with session_id: {session_id}")
260
- except Exception as e:
261
- logger.error(f"Error deleting session: {e}")
262
- raise
263
-
264
- def drop(self) -> None:
265
- if self.table_exists():
266
- logger.info(f"Deleting table: {self.table_name}")
267
- self.table.drop(self.db_engine)
268
-
269
- def upgrade_schema(self) -> None:
270
- pass
271
-
272
- def __deepcopy__(self, memo):
273
- """
274
- Create a deep copy of the SingleStoreAgentStorage instance, handling unpickleable attributes.
275
-
276
- Args:
277
- memo (dict): A dictionary of objects already copied during the current copying pass.
278
-
279
- Returns:
280
- SingleStoreAgentStorage: A deep-copied instance of SingleStoreAgentStorage.
281
- """
282
- from copy import deepcopy
283
-
284
- # Create a new instance without calling __init__
285
- cls = self.__class__
286
- copied_obj = cls.__new__(cls)
287
- memo[id(self)] = copied_obj
288
-
289
- # Deep copy attributes
290
- for k, v in self.__dict__.items():
291
- if k in {"metadata", "table"}:
292
- continue
293
- # Reuse db_engine and Session without copying
294
- elif k in {"db_engine", "Session"}:
295
- setattr(copied_obj, k, v)
296
- else:
297
- setattr(copied_obj, k, deepcopy(v, memo))
298
-
299
- # Recreate metadata and table for the copied instance
300
- copied_obj.metadata = MetaData(schema=self.schema)
301
- copied_obj.table = copied_obj.get_table()
302
-
303
- return copied_obj
@@ -1,357 +0,0 @@
1
- import time
2
- from pathlib import Path
3
- from typing import List, Optional
4
-
5
- try:
6
- from sqlalchemy.dialects import sqlite
7
- from sqlalchemy.engine import Engine, create_engine
8
- from sqlalchemy.inspection import inspect
9
- from sqlalchemy.orm import Session, sessionmaker
10
- from sqlalchemy.schema import Column, MetaData, Table
11
- from sqlalchemy.sql.expression import select
12
- from sqlalchemy.types import String
13
- except ImportError:
14
- raise ImportError("`sqlalchemy` not installed. Please install it using `pip install sqlalchemy`")
15
-
16
- from agno.storage.agent.base import AgentStorage
17
- from agno.storage.agent.session import AgentSession
18
- from agno.utils.log import logger
19
-
20
-
21
- class SqliteAgentStorage(AgentStorage):
22
- def __init__(
23
- self,
24
- table_name: str,
25
- db_url: Optional[str] = None,
26
- db_file: Optional[str] = None,
27
- db_engine: Optional[Engine] = None,
28
- schema_version: int = 1,
29
- auto_upgrade_schema: bool = False,
30
- ):
31
- """
32
- This class provides agent storage using a sqlite database.
33
-
34
- The following order is used to determine the database connection:
35
- 1. Use the db_engine if provided
36
- 2. Use the db_url
37
- 3. Use the db_file
38
- 4. Create a new in-memory database
39
-
40
- Args:
41
- table_name: The name of the table to store Agent sessions.
42
- db_url: The database URL to connect to.
43
- db_file: The database file to connect to.
44
- db_engine: The SQLAlchemy database engine to use.
45
- """
46
- _engine: Optional[Engine] = db_engine
47
- if _engine is None and db_url is not None:
48
- _engine = create_engine(db_url)
49
- elif _engine is None and db_file is not None:
50
- # Use the db_file to create the engine
51
- db_path = Path(db_file).resolve()
52
- # Ensure the directory exists
53
- db_path.parent.mkdir(parents=True, exist_ok=True)
54
- _engine = create_engine(f"sqlite:///{db_path}")
55
- else:
56
- _engine = create_engine("sqlite://")
57
-
58
- if _engine is None:
59
- raise ValueError("Must provide either db_url, db_file or db_engine")
60
-
61
- # Database attributes
62
- self.table_name: str = table_name
63
- self.db_url: Optional[str] = db_url
64
- self.db_engine: Engine = _engine
65
- self.metadata: MetaData = MetaData()
66
- self.inspector = inspect(self.db_engine)
67
-
68
- # Table schema version
69
- self.schema_version: int = schema_version
70
- # Automatically upgrade schema if True
71
- self.auto_upgrade_schema: bool = auto_upgrade_schema
72
-
73
- # Database session
74
- self.Session: sessionmaker[Session] = sessionmaker(bind=self.db_engine)
75
- # Database table for storage
76
- self.table: Table = self.get_table()
77
-
78
- def get_table_v1(self) -> Table:
79
- """
80
- Define the table schema for version 1.
81
-
82
- Returns:
83
- Table: SQLAlchemy Table object representing the schema.
84
- """
85
- return Table(
86
- self.table_name,
87
- self.metadata,
88
- # Session UUID: Primary Key
89
- Column("session_id", String, primary_key=True),
90
- # ID of the agent that this session is associated with
91
- Column("agent_id", String),
92
- # ID of the user interacting with this agent
93
- Column("user_id", String),
94
- # Agent Memory
95
- Column("memory", sqlite.JSON),
96
- # Agent Data
97
- Column("agent_data", sqlite.JSON),
98
- # Session Data
99
- Column("session_data", sqlite.JSON),
100
- # Extra Data stored with this agent
101
- Column("extra_data", sqlite.JSON),
102
- # The Unix timestamp of when this session was created.
103
- Column("created_at", sqlite.INTEGER, default=lambda: int(time.time())),
104
- # The Unix timestamp of when this session was last updated.
105
- Column("updated_at", sqlite.INTEGER, onupdate=lambda: int(time.time())),
106
- extend_existing=True,
107
- sqlite_autoincrement=True,
108
- )
109
-
110
- def get_table(self) -> Table:
111
- """
112
- Get the table schema based on the schema version.
113
-
114
- Returns:
115
- Table: SQLAlchemy Table object for the current schema version.
116
-
117
- Raises:
118
- ValueError: If an unsupported schema version is specified.
119
- """
120
- if self.schema_version == 1:
121
- return self.get_table_v1()
122
- else:
123
- raise ValueError(f"Unsupported schema version: {self.schema_version}")
124
-
125
- def table_exists(self) -> bool:
126
- """
127
- Check if the table exists in the database.
128
-
129
- Returns:
130
- bool: True if the table exists, False otherwise.
131
- """
132
- logger.debug(f"Checking if table exists: {self.table.name}")
133
- try:
134
- return self.inspector.has_table(self.table.name)
135
- except Exception as e:
136
- logger.error(f"Error checking if table exists: {e}")
137
- return False
138
-
139
- def create(self) -> None:
140
- """
141
- Create the table if it doesn't exist.
142
- """
143
- if not self.table_exists():
144
- logger.debug(f"Creating table: {self.table.name}")
145
- self.table.create(self.db_engine, checkfirst=True)
146
-
147
- def read(self, session_id: str, user_id: Optional[str] = None) -> Optional[AgentSession]:
148
- """
149
- Read an AgentSession from the database.
150
-
151
- Args:
152
- session_id (str): ID of the session to read.
153
- user_id (Optional[str]): User ID to filter by. Defaults to None.
154
-
155
- Returns:
156
- Optional[AgentSession]: AgentSession object if found, None otherwise.
157
- """
158
- try:
159
- with self.Session() as sess:
160
- stmt = select(self.table).where(self.table.c.session_id == session_id)
161
- if user_id:
162
- stmt = stmt.where(self.table.c.user_id == user_id)
163
- result = sess.execute(stmt).fetchone()
164
- return AgentSession.from_dict(result._mapping) if result is not None else None # type: ignore
165
- except Exception as e:
166
- logger.debug(f"Exception reading from table: {e}")
167
- logger.debug(f"Table does not exist: {self.table.name}")
168
- logger.debug("Creating table for future transactions")
169
- self.create()
170
- return None
171
-
172
- def get_all_session_ids(self, user_id: Optional[str] = None, agent_id: Optional[str] = None) -> List[str]:
173
- """
174
- Get all session IDs, optionally filtered by user_id and/or agent_id.
175
-
176
- Args:
177
- user_id (Optional[str]): The ID of the user to filter by.
178
- agent_id (Optional[str]): The ID of the agent to filter by.
179
-
180
- Returns:
181
- List[str]: List of session IDs matching the criteria.
182
- """
183
- try:
184
- with self.Session() as sess, sess.begin():
185
- # get all session_ids
186
- stmt = select(self.table.c.session_id)
187
- if user_id is not None:
188
- stmt = stmt.where(self.table.c.user_id == user_id)
189
- if agent_id is not None:
190
- stmt = stmt.where(self.table.c.agent_id == agent_id)
191
- # order by created_at desc
192
- stmt = stmt.order_by(self.table.c.created_at.desc())
193
- # execute query
194
- rows = sess.execute(stmt).fetchall()
195
- return [row[0] for row in rows] if rows is not None else []
196
- except Exception as e:
197
- logger.debug(f"Exception reading from table: {e}")
198
- logger.debug(f"Table does not exist: {self.table.name}")
199
- logger.debug("Creating table for future transactions")
200
- self.create()
201
- return []
202
-
203
- def get_all_sessions(self, user_id: Optional[str] = None, agent_id: Optional[str] = None) -> List[AgentSession]:
204
- """
205
- Get all sessions, optionally filtered by user_id and/or agent_id.
206
-
207
- Args:
208
- user_id (Optional[str]): The ID of the user to filter by.
209
- agent_id (Optional[str]): The ID of the agent to filter by.
210
-
211
- Returns:
212
- List[AgentSession]: List of AgentSession objects matching the criteria.
213
- """
214
- try:
215
- with self.Session() as sess, sess.begin():
216
- # get all sessions
217
- stmt = select(self.table)
218
- if user_id is not None:
219
- stmt = stmt.where(self.table.c.user_id == user_id)
220
- if agent_id is not None:
221
- stmt = stmt.where(self.table.c.agent_id == agent_id)
222
- # order by created_at desc
223
- stmt = stmt.order_by(self.table.c.created_at.desc())
224
- # execute query
225
- rows = sess.execute(stmt).fetchall()
226
- return [AgentSession.from_dict(row._mapping) for row in rows] if rows is not None else [] # type: ignore
227
- except Exception as e:
228
- logger.debug(f"Exception reading from table: {e}")
229
- logger.debug(f"Table does not exist: {self.table.name}")
230
- logger.debug("Creating table for future transactions")
231
- self.create()
232
- return []
233
-
234
- def upsert(self, session: AgentSession, create_and_retry: bool = True) -> Optional[AgentSession]:
235
- """
236
- Insert or update an AgentSession in the database.
237
-
238
- Args:
239
- session (AgentSession): The session data to upsert.
240
- create_and_retry (bool): Retry upsert if table does not exist.
241
-
242
- Returns:
243
- Optional[AgentSession]: The upserted AgentSession, or None if operation failed.
244
- """
245
- try:
246
- with self.Session() as sess, sess.begin():
247
- # Create an insert statement
248
- stmt = sqlite.insert(self.table).values(
249
- session_id=session.session_id,
250
- agent_id=session.agent_id,
251
- user_id=session.user_id,
252
- memory=session.memory,
253
- agent_data=session.agent_data,
254
- session_data=session.session_data,
255
- extra_data=session.extra_data,
256
- )
257
-
258
- # Define the upsert if the session_id already exists
259
- # See: https://docs.sqlalchemy.org/en/20/dialects/sqlite.html#insert-on-conflict-upsert
260
- stmt = stmt.on_conflict_do_update(
261
- index_elements=["session_id"],
262
- set_=dict(
263
- agent_id=session.agent_id,
264
- user_id=session.user_id,
265
- memory=session.memory,
266
- agent_data=session.agent_data,
267
- session_data=session.session_data,
268
- extra_data=session.extra_data,
269
- updated_at=int(time.time()),
270
- ), # The updated value for each column
271
- )
272
-
273
- sess.execute(stmt)
274
- except Exception as e:
275
- logger.debug(f"Exception upserting into table: {e}")
276
- if create_and_retry and not self.table_exists():
277
- logger.debug(f"Table does not exist: {self.table.name}")
278
- logger.debug("Creating table and retrying upsert")
279
- self.create()
280
- return self.upsert(session, create_and_retry=False)
281
- return None
282
- return self.read(session_id=session.session_id)
283
-
284
- def delete_session(self, session_id: Optional[str] = None):
285
- """
286
- Delete a workflow session from the database.
287
-
288
- Args:
289
- session_id (Optional[str]): The ID of the session to delete.
290
-
291
- Raises:
292
- ValueError: If session_id is not provided.
293
- """
294
- if session_id is None:
295
- logger.warning("No session_id provided for deletion.")
296
- return
297
-
298
- try:
299
- with self.Session() as sess, sess.begin():
300
- # Delete the session with the given session_id
301
- delete_stmt = self.table.delete().where(self.table.c.session_id == session_id)
302
- result = sess.execute(delete_stmt)
303
- if result.rowcount == 0:
304
- logger.debug(f"No session found with session_id: {session_id}")
305
- else:
306
- logger.debug(f"Successfully deleted session with session_id: {session_id}")
307
- except Exception as e:
308
- logger.error(f"Error deleting session: {e}")
309
-
310
- def drop(self) -> None:
311
- """
312
- Drop the table from the database if it exists.
313
- """
314
- if self.table_exists():
315
- logger.debug(f"Deleting table: {self.table_name}")
316
- self.table.drop(self.db_engine)
317
-
318
- def upgrade_schema(self) -> None:
319
- """
320
- Upgrade the schema of the workflow storage table.
321
- This method is currently a placeholder and does not perform any actions.
322
- """
323
- pass
324
-
325
- def __deepcopy__(self, memo):
326
- """
327
- Create a deep copy of the SqliteAgentStorage instance, handling unpickleable attributes.
328
-
329
- Args:
330
- memo (dict): A dictionary of objects already copied during the current copying pass.
331
-
332
- Returns:
333
- SqliteAgentStorage: A deep-copied instance of SqliteAgentStorage.
334
- """
335
- from copy import deepcopy
336
-
337
- # Create a new instance without calling __init__
338
- cls = self.__class__
339
- copied_obj = cls.__new__(cls)
340
- memo[id(self)] = copied_obj
341
-
342
- # Deep copy attributes
343
- for k, v in self.__dict__.items():
344
- if k in {"metadata", "table", "inspector"}:
345
- continue
346
- # Reuse db_engine and Session without copying
347
- elif k in {"db_engine", "Session"}:
348
- setattr(copied_obj, k, v)
349
- else:
350
- setattr(copied_obj, k, deepcopy(v, memo))
351
-
352
- # Recreate metadata and table for the copied instance
353
- copied_obj.metadata = MetaData()
354
- copied_obj.inspector = inspect(copied_obj.db_engine)
355
- copied_obj.table = copied_obj.get_table()
356
-
357
- return copied_obj