diff --git a/tools/approval.py b/tools/approval.py index ab2a10927..c47672b8b 100644 --- a/tools/approval.py +++ b/tools/approval.py @@ -724,7 +724,8 @@ def check_all_command_guards(command: str, env_type: str, logger.debug("Smart approval: auto-approved '%s' (%s)", command[:60], combined_desc_for_llm) return {"approved": True, "message": None, - "smart_approved": True} + "smart_approved": True, + "description": combined_desc_for_llm} elif verdict == "deny": combined_desc_for_llm = "; ".join(desc for _, desc, _ in warnings) return { @@ -819,7 +820,8 @@ def check_all_command_guards(command: str, env_type: str, approve_permanent(key) save_permanent_allowlist(_permanent_approved) - return {"approved": True, "message": None} + return {"approved": True, "message": None, + "user_approved": True, "description": combined_desc} # Fallback: no gateway callback registered (e.g. cron, batch). # Return approval_required for backward compat. @@ -865,4 +867,5 @@ def check_all_command_guards(command: str, env_type: str, approve_permanent(key) save_permanent_allowlist(_permanent_approved) - return {"approved": True, "message": None} + return {"approved": True, "message": None, + "user_approved": True, "description": combined_desc} diff --git a/tools/terminal_tool.py b/tools/terminal_tool.py index 92581dbc4..31d7d77c6 100644 --- a/tools/terminal_tool.py +++ b/tools/terminal_tool.py @@ -1058,6 +1058,7 @@ def terminal_tool( # Pre-exec security checks (tirith + dangerous command detection) # Skip check if force=True (user has confirmed they want to run it) + approval_note = None if not force: approval = _check_all_guards(command, env_type) if not approval["approved"]: @@ -1084,6 +1085,13 @@ def terminal_tool( "error": approval.get("message", fallback_msg), "status": "blocked" }, ensure_ascii=False) + # Track whether approval was explicitly granted by the user + if approval.get("user_approved"): + desc = approval.get("description", "flagged as dangerous") + approval_note = f"Command required approval ({desc}) and was approved by the user." + elif approval.get("smart_approved"): + desc = approval.get("description", "flagged as dangerous") + approval_note = f"Command was flagged ({desc}) and auto-approved by smart approval." # Prepare command for execution if background: @@ -1121,6 +1129,8 @@ def terminal_tool( "exit_code": 0, "error": None, } + if approval_note: + result_data["approval"] = approval_note # Transparent timeout clamping note max_timeout = effective_timeout @@ -1232,11 +1242,14 @@ def terminal_tool( from agent.redact import redact_sensitive_text output = redact_sensitive_text(output.strip()) if output else "" - return json.dumps({ + result_dict = { "output": output, "exit_code": returncode, "error": None - }, ensure_ascii=False) + } + if approval_note: + result_dict["approval"] = approval_note + return json.dumps(result_dict, ensure_ascii=False) except Exception as e: import traceback