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/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