agno 1.8.0__py3-none-any.whl → 2.0.0a1__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 (583) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +2781 -4126
  4. agno/api/agent.py +9 -65
  5. agno/api/api.py +5 -46
  6. agno/api/evals.py +6 -17
  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 +9 -64
  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 +1749 -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 +1438 -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 +888 -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 +1051 -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 +1417 -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 +298 -0
  52. agno/db/postgres/__init__.py +3 -0
  53. agno/db/postgres/postgres.py +1720 -0
  54. agno/db/postgres/schemas.py +124 -0
  55. agno/db/postgres/utils.py +281 -0
  56. agno/db/redis/__init__.py +3 -0
  57. agno/db/redis/redis.py +1371 -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 +1722 -0
  67. agno/db/singlestore/utils.py +327 -0
  68. agno/db/sqlite/__init__.py +3 -0
  69. agno/db/sqlite/schemas.py +119 -0
  70. agno/db/sqlite/sqlite.py +1680 -0
  71. agno/db/sqlite/utils.py +269 -0
  72. agno/db/utils.py +88 -0
  73. agno/eval/__init__.py +14 -0
  74. agno/eval/accuracy.py +142 -43
  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 +10 -10
  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 +1515 -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 +68 -15
  115. agno/knowledge/reader/docx_reader.py +83 -0
  116. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  117. agno/knowledge/reader/gcs_reader.py +67 -0
  118. agno/{document → knowledge}/reader/json_reader.py +30 -9
  119. agno/{document → knowledge}/reader/markdown_reader.py +36 -9
  120. agno/{document → knowledge}/reader/pdf_reader.py +79 -21
  121. agno/knowledge/reader/reader_factory.py +275 -0
  122. agno/knowledge/reader/s3_reader.py +171 -0
  123. agno/{document → knowledge}/reader/text_reader.py +31 -10
  124. agno/knowledge/reader/url_reader.py +84 -0
  125. agno/knowledge/reader/web_search_reader.py +389 -0
  126. agno/{document → knowledge}/reader/website_reader.py +37 -10
  127. agno/knowledge/reader/wikipedia_reader.py +59 -0
  128. agno/knowledge/reader/youtube_reader.py +78 -0
  129. agno/knowledge/remote_content/remote_content.py +88 -0
  130. agno/{reranker → knowledge/reranker}/base.py +1 -1
  131. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  132. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  133. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  134. agno/knowledge/types.py +30 -0
  135. agno/knowledge/utils.py +169 -0
  136. agno/media.py +2 -2
  137. agno/memory/__init__.py +2 -10
  138. agno/memory/manager.py +1003 -148
  139. agno/models/aimlapi/__init__.py +2 -2
  140. agno/models/aimlapi/aimlapi.py +6 -6
  141. agno/models/anthropic/claude.py +129 -82
  142. agno/models/aws/bedrock.py +107 -175
  143. agno/models/aws/claude.py +64 -18
  144. agno/models/azure/ai_foundry.py +73 -23
  145. agno/models/base.py +347 -287
  146. agno/models/cerebras/cerebras.py +84 -27
  147. agno/models/cohere/chat.py +106 -98
  148. agno/models/dashscope/dashscope.py +14 -5
  149. agno/models/google/gemini.py +123 -53
  150. agno/models/groq/groq.py +97 -35
  151. agno/models/huggingface/huggingface.py +92 -27
  152. agno/models/ibm/watsonx.py +72 -13
  153. agno/models/litellm/chat.py +85 -13
  154. agno/models/message.py +38 -144
  155. agno/models/meta/llama.py +85 -49
  156. agno/models/metrics.py +120 -0
  157. agno/models/mistral/mistral.py +90 -21
  158. agno/models/ollama/__init__.py +0 -2
  159. agno/models/ollama/chat.py +84 -46
  160. agno/models/openai/chat.py +135 -27
  161. agno/models/openai/responses.py +233 -115
  162. agno/models/perplexity/perplexity.py +26 -2
  163. agno/models/portkey/portkey.py +0 -7
  164. agno/models/response.py +14 -8
  165. agno/models/utils.py +20 -0
  166. agno/models/vercel/__init__.py +2 -2
  167. agno/models/vercel/v0.py +1 -1
  168. agno/models/vllm/__init__.py +2 -2
  169. agno/models/vllm/vllm.py +3 -3
  170. agno/models/xai/xai.py +10 -10
  171. agno/os/__init__.py +3 -0
  172. agno/os/app.py +393 -0
  173. agno/os/auth.py +47 -0
  174. agno/os/config.py +103 -0
  175. agno/os/interfaces/agui/__init__.py +3 -0
  176. agno/os/interfaces/agui/agui.py +31 -0
  177. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  178. agno/{app → os/interfaces}/agui/utils.py +65 -28
  179. agno/os/interfaces/base.py +21 -0
  180. agno/os/interfaces/slack/__init__.py +3 -0
  181. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  182. agno/os/interfaces/slack/slack.py +33 -0
  183. agno/os/interfaces/whatsapp/__init__.py +3 -0
  184. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  185. agno/os/interfaces/whatsapp/whatsapp.py +30 -0
  186. agno/os/router.py +843 -0
  187. agno/os/routers/__init__.py +3 -0
  188. agno/os/routers/evals/__init__.py +3 -0
  189. agno/os/routers/evals/evals.py +204 -0
  190. agno/os/routers/evals/schemas.py +142 -0
  191. agno/os/routers/evals/utils.py +161 -0
  192. agno/os/routers/knowledge/__init__.py +3 -0
  193. agno/os/routers/knowledge/knowledge.py +413 -0
  194. agno/os/routers/knowledge/schemas.py +118 -0
  195. agno/os/routers/memory/__init__.py +3 -0
  196. agno/os/routers/memory/memory.py +179 -0
  197. agno/os/routers/memory/schemas.py +58 -0
  198. agno/os/routers/metrics/__init__.py +3 -0
  199. agno/os/routers/metrics/metrics.py +58 -0
  200. agno/os/routers/metrics/schemas.py +47 -0
  201. agno/os/routers/session/__init__.py +3 -0
  202. agno/os/routers/session/session.py +163 -0
  203. agno/os/schema.py +892 -0
  204. agno/{app/playground → os}/settings.py +8 -15
  205. agno/os/utils.py +270 -0
  206. agno/reasoning/azure_ai_foundry.py +4 -4
  207. agno/reasoning/deepseek.py +4 -4
  208. agno/reasoning/default.py +6 -11
  209. agno/reasoning/groq.py +4 -4
  210. agno/reasoning/helpers.py +4 -6
  211. agno/reasoning/ollama.py +4 -4
  212. agno/reasoning/openai.py +4 -4
  213. agno/run/{response.py → agent.py} +144 -72
  214. agno/run/base.py +44 -58
  215. agno/run/cancel.py +83 -0
  216. agno/run/team.py +133 -77
  217. agno/run/workflow.py +537 -12
  218. agno/session/__init__.py +10 -0
  219. agno/session/agent.py +244 -0
  220. agno/session/summary.py +225 -0
  221. agno/session/team.py +262 -0
  222. agno/{storage/session/v2 → session}/workflow.py +47 -24
  223. agno/team/__init__.py +15 -16
  224. agno/team/team.py +2967 -4243
  225. agno/tools/agentql.py +14 -5
  226. agno/tools/airflow.py +9 -4
  227. agno/tools/api.py +7 -3
  228. agno/tools/apify.py +2 -46
  229. agno/tools/arxiv.py +8 -3
  230. agno/tools/aws_lambda.py +7 -5
  231. agno/tools/aws_ses.py +7 -1
  232. agno/tools/baidusearch.py +4 -1
  233. agno/tools/bitbucket.py +4 -4
  234. agno/tools/brandfetch.py +14 -11
  235. agno/tools/bravesearch.py +4 -1
  236. agno/tools/brightdata.py +42 -22
  237. agno/tools/browserbase.py +13 -4
  238. agno/tools/calcom.py +12 -10
  239. agno/tools/calculator.py +10 -27
  240. agno/tools/cartesia.py +18 -13
  241. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  242. agno/tools/confluence.py +71 -18
  243. agno/tools/crawl4ai.py +7 -1
  244. agno/tools/csv_toolkit.py +9 -8
  245. agno/tools/dalle.py +18 -11
  246. agno/tools/daytona.py +13 -16
  247. agno/tools/decorator.py +6 -3
  248. agno/tools/desi_vocal.py +16 -7
  249. agno/tools/discord.py +11 -8
  250. agno/tools/docker.py +30 -42
  251. agno/tools/duckdb.py +34 -53
  252. agno/tools/duckduckgo.py +8 -7
  253. agno/tools/e2b.py +62 -62
  254. agno/tools/eleven_labs.py +35 -28
  255. agno/tools/email.py +4 -1
  256. agno/tools/evm.py +7 -1
  257. agno/tools/exa.py +19 -14
  258. agno/tools/fal.py +29 -29
  259. agno/tools/file.py +9 -8
  260. agno/tools/financial_datasets.py +25 -44
  261. agno/tools/firecrawl.py +22 -22
  262. agno/tools/function.py +68 -17
  263. agno/tools/giphy.py +22 -10
  264. agno/tools/github.py +48 -126
  265. agno/tools/gmail.py +46 -62
  266. agno/tools/google_bigquery.py +7 -6
  267. agno/tools/google_maps.py +11 -26
  268. agno/tools/googlesearch.py +7 -2
  269. agno/tools/googlesheets.py +21 -17
  270. agno/tools/hackernews.py +9 -5
  271. agno/tools/jina.py +5 -4
  272. agno/tools/jira.py +18 -9
  273. agno/tools/knowledge.py +31 -32
  274. agno/tools/linear.py +18 -33
  275. agno/tools/linkup.py +5 -1
  276. agno/tools/local_file_system.py +8 -5
  277. agno/tools/lumalab.py +31 -19
  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 +32 -14
  282. agno/tools/models/gemini.py +58 -31
  283. agno/tools/models/groq.py +29 -20
  284. agno/tools/models/nebius.py +27 -11
  285. agno/tools/models_labs.py +39 -15
  286. agno/tools/moviepy_video.py +7 -6
  287. agno/tools/neo4j.py +134 -0
  288. agno/tools/newspaper.py +7 -2
  289. agno/tools/newspaper4k.py +8 -3
  290. agno/tools/openai.py +57 -26
  291. agno/tools/openbb.py +12 -11
  292. agno/tools/opencv.py +62 -46
  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 +54 -41
  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 +95 -118
  335. agno/utils/knowledge.py +29 -0
  336. agno/utils/location.py +2 -2
  337. agno/utils/log.py +2 -2
  338. agno/utils/mcp.py +11 -5
  339. agno/utils/media.py +39 -0
  340. agno/utils/message.py +12 -1
  341. agno/utils/models/claude.py +6 -4
  342. agno/utils/models/mistral.py +8 -7
  343. agno/utils/models/schema_utils.py +3 -3
  344. agno/utils/pprint.py +33 -32
  345. agno/utils/print_response/agent.py +779 -0
  346. agno/utils/print_response/team.py +1565 -0
  347. agno/utils/print_response/workflow.py +1451 -0
  348. agno/utils/prompts.py +14 -14
  349. agno/utils/reasoning.py +87 -0
  350. agno/utils/response.py +42 -42
  351. agno/utils/string.py +8 -22
  352. agno/utils/team.py +50 -0
  353. agno/utils/timer.py +2 -2
  354. agno/vectordb/base.py +33 -21
  355. agno/vectordb/cassandra/cassandra.py +287 -23
  356. agno/vectordb/chroma/chromadb.py +482 -59
  357. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  358. agno/vectordb/couchbase/couchbase.py +309 -29
  359. agno/vectordb/lancedb/lance_db.py +360 -21
  360. agno/vectordb/langchaindb/__init__.py +5 -0
  361. agno/vectordb/langchaindb/langchaindb.py +145 -0
  362. agno/vectordb/lightrag/__init__.py +5 -0
  363. agno/vectordb/lightrag/lightrag.py +374 -0
  364. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  365. agno/vectordb/milvus/milvus.py +242 -32
  366. agno/vectordb/mongodb/mongodb.py +200 -24
  367. agno/vectordb/pgvector/pgvector.py +319 -37
  368. agno/vectordb/pineconedb/pineconedb.py +221 -27
  369. agno/vectordb/qdrant/qdrant.py +356 -14
  370. agno/vectordb/singlestore/singlestore.py +286 -29
  371. agno/vectordb/surrealdb/surrealdb.py +187 -7
  372. agno/vectordb/upstashdb/upstashdb.py +342 -26
  373. agno/vectordb/weaviate/weaviate.py +227 -165
  374. agno/workflow/__init__.py +17 -13
  375. agno/workflow/{v2/condition.py → condition.py} +135 -32
  376. agno/workflow/{v2/loop.py → loop.py} +115 -28
  377. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  378. agno/workflow/{v2/router.py → router.py} +133 -32
  379. agno/workflow/{v2/step.py → step.py} +200 -42
  380. agno/workflow/{v2/steps.py → steps.py} +147 -66
  381. agno/workflow/types.py +482 -0
  382. agno/workflow/workflow.py +2394 -696
  383. agno-2.0.0a1.dist-info/METADATA +355 -0
  384. agno-2.0.0a1.dist-info/RECORD +514 -0
  385. agno/agent/metrics.py +0 -107
  386. agno/api/app.py +0 -35
  387. agno/api/playground.py +0 -92
  388. agno/api/schemas/app.py +0 -12
  389. agno/api/schemas/playground.py +0 -22
  390. agno/api/schemas/user.py +0 -35
  391. agno/api/schemas/workspace.py +0 -46
  392. agno/api/user.py +0 -160
  393. agno/api/workflows.py +0 -33
  394. agno/api/workspace.py +0 -175
  395. agno/app/agui/__init__.py +0 -3
  396. agno/app/agui/app.py +0 -17
  397. agno/app/agui/sync_router.py +0 -120
  398. agno/app/base.py +0 -186
  399. agno/app/discord/__init__.py +0 -3
  400. agno/app/fastapi/__init__.py +0 -3
  401. agno/app/fastapi/app.py +0 -107
  402. agno/app/fastapi/async_router.py +0 -457
  403. agno/app/fastapi/sync_router.py +0 -448
  404. agno/app/playground/app.py +0 -228
  405. agno/app/playground/async_router.py +0 -1050
  406. agno/app/playground/deploy.py +0 -249
  407. agno/app/playground/operator.py +0 -183
  408. agno/app/playground/schemas.py +0 -220
  409. agno/app/playground/serve.py +0 -55
  410. agno/app/playground/sync_router.py +0 -1042
  411. agno/app/playground/utils.py +0 -46
  412. agno/app/settings.py +0 -15
  413. agno/app/slack/__init__.py +0 -3
  414. agno/app/slack/app.py +0 -19
  415. agno/app/slack/sync_router.py +0 -92
  416. agno/app/utils.py +0 -54
  417. agno/app/whatsapp/__init__.py +0 -3
  418. agno/app/whatsapp/app.py +0 -15
  419. agno/app/whatsapp/sync_router.py +0 -197
  420. agno/cli/auth_server.py +0 -249
  421. agno/cli/config.py +0 -274
  422. agno/cli/console.py +0 -88
  423. agno/cli/credentials.py +0 -23
  424. agno/cli/entrypoint.py +0 -571
  425. agno/cli/operator.py +0 -357
  426. agno/cli/settings.py +0 -96
  427. agno/cli/ws/ws_cli.py +0 -817
  428. agno/constants.py +0 -13
  429. agno/document/__init__.py +0 -5
  430. agno/document/chunking/semantic.py +0 -45
  431. agno/document/chunking/strategy.py +0 -31
  432. agno/document/reader/__init__.py +0 -5
  433. agno/document/reader/base.py +0 -47
  434. agno/document/reader/docx_reader.py +0 -60
  435. agno/document/reader/gcs/pdf_reader.py +0 -44
  436. agno/document/reader/s3/pdf_reader.py +0 -59
  437. agno/document/reader/s3/text_reader.py +0 -63
  438. agno/document/reader/url_reader.py +0 -59
  439. agno/document/reader/youtube_reader.py +0 -58
  440. agno/embedder/__init__.py +0 -5
  441. agno/embedder/langdb.py +0 -80
  442. agno/embedder/mistral.py +0 -82
  443. agno/embedder/openai.py +0 -78
  444. agno/file/__init__.py +0 -5
  445. agno/file/file.py +0 -16
  446. agno/file/local/csv.py +0 -32
  447. agno/file/local/txt.py +0 -19
  448. agno/infra/app.py +0 -240
  449. agno/infra/base.py +0 -144
  450. agno/infra/context.py +0 -20
  451. agno/infra/db_app.py +0 -52
  452. agno/infra/resource.py +0 -205
  453. agno/infra/resources.py +0 -55
  454. agno/knowledge/agent.py +0 -698
  455. agno/knowledge/arxiv.py +0 -33
  456. agno/knowledge/combined.py +0 -36
  457. agno/knowledge/csv.py +0 -144
  458. agno/knowledge/csv_url.py +0 -124
  459. agno/knowledge/document.py +0 -223
  460. agno/knowledge/docx.py +0 -137
  461. agno/knowledge/firecrawl.py +0 -34
  462. agno/knowledge/gcs/__init__.py +0 -0
  463. agno/knowledge/gcs/base.py +0 -39
  464. agno/knowledge/gcs/pdf.py +0 -125
  465. agno/knowledge/json.py +0 -137
  466. agno/knowledge/langchain.py +0 -71
  467. agno/knowledge/light_rag.py +0 -273
  468. agno/knowledge/llamaindex.py +0 -66
  469. agno/knowledge/markdown.py +0 -154
  470. agno/knowledge/pdf.py +0 -164
  471. agno/knowledge/pdf_bytes.py +0 -42
  472. agno/knowledge/pdf_url.py +0 -148
  473. agno/knowledge/s3/__init__.py +0 -0
  474. agno/knowledge/s3/base.py +0 -64
  475. agno/knowledge/s3/pdf.py +0 -33
  476. agno/knowledge/s3/text.py +0 -34
  477. agno/knowledge/text.py +0 -141
  478. agno/knowledge/url.py +0 -46
  479. agno/knowledge/website.py +0 -179
  480. agno/knowledge/wikipedia.py +0 -32
  481. agno/knowledge/youtube.py +0 -35
  482. agno/memory/agent.py +0 -423
  483. agno/memory/classifier.py +0 -104
  484. agno/memory/db/__init__.py +0 -5
  485. agno/memory/db/base.py +0 -42
  486. agno/memory/db/mongodb.py +0 -189
  487. agno/memory/db/postgres.py +0 -203
  488. agno/memory/db/sqlite.py +0 -193
  489. agno/memory/memory.py +0 -22
  490. agno/memory/row.py +0 -36
  491. agno/memory/summarizer.py +0 -201
  492. agno/memory/summary.py +0 -19
  493. agno/memory/team.py +0 -415
  494. agno/memory/v2/__init__.py +0 -2
  495. agno/memory/v2/db/__init__.py +0 -1
  496. agno/memory/v2/db/base.py +0 -42
  497. agno/memory/v2/db/firestore.py +0 -339
  498. agno/memory/v2/db/mongodb.py +0 -196
  499. agno/memory/v2/db/postgres.py +0 -214
  500. agno/memory/v2/db/redis.py +0 -187
  501. agno/memory/v2/db/schema.py +0 -54
  502. agno/memory/v2/db/sqlite.py +0 -209
  503. agno/memory/v2/manager.py +0 -437
  504. agno/memory/v2/memory.py +0 -1097
  505. agno/memory/v2/schema.py +0 -55
  506. agno/memory/v2/summarizer.py +0 -215
  507. agno/memory/workflow.py +0 -38
  508. agno/models/ollama/tools.py +0 -430
  509. agno/models/qwen/__init__.py +0 -5
  510. agno/playground/__init__.py +0 -10
  511. agno/playground/deploy.py +0 -3
  512. agno/playground/playground.py +0 -3
  513. agno/playground/serve.py +0 -3
  514. agno/playground/settings.py +0 -3
  515. agno/reranker/__init__.py +0 -0
  516. agno/run/v2/__init__.py +0 -0
  517. agno/run/v2/workflow.py +0 -567
  518. agno/storage/__init__.py +0 -0
  519. agno/storage/agent/__init__.py +0 -0
  520. agno/storage/agent/dynamodb.py +0 -1
  521. agno/storage/agent/json.py +0 -1
  522. agno/storage/agent/mongodb.py +0 -1
  523. agno/storage/agent/postgres.py +0 -1
  524. agno/storage/agent/singlestore.py +0 -1
  525. agno/storage/agent/sqlite.py +0 -1
  526. agno/storage/agent/yaml.py +0 -1
  527. agno/storage/base.py +0 -60
  528. agno/storage/dynamodb.py +0 -673
  529. agno/storage/firestore.py +0 -297
  530. agno/storage/gcs_json.py +0 -261
  531. agno/storage/in_memory.py +0 -234
  532. agno/storage/json.py +0 -237
  533. agno/storage/mongodb.py +0 -328
  534. agno/storage/mysql.py +0 -685
  535. agno/storage/postgres.py +0 -682
  536. agno/storage/redis.py +0 -336
  537. agno/storage/session/__init__.py +0 -16
  538. agno/storage/session/agent.py +0 -64
  539. agno/storage/session/team.py +0 -63
  540. agno/storage/session/v2/__init__.py +0 -5
  541. agno/storage/session/workflow.py +0 -61
  542. agno/storage/singlestore.py +0 -606
  543. agno/storage/sqlite.py +0 -646
  544. agno/storage/workflow/__init__.py +0 -0
  545. agno/storage/workflow/mongodb.py +0 -1
  546. agno/storage/workflow/postgres.py +0 -1
  547. agno/storage/workflow/sqlite.py +0 -1
  548. agno/storage/yaml.py +0 -241
  549. agno/tools/thinking.py +0 -73
  550. agno/utils/defaults.py +0 -57
  551. agno/utils/filesystem.py +0 -39
  552. agno/utils/git.py +0 -52
  553. agno/utils/json_io.py +0 -30
  554. agno/utils/load_env.py +0 -19
  555. agno/utils/py_io.py +0 -19
  556. agno/utils/pyproject.py +0 -18
  557. agno/utils/resource_filter.py +0 -31
  558. agno/workflow/v2/__init__.py +0 -21
  559. agno/workflow/v2/types.py +0 -357
  560. agno/workflow/v2/workflow.py +0 -3312
  561. agno/workspace/__init__.py +0 -0
  562. agno/workspace/config.py +0 -325
  563. agno/workspace/enums.py +0 -6
  564. agno/workspace/helpers.py +0 -52
  565. agno/workspace/operator.py +0 -757
  566. agno/workspace/settings.py +0 -158
  567. agno-1.8.0.dist-info/METADATA +0 -979
  568. agno-1.8.0.dist-info/RECORD +0 -565
  569. agno-1.8.0.dist-info/entry_points.txt +0 -3
  570. /agno/{app → db/migrations}/__init__.py +0 -0
  571. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  572. /agno/{cli → integrations}/__init__.py +0 -0
  573. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  574. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  575. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  576. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  577. /agno/{app → os/interfaces}/slack/security.py +0 -0
  578. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  579. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  580. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  581. {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/WHEEL +0 -0
  582. {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
  583. {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/top_level.txt +0 -0
agno/storage/dynamodb.py DELETED
@@ -1,673 +0,0 @@
1
- import time
2
- from dataclasses import asdict
3
- from decimal import Decimal
4
- from typing import Any, Dict, List, Literal, Optional
5
-
6
- from agno.storage.base import Storage
7
- from agno.storage.session import Session
8
- from agno.storage.session.agent import AgentSession
9
- from agno.storage.session.team import TeamSession
10
- from agno.storage.session.v2.workflow import WorkflowSession as WorkflowSessionV2
11
- from agno.storage.session.workflow import WorkflowSession
12
- from agno.utils.log import log_debug, log_info, logger
13
-
14
- try:
15
- import boto3
16
- from boto3.dynamodb.conditions import Key
17
- from botocore.exceptions import ClientError
18
- except ImportError:
19
- raise ImportError("`boto3` not installed. Please install using `pip install boto3`.")
20
-
21
-
22
- class DynamoDbStorage(Storage):
23
- def __init__(
24
- self,
25
- table_name: str,
26
- profile_name: Optional[str] = None,
27
- region_name: Optional[str] = None,
28
- aws_access_key_id: Optional[str] = None,
29
- aws_secret_access_key: Optional[str] = None,
30
- endpoint_url: Optional[str] = None,
31
- create_table_if_not_exists: bool = True,
32
- mode: Optional[Literal["agent", "team", "workflow", "workflow_v2"]] = "agent",
33
- create_table_read_capacity_units: int = 5,
34
- create_table_write_capacity_units: int = 5,
35
- ):
36
- """
37
- Initialize the DynamoDbStorage.
38
-
39
- Args:
40
- table_name (str): The name of the DynamoDB table.
41
- profile_name (Optional[str]): AWS profile name to use for credentials.
42
- region_name (Optional[str]): AWS region name.
43
- aws_access_key_id (Optional[str]): AWS access key ID.
44
- aws_secret_access_key (Optional[str]): AWS secret access key.
45
- endpoint_url (Optional[str]): The complete URL to use for the constructed client.
46
- create_table_if_not_exists (bool): Whether to create the table if it does not exist.
47
- mode (Optional[Literal["agent", "team", "workflow", "workflow_v2"]]): The mode of the storage.
48
- create_table_read_capacity_units Optional[int]: Read capacity units for created table (default: 5).
49
- create_table_write_capacity_units Optional[int]: Write capacity units for created table (default: 5).
50
- """
51
- super().__init__(mode)
52
- self.table_name = table_name
53
- self.profile_name = profile_name
54
- self.region_name = region_name
55
- self.endpoint_url = endpoint_url
56
- self.aws_access_key_id = aws_access_key_id
57
- self.aws_secret_access_key = aws_secret_access_key
58
- self.create_table_if_not_exists = create_table_if_not_exists
59
- self.create_table_read_capacity_units = create_table_read_capacity_units
60
- self.create_table_write_capacity_units = create_table_write_capacity_units
61
-
62
- # Create session using profile name if provided
63
- if self.profile_name:
64
- session = boto3.Session(profile_name=self.profile_name)
65
- self.dynamodb = session.resource(
66
- "dynamodb",
67
- region_name=self.region_name,
68
- endpoint_url=self.endpoint_url,
69
- )
70
- else:
71
- # Initialize DynamoDB resource with default credentials
72
- self.dynamodb = boto3.resource(
73
- "dynamodb",
74
- aws_access_key_id=self.aws_access_key_id,
75
- aws_secret_access_key=self.aws_secret_access_key,
76
- region_name=self.region_name,
77
- endpoint_url=self.endpoint_url,
78
- )
79
-
80
- # Initialize table
81
- self.table = self.dynamodb.Table(self.table_name)
82
-
83
- # Optionally create table if it does not exist
84
- if self.create_table_if_not_exists:
85
- self.create()
86
- log_debug(f"Initialized DynamoDbStorage with table '{self.table_name}'")
87
-
88
- @property
89
- def mode(self) -> Literal["agent", "team", "workflow", "workflow_v2"]:
90
- """Get the mode of the storage."""
91
- return super().mode
92
-
93
- @mode.setter
94
- def mode(self, value: Optional[Literal["agent", "team", "workflow", "workflow_v2"]]) -> None:
95
- """Set the mode and refresh the table if mode changes."""
96
- super(DynamoDbStorage, type(self)).mode.fset(self, value) # type: ignore
97
- if value is not None:
98
- if self.create_table_if_not_exists:
99
- self.create()
100
-
101
- def create(self) -> None:
102
- """
103
- Create the DynamoDB table if it does not exist.
104
- """
105
- provisioned_throughput = {
106
- "ReadCapacityUnits": self.create_table_read_capacity_units,
107
- "WriteCapacityUnits": self.create_table_write_capacity_units,
108
- }
109
-
110
- try:
111
- # Check if table exists
112
- self.dynamodb.meta.client.describe_table(TableName=self.table_name)
113
- log_debug(f"Table '{self.table_name}' already exists.")
114
- except ClientError as e:
115
- if e.response["Error"]["Code"] == "ResourceNotFoundException":
116
- log_debug(f"Creating table '{self.table_name}'.")
117
-
118
- attribute_definitions = []
119
- if self.mode == "agent":
120
- attribute_definitions = [
121
- {"AttributeName": "session_id", "AttributeType": "S"},
122
- {"AttributeName": "user_id", "AttributeType": "S"},
123
- {"AttributeName": "agent_id", "AttributeType": "S"},
124
- {"AttributeName": "created_at", "AttributeType": "N"},
125
- ]
126
- elif self.mode == "team":
127
- attribute_definitions = [
128
- {"AttributeName": "session_id", "AttributeType": "S"},
129
- {"AttributeName": "user_id", "AttributeType": "S"},
130
- {"AttributeName": "team_id", "AttributeType": "S"},
131
- {"AttributeName": "created_at", "AttributeType": "N"},
132
- ]
133
- elif self.mode == "workflow":
134
- attribute_definitions = [
135
- {"AttributeName": "session_id", "AttributeType": "S"},
136
- {"AttributeName": "user_id", "AttributeType": "S"},
137
- {"AttributeName": "workflow_id", "AttributeType": "S"},
138
- {"AttributeName": "created_at", "AttributeType": "N"},
139
- ]
140
- elif self.mode == "workflow_v2":
141
- attribute_definitions = [
142
- {"AttributeName": "session_id", "AttributeType": "S"},
143
- {"AttributeName": "user_id", "AttributeType": "S"},
144
- {"AttributeName": "workflow_id", "AttributeType": "S"},
145
- {"AttributeName": "created_at", "AttributeType": "N"},
146
- ]
147
- secondary_indexes = [
148
- {
149
- "IndexName": "user_id-index",
150
- "KeySchema": [
151
- {"AttributeName": "user_id", "KeyType": "HASH"},
152
- {"AttributeName": "created_at", "KeyType": "RANGE"},
153
- ],
154
- "Projection": {"ProjectionType": "ALL"},
155
- "ProvisionedThroughput": provisioned_throughput,
156
- }
157
- ]
158
- if self.mode == "agent":
159
- secondary_indexes.append(
160
- {
161
- "IndexName": "agent_id-index",
162
- "KeySchema": [
163
- {"AttributeName": "agent_id", "KeyType": "HASH"},
164
- {"AttributeName": "created_at", "KeyType": "RANGE"},
165
- ],
166
- "Projection": {"ProjectionType": "ALL"},
167
- "ProvisionedThroughput": provisioned_throughput,
168
- }
169
- )
170
- elif self.mode == "team":
171
- secondary_indexes.append(
172
- {
173
- "IndexName": "team_id-index",
174
- "KeySchema": [
175
- {"AttributeName": "team_id", "KeyType": "HASH"},
176
- {"AttributeName": "created_at", "KeyType": "RANGE"},
177
- ],
178
- "Projection": {"ProjectionType": "ALL"},
179
- "ProvisionedThroughput": provisioned_throughput,
180
- }
181
- )
182
- elif self.mode == "workflow":
183
- secondary_indexes.append(
184
- {
185
- "IndexName": "workflow_id-index",
186
- "KeySchema": [
187
- {"AttributeName": "workflow_id", "KeyType": "HASH"},
188
- {"AttributeName": "created_at", "KeyType": "RANGE"},
189
- ],
190
- "Projection": {"ProjectionType": "ALL"},
191
- "ProvisionedThroughput": provisioned_throughput,
192
- }
193
- )
194
- elif self.mode == "workflow_v2":
195
- secondary_indexes.append(
196
- {
197
- "IndexName": "workflow_id-index",
198
- "KeySchema": [
199
- {"AttributeName": "workflow_id", "KeyType": "HASH"},
200
- {"AttributeName": "created_at", "KeyType": "RANGE"},
201
- ],
202
- "Projection": {"ProjectionType": "ALL"},
203
- "ProvisionedThroughput": provisioned_throughput,
204
- }
205
- )
206
- # Create the table
207
- self.table = self.dynamodb.create_table(
208
- TableName=self.table_name,
209
- KeySchema=[{"AttributeName": "session_id", "KeyType": "HASH"}],
210
- AttributeDefinitions=attribute_definitions,
211
- GlobalSecondaryIndexes=secondary_indexes,
212
- ProvisionedThroughput=provisioned_throughput,
213
- )
214
- # Wait until the table exists.
215
- self.table.wait_until_exists()
216
- log_debug(f"Table '{self.table_name}' created successfully.")
217
- else:
218
- logger.error(f"Unable to create table '{self.table_name}': {e.response['Error']['Message']}")
219
- except Exception as e:
220
- logger.error(f"Exception during table creation: {e}")
221
-
222
- def read(self, session_id: str, user_id: Optional[str] = None) -> Optional[Session]:
223
- """
224
- Read and return a Session from the database.
225
-
226
- Args:
227
- session_id (str): ID of the session to read.
228
- user_id (Optional[str]): User ID to filter by. Defaults to None.
229
-
230
- Returns:
231
- Optional[Session]: Session object if found, None otherwise.
232
- """
233
- try:
234
- key = {"session_id": session_id}
235
- if user_id is not None:
236
- key["user_id"] = user_id
237
-
238
- response = self.table.get_item(Key=key)
239
- item = response.get("Item", None)
240
- if item is not None:
241
- # Convert Decimal to int or float
242
- item = self._deserialize_item(item)
243
- if self.mode == "agent":
244
- return AgentSession.from_dict(item)
245
- elif self.mode == "team":
246
- return TeamSession.from_dict(item)
247
- elif self.mode == "workflow":
248
- return WorkflowSession.from_dict(item)
249
- elif self.mode == "workflow_v2":
250
- return WorkflowSessionV2.from_dict(item)
251
- except Exception as e:
252
- logger.error(f"Error reading session_id '{session_id}' with user_id '{user_id}': {e}")
253
- return None
254
-
255
- def get_all_session_ids(self, user_id: Optional[str] = None, entity_id: Optional[str] = None) -> List[str]:
256
- """
257
- Retrieve all session IDs, optionally filtered by user_id and/or entity_id.
258
-
259
- Args:
260
- user_id (Optional[str], optional): User ID to filter by. Defaults to None.
261
- entity_id (Optional[str], optional): Entity ID to filter by. Defaults to None.
262
-
263
- Returns:
264
- List[str]: List of session IDs matching the criteria.
265
- """
266
- session_ids: List[str] = []
267
- try:
268
- if user_id is not None:
269
- # Query using user_id index
270
- response = self.table.query(
271
- IndexName="user_id-index",
272
- KeyConditionExpression=Key("user_id").eq(user_id),
273
- ProjectionExpression="session_id",
274
- )
275
- items = response.get("Items", [])
276
- session_ids.extend([item["session_id"] for item in items if "session_id" in item])
277
- elif entity_id is not None:
278
- if self.mode == "agent":
279
- # Query using agent_id index
280
- response = self.table.query(
281
- IndexName="agent_id-index",
282
- KeyConditionExpression=Key("agent_id").eq(entity_id),
283
- ProjectionExpression="session_id",
284
- )
285
- elif self.mode == "team":
286
- # Query using team_id index
287
- response = self.table.query(
288
- IndexName="team_id-index",
289
- KeyConditionExpression=Key("team_id").eq(entity_id),
290
- ProjectionExpression="session_id",
291
- )
292
- elif self.mode == "workflow":
293
- # Query using workflow_id index
294
- response = self.table.query(
295
- IndexName="workflow_id-index",
296
- KeyConditionExpression=Key("workflow_id").eq(entity_id),
297
- ProjectionExpression="session_id",
298
- )
299
- items = response.get("Items", []) # type: ignore
300
- session_ids.extend([item["session_id"] for item in items if "session_id" in item])
301
- else:
302
- # Scan the whole table
303
- response = self.table.scan(ProjectionExpression="session_id")
304
- items = response.get("Items", [])
305
- session_ids.extend([item["session_id"] for item in items if "session_id" in item])
306
- except Exception as e:
307
- logger.error(f"Error retrieving session IDs: {e}")
308
- return session_ids
309
-
310
- def get_all_sessions(self, user_id: Optional[str] = None, entity_id: Optional[str] = None) -> List[Session]:
311
- """
312
- Retrieve all sessions, optionally filtered by user_id and/or entity_id.
313
-
314
- Args:
315
- user_id (Optional[str], optional): User ID to filter by. Defaults to None.
316
- entity_id (Optional[str], optional): Entity ID to filter by. Defaults to None.
317
-
318
- Returns:
319
- List[Session]: List of AgentSession or WorkflowSession objects matching the criteria.
320
- """
321
- sessions: List[Session] = []
322
- try:
323
- if user_id is not None:
324
- if self.mode == "agent":
325
- # Query using user_id index
326
- response = self.table.query(
327
- IndexName="user_id-index",
328
- KeyConditionExpression=Key("user_id").eq(user_id),
329
- ProjectionExpression="session_id, agent_id, user_id, team_session_id, memory, agent_data, session_data, extra_data, created_at, updated_at",
330
- )
331
- elif self.mode == "team":
332
- # Query using user_id index
333
- response = self.table.query(
334
- IndexName="user_id-index",
335
- KeyConditionExpression=Key("user_id").eq(user_id),
336
- ProjectionExpression="session_id, team_id, user_id, team_session_id, memory, team_data, session_data, extra_data, created_at, updated_at",
337
- )
338
- elif self.mode == "workflow":
339
- # Query using user_id index
340
- response = self.table.query(
341
- IndexName="user_id-index",
342
- KeyConditionExpression=Key("user_id").eq(user_id),
343
- ProjectionExpression="session_id, workflow_id, user_id, memory, workflow_data, session_data, extra_data, created_at, updated_at",
344
- )
345
- elif self.mode == "workflow_v2":
346
- # Query using user_id index
347
- response = self.table.query(
348
- IndexName="user_id-index",
349
- KeyConditionExpression=Key("user_id").eq(user_id),
350
- ProjectionExpression="session_id, workflow_id, user_id, workflow_name, runs, workflow_data, session_data, extra_data, created_at, updated_at",
351
- )
352
- items = response.get("Items", []) # type: ignore
353
- for item in items:
354
- item = self._deserialize_item(item)
355
- _session: Optional[Session] = None
356
- if self.mode == "agent":
357
- _session = AgentSession.from_dict(item)
358
- else:
359
- _session = WorkflowSession.from_dict(item) # type: ignore
360
- if _session is not None:
361
- sessions.append(_session)
362
- elif entity_id is not None:
363
- if self.mode == "agent":
364
- # Query using agent_id index
365
- response = self.table.query(
366
- IndexName="agent_id-index",
367
- KeyConditionExpression=Key("agent_id").eq(entity_id),
368
- ProjectionExpression="session_id, agent_id, user_id, team_session_id, memory, agent_data, session_data, extra_data, created_at, updated_at",
369
- )
370
- elif self.mode == "team":
371
- # Query using team_id index
372
- response = self.table.query(
373
- IndexName="team_id-index",
374
- KeyConditionExpression=Key("team_id").eq(entity_id),
375
- ProjectionExpression="session_id, team_id, user_id, team_session_id, memory, team_data, session_data, extra_data, created_at, updated_at",
376
- )
377
- elif self.mode == "workflow":
378
- # Query using workflow_id index
379
- response = self.table.query(
380
- IndexName="workflow_id-index",
381
- KeyConditionExpression=Key("workflow_id").eq(entity_id),
382
- ProjectionExpression="session_id, workflow_id, user_id, memory, workflow_data, session_data, extra_data, created_at, updated_at",
383
- )
384
- elif self.mode == "workflow_v2":
385
- # Query using workflow_id index
386
- response = self.table.query(
387
- IndexName="workflow_id-index",
388
- KeyConditionExpression=Key("workflow_id").eq(entity_id),
389
- ProjectionExpression="session_id, workflow_id, user_id, workflow_name, runs, workflow_data, session_data, extra_data, created_at, updated_at",
390
- )
391
- items = response.get("Items", []) # type: ignore
392
- for item in items:
393
- item = self._deserialize_item(item)
394
- if self.mode == "agent":
395
- _session = AgentSession.from_dict(item) # type: ignore
396
- else:
397
- _session = WorkflowSession.from_dict(item) # type: ignore
398
- if _session is not None:
399
- sessions.append(_session)
400
- else:
401
- # Scan the whole table
402
- if self.mode == "agent":
403
- response = self.table.scan(
404
- ProjectionExpression="session_id, agent_id, user_id, team_session_id, memory, agent_data, session_data, extra_data, created_at, updated_at"
405
- )
406
- elif self.mode == "team":
407
- response = self.table.scan(
408
- ProjectionExpression="session_id, team_id, user_id, team_session_id, memory, team_data, session_data, extra_data, created_at, updated_at"
409
- )
410
- elif self.mode == "workflow":
411
- response = self.table.scan(
412
- ProjectionExpression="session_id, workflow_id, user_id, memory, workflow_data, session_data, extra_data, created_at, updated_at"
413
- )
414
- elif self.mode == "workflow_v2":
415
- response = self.table.scan(
416
- ProjectionExpression="session_id, workflow_id, user_id, workflow_name, runs, workflow_data, session_data, extra_data, created_at, updated_at"
417
- )
418
- items = response.get("Items", [])
419
- for item in items:
420
- item = self._deserialize_item(item)
421
- if self.mode == "agent":
422
- _session = AgentSession.from_dict(item) # type: ignore
423
- elif self.mode == "team":
424
- _session = TeamSession.from_dict(item) # type: ignore
425
- else:
426
- _session = WorkflowSession.from_dict(item) # type: ignore
427
- if _session is not None:
428
- sessions.append(_session)
429
- except Exception as e:
430
- logger.error(f"Error retrieving sessions: {e}")
431
- return sessions
432
-
433
- def get_recent_sessions(
434
- self,
435
- user_id: Optional[str] = None,
436
- entity_id: Optional[str] = None,
437
- limit: Optional[int] = 2,
438
- ) -> List[Session]:
439
- """Get the last N sessions, ordered by created_at descending.
440
-
441
- Args:
442
- num_history_sessions: Number of most recent sessions to return
443
- user_id: Filter by user ID
444
- entity_id: Filter by entity ID (agent_id, team_id, or workflow_id)
445
-
446
- Returns:
447
- List[Session]: List of most recent sessions
448
- """
449
- sessions: List[Session] = []
450
- try:
451
- if user_id is not None:
452
- if self.mode == "agent":
453
- response = self.table.query(
454
- IndexName="user_id-index",
455
- KeyConditionExpression=Key("user_id").eq(user_id),
456
- ProjectionExpression="session_id, agent_id, user_id, team_session_id, memory, agent_data, session_data, extra_data, created_at, updated_at",
457
- ScanIndexForward=False,
458
- Limit=limit if limit is not None else None,
459
- )
460
- elif self.mode == "team":
461
- response = self.table.query(
462
- IndexName="user_id-index",
463
- KeyConditionExpression=Key("user_id").eq(user_id),
464
- ProjectionExpression="session_id, team_id, user_id, team_session_id, memory, team_data, session_data, extra_data, created_at, updated_at",
465
- ScanIndexForward=False,
466
- Limit=limit if limit is not None else None,
467
- )
468
- elif self.mode == "workflow":
469
- response = self.table.query(
470
- IndexName="user_id-index",
471
- KeyConditionExpression=Key("user_id").eq(user_id),
472
- ProjectionExpression="session_id, workflow_id, user_id, memory, workflow_data, session_data, extra_data, created_at, updated_at",
473
- ScanIndexForward=False,
474
- Limit=limit if limit is not None else None,
475
- )
476
- elif self.mode == "workflow_v2":
477
- response = self.table.query(
478
- IndexName="user_id-index",
479
- KeyConditionExpression=Key("user_id").eq(user_id),
480
- ProjectionExpression="session_id, workflow_id, user_id, workflow_name, runs, workflow_data, session_data, extra_data, created_at, updated_at",
481
- ScanIndexForward=False,
482
- Limit=limit if limit is not None else None,
483
- )
484
- elif entity_id is not None:
485
- if self.mode == "agent":
486
- response = self.table.query(
487
- IndexName="agent_id-index",
488
- KeyConditionExpression=Key("agent_id").eq(entity_id),
489
- ProjectionExpression="session_id, agent_id, user_id, team_session_id, memory, agent_data, session_data, extra_data, created_at, updated_at",
490
- ScanIndexForward=False,
491
- Limit=limit if limit is not None else None,
492
- )
493
- elif self.mode == "team":
494
- response = self.table.query(
495
- IndexName="team_id-index",
496
- KeyConditionExpression=Key("team_id").eq(entity_id),
497
- ProjectionExpression="session_id, team_id, user_id, team_session_id, memory, team_data, session_data, extra_data, created_at, updated_at",
498
- ScanIndexForward=False,
499
- Limit=limit if limit is not None else None,
500
- )
501
- elif self.mode == "workflow":
502
- response = self.table.query(
503
- IndexName="workflow_id-index",
504
- KeyConditionExpression=Key("workflow_id").eq(entity_id),
505
- ProjectionExpression="session_id, workflow_id, user_id, memory, workflow_data, session_data, extra_data, created_at, updated_at",
506
- ScanIndexForward=False,
507
- Limit=limit if limit is not None else None,
508
- )
509
- elif self.mode == "workflow_v2":
510
- response = self.table.query(
511
- IndexName="workflow_id-index",
512
- KeyConditionExpression=Key("workflow_id").eq(entity_id),
513
- ProjectionExpression="session_id, workflow_id, user_id, workflow_name, runs, workflow_data, session_data, extra_data, created_at, updated_at",
514
- ScanIndexForward=False,
515
- Limit=limit if limit is not None else None,
516
- )
517
- else:
518
- # If no filters, scan the table and sort by created_at
519
- if self.mode == "agent":
520
- response = self.table.scan(
521
- ProjectionExpression="session_id, agent_id, user_id, team_session_id, memory, agent_data, session_data, extra_data, created_at, updated_at",
522
- Limit=limit if limit is not None else None,
523
- )
524
- elif self.mode == "team":
525
- response = self.table.scan(
526
- ProjectionExpression="session_id, team_id, user_id, team_session_id, memory, team_data, session_data, extra_data, created_at, updated_at",
527
- Limit=limit if limit is not None else None,
528
- )
529
- elif self.mode == "workflow":
530
- response = self.table.scan(
531
- ProjectionExpression="session_id, workflow_id, user_id, memory, workflow_data, session_data, extra_data, created_at, updated_at",
532
- Limit=limit if limit is not None else None,
533
- )
534
- elif self.mode == "workflow_v2":
535
- response = self.table.scan(
536
- ProjectionExpression="session_id, workflow_id, user_id, workflow_name, runs, workflow_data, session_data, extra_data, created_at, updated_at",
537
- Limit=limit if limit is not None else None,
538
- )
539
- items = response.get("Items", [])
540
- for item in items:
541
- item = self._deserialize_item(item)
542
- session: Optional[Session] = None
543
-
544
- if self.mode == "agent":
545
- session = AgentSession.from_dict(item)
546
- elif self.mode == "team":
547
- session = TeamSession.from_dict(item)
548
- elif self.mode == "workflow":
549
- session = WorkflowSession.from_dict(item)
550
- elif self.mode == "workflow_v2":
551
- session = WorkflowSessionV2.from_dict(item)
552
- if session is not None:
553
- sessions.append(session)
554
-
555
- except Exception as e:
556
- logger.error(f"Error getting last {limit} sessions: {e}")
557
-
558
- return sessions
559
-
560
- def upsert(self, session: Session) -> Optional[Session]:
561
- """
562
- Create or update a Session in the database.
563
-
564
- Args:
565
- session (Session): The session data to upsert.
566
-
567
- Returns:
568
- Optional[Session]: The upserted Session, or None if operation failed.
569
- """
570
- try:
571
- if self.mode == "workflow_v2":
572
- item = session.to_dict()
573
- else:
574
- item = asdict(session)
575
-
576
- # Add timestamps
577
- current_time = int(time.time())
578
- if "created_at" not in item or item["created_at"] is None:
579
- item["created_at"] = current_time
580
- item["updated_at"] = current_time
581
-
582
- # Convert data to DynamoDB compatible format
583
- item = self._serialize_item(item)
584
-
585
- # Put item into DynamoDB
586
- self.table.put_item(Item=item)
587
- return self.read(session.session_id)
588
- except Exception as e:
589
- logger.error(f"Error upserting session: {e}")
590
- return None
591
-
592
- def delete_session(self, session_id: Optional[str] = None):
593
- """
594
- Delete a session from the database.
595
-
596
- Args:
597
- session_id (Optional[str], optional): ID of the session to delete. Defaults to None.
598
- """
599
- if session_id is None:
600
- logger.warning("No session_id provided for deletion.")
601
- return
602
- try:
603
- self.table.delete_item(Key={"session_id": session_id})
604
- log_info(f"Successfully deleted session with session_id: {session_id}")
605
- except Exception as e:
606
- logger.error(f"Error deleting session: {e}")
607
-
608
- def drop(self) -> None:
609
- """
610
- Drop the table from the database if it exists.
611
- """
612
- try:
613
- self.table.delete()
614
- self.table.wait_until_not_exists()
615
- log_debug(f"Table '{self.table_name}' deleted successfully.")
616
- except Exception as e:
617
- logger.error(f"Error deleting table '{self.table_name}': {e}")
618
-
619
- def upgrade_schema(self) -> None:
620
- """
621
- Upgrade the schema to the latest version.
622
- This method is currently a placeholder and does not perform any actions.
623
- """
624
- pass
625
-
626
- def _serialize_item(self, item: Dict[str, Any]) -> Dict[str, Any]:
627
- """
628
- Serialize item to be compatible with DynamoDB.
629
-
630
- Args:
631
- item (Dict[str, Any]): The item to serialize.
632
-
633
- Returns:
634
- Dict[str, Any]: The serialized item.
635
- """
636
-
637
- def serialize_value(value):
638
- if isinstance(value, float):
639
- return Decimal(str(value))
640
- elif isinstance(value, dict):
641
- return {k: serialize_value(v) for k, v in value.items()}
642
- elif isinstance(value, list):
643
- return [serialize_value(v) for v in value]
644
- else:
645
- return value
646
-
647
- return {k: serialize_value(v) for k, v in item.items() if v is not None}
648
-
649
- def _deserialize_item(self, item: Dict[str, Any]) -> Dict[str, Any]:
650
- """
651
- Deserialize item from DynamoDB format.
652
-
653
- Args:
654
- item (Dict[str, Any]): The item to deserialize.
655
-
656
- Returns:
657
- Dict[str, Any]: The deserialized item.
658
- """
659
-
660
- def deserialize_value(value):
661
- if isinstance(value, Decimal):
662
- if value % 1 == 0:
663
- return int(value)
664
- else:
665
- return float(value)
666
- elif isinstance(value, dict):
667
- return {k: deserialize_value(v) for k, v in value.items()}
668
- elif isinstance(value, list):
669
- return [deserialize_value(v) for v in value]
670
- else:
671
- return value
672
-
673
- return {k: deserialize_value(v) for k, v in item.items()}