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