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/firestore.py DELETED
@@ -1,297 +0,0 @@
1
- from datetime import datetime, timezone
2
- from typing import Any, Dict, List, Literal, Optional, Union
3
- from uuid import UUID
4
-
5
- from agno.storage.base import Storage
6
- from agno.storage.session import Session
7
- from agno.storage.session.agent import AgentSession
8
- from agno.storage.session.team import TeamSession
9
- from agno.storage.session.v2.workflow import WorkflowSession as WorkflowSessionV2
10
- from agno.storage.session.workflow import WorkflowSession
11
- from agno.utils.log import log_debug, logger
12
-
13
- try:
14
- from google.api_core import exceptions as google_exceptions
15
- from google.cloud.firestore_v1 import (
16
- Client,
17
- CollectionReference,
18
- DocumentReference,
19
- Query,
20
- )
21
- from google.cloud.firestore_v1.base_query import FieldFilter
22
- except ImportError:
23
- raise ImportError("`firestore` not installed. Please install it with `pip install google-cloud-firestore`")
24
-
25
-
26
- class FirestoreStorage(Storage):
27
- def __init__(
28
- self,
29
- collection_name: str,
30
- db_name: Optional[str] = "(default)",
31
- project_id: Optional[str] = None,
32
- client: Optional[Client] = None,
33
- mode: Optional[Literal["agent", "team", "workflow", "workflow_v2"]] = "agent",
34
- ):
35
- super().__init__(mode)
36
- self.collection_name = collection_name
37
- self.db_name = db_name
38
- self.project_id = project_id
39
-
40
- # Initialize Firestore client
41
- self._client = client
42
- if self._client is None:
43
- self._client = self._initialize_client()
44
-
45
- # Get collection reference
46
- self.collection: CollectionReference = self._client.collection(self.collection_name)
47
- log_debug(f"Created FirestoreStorage with collection: '{self.collection_name}'")
48
-
49
- def _initialize_client(self) -> Client:
50
- """Initialize and return a Firestore client with proper error handling."""
51
- try:
52
- client = Client(database=self.db_name, project=self.project_id)
53
- log_debug(f"Firestore client initialized with database: '{self.db_name}'")
54
- return client
55
- except google_exceptions.Unauthenticated as e:
56
- raise ImportError(
57
- "Failed to authenticate with Google Cloud. Please set up authentication:\n"
58
- "1. Run: gcloud auth application-default login\n"
59
- "2. Or set GOOGLE_APPLICATION_CREDENTIALS environment variable"
60
- ) from e
61
- except google_exceptions.PermissionDenied as e:
62
- raise ImportError(
63
- "Permission denied when accessing Firestore. Please ensure:\n"
64
- "1. Your service account has the 'Cloud Datastore User' role\n"
65
- "2. The Firestore API is enabled for your project"
66
- ) from e
67
- except Exception as e:
68
- raise ImportError(f"Failed to initialize Firestore client: {e}") from e
69
-
70
- def _delete_document(self, document: DocumentReference) -> None:
71
- """Recursively delete a document and all its subcollections."""
72
- log_debug(f"Deleting document: {document.path}")
73
- for collection in document.collections():
74
- self._delete_collection(collection)
75
- document.delete()
76
-
77
- def _delete_collection(self, collection: CollectionReference) -> None:
78
- """Recursively delete all documents in a collection."""
79
- for document in collection.list_documents():
80
- self._delete_document(document)
81
-
82
- def _build_query(
83
- self, base_query: CollectionReference, user_id: Optional[str] = None, entity_id: Optional[str] = None
84
- ) -> Union[Query, CollectionReference]:
85
- """Build a Firestore query with optional filters."""
86
- query: Union[Query, CollectionReference] = base_query
87
-
88
- if user_id:
89
- query = query.where(filter=FieldFilter("user_id", "==", user_id))
90
-
91
- if entity_id:
92
- if self.mode == "agent":
93
- query = query.where(filter=FieldFilter("agent_id", "==", entity_id))
94
- elif self.mode == "team":
95
- query = query.where(filter=FieldFilter("team_id", "==", entity_id))
96
- elif self.mode == "workflow":
97
- query = query.where(filter=FieldFilter("workflow_id", "==", entity_id))
98
- elif self.mode == "workflow_v2":
99
- query = query.where(filter=FieldFilter("workflow_id", "==", entity_id))
100
-
101
- return query
102
-
103
- def _parse_session(self, doc_data: Optional[Dict[str, Any]]) -> Optional[Session]:
104
- """Parse document data into appropriate Session type."""
105
- if not doc_data:
106
- return None
107
-
108
- try:
109
- if self.mode == "agent":
110
- return AgentSession.from_dict(doc_data)
111
- elif self.mode == "team":
112
- return TeamSession.from_dict(doc_data)
113
- elif self.mode == "workflow":
114
- return WorkflowSession.from_dict(doc_data)
115
- elif self.mode == "workflow_v2":
116
- return WorkflowSessionV2.from_dict(doc_data)
117
- except Exception as e:
118
- logger.error(f"Error parsing session data: {e}")
119
- return None
120
-
121
- def create(self) -> None:
122
- """
123
- Create storage if it doesn't exist.
124
- For Firestore, this is a no-operation as collections are created automatically.
125
- """
126
- try:
127
- if self._client:
128
- list(self._client.collections())
129
- log_debug("Firestore connection successful")
130
- except Exception as e:
131
- logger.error(f"Could not connect to Firestore: {e}")
132
- raise
133
-
134
- def read(self, session_id: str, user_id: Optional[str] = None) -> Optional[Session]:
135
- """Read a session from Firestore."""
136
- try:
137
- query = self.collection.where(filter=FieldFilter("session_id", "==", session_id))
138
-
139
- if user_id:
140
- query = query.where(filter=FieldFilter("user_id", "==", user_id))
141
-
142
- docs = query.get()
143
- for doc in docs:
144
- doc_dict = doc.to_dict()
145
- if doc_dict:
146
- return self._parse_session(doc_dict)
147
-
148
- return None
149
- except Exception as e:
150
- logger.error(f"Error reading session: {e}")
151
- return None
152
-
153
- def get_all_session_ids(self, user_id: Optional[str] = None, entity_id: Optional[str] = None) -> List[str]:
154
- """Get all session IDs, optionally filtered by user_id and/or entity_id."""
155
- try:
156
- query = self._build_query(self.collection, user_id, entity_id)
157
- docs = query.get()
158
-
159
- # Sort by created_at descending and extract session IDs
160
- session_ids: List[str] = []
161
- doc_list = []
162
- for doc in docs:
163
- doc_data = doc.to_dict()
164
- if doc_data:
165
- doc_list.append(doc_data)
166
-
167
- sorted_docs = sorted(doc_list, key=lambda x: x.get("created_at", 0), reverse=True)
168
-
169
- for doc_data in sorted_docs:
170
- session_id = doc_data.get("session_id")
171
- if session_id:
172
- session_ids.append(session_id)
173
-
174
- return session_ids
175
- except Exception as e:
176
- logger.error(f"Error getting session IDs: {e}")
177
- return []
178
-
179
- def get_all_sessions(self, user_id: Optional[str] = None, entity_id: Optional[str] = None) -> List[Session]:
180
- """Get all sessions, optionally filtered by user_id and/or entity_id."""
181
- sessions: List[Session] = []
182
- try:
183
- query = self._build_query(self.collection, user_id, entity_id)
184
- docs = query.get()
185
-
186
- # Sort by created_at descending
187
- doc_list = []
188
- for doc in docs:
189
- doc_data = doc.to_dict()
190
- if doc_data:
191
- doc_list.append(doc_data)
192
-
193
- sorted_docs = sorted(doc_list, key=lambda x: x.get("created_at", 0), reverse=True)
194
-
195
- for doc_data in sorted_docs:
196
- session = self._parse_session(doc_data)
197
- if session:
198
- sessions.append(session)
199
-
200
- return sessions
201
- except Exception as e:
202
- logger.error(f"Error getting all sessions: {e}")
203
- return []
204
-
205
- def get_recent_sessions(
206
- self,
207
- user_id: Optional[str] = None,
208
- entity_id: Optional[str] = None,
209
- limit: Optional[int] = 2,
210
- ) -> List[Session]:
211
- """Get the last N sessions, ordered by created_at descending."""
212
- sessions: List[Session] = []
213
- try:
214
- query = self._build_query(self.collection, user_id, entity_id)
215
- docs = query.get()
216
-
217
- # Sort by created_at descending
218
- doc_list = []
219
- for doc in docs:
220
- doc_data = doc.to_dict()
221
- if doc_data:
222
- doc_list.append(doc_data)
223
-
224
- sorted_docs = sorted(doc_list, key=lambda x: x.get("created_at", 0), reverse=True)
225
-
226
- # Apply limit
227
- if limit is not None:
228
- sorted_docs = sorted_docs[:limit]
229
-
230
- for doc_data in sorted_docs:
231
- session = self._parse_session(doc_data)
232
- if session:
233
- sessions.append(session)
234
-
235
- return sessions
236
- except Exception as e:
237
- logger.error(f"Error getting recent sessions: {e}")
238
- return []
239
-
240
- def upsert(self, session: Session, create_and_retry: bool = True) -> Optional[Session]:
241
- """Insert or update a session in Firestore."""
242
- try:
243
- # Prepare session data
244
- session_dict = session.to_dict()
245
- now = datetime.now(timezone.utc)
246
- timestamp = int(now.timestamp())
247
-
248
- if isinstance(session.session_id, UUID):
249
- session_dict["session_id"] = str(session.session_id)
250
-
251
- # Add timestamps
252
- session_dict["updated_at"] = timestamp
253
-
254
- # Get document reference
255
- doc_ref = self.collection.document(session_dict["session_id"])
256
- doc = doc_ref.get()
257
-
258
- # Add created_at for new documents
259
- if not doc.exists:
260
- session_dict["created_at"] = timestamp
261
-
262
- # Save to Firestore
263
- doc_ref.set(session_dict)
264
-
265
- # Return the updated session
266
- return self.read(session_id=session_dict["session_id"])
267
-
268
- except Exception as e:
269
- logger.error(f"Error upserting session: {e}")
270
- return None
271
-
272
- def delete_session(self, session_id: Optional[str] = None) -> None:
273
- """Delete a session from Firestore."""
274
- if session_id is None:
275
- logger.warning("No session_id provided for deletion")
276
- return
277
-
278
- try:
279
- self.collection.document(session_id).delete()
280
- log_debug(f"Deleted session: {session_id}")
281
- except Exception as e:
282
- logger.error(f"Error deleting session: {e}")
283
-
284
- def drop(self) -> None:
285
- """Drop all sessions from storage."""
286
- try:
287
- self._delete_collection(self.collection)
288
- log_debug(f"Dropped all sessions in collection: {self.collection_name}")
289
- except Exception as e:
290
- logger.error(f"Error dropping collection: {e}")
291
-
292
- def upgrade_schema(self) -> None:
293
- """
294
- Upgrade the schema of the storage.
295
- For Firestore, this is a no-op as it's schema-less.
296
- """
297
- pass
agno/storage/gcs_json.py DELETED
@@ -1,261 +0,0 @@
1
- import json
2
- import time
3
- from typing import Any, List, Literal, Optional
4
-
5
- from agno.storage.json import JsonStorage, Storage
6
- from agno.storage.session import Session
7
- from agno.storage.session.agent import AgentSession
8
- from agno.storage.session.team import TeamSession
9
- from agno.storage.session.v2.workflow import WorkflowSession as WorkflowSessionV2
10
- from agno.storage.session.workflow import WorkflowSession
11
- from agno.utils.log import logger
12
-
13
- try:
14
- from google.cloud import storage as gcs
15
- except ImportError:
16
- raise ImportError("`google-cloud-storage` not installed. Please install it with `pip install google-cloud-storage`")
17
-
18
-
19
- class GCSJsonStorage(JsonStorage):
20
- """
21
- A Cloud-based JSON storage for agent sessions that stores session (memory) data
22
- in a GCS bucket. This class derives from JsonStorage and replaces local
23
- file system operations with Cloud Storage operations. The GCS client and bucket
24
- are initialized once in the constructor and then reused for all subsequent operations.
25
-
26
- Parameters:
27
- - bucket_name: The GCS bucket name (must be provided).
28
- - prefix: The GCS folder path prefix). See (Flat Namespace)[https://cloud.google.com/storage/docs/objects#flat-namespace] in GCS docs for details.
29
- - mode: One of "agent", "team", or "workflow". Defaults to "agent".
30
- - project: Optional; the GCP project ID. Defaults to current Google Cloud's project (set with `gcloud init`).
31
- - location: Optional; the GCP location for the bucket. Default's to current project's location.
32
- - credentials: Optional credentials object; if not provided, defaults will be used.
33
- """
34
-
35
- def __init__(
36
- self,
37
- bucket_name: str,
38
- prefix: Optional[str] = "",
39
- mode: Optional[Literal["agent", "team", "workflow", "workflow_v2"]] = "agent",
40
- project: Optional[str] = None,
41
- location: Optional[str] = None,
42
- credentials: Optional[Any] = None,
43
- ):
44
- # Call Storage's __init__ directly to bypass the folder creation logic in JsonStorage.
45
- Storage.__init__(self, mode=mode)
46
- self.bucket_name = bucket_name
47
- if prefix is not None and prefix != "" and not prefix.endswith("/"):
48
- prefix += "/"
49
- self.prefix = prefix
50
- self.project = project
51
- self.location = location
52
-
53
- # Initialize the GCS client once; if STORAGE_EMULATOR_HOST is set, it will be used automatically.
54
- self.client = gcs.Client(project=self.project, credentials=credentials)
55
- self.bucket = self.client.bucket(self.bucket_name)
56
-
57
- def _get_blob_path(self, session_id: str) -> str:
58
- """Returns the blob path for a given session."""
59
- return f"{self.prefix}{session_id}.json"
60
-
61
- def create(self) -> None:
62
- """
63
- Creates the bucket if it doesn't exist
64
- The client and bucket are already stored in self.
65
- """
66
- try:
67
- self.bucket = self.client.create_bucket(self.bucket_name, self.location, self.project)
68
- logger.info(f"Bucket {self.bucket_name} created successfully.")
69
- except Exception as e:
70
- # If the bucket already exists, check for conflict (HTTP 409) and continue.
71
- if hasattr(e, "code") and e.code == 409:
72
- logger.info(f"Bucket {self.bucket_name} already exists.")
73
- else:
74
- logger.error(f"Failed to create bucket {self.bucket_name}: {e}")
75
- raise
76
-
77
- def serialize(self, data: dict) -> str:
78
- return json.dumps(data, ensure_ascii=False, indent=4)
79
-
80
- def deserialize(self, data: str) -> dict:
81
- return json.loads(data)
82
-
83
- def read(self, session_id: str, user_id: Optional[str] = None) -> Optional[Session]:
84
- """
85
- Reads a session JSON blob from the GCS bucket and returns a Session object.
86
- If the blob is not found, returns None.
87
- """
88
- blob = self.bucket.blob(self._get_blob_path(session_id))
89
- try:
90
- data_str = blob.download_as_bytes().decode("utf-8")
91
- data = self.deserialize(data_str)
92
- except Exception as e:
93
- # If the error indicates that the blob was not found (404), return None.
94
- if "404" in str(e):
95
- return None
96
- logger.error(f"Error reading session {session_id} from GCS: {e}")
97
- return None
98
-
99
- if user_id and data.get("user_id") != user_id:
100
- return None
101
-
102
- if self.mode == "agent":
103
- return AgentSession.from_dict(data)
104
- elif self.mode == "team":
105
- return TeamSession.from_dict(data)
106
- elif self.mode == "workflow":
107
- return WorkflowSession.from_dict(data)
108
- elif self.mode == "workflow_v2":
109
- return WorkflowSessionV2.from_dict(data)
110
- return None
111
-
112
- def get_all_session_ids(self, user_id: Optional[str] = None, entity_id: Optional[str] = None) -> List[str]:
113
- """
114
- Lists all session IDs stored in the bucket.
115
- """
116
- session_ids = []
117
- for blob in self.client.list_blobs(self.bucket, prefix=self.prefix):
118
- if blob.name.endswith(".json"):
119
- session_ids.append(blob.name.replace(".json", ""))
120
- return session_ids
121
-
122
- def get_all_sessions(self, user_id: Optional[str] = None, entity_id: Optional[str] = None) -> List[Session]:
123
- """
124
- Retrieves all sessions stored in the bucket.
125
- """
126
- sessions: List[Session] = []
127
- for blob in self.client.list_blobs(self.bucket, prefix=self.prefix):
128
- if blob.name.endswith(".json"):
129
- try:
130
- data_str = blob.download_as_bytes().decode("utf-8")
131
- data = self.deserialize(data_str)
132
-
133
- if user_id and data.get("user_id") != user_id:
134
- continue
135
- session: Optional[Session] = None
136
- if self.mode == "agent":
137
- session = AgentSession.from_dict(data)
138
- elif self.mode == "team":
139
- session = TeamSession.from_dict(data)
140
- elif self.mode == "workflow":
141
- session = WorkflowSession.from_dict(data)
142
- elif self.mode == "workflow_v2":
143
- session = WorkflowSessionV2.from_dict(data)
144
- if session is not None:
145
- sessions.append(session)
146
- except Exception as e:
147
- logger.error(f"Error reading session from blob {blob.name}: {e}")
148
- continue
149
- return sessions
150
-
151
- def get_recent_sessions(
152
- self,
153
- user_id: Optional[str] = None,
154
- entity_id: Optional[str] = None,
155
- limit: Optional[int] = 2,
156
- ) -> List[Session]:
157
- """Get the last N sessions, ordered by created_at descending.
158
-
159
- Args:
160
- num_history_sessions: Number of most recent sessions to return
161
- user_id: Filter by user ID
162
- entity_id: Filter by entity ID (agent_id, team_id, or workflow_id)
163
-
164
- Returns:
165
- List[Session]: List of most recent sessions
166
- """
167
- sessions: List[Session] = []
168
- # List of (created_at, data) tuples for sorting
169
- session_data: List[tuple[int, dict]] = []
170
-
171
- try:
172
- # Get all blobs with the specified prefix
173
- for blob in self.client.list_blobs(self.bucket, prefix=self.prefix):
174
- if not blob.name.endswith(".json"):
175
- continue
176
-
177
- try:
178
- data_str = blob.download_as_bytes().decode("utf-8")
179
- data = self.deserialize(data_str)
180
-
181
- # Apply filters
182
- if user_id and data.get("user_id") != user_id:
183
- continue
184
-
185
- # Store with created_at for sorting
186
- created_at = data.get("created_at", 0)
187
- session_data.append((created_at, data))
188
-
189
- except Exception as e:
190
- logger.error(f"Error reading session from blob {blob.name}: {e}")
191
- continue
192
-
193
- # Sort by created_at descending and take only num_history_sessions
194
- session_data.sort(key=lambda x: x[0], reverse=True)
195
- if limit is not None:
196
- session_data = session_data[:limit]
197
-
198
- # Convert filtered and sorted data to Session objects
199
- for _, data in session_data:
200
- session: Optional[Session] = None
201
- if self.mode == "agent":
202
- session = AgentSession.from_dict(data)
203
- elif self.mode == "team":
204
- session = TeamSession.from_dict(data)
205
- elif self.mode == "workflow":
206
- session = WorkflowSession.from_dict(data)
207
- elif self.mode == "workflow_v2":
208
- session = WorkflowSessionV2.from_dict(data)
209
- if session is not None:
210
- sessions.append(session)
211
-
212
- except Exception as e:
213
- logger.error(f"Error getting last {limit} sessions: {e}")
214
-
215
- return sessions
216
-
217
- def upsert(self, session: Session) -> Optional[Session]:
218
- """
219
- Inserts or updates a session JSON blob in the GCS bucket.
220
- """
221
- blob = self.bucket.blob(self._get_blob_path(session.session_id))
222
- try:
223
- data = session.to_dict()
224
- data["updated_at"] = int(time.time())
225
- if "created_at" not in data or data["created_at"] is None:
226
- data["created_at"] = data["updated_at"]
227
- json_data = self.serialize(data)
228
- blob.upload_from_string(json_data, content_type="application/json")
229
- return session
230
- except Exception as e:
231
- logger.error(f"Error upserting session {session.session_id}: {e}")
232
- return None
233
-
234
- def delete_session(self, session_id: Optional[str] = None):
235
- """
236
- Deletes a session JSON blob from the GCS bucket.
237
- """
238
- if session_id is None:
239
- return
240
- blob = self.bucket.blob(self._get_blob_path(session_id))
241
- try:
242
- blob.delete()
243
- except Exception as e:
244
- logger.error(f"Error deleting session {session_id}: {e}")
245
-
246
- def drop(self) -> None:
247
- """
248
- Deletes all session JSON blobs from the bucket.
249
- """
250
- prefix = ""
251
- for blob in self.client.list_blobs(self.bucket, prefix=prefix):
252
- try:
253
- blob.delete()
254
- except Exception as e:
255
- logger.error(f"Error deleting blob {blob.name}: {e}")
256
-
257
- def upgrade_schema(self) -> None:
258
- """
259
- Schema upgrade is not implemented.
260
- """
261
- pass