feat: 优化鲁班角色并完善ToolSandbox工具开发体系

## 鲁班角色优化
- 新增tool-best-practices知识模块:工具设计最佳实践、性能优化、安全防护
- 新增dpml-tool-tagging知识模块:DPML工具标签四组件架构精通
- 增强craftsmanship思维模式:现代工具特征完善
- 资源迁移到包级别:支持跨项目共享

## ToolSandbox架构完善
- 实现ToolSandbox类:支持@tool://协议的三阶段执行流程
- 优化依赖管理:getDependencies()接口标准化
- 完善UserProtocol:支持@user://沙箱目录访问
- 增强工具发现:FilePatternDiscovery支持多种文件模式

## 工具生态建设
- 添加tool.tag.md:DPML工具标签框架完整定义
- 重构ToolInterface:统一getDependencies()接口规范
- 优化ToolExecutor:集成ToolSandbox执行流程
- 更新注册表:29个资源完整注册发现

## 技术架构改进
- pnpm依赖集成:自动化沙箱环境管理
- 协议系统完善:@tool://和@user://协议标准化
- 资源结构统一:包级别和项目级别一致性
- 开发流程标准化:从需求分析到质量保证的完整工作流

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
sean
2025-06-28 19:42:16 +08:00
parent 5f9fa4c92c
commit eea46a8ee1
20 changed files with 3250 additions and 536 deletions

517
src/lib/tool/ToolSandbox.js Normal file
View File

@ -0,0 +1,517 @@
const path = require('path');
const fs = require('fs').promises;
const { spawn } = require('child_process');
const vm = require('vm');
/**
* ToolSandbox - 工具沙箱环境管理器
*
* 基于现有协议系统的工具执行环境,支持:
* - @tool:// 协议定位工具
* - @user://.promptx/toolbox 沙箱隔离
* - 自动依赖管理
* - 可复用的执行环境
*/
class ToolSandbox {
constructor(toolReference, options = {}) {
this.toolReference = toolReference; // @tool://url-validator
this.resourceManager = null; // ResourceManager实例
this.toolId = null; // 工具ID如 url-validator
this.toolContent = null; // 工具文件内容
this.toolInstance = null; // 工具实例
this.dependencies = []; // 依赖列表
this.sandboxPath = null; // 沙箱目录路径
this.sandboxContext = null; // VM沙箱上下文
// 状态标志
this.isAnalyzed = false;
this.isPrepared = false;
// 配置选项
this.options = {
timeout: 30000,
enableDependencyInstall: true,
forceReinstall: false,
...options
};
}
/**
* 设置ResourceManager实例
* @param {ResourceManager} resourceManager
*/
setResourceManager(resourceManager) {
this.resourceManager = resourceManager;
}
/**
* 分析工具:加载工具内容,提取元信息和依赖
* @returns {Promise<Object>} 分析结果
*/
async analyze() {
if (this.isAnalyzed) {
return this.getAnalysisResult();
}
if (!this.resourceManager) {
throw new Error('ResourceManager not set. Call setResourceManager() first.');
}
try {
// 1. 解析工具引用提取工具ID
this.toolId = this.extractToolId(this.toolReference);
// 2. 通过协议系统加载工具
const toolResult = await this.resourceManager.loadResource(this.toolReference);
if (!toolResult.success) {
// 调试:尝试不同的查找方式
console.log(`🔍 调试:尝试查找工具 ${this.toolReference}`);
const directLookup = this.resourceManager.registryData.findResourceById(`tool:${this.toolId}`, 'tool');
console.log(` - 直接查找 tool:${this.toolId}: ${directLookup ? '找到' : '未找到'}`);
throw new Error(`Failed to load tool: ${toolResult.error.message}`);
}
this.toolContent = toolResult.content;
// 3. 设置沙箱路径
this.sandboxPath = await this.resolveSandboxPath();
// 4. 在基础沙箱中分析工具
await this.analyzeToolInSandbox();
this.isAnalyzed = true;
return this.getAnalysisResult();
} catch (error) {
throw new Error(`Tool analysis failed: ${error.message}`);
}
}
/**
* 准备依赖:安装依赖,准备执行环境
* @returns {Promise<Object>} 准备结果
*/
async prepareDependencies() {
if (!this.isAnalyzed) {
await this.analyze();
}
if (this.isPrepared && !this.options.forceReinstall) {
return { success: true, message: 'Dependencies already prepared' };
}
try {
// 1. 确保沙箱目录存在
await this.ensureSandboxDirectory();
// 2. 如果有依赖,安装它们
if (this.dependencies.length > 0) {
await this.installDependencies();
}
// 3. 创建执行沙箱环境
await this.createExecutionSandbox();
this.isPrepared = true;
return {
success: true,
sandboxPath: this.sandboxPath,
dependencies: this.dependencies
};
} catch (error) {
throw new Error(`Dependency preparation failed: ${error.message}`);
}
}
/**
* 执行工具
* @param {Object} parameters - 工具参数
* @returns {Promise<Object>} 执行结果
*/
async execute(parameters = {}) {
if (!this.isPrepared) {
await this.prepareDependencies();
}
try {
// 1. 参数验证
await this.validateParameters(parameters);
// 2. 在沙箱中执行工具
const result = await this.executeInSandbox(parameters);
return {
success: true,
data: result,
metadata: {
toolId: this.toolId,
sandboxPath: this.sandboxPath,
executionTime: Date.now()
}
};
} catch (error) {
return {
success: false,
error: {
message: error.message,
stack: error.stack
},
metadata: {
toolId: this.toolId,
sandboxPath: this.sandboxPath
}
};
}
}
/**
* 提取工具ID
* @param {string} toolReference - @tool://url-validator
* @returns {string} 工具ID
*/
extractToolId(toolReference) {
const match = toolReference.match(/^@tool:\/\/(.+)$/);
if (!match) {
throw new Error(`Invalid tool reference format: ${toolReference}`);
}
return match[1];
}
/**
* 解析沙箱路径
* @returns {Promise<string>} 沙箱绝对路径
*/
async resolveSandboxPath() {
// 使用 @user://.promptx/toolbox/{toolId} 作为沙箱路径
const userDataReference = `@user://.promptx/toolbox/${this.toolId}`;
const result = await this.resourceManager.resolveProtocolReference(userDataReference);
if (!result.success) {
throw new Error(`Failed to resolve sandbox path: ${result.error}`);
}
// 通过UserProtocol解析实际路径
const userProtocol = this.resourceManager.protocols.get('user');
const sandboxPath = await userProtocol.resolvePath(
`.promptx/toolbox/${this.toolId}`,
new Map()
);
return sandboxPath;
}
/**
* 在基础沙箱中分析工具
*/
async analyzeToolInSandbox() {
const basicSandbox = this.createBasicSandbox();
const script = new vm.Script(this.toolContent, { filename: `${this.toolId}.js` });
const context = vm.createContext(basicSandbox);
script.runInContext(context);
const exported = context.module.exports;
if (!exported) {
throw new Error(`Tool does not export anything: ${this.toolId}`);
}
// 创建工具实例
let toolInstance;
if (typeof exported === 'function') {
toolInstance = new exported();
} else if (typeof exported === 'object') {
toolInstance = exported;
} else {
throw new Error(`Invalid tool export format: ${this.toolId}`);
}
// 提取依赖
if (typeof toolInstance.getDependencies === 'function') {
try {
this.dependencies = toolInstance.getDependencies() || [];
} catch (error) {
console.warn(`[ToolSandbox] Failed to get dependencies for ${this.toolId}: ${error.message}`);
this.dependencies = [];
}
}
this.toolInstance = toolInstance;
}
/**
* 确保沙箱目录存在
*/
async ensureSandboxDirectory() {
try {
await fs.access(this.sandboxPath);
} catch (error) {
if (error.code === 'ENOENT') {
await fs.mkdir(this.sandboxPath, { recursive: true });
} else {
throw error;
}
}
}
/**
* 安装依赖
*/
async installDependencies() {
if (this.dependencies.length === 0) {
return;
}
// 1. 创建package.json
await this.createPackageJson();
// 2. 使用内置pnpm安装依赖
await this.runPnpmInstall();
}
/**
* 创建package.json
*/
async createPackageJson() {
const packageJsonPath = path.join(this.sandboxPath, 'package.json');
// 检查是否已存在且不强制重装
if (!this.options.forceReinstall) {
try {
await fs.access(packageJsonPath);
return; // 已存在,跳过
} catch (error) {
// 不存在,继续创建
}
}
const packageJson = {
name: `toolbox-${this.toolId}`,
version: '1.0.0',
description: `Sandbox for tool: ${this.toolId}`,
private: true,
dependencies: {}
};
// 解析依赖格式 ["validator@^13.11.0", "lodash"]
for (const dep of this.dependencies) {
if (dep.includes('@')) {
const [name, version] = dep.split('@');
packageJson.dependencies[name] = version;
} else {
packageJson.dependencies[dep] = 'latest';
}
}
await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
}
/**
* 运行pnpm安装
*/
async runPnpmInstall() {
return new Promise((resolve, reject) => {
// 获取内置pnpm路径 - 直接从node_modules获取
const pnpmModulePath = require.resolve('pnpm');
const pnpmBinPath = path.join(path.dirname(pnpmModulePath), 'bin', 'pnpm.cjs');
const pnpm = spawn('node', [pnpmBinPath, 'install'], {
cwd: this.sandboxPath,
stdio: 'pipe'
});
let stdout = '';
let stderr = '';
pnpm.stdout.on('data', (data) => {
stdout += data.toString();
});
pnpm.stderr.on('data', (data) => {
stderr += data.toString();
});
pnpm.on('close', (code) => {
if (code === 0) {
resolve({ stdout, stderr });
} else {
reject(new Error(`pnpm install failed with code ${code}: ${stderr}`));
}
});
pnpm.on('error', (error) => {
reject(new Error(`Failed to spawn pnpm: ${error.message}`));
});
});
}
/**
* 创建执行沙箱环境
*/
async createExecutionSandbox() {
this.sandboxContext = this.createSmartSandbox();
// 在智能沙箱中重新加载工具
const script = new vm.Script(this.toolContent, { filename: `${this.toolId}.js` });
const context = vm.createContext(this.sandboxContext);
script.runInContext(context);
const exported = context.module.exports;
if (typeof exported === 'function') {
this.toolInstance = new exported();
} else if (typeof exported === 'object') {
this.toolInstance = exported;
}
}
/**
* 创建基础沙箱
*/
createBasicSandbox() {
return {
require: require,
module: { exports: {} },
exports: {},
console: console,
Buffer: Buffer,
process: {
env: process.env,
hrtime: process.hrtime
},
setTimeout: setTimeout,
clearTimeout: clearTimeout,
setInterval: setInterval,
clearInterval: clearInterval,
Object: Object,
Array: Array,
String: String,
Number: Number,
Boolean: Boolean,
Date: Date,
JSON: JSON,
Math: Math,
RegExp: RegExp,
Error: Error,
URL: URL
};
}
/**
* 创建智能沙箱(支持依赖)
*/
createSmartSandbox() {
return {
require: (moduleName) => {
try {
// 优先从沙箱目录查找依赖
return require(require.resolve(moduleName, {
paths: [
path.join(this.sandboxPath, 'node_modules'),
this.sandboxPath,
process.cwd() + '/node_modules'
]
}));
} catch (error) {
// 回退到默认require
return require(moduleName);
}
},
module: { exports: {} },
exports: {},
console: console,
Buffer: Buffer,
process: {
env: process.env,
hrtime: process.hrtime
},
setTimeout: setTimeout,
clearTimeout: clearTimeout,
setInterval: setInterval,
clearInterval: clearInterval,
Object: Object,
Array: Array,
String: String,
Number: Number,
Boolean: Boolean,
Date: Date,
JSON: JSON,
Math: Math,
RegExp: RegExp,
Error: Error,
URL: URL
};
}
/**
* 参数验证
*/
async validateParameters(parameters) {
if (typeof this.toolInstance.validate === 'function') {
const result = this.toolInstance.validate(parameters);
if (typeof result === 'boolean' && !result) {
throw new Error('Parameter validation failed');
} else if (result && typeof result === 'object' && !result.valid) {
throw new Error(`Parameter validation failed: ${result.errors?.join(', ')}`);
}
}
}
/**
* 在沙箱中执行工具
*/
async executeInSandbox(parameters) {
if (!this.toolInstance || typeof this.toolInstance.execute !== 'function') {
throw new Error(`Tool ${this.toolId} does not have execute method`);
}
return await this.toolInstance.execute(parameters);
}
/**
* 获取分析结果
*/
getAnalysisResult() {
return {
toolId: this.toolId,
dependencies: this.dependencies,
sandboxPath: this.sandboxPath,
hasMetadata: typeof this.toolInstance?.getMetadata === 'function',
hasSchema: typeof this.toolInstance?.getSchema === 'function'
};
}
/**
* 清理沙箱资源
*/
async cleanup() {
// 可选:清理临时文件、关闭连接等
this.sandboxContext = null;
this.toolInstance = null;
}
/**
* 获取工具元信息
*/
getToolMetadata() {
if (this.toolInstance && typeof this.toolInstance.getMetadata === 'function') {
return this.toolInstance.getMetadata();
}
return null;
}
/**
* 获取工具Schema
*/
getToolSchema() {
if (this.toolInstance && typeof this.toolInstance.getSchema === 'function') {
return this.toolInstance.getSchema();
}
return null;
}
}
module.exports = ToolSandbox;