1085 lines
25 KiB
Markdown
1085 lines
25 KiB
Markdown
# Tool 管理 + Agent 工具授权 + 多模态 OCR 前置治理 实施文档
|
||
|
||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||
|
||
**Goal:** 为 Neta 实现一套真正可落地的 Tool 治理体系,包括全局 Tool 管理、Agent 级 toolset/tool 授权、运行时统一 Tool 解析、Prompt Builder 接入、前端管理页面和后续多模态 OCR 接入的前置能力。
|
||
|
||
**Architecture:** 保留现有 `catalog.ts` 作为代码注册层,新增 `netaclaw_tool` 作为全局治理表,扩展 `netaclaw_agent` 的 `toolsets/tools` 配置,新增 `tool_registry.ts` 和 `tool_resolver.ts` 统一打通 catalog、DB 配置、Agent 授权、模型能力约束和运行时 Tool 实例组装。前端新增 Tool 管理页和 Agent 编辑页中的工具配置 Tab。Prompt Builder 改为消费 resolver 的结果,而不是静态推导工具列表。
|
||
|
||
**V1 Scope Constraint:** 首版 Agent 授权模型收敛为 `toolsets + tools.disabled`。`tools.enabled` 不进入首版实施,避免 UI、运行时、数据库语义同时过重。
|
||
|
||
**Tech Stack:** MySQL + TypeORM + Midway.js + Vue 3 + Element Plus + TypeScript
|
||
|
||
**Spec:** `docs/superpowers/specs/2026-04-18-tool-management-and-agent-tool-governance-design.md`
|
||
|
||
---
|
||
|
||
## 一、实施范围
|
||
|
||
本实施覆盖以下内容:
|
||
|
||
1. 数据库表与字段设计落库
|
||
2. 后端 Tool 元数据同步与运行时解析
|
||
3. Agent 配置模型扩展
|
||
4. Prompt Builder 接入 Tool Resolver
|
||
5. 前端 Tool 管理页面
|
||
6. 前端 Agent 编辑页工具配置
|
||
7. 联调、验收、回滚预案
|
||
|
||
本实施不直接实现 OCR,但会为 OCR 接入完成全部前置基础设施。
|
||
|
||
---
|
||
|
||
## 二、文件结构
|
||
|
||
### 新增文件
|
||
|
||
| 文件 | 职责 |
|
||
|------|------|
|
||
| `packages/backend/src/modules/netaclaw/entity/tool.ts` | Tool 全局治理实体 |
|
||
| `packages/backend/src/modules/netaclaw/service/tool_registry.ts` | catalog -> DB 同步、后台查询 |
|
||
| `packages/backend/src/modules/netaclaw/service/tool_resolver.ts` | 运行时统一工具解析 |
|
||
| `packages/backend/src/modules/netaclaw/controller/admin/tool.ts` | Tool 管理接口 |
|
||
| `packages/frontend/src/modules/agent/views/tools.vue` | Tool 管理页面 |
|
||
|
||
### 修改文件
|
||
|
||
| 文件 | 改动 |
|
||
|------|------|
|
||
| `packages/backend/src/entities.ts` | 注册新实体 |
|
||
| `packages/backend/src/modules/netaclaw/tools/catalog.ts` | 扩展 ToolSchema 元数据 |
|
||
| `packages/backend/src/modules/netaclaw/tools/common.ts` | 对齐 visibility/capability 类型 |
|
||
| `packages/backend/src/modules/netaclaw/entity/agent.ts` | 新增 `toolsets`、`tools` 字段 |
|
||
| `packages/backend/src/modules/netaclaw/service/agent_executor.ts` | 改为使用 Tool Resolver |
|
||
| `packages/backend/src/modules/netaclaw/gateway/server.ts` | 改为使用 Tool Resolver |
|
||
| `packages/backend/src/modules/netaclaw/service/crew_orchestrator.ts` | 接入 Tool Resolver |
|
||
| `packages/backend/src/modules/netaclaw/service/crew_delegate.ts` | 接入 Tool Resolver |
|
||
| `packages/backend/src/modules/netaclaw/runtime/prompt_builder.ts` | 接入 resolved tool names + prompt hints |
|
||
| `packages/backend/src/modules/netaclaw/runtime/prompt_guidance.ts` | 支持 tool prompt hint 注入 |
|
||
| `packages/backend/src/modules/netaclaw/service/skill_context.ts` | 改为消费 resolver 输出的 builtin tool names |
|
||
| `packages/backend/src/modules/netaclaw/controller/agent.ts` | previewPrompt 接入 resolver |
|
||
| `packages/frontend/src/modules/agent/config.ts` | 新增 Tool 管理菜单 |
|
||
| `packages/frontend/src/modules/agent/views/agent-edit.vue` | 新增“工具配置”Tab |
|
||
| `packages/frontend/src/modules/agent/types/index.d.ts` | 扩展 Agent 类型定义 |
|
||
|
||
---
|
||
|
||
## 三、数据库实施
|
||
|
||
## Task 1: 新增 Tool 治理表
|
||
|
||
**Files:**
|
||
- Create: `packages/backend/src/modules/netaclaw/entity/tool.ts`
|
||
- Modify: `packages/backend/src/entities.ts`
|
||
|
||
- [ ] **Step 1: 创建 `tool.ts` Entity**
|
||
|
||
```typescript
|
||
// packages/backend/src/modules/netaclaw/entity/tool.ts
|
||
import { BaseEntity } from '../../base/entity/base.js';
|
||
import { Column, Entity, Index } from 'typeorm';
|
||
|
||
@Entity('netaclaw_tool')
|
||
export class NetaClawToolEntity extends BaseEntity {
|
||
@Index({ unique: true })
|
||
@Column({ comment: 'Tool 名称', length: 100 })
|
||
name: string;
|
||
|
||
@Column({ comment: '展示名', length: 200, nullable: true })
|
||
label: string;
|
||
|
||
@Index()
|
||
@Column({ comment: '所属 toolset', length: 50 })
|
||
toolset: string;
|
||
|
||
@Column({ comment: '描述', type: 'text', nullable: true })
|
||
description: string;
|
||
|
||
@Column({ comment: '可见性', length: 20, nullable: true })
|
||
visibility: string;
|
||
|
||
@Column({ comment: '能力要求', length: 20, nullable: true })
|
||
capability: string;
|
||
|
||
@Index()
|
||
@Column({ comment: '状态 0=禁用 1=启用', default: 1 })
|
||
status: number;
|
||
|
||
@Column({ comment: '是否核心工具', default: 0 })
|
||
isCore: number;
|
||
|
||
@Column({ comment: '是否允许禁用', default: 1 })
|
||
canDisable: number;
|
||
|
||
@Column({ comment: 'Prompt Hint 覆写', type: 'text', nullable: true })
|
||
promptHint: string;
|
||
|
||
@Column({ comment: '排序', default: 0 })
|
||
sort: number;
|
||
|
||
@Column({ comment: '扩展字段', type: 'json', nullable: true })
|
||
extra: Record<string, unknown>;
|
||
}
|
||
```
|
||
|
||
说明:
|
||
|
||
- `toolset/visibility/capability/isCore/canDisable` 属于代码注册镜像字段
|
||
- 后台只允许修改 `label/description/status/promptHint/sort/extra`
|
||
- 不允许将运行时能力语义下放为运营配置
|
||
|
||
- [ ] **Step 2: 在 `entities.ts` 注册 Entity**
|
||
|
||
仿照现有模式添加:
|
||
|
||
```typescript
|
||
import * as entityXX from './modules/netaclaw/entity/tool';
|
||
```
|
||
|
||
并在 `entities` 数组中追加:
|
||
|
||
```typescript
|
||
...Object.values(entityXX),
|
||
```
|
||
|
||
- [ ] **Step 3: 启动后端验证表创建**
|
||
|
||
Run: `cd packages/backend && npx midway-bin dev`
|
||
|
||
Expected:
|
||
|
||
- `netaclaw_tool` 自动建表成功
|
||
|
||
- [ ] **Step 4: 提交**
|
||
|
||
```bash
|
||
git add packages/backend/src/modules/netaclaw/entity/tool.ts packages/backend/src/entities.ts
|
||
git commit -m "feat(netaclaw): add netaclaw_tool entity for global tool governance"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 2: 扩展 Agent 表
|
||
|
||
**Files:**
|
||
- Modify: `packages/backend/src/modules/netaclaw/entity/agent.ts`
|
||
|
||
- [ ] **Step 1: 新增 `toolsets` 和 `tools` 字段**
|
||
|
||
在 `NetaClawAgentEntity` 中新增:
|
||
|
||
```typescript
|
||
@Column({ type: 'json', comment: '启用的 toolset 列表', nullable: true })
|
||
toolsets: string[];
|
||
|
||
@Column({ type: 'json', comment: '工具精细配置', nullable: true })
|
||
tools: {
|
||
disabled?: string[];
|
||
};
|
||
```
|
||
|
||
- [ ] **Step 2: 启动后端验证字段增加**
|
||
|
||
Expected:
|
||
|
||
- `netaclaw_agent` 表新增 `toolsets`、`tools`
|
||
|
||
- [ ] **Step 3: 提交**
|
||
|
||
```bash
|
||
git add packages/backend/src/modules/netaclaw/entity/agent.ts
|
||
git commit -m "feat(netaclaw): extend agent entity with toolsets and tools config"
|
||
```
|
||
|
||
---
|
||
|
||
## 四、后端基础设施实施
|
||
|
||
## Task 3: 扩展 catalog 元数据
|
||
|
||
**Files:**
|
||
- Modify: `packages/backend/src/modules/netaclaw/tools/catalog.ts`
|
||
- Modify: `packages/backend/src/modules/netaclaw/tools/builtin/*.ts`(按需)
|
||
|
||
- [ ] **Step 1: 扩展 `ToolSchema`**
|
||
|
||
将:
|
||
|
||
```typescript
|
||
export interface ToolSchema {
|
||
name: string;
|
||
toolset: string;
|
||
description: string;
|
||
}
|
||
```
|
||
|
||
改为:
|
||
|
||
```typescript
|
||
export interface ToolSchema {
|
||
name: string;
|
||
toolset: string;
|
||
description: string;
|
||
visibility?: 'internal' | 'tool' | 'skill';
|
||
capability?: 'text' | 'vision' | 'multimodal';
|
||
isCore?: boolean;
|
||
canDisable?: boolean;
|
||
supportsPromptHint?: boolean;
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 2: 增加 catalog 查询方法**
|
||
|
||
新增:
|
||
|
||
```typescript
|
||
export function getAllToolSchemas(): ToolSchema[] { ... }
|
||
export function getToolSchema(name: string): ToolSchema | undefined { ... }
|
||
export function getToolNamesByToolset(toolset: string): string[] { ... }
|
||
```
|
||
|
||
- [ ] **Step 3: 为核心工具补默认元数据**
|
||
|
||
至少给以下工具补齐:
|
||
|
||
- `bash`
|
||
- `read_file`
|
||
- `write_file`
|
||
- `list_dir`
|
||
- `patch`
|
||
- `clarify`
|
||
- `todo`
|
||
|
||
建议规则:
|
||
|
||
- `base` 工具默认 `capability=text`
|
||
- `clarify/todo` 默认 `isCore=1`
|
||
- `todo` 可 `visibility=internal`
|
||
- `clarify` 可 `visibility=tool`
|
||
|
||
- [ ] **Step 4: 预留 `vision` / `document` toolset 常量**
|
||
|
||
不必现在接入 OCR,只需允许这些 toolset 名存在。
|
||
|
||
- [ ] **Step 5: 编译验证**
|
||
|
||
Run: `cd packages/backend && npm run build`
|
||
|
||
- [ ] **Step 6: 提交**
|
||
|
||
```bash
|
||
git add packages/backend/src/modules/netaclaw/tools/catalog.ts packages/backend/src/modules/netaclaw/tools/builtin
|
||
git commit -m "feat(netaclaw): extend tool catalog metadata for governance"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 4: 新增 Tool Registry Service
|
||
|
||
**Files:**
|
||
- Create: `packages/backend/src/modules/netaclaw/service/tool_registry.ts`
|
||
|
||
- [ ] **Step 1: 创建 Service**
|
||
|
||
职责:
|
||
|
||
1. 读取 catalog 全量工具
|
||
2. 同步到 `netaclaw_tool`
|
||
3. 分页查询
|
||
4. 返回 Agent 配置可选工具
|
||
|
||
建议结构:
|
||
|
||
```typescript
|
||
@Provide()
|
||
@Scope(ScopeEnum.Singleton)
|
||
export class NetaClawToolRegistryService {
|
||
@InjectEntityModel(NetaClawToolEntity)
|
||
toolRepo: Repository<NetaClawToolEntity>;
|
||
|
||
async syncCatalogToDb() { ... }
|
||
async page(params) { ... }
|
||
async info(id: number) { ... }
|
||
async update(data) { ... }
|
||
async all() { ... }
|
||
async listForAgentConfig() { ... }
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 2: 实现 `syncCatalogToDb()`**
|
||
|
||
逻辑:
|
||
|
||
1. 读取 `getAllToolSchemas()`
|
||
2. DB 无记录则插入
|
||
3. DB 已有记录则保留人工字段,仅补齐缺失元数据
|
||
4. catalog 中不存在但 DB 中存在的记录不物理删除
|
||
|
||
启动策略:
|
||
|
||
- 后端启动时自动执行一次幂等 `syncCatalogToDb()`
|
||
- `/admin/netaclaw/tool/sync` 仅作为人工刷新入口
|
||
- 不允许把首屏正确性依赖在手工点击同步按钮上
|
||
|
||
默认回填规则:
|
||
|
||
- `label = name`
|
||
- `status = 1`
|
||
- `capability = schema.capability ?? 'text'`
|
||
- `visibility = schema.visibility ?? 'tool'`
|
||
- `isCore = schema.isCore ? 1 : 0`
|
||
- `canDisable = schema.canDisable ?? (schema.isCore ? 0 : 1)`
|
||
|
||
- [ ] **Step 3: 实现 `update()` 的保护逻辑**
|
||
|
||
要求:
|
||
|
||
- `isCore=1 && canDisable=0` 时,禁止将 `status` 改为 0
|
||
- `name/toolset/visibility/capability/isCore/canDisable` 默认不允许后台修改
|
||
- 若 `supportsPromptHint !== true`,则禁止写入 `promptHint`
|
||
|
||
- [ ] **Step 4: 编译验证**
|
||
|
||
- [ ] **Step 5: 提交**
|
||
|
||
```bash
|
||
git add packages/backend/src/modules/netaclaw/service/tool_registry.ts
|
||
git commit -m "feat(netaclaw): add tool registry service for catalog-db sync"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 5: 新增 Tool Resolver Service
|
||
|
||
**Files:**
|
||
- Create: `packages/backend/src/modules/netaclaw/service/tool_resolver.ts`
|
||
|
||
- [ ] **Step 1: 创建解析接口**
|
||
|
||
```typescript
|
||
interface ResolveToolParams {
|
||
agent: NetaClawAgentEntity | null;
|
||
modelCapability?: 'text' | 'vision' | 'multimodal';
|
||
memoryEnabled?: boolean;
|
||
hasSkills?: boolean;
|
||
crewRole?: 'master' | 'sub';
|
||
}
|
||
|
||
interface ResolveToolResult {
|
||
tools: AnyAgentTool[];
|
||
toolNames: string[];
|
||
builtinToolNames: string[];
|
||
toolPromptHints: Record<string, string>;
|
||
disabledReasons: Array<{ name: string; reason: string }>;
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 2: 实现 toolset 展开逻辑**
|
||
|
||
默认规则:
|
||
|
||
1. 老 Agent 无 `toolsets` 时:
|
||
- 使用 `TOOLSET_DEFAULTS`
|
||
2. 有 `toolsets` 时:
|
||
- 按 `toolsets` 从 catalog 展开
|
||
3. 再剔除 `tools.disabled`
|
||
|
||
- [ ] **Step 3: 实现全局 Tool 配置过滤**
|
||
|
||
从 `netaclaw_tool` 查询配置,过滤:
|
||
|
||
- `status=0`
|
||
- 不满足场景约束
|
||
|
||
- [ ] **Step 4: 实现 capability 过滤**
|
||
|
||
统一判断:
|
||
|
||
```typescript
|
||
function matchCapability(toolCap: string, modelCap?: string): boolean { ... }
|
||
```
|
||
|
||
规则:
|
||
|
||
- `text` 工具允许任意模型
|
||
- `vision` 工具要求 `vision|multimodal`
|
||
- `multimodal` 工具要求 `multimodal`
|
||
|
||
- [ ] **Step 4.1: 补齐模型能力来源**
|
||
|
||
要求:
|
||
|
||
- 优先在 `model_channel.ts` 的运行时解析接口中直接返回 `capability`
|
||
- `agent_executor.ts` / `gateway/server.ts` / `crew_*` 禁止各自重复解析模型能力
|
||
- 若 Agent 未绑定 channel,需定义统一 fallback:
|
||
- 显式配置 capability 时用显式值
|
||
- 未配置时按 `text` 处理,并在 disabledReasons 中保留解释能力
|
||
|
||
- [ ] **Step 5: 组装运行时工具实例**
|
||
|
||
这里不要复刻 Hermes 的 handler registry。
|
||
|
||
Neta 应继续按现有工厂方式组装:
|
||
|
||
- 静态工具:
|
||
- `bashTool`
|
||
- `readFileTool`
|
||
- `writeFileTool`
|
||
- `listDirTool`
|
||
- `patchTool`
|
||
- `clarifyTool`
|
||
- Memory 工具:
|
||
- 在 `memoryEnabled` 时工厂创建
|
||
- Skill 工具:
|
||
- 在 `hasSkills` 时工厂创建
|
||
- Crew 工具:
|
||
- 在 `crewRole=master` 时工厂创建
|
||
|
||
- [ ] **Step 5.1: 输出 `builtinToolNames` 给 skill context**
|
||
|
||
要求:
|
||
|
||
- resolver 需要区分“所有注入工具名”和“提供给 skill system 的 builtin tool names”
|
||
- `buildSkillContext()` 不再使用硬编码 builtin 列表
|
||
|
||
- [ ] **Step 6: 输出 `toolPromptHints`**
|
||
|
||
从 `netaclaw_tool.promptHint` 收集:
|
||
|
||
```typescript
|
||
{
|
||
patch: '...',
|
||
clarify: '...'
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 7: 编译验证**
|
||
|
||
- [ ] **Step 8: 提交**
|
||
|
||
```bash
|
||
git add packages/backend/src/modules/netaclaw/service/tool_resolver.ts
|
||
git commit -m "feat(netaclaw): add tool resolver for runtime tool governance"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 6: 新增 Tool 管理 Controller
|
||
|
||
**Files:**
|
||
- Create: `packages/backend/src/modules/netaclaw/controller/admin/tool.ts`
|
||
|
||
- [ ] **Step 1: 创建 Admin Controller**
|
||
|
||
接口:
|
||
|
||
- `/admin/netaclaw/tool/page`
|
||
- `/admin/netaclaw/tool/info`
|
||
- `/admin/netaclaw/tool/update`
|
||
- `/admin/netaclaw/tool/all`
|
||
- `/admin/netaclaw/tool/sync`
|
||
- `/admin/netaclaw/tool/forAgent`
|
||
|
||
- [ ] **Step 2: `sync` 接口调用 `syncCatalogToDb()`**
|
||
|
||
建议首次进入页面前手动调用一次,也可在服务启动时懒同步。
|
||
|
||
- [ ] **Step 3: 启动后端验证接口可达**
|
||
|
||
- [ ] **Step 4: 提交**
|
||
|
||
```bash
|
||
git add packages/backend/src/modules/netaclaw/controller/admin/tool.ts
|
||
git commit -m "feat(netaclaw): add admin tool controller"
|
||
```
|
||
|
||
---
|
||
|
||
## 五、运行时接入实施
|
||
|
||
## Task 7: 改造 agent_executor.ts
|
||
|
||
**Files:**
|
||
- Modify: `packages/backend/src/modules/netaclaw/service/agent_executor.ts`
|
||
|
||
- [ ] **Step 1: 注入 `NetaClawToolResolverService`**
|
||
|
||
新增:
|
||
|
||
```typescript
|
||
@Inject()
|
||
toolResolver: NetaClawToolResolverService;
|
||
```
|
||
|
||
- [ ] **Step 2: 删除 `defaultTools` 硬编码依赖**
|
||
|
||
从:
|
||
|
||
```typescript
|
||
private readonly defaultTools: AnyAgentTool[] = [...]
|
||
```
|
||
|
||
迁移为 resolver 统一输出。
|
||
|
||
- [ ] **Step 3: 在解析模型后得到 `modelCapability`**
|
||
|
||
从当前 channel / modelConfig 推导 capability:
|
||
|
||
1. 优先调用 `model_channel.ts` 统一运行时解析接口
|
||
2. 直接拿到 `capability`
|
||
3. 禁止在 executor 内手写重复解析逻辑
|
||
|
||
- [ ] **Step 4: 调用 resolver**
|
||
|
||
```typescript
|
||
const resolvedTools = await this.toolResolver.resolve({
|
||
agent: agentEntity,
|
||
modelCapability,
|
||
memoryEnabled: !!memoryConfig?.enabled,
|
||
hasSkills: !!agentEntity.skills?.length,
|
||
});
|
||
```
|
||
|
||
- [ ] **Step 5: 将 `resolvedTools.builtinToolNames` 传给 `buildSkillContext()`**
|
||
|
||
替换现在的硬编码:
|
||
|
||
```typescript
|
||
const builtinToolNames = ['bash', 'read_file', 'write_file', 'list_dir', 'patch'];
|
||
```
|
||
|
||
-- [ ] **Step 6: 将 `resolvedTools.toolNames` 传给 Prompt Builder**
|
||
|
||
替换现在的:
|
||
|
||
```typescript
|
||
collectAvailableToolNames(...)
|
||
```
|
||
|
||
为:
|
||
|
||
```typescript
|
||
availableToolNames: resolvedTools.toolNames
|
||
```
|
||
|
||
- [ ] **Step 7: 将 `resolvedTools.tools` 传给 runAgent**
|
||
|
||
- [ ] **Step 8: 编译验证**
|
||
|
||
- [ ] **Step 9: 提交**
|
||
|
||
```bash
|
||
git add packages/backend/src/modules/netaclaw/service/agent_executor.ts
|
||
git commit -m "refactor(netaclaw): agent executor uses tool resolver"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 8: 改造 gateway/server.ts
|
||
|
||
**Files:**
|
||
- Modify: `packages/backend/src/modules/netaclaw/gateway/server.ts`
|
||
|
||
- [ ] **Step 1: 注入 Tool Resolver**
|
||
|
||
- [ ] **Step 2: 替换默认工具拼装**
|
||
|
||
要求:
|
||
|
||
- WS 路径与 REST 路径使用相同解析逻辑
|
||
- 不再各自维护工具集合
|
||
|
||
- [ ] **Step 3: Prompt Builder 改用 resolved tool names**
|
||
|
||
- [ ] **Step 4: 编译验证**
|
||
|
||
- [ ] **Step 5: 提交**
|
||
|
||
```bash
|
||
git add packages/backend/src/modules/netaclaw/gateway/server.ts
|
||
git commit -m "refactor(netaclaw): gateway uses tool resolver"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 9: 改造 crew_orchestrator.ts / crew_delegate.ts
|
||
|
||
**Files:**
|
||
- Modify: `packages/backend/src/modules/netaclaw/service/crew_orchestrator.ts`
|
||
- Modify: `packages/backend/src/modules/netaclaw/service/crew_delegate.ts`
|
||
|
||
- [ ] **Step 1: master 场景接入 resolver**
|
||
|
||
`crewRole='master'`
|
||
|
||
- [ ] **Step 2: sub 场景接入 resolver**
|
||
|
||
`crewRole='sub'`
|
||
|
||
- [ ] **Step 3: 验证 `delegate_*` 只在 master 中出现**
|
||
|
||
- [ ] **Step 4: 编译验证**
|
||
|
||
- [ ] **Step 5: 提交**
|
||
|
||
```bash
|
||
git add packages/backend/src/modules/netaclaw/service/crew_orchestrator.ts packages/backend/src/modules/netaclaw/service/crew_delegate.ts
|
||
git commit -m "refactor(netaclaw): crew runtime uses tool resolver"
|
||
```
|
||
|
||
---
|
||
|
||
## 六、Prompt Builder 实施
|
||
|
||
## Task 10: prompt_builder.ts 接入 Tool Prompt Hint
|
||
|
||
**Files:**
|
||
- Modify: `packages/backend/src/modules/netaclaw/runtime/prompt_builder.ts`
|
||
- Modify: `packages/backend/src/modules/netaclaw/runtime/prompt_guidance.ts`
|
||
- Modify: `packages/backend/src/modules/netaclaw/service/skill_context.ts`
|
||
- Modify: `packages/backend/src/modules/netaclaw/controller/agent.ts`
|
||
|
||
- [ ] **Step 1: 扩展 `getToolBehaviorGuidance()`**
|
||
|
||
从:
|
||
|
||
```typescript
|
||
getToolBehaviorGuidance(toolNames: string[])
|
||
```
|
||
|
||
改为:
|
||
|
||
```typescript
|
||
getToolBehaviorGuidance(
|
||
toolNames: string[],
|
||
toolPromptHints?: Record<string, string>
|
||
)
|
||
```
|
||
|
||
逻辑:
|
||
|
||
- 若某 Tool 有 DB `promptHint` 覆写,则优先使用覆写
|
||
- 否则回退默认 guidance
|
||
|
||
- [ ] **Step 2: Prompt Builder 接收 `toolPromptHints`**
|
||
|
||
在 `BuildSystemPromptParams` 中新增:
|
||
|
||
```typescript
|
||
toolPromptHints?: Record<string, string>;
|
||
```
|
||
|
||
- [ ] **Step 3: skill_context 改为消费 resolver 输出**
|
||
|
||
要求:
|
||
|
||
- `buildSkillContext()` 的 builtin tool names 参数由 resolver 提供
|
||
- 不能再保留硬编码 builtin 工具列表
|
||
|
||
- [ ] **Step 4: previewPrompt 接口接入 resolver**
|
||
|
||
让预览接口返回:
|
||
|
||
- `layers`
|
||
- `toolNames`
|
||
- `disabledReasons`
|
||
|
||
这样前端可解释“为什么某工具没有被注入”。
|
||
|
||
- [ ] **Step 5: 编译验证**
|
||
|
||
- [ ] **Step 6: 提交**
|
||
|
||
```bash
|
||
git add packages/backend/src/modules/netaclaw/runtime/prompt_builder.ts packages/backend/src/modules/netaclaw/runtime/prompt_guidance.ts packages/backend/src/modules/netaclaw/service/skill_context.ts packages/backend/src/modules/netaclaw/controller/agent.ts
|
||
git commit -m "feat(netaclaw): prompt builder supports resolved tools and prompt hints"
|
||
```
|
||
|
||
---
|
||
|
||
## 七、前端实施
|
||
|
||
## Task 11: 新增 Tool 管理菜单
|
||
|
||
**Files:**
|
||
- Modify: `packages/frontend/src/modules/agent/config.ts`
|
||
|
||
- [ ] **Step 1: 在 Skill 管理上方插入路由**
|
||
|
||
```typescript
|
||
{
|
||
path: '/agent/tools',
|
||
meta: { label: 'Tool 管理' },
|
||
component: () => import('./views/tools.vue')
|
||
},
|
||
```
|
||
|
||
- [ ] **Step 2: 本地验证菜单顺序**
|
||
|
||
- [ ] **Step 3: 提交**
|
||
|
||
```bash
|
||
git add packages/frontend/src/modules/agent/config.ts
|
||
git commit -m "feat(frontend): add tool management route"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 12: 实现 Tool 管理页
|
||
|
||
**Files:**
|
||
- Create: `packages/frontend/src/modules/agent/views/tools.vue`
|
||
|
||
- [ ] **Step 1: 创建页面骨架**
|
||
|
||
包含:
|
||
|
||
- 筛选区
|
||
- 表格区
|
||
- 编辑抽屉
|
||
- 同步按钮
|
||
|
||
- [ ] **Step 2: 对接接口**
|
||
|
||
使用:
|
||
|
||
- `/admin/netaclaw/tool/page`
|
||
- `/admin/netaclaw/tool/update`
|
||
- `/admin/netaclaw/tool/sync`
|
||
|
||
- [ ] **Step 3: 页面字段**
|
||
|
||
表格列:
|
||
|
||
- name
|
||
- label
|
||
- toolset
|
||
- capability
|
||
- visibility
|
||
- isCore
|
||
- status
|
||
- promptHint 状态
|
||
|
||
- [ ] **Step 4: 编辑抽屉**
|
||
|
||
允许编辑:
|
||
|
||
- label
|
||
- description
|
||
- status
|
||
- promptHint
|
||
- sort
|
||
|
||
只读:
|
||
|
||
- name
|
||
- toolset
|
||
- capability
|
||
- visibility
|
||
- isCore
|
||
- canDisable
|
||
|
||
- [ ] **Step 5: 对核心工具加禁用保护**
|
||
|
||
前端禁用开关,后端再次校验。
|
||
|
||
- [ ] **Step 6: 浏览器验证**
|
||
|
||
验证:
|
||
|
||
- 页面可打开
|
||
- 同步后出现工具列表
|
||
- 可编辑提示词
|
||
- 核心工具不能关闭
|
||
|
||
- [ ] **Step 7: 提交**
|
||
|
||
```bash
|
||
git add packages/frontend/src/modules/agent/views/tools.vue
|
||
git commit -m "feat(frontend): add tool management page"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 13: 扩展前端 Agent 类型
|
||
|
||
**Files:**
|
||
- Modify: `packages/frontend/src/modules/agent/types/index.d.ts`
|
||
|
||
- [ ] **Step 1: 为 AgentInfo 增加字段**
|
||
|
||
新增:
|
||
|
||
```typescript
|
||
toolsets?: string[];
|
||
tools?: {
|
||
disabled?: string[];
|
||
};
|
||
```
|
||
|
||
- [ ] **Step 2: 编译验证**
|
||
|
||
- [ ] **Step 3: 提交**
|
||
|
||
```bash
|
||
git add packages/frontend/src/modules/agent/types/index.d.ts
|
||
git commit -m "feat(frontend): extend agent types with toolsets and tools"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 14: 改造 agent-edit.vue
|
||
|
||
**Files:**
|
||
- Modify: `packages/frontend/src/modules/agent/views/agent-edit.vue`
|
||
|
||
- [ ] **Step 1: 新增“工具配置”Tab**
|
||
|
||
位置:
|
||
|
||
- 与 `Skill配置` 平级
|
||
|
||
- [ ] **Step 2: 新增 toolset 多选区**
|
||
|
||
数据源:
|
||
|
||
- `/admin/netaclaw/tool/forAgent`
|
||
|
||
从接口中提取唯一 toolset 列表。
|
||
|
||
- [ ] **Step 3: 新增工具精细控制双栏**
|
||
|
||
展示:
|
||
|
||
- 可用工具
|
||
- 已禁用覆盖
|
||
|
||
最小实现建议:
|
||
|
||
- 左栏: 可选工具
|
||
- 右栏: 已禁用工具
|
||
|
||
通过 `toolsets` 先决定默认启用范围,`tools.disabled` 做剔除。
|
||
|
||
- [ ] **Step 4: loadAgent 回填**
|
||
|
||
回填:
|
||
|
||
- `toolsets`
|
||
- `tools.disabled`
|
||
|
||
- [ ] **Step 5: handleSave 提交**
|
||
|
||
请求体追加:
|
||
|
||
```typescript
|
||
toolsets: form.value.toolsets,
|
||
tools: form.value.tools,
|
||
```
|
||
|
||
- [ ] **Step 6: Prompt 预览展示被过滤工具**
|
||
|
||
若后端 previewPrompt 返回:
|
||
|
||
- `toolNames`
|
||
- `disabledReasons`
|
||
|
||
则页面增加一个提示区域显示。
|
||
|
||
- [ ] **Step 7: 浏览器验证**
|
||
|
||
验证:
|
||
|
||
- 可勾选 toolsets
|
||
- 可禁用单工具
|
||
- 保存后再次打开可回填
|
||
- preview 可看到过滤原因
|
||
|
||
- [ ] **Step 8: 提交**
|
||
|
||
```bash
|
||
git add packages/frontend/src/modules/agent/views/agent-edit.vue
|
||
git commit -m "feat(frontend): add agent toolsets and tools configuration tab"
|
||
```
|
||
|
||
---
|
||
|
||
## 八、联调与验收
|
||
|
||
## Task 15: 数据同步验证
|
||
|
||
- [ ] **Step 1: 启动后端**
|
||
|
||
- [ ] **Step 2: 调用 `/admin/netaclaw/tool/sync`**
|
||
|
||
Expected:
|
||
|
||
- `netaclaw_tool` 中出现 catalog 全量工具
|
||
|
||
- [ ] **Step 3: 检查核心字段**
|
||
|
||
至少检查:
|
||
|
||
- `todo`
|
||
- `clarify`
|
||
- `bash`
|
||
- `read_file`
|
||
- `patch`
|
||
|
||
---
|
||
|
||
## Task 16: Agent 工具授权联调
|
||
|
||
- [ ] **Step 1: 新建一个 Agent**
|
||
|
||
配置:
|
||
|
||
- `toolsets = ['base', 'planning']`
|
||
- `tools.disabled = ['bash']`
|
||
|
||
- [ ] **Step 2: 预览 Prompt**
|
||
|
||
Expected:
|
||
|
||
- `bash` 不在 toolNames 中
|
||
- `read_file/write_file/list_dir/patch/todo` 仍在
|
||
|
||
- [ ] **Step 3: 发起真实对话**
|
||
|
||
构造任务要求执行 bash。
|
||
|
||
Expected:
|
||
|
||
- 模型看不到 `bash`
|
||
- 不应产生 bash tool call
|
||
|
||
---
|
||
|
||
## Task 17: capability 过滤联调
|
||
|
||
- [ ] **Step 1: 准备一个 text 模型 Agent**
|
||
|
||
- [ ] **Step 2: 准备一个代码注册层声明 `capability=vision` 的测试 Tool**
|
||
|
||
要求:
|
||
|
||
- 不通过后台或 DB 手工修改 `capability`
|
||
- 若暂时没有真实视觉工具,可在本地临时注册一个测试 Tool 用于联调
|
||
|
||
- [ ] **Step 3: 预览 Prompt**
|
||
|
||
Expected:
|
||
|
||
- 该工具被过滤
|
||
- disabledReasons 中出现 `capability_mismatch`
|
||
|
||
---
|
||
|
||
## Task 18: Tool Prompt Hint 联调
|
||
|
||
- [ ] **Step 1: 在 Tool 管理页给 `patch` 写入 promptHint**
|
||
|
||
- [ ] **Step 2: 预览 Prompt**
|
||
|
||
Expected:
|
||
|
||
- Layer 4 中优先出现 DB 覆写内容,而不是默认 guidance
|
||
|
||
---
|
||
|
||
## 九、验收标准
|
||
|
||
以下全部满足才算完成:
|
||
|
||
### 数据库
|
||
|
||
- `netaclaw_tool` 表存在
|
||
- `netaclaw_agent` 新增 `toolsets/tools`
|
||
|
||
### 后端
|
||
|
||
- catalog 可同步到 DB
|
||
- Tool Resolver 成为统一事实来源
|
||
- `model_channel.ts` 统一提供运行时 `capability`
|
||
- REST/WS/Crew 三条路径都走 resolver
|
||
- skill_context 消费 resolver 输出的 builtin tool names
|
||
- previewPrompt 可返回 toolNames 和 disabledReasons
|
||
|
||
### 前端
|
||
|
||
- 出现 Tool 管理菜单与页面
|
||
- Tool 管理页可编辑全局状态和 promptHint
|
||
- Agent 编辑页可配置 toolsets 与单工具覆盖
|
||
- Prompt 预览能看到工具生效与过滤原因
|
||
|
||
### 行为
|
||
|
||
- 全局禁用的工具不会被注入
|
||
- Agent 禁用的工具不会被注入
|
||
- capability 不满足的工具不会被注入
|
||
- 核心不可禁用工具不能被后台关闭
|
||
|
||
---
|
||
|
||
## 十、回滚预案
|
||
|
||
若某阶段出问题,按以下顺序回滚。
|
||
|
||
### 1. 页面级回滚
|
||
|
||
- 隐藏 `/agent/tools`
|
||
- 隐藏 Agent 编辑页中的“工具配置”Tab
|
||
|
||
不影响现有 Agent 基本能力。
|
||
|
||
### 2. 运行时回滚
|
||
|
||
若 resolver 逻辑异常,可临时回退:
|
||
|
||
- `agent_executor.ts` 恢复 `defaultTools`
|
||
- `gateway/server.ts` 恢复原工具拼装
|
||
|
||
数据库结构可保留,不影响运行。
|
||
|
||
### 3. 数据级回滚
|
||
|
||
- `netaclaw_tool` 表可保留
|
||
- `toolsets/tools` 字段即使存在,也不影响老代码
|
||
|
||
因此本方案具备较好的渐进式上线条件。
|
||
|
||
---
|
||
|
||
## 十一、实施顺序建议
|
||
|
||
建议严格按以下顺序推进:
|
||
|
||
1. 数据库实体
|
||
2. catalog 扩展
|
||
3. tool_registry
|
||
4. tool_resolver
|
||
5. model capability 统一解析链路
|
||
6. agent_executor / gateway / crew 接入
|
||
7. prompt_builder / skill_context 接入
|
||
7. Tool 管理页
|
||
8. Agent 编辑页工具配置
|
||
9. 联调验收
|
||
|
||
不要先做前端页面。否则会出现“配置存在但运行时无效”的假闭环。
|
||
|
||
---
|
||
|
||
## 十二、后续 OCR 接入说明
|
||
|
||
当本实施完成后,接入 OCR 的工作将降维为一项普通功能开发:
|
||
|
||
1. 在 `catalog.ts` 注册 `vision_ocr`
|
||
2. 设置:
|
||
- `toolset='vision'`
|
||
- `capability='vision'`
|
||
3. 在 Tool 管理页全局启用
|
||
4. 在 Agent 工具配置中勾选
|
||
5. 由 resolver 自动判断模型是否支持
|
||
|
||
也就是说,这份实施文档完成后,OCR 不再是架构问题,而只是业务工具实现问题。
|