feat(mcp_client): add MUTATING_TOOLS frozenset sentinel for HITL enforcement
This commit is contained in:
@@ -40,6 +40,17 @@ import urllib.parse
|
||||
from html.parser import HTMLParser
|
||||
import re as _re
|
||||
|
||||
# ------------------------------------------------------------------ mutating tools sentinel
|
||||
|
||||
# Tools that write or modify files. ai_client checks this set before dispatch
|
||||
# and routes to pre_tool_callback (GUI approval) if the tool name is present.
|
||||
MUTATING_TOOLS: frozenset[str] = frozenset({
|
||||
"set_file_slice",
|
||||
"py_update_definition",
|
||||
"py_set_signature",
|
||||
"py_set_var_declaration",
|
||||
})
|
||||
|
||||
# ------------------------------------------------------------------ state
|
||||
|
||||
# Set by configure() before the AI send loop starts.
|
||||
|
||||
@@ -67,3 +67,29 @@ def test_gui_agent_tool_names_exposes_all_dispatch_tools():
|
||||
gui_tools = set(AGENT_TOOL_NAMES)
|
||||
missing = ALL_DISPATCH_TOOLS - gui_tools
|
||||
assert not missing, f"Tools missing from gui_2.AGENT_TOOL_NAMES: {missing}"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Task 2.3: MUTATING_TOOLS constant in mcp_client.py
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_mcp_client_has_mutating_tools_constant():
|
||||
"""mcp_client must expose a MUTATING_TOOLS frozenset."""
|
||||
import mcp_client
|
||||
assert hasattr(mcp_client, "MUTATING_TOOLS"), "MUTATING_TOOLS missing from mcp_client"
|
||||
assert isinstance(mcp_client.MUTATING_TOOLS, frozenset)
|
||||
|
||||
|
||||
def test_mutating_tools_contains_write_tools():
|
||||
"""MUTATING_TOOLS must include all four write tools."""
|
||||
import mcp_client
|
||||
for tool in MUTATING_TOOLS:
|
||||
assert tool in mcp_client.MUTATING_TOOLS, f"{tool} missing from mcp_client.MUTATING_TOOLS"
|
||||
|
||||
|
||||
def test_mutating_tools_excludes_read_tools():
|
||||
"""MUTATING_TOOLS must not include read-only tools."""
|
||||
import mcp_client
|
||||
read_only = {"read_file", "get_file_slice", "py_get_definition", "py_get_skeleton"}
|
||||
for tool in read_only:
|
||||
assert tool not in mcp_client.MUTATING_TOOLS, f"Read-only tool '{tool}' must not be in MUTATING_TOOLS"
|
||||
|
||||
Reference in New Issue
Block a user