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

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