Files
EvoScientist-Multi/tests/test_agent_factory_extensions.py
ouyangbo ddf337fc40
Docker / build (push) Has been cancelled
Test / pytest (windows-latest, 3.12) (push) Has been cancelled
Build / build (push) Has been cancelled
Lint / ruff (push) Has been cancelled
Test / pytest (ubuntu-latest, 3.11) (push) Has been cancelled
Test / pytest (ubuntu-latest, 3.12) (push) Has been cancelled
Test / pytest (windows-latest, 3.11) (push) Has been cancelled
审批暂停与继续:锚点恢复准入 + 不批准终止本轮(含 HITL 装配收敛与工作区范围)
langgraph_dev/http.py
- _compatible_checkpoint/_history_admission 支持带锚点准入:以承载 __interrupt__ 的检查点
  为父状态读取并校验中断标识;payload 保留锚点作为父状态
- 不带锚点时行为与原来完全一致(兼容性只靠这一条)

middleware/dynamic_review.py
- _abort_requested/_finish_turn + hook_config(can_jump_to=["end"]):在库消费中断后结束本轮
  (工具不执行、不再发起模型调用);无标记时完全休眠

随本批一并落定(早前改动):EvoScientist.py / workspace_scope.py 的 HITL 装配收敛与工作区范围,
以及对应测试调整。
2026-09-14 16:53:30 +08:00

203 lines
6.9 KiB
Python

def test_create_cli_agent_accepts_host_backend_and_memory_options(
monkeypatch, tmp_path
):
import EvoScientist.EvoScientist as agent_module
from EvoScientist.config.settings import EvoScientistConfig
calls = {}
workspace_backend = object()
chat_model = object()
class _CompositeBackend:
def __init__(self, *, default, routes, artifacts_root=None):
calls["default_backend"] = default
calls["routes"] = routes
calls["artifacts_root"] = artifacts_root
class _MemoryBackend:
def __init__(self, **kwargs):
calls["memory_backend_kwargs"] = kwargs
class _SkillsBackend:
def __init__(self, **kwargs):
calls["skills_backend_kwargs"] = kwargs
class _Agent:
def with_config(self, config):
calls["agent_config"] = config
return self
cfg = EvoScientistConfig(auto_approve=True, recursion_limit=321)
monkeypatch.setattr("deepagents.backends.CompositeBackend", _CompositeBackend)
monkeypatch.setattr("deepagents.create_deep_agent", lambda **kwargs: _Agent())
monkeypatch.setattr("EvoScientist.backends.MemoryFilesystemBackend", _MemoryBackend)
monkeypatch.setattr("EvoScientist.backends.MergedSkillsBackend", _SkillsBackend)
monkeypatch.setattr(agent_module, "set_active_workspace", lambda path: None)
monkeypatch.setattr(
agent_module,
"_get_default_middleware",
lambda **kwargs: calls.setdefault("middleware_kwargs", kwargs) or [],
)
monkeypatch.setattr(
agent_module,
"load_mcp_and_build_kwargs",
lambda *args, **kwargs: {"subagents": [{"name": "research"}]},
)
memory_dir = tmp_path / "memory"
result = agent_module.create_cli_agent(
workspace_dir=str(tmp_path / "workspace"),
checkpointer=object(),
config=cfg,
chat_model=chat_model,
workspace_backend=workspace_backend,
memory_dir=memory_dir,
tool_selector_threshold=8,
memory_max_inline_profile_chars=1000,
enable_subagents=False,
enable_background_execution=False,
)
assert isinstance(result, _Agent)
assert calls["default_backend"] is workspace_backend
assert calls["memory_backend_kwargs"] == {
"root_dir": str(memory_dir),
"virtual_mode": True,
}
assert calls["middleware_kwargs"]["memory_dir"] == str(memory_dir)
assert calls["middleware_kwargs"]["tool_selector_threshold"] == 8
assert calls["middleware_kwargs"]["memory_max_inline_profile_chars"] == 1000
assert calls["middleware_kwargs"]["enable_background_execution"] is False
assert calls["middleware_kwargs"]["enable_legacy_model_fallback"] is True
assert calls["agent_config"] == {"recursion_limit": 321}
def test_create_cli_agent_installs_route_middleware_in_fixed_slot(
monkeypatch, tmp_path
):
import EvoScientist.EvoScientist as agent_module
from EvoScientist.config.settings import EvoScientistConfig
calls = {}
class _Middleware:
def __init__(self, name):
self.name = name
class _Backend:
def __init__(self, **_kwargs):
pass
class _CompositeBackend:
def __init__(self, **_kwargs):
pass
class _Agent:
def with_config(self, _config):
return self
default_chain = [
_Middleware("error_normalization"),
_Middleware("configurable_model"),
_Middleware("context_editing"),
_Middleware("tool_protocol_guard"),
]
route = _Middleware("gateway_route_fallback")
monkeypatch.setattr("deepagents.backends.CompositeBackend", _CompositeBackend)
monkeypatch.setattr("deepagents.create_deep_agent", lambda **_kwargs: _Agent())
monkeypatch.setattr("EvoScientist.backends.MemoryFilesystemBackend", _Backend)
monkeypatch.setattr("EvoScientist.backends.MergedSkillsBackend", _Backend)
monkeypatch.setattr(agent_module, "set_active_workspace", lambda _path: None)
def fake_default_middleware(**kwargs):
calls["middleware_kwargs"] = kwargs
return list(default_chain)
monkeypatch.setattr(
agent_module, "_get_default_middleware", fake_default_middleware
)
def fake_load(_backend, middleware, **_kwargs):
calls["middleware"] = middleware
return {"subagents": []}
monkeypatch.setattr(agent_module, "load_mcp_and_build_kwargs", fake_load)
agent_module.create_cli_agent(
workspace_dir=str(tmp_path),
checkpointer=object(),
config=EvoScientistConfig(auto_approve=True),
chat_model=object(),
workspace_backend=object(),
main_agent_route_middleware=route,
)
assert calls["middleware_kwargs"]["enable_legacy_model_fallback"] is False
assert [middleware.name for middleware in calls["middleware"][:6]] == [
"error_normalization",
"provider_context_media",
"configurable_model",
"gateway_route_fallback",
"context_editing",
"tool_protocol_guard",
]
def test_create_cli_agent_replaces_framework_skill_injection(monkeypatch, tmp_path):
import EvoScientist.EvoScientist as agent_module
from EvoScientist.config.settings import EvoScientistConfig
from EvoScientist.middleware import BudgetedSkillsMiddleware
calls = {}
class _Backend:
def __init__(self, **_kwargs):
pass
class _CompositeBackend:
def __init__(self, **_kwargs):
pass
class _Agent:
def with_config(self, _config):
return self
def _create_deep_agent(**kwargs):
calls["kwargs"] = kwargs
return _Agent()
monkeypatch.setattr("deepagents.backends.CompositeBackend", _CompositeBackend)
monkeypatch.setattr("deepagents.create_deep_agent", _create_deep_agent)
monkeypatch.setattr("EvoScientist.backends.MemoryFilesystemBackend", _Backend)
monkeypatch.setattr("EvoScientist.backends.MergedSkillsBackend", _Backend)
monkeypatch.setattr(agent_module, "set_active_workspace", lambda _path: None)
monkeypatch.setattr(agent_module, "_get_default_middleware", lambda **_kwargs: [])
monkeypatch.setattr(
agent_module,
"load_mcp_and_build_kwargs",
lambda *_args, **_kwargs: {
"skills": ["/skills/"],
"middleware": [],
"subagents": [{"name": "research", "skills": ["/skills/"]}],
},
)
agent_module.create_cli_agent(
workspace_dir=str(tmp_path),
checkpointer=object(),
config=EvoScientistConfig(auto_approve=True),
chat_model=object(),
workspace_backend=object(),
)
assert calls["kwargs"]["skills"] is None
assert any(
isinstance(middleware, BudgetedSkillsMiddleware)
for middleware in calls["kwargs"]["middleware"]
)
subagent = calls["kwargs"]["subagents"][0]
assert subagent["skills"] is None
assert isinstance(subagent["middleware"][0], BudgetedSkillsMiddleware)