fischer-agentkit/tests/unit/test_plan_exec_autonomy.py

124 lines
4.9 KiB
Python

"""Integration tests for PLAN_EXEC autonomy mode wiring (IQ-Boost U2).
Verifies that ``_build_phase_engine`` in chat.py constructs a PLAN_EXEC
engine with ``autonomy_mode=True`` and ``dangerous_tools_config`` injected
from ``ServerConfig``. This is the integration seam between U1 (config)
and U2 (engine gate).
"""
from __future__ import annotations
from unittest.mock import MagicMock
from agentkit.chat.skill_routing import ExecutionMode
from agentkit.core.react import ReActEngine
from agentkit.server.config import DangerousToolsConfig, ServerConfig
def _make_server_config(dangerous_tools: DangerousToolsConfig | None = None) -> ServerConfig:
"""Build a minimal ServerConfig with the dangerous_tools section."""
cfg = ServerConfig.from_dict({})
if dangerous_tools is not None:
cfg.dangerous_tools = dangerous_tools
return cfg
class TestBuildPhaseEngineAutonomyWiring:
"""_build_phase_engine injects autonomy config into the PLAN_EXEC engine."""
def test_plan_exec_engine_gets_autonomy_mode(self):
"""When PLAN_EXEC is engaged, the engine has autonomy_mode=True."""
# Import here to avoid module-level FastAPI app construction.
from agentkit.server.routes.chat import _build_phase_engine
server_cfg = _make_server_config(DangerousToolsConfig())
engine, tools, err = _build_phase_engine(
server_config=server_cfg,
llm_gateway=MagicMock(),
execution_mode=ExecutionMode.PLAN_EXEC,
base_tools=[],
session_id="test-session",
)
assert err is None
assert engine is not None
assert isinstance(engine, ReActEngine)
assert engine._autonomy_mode is True
assert engine._dangerous_tools_config is not None
assert engine._dangerous_tools_config.is_dangerous("rm") is True
def test_plan_exec_engine_gets_custom_dangerous_config(self):
"""Custom dangerous_tools config (disabled) propagates to the engine."""
from agentkit.server.routes.chat import _build_phase_engine
server_cfg = _make_server_config(DangerousToolsConfig(enabled=False))
engine, _, err = _build_phase_engine(
server_config=server_cfg,
llm_gateway=MagicMock(),
execution_mode=ExecutionMode.PLAN_EXEC,
base_tools=[],
session_id="test",
)
assert err is None
assert engine is not None
assert engine._dangerous_tools_config.enabled is False
# Disabled whitelist → nothing is dangerous
assert engine._dangerous_tools_config.is_dangerous("rm") is False
def test_non_plan_exec_mode_returns_none_engine(self):
"""Non-PLAN_EXEC mode → (None, None, None) — no autonomy engine built."""
from agentkit.server.routes.chat import _build_phase_engine
server_cfg = _make_server_config(DangerousToolsConfig())
engine, tools, err = _build_phase_engine(
server_config=server_cfg,
llm_gateway=MagicMock(),
execution_mode=ExecutionMode.REACT,
base_tools=[],
session_id="test",
)
assert engine is None
assert tools is None
assert err is None
def test_plan_exec_engine_gets_default_dangerous_config_when_server_config_missing(
self,
):
"""When server_config is None or lacks dangerous_tools, the engine
still gets autonomy_mode=True (config defaults to None — gate is a
no-op, but autonomy flag is set for future wiring)."""
from agentkit.server.routes.chat import _build_phase_engine
# server_config=None simulates tests/misconfigured deployments.
engine, _, err = _build_phase_engine(
server_config=None,
llm_gateway=MagicMock(),
execution_mode=ExecutionMode.PLAN_EXEC,
base_tools=[],
session_id="test",
)
assert err is None
assert engine is not None
assert engine._autonomy_mode is True
# dangerous_tools_config is None when server_config is None — gate
# becomes a transparent no-op (backward compat for tests without config).
assert engine._dangerous_tools_config is None
def test_plan_exec_engine_includes_advance_phase_tool(self):
"""PLAN_EXEC engine's tool list includes AdvancePhaseTool."""
from agentkit.server.routes.chat import _build_phase_engine
server_cfg = _make_server_config(DangerousToolsConfig())
engine, tools, err = _build_phase_engine(
server_config=server_cfg,
llm_gateway=MagicMock(),
execution_mode=ExecutionMode.PLAN_EXEC,
base_tools=[],
session_id="test",
)
assert err is None
assert engine is not None
assert tools is not None
# AdvancePhaseTool appended to the base tool list.
assert len(tools) == 1
assert type(tools[0]).__name__ == "AdvancePhaseTool"