mirror of
https://github.com/anthropics/claude-code-sdk-python.git
synced 2025-12-23 09:19:52 +00:00
update PermissionResult to match latest control protocol (#209)
Recreation of https://github.com/anthropics/claude-agent-sdk-python/pull/174, with signed commits
This commit is contained in:
parent
70358589cf
commit
24408f9ddd
3 changed files with 50 additions and 9 deletions
|
|
@ -213,13 +213,18 @@ class Query:
|
|||
|
||||
# Convert PermissionResult to expected dict format
|
||||
if isinstance(response, PermissionResultAllow):
|
||||
response_data = {"allow": True}
|
||||
response_data = {"behavior": "allow"}
|
||||
if response.updated_input is not None:
|
||||
response_data["input"] = response.updated_input
|
||||
# TODO: Handle updatedPermissions when control protocol supports it
|
||||
response_data["updatedInput"] = response.updated_input
|
||||
if response.updated_permissions is not None:
|
||||
response_data["updatedPermissions"] = [
|
||||
permission.to_dict()
|
||||
for permission in response.updated_permissions
|
||||
]
|
||||
elif isinstance(response, PermissionResultDeny):
|
||||
response_data = {"allow": False, "reason": response.message}
|
||||
# TODO: Handle interrupt flag when control protocol supports it
|
||||
response_data = {"behavior": "deny", "message": response.message}
|
||||
if response.interrupt:
|
||||
response_data["interrupt"] = response.interrupt
|
||||
else:
|
||||
raise TypeError(
|
||||
f"Tool permission callback must return PermissionResult (PermissionResultAllow or PermissionResultDeny), got {type(response)}"
|
||||
|
|
|
|||
|
|
@ -70,6 +70,42 @@ class PermissionUpdate:
|
|||
directories: list[str] | None = None
|
||||
destination: PermissionUpdateDestination | None = None
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
"""Convert PermissionUpdate to dictionary format matching TypeScript control protocol."""
|
||||
result: dict[str, Any] = {
|
||||
"type": self.type,
|
||||
}
|
||||
|
||||
# Add destination for all variants
|
||||
if self.destination is not None:
|
||||
result["destination"] = self.destination
|
||||
|
||||
# Handle different type variants
|
||||
if self.type in ["addRules", "replaceRules", "removeRules"]:
|
||||
# Rules-based variants require rules and behavior
|
||||
if self.rules is not None:
|
||||
result["rules"] = [
|
||||
{
|
||||
"toolName": rule.tool_name,
|
||||
"ruleContent": rule.rule_content,
|
||||
}
|
||||
for rule in self.rules
|
||||
]
|
||||
if self.behavior is not None:
|
||||
result["behavior"] = self.behavior
|
||||
|
||||
elif self.type == "setMode":
|
||||
# Mode variant requires mode
|
||||
if self.mode is not None:
|
||||
result["mode"] = self.mode
|
||||
|
||||
elif self.type in ["addDirectories", "removeDirectories"]:
|
||||
# Directory variants require directories
|
||||
if self.directories is not None:
|
||||
result["directories"] = self.directories
|
||||
|
||||
return result
|
||||
|
||||
|
||||
# Tool callback types
|
||||
@dataclass
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ class TestToolPermissionCallbacks:
|
|||
# Check response was sent
|
||||
assert len(transport.written_messages) == 1
|
||||
response = transport.written_messages[0]
|
||||
assert '"allow": true' in response
|
||||
assert '"behavior": "allow"' in response
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_permission_callback_deny(self):
|
||||
|
|
@ -125,8 +125,8 @@ class TestToolPermissionCallbacks:
|
|||
# Check response
|
||||
assert len(transport.written_messages) == 1
|
||||
response = transport.written_messages[0]
|
||||
assert '"allow": false' in response
|
||||
assert '"reason": "Security policy violation"' in response
|
||||
assert '"behavior": "deny"' in response
|
||||
assert '"message": "Security policy violation"' in response
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_permission_callback_input_modification(self):
|
||||
|
|
@ -164,7 +164,7 @@ class TestToolPermissionCallbacks:
|
|||
# Check response includes modified input
|
||||
assert len(transport.written_messages) == 1
|
||||
response = transport.written_messages[0]
|
||||
assert '"allow": true' in response
|
||||
assert '"behavior": "allow"' in response
|
||||
assert '"safe_mode": true' in response
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue