agno 1.8.2__py3-none-any.whl → 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (589) hide show
  1. agno/agent/__init__.py +19 -27
  2. agno/agent/agent.py +3143 -4170
  3. agno/api/agent.py +11 -67
  4. agno/api/api.py +5 -46
  5. agno/api/evals.py +8 -19
  6. agno/api/os.py +17 -0
  7. agno/api/routes.py +6 -41
  8. agno/api/schemas/__init__.py +9 -0
  9. agno/api/schemas/agent.py +5 -21
  10. agno/api/schemas/evals.py +7 -16
  11. agno/api/schemas/os.py +14 -0
  12. agno/api/schemas/team.py +5 -21
  13. agno/api/schemas/utils.py +21 -0
  14. agno/api/schemas/workflows.py +11 -7
  15. agno/api/settings.py +53 -0
  16. agno/api/team.py +11 -66
  17. agno/api/workflow.py +28 -0
  18. agno/cloud/aws/base.py +214 -0
  19. agno/cloud/aws/s3/__init__.py +2 -0
  20. agno/cloud/aws/s3/api_client.py +43 -0
  21. agno/cloud/aws/s3/bucket.py +195 -0
  22. agno/cloud/aws/s3/object.py +57 -0
  23. agno/db/__init__.py +24 -0
  24. agno/db/base.py +245 -0
  25. agno/db/dynamo/__init__.py +3 -0
  26. agno/db/dynamo/dynamo.py +1743 -0
  27. agno/db/dynamo/schemas.py +278 -0
  28. agno/db/dynamo/utils.py +684 -0
  29. agno/db/firestore/__init__.py +3 -0
  30. agno/db/firestore/firestore.py +1432 -0
  31. agno/db/firestore/schemas.py +130 -0
  32. agno/db/firestore/utils.py +278 -0
  33. agno/db/gcs_json/__init__.py +3 -0
  34. agno/db/gcs_json/gcs_json_db.py +1001 -0
  35. agno/db/gcs_json/utils.py +194 -0
  36. agno/db/in_memory/__init__.py +3 -0
  37. agno/db/in_memory/in_memory_db.py +882 -0
  38. agno/db/in_memory/utils.py +172 -0
  39. agno/db/json/__init__.py +3 -0
  40. agno/db/json/json_db.py +1045 -0
  41. agno/db/json/utils.py +196 -0
  42. agno/db/migrations/v1_to_v2.py +162 -0
  43. agno/db/mongo/__init__.py +3 -0
  44. agno/db/mongo/mongo.py +1416 -0
  45. agno/db/mongo/schemas.py +77 -0
  46. agno/db/mongo/utils.py +204 -0
  47. agno/db/mysql/__init__.py +3 -0
  48. agno/db/mysql/mysql.py +1719 -0
  49. agno/db/mysql/schemas.py +124 -0
  50. agno/db/mysql/utils.py +297 -0
  51. agno/db/postgres/__init__.py +3 -0
  52. agno/db/postgres/postgres.py +1710 -0
  53. agno/db/postgres/schemas.py +124 -0
  54. agno/db/postgres/utils.py +280 -0
  55. agno/db/redis/__init__.py +3 -0
  56. agno/db/redis/redis.py +1367 -0
  57. agno/db/redis/schemas.py +109 -0
  58. agno/db/redis/utils.py +288 -0
  59. agno/db/schemas/__init__.py +3 -0
  60. agno/db/schemas/evals.py +33 -0
  61. agno/db/schemas/knowledge.py +40 -0
  62. agno/db/schemas/memory.py +46 -0
  63. agno/db/singlestore/__init__.py +3 -0
  64. agno/db/singlestore/schemas.py +116 -0
  65. agno/db/singlestore/singlestore.py +1712 -0
  66. agno/db/singlestore/utils.py +326 -0
  67. agno/db/sqlite/__init__.py +3 -0
  68. agno/db/sqlite/schemas.py +119 -0
  69. agno/db/sqlite/sqlite.py +1676 -0
  70. agno/db/sqlite/utils.py +268 -0
  71. agno/db/utils.py +88 -0
  72. agno/eval/__init__.py +14 -0
  73. agno/eval/accuracy.py +154 -48
  74. agno/eval/performance.py +88 -23
  75. agno/eval/reliability.py +73 -20
  76. agno/eval/utils.py +23 -13
  77. agno/integrations/discord/__init__.py +3 -0
  78. agno/{app → integrations}/discord/client.py +10 -10
  79. agno/knowledge/__init__.py +2 -2
  80. agno/{document → knowledge}/chunking/agentic.py +2 -2
  81. agno/{document → knowledge}/chunking/document.py +2 -2
  82. agno/{document → knowledge}/chunking/fixed.py +3 -3
  83. agno/{document → knowledge}/chunking/markdown.py +2 -2
  84. agno/{document → knowledge}/chunking/recursive.py +2 -2
  85. agno/{document → knowledge}/chunking/row.py +2 -2
  86. agno/knowledge/chunking/semantic.py +59 -0
  87. agno/knowledge/chunking/strategy.py +121 -0
  88. agno/knowledge/content.py +74 -0
  89. agno/knowledge/document/__init__.py +5 -0
  90. agno/{document → knowledge/document}/base.py +12 -2
  91. agno/knowledge/embedder/__init__.py +5 -0
  92. agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
  93. agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
  94. agno/{embedder → knowledge/embedder}/base.py +6 -0
  95. agno/{embedder → knowledge/embedder}/cohere.py +72 -1
  96. agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
  97. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  98. agno/{embedder → knowledge/embedder}/google.py +74 -1
  99. agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
  100. agno/{embedder → knowledge/embedder}/jina.py +48 -2
  101. agno/knowledge/embedder/langdb.py +22 -0
  102. agno/knowledge/embedder/mistral.py +139 -0
  103. agno/{embedder → knowledge/embedder}/nebius.py +1 -1
  104. agno/{embedder → knowledge/embedder}/ollama.py +54 -3
  105. agno/knowledge/embedder/openai.py +223 -0
  106. agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
  107. agno/{embedder → knowledge/embedder}/together.py +1 -1
  108. agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
  109. agno/knowledge/knowledge.py +1551 -0
  110. agno/knowledge/reader/__init__.py +7 -0
  111. agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
  112. agno/knowledge/reader/base.py +88 -0
  113. agno/{document → knowledge}/reader/csv_reader.py +47 -65
  114. agno/knowledge/reader/docx_reader.py +83 -0
  115. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  116. agno/{document → knowledge}/reader/json_reader.py +30 -9
  117. agno/{document → knowledge}/reader/markdown_reader.py +58 -9
  118. agno/{document → knowledge}/reader/pdf_reader.py +71 -126
  119. agno/knowledge/reader/reader_factory.py +268 -0
  120. agno/knowledge/reader/s3_reader.py +101 -0
  121. agno/{document → knowledge}/reader/text_reader.py +31 -10
  122. agno/knowledge/reader/url_reader.py +128 -0
  123. agno/knowledge/reader/web_search_reader.py +366 -0
  124. agno/{document → knowledge}/reader/website_reader.py +37 -10
  125. agno/knowledge/reader/wikipedia_reader.py +59 -0
  126. agno/knowledge/reader/youtube_reader.py +78 -0
  127. agno/knowledge/remote_content/remote_content.py +88 -0
  128. agno/{reranker → knowledge/reranker}/base.py +1 -1
  129. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  130. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  131. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  132. agno/knowledge/types.py +30 -0
  133. agno/knowledge/utils.py +169 -0
  134. agno/media.py +269 -268
  135. agno/memory/__init__.py +2 -10
  136. agno/memory/manager.py +1003 -148
  137. agno/models/aimlapi/__init__.py +2 -2
  138. agno/models/aimlapi/aimlapi.py +6 -6
  139. agno/models/anthropic/claude.py +128 -72
  140. agno/models/aws/bedrock.py +107 -175
  141. agno/models/aws/claude.py +64 -18
  142. agno/models/azure/ai_foundry.py +73 -23
  143. agno/models/base.py +346 -290
  144. agno/models/cerebras/cerebras.py +84 -27
  145. agno/models/cohere/chat.py +106 -98
  146. agno/models/google/gemini.py +105 -46
  147. agno/models/groq/groq.py +97 -35
  148. agno/models/huggingface/huggingface.py +92 -27
  149. agno/models/ibm/watsonx.py +72 -13
  150. agno/models/litellm/chat.py +85 -13
  151. agno/models/message.py +46 -151
  152. agno/models/meta/llama.py +85 -49
  153. agno/models/metrics.py +120 -0
  154. agno/models/mistral/mistral.py +90 -21
  155. agno/models/ollama/__init__.py +0 -2
  156. agno/models/ollama/chat.py +85 -47
  157. agno/models/openai/chat.py +154 -37
  158. agno/models/openai/responses.py +178 -105
  159. agno/models/perplexity/perplexity.py +26 -2
  160. agno/models/portkey/portkey.py +0 -7
  161. agno/models/response.py +15 -9
  162. agno/models/utils.py +20 -0
  163. agno/models/vercel/__init__.py +2 -2
  164. agno/models/vercel/v0.py +1 -1
  165. agno/models/vllm/__init__.py +2 -2
  166. agno/models/vllm/vllm.py +3 -3
  167. agno/models/xai/xai.py +10 -10
  168. agno/os/__init__.py +3 -0
  169. agno/os/app.py +497 -0
  170. agno/os/auth.py +47 -0
  171. agno/os/config.py +103 -0
  172. agno/os/interfaces/agui/__init__.py +3 -0
  173. agno/os/interfaces/agui/agui.py +31 -0
  174. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  175. agno/{app → os/interfaces}/agui/utils.py +65 -28
  176. agno/os/interfaces/base.py +21 -0
  177. agno/os/interfaces/slack/__init__.py +3 -0
  178. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  179. agno/os/interfaces/slack/slack.py +32 -0
  180. agno/os/interfaces/whatsapp/__init__.py +3 -0
  181. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  182. agno/os/interfaces/whatsapp/whatsapp.py +29 -0
  183. agno/os/mcp.py +235 -0
  184. agno/os/router.py +1400 -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 +393 -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 +850 -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 +410 -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 +178 -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 +536 -0
  201. agno/os/schema.py +945 -0
  202. agno/{app/playground → os}/settings.py +7 -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/agent.py +633 -0
  212. agno/run/base.py +53 -77
  213. agno/run/cancel.py +81 -0
  214. agno/run/team.py +243 -96
  215. agno/run/workflow.py +550 -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 +3260 -4824
  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 +43 -23
  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 +20 -17
  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 +22 -12
  244. agno/tools/daytona.py +13 -16
  245. agno/tools/decorator.py +6 -3
  246. agno/tools/desi_vocal.py +17 -8
  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 +62 -62
  252. agno/tools/eleven_labs.py +36 -29
  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 +30 -30
  257. agno/tools/file.py +9 -8
  258. agno/tools/financial_datasets.py +25 -44
  259. agno/tools/firecrawl.py +17 -18
  260. agno/tools/function.py +127 -18
  261. agno/tools/giphy.py +23 -11
  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 +32 -20
  276. agno/tools/mcp.py +1 -2
  277. agno/tools/mem0.py +18 -12
  278. agno/tools/memori.py +14 -10
  279. agno/tools/mlx_transcribe.py +3 -2
  280. agno/tools/models/azure_openai.py +33 -15
  281. agno/tools/models/gemini.py +59 -32
  282. agno/tools/models/groq.py +30 -23
  283. agno/tools/models/nebius.py +28 -12
  284. agno/tools/models_labs.py +40 -16
  285. agno/tools/moviepy_video.py +7 -6
  286. agno/tools/neo4j.py +10 -8
  287. agno/tools/newspaper.py +7 -2
  288. agno/tools/newspaper4k.py +8 -3
  289. agno/tools/openai.py +58 -32
  290. agno/tools/openbb.py +12 -11
  291. agno/tools/opencv.py +63 -47
  292. agno/tools/openweather.py +14 -12
  293. agno/tools/pandas.py +11 -3
  294. agno/tools/postgres.py +4 -12
  295. agno/tools/pubmed.py +4 -1
  296. agno/tools/python.py +9 -22
  297. agno/tools/reasoning.py +35 -27
  298. agno/tools/reddit.py +11 -26
  299. agno/tools/replicate.py +55 -42
  300. agno/tools/resend.py +4 -1
  301. agno/tools/scrapegraph.py +15 -14
  302. agno/tools/searxng.py +10 -23
  303. agno/tools/serpapi.py +6 -3
  304. agno/tools/serper.py +13 -4
  305. agno/tools/shell.py +9 -2
  306. agno/tools/slack.py +12 -11
  307. agno/tools/sleep.py +3 -2
  308. agno/tools/spider.py +24 -4
  309. agno/tools/sql.py +7 -6
  310. agno/tools/tavily.py +6 -4
  311. agno/tools/telegram.py +12 -4
  312. agno/tools/todoist.py +11 -31
  313. agno/tools/toolkit.py +1 -1
  314. agno/tools/trafilatura.py +22 -6
  315. agno/tools/trello.py +9 -22
  316. agno/tools/twilio.py +10 -3
  317. agno/tools/user_control_flow.py +6 -1
  318. agno/tools/valyu.py +34 -5
  319. agno/tools/visualization.py +19 -28
  320. agno/tools/webbrowser.py +4 -3
  321. agno/tools/webex.py +11 -7
  322. agno/tools/website.py +15 -46
  323. agno/tools/webtools.py +12 -4
  324. agno/tools/whatsapp.py +5 -9
  325. agno/tools/wikipedia.py +20 -13
  326. agno/tools/x.py +14 -13
  327. agno/tools/yfinance.py +13 -40
  328. agno/tools/youtube.py +26 -20
  329. agno/tools/zendesk.py +7 -2
  330. agno/tools/zep.py +10 -7
  331. agno/tools/zoom.py +10 -9
  332. agno/utils/common.py +1 -19
  333. agno/utils/events.py +100 -123
  334. agno/utils/gemini.py +1 -1
  335. agno/utils/knowledge.py +29 -0
  336. agno/utils/log.py +54 -4
  337. agno/utils/mcp.py +68 -10
  338. agno/utils/media.py +39 -0
  339. agno/utils/message.py +12 -1
  340. agno/utils/models/aws_claude.py +1 -1
  341. agno/utils/models/claude.py +6 -12
  342. agno/utils/models/cohere.py +1 -1
  343. agno/utils/models/mistral.py +8 -7
  344. agno/utils/models/schema_utils.py +3 -3
  345. agno/utils/models/watsonx.py +1 -1
  346. agno/utils/openai.py +1 -1
  347. agno/utils/pprint.py +33 -32
  348. agno/utils/print_response/agent.py +779 -0
  349. agno/utils/print_response/team.py +1669 -0
  350. agno/utils/print_response/workflow.py +1451 -0
  351. agno/utils/prompts.py +14 -14
  352. agno/utils/reasoning.py +87 -0
  353. agno/utils/response.py +42 -42
  354. agno/utils/streamlit.py +481 -0
  355. agno/utils/string.py +8 -22
  356. agno/utils/team.py +50 -0
  357. agno/utils/timer.py +2 -2
  358. agno/vectordb/base.py +33 -21
  359. agno/vectordb/cassandra/cassandra.py +287 -23
  360. agno/vectordb/chroma/chromadb.py +482 -59
  361. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  362. agno/vectordb/couchbase/couchbase.py +309 -29
  363. agno/vectordb/lancedb/lance_db.py +360 -21
  364. agno/vectordb/langchaindb/__init__.py +5 -0
  365. agno/vectordb/langchaindb/langchaindb.py +145 -0
  366. agno/vectordb/lightrag/__init__.py +5 -0
  367. agno/vectordb/lightrag/lightrag.py +374 -0
  368. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  369. agno/vectordb/milvus/milvus.py +242 -32
  370. agno/vectordb/mongodb/mongodb.py +200 -24
  371. agno/vectordb/pgvector/pgvector.py +319 -37
  372. agno/vectordb/pineconedb/pineconedb.py +221 -27
  373. agno/vectordb/qdrant/qdrant.py +334 -14
  374. agno/vectordb/singlestore/singlestore.py +286 -29
  375. agno/vectordb/surrealdb/surrealdb.py +187 -7
  376. agno/vectordb/upstashdb/upstashdb.py +342 -26
  377. agno/vectordb/weaviate/weaviate.py +227 -165
  378. agno/workflow/__init__.py +17 -13
  379. agno/workflow/{v2/condition.py → condition.py} +135 -32
  380. agno/workflow/{v2/loop.py → loop.py} +115 -28
  381. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  382. agno/workflow/{v2/router.py → router.py} +133 -32
  383. agno/workflow/{v2/step.py → step.py} +207 -49
  384. agno/workflow/{v2/steps.py → steps.py} +147 -66
  385. agno/workflow/types.py +482 -0
  386. agno/workflow/workflow.py +2410 -696
  387. agno-2.0.0.dist-info/METADATA +494 -0
  388. agno-2.0.0.dist-info/RECORD +515 -0
  389. agno-2.0.0.dist-info/licenses/LICENSE +201 -0
  390. agno/agent/metrics.py +0 -110
  391. agno/api/app.py +0 -35
  392. agno/api/playground.py +0 -92
  393. agno/api/schemas/app.py +0 -12
  394. agno/api/schemas/playground.py +0 -22
  395. agno/api/schemas/user.py +0 -35
  396. agno/api/schemas/workspace.py +0 -46
  397. agno/api/user.py +0 -160
  398. agno/api/workflows.py +0 -33
  399. agno/api/workspace.py +0 -175
  400. agno/app/agui/__init__.py +0 -3
  401. agno/app/agui/app.py +0 -17
  402. agno/app/agui/sync_router.py +0 -120
  403. agno/app/base.py +0 -186
  404. agno/app/discord/__init__.py +0 -3
  405. agno/app/fastapi/__init__.py +0 -3
  406. agno/app/fastapi/app.py +0 -107
  407. agno/app/fastapi/async_router.py +0 -457
  408. agno/app/fastapi/sync_router.py +0 -448
  409. agno/app/playground/app.py +0 -228
  410. agno/app/playground/async_router.py +0 -1053
  411. agno/app/playground/deploy.py +0 -249
  412. agno/app/playground/operator.py +0 -183
  413. agno/app/playground/schemas.py +0 -223
  414. agno/app/playground/serve.py +0 -55
  415. agno/app/playground/sync_router.py +0 -1045
  416. agno/app/playground/utils.py +0 -46
  417. agno/app/settings.py +0 -15
  418. agno/app/slack/__init__.py +0 -3
  419. agno/app/slack/app.py +0 -19
  420. agno/app/slack/sync_router.py +0 -92
  421. agno/app/utils.py +0 -54
  422. agno/app/whatsapp/__init__.py +0 -3
  423. agno/app/whatsapp/app.py +0 -15
  424. agno/app/whatsapp/sync_router.py +0 -197
  425. agno/cli/auth_server.py +0 -249
  426. agno/cli/config.py +0 -274
  427. agno/cli/console.py +0 -88
  428. agno/cli/credentials.py +0 -23
  429. agno/cli/entrypoint.py +0 -571
  430. agno/cli/operator.py +0 -357
  431. agno/cli/settings.py +0 -96
  432. agno/cli/ws/ws_cli.py +0 -817
  433. agno/constants.py +0 -13
  434. agno/document/__init__.py +0 -5
  435. agno/document/chunking/semantic.py +0 -45
  436. agno/document/chunking/strategy.py +0 -31
  437. agno/document/reader/__init__.py +0 -5
  438. agno/document/reader/base.py +0 -47
  439. agno/document/reader/docx_reader.py +0 -60
  440. agno/document/reader/gcs/pdf_reader.py +0 -44
  441. agno/document/reader/s3/pdf_reader.py +0 -59
  442. agno/document/reader/s3/text_reader.py +0 -63
  443. agno/document/reader/url_reader.py +0 -59
  444. agno/document/reader/youtube_reader.py +0 -58
  445. agno/embedder/__init__.py +0 -5
  446. agno/embedder/langdb.py +0 -80
  447. agno/embedder/mistral.py +0 -82
  448. agno/embedder/openai.py +0 -78
  449. agno/file/__init__.py +0 -5
  450. agno/file/file.py +0 -16
  451. agno/file/local/csv.py +0 -32
  452. agno/file/local/txt.py +0 -19
  453. agno/infra/app.py +0 -240
  454. agno/infra/base.py +0 -144
  455. agno/infra/context.py +0 -20
  456. agno/infra/db_app.py +0 -52
  457. agno/infra/resource.py +0 -205
  458. agno/infra/resources.py +0 -55
  459. agno/knowledge/agent.py +0 -702
  460. agno/knowledge/arxiv.py +0 -33
  461. agno/knowledge/combined.py +0 -36
  462. agno/knowledge/csv.py +0 -144
  463. agno/knowledge/csv_url.py +0 -124
  464. agno/knowledge/document.py +0 -223
  465. agno/knowledge/docx.py +0 -137
  466. agno/knowledge/firecrawl.py +0 -34
  467. agno/knowledge/gcs/__init__.py +0 -0
  468. agno/knowledge/gcs/base.py +0 -39
  469. agno/knowledge/gcs/pdf.py +0 -125
  470. agno/knowledge/json.py +0 -137
  471. agno/knowledge/langchain.py +0 -71
  472. agno/knowledge/light_rag.py +0 -273
  473. agno/knowledge/llamaindex.py +0 -66
  474. agno/knowledge/markdown.py +0 -154
  475. agno/knowledge/pdf.py +0 -164
  476. agno/knowledge/pdf_bytes.py +0 -42
  477. agno/knowledge/pdf_url.py +0 -148
  478. agno/knowledge/s3/__init__.py +0 -0
  479. agno/knowledge/s3/base.py +0 -64
  480. agno/knowledge/s3/pdf.py +0 -33
  481. agno/knowledge/s3/text.py +0 -34
  482. agno/knowledge/text.py +0 -141
  483. agno/knowledge/url.py +0 -46
  484. agno/knowledge/website.py +0 -179
  485. agno/knowledge/wikipedia.py +0 -32
  486. agno/knowledge/youtube.py +0 -35
  487. agno/memory/agent.py +0 -423
  488. agno/memory/classifier.py +0 -104
  489. agno/memory/db/__init__.py +0 -5
  490. agno/memory/db/base.py +0 -42
  491. agno/memory/db/mongodb.py +0 -189
  492. agno/memory/db/postgres.py +0 -203
  493. agno/memory/db/sqlite.py +0 -193
  494. agno/memory/memory.py +0 -22
  495. agno/memory/row.py +0 -36
  496. agno/memory/summarizer.py +0 -201
  497. agno/memory/summary.py +0 -19
  498. agno/memory/team.py +0 -415
  499. agno/memory/v2/__init__.py +0 -2
  500. agno/memory/v2/db/__init__.py +0 -1
  501. agno/memory/v2/db/base.py +0 -42
  502. agno/memory/v2/db/firestore.py +0 -339
  503. agno/memory/v2/db/mongodb.py +0 -196
  504. agno/memory/v2/db/postgres.py +0 -214
  505. agno/memory/v2/db/redis.py +0 -187
  506. agno/memory/v2/db/schema.py +0 -54
  507. agno/memory/v2/db/sqlite.py +0 -209
  508. agno/memory/v2/manager.py +0 -437
  509. agno/memory/v2/memory.py +0 -1097
  510. agno/memory/v2/schema.py +0 -55
  511. agno/memory/v2/summarizer.py +0 -215
  512. agno/memory/workflow.py +0 -38
  513. agno/models/ollama/tools.py +0 -430
  514. agno/models/qwen/__init__.py +0 -5
  515. agno/playground/__init__.py +0 -10
  516. agno/playground/deploy.py +0 -3
  517. agno/playground/playground.py +0 -3
  518. agno/playground/serve.py +0 -3
  519. agno/playground/settings.py +0 -3
  520. agno/reranker/__init__.py +0 -0
  521. agno/run/response.py +0 -467
  522. agno/run/v2/__init__.py +0 -0
  523. agno/run/v2/workflow.py +0 -567
  524. agno/storage/__init__.py +0 -0
  525. agno/storage/agent/__init__.py +0 -0
  526. agno/storage/agent/dynamodb.py +0 -1
  527. agno/storage/agent/json.py +0 -1
  528. agno/storage/agent/mongodb.py +0 -1
  529. agno/storage/agent/postgres.py +0 -1
  530. agno/storage/agent/singlestore.py +0 -1
  531. agno/storage/agent/sqlite.py +0 -1
  532. agno/storage/agent/yaml.py +0 -1
  533. agno/storage/base.py +0 -60
  534. agno/storage/dynamodb.py +0 -673
  535. agno/storage/firestore.py +0 -297
  536. agno/storage/gcs_json.py +0 -261
  537. agno/storage/in_memory.py +0 -234
  538. agno/storage/json.py +0 -237
  539. agno/storage/mongodb.py +0 -328
  540. agno/storage/mysql.py +0 -685
  541. agno/storage/postgres.py +0 -682
  542. agno/storage/redis.py +0 -336
  543. agno/storage/session/__init__.py +0 -16
  544. agno/storage/session/agent.py +0 -64
  545. agno/storage/session/team.py +0 -63
  546. agno/storage/session/v2/__init__.py +0 -5
  547. agno/storage/session/workflow.py +0 -61
  548. agno/storage/singlestore.py +0 -606
  549. agno/storage/sqlite.py +0 -646
  550. agno/storage/workflow/__init__.py +0 -0
  551. agno/storage/workflow/mongodb.py +0 -1
  552. agno/storage/workflow/postgres.py +0 -1
  553. agno/storage/workflow/sqlite.py +0 -1
  554. agno/storage/yaml.py +0 -241
  555. agno/tools/thinking.py +0 -73
  556. agno/utils/defaults.py +0 -57
  557. agno/utils/filesystem.py +0 -39
  558. agno/utils/git.py +0 -52
  559. agno/utils/json_io.py +0 -30
  560. agno/utils/load_env.py +0 -19
  561. agno/utils/py_io.py +0 -19
  562. agno/utils/pyproject.py +0 -18
  563. agno/utils/resource_filter.py +0 -31
  564. agno/workflow/v2/__init__.py +0 -21
  565. agno/workflow/v2/types.py +0 -357
  566. agno/workflow/v2/workflow.py +0 -3313
  567. agno/workspace/__init__.py +0 -0
  568. agno/workspace/config.py +0 -325
  569. agno/workspace/enums.py +0 -6
  570. agno/workspace/helpers.py +0 -52
  571. agno/workspace/operator.py +0 -757
  572. agno/workspace/settings.py +0 -158
  573. agno-1.8.2.dist-info/METADATA +0 -982
  574. agno-1.8.2.dist-info/RECORD +0 -566
  575. agno-1.8.2.dist-info/entry_points.txt +0 -3
  576. agno-1.8.2.dist-info/licenses/LICENSE +0 -375
  577. /agno/{app → db/migrations}/__init__.py +0 -0
  578. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  579. /agno/{cli → integrations}/__init__.py +0 -0
  580. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  581. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  582. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  583. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  584. /agno/{app → os/interfaces}/slack/security.py +0 -0
  585. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  586. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  587. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  588. {agno-1.8.2.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
  589. {agno-1.8.2.dist-info → agno-2.0.0.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