mirror of
https://github.com/jmagar/unraid-mcp.git
synced 2026-03-23 12:39:24 -07:00
feat(guards): wire elicitation into notifications/vm/rclone/settings/storage
Replace hard ToolError guard with gate_destructive_action() in 5 tools so destructive actions prompt for interactive confirmation via MCP elicitation when ctx is available, and still accept confirm=True as a bypass. Update all test match strings from "destructive" to "not confirmed" accordingly.
This commit is contained in:
@@ -576,7 +576,7 @@ class TestVMToolRequests:
|
||||
@respx.mock
|
||||
async def test_force_stop_requires_confirm(self) -> None:
|
||||
tool = self._get_tool()
|
||||
with pytest.raises(ToolError, match="destructive"):
|
||||
with pytest.raises(ToolError, match="not confirmed"):
|
||||
await tool(action="force_stop", vm_id="vm-789")
|
||||
|
||||
@respx.mock
|
||||
@@ -593,7 +593,7 @@ class TestVMToolRequests:
|
||||
@respx.mock
|
||||
async def test_reset_requires_confirm(self) -> None:
|
||||
tool = self._get_tool()
|
||||
with pytest.raises(ToolError, match="destructive"):
|
||||
with pytest.raises(ToolError, match="not confirmed"):
|
||||
await tool(action="reset", vm_id="vm-abc")
|
||||
|
||||
@respx.mock
|
||||
@@ -880,7 +880,7 @@ class TestNotificationsToolRequests:
|
||||
@respx.mock
|
||||
async def test_delete_requires_confirm(self) -> None:
|
||||
tool = self._get_tool()
|
||||
with pytest.raises(ToolError, match="destructive"):
|
||||
with pytest.raises(ToolError, match="not confirmed"):
|
||||
await tool(action="delete", notification_id="n1", notification_type="UNREAD")
|
||||
|
||||
@respx.mock
|
||||
@@ -990,7 +990,7 @@ class TestRCloneToolRequests:
|
||||
@respx.mock
|
||||
async def test_delete_remote_requires_confirm(self) -> None:
|
||||
tool = self._get_tool()
|
||||
with pytest.raises(ToolError, match="destructive"):
|
||||
with pytest.raises(ToolError, match="not confirmed"):
|
||||
await tool(action="delete_remote", name="old-remote")
|
||||
|
||||
@respx.mock
|
||||
|
||||
@@ -40,12 +40,12 @@ def _make_tool():
|
||||
class TestNotificationsValidation:
|
||||
async def test_delete_requires_confirm(self, _mock_graphql: AsyncMock) -> None:
|
||||
tool_fn = _make_tool()
|
||||
with pytest.raises(ToolError, match="destructive"):
|
||||
with pytest.raises(ToolError, match="not confirmed"):
|
||||
await tool_fn(action="delete", notification_id="n:1", notification_type="UNREAD")
|
||||
|
||||
async def test_delete_archived_requires_confirm(self, _mock_graphql: AsyncMock) -> None:
|
||||
tool_fn = _make_tool()
|
||||
with pytest.raises(ToolError, match="destructive"):
|
||||
with pytest.raises(ToolError, match="not confirmed"):
|
||||
await tool_fn(action="delete_archived")
|
||||
|
||||
async def test_create_requires_fields(self, _mock_graphql: AsyncMock) -> None:
|
||||
|
||||
@@ -22,7 +22,7 @@ def _make_tool():
|
||||
class TestRcloneValidation:
|
||||
async def test_delete_requires_confirm(self) -> None:
|
||||
tool_fn = _make_tool()
|
||||
with pytest.raises(ToolError, match="destructive"):
|
||||
with pytest.raises(ToolError, match="not confirmed"):
|
||||
await tool_fn(action="delete_remote", name="gdrive")
|
||||
|
||||
async def test_create_requires_fields(self) -> None:
|
||||
|
||||
@@ -290,7 +290,7 @@ class TestStorageNetworkErrors:
|
||||
class TestStorageFlashBackup:
|
||||
async def test_flash_backup_requires_confirm(self, _mock_graphql: AsyncMock) -> None:
|
||||
tool_fn = _make_tool()
|
||||
with pytest.raises(ToolError, match="destructive"):
|
||||
with pytest.raises(ToolError, match="not confirmed"):
|
||||
await tool_fn(
|
||||
action="flash_backup", remote_name="r", source_path="/boot", destination_path="r:b"
|
||||
)
|
||||
|
||||
@@ -31,7 +31,7 @@ class TestVmValidation:
|
||||
async def test_destructive_actions_require_confirm(self, _mock_graphql: AsyncMock) -> None:
|
||||
tool_fn = _make_tool()
|
||||
for action in ("force_stop", "reset"):
|
||||
with pytest.raises(ToolError, match="destructive"):
|
||||
with pytest.raises(ToolError, match="not confirmed"):
|
||||
await tool_fn(action=action, vm_id="uuid-1")
|
||||
|
||||
async def test_destructive_vm_id_check_before_confirm(self, _mock_graphql: AsyncMock) -> None:
|
||||
|
||||
Reference in New Issue
Block a user