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