mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-29 06:31:32 +00:00
feat(acp): enrich permission request cards
This commit is contained in:
parent
2057977102
commit
52e3bfc2f4
2 changed files with 47 additions and 5 deletions
|
|
@ -23,11 +23,21 @@ _OPTION_ID_TO_HERMES = {
|
|||
"allow_session": "session",
|
||||
"allow_always": "always",
|
||||
"deny": "deny",
|
||||
"deny_always": "deny",
|
||||
}
|
||||
|
||||
_PERMISSION_REQUEST_IDS = count(1)
|
||||
|
||||
|
||||
def _permission_option_supports_kind(kind: str) -> bool:
|
||||
"""Return whether the installed ACP SDK accepts a permission option kind."""
|
||||
try:
|
||||
PermissionOption(option_id="__probe__", kind=kind, name="probe")
|
||||
except Exception:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _build_permission_options(*, allow_permanent: bool) -> list[PermissionOption]:
|
||||
"""Return ACP options that match Hermes approval semantics."""
|
||||
options = [
|
||||
|
|
@ -49,6 +59,14 @@ def _build_permission_options(*, allow_permanent: bool) -> list[PermissionOption
|
|||
),
|
||||
)
|
||||
options.append(PermissionOption(option_id="deny", kind="reject_once", name="Deny"))
|
||||
if _permission_option_supports_kind("reject_always"):
|
||||
options.append(
|
||||
PermissionOption(
|
||||
option_id="deny_always",
|
||||
kind="reject_always",
|
||||
name="Deny always",
|
||||
),
|
||||
)
|
||||
return options
|
||||
|
||||
|
||||
|
|
@ -62,12 +80,14 @@ def _build_permission_tool_call(command: str, description: str):
|
|||
import acp as _acp
|
||||
|
||||
tool_call_id = f"perm-check-{next(_PERMISSION_REQUEST_IDS)}"
|
||||
title = f"{description}: {command}" if description else command
|
||||
content_text = f"{description}\n$ {command}" if description else f"$ {command}"
|
||||
return _acp.update_tool_call(
|
||||
tool_call_id,
|
||||
title=description,
|
||||
title=title,
|
||||
kind="execute",
|
||||
status="pending",
|
||||
content=[_acp.tool_content(_acp.text_block(f"$ {command}"))],
|
||||
content=[_acp.tool_content(_acp.text_block(content_text))],
|
||||
raw_input={"command": command, "description": description},
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -76,12 +76,22 @@ class TestApprovalBridge:
|
|||
assert tool_call.tool_call_id.startswith("perm-check-")
|
||||
assert tool_call.kind == "execute"
|
||||
assert tool_call.status == "pending"
|
||||
assert tool_call.title == "dangerous command"
|
||||
assert "dangerous command" in tool_call.title
|
||||
assert "rm -rf /" in tool_call.title
|
||||
content_text = tool_call.content[0].content.text
|
||||
assert "$ rm -rf /" in content_text
|
||||
assert "dangerous command" in content_text
|
||||
assert tool_call.raw_input == {
|
||||
"command": "rm -rf /",
|
||||
"description": "dangerous command",
|
||||
}
|
||||
assert option_ids == ["allow_once", "allow_session", "allow_always", "deny"]
|
||||
assert option_ids == [
|
||||
"allow_once",
|
||||
"allow_session",
|
||||
"allow_always",
|
||||
"deny",
|
||||
"deny_always",
|
||||
]
|
||||
|
||||
def test_tool_call_ids_are_unique(self):
|
||||
_, first_kwargs, _, _, _ = _invoke_callback(
|
||||
|
|
@ -103,7 +113,19 @@ class TestApprovalBridge:
|
|||
option_ids = [option.option_id for option in kwargs["options"]]
|
||||
|
||||
assert result == "session"
|
||||
assert option_ids == ["allow_once", "allow_session", "deny"]
|
||||
assert option_ids == ["allow_once", "allow_session", "deny", "deny_always"]
|
||||
|
||||
def test_reject_always_outcome_denies_without_changing_policy(self):
|
||||
result, kwargs, _, _, _ = _invoke_callback(
|
||||
AllowedOutcome(option_id="deny_always", outcome="selected"),
|
||||
use_prompt_path=True,
|
||||
)
|
||||
|
||||
deny_always = [option for option in kwargs["options"] if option.option_id == "deny_always"]
|
||||
|
||||
assert result == "deny"
|
||||
assert len(deny_always) == 1
|
||||
assert deny_always[0].kind == "reject_always"
|
||||
|
||||
def test_allow_always_maps_correctly(self):
|
||||
result, _, _, _, _ = _invoke_callback(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue