fix(acp): use modes for edit auto-approval

This commit is contained in:
HenkDz
2026-05-16 19:15:08 +01:00
committed by Teknium
parent f70e0b85dd
commit 0292398604
5 changed files with 165 additions and 87 deletions

View File

@@ -24,6 +24,7 @@ from acp.schema import (
PromptResponse,
ResumeSessionResponse,
SessionModelState,
SessionModeState,
SetSessionConfigOptionResponse,
SetSessionModelResponse,
SetSessionModeResponse,
@@ -52,31 +53,34 @@ def agent(mock_manager):
"""HermesACPAgent backed by a mock session manager."""
return HermesACPAgent(session_manager=mock_manager)
@pytest.mark.asyncio
async def test_new_session_includes_edit_approval_config_option(self, agent):
resp = await agent.new_session(cwd="/tmp")
assert resp.config_options
option = resp.config_options[0]
assert option.id == "edit_approval_policy"
assert option.current_value == "ask"
assert {choice.value for choice in option.options} == {
"ask",
"workspace_session",
"session",
}
@pytest.mark.asyncio
async def test_new_session_exposes_edit_approvals_as_modes_not_config_options(agent):
resp = await agent.new_session(cwd="/tmp")
@pytest.mark.asyncio
async def test_set_config_option_persists_edit_approval_policy(self, agent):
resp = await agent.new_session(cwd="/tmp")
update = await agent.set_config_option(
"edit_approval_policy",
resp.session_id,
"workspace_session",
)
assert resp.config_options is None
assert isinstance(resp.modes, SessionModeState)
assert resp.modes.current_mode_id == "default"
assert [(mode.id, mode.name) for mode in resp.modes.available_modes] == [
("default", "Default"),
("accept_edits", "Accept Edits"),
("dont_ask", "Don't Ask"),
]
assert isinstance(update, SetSessionConfigOptionResponse)
assert update.config_options[0].current_value == "workspace_session"
@pytest.mark.asyncio
async def test_set_config_option_persists_edit_approval_policy_without_advertising_config(agent):
resp = await agent.new_session(cwd="/tmp")
update = await agent.set_config_option(
"edit_approval_policy",
resp.session_id,
"workspace_session",
)
state = agent.session_manager.get_session(resp.session_id)
assert isinstance(update, SetSessionConfigOptionResponse)
assert update.config_options == []
assert getattr(state, "mode", None) == "accept_edits"
# ---------------------------------------------------------------------------
@@ -891,11 +895,11 @@ class TestSessionConfiguration:
@pytest.mark.asyncio
async def test_set_session_mode_returns_response(self, agent):
new_resp = await agent.new_session(cwd="/tmp")
resp = await agent.set_session_mode(mode_id="chat", session_id=new_resp.session_id)
resp = await agent.set_session_mode(mode_id="accept_edits", session_id=new_resp.session_id)
state = agent.session_manager.get_session(new_resp.session_id)
assert isinstance(resp, SetSessionModeResponse)
assert getattr(state, "mode", None) == "chat"
assert getattr(state, "mode", None) == "accept_edits"
@pytest.mark.asyncio
async def test_router_accepts_stable_session_config_methods(self, agent):
@@ -904,7 +908,7 @@ class TestSessionConfiguration:
mode_result = await router(
"session/set_mode",
{"modeId": "chat", "sessionId": new_resp.session_id},
{"modeId": "accept_edits", "sessionId": new_resp.session_id},
False,
)
config_result = await router(
@@ -918,8 +922,7 @@ class TestSessionConfiguration:
)
assert mode_result == {}
assert config_result["configOptions"]
assert config_result["configOptions"][0]["id"] == "edit_approval_policy"
assert config_result["configOptions"] == []
@pytest.mark.asyncio
async def test_router_accepts_unstable_model_switch_when_enabled(self, agent):

View File

@@ -2,6 +2,7 @@
import pytest
from acp_adapter.edit_approval import EditProposal
from acp_adapter.tools import (
TOOL_KIND_MAP,
build_tool_complete,
@@ -174,6 +175,25 @@ class TestBuildToolStart:
assert "Approval prompt shows the diff" in item.content.text
assert "new_file.py" in item.content.text
def test_auto_approved_edit_start_shows_diff_content(self):
"""Auto-approved edit starts need the diff because no approval card exists."""
args = {"path": "/tmp/acp.txt", "old_string": "old", "new_string": "new"}
result = build_tool_start(
"tc-auto-edit",
"patch",
args,
edit_diff=EditProposal("patch", "/tmp/acp.txt", "old\n", "new\n", args),
)
assert isinstance(result, ToolCallStart)
assert result.kind == "edit"
assert len(result.content) == 1
item = result.content[0]
assert isinstance(item, FileEditToolCallContent)
assert item.path == "/tmp/acp.txt"
assert item.old_text == "old\n"
assert item.new_text == "new\n"
def test_build_tool_start_for_terminal(self):
"""terminal should produce text content with the command."""
args = {"command": "ls -la /tmp"}