mirror of
https://github.com/shareAI-lab/analysis_claude_code.git
synced 2026-09-20 12:13:38 +08:00
Refine course progression and runtime safety
This commit is contained in:
@@ -8,13 +8,17 @@ Three gates inserted before tool execution:
|
||||
Gate 2: Rule matching (write outside workspace? destructive cmd?)
|
||||
Gate 3: User approval (pause and wait for confirmation)
|
||||
|
||||
+-------+ +--------+ +--------+ +--------+ +------+
|
||||
| Tool | -> | Gate 1 | -> | Gate 2 | -> | Gate 3 | -> | Exec |
|
||||
| call | | deny? | | match? | | allow? | | |
|
||||
+-------+ +--------+ +--------+ +--------+ +------+
|
||||
| | | |
|
||||
v v v v
|
||||
(normal) (blocked) (ask user) (user says no?)
|
||||
+----------+ +-------+ +--------------+ +---------------+
|
||||
| User | ---> | LLM | ---> | Permission | ---> | Tool Dispatch |
|
||||
| prompt | | | | 1. deny list | | execute |
|
||||
+----------+ +---+---+ | 2. rules | +-------+-------+
|
||||
^ | 3. approval | |
|
||||
| +------+-------+ |
|
||||
| | deny |
|
||||
| v v
|
||||
| +-------------------------------+
|
||||
+----------+ tool_result: denied or output |
|
||||
+-------------------------------+
|
||||
|
||||
Only one line added to the agent loop:
|
||||
|
||||
@@ -27,7 +31,8 @@ Builds on s02 (multi-tool). Usage:
|
||||
Needs: pip install anthropic python-dotenv + ANTHROPIC_API_KEY in .env
|
||||
"""
|
||||
|
||||
import os, subprocess
|
||||
import os
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
try:
|
||||
@@ -53,9 +58,7 @@ MODEL = os.environ["MODEL_ID"]
|
||||
SYSTEM = f"You are a coding agent at {WORKDIR}. All destructive operations require user approval."
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════
|
||||
# FROM s02 : Tool Implementations
|
||||
# ═══════════════════════════════════════════════════════════
|
||||
# -- From s02: tool implementations --
|
||||
|
||||
def run_bash(command: str) -> str:
|
||||
try:
|
||||
@@ -111,9 +114,7 @@ def run_glob(pattern: str) -> str:
|
||||
return f"Error: {e}"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════
|
||||
# FROM s02 (unchanged): Tool Definitions & Dispatch
|
||||
# ═══════════════════════════════════════════════════════════
|
||||
# -- From s02 (unchanged): tool definitions and dispatch --
|
||||
|
||||
TOOLS = [
|
||||
{"name": "bash", "description": "Run a shell command.",
|
||||
@@ -134,11 +135,9 @@ TOOL_HANDLERS = {
|
||||
}
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════
|
||||
# NEW in s03: Three-Gate Permission Pipeline
|
||||
# ═══════════════════════════════════════════════════════════
|
||||
# -- New in s03: three-gate permission pipeline --
|
||||
|
||||
# Gate 1: Hard deny list — always forbidden
|
||||
# Gate 1: Hard deny list - always forbidden
|
||||
DENY_LIST = ["rm -rf /", "sudo", "shutdown", "reboot", "mkfs", "dd if=", "> /dev/sda"]
|
||||
|
||||
def check_deny_list(command: str) -> str | None:
|
||||
@@ -148,7 +147,7 @@ def check_deny_list(command: str) -> str | None:
|
||||
return None
|
||||
|
||||
|
||||
# Gate 2: Rule matching — context-dependent checks
|
||||
# Gate 2: Rule matching - context-dependent checks
|
||||
PERMISSION_RULES = [
|
||||
{"tools": ["read_file", "write_file", "edit_file"],
|
||||
"check": lambda args: not (WORKDIR / args.get("path", "")).resolve().is_relative_to(WORKDIR),
|
||||
@@ -165,9 +164,9 @@ def check_rules(tool_name: str, args: dict) -> str | None:
|
||||
return None
|
||||
|
||||
|
||||
# Gate 3: User approval — wait for confirmation after rule match
|
||||
# Gate 3: User approval - wait for confirmation after rule match
|
||||
def ask_user(tool_name: str, args: dict, reason: str) -> str:
|
||||
print(f"\n\033[33m⚠ {reason}\033[0m")
|
||||
print(f"\n\033[33m[permission] {reason}\033[0m")
|
||||
print(f" Tool: {tool_name}({args})")
|
||||
choice = input(" Allow? [y/N] ").strip().lower()
|
||||
return "allow" if choice in ("y", "yes") else "deny"
|
||||
@@ -178,7 +177,7 @@ def check_permission(block) -> bool:
|
||||
if block.name == "bash":
|
||||
reason = check_deny_list(block.input.get("command", ""))
|
||||
if reason:
|
||||
print(f"\n\033[31m⛔ {reason}\033[0m")
|
||||
print(f"\n\033[31m[blocked] {reason}\033[0m")
|
||||
return False
|
||||
reason = check_rules(block.name, block.input)
|
||||
if reason:
|
||||
@@ -188,9 +187,7 @@ def check_permission(block) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════
|
||||
# agent_loop — same as s02, with check_permission() inserted
|
||||
# ═══════════════════════════════════════════════════════════
|
||||
# -- Agent loop: same as s02, with check_permission() inserted --
|
||||
|
||||
def agent_loop(messages: list):
|
||||
while True:
|
||||
@@ -226,7 +223,7 @@ def agent_loop(messages: list):
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("s03: Permission")
|
||||
print("输入问题,回车发送。输入 q 退出。\n")
|
||||
print("Enter a question, press Enter to send. Type q to quit.\n")
|
||||
|
||||
history = []
|
||||
while True:
|
||||
|
||||
Reference in New Issue
Block a user