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
|
@@ -0,0 +1,759 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
import warnings
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any, AsyncIterator, Awaitable, Callable, Dict, Iterator, List, Optional, Union
|
|
5
|
+
from uuid import uuid4
|
|
6
|
+
|
|
7
|
+
from agno.run.agent import RunOutputEvent
|
|
8
|
+
from agno.run.base import RunContext
|
|
9
|
+
from agno.run.team import TeamRunOutputEvent
|
|
10
|
+
from agno.run.workflow import (
|
|
11
|
+
ConditionExecutionCompletedEvent,
|
|
12
|
+
ConditionExecutionStartedEvent,
|
|
13
|
+
WorkflowRunOutput,
|
|
14
|
+
WorkflowRunOutputEvent,
|
|
15
|
+
)
|
|
16
|
+
from agno.session.workflow import WorkflowSession
|
|
17
|
+
from agno.utils.log import log_debug, logger
|
|
18
|
+
from agno.workflow.step import Step
|
|
19
|
+
from agno.workflow.types import StepInput, StepOutput, StepType
|
|
20
|
+
|
|
21
|
+
WorkflowSteps = List[
|
|
22
|
+
Union[
|
|
23
|
+
Callable[
|
|
24
|
+
[StepInput], Union[StepOutput, Awaitable[StepOutput], Iterator[StepOutput], AsyncIterator[StepOutput]]
|
|
25
|
+
],
|
|
26
|
+
Step,
|
|
27
|
+
"Steps", # type: ignore # noqa: F821
|
|
28
|
+
"Loop", # type: ignore # noqa: F821
|
|
29
|
+
"Parallel", # type: ignore # noqa: F821
|
|
30
|
+
"Condition", # type: ignore # noqa: F821
|
|
31
|
+
"Router", # type: ignore # noqa: F821
|
|
32
|
+
]
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass
|
|
37
|
+
class Condition:
|
|
38
|
+
"""A condition that executes a step (or list of steps) if the condition is met"""
|
|
39
|
+
|
|
40
|
+
# Evaluator should only return boolean
|
|
41
|
+
evaluator: Union[
|
|
42
|
+
Callable[[StepInput], bool],
|
|
43
|
+
Callable[[StepInput], Awaitable[bool]],
|
|
44
|
+
bool,
|
|
45
|
+
]
|
|
46
|
+
steps: WorkflowSteps
|
|
47
|
+
|
|
48
|
+
name: Optional[str] = None
|
|
49
|
+
description: Optional[str] = None
|
|
50
|
+
|
|
51
|
+
def _prepare_steps(self):
|
|
52
|
+
"""Prepare the steps for execution - mirrors workflow logic"""
|
|
53
|
+
from agno.agent.agent import Agent
|
|
54
|
+
from agno.team.team import Team
|
|
55
|
+
from agno.workflow.loop import Loop
|
|
56
|
+
from agno.workflow.parallel import Parallel
|
|
57
|
+
from agno.workflow.router import Router
|
|
58
|
+
from agno.workflow.step import Step
|
|
59
|
+
from agno.workflow.steps import Steps
|
|
60
|
+
|
|
61
|
+
prepared_steps: WorkflowSteps = []
|
|
62
|
+
for step in self.steps:
|
|
63
|
+
if callable(step) and hasattr(step, "__name__"):
|
|
64
|
+
prepared_steps.append(Step(name=step.__name__, description="User-defined callable step", executor=step))
|
|
65
|
+
elif isinstance(step, Agent):
|
|
66
|
+
prepared_steps.append(Step(name=step.name, description=step.description, agent=step))
|
|
67
|
+
elif isinstance(step, Team):
|
|
68
|
+
prepared_steps.append(Step(name=step.name, description=step.description, team=step))
|
|
69
|
+
elif isinstance(step, (Step, Steps, Loop, Parallel, Condition, Router)):
|
|
70
|
+
prepared_steps.append(step)
|
|
71
|
+
else:
|
|
72
|
+
raise ValueError(f"Invalid step type: {type(step).__name__}")
|
|
73
|
+
|
|
74
|
+
self.steps = prepared_steps
|
|
75
|
+
|
|
76
|
+
def _update_step_input_from_outputs(
|
|
77
|
+
self,
|
|
78
|
+
step_input: StepInput,
|
|
79
|
+
step_outputs: Union[StepOutput, List[StepOutput]],
|
|
80
|
+
condition_step_outputs: Optional[Dict[str, StepOutput]] = None,
|
|
81
|
+
) -> StepInput:
|
|
82
|
+
"""Helper to update step input from step outputs - mirrors Loop logic"""
|
|
83
|
+
current_images = step_input.images or []
|
|
84
|
+
current_videos = step_input.videos or []
|
|
85
|
+
current_audio = step_input.audio or []
|
|
86
|
+
|
|
87
|
+
if isinstance(step_outputs, list):
|
|
88
|
+
all_images = sum([out.images or [] for out in step_outputs], [])
|
|
89
|
+
all_videos = sum([out.videos or [] for out in step_outputs], [])
|
|
90
|
+
all_audio = sum([out.audio or [] for out in step_outputs], [])
|
|
91
|
+
# Use the last output's content for chaining
|
|
92
|
+
previous_step_content = step_outputs[-1].content if step_outputs else None
|
|
93
|
+
else:
|
|
94
|
+
# Single output
|
|
95
|
+
all_images = step_outputs.images or []
|
|
96
|
+
all_videos = step_outputs.videos or []
|
|
97
|
+
all_audio = step_outputs.audio or []
|
|
98
|
+
previous_step_content = step_outputs.content
|
|
99
|
+
|
|
100
|
+
updated_previous_step_outputs = {}
|
|
101
|
+
if step_input.previous_step_outputs:
|
|
102
|
+
updated_previous_step_outputs.update(step_input.previous_step_outputs)
|
|
103
|
+
if condition_step_outputs:
|
|
104
|
+
updated_previous_step_outputs.update(condition_step_outputs)
|
|
105
|
+
|
|
106
|
+
return StepInput(
|
|
107
|
+
input=step_input.input,
|
|
108
|
+
previous_step_content=previous_step_content,
|
|
109
|
+
previous_step_outputs=updated_previous_step_outputs,
|
|
110
|
+
additional_data=step_input.additional_data,
|
|
111
|
+
images=current_images + all_images,
|
|
112
|
+
videos=current_videos + all_videos,
|
|
113
|
+
audio=current_audio + all_audio,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
def _evaluate_condition(self, step_input: StepInput, session_state: Optional[Dict[str, Any]] = None) -> bool:
|
|
117
|
+
"""Evaluate the condition and return boolean result"""
|
|
118
|
+
if isinstance(self.evaluator, bool):
|
|
119
|
+
return self.evaluator
|
|
120
|
+
|
|
121
|
+
if callable(self.evaluator):
|
|
122
|
+
if session_state is not None and self._evaluator_has_session_state_param():
|
|
123
|
+
result = self.evaluator(step_input, session_state=session_state) # type: ignore[call-arg]
|
|
124
|
+
else:
|
|
125
|
+
result = self.evaluator(step_input)
|
|
126
|
+
|
|
127
|
+
if isinstance(result, bool):
|
|
128
|
+
return result
|
|
129
|
+
else:
|
|
130
|
+
logger.warning(f"Condition evaluator returned unexpected type: {type(result)}, expected bool")
|
|
131
|
+
return False
|
|
132
|
+
|
|
133
|
+
return False
|
|
134
|
+
|
|
135
|
+
async def _aevaluate_condition(self, step_input: StepInput, session_state: Optional[Dict[str, Any]] = None) -> bool:
|
|
136
|
+
"""Async version of condition evaluation"""
|
|
137
|
+
if isinstance(self.evaluator, bool):
|
|
138
|
+
return self.evaluator
|
|
139
|
+
|
|
140
|
+
if callable(self.evaluator):
|
|
141
|
+
has_session_state = session_state is not None and self._evaluator_has_session_state_param()
|
|
142
|
+
|
|
143
|
+
if inspect.iscoroutinefunction(self.evaluator):
|
|
144
|
+
if has_session_state:
|
|
145
|
+
result = await self.evaluator(step_input, session_state=session_state) # type: ignore[call-arg]
|
|
146
|
+
else:
|
|
147
|
+
result = await self.evaluator(step_input)
|
|
148
|
+
else:
|
|
149
|
+
if has_session_state:
|
|
150
|
+
result = self.evaluator(step_input, session_state=session_state) # type: ignore[call-arg]
|
|
151
|
+
else:
|
|
152
|
+
result = self.evaluator(step_input)
|
|
153
|
+
|
|
154
|
+
if isinstance(result, bool):
|
|
155
|
+
return result
|
|
156
|
+
else:
|
|
157
|
+
logger.warning(f"Condition evaluator returned unexpected type: {type(result)}, expected bool")
|
|
158
|
+
return False
|
|
159
|
+
|
|
160
|
+
return False
|
|
161
|
+
|
|
162
|
+
def _evaluator_has_session_state_param(self) -> bool:
|
|
163
|
+
"""Check if the evaluator function has a session_state parameter"""
|
|
164
|
+
if not callable(self.evaluator):
|
|
165
|
+
return False
|
|
166
|
+
|
|
167
|
+
try:
|
|
168
|
+
sig = inspect.signature(self.evaluator)
|
|
169
|
+
return "session_state" in sig.parameters
|
|
170
|
+
except Exception:
|
|
171
|
+
return False
|
|
172
|
+
|
|
173
|
+
def execute(
|
|
174
|
+
self,
|
|
175
|
+
step_input: StepInput,
|
|
176
|
+
session_id: Optional[str] = None,
|
|
177
|
+
user_id: Optional[str] = None,
|
|
178
|
+
workflow_run_response: Optional[WorkflowRunOutput] = None,
|
|
179
|
+
store_executor_outputs: bool = True,
|
|
180
|
+
run_context: Optional[RunContext] = None,
|
|
181
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
182
|
+
workflow_session: Optional[WorkflowSession] = None,
|
|
183
|
+
add_workflow_history_to_steps: Optional[bool] = False,
|
|
184
|
+
num_history_runs: int = 3,
|
|
185
|
+
background_tasks: Optional[Any] = None,
|
|
186
|
+
) -> StepOutput:
|
|
187
|
+
"""Execute the condition and its steps with sequential chaining if condition is true"""
|
|
188
|
+
log_debug(f"Condition Start: {self.name}", center=True, symbol="-")
|
|
189
|
+
|
|
190
|
+
conditional_step_id = str(uuid4())
|
|
191
|
+
|
|
192
|
+
self._prepare_steps()
|
|
193
|
+
|
|
194
|
+
# Evaluate the condition
|
|
195
|
+
if run_context is not None and run_context.session_state is not None:
|
|
196
|
+
condition_result = self._evaluate_condition(step_input, session_state=run_context.session_state)
|
|
197
|
+
else:
|
|
198
|
+
condition_result = self._evaluate_condition(step_input, session_state=session_state)
|
|
199
|
+
|
|
200
|
+
log_debug(f"Condition {self.name} evaluated to: {condition_result}")
|
|
201
|
+
|
|
202
|
+
if not condition_result:
|
|
203
|
+
log_debug(f"Condition {self.name} not met, skipping {len(self.steps)} steps")
|
|
204
|
+
return StepOutput(
|
|
205
|
+
step_name=self.name,
|
|
206
|
+
step_id=conditional_step_id,
|
|
207
|
+
step_type=StepType.CONDITION,
|
|
208
|
+
content=f"Condition {self.name} not met - skipped {len(self.steps)} steps",
|
|
209
|
+
success=True,
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
log_debug(f"Condition {self.name} met, executing {len(self.steps)} steps")
|
|
213
|
+
all_results: List[StepOutput] = []
|
|
214
|
+
current_step_input = step_input
|
|
215
|
+
condition_step_outputs = {}
|
|
216
|
+
|
|
217
|
+
for i, step in enumerate(self.steps):
|
|
218
|
+
try:
|
|
219
|
+
step_output = step.execute( # type: ignore[union-attr]
|
|
220
|
+
current_step_input,
|
|
221
|
+
session_id=session_id,
|
|
222
|
+
user_id=user_id,
|
|
223
|
+
workflow_run_response=workflow_run_response,
|
|
224
|
+
store_executor_outputs=store_executor_outputs,
|
|
225
|
+
run_context=run_context,
|
|
226
|
+
session_state=session_state,
|
|
227
|
+
workflow_session=workflow_session,
|
|
228
|
+
add_workflow_history_to_steps=add_workflow_history_to_steps,
|
|
229
|
+
num_history_runs=num_history_runs,
|
|
230
|
+
background_tasks=background_tasks,
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
# Handle both single StepOutput and List[StepOutput] (from Loop/Condition/Router steps)
|
|
234
|
+
if isinstance(step_output, list):
|
|
235
|
+
all_results.extend(step_output)
|
|
236
|
+
if step_output:
|
|
237
|
+
step_name = getattr(step, "name", f"step_{i}")
|
|
238
|
+
log_debug(f"Executing condition step {i + 1}/{len(self.steps)}: {step_name}")
|
|
239
|
+
|
|
240
|
+
condition_step_outputs[step_name] = step_output[-1]
|
|
241
|
+
|
|
242
|
+
if any(output.stop for output in step_output):
|
|
243
|
+
logger.info(f"Early termination requested by condition step {step_name}")
|
|
244
|
+
break
|
|
245
|
+
else:
|
|
246
|
+
all_results.append(step_output)
|
|
247
|
+
step_name = getattr(step, "name", f"step_{i}")
|
|
248
|
+
condition_step_outputs[step_name] = step_output
|
|
249
|
+
|
|
250
|
+
if step_output.stop:
|
|
251
|
+
logger.info(f"Early termination requested by condition step {step_name}")
|
|
252
|
+
break
|
|
253
|
+
|
|
254
|
+
step_name = getattr(step, "name", f"step_{i}")
|
|
255
|
+
log_debug(f"Condition step {step_name} completed")
|
|
256
|
+
|
|
257
|
+
current_step_input = self._update_step_input_from_outputs(
|
|
258
|
+
current_step_input, step_output, condition_step_outputs
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
except Exception as e:
|
|
262
|
+
step_name = getattr(step, "name", f"step_{i}")
|
|
263
|
+
logger.error(f"Condition step {step_name} failed: {e}")
|
|
264
|
+
error_output = StepOutput(
|
|
265
|
+
step_name=step_name,
|
|
266
|
+
content=f"Step {step_name} failed: {str(e)}",
|
|
267
|
+
success=False,
|
|
268
|
+
error=str(e),
|
|
269
|
+
)
|
|
270
|
+
all_results.append(error_output)
|
|
271
|
+
break
|
|
272
|
+
|
|
273
|
+
log_debug(f"Condition End: {self.name} ({len(all_results)} results)", center=True, symbol="-")
|
|
274
|
+
|
|
275
|
+
return StepOutput(
|
|
276
|
+
step_name=self.name,
|
|
277
|
+
step_id=conditional_step_id,
|
|
278
|
+
step_type=StepType.CONDITION,
|
|
279
|
+
content=f"Condition {self.name} completed with {len(all_results)} results",
|
|
280
|
+
success=all(result.success for result in all_results) if all_results else True,
|
|
281
|
+
error=None,
|
|
282
|
+
stop=False,
|
|
283
|
+
steps=all_results,
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
def execute_stream(
|
|
287
|
+
self,
|
|
288
|
+
step_input: StepInput,
|
|
289
|
+
session_id: Optional[str] = None,
|
|
290
|
+
user_id: Optional[str] = None,
|
|
291
|
+
stream_events: bool = False,
|
|
292
|
+
stream_intermediate_steps: bool = False, # type: ignore
|
|
293
|
+
stream_executor_events: bool = True,
|
|
294
|
+
workflow_run_response: Optional[WorkflowRunOutput] = None,
|
|
295
|
+
step_index: Optional[Union[int, tuple]] = None,
|
|
296
|
+
store_executor_outputs: bool = True,
|
|
297
|
+
run_context: Optional[RunContext] = None,
|
|
298
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
299
|
+
parent_step_id: Optional[str] = None,
|
|
300
|
+
workflow_session: Optional[WorkflowSession] = None,
|
|
301
|
+
add_workflow_history_to_steps: Optional[bool] = False,
|
|
302
|
+
num_history_runs: int = 3,
|
|
303
|
+
background_tasks: Optional[Any] = None,
|
|
304
|
+
) -> Iterator[Union[WorkflowRunOutputEvent, StepOutput]]:
|
|
305
|
+
"""Execute the condition with streaming support - mirrors Loop logic"""
|
|
306
|
+
log_debug(f"Condition Start: {self.name}", center=True, symbol="-")
|
|
307
|
+
|
|
308
|
+
conditional_step_id = str(uuid4())
|
|
309
|
+
|
|
310
|
+
self._prepare_steps()
|
|
311
|
+
|
|
312
|
+
# Evaluate the condition
|
|
313
|
+
if run_context is not None and run_context.session_state is not None:
|
|
314
|
+
condition_result = self._evaluate_condition(step_input, session_state=run_context.session_state)
|
|
315
|
+
else:
|
|
316
|
+
condition_result = self._evaluate_condition(step_input, session_state=session_state)
|
|
317
|
+
log_debug(f"Condition {self.name} evaluated to: {condition_result}")
|
|
318
|
+
|
|
319
|
+
# Considering both stream_events and stream_intermediate_steps (deprecated)
|
|
320
|
+
if stream_intermediate_steps is not None:
|
|
321
|
+
warnings.warn(
|
|
322
|
+
"The 'stream_intermediate_steps' parameter is deprecated and will be removed in future versions. Use 'stream_events' instead.",
|
|
323
|
+
DeprecationWarning,
|
|
324
|
+
stacklevel=2,
|
|
325
|
+
)
|
|
326
|
+
stream_events = stream_events or stream_intermediate_steps
|
|
327
|
+
|
|
328
|
+
if stream_events and workflow_run_response:
|
|
329
|
+
# Yield condition started event
|
|
330
|
+
yield ConditionExecutionStartedEvent(
|
|
331
|
+
run_id=workflow_run_response.run_id or "",
|
|
332
|
+
workflow_name=workflow_run_response.workflow_name or "",
|
|
333
|
+
workflow_id=workflow_run_response.workflow_id or "",
|
|
334
|
+
session_id=workflow_run_response.session_id or "",
|
|
335
|
+
step_name=self.name,
|
|
336
|
+
step_index=step_index,
|
|
337
|
+
condition_result=condition_result,
|
|
338
|
+
step_id=conditional_step_id,
|
|
339
|
+
parent_step_id=parent_step_id,
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
if not condition_result:
|
|
343
|
+
if stream_events and workflow_run_response:
|
|
344
|
+
# Yield condition completed event for empty case
|
|
345
|
+
yield ConditionExecutionCompletedEvent(
|
|
346
|
+
run_id=workflow_run_response.run_id or "",
|
|
347
|
+
workflow_name=workflow_run_response.workflow_name or "",
|
|
348
|
+
workflow_id=workflow_run_response.workflow_id or "",
|
|
349
|
+
session_id=workflow_run_response.session_id or "",
|
|
350
|
+
step_name=self.name,
|
|
351
|
+
step_index=step_index,
|
|
352
|
+
condition_result=False,
|
|
353
|
+
executed_steps=0,
|
|
354
|
+
step_results=[],
|
|
355
|
+
step_id=conditional_step_id,
|
|
356
|
+
parent_step_id=parent_step_id,
|
|
357
|
+
)
|
|
358
|
+
return
|
|
359
|
+
|
|
360
|
+
log_debug(f"Condition {self.name} met, executing {len(self.steps)} steps")
|
|
361
|
+
all_results = []
|
|
362
|
+
current_step_input = step_input
|
|
363
|
+
condition_step_outputs = {}
|
|
364
|
+
|
|
365
|
+
for i, step in enumerate(self.steps):
|
|
366
|
+
try:
|
|
367
|
+
step_outputs_for_step = []
|
|
368
|
+
|
|
369
|
+
# Create child index for each step within condition
|
|
370
|
+
if step_index is None or isinstance(step_index, int):
|
|
371
|
+
# Condition is a main step - child steps get x.1, x.2, x.3 format
|
|
372
|
+
child_step_index = (step_index if step_index is not None else 1, i)
|
|
373
|
+
else:
|
|
374
|
+
# Condition is already a child step - child steps get same parent number: x.y, x.y, x.y
|
|
375
|
+
child_step_index = step_index
|
|
376
|
+
|
|
377
|
+
# Stream step execution
|
|
378
|
+
for event in step.execute_stream( # type: ignore[union-attr]
|
|
379
|
+
current_step_input,
|
|
380
|
+
session_id=session_id,
|
|
381
|
+
user_id=user_id,
|
|
382
|
+
stream_events=stream_events,
|
|
383
|
+
stream_executor_events=stream_executor_events,
|
|
384
|
+
workflow_run_response=workflow_run_response,
|
|
385
|
+
step_index=child_step_index,
|
|
386
|
+
store_executor_outputs=store_executor_outputs,
|
|
387
|
+
run_context=run_context,
|
|
388
|
+
session_state=session_state,
|
|
389
|
+
parent_step_id=conditional_step_id,
|
|
390
|
+
workflow_session=workflow_session,
|
|
391
|
+
add_workflow_history_to_steps=add_workflow_history_to_steps,
|
|
392
|
+
num_history_runs=num_history_runs,
|
|
393
|
+
background_tasks=background_tasks,
|
|
394
|
+
):
|
|
395
|
+
if isinstance(event, StepOutput):
|
|
396
|
+
step_outputs_for_step.append(event)
|
|
397
|
+
all_results.append(event)
|
|
398
|
+
else:
|
|
399
|
+
# Yield other events (streaming content, step events, etc.)
|
|
400
|
+
yield event
|
|
401
|
+
|
|
402
|
+
step_name = getattr(step, "name", f"step_{i}")
|
|
403
|
+
log_debug(f"Condition step {step_name} streaming completed")
|
|
404
|
+
|
|
405
|
+
if step_outputs_for_step:
|
|
406
|
+
if len(step_outputs_for_step) == 1:
|
|
407
|
+
condition_step_outputs[step_name] = step_outputs_for_step[0]
|
|
408
|
+
|
|
409
|
+
if step_outputs_for_step[0].stop:
|
|
410
|
+
logger.info(f"Early termination requested by condition step {step_name}")
|
|
411
|
+
break
|
|
412
|
+
|
|
413
|
+
current_step_input = self._update_step_input_from_outputs(
|
|
414
|
+
current_step_input, step_outputs_for_step[0], condition_step_outputs
|
|
415
|
+
)
|
|
416
|
+
else:
|
|
417
|
+
# Use last output
|
|
418
|
+
condition_step_outputs[step_name] = step_outputs_for_step[-1]
|
|
419
|
+
|
|
420
|
+
if any(output.stop for output in step_outputs_for_step):
|
|
421
|
+
logger.info(f"Early termination requested by condition step {step_name}")
|
|
422
|
+
break
|
|
423
|
+
|
|
424
|
+
current_step_input = self._update_step_input_from_outputs(
|
|
425
|
+
current_step_input, step_outputs_for_step, condition_step_outputs
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
except Exception as e:
|
|
429
|
+
step_name = getattr(step, "name", f"step_{i}")
|
|
430
|
+
logger.error(f"Condition step {step_name} streaming failed: {e}")
|
|
431
|
+
error_output = StepOutput(
|
|
432
|
+
step_name=step_name,
|
|
433
|
+
content=f"Step {step_name} failed: {str(e)}",
|
|
434
|
+
success=False,
|
|
435
|
+
error=str(e),
|
|
436
|
+
)
|
|
437
|
+
all_results.append(error_output)
|
|
438
|
+
break
|
|
439
|
+
|
|
440
|
+
log_debug(f"Condition End: {self.name} ({len(all_results)} results)", center=True, symbol="-")
|
|
441
|
+
if stream_events and workflow_run_response:
|
|
442
|
+
# Yield condition completed event
|
|
443
|
+
yield ConditionExecutionCompletedEvent(
|
|
444
|
+
run_id=workflow_run_response.run_id or "",
|
|
445
|
+
workflow_name=workflow_run_response.workflow_name or "",
|
|
446
|
+
workflow_id=workflow_run_response.workflow_id or "",
|
|
447
|
+
session_id=workflow_run_response.session_id or "",
|
|
448
|
+
step_name=self.name,
|
|
449
|
+
step_index=step_index,
|
|
450
|
+
condition_result=True,
|
|
451
|
+
executed_steps=len(self.steps),
|
|
452
|
+
step_results=all_results,
|
|
453
|
+
step_id=conditional_step_id,
|
|
454
|
+
parent_step_id=parent_step_id,
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
yield StepOutput(
|
|
458
|
+
step_name=self.name,
|
|
459
|
+
step_id=conditional_step_id,
|
|
460
|
+
step_type=StepType.CONDITION,
|
|
461
|
+
content=f"Condition {self.name} completed with {len(all_results)} results",
|
|
462
|
+
success=all(result.success for result in all_results) if all_results else True,
|
|
463
|
+
steps=all_results,
|
|
464
|
+
)
|
|
465
|
+
|
|
466
|
+
async def aexecute(
|
|
467
|
+
self,
|
|
468
|
+
step_input: StepInput,
|
|
469
|
+
session_id: Optional[str] = None,
|
|
470
|
+
user_id: Optional[str] = None,
|
|
471
|
+
workflow_run_response: Optional[WorkflowRunOutput] = None,
|
|
472
|
+
store_executor_outputs: bool = True,
|
|
473
|
+
run_context: Optional[RunContext] = None,
|
|
474
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
475
|
+
workflow_session: Optional[WorkflowSession] = None,
|
|
476
|
+
add_workflow_history_to_steps: Optional[bool] = False,
|
|
477
|
+
num_history_runs: int = 3,
|
|
478
|
+
background_tasks: Optional[Any] = None,
|
|
479
|
+
) -> StepOutput:
|
|
480
|
+
"""Async execute the condition and its steps with sequential chaining"""
|
|
481
|
+
log_debug(f"Condition Start: {self.name}", center=True, symbol="-")
|
|
482
|
+
|
|
483
|
+
conditional_step_id = str(uuid4())
|
|
484
|
+
|
|
485
|
+
self._prepare_steps()
|
|
486
|
+
|
|
487
|
+
# Evaluate the condition
|
|
488
|
+
if run_context is not None and run_context.session_state is not None:
|
|
489
|
+
condition_result = await self._aevaluate_condition(step_input, session_state=run_context.session_state)
|
|
490
|
+
else:
|
|
491
|
+
condition_result = await self._aevaluate_condition(step_input, session_state=session_state)
|
|
492
|
+
log_debug(f"Condition {self.name} evaluated to: {condition_result}")
|
|
493
|
+
|
|
494
|
+
if not condition_result:
|
|
495
|
+
log_debug(f"Condition {self.name} not met, skipping {len(self.steps)} steps")
|
|
496
|
+
return StepOutput(
|
|
497
|
+
step_name=self.name,
|
|
498
|
+
step_id=str(uuid4()),
|
|
499
|
+
step_type=StepType.CONDITION,
|
|
500
|
+
content=f"Condition {self.name} not met - skipped {len(self.steps)} steps",
|
|
501
|
+
success=True,
|
|
502
|
+
)
|
|
503
|
+
|
|
504
|
+
log_debug(f"Condition {self.name} met, executing {len(self.steps)} steps")
|
|
505
|
+
|
|
506
|
+
# Chain steps sequentially like Loop does
|
|
507
|
+
all_results: List[StepOutput] = []
|
|
508
|
+
current_step_input = step_input
|
|
509
|
+
condition_step_outputs = {}
|
|
510
|
+
|
|
511
|
+
for i, step in enumerate(self.steps):
|
|
512
|
+
try:
|
|
513
|
+
step_output = await step.aexecute( # type: ignore[union-attr]
|
|
514
|
+
current_step_input,
|
|
515
|
+
session_id=session_id,
|
|
516
|
+
user_id=user_id,
|
|
517
|
+
workflow_run_response=workflow_run_response,
|
|
518
|
+
store_executor_outputs=store_executor_outputs,
|
|
519
|
+
run_context=run_context,
|
|
520
|
+
session_state=session_state,
|
|
521
|
+
workflow_session=workflow_session,
|
|
522
|
+
add_workflow_history_to_steps=add_workflow_history_to_steps,
|
|
523
|
+
num_history_runs=num_history_runs,
|
|
524
|
+
background_tasks=background_tasks,
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
# Handle both single StepOutput and List[StepOutput]
|
|
528
|
+
if isinstance(step_output, list):
|
|
529
|
+
all_results.extend(step_output)
|
|
530
|
+
if step_output:
|
|
531
|
+
step_name = getattr(step, "name", f"step_{i}")
|
|
532
|
+
condition_step_outputs[step_name] = step_output[-1]
|
|
533
|
+
|
|
534
|
+
if any(output.stop for output in step_output):
|
|
535
|
+
logger.info(f"Early termination requested by condition step {step_name}")
|
|
536
|
+
break
|
|
537
|
+
else:
|
|
538
|
+
all_results.append(step_output)
|
|
539
|
+
step_name = getattr(step, "name", f"step_{i}")
|
|
540
|
+
condition_step_outputs[step_name] = step_output
|
|
541
|
+
|
|
542
|
+
if step_output.stop:
|
|
543
|
+
logger.info(f"Early termination requested by condition step {step_name}")
|
|
544
|
+
break
|
|
545
|
+
|
|
546
|
+
step_name = getattr(step, "name", f"step_{i}")
|
|
547
|
+
log_debug(f"Condition step {step_name} async completed")
|
|
548
|
+
|
|
549
|
+
current_step_input = self._update_step_input_from_outputs(
|
|
550
|
+
current_step_input, step_output, condition_step_outputs
|
|
551
|
+
)
|
|
552
|
+
|
|
553
|
+
except Exception as e:
|
|
554
|
+
step_name = getattr(step, "name", f"step_{i}")
|
|
555
|
+
logger.error(f"Condition step {step_name} async failed: {e}")
|
|
556
|
+
error_output = StepOutput(
|
|
557
|
+
step_name=step_name,
|
|
558
|
+
content=f"Step {step_name} failed: {str(e)}",
|
|
559
|
+
success=False,
|
|
560
|
+
error=str(e),
|
|
561
|
+
)
|
|
562
|
+
all_results.append(error_output)
|
|
563
|
+
break
|
|
564
|
+
|
|
565
|
+
log_debug(f"Condition End: {self.name} ({len(all_results)} results)", center=True, symbol="-")
|
|
566
|
+
|
|
567
|
+
return StepOutput(
|
|
568
|
+
step_name=self.name,
|
|
569
|
+
step_id=conditional_step_id,
|
|
570
|
+
step_type=StepType.CONDITION,
|
|
571
|
+
content=f"Condition {self.name} completed with {len(all_results)} results",
|
|
572
|
+
success=all(result.success for result in all_results) if all_results else True,
|
|
573
|
+
error=None,
|
|
574
|
+
stop=False,
|
|
575
|
+
steps=all_results,
|
|
576
|
+
)
|
|
577
|
+
|
|
578
|
+
async def aexecute_stream(
|
|
579
|
+
self,
|
|
580
|
+
step_input: StepInput,
|
|
581
|
+
session_id: Optional[str] = None,
|
|
582
|
+
user_id: Optional[str] = None,
|
|
583
|
+
stream_events: bool = False,
|
|
584
|
+
stream_intermediate_steps: bool = False,
|
|
585
|
+
stream_executor_events: bool = True,
|
|
586
|
+
workflow_run_response: Optional[WorkflowRunOutput] = None,
|
|
587
|
+
step_index: Optional[Union[int, tuple]] = None,
|
|
588
|
+
store_executor_outputs: bool = True,
|
|
589
|
+
run_context: Optional[RunContext] = None,
|
|
590
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
591
|
+
parent_step_id: Optional[str] = None,
|
|
592
|
+
workflow_session: Optional[WorkflowSession] = None,
|
|
593
|
+
add_workflow_history_to_steps: Optional[bool] = False,
|
|
594
|
+
num_history_runs: int = 3,
|
|
595
|
+
background_tasks: Optional[Any] = None,
|
|
596
|
+
) -> AsyncIterator[Union[WorkflowRunOutputEvent, TeamRunOutputEvent, RunOutputEvent, StepOutput]]:
|
|
597
|
+
"""Async execute the condition with streaming support - mirrors Loop logic"""
|
|
598
|
+
log_debug(f"Condition Start: {self.name}", center=True, symbol="-")
|
|
599
|
+
|
|
600
|
+
conditional_step_id = str(uuid4())
|
|
601
|
+
|
|
602
|
+
self._prepare_steps()
|
|
603
|
+
|
|
604
|
+
# Evaluate the condition
|
|
605
|
+
if run_context is not None and run_context.session_state is not None:
|
|
606
|
+
condition_result = await self._aevaluate_condition(step_input, session_state=run_context.session_state)
|
|
607
|
+
else:
|
|
608
|
+
condition_result = await self._aevaluate_condition(step_input, session_state=session_state)
|
|
609
|
+
log_debug(f"Condition {self.name} evaluated to: {condition_result}")
|
|
610
|
+
|
|
611
|
+
# Considering both stream_events and stream_intermediate_steps (deprecated)
|
|
612
|
+
if stream_intermediate_steps is not None:
|
|
613
|
+
warnings.warn(
|
|
614
|
+
"The 'stream_intermediate_steps' parameter is deprecated and will be removed in future versions. Use 'stream_events' instead.",
|
|
615
|
+
DeprecationWarning,
|
|
616
|
+
stacklevel=2,
|
|
617
|
+
)
|
|
618
|
+
stream_events = stream_events or stream_intermediate_steps
|
|
619
|
+
|
|
620
|
+
if stream_events and workflow_run_response:
|
|
621
|
+
# Yield condition started event
|
|
622
|
+
yield ConditionExecutionStartedEvent(
|
|
623
|
+
run_id=workflow_run_response.run_id or "",
|
|
624
|
+
workflow_name=workflow_run_response.workflow_name or "",
|
|
625
|
+
workflow_id=workflow_run_response.workflow_id or "",
|
|
626
|
+
session_id=workflow_run_response.session_id or "",
|
|
627
|
+
step_name=self.name,
|
|
628
|
+
step_index=step_index,
|
|
629
|
+
condition_result=condition_result,
|
|
630
|
+
step_id=conditional_step_id,
|
|
631
|
+
parent_step_id=parent_step_id,
|
|
632
|
+
)
|
|
633
|
+
|
|
634
|
+
if not condition_result:
|
|
635
|
+
if stream_events and workflow_run_response:
|
|
636
|
+
# Yield condition completed event for empty case
|
|
637
|
+
yield ConditionExecutionCompletedEvent(
|
|
638
|
+
run_id=workflow_run_response.run_id or "",
|
|
639
|
+
workflow_name=workflow_run_response.workflow_name or "",
|
|
640
|
+
workflow_id=workflow_run_response.workflow_id or "",
|
|
641
|
+
session_id=workflow_run_response.session_id or "",
|
|
642
|
+
step_name=self.name,
|
|
643
|
+
step_index=step_index,
|
|
644
|
+
condition_result=False,
|
|
645
|
+
executed_steps=0,
|
|
646
|
+
step_results=[],
|
|
647
|
+
step_id=conditional_step_id,
|
|
648
|
+
parent_step_id=parent_step_id,
|
|
649
|
+
)
|
|
650
|
+
return
|
|
651
|
+
|
|
652
|
+
log_debug(f"Condition {self.name} met, executing {len(self.steps)} steps")
|
|
653
|
+
|
|
654
|
+
# Chain steps sequentially like Loop does
|
|
655
|
+
all_results = []
|
|
656
|
+
current_step_input = step_input
|
|
657
|
+
condition_step_outputs = {}
|
|
658
|
+
|
|
659
|
+
for i, step in enumerate(self.steps):
|
|
660
|
+
try:
|
|
661
|
+
step_outputs_for_step = []
|
|
662
|
+
|
|
663
|
+
# Create child index for each step within condition
|
|
664
|
+
if step_index is None or isinstance(step_index, int):
|
|
665
|
+
# Condition is a main step - child steps get x.1, x.2, x.3 format
|
|
666
|
+
child_step_index = (step_index if step_index is not None else 1, i)
|
|
667
|
+
else:
|
|
668
|
+
# Condition is already a child step - child steps get same parent number: x.y, x.y, x.y
|
|
669
|
+
child_step_index = step_index
|
|
670
|
+
|
|
671
|
+
# Stream step execution - mirroring Loop logic
|
|
672
|
+
async for event in step.aexecute_stream( # type: ignore[union-attr]
|
|
673
|
+
current_step_input,
|
|
674
|
+
session_id=session_id,
|
|
675
|
+
user_id=user_id,
|
|
676
|
+
stream_events=stream_events,
|
|
677
|
+
stream_executor_events=stream_executor_events,
|
|
678
|
+
workflow_run_response=workflow_run_response,
|
|
679
|
+
step_index=child_step_index,
|
|
680
|
+
store_executor_outputs=store_executor_outputs,
|
|
681
|
+
run_context=run_context,
|
|
682
|
+
session_state=session_state,
|
|
683
|
+
parent_step_id=conditional_step_id,
|
|
684
|
+
workflow_session=workflow_session,
|
|
685
|
+
add_workflow_history_to_steps=add_workflow_history_to_steps,
|
|
686
|
+
num_history_runs=num_history_runs,
|
|
687
|
+
background_tasks=background_tasks,
|
|
688
|
+
):
|
|
689
|
+
if isinstance(event, StepOutput):
|
|
690
|
+
step_outputs_for_step.append(event)
|
|
691
|
+
all_results.append(event)
|
|
692
|
+
else:
|
|
693
|
+
# Yield other events (streaming content, step events, etc.)
|
|
694
|
+
yield event
|
|
695
|
+
|
|
696
|
+
step_name = getattr(step, "name", f"step_{i}")
|
|
697
|
+
log_debug(f"Condition step {step_name} async streaming completed")
|
|
698
|
+
|
|
699
|
+
if step_outputs_for_step:
|
|
700
|
+
if len(step_outputs_for_step) == 1:
|
|
701
|
+
condition_step_outputs[step_name] = step_outputs_for_step[0]
|
|
702
|
+
|
|
703
|
+
if step_outputs_for_step[0].stop:
|
|
704
|
+
logger.info(f"Early termination requested by condition step {step_name}")
|
|
705
|
+
break
|
|
706
|
+
|
|
707
|
+
current_step_input = self._update_step_input_from_outputs(
|
|
708
|
+
current_step_input, step_outputs_for_step[0], condition_step_outputs
|
|
709
|
+
)
|
|
710
|
+
else:
|
|
711
|
+
# Use last output
|
|
712
|
+
condition_step_outputs[step_name] = step_outputs_for_step[-1]
|
|
713
|
+
|
|
714
|
+
if any(output.stop for output in step_outputs_for_step):
|
|
715
|
+
logger.info(f"Early termination requested by condition step {step_name}")
|
|
716
|
+
break
|
|
717
|
+
|
|
718
|
+
current_step_input = self._update_step_input_from_outputs(
|
|
719
|
+
current_step_input, step_outputs_for_step, condition_step_outputs
|
|
720
|
+
)
|
|
721
|
+
|
|
722
|
+
except Exception as e:
|
|
723
|
+
step_name = getattr(step, "name", f"step_{i}")
|
|
724
|
+
logger.error(f"Condition step {step_name} async streaming failed: {e}")
|
|
725
|
+
error_output = StepOutput(
|
|
726
|
+
step_name=step_name,
|
|
727
|
+
content=f"Step {step_name} failed: {str(e)}",
|
|
728
|
+
success=False,
|
|
729
|
+
error=str(e),
|
|
730
|
+
)
|
|
731
|
+
all_results.append(error_output)
|
|
732
|
+
break
|
|
733
|
+
|
|
734
|
+
log_debug(f"Condition End: {self.name} ({len(all_results)} results)", center=True, symbol="-")
|
|
735
|
+
|
|
736
|
+
if stream_events and workflow_run_response:
|
|
737
|
+
# Yield condition completed event
|
|
738
|
+
yield ConditionExecutionCompletedEvent(
|
|
739
|
+
run_id=workflow_run_response.run_id or "",
|
|
740
|
+
workflow_name=workflow_run_response.workflow_name or "",
|
|
741
|
+
workflow_id=workflow_run_response.workflow_id or "",
|
|
742
|
+
session_id=workflow_run_response.session_id or "",
|
|
743
|
+
step_name=self.name,
|
|
744
|
+
step_index=step_index,
|
|
745
|
+
condition_result=True,
|
|
746
|
+
executed_steps=len(self.steps),
|
|
747
|
+
step_results=all_results,
|
|
748
|
+
step_id=conditional_step_id,
|
|
749
|
+
parent_step_id=parent_step_id,
|
|
750
|
+
)
|
|
751
|
+
|
|
752
|
+
yield StepOutput(
|
|
753
|
+
step_name=self.name,
|
|
754
|
+
step_id=conditional_step_id,
|
|
755
|
+
step_type=StepType.CONDITION,
|
|
756
|
+
content=f"Condition {self.name} completed with {len(all_results)} results",
|
|
757
|
+
success=all(result.success for result in all_results) if all_results else True,
|
|
758
|
+
steps=all_results,
|
|
759
|
+
)
|