mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-05-21 07:26:50 +00:00
fix: read lead agent options from context (#2515)
* fix: read lead agent options from context * fix: validate runtime context config
This commit is contained in:
@@ -145,6 +145,21 @@ def test_build_run_config_explicit_agent_name_not_overwritten():
|
||||
assert config["configurable"]["agent_name"] == "explicit-agent"
|
||||
|
||||
|
||||
def test_build_run_config_context_custom_agent_injects_agent_name():
|
||||
"""Custom assistant_id must be forwarded as context['agent_name'] in context mode."""
|
||||
from app.gateway.services import build_run_config
|
||||
|
||||
config = build_run_config(
|
||||
"thread-1",
|
||||
{"context": {"model_name": "deepseek-v3"}},
|
||||
None,
|
||||
assistant_id="finalis",
|
||||
)
|
||||
|
||||
assert config["context"]["agent_name"] == "finalis"
|
||||
assert "configurable" not in config
|
||||
|
||||
|
||||
def test_resolve_agent_factory_returns_make_lead_agent():
|
||||
"""resolve_agent_factory always returns make_lead_agent regardless of assistant_id."""
|
||||
from app.gateway.services import resolve_agent_factory
|
||||
@@ -298,6 +313,36 @@ def test_build_run_config_with_context():
|
||||
assert config["recursion_limit"] == 100
|
||||
|
||||
|
||||
def test_build_run_config_null_context_becomes_empty_context():
|
||||
"""When caller sends context=null, treat it as an empty context object."""
|
||||
from app.gateway.services import build_run_config
|
||||
|
||||
config = build_run_config("thread-1", {"context": None}, None)
|
||||
|
||||
assert config["context"] == {}
|
||||
assert "configurable" not in config
|
||||
|
||||
|
||||
def test_build_run_config_rejects_non_mapping_context():
|
||||
"""When caller sends a non-object context, raise a clear error instead of a TypeError."""
|
||||
import pytest
|
||||
|
||||
from app.gateway.services import build_run_config
|
||||
|
||||
with pytest.raises(ValueError, match="context"):
|
||||
build_run_config("thread-1", {"context": "bad-context"}, None)
|
||||
|
||||
|
||||
def test_build_run_config_null_context_custom_agent_injects_agent_name():
|
||||
"""Custom assistant_id can still be injected when context=null starts context mode."""
|
||||
from app.gateway.services import build_run_config
|
||||
|
||||
config = build_run_config("thread-1", {"context": None}, None, assistant_id="finalis")
|
||||
|
||||
assert config["context"] == {"agent_name": "finalis"}
|
||||
assert "configurable" not in config
|
||||
|
||||
|
||||
def test_build_run_config_context_plus_configurable_warns(caplog):
|
||||
"""When caller sends both 'context' and 'configurable', prefer 'context' and log a warning."""
|
||||
import logging
|
||||
|
||||
@@ -113,6 +113,54 @@ def test_make_lead_agent_disables_thinking_when_model_does_not_support_it(monkey
|
||||
assert result["model"] is not None
|
||||
|
||||
|
||||
def test_make_lead_agent_reads_runtime_options_from_context(monkeypatch):
|
||||
app_config = _make_app_config(
|
||||
[
|
||||
_make_model("default-model", supports_thinking=False),
|
||||
_make_model("context-model", supports_thinking=True),
|
||||
]
|
||||
)
|
||||
|
||||
import deerflow.tools as tools_module
|
||||
|
||||
get_available_tools = MagicMock(return_value=[])
|
||||
monkeypatch.setattr(lead_agent_module, "get_app_config", lambda: app_config)
|
||||
monkeypatch.setattr(tools_module, "get_available_tools", get_available_tools)
|
||||
monkeypatch.setattr(lead_agent_module, "_build_middlewares", lambda config, model_name, agent_name=None: [])
|
||||
|
||||
captured: dict[str, object] = {}
|
||||
|
||||
def _fake_create_chat_model(*, name, thinking_enabled, reasoning_effort=None):
|
||||
captured["name"] = name
|
||||
captured["thinking_enabled"] = thinking_enabled
|
||||
captured["reasoning_effort"] = reasoning_effort
|
||||
return object()
|
||||
|
||||
monkeypatch.setattr(lead_agent_module, "create_chat_model", _fake_create_chat_model)
|
||||
monkeypatch.setattr(lead_agent_module, "create_agent", lambda **kwargs: kwargs)
|
||||
|
||||
result = lead_agent_module.make_lead_agent(
|
||||
{
|
||||
"context": {
|
||||
"model_name": "context-model",
|
||||
"thinking_enabled": False,
|
||||
"reasoning_effort": "high",
|
||||
"is_plan_mode": True,
|
||||
"subagent_enabled": True,
|
||||
"max_concurrent_subagents": 7,
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
assert captured == {
|
||||
"name": "context-model",
|
||||
"thinking_enabled": False,
|
||||
"reasoning_effort": "high",
|
||||
}
|
||||
get_available_tools.assert_called_once_with(model_name="context-model", groups=None, subagent_enabled=True)
|
||||
assert result["model"] is not None
|
||||
|
||||
|
||||
def test_make_lead_agent_rejects_invalid_bootstrap_agent_name(monkeypatch):
|
||||
app_config = _make_app_config([_make_model("safe-model", supports_thinking=False)])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user