fix(skill-review): after_agent must be sync, not async
This commit is contained in:
1 parent
d713f0209d
commit
23a18ec318
2 files changed
+7
-11
No files matched your search
+1
-1
@@ -39,7 +39,7 @@ class SkillReviewMiddleware(AgentMiddleware[SkillReviewMiddlewareState]):
|
|||||||
state_schema = SkillReviewMiddlewareState
|
state_schema = SkillReviewMiddlewareState
|
||||||
|
|
||||||
@override
|
@override
|
||||||
async def after_agent(self, state: Any, runtime: Runtime) -> None:
|
def after_agent(self, state: Any, runtime: Runtime) -> None:
|
||||||
"""Fire background review; never raises — failures are logged only."""
|
"""Fire background review; never raises — failures are logged only."""
|
||||||
try:
|
try:
|
||||||
app_config = get_app_config()
|
app_config = get_app_config()
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
"""Tests for SkillReviewMiddleware."""
|
"""Tests for SkillReviewMiddleware."""
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
import pytest
|
|
||||||
from langchain_core.messages import AIMessage, HumanMessage
|
from langchain_core.messages import AIMessage, HumanMessage
|
||||||
|
|
||||||
from deerflow.agents.middlewares.skill_review_middleware import SkillReviewMiddleware
|
from deerflow.agents.middlewares.skill_review_middleware import SkillReviewMiddleware
|
||||||
@@ -19,8 +18,7 @@ def _make_runtime(thread_id="thread-abc"):
|
|||||||
return runtime
|
return runtime
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
def test_after_agent_calls_maybe_start_review():
|
||||||
async def test_after_agent_calls_maybe_start_review():
|
|
||||||
"""When enabled and tool calls exist, maybe_start_review is called with correct thread_id."""
|
"""When enabled and tool calls exist, maybe_start_review is called with correct thread_id."""
|
||||||
middleware = SkillReviewMiddleware()
|
middleware = SkillReviewMiddleware()
|
||||||
|
|
||||||
@@ -35,7 +33,7 @@ async def test_after_agent_calls_maybe_start_review():
|
|||||||
app_cfg = MagicMock()
|
app_cfg = MagicMock()
|
||||||
with patch("deerflow.agents.middlewares.skill_review_middleware.get_app_config", return_value=app_cfg):
|
with patch("deerflow.agents.middlewares.skill_review_middleware.get_app_config", return_value=app_cfg):
|
||||||
with patch("deerflow.agents.middlewares.skill_review_middleware.maybe_start_review") as mock_review:
|
with patch("deerflow.agents.middlewares.skill_review_middleware.maybe_start_review") as mock_review:
|
||||||
await middleware.after_agent(state, runtime)
|
middleware.after_agent(state, runtime)
|
||||||
|
|
||||||
mock_review.assert_called_once()
|
mock_review.assert_called_once()
|
||||||
call_args = mock_review.call_args
|
call_args = mock_review.call_args
|
||||||
@@ -43,8 +41,7 @@ async def test_after_agent_calls_maybe_start_review():
|
|||||||
assert call_args[0][2] is app_cfg # app_config
|
assert call_args[0][2] is app_cfg # app_config
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
def test_after_agent_no_thread_id_skips_review():
|
||||||
async def test_after_agent_no_thread_id_skips_review():
|
|
||||||
"""When thread_id is missing, maybe_start_review is NOT called."""
|
"""When thread_id is missing, maybe_start_review is NOT called."""
|
||||||
middleware = SkillReviewMiddleware()
|
middleware = SkillReviewMiddleware()
|
||||||
state = _make_state([HumanMessage(content="hi")])
|
state = _make_state([HumanMessage(content="hi")])
|
||||||
@@ -53,13 +50,12 @@ async def test_after_agent_no_thread_id_skips_review():
|
|||||||
app_cfg = MagicMock()
|
app_cfg = MagicMock()
|
||||||
with patch("deerflow.agents.middlewares.skill_review_middleware.get_app_config", return_value=app_cfg):
|
with patch("deerflow.agents.middlewares.skill_review_middleware.get_app_config", return_value=app_cfg):
|
||||||
with patch("deerflow.agents.middlewares.skill_review_middleware.maybe_start_review") as mock_review:
|
with patch("deerflow.agents.middlewares.skill_review_middleware.maybe_start_review") as mock_review:
|
||||||
await middleware.after_agent(state, runtime)
|
middleware.after_agent(state, runtime)
|
||||||
|
|
||||||
mock_review.assert_not_called()
|
mock_review.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
def test_after_agent_exception_is_swallowed():
|
||||||
async def test_after_agent_exception_is_swallowed():
|
|
||||||
"""Exceptions in after_agent must not propagate."""
|
"""Exceptions in after_agent must not propagate."""
|
||||||
middleware = SkillReviewMiddleware()
|
middleware = SkillReviewMiddleware()
|
||||||
state = _make_state([HumanMessage(content="hi")])
|
state = _make_state([HumanMessage(content="hi")])
|
||||||
@@ -67,7 +63,7 @@ async def test_after_agent_exception_is_swallowed():
|
|||||||
|
|
||||||
with patch("deerflow.agents.middlewares.skill_review_middleware.get_app_config", side_effect=RuntimeError("boom")):
|
with patch("deerflow.agents.middlewares.skill_review_middleware.get_app_config", side_effect=RuntimeError("boom")):
|
||||||
# Must not raise
|
# Must not raise
|
||||||
await middleware.after_agent(state, runtime)
|
middleware.after_agent(state, runtime)
|
||||||
|
|
||||||
|
|
||||||
def test_skill_review_middleware_in_chain_when_enabled():
|
def test_skill_review_middleware_in_chain_when_enabled():
|
||||||
|
|||||||
Reference in new issue
Block a user