Phase 7: Built-in Hooks (audit_log, dangerous_confirmation, security_scan) Phase 8: Plugin system (PluginManager, PluginSandbox, PluginManifest) Phase 9: Skills registry (SkillRegistry, local/plugin/MCP loaders) Phase 10: TeamLeader, RemoteTransport, BackgroundTaskManager
11 KiB
11 KiB
Phase 6:工具系统重构(Tool System Refactoring)
日期:2026-04-04 状态:待开始 Demo参考:claw-code-main — tools/, StreamingToolExecutor, toolOrchestration
1. 阶段目标
建立分层工具执行架构,从现有的扁平工具调用进化为具有注册表、编排层、Hook 拦截能力的工具系统。
与现有系统的区别:
| 现有 | 目标 |
|---|---|
| Sub-Commander 直接调用 Tools | ToolRegistry → ToolOrchestration → HookExecutor → ToolExecutor → Tools |
| 工具集固定 | 工具注册表支持动态注册 |
| 无流式工具执行 | StreamingToolExecutor 支持流式 |
| 无工具拦截 | PreTool/PostTool Hook 机制 |
2. 架构设计
2.1 新的工具执行架构
┌─────────────────────────────────────────────────────────────────┐
│ Agent / Sub-Commander │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ ToolOrchestration Layer │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ ToolRegistry│ │HookExecutor │ │ StreamingToolExecutor │ │
│ │ (注册表) │ │ (拦截层) │ │ (流式执行器) │ │
│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ ToolExecutor │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Built-in │ │ External │ │ MCP │ │ Plugin │ │
│ │ Tools │ │ Tools │ │ Tools │ │ Tools │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────┘
2.2 核心组件
ToolRegistry(工具注册表)
# backend/app/agents/tools/registry.py
@dataclass
class ToolManifest:
"""工具元数据"""
name: str
description: str
category: ToolCategory
parameters: dict # JSON Schema
return_schema: dict
permission_class: PermissionClass # READ/WRITE/EXTERNAL
side_effect_scope: SideEffectScope # NONE/LOCAL_STATE/DB_WRITE/NETWORK
requires_confirmation: bool
is_streaming: bool = False
tags: list[str] = field(default_factory=list)
class ToolRegistry:
"""工具注册表"""
def __init__(self):
self._tools: dict[str, ToolManifest] = {}
self._executors: dict[str, Callable] = {}
self._hooks: dict[str, list[HookConfig]] = defaultdict(list)
def register(
self,
manifest: ToolManifest,
executor: Callable,
hooks: list[HookConfig] | None = None
):
"""注册工具"""
self._tools[manifest.name] = manifest
self._executors[manifest.name] = executor
if hooks:
for hook in hooks:
self._hooks[manifest.name].append(hook)
def get(self, name: str) -> ToolManifest | None:
"""获取工具元数据"""
return self._tools.get(name)
def get_executor(self, name: str) -> Callable | None:
"""获取工具执行器"""
return self._executors.get(name)
def list_by_category(self, category: ToolCategory) -> list[ToolManifest]:
"""按类别列出工具"""
return [t for t in self._tools.values() if t.category == category]
def list_all(self) -> list[ToolManifest]:
"""列出所有工具"""
return list(self._tools.values())
HookExecutor(拦截执行器)
# backend/app/agents/tools/hook_executor.py
@dataclass
class HookConfig:
"""Hook 配置"""
name: str
hook_type: HookType # PRE_TOOL_USE / POST_TOOL_USE / TOOL_ERROR / TOOL_SKIP
handler: Callable
filter_names: list[str] | None = None # 只对特定工具生效,None 表示全部
class HookExecutor:
"""工具 Hook 执行器"""
async def pre_execute(self, tool_name: str, arguments: dict) -> HookResult:
"""PreToolUse - 工具执行前拦截"""
hooks = self._get_hooks(tool_name, HookType.PRE_TOOL_USE)
ctx = HookContext(
tool_name=tool_name,
arguments=arguments,
phase=HookPhase.PRE
)
for hook in hooks:
result = await hook.handler(ctx)
if result.action == HookAction.DENY:
return HookResult(
action=HookAction.DENY,
message=result.message,
modified_args=None
)
elif result.action == HookAction.MODIFY:
ctx.arguments = result.modified_args
return HookResult(action=HookAction.ALLOW, modified_args=ctx.arguments)
async def post_execute(
self,
tool_name: str,
arguments: dict,
result: Any
) -> HookResult:
"""PostToolUse - 工具执行后拦截"""
hooks = self._get_hooks(tool_name, HookType.POST_TOOL_USE)
ctx = HookContext(
tool_name=tool_name,
arguments=arguments,
result=result,
phase=HookPhase.POST
)
for hook in hooks:
result = await hook.handler(ctx)
if result.action == HookAction.MODIFY_RESULT:
ctx.result = result.modified_result
return HookResult(action=HookAction.CONTINUE, modified_result=ctx.result)
StreamingToolExecutor(流式工具执行器)
# backend/app/agents/tools/streaming_executor.py
class StreamingToolExecutor:
"""流式工具执行器"""
async def execute_streaming(
self,
tool_name: str,
arguments: dict,
callback: Callable[[dict], Awaitable[None]]
) -> Any:
"""执行流式工具"""
manifest = self.registry.get(tool_name)
if not manifest.is_streaming:
raise ValueError(f"Tool {tool_name} does not support streaming")
executor = self.registry.get_executor(tool_name)
# 使用 aiterator 进行流式执行
async for chunk in executor(**arguments):
event = {"type": "chunk", "data": chunk}
await callback(event)
yield chunk
final_event = {"type": "done", "tool": tool_name}
await callback(final_event)
3. 新增工具集
3.1 文件操作工具
| 工具 | 描述 | 权限级别 |
|---|---|---|
| GlobTool | 按模式匹配文件 | READ |
| GrepTool | 在文件中搜索内容 | READ |
| LintTool | 代码检查 | READ |
| EditTool | 编辑文件 | WRITE |
3.2 开发工具
| 工具 | 描述 | 权限级别 |
|---|---|---|
| LSPTool | Language Server Protocol | READ |
| BashTool | 执行 Bash 命令 | EXTERNAL |
| PowerShellTool | 执行 PowerShell | EXTERNAL |
3.3 系统工具
| 工具 | 描述 | 权限级别 |
|---|---|---|
| ScheduleCronTool | Cron 定时任务 | WRITE |
| ProcessTool | 进程管理 | EXTERNAL |
3.4 协作工具
| 工具 | 描述 | 权限级别 |
|---|---|---|
| TeamAgentTool | 团队 Agent 协作 | EXTERNAL |
| TaskBroadcastTool | 任务广播 | WRITE |
3.5 高级工具
| 工具 | 描述 | 权限级别 |
|---|---|---|
| RemoteTriggerTool | 远程触发 | EXTERNAL |
| MCPClientTool | MCP 客户端 | EXTERNAL |
| AskUserQuestionTool | 向用户提问 | READ |
4. 文件结构变化
backend/app/agents/tools/
├── __init__.py # 现有 - 需重构
├── registry.py # 新增 - 工具注册表
├── manifest.py # 新增 - 工具元数据
├── hook_executor.py # 新增 - Hook 执行器
├── hook_config.py # 新增 - Hook 配置
├── streaming_executor.py # 新增 - 流式执行器
├── base.py # 新增 - 基础工具类
│
├── builtins/ # 新增 - 内置工具
│ ├── __init__.py
│ ├── file_tools.py # Glob, Grep, Edit, Lint
│ ├── system_tools.py # Bash, PowerShell, Cron
│ ├── dev_tools.py # LSP, Git
│ └── collaboration_tools.py # Team, Broadcast
│
├── task.py # 现有 - 保留
├── schedule.py # 现有 - 保留
├── search.py # 现有 - 保留
├── forum.py # 现有 - 保留
└── time_reasoning.py # 现有 - 保留
5. 迁移计划
阶段 6.1:基础设施(1-2周)
- 创建 ToolRegistry 类
- 创建 ToolManifest 数据类
- 迁移现有工具到注册表
阶段 6.2:Hook 系统(2-3周)
- 创建 HookExecutor
- 实现 PreTool/PostTool 机制
- 添加内置 Hook(确认危险操作、日志记录)
阶段 6.3:流式执行(1-2周)
- 实现 StreamingToolExecutor
- 为支持流式的工具添加 streaming 标志
- 更新 AgentService 集成
阶段 6.4:新工具集(2-3周)
- 实现新增的工具类
- 添加完整的工具文档
- 单元测试覆盖
6. 验收标准
| 检查点 | 标准 |
|---|---|
| 工具注册 | 所有现有工具已在 Registry 中注册 |
| Hook 执行 | PreTool/PostTool Hook 能正确拦截 |
| 流式执行 | 标记为 streaming 的工具可流式返回 |
| 新工具 | 新增工具集中每个工具可正常执行 |
| 向后兼容 | 现有 Sub-Commander 工具调用不受影响 |
7. Demo 借鉴
| claw-code 实现 | Jarvis 对应 |
|---|---|
src/tools/ |
backend/app/agents/tools/ |
StreamingToolExecutor.ts |
streaming_executor.py |
toolExecution.ts |
hook_executor.py |
toolHooks.ts |
hook_config.py |
ToolManifest |
manifest.py |