feat: 实现 Tool Search Tool 动态工具发现机制

- 新增 ToolRegistry 工具注册表,支持核心工具和延迟加载工具分离
- 新增 tool_search 元工具,支持关键词搜索发现可用工具
- 新增基于关键词的搜索算法,按相关度评分排序
- 为所有工具添加 metadata(分类、关键词、延迟加载标识)
- 修改 Agent 支持动态工具注入,tool_search 结果自动添加到可用工具
- 核心工具(tool_search, bash)始终加载,其他工具按需发现
This commit is contained in:
2025-12-10 19:51:25 +08:00
parent e435b2f8f8
commit bc1ece3dad
19 changed files with 569 additions and 66 deletions
+10 -2
View File
@@ -1,6 +1,7 @@
import * as fs from 'fs/promises';
import * as path from 'path';
import type { Tool, ToolResult } from '../../types/index.js';
import type { ToolResult } from '../../types/index.js';
import type { ToolWithMetadata } from '../types.js';
import { loadDescription } from '../load_description.js';
import { getPermissionManager } from '../../permission/index.js';
@@ -18,9 +19,16 @@ async function copyRecursive(source: string, dest: string): Promise<void> {
}
}
export const copyFileTool: Tool = {
export const copyFileTool: ToolWithMetadata = {
name: 'copy_file',
description: loadDescription('copy_file'),
metadata: {
name: 'copy_file',
category: 'filesystem',
description: '复制文件或目录',
keywords: ['copy', 'file', 'cp', 'duplicate', '复制', '文件', '拷贝'],
deferLoading: true,
},
parameters: {
source: {
type: 'string',
+10 -2
View File
@@ -1,12 +1,20 @@
import * as fs from 'fs/promises';
import * as path from 'path';
import type { Tool, ToolResult } from '../../types/index.js';
import type { ToolResult } from '../../types/index.js';
import type { ToolWithMetadata } from '../types.js';
import { loadDescription } from '../load_description.js';
import { getPermissionManager } from '../../permission/index.js';
export const createDirectoryTool: Tool = {
export const createDirectoryTool: ToolWithMetadata = {
name: 'create_directory',
description: loadDescription('create_directory'),
metadata: {
name: 'create_directory',
category: 'filesystem',
description: '创建目录',
keywords: ['create', 'directory', 'mkdir', 'folder', 'new', '创建', '目录', '文件夹', '新建'],
deferLoading: true,
},
parameters: {
path: {
type: 'string',
+10 -2
View File
@@ -1,12 +1,20 @@
import * as fs from 'fs/promises';
import * as path from 'path';
import type { Tool, ToolResult } from '../../types/index.js';
import type { ToolResult } from '../../types/index.js';
import type { ToolWithMetadata } from '../types.js';
import { loadDescription } from '../load_description.js';
import { getPermissionManager } from '../../permission/index.js';
export const deleteFileTool: Tool = {
export const deleteFileTool: ToolWithMetadata = {
name: 'delete_file',
description: loadDescription('delete_file'),
metadata: {
name: 'delete_file',
category: 'filesystem',
description: '删除文件或目录',
keywords: ['delete', 'remove', 'file', 'rm', '删除', '移除', '文件'],
deferLoading: true,
},
parameters: {
path: {
type: 'string',
+10 -2
View File
@@ -1,12 +1,20 @@
import * as fs from 'fs/promises';
import * as path from 'path';
import type { Tool, ToolResult } from '../../types/index.js';
import type { ToolResult } from '../../types/index.js';
import type { ToolWithMetadata } from '../types.js';
import { loadDescription } from '../load_description.js';
import { getPermissionManager } from '../../permission/index.js';
export const editFileTool: Tool = {
export const editFileTool: ToolWithMetadata = {
name: 'edit_file',
description: loadDescription('edit_file'),
metadata: {
name: 'edit_file',
category: 'filesystem',
description: '编辑文件内容(查找替换)',
keywords: ['edit', 'file', 'replace', 'modify', 'change', 'update', '编辑', '文件', '替换', '修改', '更新'],
deferLoading: true,
},
parameters: {
path: {
type: 'string',
+10 -2
View File
@@ -1,6 +1,7 @@
import * as fs from 'fs/promises';
import * as path from 'path';
import type { Tool, ToolResult } from '../../types/index.js';
import type { ToolResult } from '../../types/index.js';
import type { ToolWithMetadata } from '../types.js';
import { loadDescription } from '../load_description.js';
import { getPermissionManager } from '../../permission/index.js';
@@ -45,9 +46,16 @@ function formatPermissions(mode: number): string {
return `${fileType?.[1] || 'unknown'} (${perms})`;
}
export const getFileInfoTool: Tool = {
export const getFileInfoTool: ToolWithMetadata = {
name: 'get_file_info',
description: loadDescription('get_file_info'),
metadata: {
name: 'get_file_info',
category: 'filesystem',
description: '获取文件元信息',
keywords: ['file', 'info', 'stat', 'size', 'permission', 'metadata', '文件', '信息', '大小', '权限', '属性'],
deferLoading: true,
},
parameters: {
path: {
type: 'string',
+10 -2
View File
@@ -1,6 +1,7 @@
import * as fs from 'fs/promises';
import * as path from 'path';
import type { Tool, ToolResult } from '../../types/index.js';
import type { ToolResult } from '../../types/index.js';
import type { ToolWithMetadata } from '../types.js';
import { loadDescription } from '../load_description.js';
import { getPermissionManager } from '../../permission/index.js';
@@ -10,9 +11,16 @@ interface GrepMatch {
content: string;
}
export const grepContentTool: Tool = {
export const grepContentTool: ToolWithMetadata = {
name: 'grep_content',
description: loadDescription('grep_content'),
metadata: {
name: 'grep_content',
category: 'filesystem',
description: '在文件内容中搜索文本',
keywords: ['grep', 'search', 'content', 'text', 'find', 'regex', '搜索', '内容', '文本', '查找', '正则'],
deferLoading: true,
},
parameters: {
directory: {
type: 'string',
+10 -2
View File
@@ -1,12 +1,20 @@
import * as fs from 'fs/promises';
import * as path from 'path';
import type { Tool, ToolResult } from '../../types/index.js';
import type { ToolResult } from '../../types/index.js';
import type { ToolWithMetadata } from '../types.js';
import { loadDescription } from '../load_description.js';
import { getPermissionManager } from '../../permission/index.js';
export const listDirTool: Tool = {
export const listDirTool: ToolWithMetadata = {
name: 'list_directory',
description: loadDescription('list_directory'),
metadata: {
name: 'list_directory',
category: 'filesystem',
description: '列出目录内容',
keywords: ['list', 'directory', 'ls', 'dir', 'folder', '列出', '目录', '文件夹', '查看'],
deferLoading: true,
},
parameters: {
path: {
type: 'string',
+10 -2
View File
@@ -1,12 +1,20 @@
import * as fs from 'fs/promises';
import * as path from 'path';
import type { Tool, ToolResult } from '../../types/index.js';
import type { ToolResult } from '../../types/index.js';
import type { ToolWithMetadata } from '../types.js';
import { loadDescription } from '../load_description.js';
import { getPermissionManager } from '../../permission/index.js';
export const moveFileTool: Tool = {
export const moveFileTool: ToolWithMetadata = {
name: 'move_file',
description: loadDescription('move_file'),
metadata: {
name: 'move_file',
category: 'filesystem',
description: '移动或重命名文件/目录',
keywords: ['move', 'rename', 'file', 'mv', '移动', '重命名', '文件'],
deferLoading: true,
},
parameters: {
source: {
type: 'string',
+10 -2
View File
@@ -1,12 +1,20 @@
import * as fs from 'fs/promises';
import * as path from 'path';
import type { Tool, ToolResult } from '../../types/index.js';
import type { ToolResult } from '../../types/index.js';
import type { ToolWithMetadata } from '../types.js';
import { loadDescription } from '../load_description.js';
import { getPermissionManager } from '../../permission/index.js';
export const readFileTool: Tool = {
export const readFileTool: ToolWithMetadata = {
name: 'read_file',
description: loadDescription('read_file'),
metadata: {
name: 'read_file',
category: 'filesystem',
description: '读取文件内容',
keywords: ['read', 'file', 'content', 'cat', 'view', 'open', '读取', '文件', '内容', '查看', '打开'],
deferLoading: true,
},
parameters: {
path: {
type: 'string',
+10 -2
View File
@@ -1,12 +1,20 @@
import * as fs from 'fs/promises';
import * as path from 'path';
import type { Tool, ToolResult } from '../../types/index.js';
import type { ToolResult } from '../../types/index.js';
import type { ToolWithMetadata } from '../types.js';
import { loadDescription } from '../load_description.js';
import { getPermissionManager } from '../../permission/index.js';
export const searchFilesTool: Tool = {
export const searchFilesTool: ToolWithMetadata = {
name: 'search_files',
description: loadDescription('search_files'),
metadata: {
name: 'search_files',
category: 'filesystem',
description: '按文件名搜索文件',
keywords: ['search', 'file', 'find', 'glob', 'pattern', '搜索', '文件', '查找', '匹配'],
deferLoading: true,
},
parameters: {
directory: {
type: 'string',
+10 -2
View File
@@ -1,12 +1,20 @@
import * as fs from 'fs/promises';
import * as path from 'path';
import type { Tool, ToolResult } from '../../types/index.js';
import type { ToolResult } from '../../types/index.js';
import type { ToolWithMetadata } from '../types.js';
import { loadDescription } from '../load_description.js';
import { getPermissionManager } from '../../permission/index.js';
export const writeFileTool: Tool = {
export const writeFileTool: ToolWithMetadata = {
name: 'write_file',
description: loadDescription('write_file'),
metadata: {
name: 'write_file',
category: 'filesystem',
description: '写入文件内容',
keywords: ['write', 'file', 'save', 'create', '写入', '文件', '保存', '创建', '新建'],
deferLoading: true,
},
parameters: {
path: {
type: 'string',