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/workflow/types.py ADDED
@@ -0,0 +1,482 @@
1
+ from dataclasses import dataclass
2
+ from enum import Enum
3
+ from typing import Any, Dict, List, Optional, Union
4
+
5
+ from fastapi import WebSocket
6
+ from pydantic import BaseModel
7
+
8
+ from agno.media import Audio, File, Image, Video
9
+ from agno.models.metrics import Metrics
10
+ from agno.utils.log import log_warning
11
+
12
+
13
+ @dataclass
14
+ class WorkflowExecutionInput:
15
+ """Input data for a step execution"""
16
+
17
+ input: Optional[Union[str, Dict[str, Any], List[Any], BaseModel]] = None
18
+
19
+ additional_data: Optional[Dict[str, Any]] = None
20
+
21
+ # Media inputs
22
+ images: Optional[List[Image]] = None
23
+ videos: Optional[List[Video]] = None
24
+ audio: Optional[List[Audio]] = None
25
+ files: Optional[List[File]] = None
26
+
27
+ def get_input_as_string(self) -> Optional[str]:
28
+ """Convert input to string representation"""
29
+ if self.input is None:
30
+ return None
31
+
32
+ if isinstance(self.input, str):
33
+ return self.input
34
+ elif isinstance(self.input, BaseModel):
35
+ return self.input.model_dump_json(indent=2, exclude_none=True)
36
+ elif isinstance(self.input, (dict, list)):
37
+ import json
38
+
39
+ return json.dumps(self.input, indent=2, default=str)
40
+ else:
41
+ return str(self.input)
42
+
43
+ def to_dict(self) -> Dict[str, Any]:
44
+ """Convert to dictionary"""
45
+ input_dict: Optional[Union[str, Dict[str, Any], List[Any]]] = None
46
+ if self.input is not None:
47
+ if isinstance(self.input, BaseModel):
48
+ input_dict = self.input.model_dump(exclude_none=True)
49
+ elif isinstance(self.input, (dict, list)):
50
+ input_dict = self.input
51
+ else:
52
+ input_dict = str(self.input)
53
+
54
+ return {
55
+ "input": input_dict,
56
+ "additional_data": self.additional_data,
57
+ "images": [img.to_dict() for img in self.images] if self.images else None,
58
+ "videos": [vid.to_dict() for vid in self.videos] if self.videos else None,
59
+ "audio": [aud.to_dict() for aud in self.audio] if self.audio else None,
60
+ }
61
+
62
+
63
+ @dataclass
64
+ class StepInput:
65
+ """Input data for a step execution"""
66
+
67
+ input: Optional[Union[str, Dict[str, Any], List[Any], BaseModel]] = None
68
+
69
+ previous_step_content: Optional[Any] = None
70
+ previous_step_outputs: Optional[Dict[str, "StepOutput"]] = None
71
+
72
+ additional_data: Optional[Dict[str, Any]] = None
73
+
74
+ # Media inputs
75
+ images: Optional[List[Image]] = None
76
+ videos: Optional[List[Video]] = None
77
+ audio: Optional[List[Audio]] = None
78
+ files: Optional[List[File]] = None
79
+
80
+ def get_input_as_string(self) -> Optional[str]:
81
+ """Convert input to string representation"""
82
+ if self.input is None:
83
+ return None
84
+
85
+ if isinstance(self.input, str):
86
+ return self.input
87
+ elif isinstance(self.input, BaseModel):
88
+ return self.input.model_dump_json(indent=2, exclude_none=True)
89
+ elif isinstance(self.input, (dict, list)):
90
+ import json
91
+
92
+ return json.dumps(self.input, indent=2, default=str)
93
+ else:
94
+ return str(self.input)
95
+
96
+ def get_step_output(self, step_name: str) -> Optional["StepOutput"]:
97
+ """Get output from a specific previous step by name"""
98
+ if not self.previous_step_outputs:
99
+ return None
100
+ return self.previous_step_outputs.get(step_name)
101
+
102
+ def get_step_content(self, step_name: str) -> Optional[Union[str, Dict[str, str]]]:
103
+ """Get content from a specific previous step by name
104
+
105
+ For parallel steps, if you ask for the parallel step name, returns a dict
106
+ with {step_name: content} for each sub-step.
107
+ For other nested steps (Condition, Router, Loop, Steps), returns the deepest content.
108
+ """
109
+ step_output = self.get_step_output(step_name)
110
+ if not step_output:
111
+ return None
112
+
113
+ # Check if this is a parallel step with nested steps
114
+ if step_output.step_type == "Parallel" and step_output.steps:
115
+ # Return dict with {step_name: content} for each sub-step
116
+ parallel_content = {}
117
+ for sub_step in step_output.steps:
118
+ if sub_step.step_name and sub_step.content:
119
+ # Check if this sub-step has its own nested steps (like Condition -> Research Step)
120
+ if sub_step.steps and len(sub_step.steps) > 0:
121
+ # This is a composite step (like Condition) - get content from its nested steps
122
+ for nested_step in sub_step.steps:
123
+ if nested_step.step_name and nested_step.content:
124
+ parallel_content[nested_step.step_name] = str(nested_step.content)
125
+ else:
126
+ # This is a direct step - use its content
127
+ parallel_content[sub_step.step_name] = str(sub_step.content)
128
+ return parallel_content if parallel_content else str(step_output.content)
129
+
130
+ # For other nested step types (Condition, Router, Loop, Steps), get the deepest content
131
+ elif step_output.steps and len(step_output.steps) > 0:
132
+ # This is a nested step structure - recursively get the deepest content
133
+ return self._get_deepest_step_content(step_output.steps[-1])
134
+
135
+ # Regular step, return content directly
136
+ return step_output.content # type: ignore[return-value]
137
+
138
+ def _get_deepest_step_content(self, step_output: "StepOutput") -> Optional[Union[str, Dict[str, str]]]:
139
+ """Helper method to recursively extract deepest content from nested steps"""
140
+ # If this step has nested steps, go deeper
141
+ if step_output.steps and len(step_output.steps) > 0:
142
+ return self._get_deepest_step_content(step_output.steps[-1])
143
+
144
+ # Return the content of this step
145
+ return step_output.content # type: ignore[return-value]
146
+
147
+ def get_all_previous_content(self) -> str:
148
+ """Get concatenated content from all previous steps"""
149
+ if not self.previous_step_outputs:
150
+ return ""
151
+
152
+ content_parts = []
153
+ for step_name, output in self.previous_step_outputs.items():
154
+ if output.content:
155
+ content_parts.append(f"=== {step_name} ===\n{output.content}")
156
+
157
+ return "\n\n".join(content_parts)
158
+
159
+ def get_last_step_content(self) -> Optional[str]:
160
+ """Get content from the most recent step (for backward compatibility)"""
161
+ if not self.previous_step_outputs:
162
+ return None
163
+
164
+ last_output = list(self.previous_step_outputs.values())[-1] if self.previous_step_outputs else None
165
+ if not last_output:
166
+ return None
167
+
168
+ # Use the helper method to get the deepest content
169
+ return self._get_deepest_step_content(last_output) # type: ignore[return-value]
170
+
171
+ def to_dict(self) -> Dict[str, Any]:
172
+ """Convert to dictionary"""
173
+ # Handle the unified message field
174
+ input_dict: Optional[Union[str, Dict[str, Any], List[Any]]] = None
175
+ if self.input is not None:
176
+ if isinstance(self.input, BaseModel):
177
+ input_dict = self.input.model_dump(exclude_none=True)
178
+ elif isinstance(self.input, (dict, list)):
179
+ input_dict = self.input
180
+ else:
181
+ input_dict = str(self.input)
182
+
183
+ previous_step_content_str: Optional[str] = None
184
+ # Handle previous_step_content (keep existing logic)
185
+ if isinstance(self.previous_step_content, BaseModel):
186
+ previous_step_content_str = self.previous_step_content.model_dump_json(indent=2, exclude_none=True)
187
+ elif isinstance(self.previous_step_content, dict):
188
+ import json
189
+
190
+ previous_step_content_str = json.dumps(self.previous_step_content, indent=2, default=str)
191
+ elif self.previous_step_content:
192
+ previous_step_content_str = str(self.previous_step_content)
193
+
194
+ # Convert previous_step_outputs to serializable format (keep existing logic)
195
+ previous_steps_dict = {}
196
+ if self.previous_step_outputs:
197
+ for step_name, output in self.previous_step_outputs.items():
198
+ previous_steps_dict[step_name] = output.to_dict()
199
+
200
+ return {
201
+ "input": input_dict,
202
+ "previous_step_outputs": previous_steps_dict,
203
+ "previous_step_content": previous_step_content_str,
204
+ "additional_data": self.additional_data,
205
+ "images": [img.to_dict() for img in self.images] if self.images else None,
206
+ "videos": [vid.to_dict() for vid in self.videos] if self.videos else None,
207
+ "audio": [aud.to_dict() for aud in self.audio] if self.audio else None,
208
+ "files": [file for file in self.files] if self.files else None,
209
+ }
210
+
211
+
212
+ @dataclass
213
+ class StepOutput:
214
+ """Output data from a step execution"""
215
+
216
+ step_name: Optional[str] = None
217
+ step_id: Optional[str] = None
218
+ step_type: Optional[str] = None
219
+ executor_type: Optional[str] = None
220
+ executor_name: Optional[str] = None
221
+ # Primary output
222
+ content: Optional[Union[str, Dict[str, Any], List[Any], BaseModel, Any]] = None
223
+
224
+ # Link to the run ID of the step execution
225
+ step_run_id: Optional[str] = None
226
+
227
+ # Media outputs
228
+ images: Optional[List[Image]] = None
229
+ videos: Optional[List[Video]] = None
230
+ audio: Optional[List[Audio]] = None
231
+ files: Optional[List[File]] = None
232
+
233
+ # Metrics for this step execution
234
+ metrics: Optional[Metrics] = None
235
+
236
+ success: bool = True
237
+ error: Optional[str] = None
238
+
239
+ stop: bool = False
240
+
241
+ steps: Optional[List["StepOutput"]] = None
242
+
243
+ def to_dict(self) -> Dict[str, Any]:
244
+ """Convert to dictionary"""
245
+ # Handle the unified content field
246
+ content_dict: Optional[Union[str, Dict[str, Any], List[Any]]] = None
247
+ if self.content is not None:
248
+ if isinstance(self.content, BaseModel):
249
+ content_dict = self.content.model_dump(exclude_none=True)
250
+ elif isinstance(self.content, (dict, list)):
251
+ content_dict = self.content
252
+ else:
253
+ content_dict = str(self.content)
254
+
255
+ result = {
256
+ "content": content_dict,
257
+ "step_name": self.step_name,
258
+ "step_id": self.step_id,
259
+ "step_type": self.step_type,
260
+ "executor_type": self.executor_type,
261
+ "executor_name": self.executor_name,
262
+ "step_run_id": self.step_run_id,
263
+ "images": [img.to_dict() for img in self.images] if self.images else None,
264
+ "videos": [vid.to_dict() for vid in self.videos] if self.videos else None,
265
+ "audio": [aud.to_dict() for aud in self.audio] if self.audio else None,
266
+ "metrics": self.metrics.to_dict() if self.metrics else None,
267
+ "success": self.success,
268
+ "error": self.error,
269
+ "stop": self.stop,
270
+ "files": [file for file in self.files] if self.files else None,
271
+ }
272
+
273
+ # Add nested steps if they exist
274
+ if self.steps:
275
+ result["steps"] = [step.to_dict() for step in self.steps]
276
+
277
+ return result
278
+
279
+ @classmethod
280
+ def from_dict(cls, data: Dict[str, Any]) -> "StepOutput":
281
+ """Create StepOutput from dictionary"""
282
+ # Reconstruct media artifacts
283
+ images = data.get("images")
284
+ if images:
285
+ images = [Image.model_validate(img) for img in images]
286
+
287
+ videos = data.get("videos")
288
+ if videos:
289
+ videos = [Video.model_validate(vid) for vid in videos]
290
+
291
+ audio = data.get("audio")
292
+ if audio:
293
+ audio = [Audio.model_validate(aud) for aud in audio]
294
+
295
+ files = data.get("files")
296
+ if files:
297
+ files = [File.model_validate(file) for file in files]
298
+
299
+ metrics_data = data.get("metrics")
300
+ metrics = None
301
+ if metrics_data:
302
+ if isinstance(metrics_data, dict):
303
+ # Convert dict to Metrics object
304
+ from agno.models.metrics import Metrics
305
+
306
+ metrics = Metrics(**metrics_data)
307
+ else:
308
+ # Already a Metrics object
309
+ metrics = metrics_data
310
+
311
+ # Handle nested steps
312
+ steps_data = data.get("steps")
313
+ steps = None
314
+ if steps_data:
315
+ steps = [cls.from_dict(step_data) for step_data in steps_data]
316
+
317
+ return cls(
318
+ step_name=data.get("step_name"),
319
+ step_id=data.get("step_id"),
320
+ step_type=data.get("step_type"),
321
+ executor_type=data.get("executor_type"),
322
+ executor_name=data.get("executor_name"),
323
+ content=data.get("content"),
324
+ step_run_id=data.get("step_run_id"),
325
+ images=images,
326
+ videos=videos,
327
+ audio=audio,
328
+ files=files,
329
+ metrics=metrics,
330
+ success=data.get("success", True),
331
+ error=data.get("error"),
332
+ stop=data.get("stop", False),
333
+ steps=steps,
334
+ )
335
+
336
+
337
+ @dataclass
338
+ class StepMetrics:
339
+ """Metrics for a single step execution"""
340
+
341
+ step_name: str
342
+ executor_type: str # "agent", "team", etc.
343
+ executor_name: str
344
+ metrics: Optional[Metrics] = None
345
+
346
+ def to_dict(self) -> Dict[str, Any]:
347
+ """Convert to dictionary"""
348
+ return {
349
+ "step_name": self.step_name,
350
+ "executor_type": self.executor_type,
351
+ "executor_name": self.executor_name,
352
+ "metrics": self.metrics.to_dict() if self.metrics else None,
353
+ }
354
+
355
+ @classmethod
356
+ def from_dict(cls, data: Dict[str, Any]) -> "StepMetrics":
357
+ """Create StepMetrics from dictionary"""
358
+
359
+ # Handle metrics properly
360
+ metrics_data = data.get("metrics")
361
+ metrics = None
362
+ if metrics_data:
363
+ if isinstance(metrics_data, dict):
364
+ # Convert dict to Metrics object
365
+ from agno.models.metrics import Metrics
366
+
367
+ metrics = Metrics(**metrics_data)
368
+ else:
369
+ # Already a Metrics object
370
+ metrics = metrics_data
371
+
372
+ return cls(
373
+ step_name=data["step_name"],
374
+ executor_type=data["executor_type"],
375
+ executor_name=data["executor_name"],
376
+ metrics=metrics,
377
+ )
378
+
379
+
380
+ @dataclass
381
+ class WorkflowMetrics:
382
+ """Complete metrics for a workflow execution"""
383
+
384
+ steps: Dict[str, StepMetrics]
385
+
386
+ def to_dict(self) -> Dict[str, Any]:
387
+ """Convert to dictionary"""
388
+ return {
389
+ "steps": {name: step.to_dict() for name, step in self.steps.items()},
390
+ }
391
+
392
+ @classmethod
393
+ def from_dict(cls, data: Dict[str, Any]) -> "WorkflowMetrics":
394
+ """Create WorkflowMetrics from dictionary"""
395
+ steps = {name: StepMetrics.from_dict(step_data) for name, step_data in data["steps"].items()}
396
+
397
+ return cls(
398
+ steps=steps,
399
+ )
400
+
401
+
402
+ @dataclass
403
+ class WebSocketHandler:
404
+ """Generic WebSocket handler for real-time workflow events"""
405
+
406
+ websocket: Optional[WebSocket] = None
407
+
408
+ def format_sse_event(self, json_data: str) -> str:
409
+ """Parse JSON data into SSE-compliant format.
410
+
411
+ Args:
412
+ json_data: JSON string containing the event data
413
+
414
+ Returns:
415
+ SSE-formatted response with event type and data
416
+ """
417
+ import json
418
+
419
+ try:
420
+ # Parse the JSON to extract the event type
421
+ data = json.loads(json_data)
422
+ event_type = data.get("event", "message")
423
+
424
+ # Format as SSE: event: <event_type>\ndata: <json_data>\n\n
425
+ return f"event: {event_type}\ndata: {json_data}\n\n"
426
+ except (json.JSONDecodeError, KeyError):
427
+ # Fallback to generic message event if parsing fails
428
+ return f"event: message\ndata: {json_data}\n\n"
429
+
430
+ async def handle_event(self, event: Any) -> None:
431
+ """Handle an event object - serializes and sends via WebSocket"""
432
+ if not self.websocket:
433
+ return
434
+
435
+ try:
436
+ if hasattr(event, "to_dict"):
437
+ data = event.to_dict()
438
+ elif hasattr(event, "__dict__"):
439
+ data = event.__dict__
440
+ elif isinstance(event, dict):
441
+ data = event
442
+ else:
443
+ data = {"type": "message", "content": str(event)}
444
+
445
+ import json
446
+
447
+ await self.websocket.send_text(self.format_sse_event(json.dumps(data)))
448
+
449
+ except Exception as e:
450
+ log_warning(f"Failed to handle WebSocket event: {e}")
451
+
452
+ async def handle_text(self, message: str) -> None:
453
+ """Handle a plain text message"""
454
+ if not self.websocket:
455
+ return
456
+
457
+ try:
458
+ await self.websocket.send_text(self.format_sse_event(message))
459
+ except Exception as e:
460
+ log_warning(f"Failed to send WebSocket text: {e}")
461
+
462
+ async def handle_dict(self, data: Dict[str, Any]) -> None:
463
+ """Handle a dictionary directly"""
464
+ if not self.websocket:
465
+ return
466
+
467
+ try:
468
+ import json
469
+
470
+ await self.websocket.send_text(self.format_sse_event(json.dumps(data)))
471
+ except Exception as e:
472
+ log_warning(f"Failed to send WebSocket dict: {e}")
473
+
474
+
475
+ class StepType(str, Enum):
476
+ FUNCTION = "Function"
477
+ STEP = "Step"
478
+ STEPS = "Steps"
479
+ LOOP = "Loop"
480
+ PARALLEL = "Parallel"
481
+ CONDITION = "Condition"
482
+ ROUTER = "Router"