agno 2.2.13__py3-none-any.whl → 2.4.3__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/agent/__init__.py +6 -0
- agno/agent/agent.py +5252 -3145
- agno/agent/remote.py +525 -0
- agno/api/api.py +2 -0
- agno/client/__init__.py +3 -0
- agno/client/a2a/__init__.py +10 -0
- agno/client/a2a/client.py +554 -0
- agno/client/a2a/schemas.py +112 -0
- agno/client/a2a/utils.py +369 -0
- agno/client/os.py +2669 -0
- agno/compression/__init__.py +3 -0
- agno/compression/manager.py +247 -0
- agno/culture/manager.py +2 -2
- agno/db/base.py +927 -6
- agno/db/dynamo/dynamo.py +788 -2
- agno/db/dynamo/schemas.py +128 -0
- agno/db/dynamo/utils.py +26 -3
- agno/db/firestore/firestore.py +674 -50
- agno/db/firestore/schemas.py +41 -0
- agno/db/firestore/utils.py +25 -10
- agno/db/gcs_json/gcs_json_db.py +506 -3
- agno/db/gcs_json/utils.py +14 -2
- agno/db/in_memory/in_memory_db.py +203 -4
- agno/db/in_memory/utils.py +14 -2
- agno/db/json/json_db.py +498 -2
- agno/db/json/utils.py +14 -2
- agno/db/migrations/manager.py +199 -0
- agno/db/migrations/utils.py +19 -0
- agno/db/migrations/v1_to_v2.py +54 -16
- agno/db/migrations/versions/__init__.py +0 -0
- agno/db/migrations/versions/v2_3_0.py +977 -0
- agno/db/mongo/async_mongo.py +1013 -39
- agno/db/mongo/mongo.py +684 -4
- agno/db/mongo/schemas.py +48 -0
- agno/db/mongo/utils.py +17 -0
- agno/db/mysql/__init__.py +2 -1
- agno/db/mysql/async_mysql.py +2958 -0
- agno/db/mysql/mysql.py +722 -53
- agno/db/mysql/schemas.py +77 -11
- agno/db/mysql/utils.py +151 -8
- agno/db/postgres/async_postgres.py +1254 -137
- agno/db/postgres/postgres.py +2316 -93
- agno/db/postgres/schemas.py +153 -21
- agno/db/postgres/utils.py +22 -7
- agno/db/redis/redis.py +531 -3
- agno/db/redis/schemas.py +36 -0
- agno/db/redis/utils.py +31 -15
- agno/db/schemas/evals.py +1 -0
- agno/db/schemas/memory.py +20 -9
- agno/db/singlestore/schemas.py +70 -1
- agno/db/singlestore/singlestore.py +737 -74
- agno/db/singlestore/utils.py +13 -3
- agno/db/sqlite/async_sqlite.py +1069 -89
- agno/db/sqlite/schemas.py +133 -1
- agno/db/sqlite/sqlite.py +2203 -165
- agno/db/sqlite/utils.py +21 -11
- agno/db/surrealdb/models.py +25 -0
- agno/db/surrealdb/surrealdb.py +603 -1
- agno/db/utils.py +60 -0
- agno/eval/__init__.py +26 -3
- agno/eval/accuracy.py +25 -12
- agno/eval/agent_as_judge.py +871 -0
- agno/eval/base.py +29 -0
- agno/eval/performance.py +10 -4
- agno/eval/reliability.py +22 -13
- agno/eval/utils.py +2 -1
- agno/exceptions.py +42 -0
- agno/hooks/__init__.py +3 -0
- agno/hooks/decorator.py +164 -0
- agno/integrations/discord/client.py +13 -2
- agno/knowledge/__init__.py +4 -0
- agno/knowledge/chunking/code.py +90 -0
- agno/knowledge/chunking/document.py +65 -4
- agno/knowledge/chunking/fixed.py +4 -1
- agno/knowledge/chunking/markdown.py +102 -11
- agno/knowledge/chunking/recursive.py +2 -2
- agno/knowledge/chunking/semantic.py +130 -48
- agno/knowledge/chunking/strategy.py +18 -0
- agno/knowledge/embedder/azure_openai.py +0 -1
- agno/knowledge/embedder/google.py +1 -1
- agno/knowledge/embedder/mistral.py +1 -1
- agno/knowledge/embedder/nebius.py +1 -1
- agno/knowledge/embedder/openai.py +16 -12
- agno/knowledge/filesystem.py +412 -0
- agno/knowledge/knowledge.py +4261 -1199
- agno/knowledge/protocol.py +134 -0
- agno/knowledge/reader/arxiv_reader.py +3 -2
- agno/knowledge/reader/base.py +9 -7
- agno/knowledge/reader/csv_reader.py +91 -42
- agno/knowledge/reader/docx_reader.py +9 -10
- agno/knowledge/reader/excel_reader.py +225 -0
- agno/knowledge/reader/field_labeled_csv_reader.py +38 -48
- agno/knowledge/reader/firecrawl_reader.py +3 -2
- agno/knowledge/reader/json_reader.py +16 -22
- agno/knowledge/reader/markdown_reader.py +15 -14
- agno/knowledge/reader/pdf_reader.py +33 -28
- agno/knowledge/reader/pptx_reader.py +9 -10
- agno/knowledge/reader/reader_factory.py +135 -1
- agno/knowledge/reader/s3_reader.py +8 -16
- agno/knowledge/reader/tavily_reader.py +3 -3
- agno/knowledge/reader/text_reader.py +15 -14
- agno/knowledge/reader/utils/__init__.py +17 -0
- agno/knowledge/reader/utils/spreadsheet.py +114 -0
- agno/knowledge/reader/web_search_reader.py +8 -65
- agno/knowledge/reader/website_reader.py +16 -13
- agno/knowledge/reader/wikipedia_reader.py +36 -3
- agno/knowledge/reader/youtube_reader.py +3 -2
- agno/knowledge/remote_content/__init__.py +33 -0
- agno/knowledge/remote_content/config.py +266 -0
- agno/knowledge/remote_content/remote_content.py +105 -17
- agno/knowledge/utils.py +76 -22
- agno/learn/__init__.py +71 -0
- agno/learn/config.py +463 -0
- agno/learn/curate.py +185 -0
- agno/learn/machine.py +725 -0
- agno/learn/schemas.py +1114 -0
- agno/learn/stores/__init__.py +38 -0
- agno/learn/stores/decision_log.py +1156 -0
- agno/learn/stores/entity_memory.py +3275 -0
- agno/learn/stores/learned_knowledge.py +1583 -0
- agno/learn/stores/protocol.py +117 -0
- agno/learn/stores/session_context.py +1217 -0
- agno/learn/stores/user_memory.py +1495 -0
- agno/learn/stores/user_profile.py +1220 -0
- agno/learn/utils.py +209 -0
- agno/media.py +22 -6
- agno/memory/__init__.py +14 -1
- agno/memory/manager.py +223 -8
- 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/aimlapi.py +17 -0
- agno/models/anthropic/claude.py +434 -59
- agno/models/aws/bedrock.py +121 -20
- agno/models/aws/claude.py +131 -274
- agno/models/azure/ai_foundry.py +10 -6
- agno/models/azure/openai_chat.py +33 -10
- agno/models/base.py +1162 -561
- agno/models/cerebras/cerebras.py +120 -24
- agno/models/cerebras/cerebras_openai.py +21 -2
- agno/models/cohere/chat.py +65 -6
- agno/models/cometapi/cometapi.py +18 -1
- agno/models/dashscope/dashscope.py +2 -3
- agno/models/deepinfra/deepinfra.py +18 -1
- agno/models/deepseek/deepseek.py +69 -3
- agno/models/fireworks/fireworks.py +18 -1
- agno/models/google/gemini.py +959 -89
- agno/models/google/utils.py +22 -0
- agno/models/groq/groq.py +48 -18
- agno/models/huggingface/huggingface.py +17 -6
- agno/models/ibm/watsonx.py +16 -6
- agno/models/internlm/internlm.py +18 -1
- agno/models/langdb/langdb.py +13 -1
- agno/models/litellm/chat.py +88 -9
- agno/models/litellm/litellm_openai.py +18 -1
- agno/models/message.py +24 -5
- agno/models/meta/llama.py +40 -13
- agno/models/meta/llama_openai.py +22 -21
- agno/models/metrics.py +12 -0
- agno/models/mistral/mistral.py +8 -4
- agno/models/n1n/__init__.py +3 -0
- agno/models/n1n/n1n.py +57 -0
- agno/models/nebius/nebius.py +6 -7
- agno/models/nvidia/nvidia.py +20 -3
- agno/models/ollama/__init__.py +2 -0
- agno/models/ollama/chat.py +17 -6
- agno/models/ollama/responses.py +100 -0
- agno/models/openai/__init__.py +2 -0
- agno/models/openai/chat.py +117 -26
- agno/models/openai/open_responses.py +46 -0
- agno/models/openai/responses.py +110 -32
- agno/models/openrouter/__init__.py +2 -0
- agno/models/openrouter/openrouter.py +67 -2
- agno/models/openrouter/responses.py +146 -0
- agno/models/perplexity/perplexity.py +19 -1
- agno/models/portkey/portkey.py +7 -6
- agno/models/requesty/requesty.py +19 -2
- agno/models/response.py +20 -2
- agno/models/sambanova/sambanova.py +20 -3
- agno/models/siliconflow/siliconflow.py +19 -2
- agno/models/together/together.py +20 -3
- agno/models/vercel/v0.py +20 -3
- agno/models/vertexai/claude.py +124 -4
- agno/models/vllm/vllm.py +19 -14
- agno/models/xai/xai.py +19 -2
- agno/os/app.py +467 -137
- agno/os/auth.py +253 -5
- agno/os/config.py +22 -0
- agno/os/interfaces/a2a/a2a.py +7 -6
- agno/os/interfaces/a2a/router.py +635 -26
- agno/os/interfaces/a2a/utils.py +32 -33
- agno/os/interfaces/agui/agui.py +5 -3
- agno/os/interfaces/agui/router.py +26 -16
- agno/os/interfaces/agui/utils.py +97 -57
- agno/os/interfaces/base.py +7 -7
- agno/os/interfaces/slack/router.py +16 -7
- agno/os/interfaces/slack/slack.py +7 -7
- agno/os/interfaces/whatsapp/router.py +35 -7
- agno/os/interfaces/whatsapp/security.py +3 -1
- agno/os/interfaces/whatsapp/whatsapp.py +11 -8
- agno/os/managers.py +326 -0
- agno/os/mcp.py +652 -79
- agno/os/middleware/__init__.py +4 -0
- agno/os/middleware/jwt.py +718 -115
- agno/os/middleware/trailing_slash.py +27 -0
- agno/os/router.py +105 -1558
- agno/os/routers/agents/__init__.py +3 -0
- agno/os/routers/agents/router.py +655 -0
- agno/os/routers/agents/schema.py +288 -0
- agno/os/routers/components/__init__.py +3 -0
- agno/os/routers/components/components.py +475 -0
- agno/os/routers/database.py +155 -0
- agno/os/routers/evals/evals.py +111 -18
- agno/os/routers/evals/schemas.py +38 -5
- agno/os/routers/evals/utils.py +80 -11
- agno/os/routers/health.py +3 -3
- agno/os/routers/knowledge/knowledge.py +284 -35
- agno/os/routers/knowledge/schemas.py +14 -2
- agno/os/routers/memory/memory.py +274 -11
- agno/os/routers/memory/schemas.py +44 -3
- agno/os/routers/metrics/metrics.py +30 -15
- agno/os/routers/metrics/schemas.py +10 -6
- agno/os/routers/registry/__init__.py +3 -0
- agno/os/routers/registry/registry.py +337 -0
- agno/os/routers/session/session.py +143 -14
- agno/os/routers/teams/__init__.py +3 -0
- agno/os/routers/teams/router.py +550 -0
- agno/os/routers/teams/schema.py +280 -0
- agno/os/routers/traces/__init__.py +3 -0
- agno/os/routers/traces/schemas.py +414 -0
- agno/os/routers/traces/traces.py +549 -0
- agno/os/routers/workflows/__init__.py +3 -0
- agno/os/routers/workflows/router.py +757 -0
- agno/os/routers/workflows/schema.py +139 -0
- agno/os/schema.py +157 -584
- agno/os/scopes.py +469 -0
- agno/os/settings.py +3 -0
- agno/os/utils.py +574 -185
- agno/reasoning/anthropic.py +85 -1
- agno/reasoning/azure_ai_foundry.py +93 -1
- agno/reasoning/deepseek.py +102 -2
- agno/reasoning/default.py +6 -7
- agno/reasoning/gemini.py +87 -3
- agno/reasoning/groq.py +109 -2
- agno/reasoning/helpers.py +6 -7
- agno/reasoning/manager.py +1238 -0
- agno/reasoning/ollama.py +93 -1
- agno/reasoning/openai.py +115 -1
- agno/reasoning/vertexai.py +85 -1
- agno/registry/__init__.py +3 -0
- agno/registry/registry.py +68 -0
- agno/remote/__init__.py +3 -0
- agno/remote/base.py +581 -0
- agno/run/__init__.py +2 -4
- agno/run/agent.py +134 -19
- agno/run/base.py +49 -1
- agno/run/cancel.py +65 -52
- agno/run/cancellation_management/__init__.py +9 -0
- agno/run/cancellation_management/base.py +78 -0
- agno/run/cancellation_management/in_memory_cancellation_manager.py +100 -0
- agno/run/cancellation_management/redis_cancellation_manager.py +236 -0
- agno/run/requirement.py +181 -0
- agno/run/team.py +111 -19
- agno/run/workflow.py +2 -1
- agno/session/agent.py +57 -92
- agno/session/summary.py +1 -1
- agno/session/team.py +62 -115
- agno/session/workflow.py +353 -57
- agno/skills/__init__.py +17 -0
- agno/skills/agent_skills.py +377 -0
- agno/skills/errors.py +32 -0
- agno/skills/loaders/__init__.py +4 -0
- agno/skills/loaders/base.py +27 -0
- agno/skills/loaders/local.py +216 -0
- agno/skills/skill.py +65 -0
- agno/skills/utils.py +107 -0
- agno/skills/validator.py +277 -0
- agno/table.py +10 -0
- agno/team/__init__.py +5 -1
- agno/team/remote.py +447 -0
- agno/team/team.py +3769 -2202
- agno/tools/brandfetch.py +27 -18
- agno/tools/browserbase.py +225 -16
- agno/tools/crawl4ai.py +3 -0
- agno/tools/duckduckgo.py +25 -71
- agno/tools/exa.py +0 -21
- agno/tools/file.py +14 -13
- agno/tools/file_generation.py +12 -6
- agno/tools/firecrawl.py +15 -7
- agno/tools/function.py +94 -113
- agno/tools/google_bigquery.py +11 -2
- agno/tools/google_drive.py +4 -3
- agno/tools/knowledge.py +9 -4
- agno/tools/mcp/mcp.py +301 -18
- agno/tools/mcp/multi_mcp.py +269 -14
- agno/tools/mem0.py +11 -10
- agno/tools/memory.py +47 -46
- agno/tools/mlx_transcribe.py +10 -7
- agno/tools/models/nebius.py +5 -5
- agno/tools/models_labs.py +20 -10
- agno/tools/nano_banana.py +151 -0
- agno/tools/parallel.py +0 -7
- agno/tools/postgres.py +76 -36
- agno/tools/python.py +14 -6
- agno/tools/reasoning.py +30 -23
- agno/tools/redshift.py +406 -0
- agno/tools/shopify.py +1519 -0
- agno/tools/spotify.py +919 -0
- agno/tools/tavily.py +4 -1
- agno/tools/toolkit.py +253 -18
- agno/tools/websearch.py +93 -0
- agno/tools/website.py +1 -1
- agno/tools/wikipedia.py +1 -1
- agno/tools/workflow.py +56 -48
- agno/tools/yfinance.py +12 -11
- agno/tracing/__init__.py +12 -0
- agno/tracing/exporter.py +161 -0
- agno/tracing/schemas.py +276 -0
- agno/tracing/setup.py +112 -0
- agno/utils/agent.py +251 -10
- agno/utils/cryptography.py +22 -0
- agno/utils/dttm.py +33 -0
- agno/utils/events.py +264 -7
- agno/utils/hooks.py +111 -3
- agno/utils/http.py +161 -2
- agno/utils/mcp.py +49 -8
- agno/utils/media.py +22 -1
- agno/utils/models/ai_foundry.py +9 -2
- agno/utils/models/claude.py +20 -5
- agno/utils/models/cohere.py +9 -2
- agno/utils/models/llama.py +9 -2
- agno/utils/models/mistral.py +4 -2
- agno/utils/os.py +0 -0
- agno/utils/print_response/agent.py +99 -16
- agno/utils/print_response/team.py +223 -24
- agno/utils/print_response/workflow.py +0 -2
- agno/utils/prompts.py +8 -6
- agno/utils/remote.py +23 -0
- agno/utils/response.py +1 -13
- agno/utils/string.py +91 -2
- agno/utils/team.py +62 -12
- agno/utils/tokens.py +657 -0
- agno/vectordb/base.py +15 -2
- agno/vectordb/cassandra/cassandra.py +1 -1
- agno/vectordb/chroma/__init__.py +2 -1
- agno/vectordb/chroma/chromadb.py +468 -23
- agno/vectordb/clickhouse/clickhousedb.py +1 -1
- agno/vectordb/couchbase/couchbase.py +6 -2
- agno/vectordb/lancedb/lance_db.py +7 -38
- agno/vectordb/lightrag/lightrag.py +7 -6
- agno/vectordb/milvus/milvus.py +118 -84
- agno/vectordb/mongodb/__init__.py +2 -1
- agno/vectordb/mongodb/mongodb.py +14 -31
- agno/vectordb/pgvector/pgvector.py +120 -66
- agno/vectordb/pineconedb/pineconedb.py +2 -19
- agno/vectordb/qdrant/__init__.py +2 -1
- agno/vectordb/qdrant/qdrant.py +33 -56
- agno/vectordb/redis/__init__.py +2 -1
- agno/vectordb/redis/redisdb.py +19 -31
- agno/vectordb/singlestore/singlestore.py +17 -9
- agno/vectordb/surrealdb/surrealdb.py +2 -38
- agno/vectordb/weaviate/__init__.py +2 -1
- agno/vectordb/weaviate/weaviate.py +7 -3
- agno/workflow/__init__.py +5 -1
- agno/workflow/agent.py +2 -2
- agno/workflow/condition.py +12 -10
- agno/workflow/loop.py +28 -9
- agno/workflow/parallel.py +21 -13
- agno/workflow/remote.py +362 -0
- agno/workflow/router.py +12 -9
- agno/workflow/step.py +261 -36
- agno/workflow/steps.py +12 -8
- agno/workflow/types.py +40 -77
- agno/workflow/workflow.py +939 -213
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/METADATA +134 -181
- agno-2.4.3.dist-info/RECORD +677 -0
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/WHEEL +1 -1
- agno/tools/googlesearch.py +0 -98
- agno/tools/memori.py +0 -339
- agno-2.2.13.dist-info/RECORD +0 -575
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/licenses/LICENSE +0 -0
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/top_level.txt +0 -0
agno/utils/events.py
CHANGED
|
@@ -5,8 +5,12 @@ from agno.models.message import Citations
|
|
|
5
5
|
from agno.models.response import ToolExecution
|
|
6
6
|
from agno.reasoning.step import ReasoningStep
|
|
7
7
|
from agno.run.agent import (
|
|
8
|
+
CompressionCompletedEvent,
|
|
9
|
+
CompressionStartedEvent,
|
|
8
10
|
MemoryUpdateCompletedEvent,
|
|
9
11
|
MemoryUpdateStartedEvent,
|
|
12
|
+
ModelRequestCompletedEvent,
|
|
13
|
+
ModelRequestStartedEvent,
|
|
10
14
|
OutputModelResponseCompletedEvent,
|
|
11
15
|
OutputModelResponseStartedEvent,
|
|
12
16
|
ParserModelResponseCompletedEvent,
|
|
@@ -16,6 +20,7 @@ from agno.run.agent import (
|
|
|
16
20
|
PreHookCompletedEvent,
|
|
17
21
|
PreHookStartedEvent,
|
|
18
22
|
ReasoningCompletedEvent,
|
|
23
|
+
ReasoningContentDeltaEvent,
|
|
19
24
|
ReasoningStartedEvent,
|
|
20
25
|
ReasoningStepEvent,
|
|
21
26
|
RunCancelledEvent,
|
|
@@ -33,10 +38,16 @@ from agno.run.agent import (
|
|
|
33
38
|
SessionSummaryCompletedEvent,
|
|
34
39
|
SessionSummaryStartedEvent,
|
|
35
40
|
ToolCallCompletedEvent,
|
|
41
|
+
ToolCallErrorEvent,
|
|
36
42
|
ToolCallStartedEvent,
|
|
37
43
|
)
|
|
44
|
+
from agno.run.requirement import RunRequirement
|
|
45
|
+
from agno.run.team import CompressionCompletedEvent as TeamCompressionCompletedEvent
|
|
46
|
+
from agno.run.team import CompressionStartedEvent as TeamCompressionStartedEvent
|
|
38
47
|
from agno.run.team import MemoryUpdateCompletedEvent as TeamMemoryUpdateCompletedEvent
|
|
39
48
|
from agno.run.team import MemoryUpdateStartedEvent as TeamMemoryUpdateStartedEvent
|
|
49
|
+
from agno.run.team import ModelRequestCompletedEvent as TeamModelRequestCompletedEvent
|
|
50
|
+
from agno.run.team import ModelRequestStartedEvent as TeamModelRequestStartedEvent
|
|
40
51
|
from agno.run.team import OutputModelResponseCompletedEvent as TeamOutputModelResponseCompletedEvent
|
|
41
52
|
from agno.run.team import OutputModelResponseStartedEvent as TeamOutputModelResponseStartedEvent
|
|
42
53
|
from agno.run.team import ParserModelResponseCompletedEvent as TeamParserModelResponseCompletedEvent
|
|
@@ -46,6 +57,7 @@ from agno.run.team import PostHookStartedEvent as TeamPostHookStartedEvent
|
|
|
46
57
|
from agno.run.team import PreHookCompletedEvent as TeamPreHookCompletedEvent
|
|
47
58
|
from agno.run.team import PreHookStartedEvent as TeamPreHookStartedEvent
|
|
48
59
|
from agno.run.team import ReasoningCompletedEvent as TeamReasoningCompletedEvent
|
|
60
|
+
from agno.run.team import ReasoningContentDeltaEvent as TeamReasoningContentDeltaEvent
|
|
49
61
|
from agno.run.team import ReasoningStartedEvent as TeamReasoningStartedEvent
|
|
50
62
|
from agno.run.team import ReasoningStepEvent as TeamReasoningStepEvent
|
|
51
63
|
from agno.run.team import RunCancelledEvent as TeamRunCancelledEvent
|
|
@@ -58,6 +70,7 @@ from agno.run.team import SessionSummaryCompletedEvent as TeamSessionSummaryComp
|
|
|
58
70
|
from agno.run.team import SessionSummaryStartedEvent as TeamSessionSummaryStartedEvent
|
|
59
71
|
from agno.run.team import TeamRunEvent, TeamRunInput, TeamRunOutput, TeamRunOutputEvent
|
|
60
72
|
from agno.run.team import ToolCallCompletedEvent as TeamToolCallCompletedEvent
|
|
73
|
+
from agno.run.team import ToolCallErrorEvent as TeamToolCallErrorEvent
|
|
61
74
|
from agno.run.team import ToolCallStartedEvent as TeamToolCallStartedEvent
|
|
62
75
|
from agno.session.summary import SessionSummary
|
|
63
76
|
|
|
@@ -136,7 +149,9 @@ def create_run_completed_event(from_run_response: RunOutput) -> RunCompletedEven
|
|
|
136
149
|
|
|
137
150
|
|
|
138
151
|
def create_run_paused_event(
|
|
139
|
-
from_run_response: RunOutput,
|
|
152
|
+
from_run_response: RunOutput,
|
|
153
|
+
tools: Optional[List[ToolExecution]] = None,
|
|
154
|
+
requirements: Optional[List[RunRequirement]] = None,
|
|
140
155
|
) -> RunPausedEvent:
|
|
141
156
|
return RunPausedEvent(
|
|
142
157
|
session_id=from_run_response.session_id,
|
|
@@ -144,6 +159,7 @@ def create_run_paused_event(
|
|
|
144
159
|
agent_name=from_run_response.agent_name, # type: ignore
|
|
145
160
|
run_id=from_run_response.run_id,
|
|
146
161
|
tools=tools,
|
|
162
|
+
requirements=requirements,
|
|
147
163
|
content=from_run_response.content,
|
|
148
164
|
)
|
|
149
165
|
|
|
@@ -157,23 +173,41 @@ def create_run_continued_event(from_run_response: RunOutput) -> RunContinuedEven
|
|
|
157
173
|
)
|
|
158
174
|
|
|
159
175
|
|
|
160
|
-
def create_team_run_error_event(
|
|
176
|
+
def create_team_run_error_event(
|
|
177
|
+
from_run_response: TeamRunOutput,
|
|
178
|
+
error: str,
|
|
179
|
+
error_type: Optional[str] = None,
|
|
180
|
+
error_id: Optional[str] = None,
|
|
181
|
+
additional_data: Optional[Dict[str, Any]] = None,
|
|
182
|
+
) -> TeamRunErrorEvent:
|
|
161
183
|
return TeamRunErrorEvent(
|
|
162
184
|
session_id=from_run_response.session_id,
|
|
163
185
|
team_id=from_run_response.team_id, # type: ignore
|
|
164
186
|
team_name=from_run_response.team_name, # type: ignore
|
|
165
187
|
run_id=from_run_response.run_id,
|
|
166
188
|
content=error,
|
|
189
|
+
error_type=error_type,
|
|
190
|
+
error_id=error_id,
|
|
191
|
+
additional_data=additional_data,
|
|
167
192
|
)
|
|
168
193
|
|
|
169
194
|
|
|
170
|
-
def create_run_error_event(
|
|
195
|
+
def create_run_error_event(
|
|
196
|
+
from_run_response: RunOutput,
|
|
197
|
+
error: str,
|
|
198
|
+
error_type: Optional[str] = None,
|
|
199
|
+
error_id: Optional[str] = None,
|
|
200
|
+
additional_data: Optional[Dict[str, Any]] = None,
|
|
201
|
+
) -> RunErrorEvent:
|
|
171
202
|
return RunErrorEvent(
|
|
172
203
|
session_id=from_run_response.session_id,
|
|
173
204
|
agent_id=from_run_response.agent_id, # type: ignore
|
|
174
205
|
agent_name=from_run_response.agent_name, # type: ignore
|
|
175
206
|
run_id=from_run_response.run_id,
|
|
176
207
|
content=error,
|
|
208
|
+
error_type=error_type,
|
|
209
|
+
error_id=error_id,
|
|
210
|
+
additional_data=additional_data,
|
|
177
211
|
)
|
|
178
212
|
|
|
179
213
|
|
|
@@ -323,21 +357,27 @@ def create_team_memory_update_started_event(from_run_response: TeamRunOutput) ->
|
|
|
323
357
|
)
|
|
324
358
|
|
|
325
359
|
|
|
326
|
-
def create_memory_update_completed_event(
|
|
360
|
+
def create_memory_update_completed_event(
|
|
361
|
+
from_run_response: RunOutput, memories: Optional[List[Any]] = None
|
|
362
|
+
) -> MemoryUpdateCompletedEvent:
|
|
327
363
|
return MemoryUpdateCompletedEvent(
|
|
328
364
|
session_id=from_run_response.session_id,
|
|
329
365
|
agent_id=from_run_response.agent_id, # type: ignore
|
|
330
366
|
agent_name=from_run_response.agent_name, # type: ignore
|
|
331
367
|
run_id=from_run_response.run_id,
|
|
368
|
+
memories=memories,
|
|
332
369
|
)
|
|
333
370
|
|
|
334
371
|
|
|
335
|
-
def create_team_memory_update_completed_event(
|
|
372
|
+
def create_team_memory_update_completed_event(
|
|
373
|
+
from_run_response: TeamRunOutput, memories: Optional[List[Any]] = None
|
|
374
|
+
) -> TeamMemoryUpdateCompletedEvent:
|
|
336
375
|
return TeamMemoryUpdateCompletedEvent(
|
|
337
376
|
session_id=from_run_response.session_id,
|
|
338
377
|
team_id=from_run_response.team_id, # type: ignore
|
|
339
378
|
team_name=from_run_response.team_name, # type: ignore
|
|
340
379
|
run_id=from_run_response.run_id,
|
|
380
|
+
memories=memories,
|
|
341
381
|
)
|
|
342
382
|
|
|
343
383
|
|
|
@@ -417,6 +457,19 @@ def create_reasoning_step_event(
|
|
|
417
457
|
)
|
|
418
458
|
|
|
419
459
|
|
|
460
|
+
def create_reasoning_content_delta_event(
|
|
461
|
+
from_run_response: RunOutput, reasoning_content: str
|
|
462
|
+
) -> ReasoningContentDeltaEvent:
|
|
463
|
+
"""Create an event for streaming reasoning content chunks."""
|
|
464
|
+
return ReasoningContentDeltaEvent(
|
|
465
|
+
session_id=from_run_response.session_id,
|
|
466
|
+
agent_id=from_run_response.agent_id, # type: ignore
|
|
467
|
+
agent_name=from_run_response.agent_name, # type: ignore
|
|
468
|
+
run_id=from_run_response.run_id,
|
|
469
|
+
reasoning_content=reasoning_content,
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
|
|
420
473
|
def create_team_reasoning_step_event(
|
|
421
474
|
from_run_response: TeamRunOutput, reasoning_step: ReasoningStep, reasoning_content: str
|
|
422
475
|
) -> TeamReasoningStepEvent:
|
|
@@ -431,6 +484,19 @@ def create_team_reasoning_step_event(
|
|
|
431
484
|
)
|
|
432
485
|
|
|
433
486
|
|
|
487
|
+
def create_team_reasoning_content_delta_event(
|
|
488
|
+
from_run_response: TeamRunOutput, reasoning_content: str
|
|
489
|
+
) -> TeamReasoningContentDeltaEvent:
|
|
490
|
+
"""Create an event for streaming reasoning content chunks for Team."""
|
|
491
|
+
return TeamReasoningContentDeltaEvent(
|
|
492
|
+
session_id=from_run_response.session_id,
|
|
493
|
+
team_id=from_run_response.team_id, # type: ignore
|
|
494
|
+
team_name=from_run_response.team_name, # type: ignore
|
|
495
|
+
run_id=from_run_response.run_id,
|
|
496
|
+
reasoning_content=reasoning_content,
|
|
497
|
+
)
|
|
498
|
+
|
|
499
|
+
|
|
434
500
|
def create_reasoning_completed_event(
|
|
435
501
|
from_run_response: RunOutput, content: Optional[Any] = None, content_type: Optional[str] = None
|
|
436
502
|
) -> ReasoningCompletedEvent:
|
|
@@ -511,6 +577,32 @@ def create_team_tool_call_completed_event(
|
|
|
511
577
|
)
|
|
512
578
|
|
|
513
579
|
|
|
580
|
+
def create_tool_call_error_event(
|
|
581
|
+
from_run_response: RunOutput, tool: ToolExecution, error: Optional[str] = None
|
|
582
|
+
) -> ToolCallErrorEvent:
|
|
583
|
+
return ToolCallErrorEvent(
|
|
584
|
+
session_id=from_run_response.session_id,
|
|
585
|
+
agent_id=from_run_response.agent_id, # type: ignore
|
|
586
|
+
agent_name=from_run_response.agent_name, # type: ignore
|
|
587
|
+
run_id=from_run_response.run_id,
|
|
588
|
+
tool=tool,
|
|
589
|
+
error=error,
|
|
590
|
+
)
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
def create_team_tool_call_error_event(
|
|
594
|
+
from_run_response: TeamRunOutput, tool: ToolExecution, error: Optional[str] = None
|
|
595
|
+
) -> TeamToolCallErrorEvent:
|
|
596
|
+
return TeamToolCallErrorEvent(
|
|
597
|
+
session_id=from_run_response.session_id,
|
|
598
|
+
team_id=from_run_response.team_id, # type: ignore
|
|
599
|
+
team_name=from_run_response.team_name, # type: ignore
|
|
600
|
+
run_id=from_run_response.run_id,
|
|
601
|
+
tool=tool,
|
|
602
|
+
error=error,
|
|
603
|
+
)
|
|
604
|
+
|
|
605
|
+
|
|
514
606
|
def create_run_output_content_event(
|
|
515
607
|
from_run_response: RunOutput,
|
|
516
608
|
content: Optional[Any] = None,
|
|
@@ -681,6 +773,150 @@ def create_team_output_model_response_completed_event(
|
|
|
681
773
|
)
|
|
682
774
|
|
|
683
775
|
|
|
776
|
+
def create_model_request_started_event(
|
|
777
|
+
from_run_response: RunOutput,
|
|
778
|
+
model: Optional[str] = None,
|
|
779
|
+
model_provider: Optional[str] = None,
|
|
780
|
+
) -> ModelRequestStartedEvent:
|
|
781
|
+
return ModelRequestStartedEvent(
|
|
782
|
+
session_id=from_run_response.session_id,
|
|
783
|
+
agent_id=from_run_response.agent_id, # type: ignore
|
|
784
|
+
agent_name=from_run_response.agent_name, # type: ignore
|
|
785
|
+
run_id=from_run_response.run_id,
|
|
786
|
+
model=model,
|
|
787
|
+
model_provider=model_provider,
|
|
788
|
+
)
|
|
789
|
+
|
|
790
|
+
|
|
791
|
+
def create_model_request_completed_event(
|
|
792
|
+
from_run_response: RunOutput,
|
|
793
|
+
model: Optional[str] = None,
|
|
794
|
+
model_provider: Optional[str] = None,
|
|
795
|
+
input_tokens: Optional[int] = None,
|
|
796
|
+
output_tokens: Optional[int] = None,
|
|
797
|
+
total_tokens: Optional[int] = None,
|
|
798
|
+
time_to_first_token: Optional[float] = None,
|
|
799
|
+
reasoning_tokens: Optional[int] = None,
|
|
800
|
+
cache_read_tokens: Optional[int] = None,
|
|
801
|
+
cache_write_tokens: Optional[int] = None,
|
|
802
|
+
) -> ModelRequestCompletedEvent:
|
|
803
|
+
return ModelRequestCompletedEvent(
|
|
804
|
+
session_id=from_run_response.session_id,
|
|
805
|
+
agent_id=from_run_response.agent_id, # type: ignore
|
|
806
|
+
agent_name=from_run_response.agent_name, # type: ignore
|
|
807
|
+
run_id=from_run_response.run_id,
|
|
808
|
+
model=model,
|
|
809
|
+
model_provider=model_provider,
|
|
810
|
+
input_tokens=input_tokens,
|
|
811
|
+
output_tokens=output_tokens,
|
|
812
|
+
total_tokens=total_tokens,
|
|
813
|
+
time_to_first_token=time_to_first_token,
|
|
814
|
+
reasoning_tokens=reasoning_tokens,
|
|
815
|
+
cache_read_tokens=cache_read_tokens,
|
|
816
|
+
cache_write_tokens=cache_write_tokens,
|
|
817
|
+
)
|
|
818
|
+
|
|
819
|
+
|
|
820
|
+
def create_team_model_request_started_event(
|
|
821
|
+
from_run_response: TeamRunOutput,
|
|
822
|
+
model: Optional[str] = None,
|
|
823
|
+
model_provider: Optional[str] = None,
|
|
824
|
+
) -> TeamModelRequestStartedEvent:
|
|
825
|
+
return TeamModelRequestStartedEvent(
|
|
826
|
+
session_id=from_run_response.session_id,
|
|
827
|
+
team_id=from_run_response.team_id, # type: ignore
|
|
828
|
+
team_name=from_run_response.team_name, # type: ignore
|
|
829
|
+
run_id=from_run_response.run_id,
|
|
830
|
+
model=model,
|
|
831
|
+
model_provider=model_provider,
|
|
832
|
+
)
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
def create_team_model_request_completed_event(
|
|
836
|
+
from_run_response: TeamRunOutput,
|
|
837
|
+
model: Optional[str] = None,
|
|
838
|
+
model_provider: Optional[str] = None,
|
|
839
|
+
input_tokens: Optional[int] = None,
|
|
840
|
+
output_tokens: Optional[int] = None,
|
|
841
|
+
total_tokens: Optional[int] = None,
|
|
842
|
+
time_to_first_token: Optional[float] = None,
|
|
843
|
+
reasoning_tokens: Optional[int] = None,
|
|
844
|
+
cache_read_tokens: Optional[int] = None,
|
|
845
|
+
cache_write_tokens: Optional[int] = None,
|
|
846
|
+
) -> TeamModelRequestCompletedEvent:
|
|
847
|
+
return TeamModelRequestCompletedEvent(
|
|
848
|
+
session_id=from_run_response.session_id,
|
|
849
|
+
team_id=from_run_response.team_id, # type: ignore
|
|
850
|
+
team_name=from_run_response.team_name, # type: ignore
|
|
851
|
+
run_id=from_run_response.run_id,
|
|
852
|
+
model=model,
|
|
853
|
+
model_provider=model_provider,
|
|
854
|
+
input_tokens=input_tokens,
|
|
855
|
+
output_tokens=output_tokens,
|
|
856
|
+
total_tokens=total_tokens,
|
|
857
|
+
time_to_first_token=time_to_first_token,
|
|
858
|
+
reasoning_tokens=reasoning_tokens,
|
|
859
|
+
cache_read_tokens=cache_read_tokens,
|
|
860
|
+
cache_write_tokens=cache_write_tokens,
|
|
861
|
+
)
|
|
862
|
+
|
|
863
|
+
|
|
864
|
+
def create_compression_started_event(
|
|
865
|
+
from_run_response: RunOutput,
|
|
866
|
+
) -> CompressionStartedEvent:
|
|
867
|
+
return CompressionStartedEvent(
|
|
868
|
+
session_id=from_run_response.session_id,
|
|
869
|
+
agent_id=from_run_response.agent_id, # type: ignore
|
|
870
|
+
agent_name=from_run_response.agent_name, # type: ignore
|
|
871
|
+
run_id=from_run_response.run_id,
|
|
872
|
+
)
|
|
873
|
+
|
|
874
|
+
|
|
875
|
+
def create_compression_completed_event(
|
|
876
|
+
from_run_response: RunOutput,
|
|
877
|
+
tool_results_compressed: Optional[int] = None,
|
|
878
|
+
original_size: Optional[int] = None,
|
|
879
|
+
compressed_size: Optional[int] = None,
|
|
880
|
+
) -> CompressionCompletedEvent:
|
|
881
|
+
return CompressionCompletedEvent(
|
|
882
|
+
session_id=from_run_response.session_id,
|
|
883
|
+
agent_id=from_run_response.agent_id, # type: ignore
|
|
884
|
+
agent_name=from_run_response.agent_name, # type: ignore
|
|
885
|
+
run_id=from_run_response.run_id,
|
|
886
|
+
tool_results_compressed=tool_results_compressed,
|
|
887
|
+
original_size=original_size,
|
|
888
|
+
compressed_size=compressed_size,
|
|
889
|
+
)
|
|
890
|
+
|
|
891
|
+
|
|
892
|
+
def create_team_compression_started_event(
|
|
893
|
+
from_run_response: TeamRunOutput,
|
|
894
|
+
) -> TeamCompressionStartedEvent:
|
|
895
|
+
return TeamCompressionStartedEvent(
|
|
896
|
+
session_id=from_run_response.session_id,
|
|
897
|
+
team_id=from_run_response.team_id, # type: ignore
|
|
898
|
+
team_name=from_run_response.team_name, # type: ignore
|
|
899
|
+
run_id=from_run_response.run_id,
|
|
900
|
+
)
|
|
901
|
+
|
|
902
|
+
|
|
903
|
+
def create_team_compression_completed_event(
|
|
904
|
+
from_run_response: TeamRunOutput,
|
|
905
|
+
tool_results_compressed: Optional[int] = None,
|
|
906
|
+
original_size: Optional[int] = None,
|
|
907
|
+
compressed_size: Optional[int] = None,
|
|
908
|
+
) -> TeamCompressionCompletedEvent:
|
|
909
|
+
return TeamCompressionCompletedEvent(
|
|
910
|
+
session_id=from_run_response.session_id,
|
|
911
|
+
team_id=from_run_response.team_id, # type: ignore
|
|
912
|
+
team_name=from_run_response.team_name, # type: ignore
|
|
913
|
+
run_id=from_run_response.run_id,
|
|
914
|
+
tool_results_compressed=tool_results_compressed,
|
|
915
|
+
original_size=original_size,
|
|
916
|
+
compressed_size=compressed_size,
|
|
917
|
+
)
|
|
918
|
+
|
|
919
|
+
|
|
684
920
|
def handle_event(
|
|
685
921
|
event: Union[RunOutputEvent, TeamRunOutputEvent],
|
|
686
922
|
run_response: Union[RunOutput, TeamRunOutput],
|
|
@@ -688,9 +924,30 @@ def handle_event(
|
|
|
688
924
|
store_events: bool = False,
|
|
689
925
|
) -> Union[RunOutputEvent, TeamRunOutputEvent]:
|
|
690
926
|
# We only store events that are not run_response_content events
|
|
691
|
-
|
|
692
|
-
if store_events and event.event not in
|
|
927
|
+
_events_to_skip: List[str] = [event.value for event in events_to_skip] if events_to_skip else []
|
|
928
|
+
if store_events and event.event not in _events_to_skip:
|
|
693
929
|
if run_response.events is None:
|
|
694
930
|
run_response.events = []
|
|
695
931
|
run_response.events.append(event) # type: ignore
|
|
696
932
|
return event
|
|
933
|
+
|
|
934
|
+
|
|
935
|
+
def add_error_event(
|
|
936
|
+
error: RunErrorEvent,
|
|
937
|
+
events: Optional[List[RunOutputEvent]],
|
|
938
|
+
):
|
|
939
|
+
if events is None:
|
|
940
|
+
events = []
|
|
941
|
+
events.append(error)
|
|
942
|
+
|
|
943
|
+
return events
|
|
944
|
+
|
|
945
|
+
|
|
946
|
+
def add_team_error_event(
|
|
947
|
+
error: TeamRunErrorEvent,
|
|
948
|
+
events: Optional[List[Union[RunOutputEvent, TeamRunOutputEvent]]],
|
|
949
|
+
):
|
|
950
|
+
if events is None:
|
|
951
|
+
events = []
|
|
952
|
+
events.append(error)
|
|
953
|
+
return events
|
agno/utils/hooks.py
CHANGED
|
@@ -1,14 +1,112 @@
|
|
|
1
|
+
from copy import deepcopy
|
|
1
2
|
from typing import Any, Callable, Dict, List, Optional, Union
|
|
2
3
|
|
|
4
|
+
from agno.eval.base import BaseEval
|
|
3
5
|
from agno.guardrails.base import BaseGuardrail
|
|
6
|
+
from agno.hooks.decorator import HOOK_RUN_IN_BACKGROUND_ATTR
|
|
4
7
|
from agno.utils.log import log_warning
|
|
5
8
|
|
|
9
|
+
# Keys that should be deep copied for background hooks to prevent race conditions
|
|
10
|
+
BACKGROUND_HOOK_COPY_KEYS = frozenset(
|
|
11
|
+
{"run_input", "run_context", "run_output", "session_state", "dependencies", "metadata"}
|
|
12
|
+
)
|
|
6
13
|
|
|
7
|
-
|
|
8
|
-
|
|
14
|
+
|
|
15
|
+
def copy_args_for_background(args: Dict[str, Any]) -> Dict[str, Any]:
|
|
16
|
+
"""
|
|
17
|
+
Create a copy of hook arguments for background execution.
|
|
18
|
+
|
|
19
|
+
This deep copies run_input, run_context, run_output, session_state, dependencies,
|
|
20
|
+
and metadata to prevent race conditions when hooks run in the background.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
args: The original arguments dictionary
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
A new dictionary with copied values for sensitive keys
|
|
27
|
+
"""
|
|
28
|
+
copied_args = {}
|
|
29
|
+
for key, value in args.items():
|
|
30
|
+
if key in BACKGROUND_HOOK_COPY_KEYS and value is not None:
|
|
31
|
+
try:
|
|
32
|
+
copied_args[key] = deepcopy(value)
|
|
33
|
+
except Exception:
|
|
34
|
+
# If deepcopy fails (e.g., for non-copyable objects), use the original
|
|
35
|
+
log_warning(f"Could not deepcopy {key} for background hook, using original reference")
|
|
36
|
+
copied_args[key] = value
|
|
37
|
+
else:
|
|
38
|
+
copied_args[key] = value
|
|
39
|
+
return copied_args
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def should_run_hook_in_background(hook: Callable[..., Any]) -> bool:
|
|
43
|
+
"""
|
|
44
|
+
Check if a hook function should run in background.
|
|
45
|
+
|
|
46
|
+
This checks for the _agno_run_in_background attribute set by the @hook decorator.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
hook: The hook function to check
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
True if the hook is decorated with @hook(run_in_background=True)
|
|
53
|
+
"""
|
|
54
|
+
return getattr(hook, HOOK_RUN_IN_BACKGROUND_ATTR, False)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def normalize_pre_hooks(
|
|
58
|
+
hooks: Optional[List[Union[Callable[..., Any], BaseGuardrail, BaseEval]]],
|
|
59
|
+
async_mode: bool = False,
|
|
60
|
+
) -> Optional[List[Callable[..., Any]]]:
|
|
61
|
+
"""Normalize pre-hooks to a list format.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
hooks: List of hook functions, guardrails, or eval instances
|
|
65
|
+
async_mode: Whether to use async versions of methods
|
|
66
|
+
"""
|
|
67
|
+
result_hooks: List[Callable[..., Any]] = []
|
|
68
|
+
|
|
69
|
+
if hooks is not None:
|
|
70
|
+
for hook in hooks:
|
|
71
|
+
if isinstance(hook, BaseGuardrail):
|
|
72
|
+
if async_mode:
|
|
73
|
+
result_hooks.append(hook.async_check)
|
|
74
|
+
else:
|
|
75
|
+
result_hooks.append(hook.check)
|
|
76
|
+
elif isinstance(hook, BaseEval):
|
|
77
|
+
# Extract pre_check method
|
|
78
|
+
method = hook.async_pre_check if async_mode else hook.pre_check
|
|
79
|
+
|
|
80
|
+
from functools import partial
|
|
81
|
+
|
|
82
|
+
wrapped = partial(method)
|
|
83
|
+
wrapped.__name__ = method.__name__ # type: ignore
|
|
84
|
+
setattr(wrapped, HOOK_RUN_IN_BACKGROUND_ATTR, getattr(hook, "run_in_background", False))
|
|
85
|
+
result_hooks.append(wrapped)
|
|
86
|
+
else:
|
|
87
|
+
# Check if the hook is async and used within sync methods
|
|
88
|
+
if not async_mode:
|
|
89
|
+
import asyncio
|
|
90
|
+
|
|
91
|
+
if asyncio.iscoroutinefunction(hook):
|
|
92
|
+
raise ValueError(
|
|
93
|
+
f"Cannot use {hook.__name__} (an async hook) with `run()`. Use `arun()` instead."
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
result_hooks.append(hook)
|
|
97
|
+
return result_hooks if result_hooks else None
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def normalize_post_hooks(
|
|
101
|
+
hooks: Optional[List[Union[Callable[..., Any], BaseGuardrail, BaseEval]]],
|
|
9
102
|
async_mode: bool = False,
|
|
10
103
|
) -> Optional[List[Callable[..., Any]]]:
|
|
11
|
-
"""Normalize hooks to a list format
|
|
104
|
+
"""Normalize post-hooks to a list format.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
hooks: List of hook functions, guardrails, or eval instances
|
|
108
|
+
async_mode: Whether to use async versions of methods
|
|
109
|
+
"""
|
|
12
110
|
result_hooks: List[Callable[..., Any]] = []
|
|
13
111
|
|
|
14
112
|
if hooks is not None:
|
|
@@ -18,6 +116,16 @@ def normalize_hooks(
|
|
|
18
116
|
result_hooks.append(hook.async_check)
|
|
19
117
|
else:
|
|
20
118
|
result_hooks.append(hook.check)
|
|
119
|
+
elif isinstance(hook, BaseEval):
|
|
120
|
+
# Extract post_check method
|
|
121
|
+
method = hook.async_post_check if async_mode else hook.post_check # type: ignore[assignment]
|
|
122
|
+
|
|
123
|
+
from functools import partial
|
|
124
|
+
|
|
125
|
+
wrapped = partial(method)
|
|
126
|
+
wrapped.__name__ = method.__name__ # type: ignore
|
|
127
|
+
setattr(wrapped, HOOK_RUN_IN_BACKGROUND_ATTR, getattr(hook, "run_in_background", False))
|
|
128
|
+
result_hooks.append(wrapped)
|
|
21
129
|
else:
|
|
22
130
|
# Check if the hook is async and used within sync methods
|
|
23
131
|
if not async_mode:
|