agno 1.8.0__py3-none-any.whl → 2.0.0a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (583) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +2781 -4126
  4. agno/api/agent.py +9 -65
  5. agno/api/api.py +5 -46
  6. agno/api/evals.py +6 -17
  7. agno/api/os.py +17 -0
  8. agno/api/routes.py +6 -41
  9. agno/api/schemas/__init__.py +9 -0
  10. agno/api/schemas/agent.py +5 -21
  11. agno/api/schemas/evals.py +7 -16
  12. agno/api/schemas/os.py +14 -0
  13. agno/api/schemas/team.py +5 -21
  14. agno/api/schemas/utils.py +21 -0
  15. agno/api/schemas/workflows.py +11 -7
  16. agno/api/settings.py +53 -0
  17. agno/api/team.py +9 -64
  18. agno/api/workflow.py +28 -0
  19. agno/cloud/aws/base.py +214 -0
  20. agno/cloud/aws/s3/__init__.py +2 -0
  21. agno/cloud/aws/s3/api_client.py +43 -0
  22. agno/cloud/aws/s3/bucket.py +195 -0
  23. agno/cloud/aws/s3/object.py +57 -0
  24. agno/db/__init__.py +24 -0
  25. agno/db/base.py +245 -0
  26. agno/db/dynamo/__init__.py +3 -0
  27. agno/db/dynamo/dynamo.py +1749 -0
  28. agno/db/dynamo/schemas.py +278 -0
  29. agno/db/dynamo/utils.py +684 -0
  30. agno/db/firestore/__init__.py +3 -0
  31. agno/db/firestore/firestore.py +1438 -0
  32. agno/db/firestore/schemas.py +130 -0
  33. agno/db/firestore/utils.py +278 -0
  34. agno/db/gcs_json/__init__.py +3 -0
  35. agno/db/gcs_json/gcs_json_db.py +1001 -0
  36. agno/db/gcs_json/utils.py +194 -0
  37. agno/db/in_memory/__init__.py +3 -0
  38. agno/db/in_memory/in_memory_db.py +888 -0
  39. agno/db/in_memory/utils.py +172 -0
  40. agno/db/json/__init__.py +3 -0
  41. agno/db/json/json_db.py +1051 -0
  42. agno/db/json/utils.py +196 -0
  43. agno/db/migrations/v1_to_v2.py +162 -0
  44. agno/db/mongo/__init__.py +3 -0
  45. agno/db/mongo/mongo.py +1417 -0
  46. agno/db/mongo/schemas.py +77 -0
  47. agno/db/mongo/utils.py +204 -0
  48. agno/db/mysql/__init__.py +3 -0
  49. agno/db/mysql/mysql.py +1719 -0
  50. agno/db/mysql/schemas.py +124 -0
  51. agno/db/mysql/utils.py +298 -0
  52. agno/db/postgres/__init__.py +3 -0
  53. agno/db/postgres/postgres.py +1720 -0
  54. agno/db/postgres/schemas.py +124 -0
  55. agno/db/postgres/utils.py +281 -0
  56. agno/db/redis/__init__.py +3 -0
  57. agno/db/redis/redis.py +1371 -0
  58. agno/db/redis/schemas.py +109 -0
  59. agno/db/redis/utils.py +288 -0
  60. agno/db/schemas/__init__.py +3 -0
  61. agno/db/schemas/evals.py +33 -0
  62. agno/db/schemas/knowledge.py +40 -0
  63. agno/db/schemas/memory.py +46 -0
  64. agno/db/singlestore/__init__.py +3 -0
  65. agno/db/singlestore/schemas.py +116 -0
  66. agno/db/singlestore/singlestore.py +1722 -0
  67. agno/db/singlestore/utils.py +327 -0
  68. agno/db/sqlite/__init__.py +3 -0
  69. agno/db/sqlite/schemas.py +119 -0
  70. agno/db/sqlite/sqlite.py +1680 -0
  71. agno/db/sqlite/utils.py +269 -0
  72. agno/db/utils.py +88 -0
  73. agno/eval/__init__.py +14 -0
  74. agno/eval/accuracy.py +142 -43
  75. agno/eval/performance.py +88 -23
  76. agno/eval/reliability.py +73 -20
  77. agno/eval/utils.py +23 -13
  78. agno/integrations/discord/__init__.py +3 -0
  79. agno/{app → integrations}/discord/client.py +10 -10
  80. agno/knowledge/__init__.py +2 -2
  81. agno/{document → knowledge}/chunking/agentic.py +2 -2
  82. agno/{document → knowledge}/chunking/document.py +2 -2
  83. agno/{document → knowledge}/chunking/fixed.py +3 -3
  84. agno/{document → knowledge}/chunking/markdown.py +2 -2
  85. agno/{document → knowledge}/chunking/recursive.py +2 -2
  86. agno/{document → knowledge}/chunking/row.py +2 -2
  87. agno/knowledge/chunking/semantic.py +59 -0
  88. agno/knowledge/chunking/strategy.py +121 -0
  89. agno/knowledge/content.py +74 -0
  90. agno/knowledge/document/__init__.py +5 -0
  91. agno/{document → knowledge/document}/base.py +12 -2
  92. agno/knowledge/embedder/__init__.py +5 -0
  93. agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
  94. agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
  95. agno/{embedder → knowledge/embedder}/base.py +6 -0
  96. agno/{embedder → knowledge/embedder}/cohere.py +72 -1
  97. agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
  98. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  99. agno/{embedder → knowledge/embedder}/google.py +74 -1
  100. agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
  101. agno/{embedder → knowledge/embedder}/jina.py +48 -2
  102. agno/knowledge/embedder/langdb.py +22 -0
  103. agno/knowledge/embedder/mistral.py +139 -0
  104. agno/{embedder → knowledge/embedder}/nebius.py +1 -1
  105. agno/{embedder → knowledge/embedder}/ollama.py +54 -3
  106. agno/knowledge/embedder/openai.py +223 -0
  107. agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
  108. agno/{embedder → knowledge/embedder}/together.py +1 -1
  109. agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
  110. agno/knowledge/knowledge.py +1515 -0
  111. agno/knowledge/reader/__init__.py +7 -0
  112. agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
  113. agno/knowledge/reader/base.py +88 -0
  114. agno/{document → knowledge}/reader/csv_reader.py +68 -15
  115. agno/knowledge/reader/docx_reader.py +83 -0
  116. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  117. agno/knowledge/reader/gcs_reader.py +67 -0
  118. agno/{document → knowledge}/reader/json_reader.py +30 -9
  119. agno/{document → knowledge}/reader/markdown_reader.py +36 -9
  120. agno/{document → knowledge}/reader/pdf_reader.py +79 -21
  121. agno/knowledge/reader/reader_factory.py +275 -0
  122. agno/knowledge/reader/s3_reader.py +171 -0
  123. agno/{document → knowledge}/reader/text_reader.py +31 -10
  124. agno/knowledge/reader/url_reader.py +84 -0
  125. agno/knowledge/reader/web_search_reader.py +389 -0
  126. agno/{document → knowledge}/reader/website_reader.py +37 -10
  127. agno/knowledge/reader/wikipedia_reader.py +59 -0
  128. agno/knowledge/reader/youtube_reader.py +78 -0
  129. agno/knowledge/remote_content/remote_content.py +88 -0
  130. agno/{reranker → knowledge/reranker}/base.py +1 -1
  131. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  132. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  133. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  134. agno/knowledge/types.py +30 -0
  135. agno/knowledge/utils.py +169 -0
  136. agno/media.py +2 -2
  137. agno/memory/__init__.py +2 -10
  138. agno/memory/manager.py +1003 -148
  139. agno/models/aimlapi/__init__.py +2 -2
  140. agno/models/aimlapi/aimlapi.py +6 -6
  141. agno/models/anthropic/claude.py +129 -82
  142. agno/models/aws/bedrock.py +107 -175
  143. agno/models/aws/claude.py +64 -18
  144. agno/models/azure/ai_foundry.py +73 -23
  145. agno/models/base.py +347 -287
  146. agno/models/cerebras/cerebras.py +84 -27
  147. agno/models/cohere/chat.py +106 -98
  148. agno/models/dashscope/dashscope.py +14 -5
  149. agno/models/google/gemini.py +123 -53
  150. agno/models/groq/groq.py +97 -35
  151. agno/models/huggingface/huggingface.py +92 -27
  152. agno/models/ibm/watsonx.py +72 -13
  153. agno/models/litellm/chat.py +85 -13
  154. agno/models/message.py +38 -144
  155. agno/models/meta/llama.py +85 -49
  156. agno/models/metrics.py +120 -0
  157. agno/models/mistral/mistral.py +90 -21
  158. agno/models/ollama/__init__.py +0 -2
  159. agno/models/ollama/chat.py +84 -46
  160. agno/models/openai/chat.py +135 -27
  161. agno/models/openai/responses.py +233 -115
  162. agno/models/perplexity/perplexity.py +26 -2
  163. agno/models/portkey/portkey.py +0 -7
  164. agno/models/response.py +14 -8
  165. agno/models/utils.py +20 -0
  166. agno/models/vercel/__init__.py +2 -2
  167. agno/models/vercel/v0.py +1 -1
  168. agno/models/vllm/__init__.py +2 -2
  169. agno/models/vllm/vllm.py +3 -3
  170. agno/models/xai/xai.py +10 -10
  171. agno/os/__init__.py +3 -0
  172. agno/os/app.py +393 -0
  173. agno/os/auth.py +47 -0
  174. agno/os/config.py +103 -0
  175. agno/os/interfaces/agui/__init__.py +3 -0
  176. agno/os/interfaces/agui/agui.py +31 -0
  177. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  178. agno/{app → os/interfaces}/agui/utils.py +65 -28
  179. agno/os/interfaces/base.py +21 -0
  180. agno/os/interfaces/slack/__init__.py +3 -0
  181. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  182. agno/os/interfaces/slack/slack.py +33 -0
  183. agno/os/interfaces/whatsapp/__init__.py +3 -0
  184. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  185. agno/os/interfaces/whatsapp/whatsapp.py +30 -0
  186. agno/os/router.py +843 -0
  187. agno/os/routers/__init__.py +3 -0
  188. agno/os/routers/evals/__init__.py +3 -0
  189. agno/os/routers/evals/evals.py +204 -0
  190. agno/os/routers/evals/schemas.py +142 -0
  191. agno/os/routers/evals/utils.py +161 -0
  192. agno/os/routers/knowledge/__init__.py +3 -0
  193. agno/os/routers/knowledge/knowledge.py +413 -0
  194. agno/os/routers/knowledge/schemas.py +118 -0
  195. agno/os/routers/memory/__init__.py +3 -0
  196. agno/os/routers/memory/memory.py +179 -0
  197. agno/os/routers/memory/schemas.py +58 -0
  198. agno/os/routers/metrics/__init__.py +3 -0
  199. agno/os/routers/metrics/metrics.py +58 -0
  200. agno/os/routers/metrics/schemas.py +47 -0
  201. agno/os/routers/session/__init__.py +3 -0
  202. agno/os/routers/session/session.py +163 -0
  203. agno/os/schema.py +892 -0
  204. agno/{app/playground → os}/settings.py +8 -15
  205. agno/os/utils.py +270 -0
  206. agno/reasoning/azure_ai_foundry.py +4 -4
  207. agno/reasoning/deepseek.py +4 -4
  208. agno/reasoning/default.py +6 -11
  209. agno/reasoning/groq.py +4 -4
  210. agno/reasoning/helpers.py +4 -6
  211. agno/reasoning/ollama.py +4 -4
  212. agno/reasoning/openai.py +4 -4
  213. agno/run/{response.py → agent.py} +144 -72
  214. agno/run/base.py +44 -58
  215. agno/run/cancel.py +83 -0
  216. agno/run/team.py +133 -77
  217. agno/run/workflow.py +537 -12
  218. agno/session/__init__.py +10 -0
  219. agno/session/agent.py +244 -0
  220. agno/session/summary.py +225 -0
  221. agno/session/team.py +262 -0
  222. agno/{storage/session/v2 → session}/workflow.py +47 -24
  223. agno/team/__init__.py +15 -16
  224. agno/team/team.py +2967 -4243
  225. agno/tools/agentql.py +14 -5
  226. agno/tools/airflow.py +9 -4
  227. agno/tools/api.py +7 -3
  228. agno/tools/apify.py +2 -46
  229. agno/tools/arxiv.py +8 -3
  230. agno/tools/aws_lambda.py +7 -5
  231. agno/tools/aws_ses.py +7 -1
  232. agno/tools/baidusearch.py +4 -1
  233. agno/tools/bitbucket.py +4 -4
  234. agno/tools/brandfetch.py +14 -11
  235. agno/tools/bravesearch.py +4 -1
  236. agno/tools/brightdata.py +42 -22
  237. agno/tools/browserbase.py +13 -4
  238. agno/tools/calcom.py +12 -10
  239. agno/tools/calculator.py +10 -27
  240. agno/tools/cartesia.py +18 -13
  241. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  242. agno/tools/confluence.py +71 -18
  243. agno/tools/crawl4ai.py +7 -1
  244. agno/tools/csv_toolkit.py +9 -8
  245. agno/tools/dalle.py +18 -11
  246. agno/tools/daytona.py +13 -16
  247. agno/tools/decorator.py +6 -3
  248. agno/tools/desi_vocal.py +16 -7
  249. agno/tools/discord.py +11 -8
  250. agno/tools/docker.py +30 -42
  251. agno/tools/duckdb.py +34 -53
  252. agno/tools/duckduckgo.py +8 -7
  253. agno/tools/e2b.py +62 -62
  254. agno/tools/eleven_labs.py +35 -28
  255. agno/tools/email.py +4 -1
  256. agno/tools/evm.py +7 -1
  257. agno/tools/exa.py +19 -14
  258. agno/tools/fal.py +29 -29
  259. agno/tools/file.py +9 -8
  260. agno/tools/financial_datasets.py +25 -44
  261. agno/tools/firecrawl.py +22 -22
  262. agno/tools/function.py +68 -17
  263. agno/tools/giphy.py +22 -10
  264. agno/tools/github.py +48 -126
  265. agno/tools/gmail.py +46 -62
  266. agno/tools/google_bigquery.py +7 -6
  267. agno/tools/google_maps.py +11 -26
  268. agno/tools/googlesearch.py +7 -2
  269. agno/tools/googlesheets.py +21 -17
  270. agno/tools/hackernews.py +9 -5
  271. agno/tools/jina.py +5 -4
  272. agno/tools/jira.py +18 -9
  273. agno/tools/knowledge.py +31 -32
  274. agno/tools/linear.py +18 -33
  275. agno/tools/linkup.py +5 -1
  276. agno/tools/local_file_system.py +8 -5
  277. agno/tools/lumalab.py +31 -19
  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 +32 -14
  282. agno/tools/models/gemini.py +58 -31
  283. agno/tools/models/groq.py +29 -20
  284. agno/tools/models/nebius.py +27 -11
  285. agno/tools/models_labs.py +39 -15
  286. agno/tools/moviepy_video.py +7 -6
  287. agno/tools/neo4j.py +134 -0
  288. agno/tools/newspaper.py +7 -2
  289. agno/tools/newspaper4k.py +8 -3
  290. agno/tools/openai.py +57 -26
  291. agno/tools/openbb.py +12 -11
  292. agno/tools/opencv.py +62 -46
  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 +54 -41
  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 +95 -118
  335. agno/utils/knowledge.py +29 -0
  336. agno/utils/location.py +2 -2
  337. agno/utils/log.py +2 -2
  338. agno/utils/mcp.py +11 -5
  339. agno/utils/media.py +39 -0
  340. agno/utils/message.py +12 -1
  341. agno/utils/models/claude.py +6 -4
  342. agno/utils/models/mistral.py +8 -7
  343. agno/utils/models/schema_utils.py +3 -3
  344. agno/utils/pprint.py +33 -32
  345. agno/utils/print_response/agent.py +779 -0
  346. agno/utils/print_response/team.py +1565 -0
  347. agno/utils/print_response/workflow.py +1451 -0
  348. agno/utils/prompts.py +14 -14
  349. agno/utils/reasoning.py +87 -0
  350. agno/utils/response.py +42 -42
  351. agno/utils/string.py +8 -22
  352. agno/utils/team.py +50 -0
  353. agno/utils/timer.py +2 -2
  354. agno/vectordb/base.py +33 -21
  355. agno/vectordb/cassandra/cassandra.py +287 -23
  356. agno/vectordb/chroma/chromadb.py +482 -59
  357. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  358. agno/vectordb/couchbase/couchbase.py +309 -29
  359. agno/vectordb/lancedb/lance_db.py +360 -21
  360. agno/vectordb/langchaindb/__init__.py +5 -0
  361. agno/vectordb/langchaindb/langchaindb.py +145 -0
  362. agno/vectordb/lightrag/__init__.py +5 -0
  363. agno/vectordb/lightrag/lightrag.py +374 -0
  364. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  365. agno/vectordb/milvus/milvus.py +242 -32
  366. agno/vectordb/mongodb/mongodb.py +200 -24
  367. agno/vectordb/pgvector/pgvector.py +319 -37
  368. agno/vectordb/pineconedb/pineconedb.py +221 -27
  369. agno/vectordb/qdrant/qdrant.py +356 -14
  370. agno/vectordb/singlestore/singlestore.py +286 -29
  371. agno/vectordb/surrealdb/surrealdb.py +187 -7
  372. agno/vectordb/upstashdb/upstashdb.py +342 -26
  373. agno/vectordb/weaviate/weaviate.py +227 -165
  374. agno/workflow/__init__.py +17 -13
  375. agno/workflow/{v2/condition.py → condition.py} +135 -32
  376. agno/workflow/{v2/loop.py → loop.py} +115 -28
  377. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  378. agno/workflow/{v2/router.py → router.py} +133 -32
  379. agno/workflow/{v2/step.py → step.py} +200 -42
  380. agno/workflow/{v2/steps.py → steps.py} +147 -66
  381. agno/workflow/types.py +482 -0
  382. agno/workflow/workflow.py +2394 -696
  383. agno-2.0.0a1.dist-info/METADATA +355 -0
  384. agno-2.0.0a1.dist-info/RECORD +514 -0
  385. agno/agent/metrics.py +0 -107
  386. agno/api/app.py +0 -35
  387. agno/api/playground.py +0 -92
  388. agno/api/schemas/app.py +0 -12
  389. agno/api/schemas/playground.py +0 -22
  390. agno/api/schemas/user.py +0 -35
  391. agno/api/schemas/workspace.py +0 -46
  392. agno/api/user.py +0 -160
  393. agno/api/workflows.py +0 -33
  394. agno/api/workspace.py +0 -175
  395. agno/app/agui/__init__.py +0 -3
  396. agno/app/agui/app.py +0 -17
  397. agno/app/agui/sync_router.py +0 -120
  398. agno/app/base.py +0 -186
  399. agno/app/discord/__init__.py +0 -3
  400. agno/app/fastapi/__init__.py +0 -3
  401. agno/app/fastapi/app.py +0 -107
  402. agno/app/fastapi/async_router.py +0 -457
  403. agno/app/fastapi/sync_router.py +0 -448
  404. agno/app/playground/app.py +0 -228
  405. agno/app/playground/async_router.py +0 -1050
  406. agno/app/playground/deploy.py +0 -249
  407. agno/app/playground/operator.py +0 -183
  408. agno/app/playground/schemas.py +0 -220
  409. agno/app/playground/serve.py +0 -55
  410. agno/app/playground/sync_router.py +0 -1042
  411. agno/app/playground/utils.py +0 -46
  412. agno/app/settings.py +0 -15
  413. agno/app/slack/__init__.py +0 -3
  414. agno/app/slack/app.py +0 -19
  415. agno/app/slack/sync_router.py +0 -92
  416. agno/app/utils.py +0 -54
  417. agno/app/whatsapp/__init__.py +0 -3
  418. agno/app/whatsapp/app.py +0 -15
  419. agno/app/whatsapp/sync_router.py +0 -197
  420. agno/cli/auth_server.py +0 -249
  421. agno/cli/config.py +0 -274
  422. agno/cli/console.py +0 -88
  423. agno/cli/credentials.py +0 -23
  424. agno/cli/entrypoint.py +0 -571
  425. agno/cli/operator.py +0 -357
  426. agno/cli/settings.py +0 -96
  427. agno/cli/ws/ws_cli.py +0 -817
  428. agno/constants.py +0 -13
  429. agno/document/__init__.py +0 -5
  430. agno/document/chunking/semantic.py +0 -45
  431. agno/document/chunking/strategy.py +0 -31
  432. agno/document/reader/__init__.py +0 -5
  433. agno/document/reader/base.py +0 -47
  434. agno/document/reader/docx_reader.py +0 -60
  435. agno/document/reader/gcs/pdf_reader.py +0 -44
  436. agno/document/reader/s3/pdf_reader.py +0 -59
  437. agno/document/reader/s3/text_reader.py +0 -63
  438. agno/document/reader/url_reader.py +0 -59
  439. agno/document/reader/youtube_reader.py +0 -58
  440. agno/embedder/__init__.py +0 -5
  441. agno/embedder/langdb.py +0 -80
  442. agno/embedder/mistral.py +0 -82
  443. agno/embedder/openai.py +0 -78
  444. agno/file/__init__.py +0 -5
  445. agno/file/file.py +0 -16
  446. agno/file/local/csv.py +0 -32
  447. agno/file/local/txt.py +0 -19
  448. agno/infra/app.py +0 -240
  449. agno/infra/base.py +0 -144
  450. agno/infra/context.py +0 -20
  451. agno/infra/db_app.py +0 -52
  452. agno/infra/resource.py +0 -205
  453. agno/infra/resources.py +0 -55
  454. agno/knowledge/agent.py +0 -698
  455. agno/knowledge/arxiv.py +0 -33
  456. agno/knowledge/combined.py +0 -36
  457. agno/knowledge/csv.py +0 -144
  458. agno/knowledge/csv_url.py +0 -124
  459. agno/knowledge/document.py +0 -223
  460. agno/knowledge/docx.py +0 -137
  461. agno/knowledge/firecrawl.py +0 -34
  462. agno/knowledge/gcs/__init__.py +0 -0
  463. agno/knowledge/gcs/base.py +0 -39
  464. agno/knowledge/gcs/pdf.py +0 -125
  465. agno/knowledge/json.py +0 -137
  466. agno/knowledge/langchain.py +0 -71
  467. agno/knowledge/light_rag.py +0 -273
  468. agno/knowledge/llamaindex.py +0 -66
  469. agno/knowledge/markdown.py +0 -154
  470. agno/knowledge/pdf.py +0 -164
  471. agno/knowledge/pdf_bytes.py +0 -42
  472. agno/knowledge/pdf_url.py +0 -148
  473. agno/knowledge/s3/__init__.py +0 -0
  474. agno/knowledge/s3/base.py +0 -64
  475. agno/knowledge/s3/pdf.py +0 -33
  476. agno/knowledge/s3/text.py +0 -34
  477. agno/knowledge/text.py +0 -141
  478. agno/knowledge/url.py +0 -46
  479. agno/knowledge/website.py +0 -179
  480. agno/knowledge/wikipedia.py +0 -32
  481. agno/knowledge/youtube.py +0 -35
  482. agno/memory/agent.py +0 -423
  483. agno/memory/classifier.py +0 -104
  484. agno/memory/db/__init__.py +0 -5
  485. agno/memory/db/base.py +0 -42
  486. agno/memory/db/mongodb.py +0 -189
  487. agno/memory/db/postgres.py +0 -203
  488. agno/memory/db/sqlite.py +0 -193
  489. agno/memory/memory.py +0 -22
  490. agno/memory/row.py +0 -36
  491. agno/memory/summarizer.py +0 -201
  492. agno/memory/summary.py +0 -19
  493. agno/memory/team.py +0 -415
  494. agno/memory/v2/__init__.py +0 -2
  495. agno/memory/v2/db/__init__.py +0 -1
  496. agno/memory/v2/db/base.py +0 -42
  497. agno/memory/v2/db/firestore.py +0 -339
  498. agno/memory/v2/db/mongodb.py +0 -196
  499. agno/memory/v2/db/postgres.py +0 -214
  500. agno/memory/v2/db/redis.py +0 -187
  501. agno/memory/v2/db/schema.py +0 -54
  502. agno/memory/v2/db/sqlite.py +0 -209
  503. agno/memory/v2/manager.py +0 -437
  504. agno/memory/v2/memory.py +0 -1097
  505. agno/memory/v2/schema.py +0 -55
  506. agno/memory/v2/summarizer.py +0 -215
  507. agno/memory/workflow.py +0 -38
  508. agno/models/ollama/tools.py +0 -430
  509. agno/models/qwen/__init__.py +0 -5
  510. agno/playground/__init__.py +0 -10
  511. agno/playground/deploy.py +0 -3
  512. agno/playground/playground.py +0 -3
  513. agno/playground/serve.py +0 -3
  514. agno/playground/settings.py +0 -3
  515. agno/reranker/__init__.py +0 -0
  516. agno/run/v2/__init__.py +0 -0
  517. agno/run/v2/workflow.py +0 -567
  518. agno/storage/__init__.py +0 -0
  519. agno/storage/agent/__init__.py +0 -0
  520. agno/storage/agent/dynamodb.py +0 -1
  521. agno/storage/agent/json.py +0 -1
  522. agno/storage/agent/mongodb.py +0 -1
  523. agno/storage/agent/postgres.py +0 -1
  524. agno/storage/agent/singlestore.py +0 -1
  525. agno/storage/agent/sqlite.py +0 -1
  526. agno/storage/agent/yaml.py +0 -1
  527. agno/storage/base.py +0 -60
  528. agno/storage/dynamodb.py +0 -673
  529. agno/storage/firestore.py +0 -297
  530. agno/storage/gcs_json.py +0 -261
  531. agno/storage/in_memory.py +0 -234
  532. agno/storage/json.py +0 -237
  533. agno/storage/mongodb.py +0 -328
  534. agno/storage/mysql.py +0 -685
  535. agno/storage/postgres.py +0 -682
  536. agno/storage/redis.py +0 -336
  537. agno/storage/session/__init__.py +0 -16
  538. agno/storage/session/agent.py +0 -64
  539. agno/storage/session/team.py +0 -63
  540. agno/storage/session/v2/__init__.py +0 -5
  541. agno/storage/session/workflow.py +0 -61
  542. agno/storage/singlestore.py +0 -606
  543. agno/storage/sqlite.py +0 -646
  544. agno/storage/workflow/__init__.py +0 -0
  545. agno/storage/workflow/mongodb.py +0 -1
  546. agno/storage/workflow/postgres.py +0 -1
  547. agno/storage/workflow/sqlite.py +0 -1
  548. agno/storage/yaml.py +0 -241
  549. agno/tools/thinking.py +0 -73
  550. agno/utils/defaults.py +0 -57
  551. agno/utils/filesystem.py +0 -39
  552. agno/utils/git.py +0 -52
  553. agno/utils/json_io.py +0 -30
  554. agno/utils/load_env.py +0 -19
  555. agno/utils/py_io.py +0 -19
  556. agno/utils/pyproject.py +0 -18
  557. agno/utils/resource_filter.py +0 -31
  558. agno/workflow/v2/__init__.py +0 -21
  559. agno/workflow/v2/types.py +0 -357
  560. agno/workflow/v2/workflow.py +0 -3312
  561. agno/workspace/__init__.py +0 -0
  562. agno/workspace/config.py +0 -325
  563. agno/workspace/enums.py +0 -6
  564. agno/workspace/helpers.py +0 -52
  565. agno/workspace/operator.py +0 -757
  566. agno/workspace/settings.py +0 -158
  567. agno-1.8.0.dist-info/METADATA +0 -979
  568. agno-1.8.0.dist-info/RECORD +0 -565
  569. agno-1.8.0.dist-info/entry_points.txt +0 -3
  570. /agno/{app → db/migrations}/__init__.py +0 -0
  571. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  572. /agno/{cli → integrations}/__init__.py +0 -0
  573. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  574. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  575. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  576. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  577. /agno/{app → os/interfaces}/slack/security.py +0 -0
  578. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  579. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  580. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  581. {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/WHEEL +0 -0
  582. {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
  583. {agno-1.8.0.dist-info → agno-2.0.0a1.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 AudioArtifact, File, ImageArtifact, VideoArtifact
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[ImageArtifact]] = None
23
+ videos: Optional[List[VideoArtifact]] = None
24
+ audio: Optional[List[AudioArtifact]] = 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[ImageArtifact]] = None
76
+ videos: Optional[List[VideoArtifact]] = None
77
+ audio: Optional[List[AudioArtifact]] = 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[ImageArtifact]] = None
229
+ videos: Optional[List[VideoArtifact]] = None
230
+ audio: Optional[List[AudioArtifact]] = 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 = [ImageArtifact.model_validate(img) for img in images]
286
+
287
+ videos = data.get("videos")
288
+ if videos:
289
+ videos = [VideoArtifact.model_validate(vid) for vid in videos]
290
+
291
+ audio = data.get("audio")
292
+ if audio:
293
+ audio = [AudioArtifact.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"