agno 1.8.1__py3-none-any.whl → 2.0.0__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 (590) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +3143 -4170
  4. agno/api/agent.py +11 -67
  5. agno/api/api.py +5 -46
  6. agno/api/evals.py +8 -19
  7. agno/api/os.py +17 -0
  8. agno/api/routes.py +6 -41
  9. agno/api/schemas/__init__.py +9 -0
  10. agno/api/schemas/agent.py +5 -21
  11. agno/api/schemas/evals.py +7 -16
  12. agno/api/schemas/os.py +14 -0
  13. agno/api/schemas/team.py +5 -21
  14. agno/api/schemas/utils.py +21 -0
  15. agno/api/schemas/workflows.py +11 -7
  16. agno/api/settings.py +53 -0
  17. agno/api/team.py +11 -66
  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/db/__init__.py +24 -0
  25. agno/db/base.py +245 -0
  26. agno/db/dynamo/__init__.py +3 -0
  27. agno/db/dynamo/dynamo.py +1743 -0
  28. agno/db/dynamo/schemas.py +278 -0
  29. agno/db/dynamo/utils.py +684 -0
  30. agno/db/firestore/__init__.py +3 -0
  31. agno/db/firestore/firestore.py +1432 -0
  32. agno/db/firestore/schemas.py +130 -0
  33. agno/db/firestore/utils.py +278 -0
  34. agno/db/gcs_json/__init__.py +3 -0
  35. agno/db/gcs_json/gcs_json_db.py +1001 -0
  36. agno/db/gcs_json/utils.py +194 -0
  37. agno/db/in_memory/__init__.py +3 -0
  38. agno/db/in_memory/in_memory_db.py +882 -0
  39. agno/db/in_memory/utils.py +172 -0
  40. agno/db/json/__init__.py +3 -0
  41. agno/db/json/json_db.py +1045 -0
  42. agno/db/json/utils.py +196 -0
  43. agno/db/migrations/v1_to_v2.py +162 -0
  44. agno/db/mongo/__init__.py +3 -0
  45. agno/db/mongo/mongo.py +1416 -0
  46. agno/db/mongo/schemas.py +77 -0
  47. agno/db/mongo/utils.py +204 -0
  48. agno/db/mysql/__init__.py +3 -0
  49. agno/db/mysql/mysql.py +1719 -0
  50. agno/db/mysql/schemas.py +124 -0
  51. agno/db/mysql/utils.py +297 -0
  52. agno/db/postgres/__init__.py +3 -0
  53. agno/db/postgres/postgres.py +1710 -0
  54. agno/db/postgres/schemas.py +124 -0
  55. agno/db/postgres/utils.py +280 -0
  56. agno/db/redis/__init__.py +3 -0
  57. agno/db/redis/redis.py +1367 -0
  58. agno/db/redis/schemas.py +109 -0
  59. agno/db/redis/utils.py +288 -0
  60. agno/db/schemas/__init__.py +3 -0
  61. agno/db/schemas/evals.py +33 -0
  62. agno/db/schemas/knowledge.py +40 -0
  63. agno/db/schemas/memory.py +46 -0
  64. agno/db/singlestore/__init__.py +3 -0
  65. agno/db/singlestore/schemas.py +116 -0
  66. agno/db/singlestore/singlestore.py +1712 -0
  67. agno/db/singlestore/utils.py +326 -0
  68. agno/db/sqlite/__init__.py +3 -0
  69. agno/db/sqlite/schemas.py +119 -0
  70. agno/db/sqlite/sqlite.py +1676 -0
  71. agno/db/sqlite/utils.py +268 -0
  72. agno/db/utils.py +88 -0
  73. agno/eval/__init__.py +14 -0
  74. agno/eval/accuracy.py +154 -48
  75. agno/eval/performance.py +88 -23
  76. agno/eval/reliability.py +73 -20
  77. agno/eval/utils.py +23 -13
  78. agno/integrations/discord/__init__.py +3 -0
  79. agno/{app → integrations}/discord/client.py +15 -11
  80. agno/knowledge/__init__.py +2 -2
  81. agno/{document → knowledge}/chunking/agentic.py +2 -2
  82. agno/{document → knowledge}/chunking/document.py +2 -2
  83. agno/{document → knowledge}/chunking/fixed.py +3 -3
  84. agno/{document → knowledge}/chunking/markdown.py +2 -2
  85. agno/{document → knowledge}/chunking/recursive.py +2 -2
  86. agno/{document → knowledge}/chunking/row.py +2 -2
  87. agno/knowledge/chunking/semantic.py +59 -0
  88. agno/knowledge/chunking/strategy.py +121 -0
  89. agno/knowledge/content.py +74 -0
  90. agno/knowledge/document/__init__.py +5 -0
  91. agno/{document → knowledge/document}/base.py +12 -2
  92. agno/knowledge/embedder/__init__.py +5 -0
  93. agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
  94. agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
  95. agno/{embedder → knowledge/embedder}/base.py +6 -0
  96. agno/{embedder → knowledge/embedder}/cohere.py +72 -1
  97. agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
  98. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  99. agno/{embedder → knowledge/embedder}/google.py +74 -1
  100. agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
  101. agno/{embedder → knowledge/embedder}/jina.py +48 -2
  102. agno/knowledge/embedder/langdb.py +22 -0
  103. agno/knowledge/embedder/mistral.py +139 -0
  104. agno/{embedder → knowledge/embedder}/nebius.py +1 -1
  105. agno/{embedder → knowledge/embedder}/ollama.py +54 -3
  106. agno/knowledge/embedder/openai.py +223 -0
  107. agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
  108. agno/{embedder → knowledge/embedder}/together.py +1 -1
  109. agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
  110. agno/knowledge/knowledge.py +1551 -0
  111. agno/knowledge/reader/__init__.py +7 -0
  112. agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
  113. agno/knowledge/reader/base.py +88 -0
  114. agno/{document → knowledge}/reader/csv_reader.py +47 -65
  115. agno/knowledge/reader/docx_reader.py +83 -0
  116. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  117. agno/{document → knowledge}/reader/json_reader.py +30 -9
  118. agno/{document → knowledge}/reader/markdown_reader.py +58 -9
  119. agno/{document → knowledge}/reader/pdf_reader.py +71 -126
  120. agno/knowledge/reader/reader_factory.py +268 -0
  121. agno/knowledge/reader/s3_reader.py +101 -0
  122. agno/{document → knowledge}/reader/text_reader.py +31 -10
  123. agno/knowledge/reader/url_reader.py +128 -0
  124. agno/knowledge/reader/web_search_reader.py +366 -0
  125. agno/{document → knowledge}/reader/website_reader.py +37 -10
  126. agno/knowledge/reader/wikipedia_reader.py +59 -0
  127. agno/knowledge/reader/youtube_reader.py +78 -0
  128. agno/knowledge/remote_content/remote_content.py +88 -0
  129. agno/{reranker → knowledge/reranker}/base.py +1 -1
  130. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  131. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  132. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  133. agno/knowledge/types.py +30 -0
  134. agno/knowledge/utils.py +169 -0
  135. agno/media.py +269 -268
  136. agno/memory/__init__.py +2 -10
  137. agno/memory/manager.py +1003 -148
  138. agno/models/aimlapi/__init__.py +2 -2
  139. agno/models/aimlapi/aimlapi.py +6 -6
  140. agno/models/anthropic/claude.py +131 -131
  141. agno/models/aws/bedrock.py +110 -182
  142. agno/models/aws/claude.py +64 -18
  143. agno/models/azure/ai_foundry.py +73 -23
  144. agno/models/base.py +346 -290
  145. agno/models/cerebras/cerebras.py +84 -27
  146. agno/models/cohere/chat.py +106 -98
  147. agno/models/google/gemini.py +105 -46
  148. agno/models/groq/groq.py +97 -35
  149. agno/models/huggingface/huggingface.py +92 -27
  150. agno/models/ibm/watsonx.py +72 -13
  151. agno/models/litellm/chat.py +85 -13
  152. agno/models/message.py +46 -151
  153. agno/models/meta/llama.py +85 -49
  154. agno/models/metrics.py +120 -0
  155. agno/models/mistral/mistral.py +90 -21
  156. agno/models/ollama/__init__.py +0 -2
  157. agno/models/ollama/chat.py +85 -47
  158. agno/models/openai/chat.py +154 -37
  159. agno/models/openai/responses.py +178 -105
  160. agno/models/perplexity/perplexity.py +26 -2
  161. agno/models/portkey/portkey.py +0 -7
  162. agno/models/response.py +15 -9
  163. agno/models/utils.py +20 -0
  164. agno/models/vercel/__init__.py +2 -2
  165. agno/models/vercel/v0.py +1 -1
  166. agno/models/vllm/__init__.py +2 -2
  167. agno/models/vllm/vllm.py +3 -3
  168. agno/models/xai/xai.py +10 -10
  169. agno/os/__init__.py +3 -0
  170. agno/os/app.py +497 -0
  171. agno/os/auth.py +47 -0
  172. agno/os/config.py +103 -0
  173. agno/os/interfaces/agui/__init__.py +3 -0
  174. agno/os/interfaces/agui/agui.py +31 -0
  175. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  176. agno/{app → os/interfaces}/agui/utils.py +77 -33
  177. agno/os/interfaces/base.py +21 -0
  178. agno/os/interfaces/slack/__init__.py +3 -0
  179. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  180. agno/os/interfaces/slack/slack.py +32 -0
  181. agno/os/interfaces/whatsapp/__init__.py +3 -0
  182. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  183. agno/os/interfaces/whatsapp/whatsapp.py +29 -0
  184. agno/os/mcp.py +235 -0
  185. agno/os/router.py +1400 -0
  186. agno/os/routers/__init__.py +3 -0
  187. agno/os/routers/evals/__init__.py +3 -0
  188. agno/os/routers/evals/evals.py +393 -0
  189. agno/os/routers/evals/schemas.py +142 -0
  190. agno/os/routers/evals/utils.py +161 -0
  191. agno/os/routers/knowledge/__init__.py +3 -0
  192. agno/os/routers/knowledge/knowledge.py +850 -0
  193. agno/os/routers/knowledge/schemas.py +118 -0
  194. agno/os/routers/memory/__init__.py +3 -0
  195. agno/os/routers/memory/memory.py +410 -0
  196. agno/os/routers/memory/schemas.py +58 -0
  197. agno/os/routers/metrics/__init__.py +3 -0
  198. agno/os/routers/metrics/metrics.py +178 -0
  199. agno/os/routers/metrics/schemas.py +47 -0
  200. agno/os/routers/session/__init__.py +3 -0
  201. agno/os/routers/session/session.py +536 -0
  202. agno/os/schema.py +945 -0
  203. agno/{app/playground → os}/settings.py +7 -15
  204. agno/os/utils.py +270 -0
  205. agno/reasoning/azure_ai_foundry.py +4 -4
  206. agno/reasoning/deepseek.py +4 -4
  207. agno/reasoning/default.py +6 -11
  208. agno/reasoning/groq.py +4 -4
  209. agno/reasoning/helpers.py +4 -6
  210. agno/reasoning/ollama.py +4 -4
  211. agno/reasoning/openai.py +4 -4
  212. agno/run/agent.py +633 -0
  213. agno/run/base.py +53 -77
  214. agno/run/cancel.py +81 -0
  215. agno/run/team.py +243 -96
  216. agno/run/workflow.py +550 -12
  217. agno/session/__init__.py +10 -0
  218. agno/session/agent.py +244 -0
  219. agno/session/summary.py +225 -0
  220. agno/session/team.py +262 -0
  221. agno/{storage/session/v2 → session}/workflow.py +47 -24
  222. agno/team/__init__.py +15 -16
  223. agno/team/team.py +3260 -4824
  224. agno/tools/agentql.py +14 -5
  225. agno/tools/airflow.py +9 -4
  226. agno/tools/api.py +7 -3
  227. agno/tools/apify.py +2 -46
  228. agno/tools/arxiv.py +8 -3
  229. agno/tools/aws_lambda.py +7 -5
  230. agno/tools/aws_ses.py +7 -1
  231. agno/tools/baidusearch.py +4 -1
  232. agno/tools/bitbucket.py +4 -4
  233. agno/tools/brandfetch.py +14 -11
  234. agno/tools/bravesearch.py +4 -1
  235. agno/tools/brightdata.py +43 -23
  236. agno/tools/browserbase.py +13 -4
  237. agno/tools/calcom.py +12 -10
  238. agno/tools/calculator.py +10 -27
  239. agno/tools/cartesia.py +20 -17
  240. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  241. agno/tools/confluence.py +8 -8
  242. agno/tools/crawl4ai.py +7 -1
  243. agno/tools/csv_toolkit.py +9 -8
  244. agno/tools/dalle.py +22 -12
  245. agno/tools/daytona.py +13 -16
  246. agno/tools/decorator.py +6 -3
  247. agno/tools/desi_vocal.py +17 -8
  248. agno/tools/discord.py +11 -8
  249. agno/tools/docker.py +30 -42
  250. agno/tools/duckdb.py +34 -53
  251. agno/tools/duckduckgo.py +8 -7
  252. agno/tools/e2b.py +62 -62
  253. agno/tools/eleven_labs.py +36 -29
  254. agno/tools/email.py +4 -1
  255. agno/tools/evm.py +7 -1
  256. agno/tools/exa.py +19 -14
  257. agno/tools/fal.py +30 -30
  258. agno/tools/file.py +9 -8
  259. agno/tools/financial_datasets.py +25 -44
  260. agno/tools/firecrawl.py +22 -22
  261. agno/tools/function.py +127 -18
  262. agno/tools/giphy.py +23 -11
  263. agno/tools/github.py +48 -126
  264. agno/tools/gmail.py +45 -61
  265. agno/tools/google_bigquery.py +7 -6
  266. agno/tools/google_maps.py +11 -26
  267. agno/tools/googlesearch.py +7 -2
  268. agno/tools/googlesheets.py +21 -17
  269. agno/tools/hackernews.py +9 -5
  270. agno/tools/jina.py +5 -4
  271. agno/tools/jira.py +18 -9
  272. agno/tools/knowledge.py +31 -32
  273. agno/tools/linear.py +19 -34
  274. agno/tools/linkup.py +5 -1
  275. agno/tools/local_file_system.py +8 -5
  276. agno/tools/lumalab.py +32 -20
  277. agno/tools/mcp.py +1 -2
  278. agno/tools/mem0.py +18 -12
  279. agno/tools/memori.py +14 -10
  280. agno/tools/mlx_transcribe.py +3 -2
  281. agno/tools/models/azure_openai.py +33 -15
  282. agno/tools/models/gemini.py +59 -32
  283. agno/tools/models/groq.py +30 -23
  284. agno/tools/models/nebius.py +28 -12
  285. agno/tools/models_labs.py +40 -16
  286. agno/tools/moviepy_video.py +7 -6
  287. agno/tools/neo4j.py +10 -8
  288. agno/tools/newspaper.py +7 -2
  289. agno/tools/newspaper4k.py +8 -3
  290. agno/tools/openai.py +58 -32
  291. agno/tools/openbb.py +12 -11
  292. agno/tools/opencv.py +63 -47
  293. agno/tools/openweather.py +14 -12
  294. agno/tools/pandas.py +11 -3
  295. agno/tools/postgres.py +4 -12
  296. agno/tools/pubmed.py +4 -1
  297. agno/tools/python.py +9 -22
  298. agno/tools/reasoning.py +35 -27
  299. agno/tools/reddit.py +11 -26
  300. agno/tools/replicate.py +55 -42
  301. agno/tools/resend.py +4 -1
  302. agno/tools/scrapegraph.py +15 -14
  303. agno/tools/searxng.py +10 -23
  304. agno/tools/serpapi.py +6 -3
  305. agno/tools/serper.py +13 -4
  306. agno/tools/shell.py +9 -2
  307. agno/tools/slack.py +12 -11
  308. agno/tools/sleep.py +3 -2
  309. agno/tools/spider.py +24 -4
  310. agno/tools/sql.py +7 -6
  311. agno/tools/tavily.py +6 -4
  312. agno/tools/telegram.py +12 -4
  313. agno/tools/todoist.py +11 -31
  314. agno/tools/toolkit.py +1 -1
  315. agno/tools/trafilatura.py +22 -6
  316. agno/tools/trello.py +9 -22
  317. agno/tools/twilio.py +10 -3
  318. agno/tools/user_control_flow.py +6 -1
  319. agno/tools/valyu.py +34 -5
  320. agno/tools/visualization.py +19 -28
  321. agno/tools/webbrowser.py +4 -3
  322. agno/tools/webex.py +11 -7
  323. agno/tools/website.py +15 -46
  324. agno/tools/webtools.py +12 -4
  325. agno/tools/whatsapp.py +5 -9
  326. agno/tools/wikipedia.py +20 -13
  327. agno/tools/x.py +14 -13
  328. agno/tools/yfinance.py +13 -40
  329. agno/tools/youtube.py +26 -20
  330. agno/tools/zendesk.py +7 -2
  331. agno/tools/zep.py +10 -7
  332. agno/tools/zoom.py +10 -9
  333. agno/utils/common.py +1 -19
  334. agno/utils/events.py +100 -123
  335. agno/utils/gemini.py +32 -2
  336. agno/utils/knowledge.py +29 -0
  337. agno/utils/log.py +54 -4
  338. agno/utils/mcp.py +68 -10
  339. agno/utils/media.py +39 -0
  340. agno/utils/message.py +12 -1
  341. agno/utils/models/aws_claude.py +1 -1
  342. agno/utils/models/claude.py +47 -4
  343. agno/utils/models/cohere.py +1 -1
  344. agno/utils/models/mistral.py +8 -7
  345. agno/utils/models/schema_utils.py +3 -3
  346. agno/utils/models/watsonx.py +1 -1
  347. agno/utils/openai.py +1 -1
  348. agno/utils/pprint.py +33 -32
  349. agno/utils/print_response/agent.py +779 -0
  350. agno/utils/print_response/team.py +1669 -0
  351. agno/utils/print_response/workflow.py +1451 -0
  352. agno/utils/prompts.py +14 -14
  353. agno/utils/reasoning.py +87 -0
  354. agno/utils/response.py +42 -42
  355. agno/utils/streamlit.py +481 -0
  356. agno/utils/string.py +8 -22
  357. agno/utils/team.py +50 -0
  358. agno/utils/timer.py +2 -2
  359. agno/vectordb/base.py +33 -21
  360. agno/vectordb/cassandra/cassandra.py +287 -23
  361. agno/vectordb/chroma/chromadb.py +482 -59
  362. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  363. agno/vectordb/couchbase/couchbase.py +309 -29
  364. agno/vectordb/lancedb/lance_db.py +360 -21
  365. agno/vectordb/langchaindb/__init__.py +5 -0
  366. agno/vectordb/langchaindb/langchaindb.py +145 -0
  367. agno/vectordb/lightrag/__init__.py +5 -0
  368. agno/vectordb/lightrag/lightrag.py +374 -0
  369. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  370. agno/vectordb/milvus/milvus.py +242 -32
  371. agno/vectordb/mongodb/mongodb.py +200 -24
  372. agno/vectordb/pgvector/pgvector.py +319 -37
  373. agno/vectordb/pineconedb/pineconedb.py +221 -27
  374. agno/vectordb/qdrant/qdrant.py +334 -14
  375. agno/vectordb/singlestore/singlestore.py +286 -29
  376. agno/vectordb/surrealdb/surrealdb.py +187 -7
  377. agno/vectordb/upstashdb/upstashdb.py +342 -26
  378. agno/vectordb/weaviate/weaviate.py +227 -165
  379. agno/workflow/__init__.py +17 -13
  380. agno/workflow/{v2/condition.py → condition.py} +135 -32
  381. agno/workflow/{v2/loop.py → loop.py} +115 -28
  382. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  383. agno/workflow/{v2/router.py → router.py} +133 -32
  384. agno/workflow/{v2/step.py → step.py} +207 -49
  385. agno/workflow/{v2/steps.py → steps.py} +147 -66
  386. agno/workflow/types.py +482 -0
  387. agno/workflow/workflow.py +2410 -696
  388. agno-2.0.0.dist-info/METADATA +494 -0
  389. agno-2.0.0.dist-info/RECORD +515 -0
  390. agno-2.0.0.dist-info/licenses/LICENSE +201 -0
  391. agno/agent/metrics.py +0 -107
  392. agno/api/app.py +0 -35
  393. agno/api/playground.py +0 -92
  394. agno/api/schemas/app.py +0 -12
  395. agno/api/schemas/playground.py +0 -22
  396. agno/api/schemas/user.py +0 -35
  397. agno/api/schemas/workspace.py +0 -46
  398. agno/api/user.py +0 -160
  399. agno/api/workflows.py +0 -33
  400. agno/api/workspace.py +0 -175
  401. agno/app/agui/__init__.py +0 -3
  402. agno/app/agui/app.py +0 -17
  403. agno/app/agui/sync_router.py +0 -120
  404. agno/app/base.py +0 -186
  405. agno/app/discord/__init__.py +0 -3
  406. agno/app/fastapi/__init__.py +0 -3
  407. agno/app/fastapi/app.py +0 -107
  408. agno/app/fastapi/async_router.py +0 -457
  409. agno/app/fastapi/sync_router.py +0 -448
  410. agno/app/playground/app.py +0 -228
  411. agno/app/playground/async_router.py +0 -1050
  412. agno/app/playground/deploy.py +0 -249
  413. agno/app/playground/operator.py +0 -183
  414. agno/app/playground/schemas.py +0 -220
  415. agno/app/playground/serve.py +0 -55
  416. agno/app/playground/sync_router.py +0 -1042
  417. agno/app/playground/utils.py +0 -46
  418. agno/app/settings.py +0 -15
  419. agno/app/slack/__init__.py +0 -3
  420. agno/app/slack/app.py +0 -19
  421. agno/app/slack/sync_router.py +0 -92
  422. agno/app/utils.py +0 -54
  423. agno/app/whatsapp/__init__.py +0 -3
  424. agno/app/whatsapp/app.py +0 -15
  425. agno/app/whatsapp/sync_router.py +0 -197
  426. agno/cli/auth_server.py +0 -249
  427. agno/cli/config.py +0 -274
  428. agno/cli/console.py +0 -88
  429. agno/cli/credentials.py +0 -23
  430. agno/cli/entrypoint.py +0 -571
  431. agno/cli/operator.py +0 -357
  432. agno/cli/settings.py +0 -96
  433. agno/cli/ws/ws_cli.py +0 -817
  434. agno/constants.py +0 -13
  435. agno/document/__init__.py +0 -5
  436. agno/document/chunking/semantic.py +0 -45
  437. agno/document/chunking/strategy.py +0 -31
  438. agno/document/reader/__init__.py +0 -5
  439. agno/document/reader/base.py +0 -47
  440. agno/document/reader/docx_reader.py +0 -60
  441. agno/document/reader/gcs/pdf_reader.py +0 -44
  442. agno/document/reader/s3/pdf_reader.py +0 -59
  443. agno/document/reader/s3/text_reader.py +0 -63
  444. agno/document/reader/url_reader.py +0 -59
  445. agno/document/reader/youtube_reader.py +0 -58
  446. agno/embedder/__init__.py +0 -5
  447. agno/embedder/langdb.py +0 -80
  448. agno/embedder/mistral.py +0 -82
  449. agno/embedder/openai.py +0 -78
  450. agno/file/__init__.py +0 -5
  451. agno/file/file.py +0 -16
  452. agno/file/local/csv.py +0 -32
  453. agno/file/local/txt.py +0 -19
  454. agno/infra/app.py +0 -240
  455. agno/infra/base.py +0 -144
  456. agno/infra/context.py +0 -20
  457. agno/infra/db_app.py +0 -52
  458. agno/infra/resource.py +0 -205
  459. agno/infra/resources.py +0 -55
  460. agno/knowledge/agent.py +0 -702
  461. agno/knowledge/arxiv.py +0 -33
  462. agno/knowledge/combined.py +0 -36
  463. agno/knowledge/csv.py +0 -144
  464. agno/knowledge/csv_url.py +0 -124
  465. agno/knowledge/document.py +0 -223
  466. agno/knowledge/docx.py +0 -137
  467. agno/knowledge/firecrawl.py +0 -34
  468. agno/knowledge/gcs/__init__.py +0 -0
  469. agno/knowledge/gcs/base.py +0 -39
  470. agno/knowledge/gcs/pdf.py +0 -125
  471. agno/knowledge/json.py +0 -137
  472. agno/knowledge/langchain.py +0 -71
  473. agno/knowledge/light_rag.py +0 -273
  474. agno/knowledge/llamaindex.py +0 -66
  475. agno/knowledge/markdown.py +0 -154
  476. agno/knowledge/pdf.py +0 -164
  477. agno/knowledge/pdf_bytes.py +0 -42
  478. agno/knowledge/pdf_url.py +0 -148
  479. agno/knowledge/s3/__init__.py +0 -0
  480. agno/knowledge/s3/base.py +0 -64
  481. agno/knowledge/s3/pdf.py +0 -33
  482. agno/knowledge/s3/text.py +0 -34
  483. agno/knowledge/text.py +0 -141
  484. agno/knowledge/url.py +0 -46
  485. agno/knowledge/website.py +0 -179
  486. agno/knowledge/wikipedia.py +0 -32
  487. agno/knowledge/youtube.py +0 -35
  488. agno/memory/agent.py +0 -423
  489. agno/memory/classifier.py +0 -104
  490. agno/memory/db/__init__.py +0 -5
  491. agno/memory/db/base.py +0 -42
  492. agno/memory/db/mongodb.py +0 -189
  493. agno/memory/db/postgres.py +0 -203
  494. agno/memory/db/sqlite.py +0 -193
  495. agno/memory/memory.py +0 -22
  496. agno/memory/row.py +0 -36
  497. agno/memory/summarizer.py +0 -201
  498. agno/memory/summary.py +0 -19
  499. agno/memory/team.py +0 -415
  500. agno/memory/v2/__init__.py +0 -2
  501. agno/memory/v2/db/__init__.py +0 -1
  502. agno/memory/v2/db/base.py +0 -42
  503. agno/memory/v2/db/firestore.py +0 -339
  504. agno/memory/v2/db/mongodb.py +0 -196
  505. agno/memory/v2/db/postgres.py +0 -214
  506. agno/memory/v2/db/redis.py +0 -187
  507. agno/memory/v2/db/schema.py +0 -54
  508. agno/memory/v2/db/sqlite.py +0 -209
  509. agno/memory/v2/manager.py +0 -437
  510. agno/memory/v2/memory.py +0 -1097
  511. agno/memory/v2/schema.py +0 -55
  512. agno/memory/v2/summarizer.py +0 -215
  513. agno/memory/workflow.py +0 -38
  514. agno/models/ollama/tools.py +0 -430
  515. agno/models/qwen/__init__.py +0 -5
  516. agno/playground/__init__.py +0 -10
  517. agno/playground/deploy.py +0 -3
  518. agno/playground/playground.py +0 -3
  519. agno/playground/serve.py +0 -3
  520. agno/playground/settings.py +0 -3
  521. agno/reranker/__init__.py +0 -0
  522. agno/run/response.py +0 -467
  523. agno/run/v2/__init__.py +0 -0
  524. agno/run/v2/workflow.py +0 -567
  525. agno/storage/__init__.py +0 -0
  526. agno/storage/agent/__init__.py +0 -0
  527. agno/storage/agent/dynamodb.py +0 -1
  528. agno/storage/agent/json.py +0 -1
  529. agno/storage/agent/mongodb.py +0 -1
  530. agno/storage/agent/postgres.py +0 -1
  531. agno/storage/agent/singlestore.py +0 -1
  532. agno/storage/agent/sqlite.py +0 -1
  533. agno/storage/agent/yaml.py +0 -1
  534. agno/storage/base.py +0 -60
  535. agno/storage/dynamodb.py +0 -673
  536. agno/storage/firestore.py +0 -297
  537. agno/storage/gcs_json.py +0 -261
  538. agno/storage/in_memory.py +0 -234
  539. agno/storage/json.py +0 -237
  540. agno/storage/mongodb.py +0 -328
  541. agno/storage/mysql.py +0 -685
  542. agno/storage/postgres.py +0 -682
  543. agno/storage/redis.py +0 -336
  544. agno/storage/session/__init__.py +0 -16
  545. agno/storage/session/agent.py +0 -64
  546. agno/storage/session/team.py +0 -63
  547. agno/storage/session/v2/__init__.py +0 -5
  548. agno/storage/session/workflow.py +0 -61
  549. agno/storage/singlestore.py +0 -606
  550. agno/storage/sqlite.py +0 -646
  551. agno/storage/workflow/__init__.py +0 -0
  552. agno/storage/workflow/mongodb.py +0 -1
  553. agno/storage/workflow/postgres.py +0 -1
  554. agno/storage/workflow/sqlite.py +0 -1
  555. agno/storage/yaml.py +0 -241
  556. agno/tools/thinking.py +0 -73
  557. agno/utils/defaults.py +0 -57
  558. agno/utils/filesystem.py +0 -39
  559. agno/utils/git.py +0 -52
  560. agno/utils/json_io.py +0 -30
  561. agno/utils/load_env.py +0 -19
  562. agno/utils/py_io.py +0 -19
  563. agno/utils/pyproject.py +0 -18
  564. agno/utils/resource_filter.py +0 -31
  565. agno/workflow/v2/__init__.py +0 -21
  566. agno/workflow/v2/types.py +0 -357
  567. agno/workflow/v2/workflow.py +0 -3312
  568. agno/workspace/__init__.py +0 -0
  569. agno/workspace/config.py +0 -325
  570. agno/workspace/enums.py +0 -6
  571. agno/workspace/helpers.py +0 -52
  572. agno/workspace/operator.py +0 -757
  573. agno/workspace/settings.py +0 -158
  574. agno-1.8.1.dist-info/METADATA +0 -982
  575. agno-1.8.1.dist-info/RECORD +0 -566
  576. agno-1.8.1.dist-info/entry_points.txt +0 -3
  577. agno-1.8.1.dist-info/licenses/LICENSE +0 -375
  578. /agno/{app → db/migrations}/__init__.py +0 -0
  579. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  580. /agno/{cli → integrations}/__init__.py +0 -0
  581. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  582. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  583. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  584. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  585. /agno/{app → os/interfaces}/slack/security.py +0 -0
  586. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  587. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  588. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  589. {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
  590. {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/top_level.txt +0 -0
agno/storage/sqlite.py DELETED
@@ -1,646 +0,0 @@
1
- import time
2
- from pathlib import Path
3
- from typing import List, Literal, Optional
4
-
5
- from agno.storage.base import Storage
6
- from agno.storage.session import Session
7
- from agno.storage.session.agent import AgentSession
8
- from agno.storage.session.team import TeamSession
9
- from agno.storage.session.v2.workflow import WorkflowSession as WorkflowSessionV2
10
- from agno.storage.session.workflow import WorkflowSession
11
- from agno.utils.log import log_debug, log_info, log_warning, logger
12
-
13
- try:
14
- from sqlalchemy.dialects import sqlite
15
- from sqlalchemy.engine import Engine, create_engine
16
- from sqlalchemy.inspection import inspect
17
- from sqlalchemy.orm import Session as SqlSession
18
- from sqlalchemy.orm import sessionmaker
19
- from sqlalchemy.schema import Column, MetaData, Table
20
- from sqlalchemy.sql import text
21
- from sqlalchemy.sql.expression import select
22
- from sqlalchemy.types import String
23
- except ImportError:
24
- raise ImportError("`sqlalchemy` not installed. Please install it using `pip install sqlalchemy`")
25
-
26
-
27
- class SqliteStorage(Storage):
28
- def __init__(
29
- self,
30
- table_name: str,
31
- db_url: Optional[str] = None,
32
- db_file: Optional[str] = None,
33
- db_engine: Optional[Engine] = None,
34
- schema_version: int = 1,
35
- auto_upgrade_schema: bool = False,
36
- mode: Optional[Literal["agent", "team", "workflow", "workflow_v2"]] = "agent",
37
- ):
38
- """
39
- This class provides agent storage using a sqlite database.
40
-
41
- The following order is used to determine the database connection:
42
- 1. Use the db_engine if provided
43
- 2. Use the db_url
44
- 3. Use the db_file
45
- 4. Create a new in-memory database
46
-
47
- Args:
48
- table_name: The name of the table to store Agent sessions.
49
- db_url: The database URL to connect to.
50
- db_file: The database file to connect to.
51
- db_engine: The SQLAlchemy database engine to use.
52
- """
53
- super().__init__(mode)
54
- _engine: Optional[Engine] = db_engine
55
- if _engine is None and db_url is not None:
56
- _engine = create_engine(db_url)
57
- elif _engine is None and db_file is not None:
58
- # Use the db_file to create the engine
59
- db_path = Path(db_file).resolve()
60
- # Ensure the directory exists
61
- db_path.parent.mkdir(parents=True, exist_ok=True)
62
- _engine = create_engine(f"sqlite:///{db_path}")
63
- else:
64
- _engine = create_engine("sqlite://")
65
-
66
- if _engine is None:
67
- raise ValueError("Must provide either db_url, db_file or db_engine")
68
-
69
- # Database attributes
70
- self.table_name: str = table_name
71
- self.db_url: Optional[str] = db_url
72
- self.db_engine: Engine = _engine
73
- self.metadata: MetaData = MetaData()
74
- self.inspector = inspect(self.db_engine)
75
-
76
- # Table schema version
77
- self.schema_version: int = schema_version
78
- # Automatically upgrade schema if True
79
- self.auto_upgrade_schema: bool = auto_upgrade_schema
80
- self._schema_up_to_date: bool = False
81
-
82
- # Database session
83
- self.SqlSession: sessionmaker[SqlSession] = sessionmaker(bind=self.db_engine)
84
- # Database table for storage
85
- self.table: Table = self.get_table()
86
-
87
- @property
88
- def mode(self) -> Optional[Literal["agent", "team", "workflow", "workflow_v2"]]:
89
- """Get the mode of the storage."""
90
- return super().mode
91
-
92
- @mode.setter
93
- def mode(self, value: Optional[Literal["agent", "team", "workflow", "workflow_v2"]]) -> None:
94
- """Set the mode and refresh the table if mode changes."""
95
- super(SqliteStorage, type(self)).mode.fset(self, value) # type: ignore
96
- if value is not None:
97
- self.table = self.get_table()
98
-
99
- def get_table_v1(self) -> Table:
100
- """
101
- Define the table schema for version 1.
102
-
103
- Returns:
104
- Table: SQLAlchemy Table object representing the schema.
105
- """
106
- common_columns = [
107
- Column("session_id", String, primary_key=True),
108
- Column("user_id", String, index=True),
109
- Column("memory", sqlite.JSON),
110
- Column("session_data", sqlite.JSON),
111
- Column("extra_data", sqlite.JSON),
112
- Column("created_at", sqlite.INTEGER, default=lambda: int(time.time())),
113
- Column("updated_at", sqlite.INTEGER, onupdate=lambda: int(time.time())),
114
- ]
115
-
116
- # Mode-specific columns
117
- specific_columns = []
118
- if self.mode == "agent":
119
- specific_columns = [
120
- Column("agent_id", String, index=True),
121
- Column("agent_data", sqlite.JSON),
122
- Column("team_session_id", String, index=True, nullable=True),
123
- ]
124
- elif self.mode == "team":
125
- specific_columns = [
126
- Column("team_id", String, index=True),
127
- Column("team_data", sqlite.JSON),
128
- Column("team_session_id", String, index=True, nullable=True),
129
- ]
130
- elif self.mode == "workflow":
131
- specific_columns = [
132
- Column("workflow_id", String, index=True),
133
- Column("workflow_data", sqlite.JSON),
134
- ]
135
- elif self.mode == "workflow_v2":
136
- specific_columns = [
137
- Column("workflow_id", String, index=True),
138
- Column("workflow_name", String, index=True),
139
- Column("workflow_data", sqlite.JSON),
140
- Column("runs", sqlite.JSON),
141
- ]
142
-
143
- # Create table with all columns
144
- table = Table(
145
- self.table_name,
146
- self.metadata,
147
- *common_columns,
148
- *specific_columns,
149
- extend_existing=True,
150
- sqlite_autoincrement=True,
151
- )
152
-
153
- return table
154
-
155
- def get_table(self) -> Table:
156
- """
157
- Get the table schema based on the schema version.
158
-
159
- Returns:
160
- Table: SQLAlchemy Table object for the current schema version.
161
-
162
- Raises:
163
- ValueError: If an unsupported schema version is specified.
164
- """
165
- if self.schema_version == 1:
166
- return self.get_table_v1()
167
- else:
168
- raise ValueError(f"Unsupported schema version: {self.schema_version}")
169
-
170
- def table_exists(self) -> bool:
171
- """
172
- Check if the table exists in the database.
173
-
174
- Returns:
175
- bool: True if the table exists, False otherwise.
176
- """
177
- try:
178
- # For SQLite, we need to check the sqlite_master table
179
- with self.SqlSession() as sess:
180
- result = sess.execute(
181
- text("SELECT name FROM sqlite_master WHERE type='table' AND name=:table_name"),
182
- {"table_name": self.table_name},
183
- ).scalar()
184
- return result is not None
185
- except Exception as e:
186
- logger.error(f"Error checking if table exists: {e}")
187
- return False
188
-
189
- def create(self) -> None:
190
- """
191
- Create the table if it doesn't exist.
192
- """
193
- self.table = self.get_table()
194
- if not self.table_exists():
195
- log_debug(f"Creating table: {self.table.name}")
196
- try:
197
- # First create the table without indexes
198
- table_without_indexes = Table(
199
- self.table_name,
200
- MetaData(),
201
- *[c.copy() for c in self.table.columns],
202
- )
203
- table_without_indexes.create(self.db_engine, checkfirst=True)
204
-
205
- # Then create each index individually with error handling
206
- for idx in self.table.indexes:
207
- try:
208
- idx_name = idx.name
209
- log_debug(f"Creating index: {idx_name}")
210
-
211
- # Check if index already exists using SQLite's schema table
212
- with self.SqlSession() as sess:
213
- exists_query = text("SELECT 1 FROM sqlite_master WHERE type='index' AND name=:index_name")
214
- exists = sess.execute(exists_query, {"index_name": idx_name}).scalar() is not None
215
-
216
- if not exists:
217
- idx.create(self.db_engine)
218
- else:
219
- log_debug(f"Index {idx_name} already exists, skipping creation")
220
-
221
- except Exception as e:
222
- # Log the error but continue with other indexes
223
- logger.warning(f"Error creating index {idx.name}: {e}")
224
-
225
- except Exception as e:
226
- logger.error(f"Error creating table: {e}")
227
- raise
228
-
229
- def read(self, session_id: str, user_id: Optional[str] = None) -> Optional[Session]:
230
- """
231
- Read a Session from the database.
232
-
233
- Args:
234
- session_id (str): ID of the session to read.
235
- user_id (Optional[str]): User ID to filter by. Defaults to None.
236
-
237
- Returns:
238
- Optional[Session]: Session object if found, None otherwise.
239
- """
240
- try:
241
- with self.SqlSession() as sess:
242
- stmt = select(self.table).where(self.table.c.session_id == session_id)
243
- if user_id:
244
- stmt = stmt.where(self.table.c.user_id == user_id)
245
- result = sess.execute(stmt).fetchone()
246
- if self.mode == "agent":
247
- return AgentSession.from_dict(result._mapping) if result is not None else None # type: ignore
248
- elif self.mode == "team":
249
- return TeamSession.from_dict(result._mapping) if result is not None else None # type: ignore
250
- elif self.mode == "workflow":
251
- return WorkflowSession.from_dict(result._mapping) if result is not None else None # type: ignore
252
- elif self.mode == "workflow_v2":
253
- return WorkflowSessionV2.from_dict(result._mapping) if result is not None else None # type: ignore
254
- except Exception as e:
255
- if "no such table" in str(e):
256
- log_debug(f"Table does not exist: {self.table.name}")
257
- self.create()
258
- else:
259
- log_debug(f"Exception reading from table: {e}")
260
- return None
261
-
262
- def get_all_session_ids(self, user_id: Optional[str] = None, entity_id: Optional[str] = None) -> List[str]:
263
- """
264
- Get all session IDs, optionally filtered by user_id and/or entity_id.
265
-
266
- Args:
267
- user_id (Optional[str]): The ID of the user to filter by.
268
- entity_id (Optional[str]): The ID of the agent / workflow to filter by.
269
-
270
- Returns:
271
- List[str]: List of session IDs matching the criteria.
272
- """
273
- try:
274
- with self.SqlSession() as sess, sess.begin():
275
- # get all session_ids
276
- stmt = select(self.table.c.session_id)
277
- if user_id is not None:
278
- stmt = stmt.where(self.table.c.user_id == user_id)
279
- if entity_id is not None:
280
- if self.mode == "agent":
281
- stmt = stmt.where(self.table.c.agent_id == entity_id)
282
- elif self.mode == "team":
283
- stmt = stmt.where(self.table.c.team_id == entity_id)
284
- elif self.mode == "workflow":
285
- stmt = stmt.where(self.table.c.workflow_id == entity_id)
286
- elif self.mode == "workflow_v2":
287
- stmt = stmt.where(self.table.c.workflow_id == entity_id)
288
- # order by created_at desc
289
- stmt = stmt.order_by(self.table.c.created_at.desc())
290
- # execute query
291
- rows = sess.execute(stmt).fetchall()
292
- return [row[0] for row in rows] if rows is not None else []
293
- except Exception as e:
294
- if "no such table" in str(e):
295
- log_debug(f"Table does not exist: {self.table.name}")
296
- self.create()
297
- else:
298
- log_debug(f"Exception reading from table: {e}")
299
- return []
300
-
301
- def get_all_sessions(self, user_id: Optional[str] = None, entity_id: Optional[str] = None) -> List[Session]:
302
- """
303
- Get all sessions, optionally filtered by user_id and/or entity_id.
304
-
305
- Args:
306
- user_id (Optional[str]): The ID of the user to filter by.
307
- entity_id (Optional[str]): The ID of the agent / workflow to filter by.
308
-
309
- Returns:
310
- List[Session]: List of Session objects matching the criteria.
311
- """
312
- try:
313
- with self.SqlSession() as sess, sess.begin():
314
- # get all sessions
315
- stmt = select(self.table)
316
- if user_id is not None:
317
- stmt = stmt.where(self.table.c.user_id == user_id)
318
- if entity_id is not None:
319
- if self.mode == "agent":
320
- stmt = stmt.where(self.table.c.agent_id == entity_id)
321
- elif self.mode == "team":
322
- stmt = stmt.where(self.table.c.team_id == entity_id)
323
- elif self.mode in ["workflow", "workflow_v2"]:
324
- stmt = stmt.where(self.table.c.workflow_id == entity_id)
325
- # order by created_at desc
326
- stmt = stmt.order_by(self.table.c.created_at.desc())
327
-
328
- rows = sess.execute(stmt).fetchall()
329
- if rows is not None:
330
- if self.mode == "agent":
331
- return [AgentSession.from_dict(row._mapping) for row in rows] # type: ignore
332
- elif self.mode == "team":
333
- return [TeamSession.from_dict(row._mapping) for row in rows] # type: ignore
334
- elif self.mode == "workflow":
335
- return [WorkflowSession.from_dict(row._mapping) for row in rows] # type: ignore
336
- elif self.mode == "workflow_v2":
337
- return [WorkflowSessionV2.from_dict(row._mapping) for row in rows] # type: ignore
338
- else:
339
- return []
340
- except Exception as e:
341
- if "no such table" in str(e):
342
- log_debug(f"Table does not exist: {self.table.name}")
343
- self.create()
344
- else:
345
- log_debug(f"Exception reading from table: {e}")
346
- return []
347
-
348
- def get_recent_sessions(
349
- self,
350
- user_id: Optional[str] = None,
351
- entity_id: Optional[str] = None,
352
- limit: Optional[int] = 2,
353
- ) -> List[Session]:
354
- """
355
- Get the last N sessions, ordered by created_at descending.
356
-
357
- Args:
358
- limit: Number of most recent sessions to return
359
- user_id: Filter by user ID
360
- entity_id: Filter by entity ID (agent_id, team_id, or workflow_id)
361
-
362
- Returns:
363
- List[Session]: List of most recent sessions
364
- """
365
- try:
366
- with self.SqlSession() as sess, sess.begin():
367
- # Build the query
368
- stmt = select(self.table)
369
- if user_id is not None:
370
- stmt = stmt.where(self.table.c.user_id == user_id)
371
- if entity_id is not None:
372
- if self.mode == "agent":
373
- stmt = stmt.where(self.table.c.agent_id == entity_id)
374
- elif self.mode == "team":
375
- stmt = stmt.where(self.table.c.team_id == entity_id)
376
- elif self.mode in ["workflow", "workflow_v2"]:
377
- stmt = stmt.where(self.table.c.workflow_id == entity_id)
378
-
379
- # Order by created_at desc and limit to num_history_sessions
380
- stmt = stmt.order_by(self.table.c.created_at.desc())
381
- if limit is not None:
382
- stmt = stmt.limit(limit)
383
-
384
- # Execute query
385
- rows = sess.execute(stmt).fetchall()
386
- if rows is not None:
387
- if self.mode == "agent": # type: ignore
388
- return [AgentSession.from_dict(row._mapping) for row in rows] # type: ignore
389
- elif self.mode == "team":
390
- return [TeamSession.from_dict(row._mapping) for row in rows] # type: ignore
391
- elif self.mode == "workflow":
392
- return [WorkflowSession.from_dict(row._mapping) for row in rows] # type: ignore
393
- elif self.mode == "workflow_v2":
394
- return [WorkflowSessionV2.from_dict(row._mapping) for row in rows] # type: ignore
395
- return []
396
- except Exception as e:
397
- if "no such table" in str(e):
398
- log_debug(f"Table does not exist: {self.table.name}")
399
- self.create()
400
- else:
401
- log_debug(f"Exception reading from table: {e}")
402
- return []
403
-
404
- def upgrade_schema(self) -> None:
405
- """
406
- Upgrade the schema of the storage table.
407
- Currently handles adding the team_session_id column for agent mode.
408
- """
409
- if not self.auto_upgrade_schema:
410
- log_debug("Auto schema upgrade disabled. Skipping upgrade.")
411
- return
412
-
413
- try:
414
- if self.mode == "agent" and self.table_exists():
415
- with self.SqlSession() as sess:
416
- # Check if team_session_id column exists using SQLite PRAGMA
417
- column_exists_query = text(f"PRAGMA table_info({self.table_name})")
418
- columns = sess.execute(column_exists_query).fetchall()
419
- column_exists = any(col[1] == "team_session_id" for col in columns)
420
-
421
- if not column_exists:
422
- log_info(f"Adding 'team_session_id' column to {self.table_name}")
423
- alter_table_query = text(f"ALTER TABLE {self.table_name} ADD COLUMN team_session_id TEXT")
424
- sess.execute(alter_table_query)
425
- sess.commit()
426
- self._schema_up_to_date = True
427
- log_info("Schema upgrade completed successfully")
428
- except Exception as e:
429
- logger.error(f"Error during schema upgrade: {e}")
430
- raise
431
-
432
- def upsert(self, session: Session, create_and_retry: bool = True) -> Optional[Session]:
433
- """
434
- Insert or update a Session in the database.
435
-
436
- Args:
437
- session (Session): The session data to upsert.
438
- create_and_retry (bool): Retry upsert if table does not exist.
439
-
440
- Returns:
441
- Optional[Session]: The upserted Session, or None if operation failed.
442
- """
443
- # Perform schema upgrade if auto_upgrade_schema is enabled
444
- if self.auto_upgrade_schema and not self._schema_up_to_date:
445
- self.upgrade_schema()
446
-
447
- try:
448
- with self.SqlSession() as sess, sess.begin():
449
- if self.mode == "agent":
450
- # Create an insert statement
451
- stmt = sqlite.insert(self.table).values(
452
- session_id=session.session_id,
453
- agent_id=session.agent_id, # type: ignore
454
- team_session_id=session.team_session_id, # type: ignore
455
- user_id=session.user_id,
456
- memory=getattr(session, "memory", None),
457
- agent_data=session.agent_data, # type: ignore
458
- session_data=session.session_data,
459
- extra_data=session.extra_data,
460
- )
461
-
462
- # Define the upsert if the session_id already exists
463
- stmt = stmt.on_conflict_do_update(
464
- index_elements=["session_id"],
465
- set_=dict(
466
- agent_id=session.agent_id, # type: ignore
467
- team_session_id=session.team_session_id, # type: ignore
468
- user_id=session.user_id,
469
- memory=getattr(session, "memory", None),
470
- agent_data=session.agent_data, # type: ignore
471
- session_data=session.session_data,
472
- extra_data=session.extra_data,
473
- updated_at=int(time.time()),
474
- ),
475
- )
476
- elif self.mode == "team":
477
- # Create an insert statement
478
- stmt = sqlite.insert(self.table).values(
479
- session_id=session.session_id,
480
- team_id=session.team_id, # type: ignore
481
- user_id=session.user_id,
482
- team_session_id=session.team_session_id, # type: ignore
483
- memory=getattr(session, "memory", None),
484
- team_data=session.team_data, # type: ignore
485
- session_data=session.session_data,
486
- extra_data=session.extra_data,
487
- )
488
-
489
- # Define the upsert if the session_id already exists
490
- # See: https://docs.sqlalchemy.org/en/20/dialects/sqlite.html#insert-on-conflict-upsert
491
- stmt = stmt.on_conflict_do_update(
492
- index_elements=["session_id"],
493
- set_=dict(
494
- team_id=session.team_id, # type: ignore
495
- user_id=session.user_id,
496
- team_session_id=session.team_session_id, # type: ignore
497
- memory=getattr(session, "memory", None),
498
- team_data=session.team_data, # type: ignore
499
- session_data=session.session_data,
500
- extra_data=session.extra_data,
501
- updated_at=int(time.time()),
502
- ),
503
- )
504
- elif self.mode == "workflow":
505
- # Create an insert statement
506
- stmt = sqlite.insert(self.table).values(
507
- session_id=session.session_id,
508
- workflow_id=session.workflow_id, # type: ignore
509
- user_id=session.user_id,
510
- memory=getattr(session, "memory", None),
511
- workflow_data=session.workflow_data, # type: ignore
512
- session_data=session.session_data,
513
- extra_data=session.extra_data,
514
- )
515
-
516
- # Define the upsert if the session_id already exists
517
- # See: https://docs.sqlalchemy.org/en/20/dialects/sqlite.html#insert-on-conflict-upsert
518
- stmt = stmt.on_conflict_do_update(
519
- index_elements=["session_id"],
520
- set_=dict(
521
- workflow_id=session.workflow_id, # type: ignore
522
- user_id=session.user_id,
523
- memory=getattr(session, "memory", None),
524
- workflow_data=session.workflow_data, # type: ignore
525
- session_data=session.session_data,
526
- extra_data=session.extra_data,
527
- updated_at=int(time.time()),
528
- ),
529
- )
530
- elif self.mode == "workflow_v2":
531
- # Convert session to dict to ensure proper serialization
532
- session_dict = session.to_dict()
533
-
534
- # Create an insert statement for WorkflowSessionV2
535
- stmt = sqlite.insert(self.table).values(
536
- session_id=session.session_id,
537
- workflow_id=session.workflow_id, # type: ignore
538
- workflow_name=session.workflow_name, # type: ignore
539
- user_id=session.user_id,
540
- runs=session_dict.get("runs"),
541
- workflow_data=session.workflow_data, # type: ignore
542
- session_data=session.session_data,
543
- extra_data=session.extra_data,
544
- )
545
-
546
- # Define the upsert if the session_id already exists
547
- stmt = stmt.on_conflict_do_update(
548
- index_elements=["session_id"],
549
- set_=dict(
550
- workflow_id=session.workflow_id, # type: ignore
551
- workflow_name=session.workflow_name, # type: ignore
552
- user_id=session.user_id,
553
- runs=session_dict.get("runs"),
554
- workflow_data=session.workflow_data, # type: ignore
555
- session_data=session.session_data,
556
- extra_data=session.extra_data,
557
- updated_at=int(time.time()),
558
- ),
559
- )
560
-
561
- sess.execute(stmt)
562
- except Exception as e:
563
- if create_and_retry and not self.table_exists():
564
- log_debug(f"Table does not exist: {self.table.name}")
565
- log_debug("Creating table and retrying upsert")
566
- self.create()
567
- return self.upsert(session, create_and_retry=False)
568
- else:
569
- log_warning(f"Exception upserting into table: {e}")
570
- log_warning(
571
- "A table upgrade might be required, please review these docs for more information: https://agno.link/upgrade-schema"
572
- )
573
- return None
574
- return self.read(session_id=session.session_id)
575
-
576
- def delete_session(self, session_id: Optional[str] = None):
577
- """
578
- Delete a workflow session from the database.
579
-
580
- Args:
581
- session_id (Optional[str]): The ID of the session to delete.
582
-
583
- Raises:
584
- ValueError: If session_id is not provided.
585
- """
586
- if session_id is None:
587
- logger.warning("No session_id provided for deletion.")
588
- return
589
-
590
- try:
591
- with self.SqlSession() as sess, sess.begin():
592
- # Delete the session with the given session_id
593
- delete_stmt = self.table.delete().where(self.table.c.session_id == session_id)
594
- result = sess.execute(delete_stmt)
595
- if result.rowcount == 0:
596
- log_debug(f"No session found with session_id: {session_id}")
597
- else:
598
- log_debug(f"Successfully deleted session with session_id: {session_id}")
599
- except Exception as e:
600
- logger.error(f"Error deleting session: {e}")
601
-
602
- def drop(self) -> None:
603
- """
604
- Drop the table from the database if it exists.
605
- """
606
- if self.table_exists():
607
- log_debug(f"Deleting table: {self.table_name}")
608
- # Drop with checkfirst=True to avoid errors if the table doesn't exist
609
- self.table.drop(self.db_engine, checkfirst=True)
610
- # Clear metadata to ensure indexes are recreated properly
611
- self.metadata = MetaData()
612
- self.table = self.get_table()
613
-
614
- def __deepcopy__(self, memo):
615
- """
616
- Create a deep copy of the SqliteAgentStorage instance, handling unpickleable attributes.
617
-
618
- Args:
619
- memo (dict): A dictionary of objects already copied during the current copying pass.
620
-
621
- Returns:
622
- SqliteStorage: A deep-copied instance of SqliteAgentStorage.
623
- """
624
- from copy import deepcopy
625
-
626
- # Create a new instance without calling __init__
627
- cls = self.__class__
628
- copied_obj = cls.__new__(cls)
629
- memo[id(self)] = copied_obj
630
-
631
- # Deep copy attributes
632
- for k, v in self.__dict__.items():
633
- if k in {"metadata", "table", "inspector"}:
634
- continue
635
- # Reuse db_engine and Session without copying
636
- elif k in {"db_engine", "SqlSession"}:
637
- setattr(copied_obj, k, v)
638
- else:
639
- setattr(copied_obj, k, deepcopy(v, memo))
640
-
641
- # Recreate metadata and table for the copied instance
642
- copied_obj.metadata = MetaData()
643
- copied_obj.inspector = inspect(copied_obj.db_engine)
644
- copied_obj.table = copied_obj.get_table()
645
-
646
- return copied_obj
File without changes
@@ -1 +0,0 @@
1
- from agno.storage.mongodb import MongoDbStorage as MongoDbWorkflowStorage # noqa: F401
@@ -1 +0,0 @@
1
- from agno.storage.postgres import PostgresStorage as PostgresWorkflowStorage # noqa: F401
@@ -1 +0,0 @@
1
- from agno.storage.sqlite import SqliteStorage as SqliteWorkflowStorage # noqa: F401