agno 1.8.1__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 (580) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +2778 -4123
  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/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 +129 -82
  141. agno/models/aws/bedrock.py +107 -175
  142. agno/models/aws/claude.py +64 -18
  143. agno/models/azure/ai_foundry.py +73 -23
  144. agno/models/base.py +347 -287
  145. agno/models/cerebras/cerebras.py +84 -27
  146. agno/models/cohere/chat.py +106 -98
  147. agno/models/google/gemini.py +100 -42
  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 +38 -144
  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 +84 -46
  158. agno/models/openai/chat.py +121 -23
  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 +14 -8
  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 +393 -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 +65 -28
  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 +33 -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 +30 -0
  184. agno/os/router.py +843 -0
  185. agno/os/routers/__init__.py +3 -0
  186. agno/os/routers/evals/__init__.py +3 -0
  187. agno/os/routers/evals/evals.py +204 -0
  188. agno/os/routers/evals/schemas.py +142 -0
  189. agno/os/routers/evals/utils.py +161 -0
  190. agno/os/routers/knowledge/__init__.py +3 -0
  191. agno/os/routers/knowledge/knowledge.py +413 -0
  192. agno/os/routers/knowledge/schemas.py +118 -0
  193. agno/os/routers/memory/__init__.py +3 -0
  194. agno/os/routers/memory/memory.py +179 -0
  195. agno/os/routers/memory/schemas.py +58 -0
  196. agno/os/routers/metrics/__init__.py +3 -0
  197. agno/os/routers/metrics/metrics.py +58 -0
  198. agno/os/routers/metrics/schemas.py +47 -0
  199. agno/os/routers/session/__init__.py +3 -0
  200. agno/os/routers/session/session.py +163 -0
  201. agno/os/schema.py +892 -0
  202. agno/{app/playground → os}/settings.py +8 -15
  203. agno/os/utils.py +270 -0
  204. agno/reasoning/azure_ai_foundry.py +4 -4
  205. agno/reasoning/deepseek.py +4 -4
  206. agno/reasoning/default.py +6 -11
  207. agno/reasoning/groq.py +4 -4
  208. agno/reasoning/helpers.py +4 -6
  209. agno/reasoning/ollama.py +4 -4
  210. agno/reasoning/openai.py +4 -4
  211. agno/run/{response.py → agent.py} +144 -72
  212. agno/run/base.py +44 -58
  213. agno/run/cancel.py +83 -0
  214. agno/run/team.py +133 -77
  215. agno/run/workflow.py +537 -12
  216. agno/session/__init__.py +10 -0
  217. agno/session/agent.py +244 -0
  218. agno/session/summary.py +225 -0
  219. agno/session/team.py +262 -0
  220. agno/{storage/session/v2 → session}/workflow.py +47 -24
  221. agno/team/__init__.py +15 -16
  222. agno/team/team.py +2961 -4253
  223. agno/tools/agentql.py +14 -5
  224. agno/tools/airflow.py +9 -4
  225. agno/tools/api.py +7 -3
  226. agno/tools/apify.py +2 -46
  227. agno/tools/arxiv.py +8 -3
  228. agno/tools/aws_lambda.py +7 -5
  229. agno/tools/aws_ses.py +7 -1
  230. agno/tools/baidusearch.py +4 -1
  231. agno/tools/bitbucket.py +4 -4
  232. agno/tools/brandfetch.py +14 -11
  233. agno/tools/bravesearch.py +4 -1
  234. agno/tools/brightdata.py +42 -22
  235. agno/tools/browserbase.py +13 -4
  236. agno/tools/calcom.py +12 -10
  237. agno/tools/calculator.py +10 -27
  238. agno/tools/cartesia.py +18 -13
  239. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  240. agno/tools/confluence.py +8 -8
  241. agno/tools/crawl4ai.py +7 -1
  242. agno/tools/csv_toolkit.py +9 -8
  243. agno/tools/dalle.py +18 -11
  244. agno/tools/daytona.py +13 -16
  245. agno/tools/decorator.py +6 -3
  246. agno/tools/desi_vocal.py +16 -7
  247. agno/tools/discord.py +11 -8
  248. agno/tools/docker.py +30 -42
  249. agno/tools/duckdb.py +34 -53
  250. agno/tools/duckduckgo.py +8 -7
  251. agno/tools/e2b.py +61 -61
  252. agno/tools/eleven_labs.py +35 -28
  253. agno/tools/email.py +4 -1
  254. agno/tools/evm.py +7 -1
  255. agno/tools/exa.py +19 -14
  256. agno/tools/fal.py +29 -29
  257. agno/tools/file.py +9 -8
  258. agno/tools/financial_datasets.py +25 -44
  259. agno/tools/firecrawl.py +22 -22
  260. agno/tools/function.py +68 -17
  261. agno/tools/giphy.py +22 -10
  262. agno/tools/github.py +48 -126
  263. agno/tools/gmail.py +45 -61
  264. agno/tools/google_bigquery.py +7 -6
  265. agno/tools/google_maps.py +11 -26
  266. agno/tools/googlesearch.py +7 -2
  267. agno/tools/googlesheets.py +21 -17
  268. agno/tools/hackernews.py +9 -5
  269. agno/tools/jina.py +5 -4
  270. agno/tools/jira.py +18 -9
  271. agno/tools/knowledge.py +31 -32
  272. agno/tools/linear.py +18 -33
  273. agno/tools/linkup.py +5 -1
  274. agno/tools/local_file_system.py +8 -5
  275. agno/tools/lumalab.py +31 -19
  276. agno/tools/mem0.py +18 -12
  277. agno/tools/memori.py +14 -10
  278. agno/tools/mlx_transcribe.py +3 -2
  279. agno/tools/models/azure_openai.py +32 -14
  280. agno/tools/models/gemini.py +58 -31
  281. agno/tools/models/groq.py +29 -20
  282. agno/tools/models/nebius.py +27 -11
  283. agno/tools/models_labs.py +39 -15
  284. agno/tools/moviepy_video.py +7 -6
  285. agno/tools/neo4j.py +10 -8
  286. agno/tools/newspaper.py +7 -2
  287. agno/tools/newspaper4k.py +8 -3
  288. agno/tools/openai.py +57 -26
  289. agno/tools/openbb.py +12 -11
  290. agno/tools/opencv.py +62 -46
  291. agno/tools/openweather.py +14 -12
  292. agno/tools/pandas.py +11 -3
  293. agno/tools/postgres.py +4 -12
  294. agno/tools/pubmed.py +4 -1
  295. agno/tools/python.py +9 -22
  296. agno/tools/reasoning.py +35 -27
  297. agno/tools/reddit.py +11 -26
  298. agno/tools/replicate.py +54 -41
  299. agno/tools/resend.py +4 -1
  300. agno/tools/scrapegraph.py +15 -14
  301. agno/tools/searxng.py +10 -23
  302. agno/tools/serpapi.py +6 -3
  303. agno/tools/serper.py +13 -4
  304. agno/tools/shell.py +9 -2
  305. agno/tools/slack.py +12 -11
  306. agno/tools/sleep.py +3 -2
  307. agno/tools/spider.py +24 -4
  308. agno/tools/sql.py +7 -6
  309. agno/tools/tavily.py +6 -4
  310. agno/tools/telegram.py +12 -4
  311. agno/tools/todoist.py +11 -31
  312. agno/tools/toolkit.py +1 -1
  313. agno/tools/trafilatura.py +22 -6
  314. agno/tools/trello.py +9 -22
  315. agno/tools/twilio.py +10 -3
  316. agno/tools/user_control_flow.py +6 -1
  317. agno/tools/valyu.py +34 -5
  318. agno/tools/visualization.py +19 -28
  319. agno/tools/webbrowser.py +4 -3
  320. agno/tools/webex.py +11 -7
  321. agno/tools/website.py +15 -46
  322. agno/tools/webtools.py +12 -4
  323. agno/tools/whatsapp.py +5 -9
  324. agno/tools/wikipedia.py +20 -13
  325. agno/tools/x.py +14 -13
  326. agno/tools/yfinance.py +13 -40
  327. agno/tools/youtube.py +26 -20
  328. agno/tools/zendesk.py +7 -2
  329. agno/tools/zep.py +10 -7
  330. agno/tools/zoom.py +10 -9
  331. agno/utils/common.py +1 -19
  332. agno/utils/events.py +95 -118
  333. agno/utils/knowledge.py +29 -0
  334. agno/utils/log.py +2 -2
  335. agno/utils/mcp.py +11 -5
  336. agno/utils/media.py +39 -0
  337. agno/utils/message.py +12 -1
  338. agno/utils/models/claude.py +6 -4
  339. agno/utils/models/mistral.py +8 -7
  340. agno/utils/models/schema_utils.py +3 -3
  341. agno/utils/pprint.py +33 -32
  342. agno/utils/print_response/agent.py +779 -0
  343. agno/utils/print_response/team.py +1565 -0
  344. agno/utils/print_response/workflow.py +1451 -0
  345. agno/utils/prompts.py +14 -14
  346. agno/utils/reasoning.py +87 -0
  347. agno/utils/response.py +42 -42
  348. agno/utils/string.py +8 -22
  349. agno/utils/team.py +50 -0
  350. agno/utils/timer.py +2 -2
  351. agno/vectordb/base.py +33 -21
  352. agno/vectordb/cassandra/cassandra.py +287 -23
  353. agno/vectordb/chroma/chromadb.py +482 -59
  354. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  355. agno/vectordb/couchbase/couchbase.py +309 -29
  356. agno/vectordb/lancedb/lance_db.py +360 -21
  357. agno/vectordb/langchaindb/__init__.py +5 -0
  358. agno/vectordb/langchaindb/langchaindb.py +145 -0
  359. agno/vectordb/lightrag/__init__.py +5 -0
  360. agno/vectordb/lightrag/lightrag.py +374 -0
  361. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  362. agno/vectordb/milvus/milvus.py +242 -32
  363. agno/vectordb/mongodb/mongodb.py +200 -24
  364. agno/vectordb/pgvector/pgvector.py +319 -37
  365. agno/vectordb/pineconedb/pineconedb.py +221 -27
  366. agno/vectordb/qdrant/qdrant.py +334 -14
  367. agno/vectordb/singlestore/singlestore.py +286 -29
  368. agno/vectordb/surrealdb/surrealdb.py +187 -7
  369. agno/vectordb/upstashdb/upstashdb.py +342 -26
  370. agno/vectordb/weaviate/weaviate.py +227 -165
  371. agno/workflow/__init__.py +17 -13
  372. agno/workflow/{v2/condition.py → condition.py} +135 -32
  373. agno/workflow/{v2/loop.py → loop.py} +115 -28
  374. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  375. agno/workflow/{v2/router.py → router.py} +133 -32
  376. agno/workflow/{v2/step.py → step.py} +200 -42
  377. agno/workflow/{v2/steps.py → steps.py} +147 -66
  378. agno/workflow/types.py +482 -0
  379. agno/workflow/workflow.py +2394 -696
  380. agno-2.0.0a1.dist-info/METADATA +355 -0
  381. agno-2.0.0a1.dist-info/RECORD +514 -0
  382. agno/agent/metrics.py +0 -107
  383. agno/api/app.py +0 -35
  384. agno/api/playground.py +0 -92
  385. agno/api/schemas/app.py +0 -12
  386. agno/api/schemas/playground.py +0 -22
  387. agno/api/schemas/user.py +0 -35
  388. agno/api/schemas/workspace.py +0 -46
  389. agno/api/user.py +0 -160
  390. agno/api/workflows.py +0 -33
  391. agno/api/workspace.py +0 -175
  392. agno/app/agui/__init__.py +0 -3
  393. agno/app/agui/app.py +0 -17
  394. agno/app/agui/sync_router.py +0 -120
  395. agno/app/base.py +0 -186
  396. agno/app/discord/__init__.py +0 -3
  397. agno/app/fastapi/__init__.py +0 -3
  398. agno/app/fastapi/app.py +0 -107
  399. agno/app/fastapi/async_router.py +0 -457
  400. agno/app/fastapi/sync_router.py +0 -448
  401. agno/app/playground/app.py +0 -228
  402. agno/app/playground/async_router.py +0 -1050
  403. agno/app/playground/deploy.py +0 -249
  404. agno/app/playground/operator.py +0 -183
  405. agno/app/playground/schemas.py +0 -220
  406. agno/app/playground/serve.py +0 -55
  407. agno/app/playground/sync_router.py +0 -1042
  408. agno/app/playground/utils.py +0 -46
  409. agno/app/settings.py +0 -15
  410. agno/app/slack/__init__.py +0 -3
  411. agno/app/slack/app.py +0 -19
  412. agno/app/slack/sync_router.py +0 -92
  413. agno/app/utils.py +0 -54
  414. agno/app/whatsapp/__init__.py +0 -3
  415. agno/app/whatsapp/app.py +0 -15
  416. agno/app/whatsapp/sync_router.py +0 -197
  417. agno/cli/auth_server.py +0 -249
  418. agno/cli/config.py +0 -274
  419. agno/cli/console.py +0 -88
  420. agno/cli/credentials.py +0 -23
  421. agno/cli/entrypoint.py +0 -571
  422. agno/cli/operator.py +0 -357
  423. agno/cli/settings.py +0 -96
  424. agno/cli/ws/ws_cli.py +0 -817
  425. agno/constants.py +0 -13
  426. agno/document/__init__.py +0 -5
  427. agno/document/chunking/semantic.py +0 -45
  428. agno/document/chunking/strategy.py +0 -31
  429. agno/document/reader/__init__.py +0 -5
  430. agno/document/reader/base.py +0 -47
  431. agno/document/reader/docx_reader.py +0 -60
  432. agno/document/reader/gcs/pdf_reader.py +0 -44
  433. agno/document/reader/s3/pdf_reader.py +0 -59
  434. agno/document/reader/s3/text_reader.py +0 -63
  435. agno/document/reader/url_reader.py +0 -59
  436. agno/document/reader/youtube_reader.py +0 -58
  437. agno/embedder/__init__.py +0 -5
  438. agno/embedder/langdb.py +0 -80
  439. agno/embedder/mistral.py +0 -82
  440. agno/embedder/openai.py +0 -78
  441. agno/file/__init__.py +0 -5
  442. agno/file/file.py +0 -16
  443. agno/file/local/csv.py +0 -32
  444. agno/file/local/txt.py +0 -19
  445. agno/infra/app.py +0 -240
  446. agno/infra/base.py +0 -144
  447. agno/infra/context.py +0 -20
  448. agno/infra/db_app.py +0 -52
  449. agno/infra/resource.py +0 -205
  450. agno/infra/resources.py +0 -55
  451. agno/knowledge/agent.py +0 -702
  452. agno/knowledge/arxiv.py +0 -33
  453. agno/knowledge/combined.py +0 -36
  454. agno/knowledge/csv.py +0 -144
  455. agno/knowledge/csv_url.py +0 -124
  456. agno/knowledge/document.py +0 -223
  457. agno/knowledge/docx.py +0 -137
  458. agno/knowledge/firecrawl.py +0 -34
  459. agno/knowledge/gcs/__init__.py +0 -0
  460. agno/knowledge/gcs/base.py +0 -39
  461. agno/knowledge/gcs/pdf.py +0 -125
  462. agno/knowledge/json.py +0 -137
  463. agno/knowledge/langchain.py +0 -71
  464. agno/knowledge/light_rag.py +0 -273
  465. agno/knowledge/llamaindex.py +0 -66
  466. agno/knowledge/markdown.py +0 -154
  467. agno/knowledge/pdf.py +0 -164
  468. agno/knowledge/pdf_bytes.py +0 -42
  469. agno/knowledge/pdf_url.py +0 -148
  470. agno/knowledge/s3/__init__.py +0 -0
  471. agno/knowledge/s3/base.py +0 -64
  472. agno/knowledge/s3/pdf.py +0 -33
  473. agno/knowledge/s3/text.py +0 -34
  474. agno/knowledge/text.py +0 -141
  475. agno/knowledge/url.py +0 -46
  476. agno/knowledge/website.py +0 -179
  477. agno/knowledge/wikipedia.py +0 -32
  478. agno/knowledge/youtube.py +0 -35
  479. agno/memory/agent.py +0 -423
  480. agno/memory/classifier.py +0 -104
  481. agno/memory/db/__init__.py +0 -5
  482. agno/memory/db/base.py +0 -42
  483. agno/memory/db/mongodb.py +0 -189
  484. agno/memory/db/postgres.py +0 -203
  485. agno/memory/db/sqlite.py +0 -193
  486. agno/memory/memory.py +0 -22
  487. agno/memory/row.py +0 -36
  488. agno/memory/summarizer.py +0 -201
  489. agno/memory/summary.py +0 -19
  490. agno/memory/team.py +0 -415
  491. agno/memory/v2/__init__.py +0 -2
  492. agno/memory/v2/db/__init__.py +0 -1
  493. agno/memory/v2/db/base.py +0 -42
  494. agno/memory/v2/db/firestore.py +0 -339
  495. agno/memory/v2/db/mongodb.py +0 -196
  496. agno/memory/v2/db/postgres.py +0 -214
  497. agno/memory/v2/db/redis.py +0 -187
  498. agno/memory/v2/db/schema.py +0 -54
  499. agno/memory/v2/db/sqlite.py +0 -209
  500. agno/memory/v2/manager.py +0 -437
  501. agno/memory/v2/memory.py +0 -1097
  502. agno/memory/v2/schema.py +0 -55
  503. agno/memory/v2/summarizer.py +0 -215
  504. agno/memory/workflow.py +0 -38
  505. agno/models/ollama/tools.py +0 -430
  506. agno/models/qwen/__init__.py +0 -5
  507. agno/playground/__init__.py +0 -10
  508. agno/playground/deploy.py +0 -3
  509. agno/playground/playground.py +0 -3
  510. agno/playground/serve.py +0 -3
  511. agno/playground/settings.py +0 -3
  512. agno/reranker/__init__.py +0 -0
  513. agno/run/v2/__init__.py +0 -0
  514. agno/run/v2/workflow.py +0 -567
  515. agno/storage/__init__.py +0 -0
  516. agno/storage/agent/__init__.py +0 -0
  517. agno/storage/agent/dynamodb.py +0 -1
  518. agno/storage/agent/json.py +0 -1
  519. agno/storage/agent/mongodb.py +0 -1
  520. agno/storage/agent/postgres.py +0 -1
  521. agno/storage/agent/singlestore.py +0 -1
  522. agno/storage/agent/sqlite.py +0 -1
  523. agno/storage/agent/yaml.py +0 -1
  524. agno/storage/base.py +0 -60
  525. agno/storage/dynamodb.py +0 -673
  526. agno/storage/firestore.py +0 -297
  527. agno/storage/gcs_json.py +0 -261
  528. agno/storage/in_memory.py +0 -234
  529. agno/storage/json.py +0 -237
  530. agno/storage/mongodb.py +0 -328
  531. agno/storage/mysql.py +0 -685
  532. agno/storage/postgres.py +0 -682
  533. agno/storage/redis.py +0 -336
  534. agno/storage/session/__init__.py +0 -16
  535. agno/storage/session/agent.py +0 -64
  536. agno/storage/session/team.py +0 -63
  537. agno/storage/session/v2/__init__.py +0 -5
  538. agno/storage/session/workflow.py +0 -61
  539. agno/storage/singlestore.py +0 -606
  540. agno/storage/sqlite.py +0 -646
  541. agno/storage/workflow/__init__.py +0 -0
  542. agno/storage/workflow/mongodb.py +0 -1
  543. agno/storage/workflow/postgres.py +0 -1
  544. agno/storage/workflow/sqlite.py +0 -1
  545. agno/storage/yaml.py +0 -241
  546. agno/tools/thinking.py +0 -73
  547. agno/utils/defaults.py +0 -57
  548. agno/utils/filesystem.py +0 -39
  549. agno/utils/git.py +0 -52
  550. agno/utils/json_io.py +0 -30
  551. agno/utils/load_env.py +0 -19
  552. agno/utils/py_io.py +0 -19
  553. agno/utils/pyproject.py +0 -18
  554. agno/utils/resource_filter.py +0 -31
  555. agno/workflow/v2/__init__.py +0 -21
  556. agno/workflow/v2/types.py +0 -357
  557. agno/workflow/v2/workflow.py +0 -3312
  558. agno/workspace/__init__.py +0 -0
  559. agno/workspace/config.py +0 -325
  560. agno/workspace/enums.py +0 -6
  561. agno/workspace/helpers.py +0 -52
  562. agno/workspace/operator.py +0 -757
  563. agno/workspace/settings.py +0 -158
  564. agno-1.8.1.dist-info/METADATA +0 -982
  565. agno-1.8.1.dist-info/RECORD +0 -566
  566. agno-1.8.1.dist-info/entry_points.txt +0 -3
  567. /agno/{app → db/migrations}/__init__.py +0 -0
  568. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  569. /agno/{cli → integrations}/__init__.py +0 -0
  570. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  571. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  572. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  573. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  574. /agno/{app → os/interfaces}/slack/security.py +0 -0
  575. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  576. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  577. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  578. {agno-1.8.1.dist-info → agno-2.0.0a1.dist-info}/WHEEL +0 -0
  579. {agno-1.8.1.dist-info → agno-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
  580. {agno-1.8.1.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()}