8f11340b38
Per post_module_taxonomy_de_cruft_20260627 Phase 2 (FR7). Each
'from src.models import X' for a moved class is rewritten to
'from src.<destination> import X':
Ticket, Track, WorkerContext, TrackState, TrackMetadata,
ThinkingSegment, EMPTY_TRACK_STATE -> src.mma
ProjectContext, ProjectMeta, ProjectOutput, ProjectFiles,
ProjectScreenshots, ProjectDiscussion, EMPTY_PROJECT_CONTEXT -> src.project
FileItem, Preset, ContextPreset, ContextFileEntry,
NamedViewPreset -> src.project_files
Tool, ToolPreset -> src.tool_presets
BiasProfile -> src.tool_bias
TextEditorConfig, ExternalEditorConfig,
EMPTY_TEXT_EDITOR_CONFIG -> src.external_editor
Persona -> src.personas
WorkspaceProfile -> src.workspace_manager
MCPServerConfig, MCPConfiguration, VectorStoreConfig,
RAGConfig, load_mcp_config -> src.mcp_client
NOT touched (kept on src.models; Phase 3 or Phase 4 will move them):
GenerateRequest, ConfirmRequest, DEFAULT_TOOL_CATEGORIES, Metadata, PROVIDERS
Migration was performed by the one-time script
scripts/tier2/artifacts/post_module_taxonomy_de_cruft_20260627/migrate_imports.py
which uses a class-to-module map and re.sub() to rewrite each
'from src.models import X' line.
Total: 85 import lines rewritten across 71 files.
Note: this commit depends on the v2 SHIPPED work
(origin/tier2/module_taxonomy_refactor_20260627) being merged into
this branch NEXT. On master (without the v2 SHIPPED commits), the
destination modules do not exist and these imports would fail.
89 lines
2.5 KiB
Python
89 lines
2.5 KiB
Python
import pytest
|
|
import asyncio
|
|
from src import ai_client
|
|
from src import mcp_client
|
|
from src import models
|
|
from src.tool_presets import ToolPreset, Tool
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_tool_auto_approval():
|
|
# Setup a preset with read_file as auto
|
|
preset = ToolPreset(name="AutoTest", categories={
|
|
"General": [Tool(name="read_file", approval="auto")]
|
|
})
|
|
|
|
with patch("src.tool_presets.ToolPresetManager.load_all", return_value={"AutoTest": preset}):
|
|
ai_client.set_tool_preset("AutoTest")
|
|
|
|
# Mock mcp_client.async_dispatch to avoid actual file reads
|
|
with patch("src.mcp_client.async_dispatch", return_value="File Content") as mock_dispatch:
|
|
# pre_tool_callback should NOT be called
|
|
mock_cb = MagicMock()
|
|
|
|
name, call_id, out, _ = await ai_client._execute_single_tool_call_async(
|
|
name="read_file",
|
|
args={"path": "test.txt"},
|
|
call_id="call_1",
|
|
base_dir=".",
|
|
pre_tool_callback=mock_cb,
|
|
qa_callback=None,
|
|
r_idx=0
|
|
)
|
|
|
|
assert out == "File Content"
|
|
mock_cb.assert_not_called()
|
|
mock_dispatch.assert_called_once()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_tool_ask_approval():
|
|
# Setup a preset with run_powershell as ask
|
|
preset = ToolPreset(name="AskTest", categories={
|
|
"General": [Tool(name="run_powershell", approval="ask")]
|
|
})
|
|
|
|
with patch("src.tool_presets.ToolPresetManager.load_all", return_value={"AskTest": preset}):
|
|
ai_client.set_tool_preset("AskTest")
|
|
|
|
# pre_tool_callback SHOULD be called
|
|
mock_cb = MagicMock(return_value="Success")
|
|
|
|
name, call_id, out, _ = await ai_client._execute_single_tool_call_async(
|
|
name="run_powershell",
|
|
args={"script": "dir"},
|
|
call_id="call_2",
|
|
base_dir=".",
|
|
pre_tool_callback=mock_cb,
|
|
qa_callback=None,
|
|
r_idx=0
|
|
)
|
|
|
|
assert out == "Success"
|
|
mock_cb.assert_called_once()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_tool_rejection():
|
|
# Setup a preset with run_powershell as ask
|
|
preset = ToolPreset(name="AskTest", categories={
|
|
"General": [Tool(name="run_powershell", approval="ask")]
|
|
})
|
|
|
|
with patch("src.tool_presets.ToolPresetManager.load_all", return_value={"AskTest": preset}):
|
|
ai_client.set_tool_preset("AskTest")
|
|
|
|
# mock_cb returns None (rejected)
|
|
mock_cb = MagicMock(return_value=None)
|
|
|
|
name, call_id, out, _ = await ai_client._execute_single_tool_call_async(
|
|
name="run_powershell",
|
|
args={"script": "dir"},
|
|
call_id="call_3",
|
|
base_dir=".",
|
|
pre_tool_callback=mock_cb,
|
|
qa_callback=None,
|
|
r_idx=0
|
|
)
|
|
|
|
assert "USER REJECTED" in out
|
|
mock_cb.assert_called_once()
|