Files
JARVIS/development-doc/plan/agent-update/phase-6-tool-system-refactoring.md
WIN-JHFT4D3SIVT\caoxiaozhu a3fe4d24fc feat(agents): Phase 7-10 hook system, plugins, skills, orchestration
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
2026-04-04 22:56:27 +08:00

323 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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工具注册表
```python
# 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拦截执行器
```python
# 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流式工具执行器
```python
# 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.2Hook 系统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` |