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
@@ -1,606 +0,0 @@
1
- import json
2
- from typing import Any, List, Literal, Optional
3
-
4
- from agno.storage.base import Storage
5
- from agno.storage.session import Session
6
- from agno.storage.session.agent import AgentSession
7
- from agno.storage.session.team import TeamSession
8
- from agno.storage.session.v2.workflow import WorkflowSession as WorkflowSessionV2
9
- from agno.storage.session.workflow import WorkflowSession
10
- from agno.utils.log import log_debug, log_info, log_warning, logger
11
-
12
- try:
13
- from sqlalchemy.dialects import mysql
14
- from sqlalchemy.engine import Engine, create_engine
15
- from sqlalchemy.engine.row import Row
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.expression import select, text
21
- except ImportError:
22
- raise ImportError("`sqlalchemy` not installed")
23
-
24
-
25
- class SingleStoreStorage(Storage):
26
- def __init__(
27
- self,
28
- table_name: str,
29
- schema: Optional[str] = "ai",
30
- db_url: Optional[str] = None,
31
- db_engine: Optional[Engine] = None,
32
- schema_version: int = 1,
33
- auto_upgrade_schema: bool = False,
34
- mode: Optional[Literal["agent", "team", "workflow", "workflow_v2"]] = "agent",
35
- ):
36
- """
37
- This class provides Agent storage using a singlestore table.
38
-
39
- The following order is used to determine the database connection:
40
- 1. Use the db_engine if provided
41
- 2. Use the db_url if provided
42
-
43
- Args:
44
- table_name (str): The name of the table to store the agent data.
45
- schema (Optional[str], optional): The schema of the table. Defaults to "ai".
46
- db_url (Optional[str], optional): The database URL. Defaults to None.
47
- db_engine (Optional[Engine], optional): The database engine. Defaults to None.
48
- schema_version (int, optional): The schema version. Defaults to 1.
49
- auto_upgrade_schema (bool, optional): Automatically upgrade the schema. Defaults to False.
50
- mode (Optional[Literal["agent", "team", "workflow", "workflow_v2"]], optional): The mode of the storage. Defaults to "agent".
51
- """
52
- super().__init__(mode)
53
- _engine: Optional[Engine] = db_engine
54
- if _engine is None and db_url is not None:
55
- _engine = create_engine(db_url, connect_args={"charset": "utf8mb4"})
56
-
57
- if _engine is None:
58
- raise ValueError("Must provide either db_url or db_engine")
59
-
60
- # Database attributes
61
- self.table_name: str = table_name
62
- self.schema: Optional[str] = schema
63
- self.db_url: Optional[str] = db_url
64
- self.db_engine: Engine = _engine
65
- self.metadata: MetaData = MetaData(schema=self.schema)
66
-
67
- # Table schema version
68
- self.schema_version: int = schema_version
69
- # Automatically upgrade schema if True
70
- self.auto_upgrade_schema: bool = auto_upgrade_schema
71
- self._schema_up_to_date: bool = False
72
-
73
- # Database session
74
- self.SqlSession: sessionmaker[SqlSession] = sessionmaker(bind=self.db_engine)
75
- # Database table for storage
76
- self.table: Table = self.get_table()
77
-
78
- @property
79
- def mode(self) -> Literal["agent", "team", "workflow", "workflow_v2"]:
80
- """Get the mode of the storage."""
81
- return super().mode
82
-
83
- @mode.setter
84
- def mode(self, value: Optional[Literal["agent", "team", "workflow", "workflow_v2"]]) -> None:
85
- """Set the mode and refresh the table if mode changes."""
86
- super(SingleStoreStorage, type(self)).mode.fset(self, value) # type: ignore
87
- if value is not None:
88
- self.table = self.get_table()
89
-
90
- def get_table_v1(self) -> Table:
91
- common_columns = [
92
- Column("session_id", mysql.TEXT, primary_key=True),
93
- Column("user_id", mysql.TEXT),
94
- Column("memory", mysql.JSON),
95
- Column("session_data", mysql.JSON),
96
- Column("extra_data", mysql.JSON),
97
- Column("created_at", mysql.BIGINT),
98
- Column("updated_at", mysql.BIGINT),
99
- ]
100
-
101
- specific_columns = []
102
- if self.mode == "agent":
103
- specific_columns = [
104
- Column("agent_id", mysql.TEXT),
105
- Column("team_session_id", mysql.TEXT, nullable=True),
106
- Column("agent_data", mysql.JSON),
107
- ]
108
- elif self.mode == "team":
109
- specific_columns = [
110
- Column("team_id", mysql.TEXT),
111
- Column("team_session_id", mysql.TEXT, nullable=True),
112
- Column("team_data", mysql.JSON),
113
- ]
114
- elif self.mode == "workflow":
115
- specific_columns = [
116
- Column("workflow_id", mysql.TEXT),
117
- Column("workflow_data", mysql.JSON),
118
- ]
119
- elif self.mode == "workflow_v2":
120
- specific_columns = [
121
- Column("workflow_id", mysql.TEXT),
122
- Column("workflow_data", mysql.JSON),
123
- Column("runs", mysql.JSON),
124
- ]
125
-
126
- # Create table with all columns
127
- table = Table(
128
- self.table_name,
129
- self.metadata,
130
- *common_columns,
131
- *specific_columns,
132
- extend_existing=True,
133
- schema=self.schema, # type: ignore
134
- )
135
-
136
- return table
137
-
138
- def get_table(self) -> Table:
139
- if self.schema_version == 1:
140
- return self.get_table_v1()
141
- else:
142
- raise ValueError(f"Unsupported schema version: {self.schema_version}")
143
-
144
- def table_exists(self) -> bool:
145
- log_debug(f"Checking if table exists: {self.table.name}")
146
- try:
147
- return inspect(self.db_engine).has_table(self.table.name, schema=self.schema)
148
- except Exception as e:
149
- logger.error(e)
150
- return False
151
-
152
- def create(self) -> None:
153
- self.table = self.get_table()
154
- if not self.table_exists():
155
- log_info(f"Creating table: {self.table_name}\n")
156
- self.table.create(self.db_engine)
157
-
158
- def _read(self, session: SqlSession, session_id: str, user_id: Optional[str] = None) -> Optional[Row[Any]]:
159
- stmt = select(self.table).where(self.table.c.session_id == session_id)
160
- if user_id is not None:
161
- stmt = stmt.where(self.table.c.user_id == user_id)
162
- try:
163
- return session.execute(stmt).first()
164
- except Exception as e:
165
- log_debug(f"Exception reading from table: {e}")
166
- log_debug(f"Table does not exist: {self.table.name}")
167
- log_debug(f"Creating table: {self.table_name}")
168
- self.create()
169
- return None
170
-
171
- def read(self, session_id: str, user_id: Optional[str] = None) -> Optional[Session]:
172
- with self.SqlSession.begin() as sess:
173
- existing_row: Optional[Row[Any]] = self._read(session=sess, session_id=session_id, user_id=user_id)
174
- if existing_row is not None:
175
- if self.mode == "agent":
176
- return AgentSession.from_dict(existing_row._mapping) # type: ignore
177
- elif self.mode == "team":
178
- return TeamSession.from_dict(existing_row._mapping) # type: ignore
179
- elif self.mode == "workflow":
180
- return WorkflowSession.from_dict(existing_row._mapping) # type: ignore
181
- elif self.mode == "workflow_v2":
182
- return WorkflowSessionV2.from_dict(existing_row._mapping) # type: ignore
183
- return None
184
-
185
- def get_all_session_ids(self, user_id: Optional[str] = None, entity_id: Optional[str] = None) -> List[str]:
186
- session_ids: List[str] = []
187
- try:
188
- with self.SqlSession.begin() as sess:
189
- # get all session_ids for this user
190
- stmt = select(self.table)
191
- if user_id is not None:
192
- stmt = stmt.where(self.table.c.user_id == user_id)
193
- if entity_id is not None:
194
- if self.mode == "agent":
195
- stmt = stmt.where(self.table.c.agent_id == entity_id)
196
- elif self.mode == "team":
197
- stmt = stmt.where(self.table.c.team_id == entity_id)
198
- elif self.mode == "workflow":
199
- stmt = stmt.where(self.table.c.workflow_id == entity_id)
200
- elif self.mode == "workflow_v2":
201
- stmt = stmt.where(self.table.c.workflow_id == entity_id)
202
- # order by created_at desc
203
- stmt = stmt.order_by(self.table.c.created_at.desc())
204
- # execute query
205
- rows = sess.execute(stmt).fetchall()
206
- for row in rows:
207
- if row is not None and row.session_id is not None:
208
- session_ids.append(row.session_id)
209
- except Exception as e:
210
- logger.error(f"An unexpected error occurred: {str(e)}")
211
- return session_ids
212
-
213
- def get_all_sessions(self, user_id: Optional[str] = None, entity_id: Optional[str] = None) -> List[Session]:
214
- sessions: List[Session] = []
215
- try:
216
- with self.SqlSession.begin() as sess:
217
- # get all sessions for this user
218
- stmt = select(self.table)
219
- if user_id is not None:
220
- stmt = stmt.where(self.table.c.user_id == user_id)
221
- if entity_id is not None:
222
- if self.mode == "agent":
223
- stmt = stmt.where(self.table.c.agent_id == entity_id)
224
- elif self.mode == "team":
225
- stmt = stmt.where(self.table.c.team_id == entity_id)
226
- elif self.mode == "workflow":
227
- stmt = stmt.where(self.table.c.workflow_id == entity_id)
228
- elif self.mode == "workflow_v2":
229
- stmt = stmt.where(self.table.c.workflow_id == entity_id)
230
- # order by created_at desc
231
- stmt = stmt.order_by(self.table.c.created_at.desc())
232
- # execute query
233
- rows = sess.execute(stmt).fetchall()
234
- for row in rows:
235
- if row.session_id is not None:
236
- if self.mode == "agent":
237
- _agent_session = AgentSession.from_dict(row._mapping) # type: ignore
238
- if _agent_session is not None:
239
- sessions.append(_agent_session)
240
- elif self.mode == "team":
241
- _team_session = TeamSession.from_dict(row._mapping) # type: ignore
242
- if _team_session is not None:
243
- sessions.append(_team_session)
244
- elif self.mode == "workflow":
245
- _workflow_session = WorkflowSession.from_dict(row._mapping) # type: ignore
246
- if _workflow_session is not None:
247
- sessions.append(_workflow_session)
248
- elif self.mode == "workflow_v2":
249
- _workflow_session = WorkflowSessionV2.from_dict(row._mapping) # type: ignore
250
- if _workflow_session is not None:
251
- sessions.append(_workflow_session)
252
- except Exception:
253
- log_debug(f"Table does not exist: {self.table.name}")
254
- return sessions
255
-
256
- def get_recent_sessions(
257
- self,
258
- user_id: Optional[str] = None,
259
- entity_id: Optional[str] = None,
260
- limit: Optional[int] = 2,
261
- ) -> List[Session]:
262
- """Get the last N sessions, ordered by created_at descending.
263
-
264
- Args:
265
- num_history_sessions: Number of most recent sessions to return
266
- user_id: Filter by user ID
267
- entity_id: Filter by entity ID (agent_id, team_id, or workflow_id)
268
-
269
- Returns:
270
- List[Session]: List of most recent sessions
271
- """
272
- sessions: List[Session] = []
273
- try:
274
- with self.SqlSession.begin() as sess:
275
- # Build base query
276
- stmt = select(self.table)
277
-
278
- # Add filters
279
- if user_id is not None:
280
- stmt = stmt.where(self.table.c.user_id == user_id)
281
- if entity_id is not None:
282
- if self.mode == "agent":
283
- stmt = stmt.where(self.table.c.agent_id == entity_id)
284
- elif self.mode == "team":
285
- stmt = stmt.where(self.table.c.team_id == entity_id)
286
- elif self.mode == "workflow":
287
- stmt = stmt.where(self.table.c.workflow_id == entity_id)
288
- elif self.mode == "workflow_v2":
289
- stmt = stmt.where(self.table.c.workflow_id == entity_id)
290
- # Order by created_at desc and limit results
291
- stmt = stmt.order_by(self.table.c.created_at.desc())
292
- if limit is not None:
293
- stmt = stmt.limit(limit)
294
-
295
- # Execute query
296
- rows = sess.execute(stmt).fetchall()
297
- for row in rows:
298
- if row.session_id is not None:
299
- if self.mode == "agent":
300
- session = AgentSession.from_dict(row._mapping) # type: ignore
301
- if session is not None:
302
- sessions.append(session)
303
- elif self.mode == "team":
304
- session = TeamSession.from_dict(row._mapping) # type: ignore
305
- if session is not None:
306
- sessions.append(session)
307
- elif self.mode == "workflow":
308
- session = WorkflowSession.from_dict(row._mapping) # type: ignore
309
- if session is not None:
310
- sessions.append(session)
311
- elif self.mode == "workflow_v2":
312
- session = WorkflowSessionV2.from_dict(row._mapping) # type: ignore
313
- if session is not None:
314
- sessions.append(session)
315
- except Exception as e:
316
- if "doesn't exist" in str(e):
317
- log_debug(f"Table does not exist: {self.table.name}")
318
- self.create()
319
- else:
320
- logger.error(f"Error getting last {limit} sessions: {e}")
321
-
322
- return sessions
323
-
324
- def upgrade_schema(self) -> None:
325
- """
326
- Upgrade the schema to the latest version.
327
- Currently handles adding the team_session_id column for agent mode.
328
- """
329
- if not self.auto_upgrade_schema:
330
- log_debug("Auto schema upgrade disabled. Skipping upgrade.")
331
- return
332
-
333
- try:
334
- if self.mode == "agent" and self.table_exists():
335
- with self.SqlSession() as sess:
336
- # Check if team_session_id column exists
337
- column_exists_query = text(
338
- """
339
- SELECT 1 FROM information_schema.columns
340
- WHERE table_schema = :schema AND table_name = :table
341
- AND column_name = 'team_session_id'
342
- """
343
- )
344
- column_exists = (
345
- sess.execute(column_exists_query, {"schema": self.schema, "table": self.table_name}).scalar()
346
- is not None
347
- )
348
-
349
- if not column_exists:
350
- log_info(f"Adding 'team_session_id' column to {self.schema}.{self.table_name}")
351
- alter_table_query = text(
352
- f"ALTER TABLE {self.schema}.{self.table_name} ADD COLUMN team_session_id TEXT"
353
- )
354
- sess.execute(alter_table_query)
355
- sess.commit()
356
- self._schema_up_to_date = True
357
- log_info("Schema upgrade completed successfully")
358
- except Exception as e:
359
- logger.error(f"Error during schema upgrade: {e}")
360
- raise
361
-
362
- def upsert(self, session: Session) -> Optional[Session]:
363
- """
364
- Create a new session if it does not exist, otherwise update the existing session.
365
- """
366
- # Perform schema upgrade if auto_upgrade_schema is enabled
367
- if self.auto_upgrade_schema and not self._schema_up_to_date:
368
- self.upgrade_schema()
369
-
370
- with self.SqlSession.begin() as sess:
371
- # Create an insert statement using MySQL's ON DUPLICATE KEY UPDATE syntax
372
- if self.mode == "agent":
373
- upsert_sql = text(
374
- f"""
375
- INSERT INTO {self.schema}.{self.table_name}
376
- (session_id, agent_id, team_session_id, user_id, memory, agent_data, session_data, extra_data, created_at, updated_at)
377
- VALUES
378
- (:session_id, :agent_id, :team_session_id, :user_id, :memory, :agent_data, :session_data, :extra_data, UNIX_TIMESTAMP(), NULL)
379
- ON DUPLICATE KEY UPDATE
380
- agent_id = VALUES(agent_id),
381
- team_session_id = VALUES(team_session_id),
382
- user_id = VALUES(user_id),
383
- memory = VALUES(memory),
384
- agent_data = VALUES(agent_data),
385
- session_data = VALUES(session_data),
386
- extra_data = VALUES(extra_data),
387
- updated_at = UNIX_TIMESTAMP();
388
- """
389
- )
390
- elif self.mode == "team":
391
- upsert_sql = text(
392
- f"""
393
- INSERT INTO {self.schema}.{self.table_name}
394
- (session_id, team_id, user_id, team_session_id, memory, team_data, session_data, extra_data, created_at, updated_at)
395
- VALUES
396
- (:session_id, :team_id, :user_id, :team_session_id, :memory, :team_data, :session_data, :extra_data, UNIX_TIMESTAMP(), NULL)
397
- ON DUPLICATE KEY UPDATE
398
- team_id = VALUES(team_id),
399
- team_session_id = VALUES(team_session_id),
400
- user_id = VALUES(user_id),
401
- memory = VALUES(memory),
402
- team_data = VALUES(team_data),
403
- session_data = VALUES(session_data),
404
- extra_data = VALUES(extra_data),
405
- updated_at = UNIX_TIMESTAMP();
406
- """
407
- )
408
- elif self.mode == "workflow":
409
- upsert_sql = text(
410
- f"""
411
- INSERT INTO {self.schema}.{self.table_name}
412
- (session_id, workflow_id, user_id, memory, workflow_data, session_data, extra_data, created_at, updated_at)
413
- VALUES
414
- (:session_id, :workflow_id, :user_id, :memory, :workflow_data, :session_data, :extra_data, UNIX_TIMESTAMP(), NULL)
415
- ON DUPLICATE KEY UPDATE
416
- workflow_id = VALUES(workflow_id),
417
- user_id = VALUES(user_id),
418
- memory = VALUES(memory),
419
- workflow_data = VALUES(workflow_data),
420
- session_data = VALUES(session_data),
421
- extra_data = VALUES(extra_data),
422
- updated_at = UNIX_TIMESTAMP();
423
- """
424
- )
425
- elif self.mode == "workflow_v2":
426
- # Convert session to dict to ensure proper serialization
427
- upsert_sql = text(
428
- f"""
429
- INSERT INTO {self.schema}.{self.table_name}
430
- (session_id, workflow_id, user_id, workflow_name, runs, workflow_data, session_data, extra_data, created_at, updated_at)
431
- VALUES
432
- (:session_id, :workflow_id, :user_id, :workflow_name, :runs, :workflow_data, :session_data, :extra_data, UNIX_TIMESTAMP(), NULL)
433
- ON DUPLICATE KEY UPDATE
434
- workflow_id = VALUES(workflow_id),
435
- user_id = VALUES(user_id),
436
- workflow_name = VALUES(workflow_name),
437
- runs = VALUES(runs),
438
- workflow_data = VALUES(workflow_data),
439
- session_data = VALUES(session_data),
440
- extra_data = VALUES(extra_data),
441
- updated_at = UNIX_TIMESTAMP();
442
- """
443
- )
444
-
445
- try:
446
- if self.mode == "agent":
447
- sess.execute(
448
- upsert_sql,
449
- {
450
- "session_id": session.session_id,
451
- "agent_id": session.agent_id, # type: ignore
452
- "team_session_id": session.team_session_id, # type: ignore
453
- "user_id": session.user_id,
454
- "memory": json.dumps(getattr(session, "memory", None), ensure_ascii=False)
455
- if getattr(session, "memory", None) is not None
456
- else None,
457
- "agent_data": json.dumps(session.agent_data, ensure_ascii=False) # type: ignore
458
- if session.agent_data is not None # type: ignore
459
- else None,
460
- "session_data": json.dumps(session.session_data, ensure_ascii=False)
461
- if session.session_data is not None
462
- else None,
463
- "extra_data": json.dumps(session.extra_data, ensure_ascii=False)
464
- if session.extra_data is not None
465
- else None,
466
- },
467
- )
468
- elif self.mode == "team":
469
- sess.execute(
470
- upsert_sql,
471
- {
472
- "session_id": session.session_id,
473
- "team_id": session.team_id, # type: ignore
474
- "user_id": session.user_id,
475
- "team_session_id": session.team_session_id, # type: ignore
476
- "memory": json.dumps(getattr(session, "memory", None), ensure_ascii=False)
477
- if getattr(session, "memory", None) is not None
478
- else None,
479
- "team_data": json.dumps(session.team_data, ensure_ascii=False) # type: ignore
480
- if session.team_data is not None # type: ignore
481
- else None,
482
- "session_data": json.dumps(session.session_data, ensure_ascii=False)
483
- if session.session_data is not None
484
- else None,
485
- "extra_data": json.dumps(session.extra_data, ensure_ascii=False)
486
- if session.extra_data is not None
487
- else None,
488
- },
489
- )
490
- elif self.mode == "workflow":
491
- sess.execute(
492
- upsert_sql,
493
- {
494
- "session_id": session.session_id,
495
- "workflow_id": session.workflow_id, # type: ignore
496
- "user_id": session.user_id,
497
- "memory": json.dumps(getattr(session, "memory", None), ensure_ascii=False)
498
- if getattr(session, "memory", None) is not None
499
- else None,
500
- "workflow_data": json.dumps(session.workflow_data, ensure_ascii=False) # type: ignore
501
- if session.workflow_data is not None # type: ignore
502
- else None,
503
- "session_data": json.dumps(session.session_data, ensure_ascii=False)
504
- if session.session_data is not None
505
- else None,
506
- "extra_data": json.dumps(session.extra_data, ensure_ascii=False)
507
- if session.extra_data is not None
508
- else None,
509
- },
510
- )
511
- elif self.mode == "workflow_v2":
512
- # Convert session to dict to ensure proper serialization
513
- session_dict = session.to_dict()
514
-
515
- sess.execute(
516
- upsert_sql,
517
- {
518
- "session_id": session.session_id,
519
- "workflow_id": session.workflow_id, # type: ignore
520
- "user_id": session.user_id,
521
- "workflow_name": session.workflow_name, # type: ignore
522
- "runs": json.dumps(session_dict.get("runs"), ensure_ascii=False)
523
- if session_dict.get("runs")
524
- else None,
525
- "workflow_data": json.dumps(session.workflow_data, ensure_ascii=False) # type: ignore
526
- if session.workflow_data is not None # type: ignore
527
- else None,
528
- "session_data": json.dumps(session.session_data, ensure_ascii=False)
529
- if session.session_data is not None
530
- else None,
531
- "extra_data": json.dumps(session.extra_data, ensure_ascii=False)
532
- if session.extra_data is not None
533
- else None,
534
- },
535
- )
536
- except Exception as e:
537
- # Create table and try again
538
- if not self.table_exists():
539
- log_debug(f"Table does not exist: {self.table.name}")
540
- log_debug("Creating table and retrying upsert")
541
- self.create()
542
- return self.upsert(session)
543
- else:
544
- log_warning(f"Exception upserting into table: {e}")
545
- log_warning(
546
- "A table upgrade might be required, please review these docs for more information: https://agno.link/upgrade-schema"
547
- )
548
- return None
549
- return self.read(session_id=session.session_id)
550
-
551
- def delete_session(self, session_id: Optional[str] = None):
552
- if session_id is None:
553
- logger.warning("No session_id provided for deletion.")
554
- return
555
-
556
- with self.SqlSession() as sess, sess.begin():
557
- try:
558
- # Delete the session with the given session_id
559
- delete_stmt = self.table.delete().where(self.table.c.session_id == session_id)
560
- result = sess.execute(delete_stmt)
561
-
562
- if result.rowcount == 0:
563
- logger.warning(f"No session found with session_id: {session_id}")
564
- else:
565
- log_info(f"Successfully deleted session with session_id: {session_id}")
566
- except Exception as e:
567
- logger.error(f"Error deleting session: {e}")
568
- raise
569
-
570
- def drop(self) -> None:
571
- if self.table_exists():
572
- log_info(f"Deleting table: {self.table_name}")
573
- self.table.drop(self.db_engine)
574
-
575
- def __deepcopy__(self, memo):
576
- """
577
- Create a deep copy of the SingleStoreAgentStorage instance, handling unpickleable attributes.
578
-
579
- Args:
580
- memo (dict): A dictionary of objects already copied during the current copying pass.
581
-
582
- Returns:
583
- SingleStoreStorage: A deep-copied instance of SingleStoreAgentStorage.
584
- """
585
- from copy import deepcopy
586
-
587
- # Create a new instance without calling __init__
588
- cls = self.__class__
589
- copied_obj = cls.__new__(cls)
590
- memo[id(self)] = copied_obj
591
-
592
- # Deep copy attributes
593
- for k, v in self.__dict__.items():
594
- if k in {"metadata", "table"}:
595
- continue
596
- # Reuse db_engine and Session without copying
597
- elif k in {"db_engine", "SqlSession"}:
598
- setattr(copied_obj, k, v)
599
- else:
600
- setattr(copied_obj, k, deepcopy(v, memo))
601
-
602
- # Recreate metadata and table for the copied instance
603
- copied_obj.metadata = MetaData(schema=self.schema)
604
- copied_obj.table = copied_obj.get_table()
605
-
606
- return copied_obj