agno 2.2.13__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 (575) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +51 -0
  3. agno/agent/agent.py +10405 -0
  4. agno/api/__init__.py +0 -0
  5. agno/api/agent.py +28 -0
  6. agno/api/api.py +40 -0
  7. agno/api/evals.py +22 -0
  8. agno/api/os.py +17 -0
  9. agno/api/routes.py +13 -0
  10. agno/api/schemas/__init__.py +9 -0
  11. agno/api/schemas/agent.py +16 -0
  12. agno/api/schemas/evals.py +16 -0
  13. agno/api/schemas/os.py +14 -0
  14. agno/api/schemas/response.py +6 -0
  15. agno/api/schemas/team.py +16 -0
  16. agno/api/schemas/utils.py +21 -0
  17. agno/api/schemas/workflows.py +16 -0
  18. agno/api/settings.py +53 -0
  19. agno/api/team.py +30 -0
  20. agno/api/workflow.py +28 -0
  21. agno/cloud/aws/base.py +214 -0
  22. agno/cloud/aws/s3/__init__.py +2 -0
  23. agno/cloud/aws/s3/api_client.py +43 -0
  24. agno/cloud/aws/s3/bucket.py +195 -0
  25. agno/cloud/aws/s3/object.py +57 -0
  26. agno/culture/__init__.py +3 -0
  27. agno/culture/manager.py +956 -0
  28. agno/db/__init__.py +24 -0
  29. agno/db/async_postgres/__init__.py +3 -0
  30. agno/db/base.py +598 -0
  31. agno/db/dynamo/__init__.py +3 -0
  32. agno/db/dynamo/dynamo.py +2042 -0
  33. agno/db/dynamo/schemas.py +314 -0
  34. agno/db/dynamo/utils.py +743 -0
  35. agno/db/firestore/__init__.py +3 -0
  36. agno/db/firestore/firestore.py +1795 -0
  37. agno/db/firestore/schemas.py +140 -0
  38. agno/db/firestore/utils.py +376 -0
  39. agno/db/gcs_json/__init__.py +3 -0
  40. agno/db/gcs_json/gcs_json_db.py +1335 -0
  41. agno/db/gcs_json/utils.py +228 -0
  42. agno/db/in_memory/__init__.py +3 -0
  43. agno/db/in_memory/in_memory_db.py +1160 -0
  44. agno/db/in_memory/utils.py +230 -0
  45. agno/db/json/__init__.py +3 -0
  46. agno/db/json/json_db.py +1328 -0
  47. agno/db/json/utils.py +230 -0
  48. agno/db/migrations/__init__.py +0 -0
  49. agno/db/migrations/v1_to_v2.py +635 -0
  50. agno/db/mongo/__init__.py +17 -0
  51. agno/db/mongo/async_mongo.py +2026 -0
  52. agno/db/mongo/mongo.py +1982 -0
  53. agno/db/mongo/schemas.py +87 -0
  54. agno/db/mongo/utils.py +259 -0
  55. agno/db/mysql/__init__.py +3 -0
  56. agno/db/mysql/mysql.py +2308 -0
  57. agno/db/mysql/schemas.py +138 -0
  58. agno/db/mysql/utils.py +355 -0
  59. agno/db/postgres/__init__.py +4 -0
  60. agno/db/postgres/async_postgres.py +1927 -0
  61. agno/db/postgres/postgres.py +2260 -0
  62. agno/db/postgres/schemas.py +139 -0
  63. agno/db/postgres/utils.py +442 -0
  64. agno/db/redis/__init__.py +3 -0
  65. agno/db/redis/redis.py +1660 -0
  66. agno/db/redis/schemas.py +123 -0
  67. agno/db/redis/utils.py +346 -0
  68. agno/db/schemas/__init__.py +4 -0
  69. agno/db/schemas/culture.py +120 -0
  70. agno/db/schemas/evals.py +33 -0
  71. agno/db/schemas/knowledge.py +40 -0
  72. agno/db/schemas/memory.py +46 -0
  73. agno/db/schemas/metrics.py +0 -0
  74. agno/db/singlestore/__init__.py +3 -0
  75. agno/db/singlestore/schemas.py +130 -0
  76. agno/db/singlestore/singlestore.py +2272 -0
  77. agno/db/singlestore/utils.py +384 -0
  78. agno/db/sqlite/__init__.py +4 -0
  79. agno/db/sqlite/async_sqlite.py +2293 -0
  80. agno/db/sqlite/schemas.py +133 -0
  81. agno/db/sqlite/sqlite.py +2288 -0
  82. agno/db/sqlite/utils.py +431 -0
  83. agno/db/surrealdb/__init__.py +3 -0
  84. agno/db/surrealdb/metrics.py +292 -0
  85. agno/db/surrealdb/models.py +309 -0
  86. agno/db/surrealdb/queries.py +71 -0
  87. agno/db/surrealdb/surrealdb.py +1353 -0
  88. agno/db/surrealdb/utils.py +147 -0
  89. agno/db/utils.py +116 -0
  90. agno/debug.py +18 -0
  91. agno/eval/__init__.py +14 -0
  92. agno/eval/accuracy.py +834 -0
  93. agno/eval/performance.py +773 -0
  94. agno/eval/reliability.py +306 -0
  95. agno/eval/utils.py +119 -0
  96. agno/exceptions.py +161 -0
  97. agno/filters.py +354 -0
  98. agno/guardrails/__init__.py +6 -0
  99. agno/guardrails/base.py +19 -0
  100. agno/guardrails/openai.py +144 -0
  101. agno/guardrails/pii.py +94 -0
  102. agno/guardrails/prompt_injection.py +52 -0
  103. agno/integrations/__init__.py +0 -0
  104. agno/integrations/discord/__init__.py +3 -0
  105. agno/integrations/discord/client.py +203 -0
  106. agno/knowledge/__init__.py +5 -0
  107. agno/knowledge/chunking/__init__.py +0 -0
  108. agno/knowledge/chunking/agentic.py +79 -0
  109. agno/knowledge/chunking/document.py +91 -0
  110. agno/knowledge/chunking/fixed.py +57 -0
  111. agno/knowledge/chunking/markdown.py +151 -0
  112. agno/knowledge/chunking/recursive.py +63 -0
  113. agno/knowledge/chunking/row.py +39 -0
  114. agno/knowledge/chunking/semantic.py +86 -0
  115. agno/knowledge/chunking/strategy.py +165 -0
  116. agno/knowledge/content.py +74 -0
  117. agno/knowledge/document/__init__.py +5 -0
  118. agno/knowledge/document/base.py +58 -0
  119. agno/knowledge/embedder/__init__.py +5 -0
  120. agno/knowledge/embedder/aws_bedrock.py +343 -0
  121. agno/knowledge/embedder/azure_openai.py +210 -0
  122. agno/knowledge/embedder/base.py +23 -0
  123. agno/knowledge/embedder/cohere.py +323 -0
  124. agno/knowledge/embedder/fastembed.py +62 -0
  125. agno/knowledge/embedder/fireworks.py +13 -0
  126. agno/knowledge/embedder/google.py +258 -0
  127. agno/knowledge/embedder/huggingface.py +94 -0
  128. agno/knowledge/embedder/jina.py +182 -0
  129. agno/knowledge/embedder/langdb.py +22 -0
  130. agno/knowledge/embedder/mistral.py +206 -0
  131. agno/knowledge/embedder/nebius.py +13 -0
  132. agno/knowledge/embedder/ollama.py +154 -0
  133. agno/knowledge/embedder/openai.py +195 -0
  134. agno/knowledge/embedder/sentence_transformer.py +63 -0
  135. agno/knowledge/embedder/together.py +13 -0
  136. agno/knowledge/embedder/vllm.py +262 -0
  137. agno/knowledge/embedder/voyageai.py +165 -0
  138. agno/knowledge/knowledge.py +1988 -0
  139. agno/knowledge/reader/__init__.py +7 -0
  140. agno/knowledge/reader/arxiv_reader.py +81 -0
  141. agno/knowledge/reader/base.py +95 -0
  142. agno/knowledge/reader/csv_reader.py +166 -0
  143. agno/knowledge/reader/docx_reader.py +82 -0
  144. agno/knowledge/reader/field_labeled_csv_reader.py +292 -0
  145. agno/knowledge/reader/firecrawl_reader.py +201 -0
  146. agno/knowledge/reader/json_reader.py +87 -0
  147. agno/knowledge/reader/markdown_reader.py +137 -0
  148. agno/knowledge/reader/pdf_reader.py +431 -0
  149. agno/knowledge/reader/pptx_reader.py +101 -0
  150. agno/knowledge/reader/reader_factory.py +313 -0
  151. agno/knowledge/reader/s3_reader.py +89 -0
  152. agno/knowledge/reader/tavily_reader.py +194 -0
  153. agno/knowledge/reader/text_reader.py +115 -0
  154. agno/knowledge/reader/web_search_reader.py +372 -0
  155. agno/knowledge/reader/website_reader.py +455 -0
  156. agno/knowledge/reader/wikipedia_reader.py +59 -0
  157. agno/knowledge/reader/youtube_reader.py +78 -0
  158. agno/knowledge/remote_content/__init__.py +0 -0
  159. agno/knowledge/remote_content/remote_content.py +88 -0
  160. agno/knowledge/reranker/__init__.py +3 -0
  161. agno/knowledge/reranker/base.py +14 -0
  162. agno/knowledge/reranker/cohere.py +64 -0
  163. agno/knowledge/reranker/infinity.py +195 -0
  164. agno/knowledge/reranker/sentence_transformer.py +54 -0
  165. agno/knowledge/types.py +39 -0
  166. agno/knowledge/utils.py +189 -0
  167. agno/media.py +462 -0
  168. agno/memory/__init__.py +3 -0
  169. agno/memory/manager.py +1327 -0
  170. agno/models/__init__.py +0 -0
  171. agno/models/aimlapi/__init__.py +5 -0
  172. agno/models/aimlapi/aimlapi.py +45 -0
  173. agno/models/anthropic/__init__.py +5 -0
  174. agno/models/anthropic/claude.py +757 -0
  175. agno/models/aws/__init__.py +15 -0
  176. agno/models/aws/bedrock.py +701 -0
  177. agno/models/aws/claude.py +378 -0
  178. agno/models/azure/__init__.py +18 -0
  179. agno/models/azure/ai_foundry.py +485 -0
  180. agno/models/azure/openai_chat.py +131 -0
  181. agno/models/base.py +2175 -0
  182. agno/models/cerebras/__init__.py +12 -0
  183. agno/models/cerebras/cerebras.py +501 -0
  184. agno/models/cerebras/cerebras_openai.py +112 -0
  185. agno/models/cohere/__init__.py +5 -0
  186. agno/models/cohere/chat.py +389 -0
  187. agno/models/cometapi/__init__.py +5 -0
  188. agno/models/cometapi/cometapi.py +57 -0
  189. agno/models/dashscope/__init__.py +5 -0
  190. agno/models/dashscope/dashscope.py +91 -0
  191. agno/models/deepinfra/__init__.py +5 -0
  192. agno/models/deepinfra/deepinfra.py +28 -0
  193. agno/models/deepseek/__init__.py +5 -0
  194. agno/models/deepseek/deepseek.py +61 -0
  195. agno/models/defaults.py +1 -0
  196. agno/models/fireworks/__init__.py +5 -0
  197. agno/models/fireworks/fireworks.py +26 -0
  198. agno/models/google/__init__.py +5 -0
  199. agno/models/google/gemini.py +1085 -0
  200. agno/models/groq/__init__.py +5 -0
  201. agno/models/groq/groq.py +556 -0
  202. agno/models/huggingface/__init__.py +5 -0
  203. agno/models/huggingface/huggingface.py +491 -0
  204. agno/models/ibm/__init__.py +5 -0
  205. agno/models/ibm/watsonx.py +422 -0
  206. agno/models/internlm/__init__.py +3 -0
  207. agno/models/internlm/internlm.py +26 -0
  208. agno/models/langdb/__init__.py +1 -0
  209. agno/models/langdb/langdb.py +48 -0
  210. agno/models/litellm/__init__.py +14 -0
  211. agno/models/litellm/chat.py +468 -0
  212. agno/models/litellm/litellm_openai.py +25 -0
  213. agno/models/llama_cpp/__init__.py +5 -0
  214. agno/models/llama_cpp/llama_cpp.py +22 -0
  215. agno/models/lmstudio/__init__.py +5 -0
  216. agno/models/lmstudio/lmstudio.py +25 -0
  217. agno/models/message.py +434 -0
  218. agno/models/meta/__init__.py +12 -0
  219. agno/models/meta/llama.py +475 -0
  220. agno/models/meta/llama_openai.py +78 -0
  221. agno/models/metrics.py +120 -0
  222. agno/models/mistral/__init__.py +5 -0
  223. agno/models/mistral/mistral.py +432 -0
  224. agno/models/nebius/__init__.py +3 -0
  225. agno/models/nebius/nebius.py +54 -0
  226. agno/models/nexus/__init__.py +3 -0
  227. agno/models/nexus/nexus.py +22 -0
  228. agno/models/nvidia/__init__.py +5 -0
  229. agno/models/nvidia/nvidia.py +28 -0
  230. agno/models/ollama/__init__.py +5 -0
  231. agno/models/ollama/chat.py +441 -0
  232. agno/models/openai/__init__.py +9 -0
  233. agno/models/openai/chat.py +883 -0
  234. agno/models/openai/like.py +27 -0
  235. agno/models/openai/responses.py +1050 -0
  236. agno/models/openrouter/__init__.py +5 -0
  237. agno/models/openrouter/openrouter.py +66 -0
  238. agno/models/perplexity/__init__.py +5 -0
  239. agno/models/perplexity/perplexity.py +187 -0
  240. agno/models/portkey/__init__.py +3 -0
  241. agno/models/portkey/portkey.py +81 -0
  242. agno/models/requesty/__init__.py +5 -0
  243. agno/models/requesty/requesty.py +52 -0
  244. agno/models/response.py +199 -0
  245. agno/models/sambanova/__init__.py +5 -0
  246. agno/models/sambanova/sambanova.py +28 -0
  247. agno/models/siliconflow/__init__.py +5 -0
  248. agno/models/siliconflow/siliconflow.py +25 -0
  249. agno/models/together/__init__.py +5 -0
  250. agno/models/together/together.py +25 -0
  251. agno/models/utils.py +266 -0
  252. agno/models/vercel/__init__.py +3 -0
  253. agno/models/vercel/v0.py +26 -0
  254. agno/models/vertexai/__init__.py +0 -0
  255. agno/models/vertexai/claude.py +70 -0
  256. agno/models/vllm/__init__.py +3 -0
  257. agno/models/vllm/vllm.py +78 -0
  258. agno/models/xai/__init__.py +3 -0
  259. agno/models/xai/xai.py +113 -0
  260. agno/os/__init__.py +3 -0
  261. agno/os/app.py +876 -0
  262. agno/os/auth.py +57 -0
  263. agno/os/config.py +104 -0
  264. agno/os/interfaces/__init__.py +1 -0
  265. agno/os/interfaces/a2a/__init__.py +3 -0
  266. agno/os/interfaces/a2a/a2a.py +42 -0
  267. agno/os/interfaces/a2a/router.py +250 -0
  268. agno/os/interfaces/a2a/utils.py +924 -0
  269. agno/os/interfaces/agui/__init__.py +3 -0
  270. agno/os/interfaces/agui/agui.py +47 -0
  271. agno/os/interfaces/agui/router.py +144 -0
  272. agno/os/interfaces/agui/utils.py +534 -0
  273. agno/os/interfaces/base.py +25 -0
  274. agno/os/interfaces/slack/__init__.py +3 -0
  275. agno/os/interfaces/slack/router.py +148 -0
  276. agno/os/interfaces/slack/security.py +30 -0
  277. agno/os/interfaces/slack/slack.py +47 -0
  278. agno/os/interfaces/whatsapp/__init__.py +3 -0
  279. agno/os/interfaces/whatsapp/router.py +211 -0
  280. agno/os/interfaces/whatsapp/security.py +53 -0
  281. agno/os/interfaces/whatsapp/whatsapp.py +36 -0
  282. agno/os/mcp.py +292 -0
  283. agno/os/middleware/__init__.py +7 -0
  284. agno/os/middleware/jwt.py +233 -0
  285. agno/os/router.py +1763 -0
  286. agno/os/routers/__init__.py +3 -0
  287. agno/os/routers/evals/__init__.py +3 -0
  288. agno/os/routers/evals/evals.py +430 -0
  289. agno/os/routers/evals/schemas.py +142 -0
  290. agno/os/routers/evals/utils.py +162 -0
  291. agno/os/routers/health.py +31 -0
  292. agno/os/routers/home.py +52 -0
  293. agno/os/routers/knowledge/__init__.py +3 -0
  294. agno/os/routers/knowledge/knowledge.py +997 -0
  295. agno/os/routers/knowledge/schemas.py +178 -0
  296. agno/os/routers/memory/__init__.py +3 -0
  297. agno/os/routers/memory/memory.py +515 -0
  298. agno/os/routers/memory/schemas.py +62 -0
  299. agno/os/routers/metrics/__init__.py +3 -0
  300. agno/os/routers/metrics/metrics.py +190 -0
  301. agno/os/routers/metrics/schemas.py +47 -0
  302. agno/os/routers/session/__init__.py +3 -0
  303. agno/os/routers/session/session.py +997 -0
  304. agno/os/schema.py +1055 -0
  305. agno/os/settings.py +43 -0
  306. agno/os/utils.py +630 -0
  307. agno/py.typed +0 -0
  308. agno/reasoning/__init__.py +0 -0
  309. agno/reasoning/anthropic.py +80 -0
  310. agno/reasoning/azure_ai_foundry.py +67 -0
  311. agno/reasoning/deepseek.py +63 -0
  312. agno/reasoning/default.py +97 -0
  313. agno/reasoning/gemini.py +73 -0
  314. agno/reasoning/groq.py +71 -0
  315. agno/reasoning/helpers.py +63 -0
  316. agno/reasoning/ollama.py +67 -0
  317. agno/reasoning/openai.py +86 -0
  318. agno/reasoning/step.py +31 -0
  319. agno/reasoning/vertexai.py +76 -0
  320. agno/run/__init__.py +6 -0
  321. agno/run/agent.py +787 -0
  322. agno/run/base.py +229 -0
  323. agno/run/cancel.py +81 -0
  324. agno/run/messages.py +32 -0
  325. agno/run/team.py +753 -0
  326. agno/run/workflow.py +708 -0
  327. agno/session/__init__.py +10 -0
  328. agno/session/agent.py +295 -0
  329. agno/session/summary.py +265 -0
  330. agno/session/team.py +392 -0
  331. agno/session/workflow.py +205 -0
  332. agno/team/__init__.py +37 -0
  333. agno/team/team.py +8793 -0
  334. agno/tools/__init__.py +10 -0
  335. agno/tools/agentql.py +120 -0
  336. agno/tools/airflow.py +69 -0
  337. agno/tools/api.py +122 -0
  338. agno/tools/apify.py +314 -0
  339. agno/tools/arxiv.py +127 -0
  340. agno/tools/aws_lambda.py +53 -0
  341. agno/tools/aws_ses.py +66 -0
  342. agno/tools/baidusearch.py +89 -0
  343. agno/tools/bitbucket.py +292 -0
  344. agno/tools/brandfetch.py +213 -0
  345. agno/tools/bravesearch.py +106 -0
  346. agno/tools/brightdata.py +367 -0
  347. agno/tools/browserbase.py +209 -0
  348. agno/tools/calcom.py +255 -0
  349. agno/tools/calculator.py +151 -0
  350. agno/tools/cartesia.py +187 -0
  351. agno/tools/clickup.py +244 -0
  352. agno/tools/confluence.py +240 -0
  353. agno/tools/crawl4ai.py +158 -0
  354. agno/tools/csv_toolkit.py +185 -0
  355. agno/tools/dalle.py +110 -0
  356. agno/tools/daytona.py +475 -0
  357. agno/tools/decorator.py +262 -0
  358. agno/tools/desi_vocal.py +108 -0
  359. agno/tools/discord.py +161 -0
  360. agno/tools/docker.py +716 -0
  361. agno/tools/duckdb.py +379 -0
  362. agno/tools/duckduckgo.py +91 -0
  363. agno/tools/e2b.py +703 -0
  364. agno/tools/eleven_labs.py +196 -0
  365. agno/tools/email.py +67 -0
  366. agno/tools/evm.py +129 -0
  367. agno/tools/exa.py +396 -0
  368. agno/tools/fal.py +127 -0
  369. agno/tools/file.py +240 -0
  370. agno/tools/file_generation.py +350 -0
  371. agno/tools/financial_datasets.py +288 -0
  372. agno/tools/firecrawl.py +143 -0
  373. agno/tools/function.py +1187 -0
  374. agno/tools/giphy.py +93 -0
  375. agno/tools/github.py +1760 -0
  376. agno/tools/gmail.py +922 -0
  377. agno/tools/google_bigquery.py +117 -0
  378. agno/tools/google_drive.py +270 -0
  379. agno/tools/google_maps.py +253 -0
  380. agno/tools/googlecalendar.py +674 -0
  381. agno/tools/googlesearch.py +98 -0
  382. agno/tools/googlesheets.py +377 -0
  383. agno/tools/hackernews.py +77 -0
  384. agno/tools/jina.py +101 -0
  385. agno/tools/jira.py +170 -0
  386. agno/tools/knowledge.py +218 -0
  387. agno/tools/linear.py +426 -0
  388. agno/tools/linkup.py +58 -0
  389. agno/tools/local_file_system.py +90 -0
  390. agno/tools/lumalab.py +183 -0
  391. agno/tools/mcp/__init__.py +10 -0
  392. agno/tools/mcp/mcp.py +331 -0
  393. agno/tools/mcp/multi_mcp.py +347 -0
  394. agno/tools/mcp/params.py +24 -0
  395. agno/tools/mcp_toolbox.py +284 -0
  396. agno/tools/mem0.py +193 -0
  397. agno/tools/memori.py +339 -0
  398. agno/tools/memory.py +419 -0
  399. agno/tools/mlx_transcribe.py +139 -0
  400. agno/tools/models/__init__.py +0 -0
  401. agno/tools/models/azure_openai.py +190 -0
  402. agno/tools/models/gemini.py +203 -0
  403. agno/tools/models/groq.py +158 -0
  404. agno/tools/models/morph.py +186 -0
  405. agno/tools/models/nebius.py +124 -0
  406. agno/tools/models_labs.py +195 -0
  407. agno/tools/moviepy_video.py +349 -0
  408. agno/tools/neo4j.py +134 -0
  409. agno/tools/newspaper.py +46 -0
  410. agno/tools/newspaper4k.py +93 -0
  411. agno/tools/notion.py +204 -0
  412. agno/tools/openai.py +202 -0
  413. agno/tools/openbb.py +160 -0
  414. agno/tools/opencv.py +321 -0
  415. agno/tools/openweather.py +233 -0
  416. agno/tools/oxylabs.py +385 -0
  417. agno/tools/pandas.py +102 -0
  418. agno/tools/parallel.py +314 -0
  419. agno/tools/postgres.py +257 -0
  420. agno/tools/pubmed.py +188 -0
  421. agno/tools/python.py +205 -0
  422. agno/tools/reasoning.py +283 -0
  423. agno/tools/reddit.py +467 -0
  424. agno/tools/replicate.py +117 -0
  425. agno/tools/resend.py +62 -0
  426. agno/tools/scrapegraph.py +222 -0
  427. agno/tools/searxng.py +152 -0
  428. agno/tools/serpapi.py +116 -0
  429. agno/tools/serper.py +255 -0
  430. agno/tools/shell.py +53 -0
  431. agno/tools/slack.py +136 -0
  432. agno/tools/sleep.py +20 -0
  433. agno/tools/spider.py +116 -0
  434. agno/tools/sql.py +154 -0
  435. agno/tools/streamlit/__init__.py +0 -0
  436. agno/tools/streamlit/components.py +113 -0
  437. agno/tools/tavily.py +254 -0
  438. agno/tools/telegram.py +48 -0
  439. agno/tools/todoist.py +218 -0
  440. agno/tools/tool_registry.py +1 -0
  441. agno/tools/toolkit.py +146 -0
  442. agno/tools/trafilatura.py +388 -0
  443. agno/tools/trello.py +274 -0
  444. agno/tools/twilio.py +186 -0
  445. agno/tools/user_control_flow.py +78 -0
  446. agno/tools/valyu.py +228 -0
  447. agno/tools/visualization.py +467 -0
  448. agno/tools/webbrowser.py +28 -0
  449. agno/tools/webex.py +76 -0
  450. agno/tools/website.py +54 -0
  451. agno/tools/webtools.py +45 -0
  452. agno/tools/whatsapp.py +286 -0
  453. agno/tools/wikipedia.py +63 -0
  454. agno/tools/workflow.py +278 -0
  455. agno/tools/x.py +335 -0
  456. agno/tools/yfinance.py +257 -0
  457. agno/tools/youtube.py +184 -0
  458. agno/tools/zendesk.py +82 -0
  459. agno/tools/zep.py +454 -0
  460. agno/tools/zoom.py +382 -0
  461. agno/utils/__init__.py +0 -0
  462. agno/utils/agent.py +820 -0
  463. agno/utils/audio.py +49 -0
  464. agno/utils/certs.py +27 -0
  465. agno/utils/code_execution.py +11 -0
  466. agno/utils/common.py +132 -0
  467. agno/utils/dttm.py +13 -0
  468. agno/utils/enum.py +22 -0
  469. agno/utils/env.py +11 -0
  470. agno/utils/events.py +696 -0
  471. agno/utils/format_str.py +16 -0
  472. agno/utils/functions.py +166 -0
  473. agno/utils/gemini.py +426 -0
  474. agno/utils/hooks.py +57 -0
  475. agno/utils/http.py +74 -0
  476. agno/utils/json_schema.py +234 -0
  477. agno/utils/knowledge.py +36 -0
  478. agno/utils/location.py +19 -0
  479. agno/utils/log.py +255 -0
  480. agno/utils/mcp.py +214 -0
  481. agno/utils/media.py +352 -0
  482. agno/utils/merge_dict.py +41 -0
  483. agno/utils/message.py +118 -0
  484. agno/utils/models/__init__.py +0 -0
  485. agno/utils/models/ai_foundry.py +43 -0
  486. agno/utils/models/claude.py +358 -0
  487. agno/utils/models/cohere.py +87 -0
  488. agno/utils/models/llama.py +78 -0
  489. agno/utils/models/mistral.py +98 -0
  490. agno/utils/models/openai_responses.py +140 -0
  491. agno/utils/models/schema_utils.py +153 -0
  492. agno/utils/models/watsonx.py +41 -0
  493. agno/utils/openai.py +257 -0
  494. agno/utils/pickle.py +32 -0
  495. agno/utils/pprint.py +178 -0
  496. agno/utils/print_response/__init__.py +0 -0
  497. agno/utils/print_response/agent.py +842 -0
  498. agno/utils/print_response/team.py +1724 -0
  499. agno/utils/print_response/workflow.py +1668 -0
  500. agno/utils/prompts.py +111 -0
  501. agno/utils/reasoning.py +108 -0
  502. agno/utils/response.py +163 -0
  503. agno/utils/response_iterator.py +17 -0
  504. agno/utils/safe_formatter.py +24 -0
  505. agno/utils/serialize.py +32 -0
  506. agno/utils/shell.py +22 -0
  507. agno/utils/streamlit.py +487 -0
  508. agno/utils/string.py +231 -0
  509. agno/utils/team.py +139 -0
  510. agno/utils/timer.py +41 -0
  511. agno/utils/tools.py +102 -0
  512. agno/utils/web.py +23 -0
  513. agno/utils/whatsapp.py +305 -0
  514. agno/utils/yaml_io.py +25 -0
  515. agno/vectordb/__init__.py +3 -0
  516. agno/vectordb/base.py +127 -0
  517. agno/vectordb/cassandra/__init__.py +5 -0
  518. agno/vectordb/cassandra/cassandra.py +501 -0
  519. agno/vectordb/cassandra/extra_param_mixin.py +11 -0
  520. agno/vectordb/cassandra/index.py +13 -0
  521. agno/vectordb/chroma/__init__.py +5 -0
  522. agno/vectordb/chroma/chromadb.py +929 -0
  523. agno/vectordb/clickhouse/__init__.py +9 -0
  524. agno/vectordb/clickhouse/clickhousedb.py +835 -0
  525. agno/vectordb/clickhouse/index.py +9 -0
  526. agno/vectordb/couchbase/__init__.py +3 -0
  527. agno/vectordb/couchbase/couchbase.py +1442 -0
  528. agno/vectordb/distance.py +7 -0
  529. agno/vectordb/lancedb/__init__.py +6 -0
  530. agno/vectordb/lancedb/lance_db.py +995 -0
  531. agno/vectordb/langchaindb/__init__.py +5 -0
  532. agno/vectordb/langchaindb/langchaindb.py +163 -0
  533. agno/vectordb/lightrag/__init__.py +5 -0
  534. agno/vectordb/lightrag/lightrag.py +388 -0
  535. agno/vectordb/llamaindex/__init__.py +3 -0
  536. agno/vectordb/llamaindex/llamaindexdb.py +166 -0
  537. agno/vectordb/milvus/__init__.py +4 -0
  538. agno/vectordb/milvus/milvus.py +1182 -0
  539. agno/vectordb/mongodb/__init__.py +9 -0
  540. agno/vectordb/mongodb/mongodb.py +1417 -0
  541. agno/vectordb/pgvector/__init__.py +12 -0
  542. agno/vectordb/pgvector/index.py +23 -0
  543. agno/vectordb/pgvector/pgvector.py +1462 -0
  544. agno/vectordb/pineconedb/__init__.py +5 -0
  545. agno/vectordb/pineconedb/pineconedb.py +747 -0
  546. agno/vectordb/qdrant/__init__.py +5 -0
  547. agno/vectordb/qdrant/qdrant.py +1134 -0
  548. agno/vectordb/redis/__init__.py +9 -0
  549. agno/vectordb/redis/redisdb.py +694 -0
  550. agno/vectordb/search.py +7 -0
  551. agno/vectordb/singlestore/__init__.py +10 -0
  552. agno/vectordb/singlestore/index.py +41 -0
  553. agno/vectordb/singlestore/singlestore.py +763 -0
  554. agno/vectordb/surrealdb/__init__.py +3 -0
  555. agno/vectordb/surrealdb/surrealdb.py +699 -0
  556. agno/vectordb/upstashdb/__init__.py +5 -0
  557. agno/vectordb/upstashdb/upstashdb.py +718 -0
  558. agno/vectordb/weaviate/__init__.py +8 -0
  559. agno/vectordb/weaviate/index.py +15 -0
  560. agno/vectordb/weaviate/weaviate.py +1005 -0
  561. agno/workflow/__init__.py +23 -0
  562. agno/workflow/agent.py +299 -0
  563. agno/workflow/condition.py +738 -0
  564. agno/workflow/loop.py +735 -0
  565. agno/workflow/parallel.py +824 -0
  566. agno/workflow/router.py +702 -0
  567. agno/workflow/step.py +1432 -0
  568. agno/workflow/steps.py +592 -0
  569. agno/workflow/types.py +520 -0
  570. agno/workflow/workflow.py +4321 -0
  571. agno-2.2.13.dist-info/METADATA +614 -0
  572. agno-2.2.13.dist-info/RECORD +575 -0
  573. agno-2.2.13.dist-info/WHEEL +5 -0
  574. agno-2.2.13.dist-info/licenses/LICENSE +201 -0
  575. agno-2.2.13.dist-info/top_level.txt +1 -0
agno/workflow/types.py ADDED
@@ -0,0 +1,520 @@
1
+ import json
2
+ from dataclasses import dataclass
3
+ from enum import Enum
4
+ from typing import Any, Dict, List, Optional, Tuple, Union
5
+
6
+ from fastapi import WebSocket
7
+ from pydantic import BaseModel
8
+
9
+ from agno.media import Audio, File, Image, Video
10
+ from agno.models.metrics import Metrics
11
+ from agno.session.workflow import WorkflowSession
12
+ from agno.utils.log import log_warning
13
+ from agno.utils.media import (
14
+ reconstruct_audio_list,
15
+ reconstruct_files,
16
+ reconstruct_images,
17
+ reconstruct_videos,
18
+ )
19
+ from agno.utils.serialize import json_serializer
20
+ from agno.utils.timer import Timer
21
+
22
+
23
+ @dataclass
24
+ class WorkflowExecutionInput:
25
+ """Input data for a step execution"""
26
+
27
+ input: Optional[Union[str, Dict[str, Any], List[Any], BaseModel]] = None
28
+
29
+ additional_data: Optional[Dict[str, Any]] = None
30
+
31
+ # Media inputs
32
+ images: Optional[List[Image]] = None
33
+ videos: Optional[List[Video]] = None
34
+ audio: Optional[List[Audio]] = None
35
+ files: Optional[List[File]] = None
36
+
37
+ def get_input_as_string(self) -> Optional[str]:
38
+ """Convert input to string representation"""
39
+ if self.input is None:
40
+ return None
41
+
42
+ if isinstance(self.input, str):
43
+ return self.input
44
+ elif isinstance(self.input, BaseModel):
45
+ return self.input.model_dump_json(indent=2, exclude_none=True)
46
+ elif isinstance(self.input, (dict, list)):
47
+ import json
48
+
49
+ return json.dumps(self.input, indent=2, default=str)
50
+ else:
51
+ return str(self.input)
52
+
53
+ def to_dict(self) -> Dict[str, Any]:
54
+ """Convert to dictionary"""
55
+ input_dict: Optional[Union[str, Dict[str, Any], List[Any]]] = None
56
+ if self.input is not None:
57
+ if isinstance(self.input, BaseModel):
58
+ input_dict = self.input.model_dump(exclude_none=True)
59
+ elif isinstance(self.input, (dict, list)):
60
+ input_dict = self.input
61
+ else:
62
+ input_dict = str(self.input)
63
+
64
+ return {
65
+ "input": input_dict,
66
+ "additional_data": self.additional_data,
67
+ "images": [img.to_dict() for img in self.images] if self.images else None,
68
+ "videos": [vid.to_dict() for vid in self.videos] if self.videos else None,
69
+ "audio": [aud.to_dict() for aud in self.audio] if self.audio else None,
70
+ "files": [file.to_dict() for file in self.files] if self.files else None,
71
+ }
72
+
73
+
74
+ @dataclass
75
+ class StepInput:
76
+ """Input data for a step execution"""
77
+
78
+ input: Optional[Union[str, Dict[str, Any], List[Any], BaseModel]] = None
79
+
80
+ previous_step_content: Optional[Any] = None
81
+ previous_step_outputs: Optional[Dict[str, "StepOutput"]] = None
82
+
83
+ additional_data: Optional[Dict[str, Any]] = None
84
+
85
+ # Media inputs
86
+ images: Optional[List[Image]] = None
87
+ videos: Optional[List[Video]] = None
88
+ audio: Optional[List[Audio]] = None
89
+ files: Optional[List[File]] = None
90
+
91
+ workflow_session: Optional["WorkflowSession"] = None
92
+
93
+ def get_input_as_string(self) -> Optional[str]:
94
+ """Convert input to string representation"""
95
+ if self.input is None:
96
+ return None
97
+
98
+ if isinstance(self.input, str):
99
+ return self.input
100
+ elif isinstance(self.input, BaseModel):
101
+ return self.input.model_dump_json(indent=2, exclude_none=True)
102
+ elif isinstance(self.input, (dict, list)):
103
+ import json
104
+
105
+ return json.dumps(self.input, indent=2, default=str)
106
+ else:
107
+ return str(self.input)
108
+
109
+ def get_step_output(self, step_name: str) -> Optional["StepOutput"]:
110
+ """Get output from a specific previous step by name"""
111
+ if not self.previous_step_outputs:
112
+ return None
113
+ return self.previous_step_outputs.get(step_name)
114
+
115
+ def get_step_content(self, step_name: str) -> Optional[Union[str, Dict[str, str]]]:
116
+ """Get content from a specific previous step by name
117
+
118
+ For parallel steps, if you ask for the parallel step name, returns a dict
119
+ with {step_name: content} for each sub-step.
120
+ For other nested steps (Condition, Router, Loop, Steps), returns the deepest content.
121
+ """
122
+ step_output = self.get_step_output(step_name)
123
+ if not step_output:
124
+ return None
125
+
126
+ # Check if this is a parallel step with nested steps
127
+ if step_output.step_type == "Parallel" and step_output.steps:
128
+ # Return dict with {step_name: content} for each sub-step
129
+ parallel_content = {}
130
+ for sub_step in step_output.steps:
131
+ if sub_step.step_name and sub_step.content:
132
+ # Check if this sub-step has its own nested steps (like Condition -> Research Step)
133
+ if sub_step.steps and len(sub_step.steps) > 0:
134
+ # This is a composite step (like Condition) - get content from its nested steps
135
+ for nested_step in sub_step.steps:
136
+ if nested_step.step_name and nested_step.content:
137
+ parallel_content[nested_step.step_name] = str(nested_step.content)
138
+ else:
139
+ # This is a direct step - use its content
140
+ parallel_content[sub_step.step_name] = str(sub_step.content)
141
+ return parallel_content if parallel_content else str(step_output.content)
142
+
143
+ # For other nested step types (Condition, Router, Loop, Steps), get the deepest content
144
+ elif step_output.steps and len(step_output.steps) > 0:
145
+ # This is a nested step structure - recursively get the deepest content
146
+ return self._get_deepest_step_content(step_output.steps[-1])
147
+
148
+ # Regular step, return content directly
149
+ return step_output.content # type: ignore[return-value]
150
+
151
+ def _get_deepest_step_content(self, step_output: "StepOutput") -> Optional[Union[str, Dict[str, str]]]:
152
+ """Helper method to recursively extract deepest content from nested steps"""
153
+ # If this step has nested steps, go deeper
154
+ if step_output.steps and len(step_output.steps) > 0:
155
+ return self._get_deepest_step_content(step_output.steps[-1])
156
+
157
+ # Return the content of this step
158
+ return step_output.content # type: ignore[return-value]
159
+
160
+ def get_all_previous_content(self) -> str:
161
+ """Get concatenated content from all previous steps"""
162
+ if not self.previous_step_outputs:
163
+ return ""
164
+
165
+ content_parts = []
166
+ for step_name, output in self.previous_step_outputs.items():
167
+ if output.content:
168
+ content_parts.append(f"=== {step_name} ===\n{output.content}")
169
+
170
+ return "\n\n".join(content_parts)
171
+
172
+ def get_last_step_content(self) -> Optional[str]:
173
+ """Get content from the most recent step (for backward compatibility)"""
174
+ if not self.previous_step_outputs:
175
+ return None
176
+
177
+ last_output = list(self.previous_step_outputs.values())[-1] if self.previous_step_outputs else None
178
+ if not last_output:
179
+ return None
180
+
181
+ # Use the helper method to get the deepest content
182
+ return self._get_deepest_step_content(last_output) # type: ignore[return-value]
183
+
184
+ def get_workflow_history(self, num_runs: Optional[int] = None) -> List[Tuple[str, str]]:
185
+ """Get workflow conversation history as structured data for custom function steps
186
+
187
+ Args:
188
+ num_runs: Number of recent runs to include. If None, returns all available history.
189
+ """
190
+ if not self.workflow_session:
191
+ return []
192
+
193
+ return self.workflow_session.get_workflow_history(num_runs=num_runs)
194
+
195
+ def get_workflow_history_context(self, num_runs: Optional[int] = None) -> Optional[str]:
196
+ """Get formatted workflow conversation history context for custom function steps
197
+
198
+ Args:
199
+ num_runs: Number of recent runs to include. If None, returns all available history.
200
+ """
201
+ if not self.workflow_session:
202
+ return None
203
+
204
+ return self.workflow_session.get_workflow_history_context(num_runs=num_runs)
205
+
206
+ def to_dict(self) -> Dict[str, Any]:
207
+ """Convert to dictionary"""
208
+ # Handle the unified message field
209
+ input_dict: Optional[Union[str, Dict[str, Any], List[Any]]] = None
210
+ if self.input is not None:
211
+ if isinstance(self.input, BaseModel):
212
+ input_dict = self.input.model_dump(exclude_none=True)
213
+ elif isinstance(self.input, (dict, list)):
214
+ input_dict = self.input
215
+ else:
216
+ input_dict = str(self.input)
217
+
218
+ previous_step_content_str: Optional[str] = None
219
+ # Handle previous_step_content (keep existing logic)
220
+ if isinstance(self.previous_step_content, BaseModel):
221
+ previous_step_content_str = self.previous_step_content.model_dump_json(indent=2, exclude_none=True)
222
+ elif isinstance(self.previous_step_content, dict):
223
+ import json
224
+
225
+ previous_step_content_str = json.dumps(self.previous_step_content, indent=2, default=str)
226
+ elif self.previous_step_content:
227
+ previous_step_content_str = str(self.previous_step_content)
228
+
229
+ # Convert previous_step_outputs to serializable format (keep existing logic)
230
+ previous_steps_dict = {}
231
+ if self.previous_step_outputs:
232
+ for step_name, output in self.previous_step_outputs.items():
233
+ previous_steps_dict[step_name] = output.to_dict()
234
+
235
+ return {
236
+ "input": input_dict,
237
+ "previous_step_outputs": previous_steps_dict,
238
+ "previous_step_content": previous_step_content_str,
239
+ "additional_data": self.additional_data,
240
+ "images": [img.to_dict() for img in self.images] if self.images else None,
241
+ "videos": [vid.to_dict() for vid in self.videos] if self.videos else None,
242
+ "audio": [aud.to_dict() for aud in self.audio] if self.audio else None,
243
+ "files": [file for file in self.files] if self.files else None,
244
+ }
245
+
246
+
247
+ @dataclass
248
+ class StepOutput:
249
+ """Output data from a step execution"""
250
+
251
+ step_name: Optional[str] = None
252
+ step_id: Optional[str] = None
253
+ step_type: Optional[str] = None
254
+ executor_type: Optional[str] = None
255
+ executor_name: Optional[str] = None
256
+ # Primary output
257
+ content: Optional[Union[str, Dict[str, Any], List[Any], BaseModel, Any]] = None
258
+
259
+ # Link to the run ID of the step execution
260
+ step_run_id: Optional[str] = None
261
+
262
+ # Media outputs
263
+ images: Optional[List[Image]] = None
264
+ videos: Optional[List[Video]] = None
265
+ audio: Optional[List[Audio]] = None
266
+ files: Optional[List[File]] = None
267
+
268
+ # Metrics for this step execution
269
+ metrics: Optional[Metrics] = None
270
+
271
+ success: bool = True
272
+ error: Optional[str] = None
273
+
274
+ stop: bool = False
275
+
276
+ steps: Optional[List["StepOutput"]] = None
277
+
278
+ def to_dict(self) -> Dict[str, Any]:
279
+ """Convert to dictionary"""
280
+ # Handle the unified content field
281
+ content_dict: Optional[Union[str, Dict[str, Any], List[Any]]] = None
282
+ if self.content is not None:
283
+ if isinstance(self.content, BaseModel):
284
+ content_dict = self.content.model_dump(exclude_none=True)
285
+ elif isinstance(self.content, (dict, list)):
286
+ content_dict = self.content
287
+ else:
288
+ content_dict = str(self.content)
289
+
290
+ result = {
291
+ "content": content_dict,
292
+ "step_name": self.step_name,
293
+ "step_id": self.step_id,
294
+ "step_type": self.step_type,
295
+ "executor_type": self.executor_type,
296
+ "executor_name": self.executor_name,
297
+ "step_run_id": self.step_run_id,
298
+ "images": [img.to_dict() for img in self.images] if self.images else None,
299
+ "videos": [vid.to_dict() for vid in self.videos] if self.videos else None,
300
+ "audio": [aud.to_dict() for aud in self.audio] if self.audio else None,
301
+ "metrics": self.metrics.to_dict() if self.metrics else None,
302
+ "success": self.success,
303
+ "error": self.error,
304
+ "stop": self.stop,
305
+ "files": [file for file in self.files] if self.files else None,
306
+ }
307
+
308
+ # Add nested steps if they exist
309
+ if self.steps:
310
+ result["steps"] = [step.to_dict() for step in self.steps]
311
+
312
+ return result
313
+
314
+ @classmethod
315
+ def from_dict(cls, data: Dict[str, Any]) -> "StepOutput":
316
+ """Create StepOutput from dictionary"""
317
+ # Reconstruct media artifacts
318
+ images = reconstruct_images(data.get("images"))
319
+ videos = reconstruct_videos(data.get("videos"))
320
+ audio = reconstruct_audio_list(data.get("audio"))
321
+ files = reconstruct_files(data.get("files"))
322
+
323
+ metrics_data = data.get("metrics")
324
+ metrics = None
325
+ if metrics_data:
326
+ if isinstance(metrics_data, dict):
327
+ # Convert dict to Metrics object
328
+ from agno.models.metrics import Metrics
329
+
330
+ metrics = Metrics(**metrics_data)
331
+ else:
332
+ # Already a Metrics object
333
+ metrics = metrics_data
334
+
335
+ # Handle nested steps
336
+ steps_data = data.get("steps")
337
+ steps = None
338
+ if steps_data:
339
+ steps = [cls.from_dict(step_data) for step_data in steps_data]
340
+
341
+ return cls(
342
+ step_name=data.get("step_name"),
343
+ step_id=data.get("step_id"),
344
+ step_type=data.get("step_type"),
345
+ executor_type=data.get("executor_type"),
346
+ executor_name=data.get("executor_name"),
347
+ content=data.get("content"),
348
+ step_run_id=data.get("step_run_id"),
349
+ images=images,
350
+ videos=videos,
351
+ audio=audio,
352
+ files=files,
353
+ metrics=metrics,
354
+ success=data.get("success", True),
355
+ error=data.get("error"),
356
+ stop=data.get("stop", False),
357
+ steps=steps,
358
+ )
359
+
360
+
361
+ @dataclass
362
+ class StepMetrics:
363
+ """Metrics for a single step execution"""
364
+
365
+ step_name: str
366
+ executor_type: str # "agent", "team", etc.
367
+ executor_name: str
368
+ metrics: Optional[Metrics] = None
369
+
370
+ def to_dict(self) -> Dict[str, Any]:
371
+ """Convert to dictionary"""
372
+ return {
373
+ "step_name": self.step_name,
374
+ "executor_type": self.executor_type,
375
+ "executor_name": self.executor_name,
376
+ "metrics": self.metrics.to_dict() if self.metrics else None,
377
+ }
378
+
379
+ @classmethod
380
+ def from_dict(cls, data: Dict[str, Any]) -> "StepMetrics":
381
+ """Create StepMetrics from dictionary"""
382
+
383
+ # Handle metrics properly
384
+ metrics_data = data.get("metrics")
385
+ metrics = None
386
+ if metrics_data:
387
+ if isinstance(metrics_data, dict):
388
+ # Convert dict to Metrics object
389
+ from agno.models.metrics import Metrics
390
+
391
+ metrics = Metrics(**metrics_data)
392
+ else:
393
+ # Already a Metrics object
394
+ metrics = metrics_data
395
+
396
+ return cls(
397
+ step_name=data["step_name"],
398
+ executor_type=data["executor_type"],
399
+ executor_name=data["executor_name"],
400
+ metrics=metrics,
401
+ )
402
+
403
+
404
+ @dataclass
405
+ class WorkflowMetrics:
406
+ """Complete metrics for a workflow execution"""
407
+
408
+ steps: Dict[str, StepMetrics]
409
+ # Timer utility for tracking execution time
410
+ timer: Optional[Timer] = None
411
+ # Total workflow execution time
412
+ duration: Optional[float] = None
413
+
414
+ def to_dict(self) -> Dict[str, Any]:
415
+ """Convert to dictionary"""
416
+ result: Dict[str, Any] = {
417
+ "steps": {name: step.to_dict() for name, step in self.steps.items()},
418
+ "duration": self.duration,
419
+ }
420
+ return result
421
+
422
+ @classmethod
423
+ def from_dict(cls, data: Dict[str, Any]) -> "WorkflowMetrics":
424
+ """Create WorkflowMetrics from dictionary"""
425
+ steps = {name: StepMetrics.from_dict(step_data) for name, step_data in data["steps"].items()}
426
+
427
+ return cls(
428
+ steps=steps,
429
+ duration=data.get("duration"),
430
+ )
431
+
432
+ def start_timer(self):
433
+ if self.timer is None:
434
+ self.timer = Timer()
435
+ self.timer.start()
436
+
437
+ def stop_timer(self, set_duration: bool = True):
438
+ if self.timer is not None:
439
+ self.timer.stop()
440
+ if set_duration:
441
+ self.duration = self.timer.elapsed
442
+
443
+
444
+ @dataclass
445
+ class WebSocketHandler:
446
+ """Generic WebSocket handler for real-time workflow events"""
447
+
448
+ websocket: Optional[WebSocket] = None
449
+
450
+ def format_sse_event(self, json_data: str) -> str:
451
+ """Parse JSON data into SSE-compliant format.
452
+
453
+ Args:
454
+ json_data: JSON string containing the event data
455
+
456
+ Returns:
457
+ SSE-formatted response with event type and data
458
+ """
459
+ import json
460
+
461
+ try:
462
+ # Parse the JSON to extract the event type
463
+ data = json.loads(json_data)
464
+ event_type = data.get("event", "message")
465
+
466
+ # Format as SSE: event: <event_type>\ndata: <json_data>\n\n
467
+ return f"event: {event_type}\ndata: {json_data}\n\n"
468
+ except (json.JSONDecodeError, KeyError):
469
+ # Fallback to generic message event if parsing fails
470
+ return f"event: message\ndata: {json_data}\n\n"
471
+
472
+ async def handle_event(self, event: Any) -> None:
473
+ """Handle an event object - serializes and sends via WebSocket"""
474
+ if not self.websocket:
475
+ return
476
+
477
+ try:
478
+ if hasattr(event, "to_dict"):
479
+ data = event.to_dict()
480
+ elif hasattr(event, "__dict__"):
481
+ data = event.__dict__
482
+ elif isinstance(event, dict):
483
+ data = event
484
+ else:
485
+ data = {"type": "message", "content": str(event)}
486
+
487
+ await self.websocket.send_text(self.format_sse_event(json.dumps(data, default=json_serializer)))
488
+
489
+ except Exception as e:
490
+ log_warning(f"Failed to handle WebSocket event: {e}")
491
+
492
+ async def handle_text(self, message: str) -> None:
493
+ """Handle a plain text message"""
494
+ if not self.websocket:
495
+ return
496
+
497
+ try:
498
+ await self.websocket.send_text(self.format_sse_event(message))
499
+ except Exception as e:
500
+ log_warning(f"Failed to send WebSocket text: {e}")
501
+
502
+ async def handle_dict(self, data: Dict[str, Any]) -> None:
503
+ """Handle a dictionary directly"""
504
+ if not self.websocket:
505
+ return
506
+
507
+ try:
508
+ await self.websocket.send_text(self.format_sse_event(json.dumps(data, default=json_serializer)))
509
+ except Exception as e:
510
+ log_warning(f"Failed to send WebSocket dict: {e}")
511
+
512
+
513
+ class StepType(str, Enum):
514
+ FUNCTION = "Function"
515
+ STEP = "Step"
516
+ STEPS = "Steps"
517
+ LOOP = "Loop"
518
+ PARALLEL = "Parallel"
519
+ CONDITION = "Condition"
520
+ ROUTER = "Router"