-
Notifications
You must be signed in to change notification settings - Fork 0
Refine OpenClaw adapter: method mapping, command extraction, and approval gating #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -54,6 +54,17 @@ def normalize_env() -> Dict[str, str]: | |
| re.compile(r"curl\s+.+\|\s*sh"), | ||
| ] | ||
|
|
||
| TOOL_METHOD_MAP = { | ||
| "run_terminal_cmd": "exec", | ||
| "terminal": "exec", | ||
| "read_file": "read", | ||
| "file_read": "read", | ||
| "write_file": "write", | ||
| "file_write": "write", | ||
| "process_state": "process", | ||
| "workflow_state": "process", | ||
| } | ||
|
|
||
|
|
||
| @dataclass | ||
| class ApprovalResult: | ||
|
|
@@ -116,14 +127,27 @@ def __init__(self) -> None: | |
|
|
||
| @staticmethod | ||
| def _map_method(neurorift_tool_call: Dict[str, Any]) -> str: | ||
| call_type = neurorift_tool_call.get("type") | ||
| if call_type == "run_terminal_cmd": | ||
| return "exec" | ||
| if call_type == "read_file": | ||
| return "read" | ||
| if call_type == "write_file": | ||
| return "write" | ||
| return "process" | ||
| call_type = neurorift_tool_call.get("type", "") | ||
| return TOOL_METHOD_MAP.get(call_type, "process") | ||
|
|
||
| @staticmethod | ||
| def _extract_command_preview(tool_call: Dict[str, Any], rpc_method: str) -> str: | ||
| if rpc_method != "exec": | ||
| return "" | ||
|
|
||
| for key in ("command", "cmd", "shell", "input"): | ||
| value = tool_call.get(key) | ||
| if isinstance(value, str) and value.strip(): | ||
| return value | ||
|
Comment on lines
+138
to
+141
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For Useful? React with 👍 / 👎. |
||
|
|
||
| payload = tool_call.get("payload") | ||
| if isinstance(payload, dict): | ||
| for key in ("command", "cmd"): | ||
| value = payload.get(key) | ||
| if isinstance(value, str) and value.strip(): | ||
| return value | ||
|
|
||
| return json.dumps(tool_call, ensure_ascii=False) | ||
|
|
||
| async def _call_neurorift(self, payload: Dict[str, Any]) -> Dict[str, Any]: | ||
| async with httpx.AsyncClient(timeout=self.request_timeout) as client: | ||
|
|
@@ -133,21 +157,22 @@ async def _call_neurorift(self, payload: Dict[str, Any]) -> Dict[str, Any]: | |
|
|
||
| async def _build_rpc_frame(self, tool_call: Dict[str, Any]) -> Dict[str, Any]: | ||
| rpc_method = self._map_method(tool_call) | ||
| command_preview = json.dumps(tool_call, ensure_ascii=False) | ||
| command_preview = self._extract_command_preview(tool_call, rpc_method) | ||
|
|
||
| approval = await self.approval_forwarder.evaluate( | ||
| command_preview, self.session_id | ||
| ) | ||
| if not approval.approved: | ||
| return { | ||
| "type": "rpc.reject", | ||
| "id": str(uuid.uuid4()), | ||
| "session": {"id": self.session_id, "mode": "isolated"}, | ||
| "error": { | ||
| "code": "approval_required", | ||
| "message": approval.reason, | ||
| }, | ||
| } | ||
| if rpc_method == "exec": | ||
| approval = await self.approval_forwarder.evaluate( | ||
| command_preview, self.session_id | ||
| ) | ||
| if not approval.approved: | ||
| return { | ||
| "type": "rpc.reject", | ||
| "id": str(uuid.uuid4()), | ||
| "session": {"id": self.session_id, "mode": "isolated"}, | ||
| "error": { | ||
| "code": "approval_required", | ||
| "message": approval.reason, | ||
| }, | ||
| } | ||
|
|
||
| bridged = await self._call_neurorift(tool_call) | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_map_methodnow doesTOOL_METHOD_MAP.get(call_type, "process"), which raisesTypeErrorwhentypeis a dict/list (possible with variant or malformed websocket payloads). The previous equality-chain safely fell back toprocess; this change can now crash_build_rpc_frameand terminate the adapter loop on a single bad event.Useful? React with 👍 / 👎.