feat: wire AgentLoop to DisplayAdapter and async permissions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -21,6 +21,7 @@ from app.services.llm import LLMClient
|
||||
from app.services.permissions import PermissionsService
|
||||
from app.services.streaming import StreamHandler
|
||||
from app.tools.registry import ToolRegistry, create_default_registry
|
||||
from app.utils.display import DisplayAdapter
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -76,6 +77,11 @@ def permissions(config: AppConfig) -> PermissionsService:
|
||||
return PermissionsService(config.permissions)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def display() -> MagicMock:
|
||||
return MagicMock(spec=DisplayAdapter)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def agent(
|
||||
config: AppConfig,
|
||||
@@ -84,8 +90,9 @@ def agent(
|
||||
handler: MagicMock,
|
||||
registry: ToolRegistry,
|
||||
permissions: PermissionsService,
|
||||
display: MagicMock,
|
||||
) -> AgentLoop:
|
||||
return AgentLoop(config, ctx, client, handler, registry, permissions)
|
||||
return AgentLoop(config, ctx, client, handler, registry, permissions, display)
|
||||
|
||||
|
||||
def _make_text_message(content: str) -> Message:
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
"""Tests for the tool framework and core tools (Phase 4)."""
|
||||
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -48,28 +47,40 @@ class TestBaseTool:
|
||||
|
||||
|
||||
class TestPermissionsService:
|
||||
def test_deny_list_blocks(self) -> None:
|
||||
@pytest.mark.asyncio
|
||||
async def test_deny_list_blocks(self) -> None:
|
||||
svc = PermissionsService(PermissionsConfig(deny=["dangerous_tool"]))
|
||||
assert svc.check("dangerous_tool") is False
|
||||
assert await svc.check("dangerous_tool") is False
|
||||
|
||||
def test_auto_approve_allows(self) -> None:
|
||||
@pytest.mark.asyncio
|
||||
async def test_auto_approve_allows(self) -> None:
|
||||
svc = PermissionsService(PermissionsConfig(auto_approve=["read_file"]))
|
||||
assert svc.check("read_file") is True
|
||||
assert await svc.check("read_file") is True
|
||||
|
||||
@patch("app.services.permissions.Confirm.ask", return_value=True)
|
||||
def test_prompt_user_approved(self, mock_ask: object) -> None:
|
||||
@pytest.mark.asyncio
|
||||
async def test_prompt_callback_approved(self) -> None:
|
||||
svc = PermissionsService(PermissionsConfig(prompt_user=["write_file"]))
|
||||
assert svc.check("write_file") is True
|
||||
|
||||
@patch("app.services.permissions.Confirm.ask", return_value=False)
|
||||
def test_prompt_user_denied(self, mock_ask: object) -> None:
|
||||
async def approve(tool_name: str, description: str) -> bool:
|
||||
return True
|
||||
|
||||
svc.set_prompt_callback(approve)
|
||||
assert await svc.check("write_file") is True
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_prompt_callback_denied(self) -> None:
|
||||
svc = PermissionsService(PermissionsConfig(prompt_user=["write_file"]))
|
||||
assert svc.check("write_file") is False
|
||||
|
||||
@patch("app.services.permissions.Confirm.ask", return_value=False)
|
||||
def test_unlisted_tool_prompts(self, mock_ask: object) -> None:
|
||||
async def deny(tool_name: str, description: str) -> bool:
|
||||
return False
|
||||
|
||||
svc.set_prompt_callback(deny)
|
||||
assert await svc.check("write_file") is False
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_unlisted_tool_no_callback_denied(self) -> None:
|
||||
svc = PermissionsService(PermissionsConfig())
|
||||
assert svc.check("unknown_tool") is False
|
||||
assert await svc.check("unknown_tool") is False
|
||||
|
||||
|
||||
# --- ToolRegistry ---
|
||||
|
||||
Reference in New Issue
Block a user