agno 0.1.2__py3-none-any.whl → 2.3.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.
- agno/__init__.py +8 -0
- agno/agent/__init__.py +44 -5
- agno/agent/agent.py +10531 -2975
- agno/api/agent.py +14 -53
- agno/api/api.py +7 -46
- agno/api/evals.py +22 -0
- agno/api/os.py +17 -0
- agno/api/routes.py +6 -25
- agno/api/schemas/__init__.py +9 -0
- agno/api/schemas/agent.py +6 -9
- agno/api/schemas/evals.py +16 -0
- agno/api/schemas/os.py +14 -0
- agno/api/schemas/team.py +10 -10
- agno/api/schemas/utils.py +21 -0
- agno/api/schemas/workflows.py +16 -0
- agno/api/settings.py +53 -0
- agno/api/team.py +22 -26
- agno/api/workflow.py +28 -0
- agno/cloud/aws/base.py +214 -0
- agno/cloud/aws/s3/__init__.py +2 -0
- agno/cloud/aws/s3/api_client.py +43 -0
- agno/cloud/aws/s3/bucket.py +195 -0
- agno/cloud/aws/s3/object.py +57 -0
- agno/compression/__init__.py +3 -0
- agno/compression/manager.py +247 -0
- agno/culture/__init__.py +3 -0
- agno/culture/manager.py +956 -0
- agno/db/__init__.py +24 -0
- agno/db/async_postgres/__init__.py +3 -0
- agno/db/base.py +946 -0
- agno/db/dynamo/__init__.py +3 -0
- agno/db/dynamo/dynamo.py +2781 -0
- agno/db/dynamo/schemas.py +442 -0
- agno/db/dynamo/utils.py +743 -0
- agno/db/firestore/__init__.py +3 -0
- agno/db/firestore/firestore.py +2379 -0
- agno/db/firestore/schemas.py +181 -0
- agno/db/firestore/utils.py +376 -0
- agno/db/gcs_json/__init__.py +3 -0
- agno/db/gcs_json/gcs_json_db.py +1791 -0
- agno/db/gcs_json/utils.py +228 -0
- agno/db/in_memory/__init__.py +3 -0
- agno/db/in_memory/in_memory_db.py +1312 -0
- agno/db/in_memory/utils.py +230 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1777 -0
- agno/db/json/utils.py +230 -0
- agno/db/migrations/manager.py +199 -0
- agno/db/migrations/v1_to_v2.py +635 -0
- agno/db/migrations/versions/v2_3_0.py +938 -0
- agno/db/mongo/__init__.py +17 -0
- agno/db/mongo/async_mongo.py +2760 -0
- agno/db/mongo/mongo.py +2597 -0
- agno/db/mongo/schemas.py +119 -0
- agno/db/mongo/utils.py +276 -0
- agno/db/mysql/__init__.py +4 -0
- agno/db/mysql/async_mysql.py +2912 -0
- agno/db/mysql/mysql.py +2923 -0
- agno/db/mysql/schemas.py +186 -0
- agno/db/mysql/utils.py +488 -0
- agno/db/postgres/__init__.py +4 -0
- agno/db/postgres/async_postgres.py +2579 -0
- agno/db/postgres/postgres.py +2870 -0
- agno/db/postgres/schemas.py +187 -0
- agno/db/postgres/utils.py +442 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +2141 -0
- agno/db/redis/schemas.py +159 -0
- agno/db/redis/utils.py +346 -0
- agno/db/schemas/__init__.py +4 -0
- agno/db/schemas/culture.py +120 -0
- agno/db/schemas/evals.py +34 -0
- agno/db/schemas/knowledge.py +40 -0
- agno/db/schemas/memory.py +61 -0
- agno/db/singlestore/__init__.py +3 -0
- agno/db/singlestore/schemas.py +179 -0
- agno/db/singlestore/singlestore.py +2877 -0
- agno/db/singlestore/utils.py +384 -0
- agno/db/sqlite/__init__.py +4 -0
- agno/db/sqlite/async_sqlite.py +2911 -0
- agno/db/sqlite/schemas.py +181 -0
- agno/db/sqlite/sqlite.py +2908 -0
- agno/db/sqlite/utils.py +429 -0
- agno/db/surrealdb/__init__.py +3 -0
- agno/db/surrealdb/metrics.py +292 -0
- agno/db/surrealdb/models.py +334 -0
- agno/db/surrealdb/queries.py +71 -0
- agno/db/surrealdb/surrealdb.py +1908 -0
- agno/db/surrealdb/utils.py +147 -0
- agno/db/utils.py +118 -0
- agno/eval/__init__.py +24 -0
- agno/eval/accuracy.py +666 -276
- agno/eval/agent_as_judge.py +861 -0
- agno/eval/base.py +29 -0
- agno/eval/performance.py +779 -0
- agno/eval/reliability.py +241 -62
- agno/eval/utils.py +120 -0
- agno/exceptions.py +143 -1
- agno/filters.py +354 -0
- agno/guardrails/__init__.py +6 -0
- agno/guardrails/base.py +19 -0
- agno/guardrails/openai.py +144 -0
- agno/guardrails/pii.py +94 -0
- agno/guardrails/prompt_injection.py +52 -0
- agno/hooks/__init__.py +3 -0
- agno/hooks/decorator.py +164 -0
- agno/integrations/discord/__init__.py +3 -0
- agno/integrations/discord/client.py +203 -0
- agno/knowledge/__init__.py +5 -1
- agno/{document → knowledge}/chunking/agentic.py +22 -14
- agno/{document → knowledge}/chunking/document.py +2 -2
- agno/{document → knowledge}/chunking/fixed.py +7 -6
- agno/knowledge/chunking/markdown.py +151 -0
- agno/{document → knowledge}/chunking/recursive.py +15 -3
- agno/knowledge/chunking/row.py +39 -0
- agno/knowledge/chunking/semantic.py +91 -0
- agno/knowledge/chunking/strategy.py +165 -0
- agno/knowledge/content.py +74 -0
- agno/knowledge/document/__init__.py +5 -0
- agno/{document → knowledge/document}/base.py +12 -2
- agno/knowledge/embedder/__init__.py +5 -0
- agno/knowledge/embedder/aws_bedrock.py +343 -0
- agno/knowledge/embedder/azure_openai.py +210 -0
- agno/{embedder → knowledge/embedder}/base.py +8 -0
- agno/knowledge/embedder/cohere.py +323 -0
- agno/knowledge/embedder/fastembed.py +62 -0
- agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
- agno/knowledge/embedder/google.py +258 -0
- agno/knowledge/embedder/huggingface.py +94 -0
- agno/knowledge/embedder/jina.py +182 -0
- agno/knowledge/embedder/langdb.py +22 -0
- agno/knowledge/embedder/mistral.py +206 -0
- agno/knowledge/embedder/nebius.py +13 -0
- agno/knowledge/embedder/ollama.py +154 -0
- agno/knowledge/embedder/openai.py +195 -0
- agno/knowledge/embedder/sentence_transformer.py +63 -0
- agno/{embedder → knowledge/embedder}/together.py +1 -1
- agno/knowledge/embedder/vllm.py +262 -0
- agno/knowledge/embedder/voyageai.py +165 -0
- agno/knowledge/knowledge.py +3006 -0
- agno/knowledge/reader/__init__.py +7 -0
- agno/knowledge/reader/arxiv_reader.py +81 -0
- agno/knowledge/reader/base.py +95 -0
- agno/knowledge/reader/csv_reader.py +164 -0
- agno/knowledge/reader/docx_reader.py +82 -0
- agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
- agno/knowledge/reader/firecrawl_reader.py +201 -0
- agno/knowledge/reader/json_reader.py +88 -0
- agno/knowledge/reader/markdown_reader.py +137 -0
- agno/knowledge/reader/pdf_reader.py +431 -0
- agno/knowledge/reader/pptx_reader.py +101 -0
- agno/knowledge/reader/reader_factory.py +313 -0
- agno/knowledge/reader/s3_reader.py +89 -0
- agno/knowledge/reader/tavily_reader.py +193 -0
- agno/knowledge/reader/text_reader.py +127 -0
- agno/knowledge/reader/web_search_reader.py +325 -0
- agno/knowledge/reader/website_reader.py +455 -0
- agno/knowledge/reader/wikipedia_reader.py +91 -0
- agno/knowledge/reader/youtube_reader.py +78 -0
- agno/knowledge/remote_content/remote_content.py +88 -0
- agno/knowledge/reranker/__init__.py +3 -0
- agno/{reranker → knowledge/reranker}/base.py +1 -1
- agno/{reranker → knowledge/reranker}/cohere.py +2 -2
- agno/knowledge/reranker/infinity.py +195 -0
- agno/knowledge/reranker/sentence_transformer.py +54 -0
- agno/knowledge/types.py +39 -0
- agno/knowledge/utils.py +234 -0
- agno/media.py +439 -95
- agno/memory/__init__.py +16 -3
- agno/memory/manager.py +1474 -123
- agno/memory/strategies/__init__.py +15 -0
- agno/memory/strategies/base.py +66 -0
- agno/memory/strategies/summarize.py +196 -0
- agno/memory/strategies/types.py +37 -0
- agno/models/aimlapi/__init__.py +5 -0
- agno/models/aimlapi/aimlapi.py +62 -0
- agno/models/anthropic/__init__.py +4 -0
- agno/models/anthropic/claude.py +960 -496
- agno/models/aws/__init__.py +15 -0
- agno/models/aws/bedrock.py +686 -451
- agno/models/aws/claude.py +190 -183
- agno/models/azure/__init__.py +18 -1
- agno/models/azure/ai_foundry.py +489 -0
- agno/models/azure/openai_chat.py +89 -40
- agno/models/base.py +2477 -550
- agno/models/cerebras/__init__.py +12 -0
- agno/models/cerebras/cerebras.py +565 -0
- agno/models/cerebras/cerebras_openai.py +131 -0
- agno/models/cohere/__init__.py +4 -0
- agno/models/cohere/chat.py +306 -492
- agno/models/cometapi/__init__.py +5 -0
- agno/models/cometapi/cometapi.py +74 -0
- agno/models/dashscope/__init__.py +5 -0
- agno/models/dashscope/dashscope.py +90 -0
- agno/models/deepinfra/__init__.py +5 -0
- agno/models/deepinfra/deepinfra.py +45 -0
- agno/models/deepseek/__init__.py +4 -0
- agno/models/deepseek/deepseek.py +110 -9
- agno/models/fireworks/__init__.py +4 -0
- agno/models/fireworks/fireworks.py +19 -22
- agno/models/google/__init__.py +3 -7
- agno/models/google/gemini.py +1717 -662
- agno/models/google/utils.py +22 -0
- agno/models/groq/__init__.py +4 -0
- agno/models/groq/groq.py +391 -666
- agno/models/huggingface/__init__.py +4 -0
- agno/models/huggingface/huggingface.py +266 -538
- agno/models/ibm/__init__.py +5 -0
- agno/models/ibm/watsonx.py +432 -0
- agno/models/internlm/__init__.py +3 -0
- agno/models/internlm/internlm.py +20 -3
- agno/models/langdb/__init__.py +1 -0
- agno/models/langdb/langdb.py +60 -0
- agno/models/litellm/__init__.py +14 -0
- agno/models/litellm/chat.py +503 -0
- agno/models/litellm/litellm_openai.py +42 -0
- agno/models/llama_cpp/__init__.py +5 -0
- agno/models/llama_cpp/llama_cpp.py +22 -0
- agno/models/lmstudio/__init__.py +5 -0
- agno/models/lmstudio/lmstudio.py +25 -0
- agno/models/message.py +361 -39
- agno/models/meta/__init__.py +12 -0
- agno/models/meta/llama.py +502 -0
- agno/models/meta/llama_openai.py +79 -0
- agno/models/metrics.py +120 -0
- agno/models/mistral/__init__.py +4 -0
- agno/models/mistral/mistral.py +293 -393
- agno/models/nebius/__init__.py +3 -0
- agno/models/nebius/nebius.py +53 -0
- agno/models/nexus/__init__.py +3 -0
- agno/models/nexus/nexus.py +22 -0
- agno/models/nvidia/__init__.py +4 -0
- agno/models/nvidia/nvidia.py +22 -3
- agno/models/ollama/__init__.py +4 -2
- agno/models/ollama/chat.py +257 -492
- agno/models/openai/__init__.py +7 -0
- agno/models/openai/chat.py +725 -770
- agno/models/openai/like.py +16 -2
- agno/models/openai/responses.py +1121 -0
- agno/models/openrouter/__init__.py +4 -0
- agno/models/openrouter/openrouter.py +62 -5
- agno/models/perplexity/__init__.py +5 -0
- agno/models/perplexity/perplexity.py +203 -0
- agno/models/portkey/__init__.py +3 -0
- agno/models/portkey/portkey.py +82 -0
- agno/models/requesty/__init__.py +5 -0
- agno/models/requesty/requesty.py +69 -0
- agno/models/response.py +177 -7
- agno/models/sambanova/__init__.py +4 -0
- agno/models/sambanova/sambanova.py +23 -4
- agno/models/siliconflow/__init__.py +5 -0
- agno/models/siliconflow/siliconflow.py +42 -0
- agno/models/together/__init__.py +4 -0
- agno/models/together/together.py +21 -164
- agno/models/utils.py +266 -0
- agno/models/vercel/__init__.py +3 -0
- agno/models/vercel/v0.py +43 -0
- agno/models/vertexai/__init__.py +0 -1
- agno/models/vertexai/claude.py +190 -0
- agno/models/vllm/__init__.py +3 -0
- agno/models/vllm/vllm.py +83 -0
- agno/models/xai/__init__.py +2 -0
- agno/models/xai/xai.py +111 -7
- agno/os/__init__.py +3 -0
- agno/os/app.py +1027 -0
- agno/os/auth.py +244 -0
- agno/os/config.py +126 -0
- agno/os/interfaces/__init__.py +1 -0
- agno/os/interfaces/a2a/__init__.py +3 -0
- agno/os/interfaces/a2a/a2a.py +42 -0
- agno/os/interfaces/a2a/router.py +249 -0
- agno/os/interfaces/a2a/utils.py +924 -0
- agno/os/interfaces/agui/__init__.py +3 -0
- agno/os/interfaces/agui/agui.py +47 -0
- agno/os/interfaces/agui/router.py +147 -0
- agno/os/interfaces/agui/utils.py +574 -0
- agno/os/interfaces/base.py +25 -0
- agno/os/interfaces/slack/__init__.py +3 -0
- agno/os/interfaces/slack/router.py +148 -0
- agno/os/interfaces/slack/security.py +30 -0
- agno/os/interfaces/slack/slack.py +47 -0
- agno/os/interfaces/whatsapp/__init__.py +3 -0
- agno/os/interfaces/whatsapp/router.py +210 -0
- agno/os/interfaces/whatsapp/security.py +55 -0
- agno/os/interfaces/whatsapp/whatsapp.py +36 -0
- agno/os/mcp.py +293 -0
- agno/os/middleware/__init__.py +9 -0
- agno/os/middleware/jwt.py +797 -0
- agno/os/router.py +258 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/agents/__init__.py +3 -0
- agno/os/routers/agents/router.py +599 -0
- agno/os/routers/agents/schema.py +261 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +450 -0
- agno/os/routers/evals/schemas.py +174 -0
- agno/os/routers/evals/utils.py +231 -0
- agno/os/routers/health.py +31 -0
- agno/os/routers/home.py +52 -0
- agno/os/routers/knowledge/__init__.py +3 -0
- agno/os/routers/knowledge/knowledge.py +1008 -0
- agno/os/routers/knowledge/schemas.py +178 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +661 -0
- agno/os/routers/memory/schemas.py +88 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +190 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +997 -0
- agno/os/routers/teams/__init__.py +3 -0
- agno/os/routers/teams/router.py +512 -0
- agno/os/routers/teams/schema.py +257 -0
- agno/os/routers/traces/__init__.py +3 -0
- agno/os/routers/traces/schemas.py +414 -0
- agno/os/routers/traces/traces.py +499 -0
- agno/os/routers/workflows/__init__.py +3 -0
- agno/os/routers/workflows/router.py +624 -0
- agno/os/routers/workflows/schema.py +75 -0
- agno/os/schema.py +534 -0
- agno/os/scopes.py +469 -0
- agno/{playground → os}/settings.py +7 -15
- agno/os/utils.py +973 -0
- agno/reasoning/anthropic.py +80 -0
- agno/reasoning/azure_ai_foundry.py +67 -0
- agno/reasoning/deepseek.py +63 -0
- agno/reasoning/default.py +97 -0
- agno/reasoning/gemini.py +73 -0
- agno/reasoning/groq.py +71 -0
- agno/reasoning/helpers.py +24 -1
- agno/reasoning/ollama.py +67 -0
- agno/reasoning/openai.py +86 -0
- agno/reasoning/step.py +2 -1
- agno/reasoning/vertexai.py +76 -0
- agno/run/__init__.py +6 -0
- agno/run/agent.py +822 -0
- agno/run/base.py +247 -0
- agno/run/cancel.py +81 -0
- agno/run/requirement.py +181 -0
- agno/run/team.py +767 -0
- agno/run/workflow.py +708 -0
- agno/session/__init__.py +10 -0
- agno/session/agent.py +260 -0
- agno/session/summary.py +265 -0
- agno/session/team.py +342 -0
- agno/session/workflow.py +501 -0
- agno/table.py +10 -0
- agno/team/__init__.py +37 -0
- agno/team/team.py +9536 -0
- agno/tools/__init__.py +7 -0
- agno/tools/agentql.py +120 -0
- agno/tools/airflow.py +22 -12
- agno/tools/api.py +122 -0
- agno/tools/apify.py +276 -83
- agno/tools/{arxiv_toolkit.py → arxiv.py} +20 -12
- agno/tools/aws_lambda.py +28 -7
- agno/tools/aws_ses.py +66 -0
- agno/tools/baidusearch.py +11 -4
- agno/tools/bitbucket.py +292 -0
- agno/tools/brandfetch.py +213 -0
- agno/tools/bravesearch.py +106 -0
- agno/tools/brightdata.py +367 -0
- agno/tools/browserbase.py +209 -0
- agno/tools/calcom.py +32 -23
- agno/tools/calculator.py +24 -37
- agno/tools/cartesia.py +187 -0
- agno/tools/{clickup_tool.py → clickup.py} +17 -28
- agno/tools/confluence.py +91 -26
- agno/tools/crawl4ai.py +139 -43
- agno/tools/csv_toolkit.py +28 -22
- agno/tools/dalle.py +36 -22
- agno/tools/daytona.py +475 -0
- agno/tools/decorator.py +169 -14
- agno/tools/desi_vocal.py +23 -11
- agno/tools/discord.py +32 -29
- agno/tools/docker.py +716 -0
- agno/tools/duckdb.py +76 -81
- agno/tools/duckduckgo.py +43 -40
- agno/tools/e2b.py +703 -0
- agno/tools/eleven_labs.py +65 -54
- agno/tools/email.py +13 -5
- agno/tools/evm.py +129 -0
- agno/tools/exa.py +324 -42
- agno/tools/fal.py +39 -35
- agno/tools/file.py +196 -30
- agno/tools/file_generation.py +356 -0
- agno/tools/financial_datasets.py +288 -0
- agno/tools/firecrawl.py +108 -33
- agno/tools/function.py +960 -122
- agno/tools/giphy.py +34 -12
- agno/tools/github.py +1294 -97
- agno/tools/gmail.py +922 -0
- agno/tools/google_bigquery.py +117 -0
- agno/tools/google_drive.py +271 -0
- agno/tools/google_maps.py +253 -0
- agno/tools/googlecalendar.py +607 -107
- agno/tools/googlesheets.py +377 -0
- agno/tools/hackernews.py +20 -12
- agno/tools/jina.py +24 -14
- agno/tools/jira.py +48 -19
- agno/tools/knowledge.py +218 -0
- agno/tools/linear.py +82 -43
- agno/tools/linkup.py +58 -0
- agno/tools/local_file_system.py +15 -7
- agno/tools/lumalab.py +41 -26
- agno/tools/mcp/__init__.py +10 -0
- agno/tools/mcp/mcp.py +331 -0
- agno/tools/mcp/multi_mcp.py +347 -0
- agno/tools/mcp/params.py +24 -0
- agno/tools/mcp_toolbox.py +284 -0
- agno/tools/mem0.py +193 -0
- agno/tools/memory.py +419 -0
- agno/tools/mlx_transcribe.py +11 -9
- agno/tools/models/azure_openai.py +190 -0
- agno/tools/models/gemini.py +203 -0
- agno/tools/models/groq.py +158 -0
- agno/tools/models/morph.py +186 -0
- agno/tools/models/nebius.py +124 -0
- agno/tools/models_labs.py +163 -82
- agno/tools/moviepy_video.py +18 -13
- agno/tools/nano_banana.py +151 -0
- agno/tools/neo4j.py +134 -0
- agno/tools/newspaper.py +15 -4
- agno/tools/newspaper4k.py +19 -6
- agno/tools/notion.py +204 -0
- agno/tools/openai.py +181 -17
- agno/tools/openbb.py +27 -20
- agno/tools/opencv.py +321 -0
- agno/tools/openweather.py +233 -0
- agno/tools/oxylabs.py +385 -0
- agno/tools/pandas.py +25 -15
- agno/tools/parallel.py +314 -0
- agno/tools/postgres.py +238 -185
- agno/tools/pubmed.py +125 -13
- agno/tools/python.py +48 -35
- agno/tools/reasoning.py +283 -0
- agno/tools/reddit.py +207 -29
- agno/tools/redshift.py +406 -0
- agno/tools/replicate.py +69 -26
- agno/tools/resend.py +11 -6
- agno/tools/scrapegraph.py +179 -19
- agno/tools/searxng.py +23 -31
- agno/tools/serpapi.py +15 -10
- agno/tools/serper.py +255 -0
- agno/tools/shell.py +23 -12
- agno/tools/shopify.py +1519 -0
- agno/tools/slack.py +56 -14
- agno/tools/sleep.py +8 -6
- agno/tools/spider.py +35 -11
- agno/tools/spotify.py +919 -0
- agno/tools/sql.py +34 -19
- agno/tools/tavily.py +158 -8
- agno/tools/telegram.py +18 -8
- agno/tools/todoist.py +218 -0
- agno/tools/toolkit.py +134 -9
- agno/tools/trafilatura.py +388 -0
- agno/tools/trello.py +25 -28
- agno/tools/twilio.py +18 -9
- agno/tools/user_control_flow.py +78 -0
- agno/tools/valyu.py +228 -0
- agno/tools/visualization.py +467 -0
- agno/tools/webbrowser.py +28 -0
- agno/tools/webex.py +76 -0
- agno/tools/website.py +23 -19
- agno/tools/webtools.py +45 -0
- agno/tools/whatsapp.py +286 -0
- agno/tools/wikipedia.py +28 -19
- agno/tools/workflow.py +285 -0
- agno/tools/{twitter.py → x.py} +142 -46
- agno/tools/yfinance.py +41 -39
- agno/tools/youtube.py +34 -17
- agno/tools/zendesk.py +15 -5
- agno/tools/zep.py +454 -0
- agno/tools/zoom.py +86 -37
- agno/tracing/__init__.py +12 -0
- agno/tracing/exporter.py +157 -0
- agno/tracing/schemas.py +276 -0
- agno/tracing/setup.py +111 -0
- agno/utils/agent.py +938 -0
- agno/utils/audio.py +37 -1
- agno/utils/certs.py +27 -0
- agno/utils/code_execution.py +11 -0
- agno/utils/common.py +103 -20
- agno/utils/cryptography.py +22 -0
- agno/utils/dttm.py +33 -0
- agno/utils/events.py +700 -0
- agno/utils/functions.py +107 -37
- agno/utils/gemini.py +426 -0
- agno/utils/hooks.py +171 -0
- agno/utils/http.py +185 -0
- agno/utils/json_schema.py +159 -37
- agno/utils/knowledge.py +36 -0
- agno/utils/location.py +19 -0
- agno/utils/log.py +221 -8
- agno/utils/mcp.py +214 -0
- agno/utils/media.py +335 -14
- agno/utils/merge_dict.py +22 -1
- agno/utils/message.py +77 -2
- agno/utils/models/ai_foundry.py +50 -0
- agno/utils/models/claude.py +373 -0
- agno/utils/models/cohere.py +94 -0
- agno/utils/models/llama.py +85 -0
- agno/utils/models/mistral.py +100 -0
- agno/utils/models/openai_responses.py +140 -0
- agno/utils/models/schema_utils.py +153 -0
- agno/utils/models/watsonx.py +41 -0
- agno/utils/openai.py +257 -0
- agno/utils/pickle.py +1 -1
- agno/utils/pprint.py +124 -8
- agno/utils/print_response/agent.py +930 -0
- agno/utils/print_response/team.py +1914 -0
- agno/utils/print_response/workflow.py +1668 -0
- agno/utils/prompts.py +111 -0
- agno/utils/reasoning.py +108 -0
- agno/utils/response.py +163 -0
- agno/utils/serialize.py +32 -0
- agno/utils/shell.py +4 -4
- agno/utils/streamlit.py +487 -0
- agno/utils/string.py +204 -51
- agno/utils/team.py +139 -0
- agno/utils/timer.py +9 -2
- agno/utils/tokens.py +657 -0
- agno/utils/tools.py +19 -1
- agno/utils/whatsapp.py +305 -0
- agno/utils/yaml_io.py +3 -3
- agno/vectordb/__init__.py +2 -0
- agno/vectordb/base.py +87 -9
- agno/vectordb/cassandra/__init__.py +5 -1
- agno/vectordb/cassandra/cassandra.py +383 -27
- agno/vectordb/chroma/__init__.py +4 -0
- agno/vectordb/chroma/chromadb.py +748 -83
- agno/vectordb/clickhouse/__init__.py +7 -1
- agno/vectordb/clickhouse/clickhousedb.py +554 -53
- agno/vectordb/couchbase/__init__.py +3 -0
- agno/vectordb/couchbase/couchbase.py +1446 -0
- agno/vectordb/lancedb/__init__.py +5 -0
- agno/vectordb/lancedb/lance_db.py +730 -98
- agno/vectordb/langchaindb/__init__.py +5 -0
- agno/vectordb/langchaindb/langchaindb.py +163 -0
- agno/vectordb/lightrag/__init__.py +5 -0
- agno/vectordb/lightrag/lightrag.py +388 -0
- agno/vectordb/llamaindex/__init__.py +3 -0
- agno/vectordb/llamaindex/llamaindexdb.py +166 -0
- agno/vectordb/milvus/__init__.py +3 -0
- agno/vectordb/milvus/milvus.py +966 -78
- agno/vectordb/mongodb/__init__.py +9 -1
- agno/vectordb/mongodb/mongodb.py +1175 -172
- agno/vectordb/pgvector/__init__.py +8 -0
- agno/vectordb/pgvector/pgvector.py +599 -115
- agno/vectordb/pineconedb/__init__.py +5 -1
- agno/vectordb/pineconedb/pineconedb.py +406 -43
- agno/vectordb/qdrant/__init__.py +4 -0
- agno/vectordb/qdrant/qdrant.py +914 -61
- agno/vectordb/redis/__init__.py +9 -0
- agno/vectordb/redis/redisdb.py +682 -0
- agno/vectordb/singlestore/__init__.py +8 -1
- agno/vectordb/singlestore/singlestore.py +771 -0
- agno/vectordb/surrealdb/__init__.py +3 -0
- agno/vectordb/surrealdb/surrealdb.py +663 -0
- agno/vectordb/upstashdb/__init__.py +5 -0
- agno/vectordb/upstashdb/upstashdb.py +718 -0
- agno/vectordb/weaviate/__init__.py +8 -0
- agno/vectordb/weaviate/index.py +15 -0
- agno/vectordb/weaviate/weaviate.py +1009 -0
- agno/workflow/__init__.py +23 -1
- agno/workflow/agent.py +299 -0
- agno/workflow/condition.py +759 -0
- agno/workflow/loop.py +756 -0
- agno/workflow/parallel.py +853 -0
- agno/workflow/router.py +723 -0
- agno/workflow/step.py +1564 -0
- agno/workflow/steps.py +613 -0
- agno/workflow/types.py +556 -0
- agno/workflow/workflow.py +4327 -514
- agno-2.3.13.dist-info/METADATA +639 -0
- agno-2.3.13.dist-info/RECORD +613 -0
- {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/WHEEL +1 -1
- agno-2.3.13.dist-info/licenses/LICENSE +201 -0
- agno/api/playground.py +0 -91
- agno/api/schemas/playground.py +0 -22
- agno/api/schemas/user.py +0 -22
- agno/api/schemas/workspace.py +0 -46
- agno/api/user.py +0 -160
- agno/api/workspace.py +0 -151
- agno/cli/auth_server.py +0 -118
- agno/cli/config.py +0 -275
- agno/cli/console.py +0 -88
- agno/cli/credentials.py +0 -23
- agno/cli/entrypoint.py +0 -571
- agno/cli/operator.py +0 -355
- agno/cli/settings.py +0 -85
- agno/cli/ws/ws_cli.py +0 -817
- agno/constants.py +0 -13
- agno/document/__init__.py +0 -1
- agno/document/chunking/semantic.py +0 -47
- agno/document/chunking/strategy.py +0 -31
- agno/document/reader/__init__.py +0 -1
- agno/document/reader/arxiv_reader.py +0 -41
- agno/document/reader/base.py +0 -22
- agno/document/reader/csv_reader.py +0 -84
- agno/document/reader/docx_reader.py +0 -46
- agno/document/reader/firecrawl_reader.py +0 -99
- agno/document/reader/json_reader.py +0 -43
- agno/document/reader/pdf_reader.py +0 -219
- agno/document/reader/s3/pdf_reader.py +0 -46
- agno/document/reader/s3/text_reader.py +0 -51
- agno/document/reader/text_reader.py +0 -41
- agno/document/reader/website_reader.py +0 -175
- agno/document/reader/youtube_reader.py +0 -50
- agno/embedder/__init__.py +0 -1
- agno/embedder/azure_openai.py +0 -86
- agno/embedder/cohere.py +0 -72
- agno/embedder/fastembed.py +0 -37
- agno/embedder/google.py +0 -73
- agno/embedder/huggingface.py +0 -54
- agno/embedder/mistral.py +0 -80
- agno/embedder/ollama.py +0 -57
- agno/embedder/openai.py +0 -74
- agno/embedder/sentence_transformer.py +0 -38
- agno/embedder/voyageai.py +0 -64
- agno/eval/perf.py +0 -201
- agno/file/__init__.py +0 -1
- agno/file/file.py +0 -16
- agno/file/local/csv.py +0 -32
- agno/file/local/txt.py +0 -19
- agno/infra/app.py +0 -240
- agno/infra/base.py +0 -144
- agno/infra/context.py +0 -20
- agno/infra/db_app.py +0 -52
- agno/infra/resource.py +0 -205
- agno/infra/resources.py +0 -55
- agno/knowledge/agent.py +0 -230
- agno/knowledge/arxiv.py +0 -22
- agno/knowledge/combined.py +0 -22
- agno/knowledge/csv.py +0 -28
- agno/knowledge/csv_url.py +0 -19
- agno/knowledge/document.py +0 -20
- agno/knowledge/docx.py +0 -30
- agno/knowledge/json.py +0 -28
- agno/knowledge/langchain.py +0 -71
- agno/knowledge/llamaindex.py +0 -66
- agno/knowledge/pdf.py +0 -28
- agno/knowledge/pdf_url.py +0 -26
- agno/knowledge/s3/base.py +0 -60
- agno/knowledge/s3/pdf.py +0 -21
- agno/knowledge/s3/text.py +0 -23
- agno/knowledge/text.py +0 -30
- agno/knowledge/website.py +0 -88
- agno/knowledge/wikipedia.py +0 -31
- agno/knowledge/youtube.py +0 -22
- agno/memory/agent.py +0 -392
- agno/memory/classifier.py +0 -104
- agno/memory/db/__init__.py +0 -1
- agno/memory/db/base.py +0 -42
- agno/memory/db/mongodb.py +0 -189
- agno/memory/db/postgres.py +0 -203
- agno/memory/db/sqlite.py +0 -193
- agno/memory/memory.py +0 -15
- agno/memory/row.py +0 -36
- agno/memory/summarizer.py +0 -192
- agno/memory/summary.py +0 -19
- agno/memory/workflow.py +0 -38
- agno/models/google/gemini_openai.py +0 -26
- agno/models/ollama/hermes.py +0 -221
- agno/models/ollama/tools.py +0 -362
- agno/models/vertexai/gemini.py +0 -595
- agno/playground/__init__.py +0 -3
- agno/playground/async_router.py +0 -421
- agno/playground/deploy.py +0 -249
- agno/playground/operator.py +0 -92
- agno/playground/playground.py +0 -91
- agno/playground/schemas.py +0 -76
- agno/playground/serve.py +0 -55
- agno/playground/sync_router.py +0 -405
- agno/reasoning/agent.py +0 -68
- agno/run/response.py +0 -112
- agno/storage/agent/__init__.py +0 -0
- agno/storage/agent/base.py +0 -38
- agno/storage/agent/dynamodb.py +0 -350
- agno/storage/agent/json.py +0 -92
- agno/storage/agent/mongodb.py +0 -228
- agno/storage/agent/postgres.py +0 -367
- agno/storage/agent/session.py +0 -79
- agno/storage/agent/singlestore.py +0 -303
- agno/storage/agent/sqlite.py +0 -357
- agno/storage/agent/yaml.py +0 -93
- agno/storage/workflow/__init__.py +0 -0
- agno/storage/workflow/base.py +0 -40
- agno/storage/workflow/mongodb.py +0 -233
- agno/storage/workflow/postgres.py +0 -366
- agno/storage/workflow/session.py +0 -60
- agno/storage/workflow/sqlite.py +0 -359
- agno/tools/googlesearch.py +0 -88
- agno/utils/defaults.py +0 -57
- agno/utils/filesystem.py +0 -39
- agno/utils/git.py +0 -52
- agno/utils/json_io.py +0 -30
- agno/utils/load_env.py +0 -19
- agno/utils/py_io.py +0 -19
- agno/utils/pyproject.py +0 -18
- agno/utils/resource_filter.py +0 -31
- agno/vectordb/singlestore/s2vectordb.py +0 -390
- agno/vectordb/singlestore/s2vectordb2.py +0 -355
- agno/workspace/__init__.py +0 -0
- agno/workspace/config.py +0 -325
- agno/workspace/enums.py +0 -6
- agno/workspace/helpers.py +0 -48
- agno/workspace/operator.py +0 -758
- agno/workspace/settings.py +0 -63
- agno-0.1.2.dist-info/LICENSE +0 -375
- agno-0.1.2.dist-info/METADATA +0 -502
- agno-0.1.2.dist-info/RECORD +0 -352
- agno-0.1.2.dist-info/entry_points.txt +0 -3
- /agno/{cli → db/migrations}/__init__.py +0 -0
- /agno/{cli/ws → db/migrations/versions}/__init__.py +0 -0
- /agno/{document/chunking/__init__.py → db/schemas/metrics.py} +0 -0
- /agno/{document/reader/s3 → integrations}/__init__.py +0 -0
- /agno/{file/local → knowledge/chunking}/__init__.py +0 -0
- /agno/{infra → knowledge/remote_content}/__init__.py +0 -0
- /agno/{knowledge/s3 → tools/models}/__init__.py +0 -0
- /agno/{reranker → utils/models}/__init__.py +0 -0
- /agno/{storage → utils/print_response}/__init__.py +0 -0
- {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/top_level.txt +0 -0
agno/run/workflow.py
ADDED
|
@@ -0,0 +1,708 @@
|
|
|
1
|
+
from dataclasses import asdict, dataclass, field
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from time import time
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
|
|
8
|
+
from agno.media import Audio, Image, Video
|
|
9
|
+
from agno.run.agent import RunEvent, RunOutput, run_output_event_from_dict
|
|
10
|
+
from agno.run.base import BaseRunOutputEvent, RunStatus
|
|
11
|
+
from agno.run.team import TeamRunEvent, TeamRunOutput, team_run_output_event_from_dict
|
|
12
|
+
from agno.utils.media import (
|
|
13
|
+
reconstruct_audio_list,
|
|
14
|
+
reconstruct_images,
|
|
15
|
+
reconstruct_response_audio,
|
|
16
|
+
reconstruct_videos,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from agno.workflow.types import StepOutput, WorkflowMetrics
|
|
21
|
+
else:
|
|
22
|
+
StepOutput = Any
|
|
23
|
+
WorkflowMetrics = Any
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class WorkflowRunEvent(str, Enum):
|
|
27
|
+
"""Events that can be sent by workflow execution"""
|
|
28
|
+
|
|
29
|
+
workflow_started = "WorkflowStarted"
|
|
30
|
+
workflow_completed = "WorkflowCompleted"
|
|
31
|
+
workflow_cancelled = "WorkflowCancelled"
|
|
32
|
+
workflow_error = "WorkflowError"
|
|
33
|
+
|
|
34
|
+
workflow_agent_started = "WorkflowAgentStarted"
|
|
35
|
+
workflow_agent_completed = "WorkflowAgentCompleted"
|
|
36
|
+
|
|
37
|
+
step_started = "StepStarted"
|
|
38
|
+
step_completed = "StepCompleted"
|
|
39
|
+
step_error = "StepError"
|
|
40
|
+
|
|
41
|
+
loop_execution_started = "LoopExecutionStarted"
|
|
42
|
+
loop_iteration_started = "LoopIterationStarted"
|
|
43
|
+
loop_iteration_completed = "LoopIterationCompleted"
|
|
44
|
+
loop_execution_completed = "LoopExecutionCompleted"
|
|
45
|
+
|
|
46
|
+
parallel_execution_started = "ParallelExecutionStarted"
|
|
47
|
+
parallel_execution_completed = "ParallelExecutionCompleted"
|
|
48
|
+
|
|
49
|
+
condition_execution_started = "ConditionExecutionStarted"
|
|
50
|
+
condition_execution_completed = "ConditionExecutionCompleted"
|
|
51
|
+
|
|
52
|
+
router_execution_started = "RouterExecutionStarted"
|
|
53
|
+
router_execution_completed = "RouterExecutionCompleted"
|
|
54
|
+
|
|
55
|
+
steps_execution_started = "StepsExecutionStarted"
|
|
56
|
+
steps_execution_completed = "StepsExecutionCompleted"
|
|
57
|
+
|
|
58
|
+
step_output = "StepOutput"
|
|
59
|
+
|
|
60
|
+
custom_event = "CustomEvent"
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass
|
|
64
|
+
class BaseWorkflowRunOutputEvent(BaseRunOutputEvent):
|
|
65
|
+
"""Base class for all workflow run response events"""
|
|
66
|
+
|
|
67
|
+
created_at: int = field(default_factory=lambda: int(time()))
|
|
68
|
+
event: str = ""
|
|
69
|
+
|
|
70
|
+
# Workflow-specific fields
|
|
71
|
+
workflow_id: Optional[str] = None
|
|
72
|
+
workflow_name: Optional[str] = None
|
|
73
|
+
session_id: Optional[str] = None
|
|
74
|
+
run_id: Optional[str] = None
|
|
75
|
+
step_id: Optional[str] = None
|
|
76
|
+
parent_step_id: Optional[str] = None
|
|
77
|
+
|
|
78
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
79
|
+
_dict = {k: v for k, v in asdict(self).items() if v is not None}
|
|
80
|
+
|
|
81
|
+
if hasattr(self, "content") and self.content and isinstance(self.content, BaseModel):
|
|
82
|
+
_dict["content"] = self.content.model_dump(exclude_none=True)
|
|
83
|
+
|
|
84
|
+
# Handle StepOutput fields that contain Message objects
|
|
85
|
+
if hasattr(self, "step_results") and self.step_results is not None:
|
|
86
|
+
_dict["step_results"] = [step.to_dict() if hasattr(step, "to_dict") else step for step in self.step_results]
|
|
87
|
+
|
|
88
|
+
if hasattr(self, "step_response") and self.step_response is not None:
|
|
89
|
+
_dict["step_response"] = (
|
|
90
|
+
self.step_response.to_dict() if hasattr(self.step_response, "to_dict") else self.step_response
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
if hasattr(self, "iteration_results") and self.iteration_results is not None:
|
|
94
|
+
_dict["iteration_results"] = [
|
|
95
|
+
step.to_dict() if hasattr(step, "to_dict") else step for step in self.iteration_results
|
|
96
|
+
]
|
|
97
|
+
|
|
98
|
+
if hasattr(self, "all_results") and self.all_results is not None:
|
|
99
|
+
_dict["all_results"] = [
|
|
100
|
+
[step.to_dict() if hasattr(step, "to_dict") else step for step in iteration]
|
|
101
|
+
for iteration in self.all_results
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
return _dict
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def is_cancelled(self):
|
|
108
|
+
return False
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def is_error(self):
|
|
112
|
+
return False
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def status(self):
|
|
116
|
+
status = "Completed"
|
|
117
|
+
if self.is_error:
|
|
118
|
+
status = "Error"
|
|
119
|
+
if self.is_cancelled:
|
|
120
|
+
status = "Cancelled"
|
|
121
|
+
|
|
122
|
+
return status
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@dataclass
|
|
126
|
+
class WorkflowStartedEvent(BaseWorkflowRunOutputEvent):
|
|
127
|
+
"""Event sent when workflow execution starts"""
|
|
128
|
+
|
|
129
|
+
event: str = WorkflowRunEvent.workflow_started.value
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@dataclass
|
|
133
|
+
class WorkflowAgentStartedEvent(BaseWorkflowRunOutputEvent):
|
|
134
|
+
"""Event sent when workflow agent starts (before deciding to run workflow or answer directly)"""
|
|
135
|
+
|
|
136
|
+
event: str = WorkflowRunEvent.workflow_agent_started.value
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@dataclass
|
|
140
|
+
class WorkflowAgentCompletedEvent(BaseWorkflowRunOutputEvent):
|
|
141
|
+
"""Event sent when workflow agent completes (after running workflow or answering directly)"""
|
|
142
|
+
|
|
143
|
+
event: str = WorkflowRunEvent.workflow_agent_completed.value
|
|
144
|
+
content: Optional[Any] = None
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
@dataclass
|
|
148
|
+
class WorkflowCompletedEvent(BaseWorkflowRunOutputEvent):
|
|
149
|
+
"""Event sent when workflow execution completes"""
|
|
150
|
+
|
|
151
|
+
event: str = WorkflowRunEvent.workflow_completed.value
|
|
152
|
+
content: Optional[Any] = None
|
|
153
|
+
content_type: str = "str"
|
|
154
|
+
|
|
155
|
+
# Store actual step execution results as StepOutput objects
|
|
156
|
+
step_results: List[StepOutput] = field(default_factory=list)
|
|
157
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@dataclass
|
|
161
|
+
class WorkflowErrorEvent(BaseWorkflowRunOutputEvent):
|
|
162
|
+
"""Event sent when workflow execution fails"""
|
|
163
|
+
|
|
164
|
+
event: str = WorkflowRunEvent.workflow_error.value
|
|
165
|
+
error: Optional[str] = None
|
|
166
|
+
|
|
167
|
+
# From exceptions
|
|
168
|
+
error_type: Optional[str] = None
|
|
169
|
+
error_id: Optional[str] = None
|
|
170
|
+
additional_data: Optional[Dict[str, Any]] = None
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
@dataclass
|
|
174
|
+
class WorkflowCancelledEvent(BaseWorkflowRunOutputEvent):
|
|
175
|
+
"""Event sent when workflow execution is cancelled"""
|
|
176
|
+
|
|
177
|
+
event: str = WorkflowRunEvent.workflow_cancelled.value
|
|
178
|
+
reason: Optional[str] = None
|
|
179
|
+
|
|
180
|
+
@property
|
|
181
|
+
def is_cancelled(self):
|
|
182
|
+
return True
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
@dataclass
|
|
186
|
+
class StepStartedEvent(BaseWorkflowRunOutputEvent):
|
|
187
|
+
"""Event sent when step execution starts"""
|
|
188
|
+
|
|
189
|
+
event: str = WorkflowRunEvent.step_started.value
|
|
190
|
+
step_name: Optional[str] = None
|
|
191
|
+
step_index: Optional[Union[int, tuple]] = None
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
@dataclass
|
|
195
|
+
class StepCompletedEvent(BaseWorkflowRunOutputEvent):
|
|
196
|
+
"""Event sent when step execution completes"""
|
|
197
|
+
|
|
198
|
+
event: str = WorkflowRunEvent.step_completed.value
|
|
199
|
+
step_name: Optional[str] = None
|
|
200
|
+
step_index: Optional[Union[int, tuple]] = None
|
|
201
|
+
|
|
202
|
+
content: Optional[Any] = None
|
|
203
|
+
content_type: str = "str"
|
|
204
|
+
|
|
205
|
+
# Media content fields
|
|
206
|
+
images: Optional[List[Image]] = None
|
|
207
|
+
videos: Optional[List[Video]] = None
|
|
208
|
+
audio: Optional[List[Audio]] = None
|
|
209
|
+
response_audio: Optional[Audio] = None
|
|
210
|
+
|
|
211
|
+
# Store actual step execution results as StepOutput objects
|
|
212
|
+
step_response: Optional[StepOutput] = None
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
@dataclass
|
|
216
|
+
class StepErrorEvent(BaseWorkflowRunOutputEvent):
|
|
217
|
+
"""Event sent when step execution fails"""
|
|
218
|
+
|
|
219
|
+
event: str = WorkflowRunEvent.step_error.value
|
|
220
|
+
step_name: Optional[str] = None
|
|
221
|
+
step_index: Optional[Union[int, tuple]] = None
|
|
222
|
+
error: Optional[str] = None
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
@dataclass
|
|
226
|
+
class LoopExecutionStartedEvent(BaseWorkflowRunOutputEvent):
|
|
227
|
+
"""Event sent when loop execution starts"""
|
|
228
|
+
|
|
229
|
+
event: str = WorkflowRunEvent.loop_execution_started.value
|
|
230
|
+
step_name: Optional[str] = None
|
|
231
|
+
step_index: Optional[Union[int, tuple]] = None
|
|
232
|
+
max_iterations: Optional[int] = None
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
@dataclass
|
|
236
|
+
class LoopIterationStartedEvent(BaseWorkflowRunOutputEvent):
|
|
237
|
+
"""Event sent when loop iteration starts"""
|
|
238
|
+
|
|
239
|
+
event: str = WorkflowRunEvent.loop_iteration_started.value
|
|
240
|
+
step_name: Optional[str] = None
|
|
241
|
+
step_index: Optional[Union[int, tuple]] = None
|
|
242
|
+
iteration: int = 0
|
|
243
|
+
max_iterations: Optional[int] = None
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
@dataclass
|
|
247
|
+
class LoopIterationCompletedEvent(BaseWorkflowRunOutputEvent):
|
|
248
|
+
"""Event sent when loop iteration completes"""
|
|
249
|
+
|
|
250
|
+
event: str = WorkflowRunEvent.loop_iteration_completed.value
|
|
251
|
+
step_name: Optional[str] = None
|
|
252
|
+
step_index: Optional[Union[int, tuple]] = None
|
|
253
|
+
iteration: int = 0
|
|
254
|
+
max_iterations: Optional[int] = None
|
|
255
|
+
iteration_results: List[StepOutput] = field(default_factory=list)
|
|
256
|
+
should_continue: bool = True
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
@dataclass
|
|
260
|
+
class LoopExecutionCompletedEvent(BaseWorkflowRunOutputEvent):
|
|
261
|
+
"""Event sent when loop execution completes"""
|
|
262
|
+
|
|
263
|
+
event: str = WorkflowRunEvent.loop_execution_completed.value
|
|
264
|
+
step_name: Optional[str] = None
|
|
265
|
+
step_index: Optional[Union[int, tuple]] = None
|
|
266
|
+
total_iterations: int = 0
|
|
267
|
+
max_iterations: Optional[int] = None
|
|
268
|
+
all_results: List[List[StepOutput]] = field(default_factory=list)
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
@dataclass
|
|
272
|
+
class ParallelExecutionStartedEvent(BaseWorkflowRunOutputEvent):
|
|
273
|
+
"""Event sent when parallel step execution starts"""
|
|
274
|
+
|
|
275
|
+
event: str = WorkflowRunEvent.parallel_execution_started.value
|
|
276
|
+
step_name: Optional[str] = None
|
|
277
|
+
step_index: Optional[Union[int, tuple]] = None
|
|
278
|
+
parallel_step_count: Optional[int] = None
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
@dataclass
|
|
282
|
+
class ParallelExecutionCompletedEvent(BaseWorkflowRunOutputEvent):
|
|
283
|
+
"""Event sent when parallel step execution completes"""
|
|
284
|
+
|
|
285
|
+
event: str = WorkflowRunEvent.parallel_execution_completed.value
|
|
286
|
+
step_name: Optional[str] = None
|
|
287
|
+
step_index: Optional[Union[int, tuple]] = None
|
|
288
|
+
parallel_step_count: Optional[int] = None
|
|
289
|
+
|
|
290
|
+
# Results from all parallel steps
|
|
291
|
+
step_results: List[StepOutput] = field(default_factory=list)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
@dataclass
|
|
295
|
+
class ConditionExecutionStartedEvent(BaseWorkflowRunOutputEvent):
|
|
296
|
+
"""Event sent when condition step execution starts"""
|
|
297
|
+
|
|
298
|
+
event: str = WorkflowRunEvent.condition_execution_started.value
|
|
299
|
+
step_name: Optional[str] = None
|
|
300
|
+
step_index: Optional[Union[int, tuple]] = None
|
|
301
|
+
condition_result: Optional[bool] = None
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
@dataclass
|
|
305
|
+
class ConditionExecutionCompletedEvent(BaseWorkflowRunOutputEvent):
|
|
306
|
+
"""Event sent when condition step execution completes"""
|
|
307
|
+
|
|
308
|
+
event: str = WorkflowRunEvent.condition_execution_completed.value
|
|
309
|
+
step_name: Optional[str] = None
|
|
310
|
+
step_index: Optional[Union[int, tuple]] = None
|
|
311
|
+
condition_result: Optional[bool] = None
|
|
312
|
+
executed_steps: Optional[int] = None
|
|
313
|
+
|
|
314
|
+
# Results from executed steps
|
|
315
|
+
step_results: List[StepOutput] = field(default_factory=list)
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
@dataclass
|
|
319
|
+
class RouterExecutionStartedEvent(BaseWorkflowRunOutputEvent):
|
|
320
|
+
"""Event sent when router step execution starts"""
|
|
321
|
+
|
|
322
|
+
event: str = WorkflowRunEvent.router_execution_started.value
|
|
323
|
+
step_name: Optional[str] = None
|
|
324
|
+
step_index: Optional[Union[int, tuple]] = None
|
|
325
|
+
# Names of steps selected by router
|
|
326
|
+
selected_steps: List[str] = field(default_factory=list)
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
@dataclass
|
|
330
|
+
class RouterExecutionCompletedEvent(BaseWorkflowRunOutputEvent):
|
|
331
|
+
"""Event sent when router step execution completes"""
|
|
332
|
+
|
|
333
|
+
event: str = WorkflowRunEvent.router_execution_completed.value
|
|
334
|
+
step_name: Optional[str] = None
|
|
335
|
+
step_index: Optional[Union[int, tuple]] = None
|
|
336
|
+
# Names of steps that were selected
|
|
337
|
+
selected_steps: List[str] = field(default_factory=list)
|
|
338
|
+
executed_steps: Optional[int] = None
|
|
339
|
+
|
|
340
|
+
# Results from executed steps
|
|
341
|
+
step_results: List[StepOutput] = field(default_factory=list)
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
@dataclass
|
|
345
|
+
class StepsExecutionStartedEvent(BaseWorkflowRunOutputEvent):
|
|
346
|
+
"""Event sent when steps execution starts"""
|
|
347
|
+
|
|
348
|
+
event: str = WorkflowRunEvent.steps_execution_started.value
|
|
349
|
+
step_name: Optional[str] = None
|
|
350
|
+
step_index: Optional[Union[int, tuple]] = None
|
|
351
|
+
steps_count: Optional[int] = None
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
@dataclass
|
|
355
|
+
class StepsExecutionCompletedEvent(BaseWorkflowRunOutputEvent):
|
|
356
|
+
"""Event sent when steps execution completes"""
|
|
357
|
+
|
|
358
|
+
event: str = WorkflowRunEvent.steps_execution_completed.value
|
|
359
|
+
step_name: Optional[str] = None
|
|
360
|
+
step_index: Optional[Union[int, tuple]] = None
|
|
361
|
+
steps_count: Optional[int] = None
|
|
362
|
+
executed_steps: Optional[int] = None
|
|
363
|
+
|
|
364
|
+
# Results from executed steps
|
|
365
|
+
step_results: List[StepOutput] = field(default_factory=list)
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
@dataclass
|
|
369
|
+
class StepOutputEvent(BaseWorkflowRunOutputEvent):
|
|
370
|
+
"""Event sent when a step produces output - replaces direct StepOutput yielding"""
|
|
371
|
+
|
|
372
|
+
event: str = "StepOutput"
|
|
373
|
+
step_name: Optional[str] = None
|
|
374
|
+
step_index: Optional[Union[int, tuple]] = None
|
|
375
|
+
|
|
376
|
+
# Store actual step execution result as StepOutput object
|
|
377
|
+
step_output: Optional[StepOutput] = None
|
|
378
|
+
|
|
379
|
+
# Properties for backward compatibility
|
|
380
|
+
@property
|
|
381
|
+
def content(self) -> Optional[Union[str, Dict[str, Any], List[Any], BaseModel, Any]]:
|
|
382
|
+
return self.step_output.content if self.step_output else None
|
|
383
|
+
|
|
384
|
+
@property
|
|
385
|
+
def images(self) -> Optional[List[Image]]:
|
|
386
|
+
return self.step_output.images if self.step_output else None
|
|
387
|
+
|
|
388
|
+
@property
|
|
389
|
+
def videos(self) -> Optional[List[Video]]:
|
|
390
|
+
return self.step_output.videos if self.step_output else None
|
|
391
|
+
|
|
392
|
+
@property
|
|
393
|
+
def audio(self) -> Optional[List[Audio]]:
|
|
394
|
+
return self.step_output.audio if self.step_output else None
|
|
395
|
+
|
|
396
|
+
@property
|
|
397
|
+
def success(self) -> bool:
|
|
398
|
+
return self.step_output.success if self.step_output else True
|
|
399
|
+
|
|
400
|
+
@property
|
|
401
|
+
def error(self) -> Optional[str]:
|
|
402
|
+
return self.step_output.error if self.step_output else None
|
|
403
|
+
|
|
404
|
+
@property
|
|
405
|
+
def stop(self) -> bool:
|
|
406
|
+
return self.step_output.stop if self.step_output else False
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
@dataclass
|
|
410
|
+
class CustomEvent(BaseWorkflowRunOutputEvent):
|
|
411
|
+
"""Event sent when a custom event is produced"""
|
|
412
|
+
|
|
413
|
+
event: str = WorkflowRunEvent.custom_event.value
|
|
414
|
+
|
|
415
|
+
def __init__(self, **kwargs):
|
|
416
|
+
# Store arbitrary attributes directly on the instance
|
|
417
|
+
for key, value in kwargs.items():
|
|
418
|
+
setattr(self, key, value)
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
# Union type for all workflow run response events
|
|
422
|
+
WorkflowRunOutputEvent = Union[
|
|
423
|
+
WorkflowStartedEvent,
|
|
424
|
+
WorkflowAgentStartedEvent,
|
|
425
|
+
WorkflowAgentCompletedEvent,
|
|
426
|
+
WorkflowCompletedEvent,
|
|
427
|
+
WorkflowErrorEvent,
|
|
428
|
+
WorkflowCancelledEvent,
|
|
429
|
+
StepStartedEvent,
|
|
430
|
+
StepCompletedEvent,
|
|
431
|
+
StepErrorEvent,
|
|
432
|
+
LoopExecutionStartedEvent,
|
|
433
|
+
LoopIterationStartedEvent,
|
|
434
|
+
LoopIterationCompletedEvent,
|
|
435
|
+
LoopExecutionCompletedEvent,
|
|
436
|
+
ParallelExecutionStartedEvent,
|
|
437
|
+
ParallelExecutionCompletedEvent,
|
|
438
|
+
ConditionExecutionStartedEvent,
|
|
439
|
+
ConditionExecutionCompletedEvent,
|
|
440
|
+
RouterExecutionStartedEvent,
|
|
441
|
+
RouterExecutionCompletedEvent,
|
|
442
|
+
StepsExecutionStartedEvent,
|
|
443
|
+
StepsExecutionCompletedEvent,
|
|
444
|
+
StepOutputEvent,
|
|
445
|
+
CustomEvent,
|
|
446
|
+
]
|
|
447
|
+
|
|
448
|
+
# Map event string to dataclass for workflow events
|
|
449
|
+
WORKFLOW_RUN_EVENT_TYPE_REGISTRY = {
|
|
450
|
+
WorkflowRunEvent.workflow_started.value: WorkflowStartedEvent,
|
|
451
|
+
WorkflowRunEvent.workflow_agent_started.value: WorkflowAgentStartedEvent,
|
|
452
|
+
WorkflowRunEvent.workflow_agent_completed.value: WorkflowAgentCompletedEvent,
|
|
453
|
+
WorkflowRunEvent.workflow_completed.value: WorkflowCompletedEvent,
|
|
454
|
+
WorkflowRunEvent.workflow_cancelled.value: WorkflowCancelledEvent,
|
|
455
|
+
WorkflowRunEvent.workflow_error.value: WorkflowErrorEvent,
|
|
456
|
+
WorkflowRunEvent.step_started.value: StepStartedEvent,
|
|
457
|
+
WorkflowRunEvent.step_completed.value: StepCompletedEvent,
|
|
458
|
+
WorkflowRunEvent.step_error.value: StepErrorEvent,
|
|
459
|
+
WorkflowRunEvent.loop_execution_started.value: LoopExecutionStartedEvent,
|
|
460
|
+
WorkflowRunEvent.loop_iteration_started.value: LoopIterationStartedEvent,
|
|
461
|
+
WorkflowRunEvent.loop_iteration_completed.value: LoopIterationCompletedEvent,
|
|
462
|
+
WorkflowRunEvent.loop_execution_completed.value: LoopExecutionCompletedEvent,
|
|
463
|
+
WorkflowRunEvent.parallel_execution_started.value: ParallelExecutionStartedEvent,
|
|
464
|
+
WorkflowRunEvent.parallel_execution_completed.value: ParallelExecutionCompletedEvent,
|
|
465
|
+
WorkflowRunEvent.condition_execution_started.value: ConditionExecutionStartedEvent,
|
|
466
|
+
WorkflowRunEvent.condition_execution_completed.value: ConditionExecutionCompletedEvent,
|
|
467
|
+
WorkflowRunEvent.router_execution_started.value: RouterExecutionStartedEvent,
|
|
468
|
+
WorkflowRunEvent.router_execution_completed.value: RouterExecutionCompletedEvent,
|
|
469
|
+
WorkflowRunEvent.steps_execution_started.value: StepsExecutionStartedEvent,
|
|
470
|
+
WorkflowRunEvent.steps_execution_completed.value: StepsExecutionCompletedEvent,
|
|
471
|
+
WorkflowRunEvent.step_output.value: StepOutputEvent,
|
|
472
|
+
WorkflowRunEvent.custom_event.value: CustomEvent,
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
def workflow_run_output_event_from_dict(data: dict) -> BaseWorkflowRunOutputEvent:
|
|
477
|
+
event_type = data.get("event", "")
|
|
478
|
+
if event_type in {e.value for e in RunEvent}:
|
|
479
|
+
return run_output_event_from_dict(data) # type: ignore
|
|
480
|
+
elif event_type in {e.value for e in TeamRunEvent}:
|
|
481
|
+
return team_run_output_event_from_dict(data) # type: ignore
|
|
482
|
+
else:
|
|
483
|
+
event_class = WORKFLOW_RUN_EVENT_TYPE_REGISTRY.get(event_type)
|
|
484
|
+
if not event_class:
|
|
485
|
+
raise ValueError(f"Unknown workflow event type: {event_type}")
|
|
486
|
+
return event_class.from_dict(data) # type: ignore
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
@dataclass
|
|
490
|
+
class WorkflowRunOutput:
|
|
491
|
+
"""Response returned by Workflow.run() functions - kept for backwards compatibility"""
|
|
492
|
+
|
|
493
|
+
input: Optional[Union[str, Dict[str, Any], List[Any], BaseModel]] = None
|
|
494
|
+
content: Optional[Union[str, Dict[str, Any], List[Any], BaseModel, Any]] = None
|
|
495
|
+
content_type: str = "str"
|
|
496
|
+
|
|
497
|
+
# Workflow-specific fields
|
|
498
|
+
workflow_id: Optional[str] = None
|
|
499
|
+
workflow_name: Optional[str] = None
|
|
500
|
+
|
|
501
|
+
run_id: Optional[str] = None
|
|
502
|
+
session_id: Optional[str] = None
|
|
503
|
+
|
|
504
|
+
# Media content fields
|
|
505
|
+
images: Optional[List[Image]] = None
|
|
506
|
+
videos: Optional[List[Video]] = None
|
|
507
|
+
audio: Optional[List[Audio]] = None
|
|
508
|
+
response_audio: Optional[Audio] = None
|
|
509
|
+
|
|
510
|
+
# Store actual step execution results as StepOutput objects
|
|
511
|
+
step_results: List[Union[StepOutput, List[StepOutput]]] = field(default_factory=list)
|
|
512
|
+
|
|
513
|
+
# Store agent/team responses separately with parent_run_id references
|
|
514
|
+
step_executor_runs: Optional[List[Union[RunOutput, TeamRunOutput]]] = None
|
|
515
|
+
|
|
516
|
+
# Workflow agent run - stores the full agent RunOutput when workflow agent is used
|
|
517
|
+
# The agent's parent_run_id will point to this workflow run's run_id to establish the relationship
|
|
518
|
+
workflow_agent_run: Optional[RunOutput] = None
|
|
519
|
+
|
|
520
|
+
# Store events from workflow execution
|
|
521
|
+
events: Optional[List[WorkflowRunOutputEvent]] = None
|
|
522
|
+
|
|
523
|
+
# Workflow metrics aggregated from all steps
|
|
524
|
+
metrics: Optional[WorkflowMetrics] = None
|
|
525
|
+
|
|
526
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
527
|
+
created_at: int = field(default_factory=lambda: int(time()))
|
|
528
|
+
|
|
529
|
+
status: RunStatus = RunStatus.pending
|
|
530
|
+
|
|
531
|
+
@property
|
|
532
|
+
def is_cancelled(self):
|
|
533
|
+
return self.status == RunStatus.cancelled
|
|
534
|
+
|
|
535
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
536
|
+
_dict = {
|
|
537
|
+
k: v
|
|
538
|
+
for k, v in asdict(self).items()
|
|
539
|
+
if v is not None
|
|
540
|
+
and k
|
|
541
|
+
not in [
|
|
542
|
+
"metadata",
|
|
543
|
+
"images",
|
|
544
|
+
"videos",
|
|
545
|
+
"audio",
|
|
546
|
+
"response_audio",
|
|
547
|
+
"step_results",
|
|
548
|
+
"step_executor_runs",
|
|
549
|
+
"events",
|
|
550
|
+
"metrics",
|
|
551
|
+
"workflow_agent_run",
|
|
552
|
+
]
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
if self.status is not None:
|
|
556
|
+
_dict["status"] = self.status.value if isinstance(self.status, RunStatus) else self.status
|
|
557
|
+
|
|
558
|
+
if self.metadata is not None:
|
|
559
|
+
_dict["metadata"] = self.metadata
|
|
560
|
+
|
|
561
|
+
if self.images is not None:
|
|
562
|
+
_dict["images"] = [img.to_dict() for img in self.images]
|
|
563
|
+
|
|
564
|
+
if self.videos is not None:
|
|
565
|
+
_dict["videos"] = [vid.to_dict() for vid in self.videos]
|
|
566
|
+
|
|
567
|
+
if self.audio is not None:
|
|
568
|
+
_dict["audio"] = [aud.to_dict() for aud in self.audio]
|
|
569
|
+
|
|
570
|
+
if self.response_audio is not None:
|
|
571
|
+
_dict["response_audio"] = self.response_audio.to_dict()
|
|
572
|
+
|
|
573
|
+
if self.step_results:
|
|
574
|
+
flattened_responses = []
|
|
575
|
+
for step_response in self.step_results:
|
|
576
|
+
if isinstance(step_response, list):
|
|
577
|
+
# Handle List[StepOutput] from workflow components like Steps
|
|
578
|
+
flattened_responses.extend([s.to_dict() for s in step_response])
|
|
579
|
+
else:
|
|
580
|
+
# Handle single StepOutput
|
|
581
|
+
flattened_responses.append(step_response.to_dict())
|
|
582
|
+
_dict["step_results"] = flattened_responses
|
|
583
|
+
|
|
584
|
+
if self.step_executor_runs:
|
|
585
|
+
_dict["step_executor_runs"] = [run.to_dict() for run in self.step_executor_runs]
|
|
586
|
+
|
|
587
|
+
if self.workflow_agent_run is not None:
|
|
588
|
+
_dict["workflow_agent_run"] = self.workflow_agent_run.to_dict()
|
|
589
|
+
|
|
590
|
+
if self.metrics is not None:
|
|
591
|
+
_dict["metrics"] = self.metrics.to_dict()
|
|
592
|
+
|
|
593
|
+
if self.input is not None:
|
|
594
|
+
if isinstance(self.input, BaseModel):
|
|
595
|
+
_dict["input"] = self.input.model_dump(exclude_none=True)
|
|
596
|
+
else:
|
|
597
|
+
_dict["input"] = self.input
|
|
598
|
+
|
|
599
|
+
if self.content and isinstance(self.content, BaseModel):
|
|
600
|
+
_dict["content"] = self.content.model_dump(exclude_none=True, mode="json")
|
|
601
|
+
|
|
602
|
+
if self.events is not None:
|
|
603
|
+
_dict["events"] = [e.to_dict() for e in self.events]
|
|
604
|
+
|
|
605
|
+
return _dict
|
|
606
|
+
|
|
607
|
+
@classmethod
|
|
608
|
+
def from_dict(cls, data: Dict[str, Any]) -> "WorkflowRunOutput":
|
|
609
|
+
# Import here to avoid circular import
|
|
610
|
+
from agno.workflow.step import StepOutput
|
|
611
|
+
|
|
612
|
+
workflow_metrics_dict = data.pop("metrics", {})
|
|
613
|
+
workflow_metrics = None
|
|
614
|
+
if workflow_metrics_dict:
|
|
615
|
+
from agno.workflow.workflow import WorkflowMetrics
|
|
616
|
+
|
|
617
|
+
workflow_metrics = WorkflowMetrics.from_dict(workflow_metrics_dict)
|
|
618
|
+
|
|
619
|
+
step_results = data.pop("step_results", [])
|
|
620
|
+
parsed_step_results: List[Union[StepOutput, List[StepOutput]]] = []
|
|
621
|
+
if step_results:
|
|
622
|
+
for step_output_dict in step_results:
|
|
623
|
+
# Reconstruct StepOutput from dict
|
|
624
|
+
parsed_step_results.append(StepOutput.from_dict(step_output_dict))
|
|
625
|
+
|
|
626
|
+
# Parse step_executor_runs
|
|
627
|
+
step_executor_runs_data = data.pop("step_executor_runs", [])
|
|
628
|
+
step_executor_runs: List[Union[RunOutput, TeamRunOutput]] = []
|
|
629
|
+
if step_executor_runs_data:
|
|
630
|
+
step_executor_runs = []
|
|
631
|
+
for run_data in step_executor_runs_data:
|
|
632
|
+
if "team_id" in run_data or "team_name" in run_data:
|
|
633
|
+
step_executor_runs.append(TeamRunOutput.from_dict(run_data))
|
|
634
|
+
else:
|
|
635
|
+
step_executor_runs.append(RunOutput.from_dict(run_data))
|
|
636
|
+
|
|
637
|
+
workflow_agent_run_data = data.pop("workflow_agent_run", None)
|
|
638
|
+
workflow_agent_run = None
|
|
639
|
+
if workflow_agent_run_data:
|
|
640
|
+
if isinstance(workflow_agent_run_data, dict):
|
|
641
|
+
workflow_agent_run = RunOutput.from_dict(workflow_agent_run_data)
|
|
642
|
+
elif isinstance(workflow_agent_run_data, RunOutput):
|
|
643
|
+
workflow_agent_run = workflow_agent_run_data
|
|
644
|
+
|
|
645
|
+
metadata = data.pop("metadata", None)
|
|
646
|
+
|
|
647
|
+
images = reconstruct_images(data.pop("images", []))
|
|
648
|
+
videos = reconstruct_videos(data.pop("videos", []))
|
|
649
|
+
audio = reconstruct_audio_list(data.pop("audio", []))
|
|
650
|
+
response_audio = reconstruct_response_audio(data.pop("response_audio", None))
|
|
651
|
+
|
|
652
|
+
events_data = data.pop("events", [])
|
|
653
|
+
final_events = []
|
|
654
|
+
for event in events_data or []:
|
|
655
|
+
if "agent_id" in event:
|
|
656
|
+
# Agent event from agent step
|
|
657
|
+
from agno.run.agent import run_output_event_from_dict
|
|
658
|
+
|
|
659
|
+
event = run_output_event_from_dict(event)
|
|
660
|
+
elif "team_id" in event:
|
|
661
|
+
# Team event from team step
|
|
662
|
+
from agno.run.team import team_run_output_event_from_dict
|
|
663
|
+
|
|
664
|
+
event = team_run_output_event_from_dict(event)
|
|
665
|
+
else:
|
|
666
|
+
# Pure workflow event
|
|
667
|
+
event = workflow_run_output_event_from_dict(event)
|
|
668
|
+
final_events.append(event)
|
|
669
|
+
events = final_events
|
|
670
|
+
|
|
671
|
+
input_data = data.pop("input", None)
|
|
672
|
+
|
|
673
|
+
# Filter data to only include fields that are actually defined in the WorkflowRunOutput dataclass
|
|
674
|
+
from dataclasses import fields
|
|
675
|
+
|
|
676
|
+
supported_fields = {f.name for f in fields(cls)}
|
|
677
|
+
filtered_data = {k: v for k, v in data.items() if k in supported_fields}
|
|
678
|
+
|
|
679
|
+
return cls(
|
|
680
|
+
step_results=parsed_step_results,
|
|
681
|
+
workflow_agent_run=workflow_agent_run,
|
|
682
|
+
metadata=metadata,
|
|
683
|
+
images=images,
|
|
684
|
+
videos=videos,
|
|
685
|
+
audio=audio,
|
|
686
|
+
response_audio=response_audio,
|
|
687
|
+
events=events,
|
|
688
|
+
metrics=workflow_metrics,
|
|
689
|
+
step_executor_runs=step_executor_runs,
|
|
690
|
+
input=input_data,
|
|
691
|
+
**filtered_data,
|
|
692
|
+
)
|
|
693
|
+
|
|
694
|
+
def get_content_as_string(self, **kwargs) -> str:
|
|
695
|
+
import json
|
|
696
|
+
|
|
697
|
+
from pydantic import BaseModel
|
|
698
|
+
|
|
699
|
+
if isinstance(self.content, str):
|
|
700
|
+
return self.content
|
|
701
|
+
elif isinstance(self.content, BaseModel):
|
|
702
|
+
return self.content.model_dump_json(exclude_none=True, **kwargs)
|
|
703
|
+
else:
|
|
704
|
+
return json.dumps(self.content, **kwargs)
|
|
705
|
+
|
|
706
|
+
def has_completed(self) -> bool:
|
|
707
|
+
"""Check if the workflow run is completed (either successfully or with error)"""
|
|
708
|
+
return self.status in [RunStatus.completed, RunStatus.error]
|