mirror of
https://github.com/shareAI-lab/analysis_claude_code.git
synced 2026-02-04 21:16:48 +08:00
- Remove all reverse-engineered Claude Code source code - Replace with 100% original educational content from mini-claude-code - Add clear disclaimer: independent project, not affiliated with Anthropic - 5 progressive agent implementations (v0-v4, ~1100 lines total) - Include agent-builder skill for teaching agent construction - Bilingual documentation (EN + ZH) This repository now focuses purely on teaching how modern AI agents work through original, from-scratch implementations. Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
272 lines
7.7 KiB
Python
272 lines
7.7 KiB
Python
"""
|
|
Tool Templates - Copy and customize these for your agent.
|
|
|
|
Each tool needs:
|
|
1. Definition (JSON schema for the model)
|
|
2. Implementation (Python function)
|
|
"""
|
|
|
|
from pathlib import Path
|
|
import subprocess
|
|
|
|
WORKDIR = Path.cwd()
|
|
|
|
|
|
# =============================================================================
|
|
# TOOL DEFINITIONS (for TOOLS list)
|
|
# =============================================================================
|
|
|
|
BASH_TOOL = {
|
|
"name": "bash",
|
|
"description": "Run a shell command. Use for: ls, find, grep, git, npm, python, etc.",
|
|
"input_schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"command": {
|
|
"type": "string",
|
|
"description": "The shell command to execute"
|
|
}
|
|
},
|
|
"required": ["command"],
|
|
},
|
|
}
|
|
|
|
READ_FILE_TOOL = {
|
|
"name": "read_file",
|
|
"description": "Read file contents. Returns UTF-8 text.",
|
|
"input_schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"path": {
|
|
"type": "string",
|
|
"description": "Relative path to the file"
|
|
},
|
|
"limit": {
|
|
"type": "integer",
|
|
"description": "Max lines to read (default: all)"
|
|
},
|
|
},
|
|
"required": ["path"],
|
|
},
|
|
}
|
|
|
|
WRITE_FILE_TOOL = {
|
|
"name": "write_file",
|
|
"description": "Write content to a file. Creates parent directories if needed.",
|
|
"input_schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"path": {
|
|
"type": "string",
|
|
"description": "Relative path for the file"
|
|
},
|
|
"content": {
|
|
"type": "string",
|
|
"description": "Content to write"
|
|
},
|
|
},
|
|
"required": ["path", "content"],
|
|
},
|
|
}
|
|
|
|
EDIT_FILE_TOOL = {
|
|
"name": "edit_file",
|
|
"description": "Replace exact text in a file. Use for surgical edits.",
|
|
"input_schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"path": {
|
|
"type": "string",
|
|
"description": "Relative path to the file"
|
|
},
|
|
"old_text": {
|
|
"type": "string",
|
|
"description": "Exact text to find (must match precisely)"
|
|
},
|
|
"new_text": {
|
|
"type": "string",
|
|
"description": "Replacement text"
|
|
},
|
|
},
|
|
"required": ["path", "old_text", "new_text"],
|
|
},
|
|
}
|
|
|
|
TODO_WRITE_TOOL = {
|
|
"name": "TodoWrite",
|
|
"description": "Update the task list. Use to plan and track progress.",
|
|
"input_schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"items": {
|
|
"type": "array",
|
|
"description": "Complete list of tasks",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"content": {"type": "string", "description": "Task description"},
|
|
"status": {"type": "string", "enum": ["pending", "in_progress", "completed"]},
|
|
"activeForm": {"type": "string", "description": "Present tense, e.g. 'Reading files'"},
|
|
},
|
|
"required": ["content", "status", "activeForm"],
|
|
},
|
|
}
|
|
},
|
|
"required": ["items"],
|
|
},
|
|
}
|
|
|
|
TASK_TOOL_TEMPLATE = """
|
|
# Generate dynamically with agent types
|
|
TASK_TOOL = {
|
|
"name": "Task",
|
|
"description": f"Spawn a subagent for a focused subtask.\\n\\nAgent types:\\n{get_agent_descriptions()}",
|
|
"input_schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"description": {"type": "string", "description": "Short task name (3-5 words)"},
|
|
"prompt": {"type": "string", "description": "Detailed instructions"},
|
|
"agent_type": {"type": "string", "enum": list(AGENT_TYPES.keys())},
|
|
},
|
|
"required": ["description", "prompt", "agent_type"],
|
|
},
|
|
}
|
|
"""
|
|
|
|
|
|
# =============================================================================
|
|
# TOOL IMPLEMENTATIONS
|
|
# =============================================================================
|
|
|
|
def safe_path(p: str) -> Path:
|
|
"""
|
|
Security: Ensure path stays within workspace.
|
|
Prevents ../../../etc/passwd attacks.
|
|
"""
|
|
path = (WORKDIR / p).resolve()
|
|
if not path.is_relative_to(WORKDIR):
|
|
raise ValueError(f"Path escapes workspace: {p}")
|
|
return path
|
|
|
|
|
|
def run_bash(command: str) -> str:
|
|
"""
|
|
Execute shell command with safety checks.
|
|
|
|
Safety features:
|
|
- Blocks obviously dangerous commands
|
|
- 60 second timeout
|
|
- Output truncated to 50KB
|
|
"""
|
|
dangerous = ["rm -rf /", "sudo", "shutdown", "reboot", "> /dev/"]
|
|
if any(d in command for d in dangerous):
|
|
return "Error: Dangerous command blocked"
|
|
|
|
try:
|
|
result = subprocess.run(
|
|
command,
|
|
shell=True,
|
|
cwd=WORKDIR,
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=60
|
|
)
|
|
output = (result.stdout + result.stderr).strip()
|
|
return output[:50000] if output else "(no output)"
|
|
|
|
except subprocess.TimeoutExpired:
|
|
return "Error: Command timed out (60s)"
|
|
except Exception as e:
|
|
return f"Error: {e}"
|
|
|
|
|
|
def run_read_file(path: str, limit: int = None) -> str:
|
|
"""
|
|
Read file contents with optional line limit.
|
|
|
|
Features:
|
|
- Safe path resolution
|
|
- Optional line limit for large files
|
|
- Output truncated to 50KB
|
|
"""
|
|
try:
|
|
text = safe_path(path).read_text()
|
|
lines = text.splitlines()
|
|
|
|
if limit and limit < len(lines):
|
|
lines = lines[:limit]
|
|
lines.append(f"... ({len(text.splitlines()) - limit} more lines)")
|
|
|
|
return "\n".join(lines)[:50000]
|
|
|
|
except Exception as e:
|
|
return f"Error: {e}"
|
|
|
|
|
|
def run_write_file(path: str, content: str) -> str:
|
|
"""
|
|
Write content to file, creating parent directories if needed.
|
|
|
|
Features:
|
|
- Safe path resolution
|
|
- Auto-creates parent directories
|
|
- Returns byte count for confirmation
|
|
"""
|
|
try:
|
|
fp = safe_path(path)
|
|
fp.parent.mkdir(parents=True, exist_ok=True)
|
|
fp.write_text(content)
|
|
return f"Wrote {len(content)} bytes to {path}"
|
|
|
|
except Exception as e:
|
|
return f"Error: {e}"
|
|
|
|
|
|
def run_edit_file(path: str, old_text: str, new_text: str) -> str:
|
|
"""
|
|
Replace exact text in a file (surgical edit).
|
|
|
|
Features:
|
|
- Exact string matching (not regex)
|
|
- Only replaces first occurrence (safety)
|
|
- Clear error if text not found
|
|
"""
|
|
try:
|
|
fp = safe_path(path)
|
|
content = fp.read_text()
|
|
|
|
if old_text not in content:
|
|
return f"Error: Text not found in {path}"
|
|
|
|
new_content = content.replace(old_text, new_text, 1)
|
|
fp.write_text(new_content)
|
|
return f"Edited {path}"
|
|
|
|
except Exception as e:
|
|
return f"Error: {e}"
|
|
|
|
|
|
# =============================================================================
|
|
# DISPATCHER PATTERN
|
|
# =============================================================================
|
|
|
|
def execute_tool(name: str, args: dict) -> str:
|
|
"""
|
|
Dispatch tool call to implementation.
|
|
|
|
This pattern makes it easy to add new tools:
|
|
1. Add definition to TOOLS list
|
|
2. Add implementation function
|
|
3. Add case to this dispatcher
|
|
"""
|
|
if name == "bash":
|
|
return run_bash(args["command"])
|
|
if name == "read_file":
|
|
return run_read_file(args["path"], args.get("limit"))
|
|
if name == "write_file":
|
|
return run_write_file(args["path"], args["content"])
|
|
if name == "edit_file":
|
|
return run_edit_file(args["path"], args["old_text"], args["new_text"])
|
|
# Add more tools here...
|
|
return f"Unknown tool: {name}"
|