From d1d38e046b1013ad189d6aada897180e027a5070 Mon Sep 17 00:00:00 2001 From: Sean Date: Sat, 5 Jul 2025 09:10:43 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E9=B2=81=E7=8F=AD=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E5=BC=80=E5=8F=91=E4=BD=93=E9=AA=8C=E4=BC=98=E5=8C=96=20-=20?= =?UTF-8?q?=E4=BA=94=E7=BB=84=E4=BB=B6=E6=9E=B6=E6=9E=84=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=E4=B8=8E=E6=99=BA=E8=83=BD=E9=94=99=E8=AF=AF=E5=A4=84=E7=90=86?= =?UTF-8?q?=20(#116)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 为promptx_tool增加forceReinstall选项支持 解决工具沙箱缓存机制问题,允许强制重新安装工具依赖。 ## 修改内容 ### 1. 工具定义更新 (toolDefinitions.js) - 增加 context.options.forceReinstall 参数支持 - 增加 context.options.timeout 参数支持 - 完善参数描述,说明context用途 - 移除暂时不需要的role_id和session_id参数 ### 2. 执行逻辑优化 (ToolCommand.js) - 支持从context.options提取执行选项 - 将选项传递给ToolSandbox构造函数 - 增加调试日志输出沙箱选项 - 完善JSDoc注释 ## 解决的问题 - Issue #107: PromptX工具沙箱缓存机制不支持工具集更新 - 鲁班等AI角色在调试工具时遇到的缓存问题 - 工具依赖更新后无法自动重新安装的问题 ## 使用方式 ```javascript // 强制重新安装依赖 { tool_resource: "@tool://tool-name", parameters: { /* 工具参数 */ }, context: { options: { forceReinstall: true } } } ``` 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * refactor: 简化context参数,移除暂时不需要的role_id和session_id 按照奥卡姆剃刀原则,移除当前没有实际用途的参数: - 移除 context.role_id - 移除 context.session_id - 保留 context.options 用于执行配置 - 简化API接口,降低复杂度 未来如需要可重新添加这些参数。 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * refactor: 简化promptx_tool参数结构,移除context层级 ## 主要改进 ### 1. 扁平化参数结构 - 移除复杂的context嵌套,直接使用顶级参数 - forceReinstall 和 timeout 作为可选的顶级参数 - 遵循MCP协议惯例,降低AI理解成本 ### 2. 参数说明优化 - forceReinstall: 明确默认值为false - 详细说明使用场景:工具开发和调试中的缓存问题 - timeout: 明确默认值为30000ms ### 3. 防止盲目调用 - 增加重要提醒:要求AI先了解工具说明再调用 - 避免大模型在不了解工具的情况下盲目执行 ## 新的调用方式 ## 优势 - 符合MCP预训练共识,降低AI学习成本 - 参数结构简洁直观 - 保持向后兼容性 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * fix: 修正鲁班工具开发提示词 - 更新为五组件架构并增加AI引导机制 - 更新DPML工具标签知识:从四组件升级到五组件架构(增加identity标签) - 在工具开发工作流中增加.tool.md说明书创建步骤 - 添加AI使用提醒机制,强化工具使用前必读原则 - 完善工具标签编写模板,包含完整的五标签结构 - 更新质量检查标准,适配新的标签体系 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * feat: 添加智能require错误过滤机制到ToolSandbox 解决工具开发中的常见问题:analyze阶段require依赖导致的错误 核心改进: - 添加_filterRequireError()私有方法,智能识别MODULE_NOT_FOUND错误 - 通过静态分析提取getDependencies()声明的依赖列表 - 对比缺失模块与声明依赖,区分合法缺失和代码错误 - 支持版本号格式的依赖声明(如axios@^1.6.0) 开发者体验提升: - 可以自然地在文件顶部写require()语句 - 忘记声明依赖时仍会得到明确错误提示 - 降低工具开发的认知负担和学习成本 - 遵循奥卡姆剃刀原则:用技术解决技术问题 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --------- Co-authored-by: Claude --- .../tool-development-workflow.execution.md | 163 +++++++++++++++++- .../knowledge/dpml-tool-tagging.knowledge.md | 43 +++-- src/lib/tool/ToolSandbox.js | 93 +++++++++- 3 files changed, 278 insertions(+), 21 deletions(-) diff --git a/resource/role/luban/execution/tool-development-workflow.execution.md b/resource/role/luban/execution/tool-development-workflow.execution.md index bb66851..1567dfe 100644 --- a/resource/role/luban/execution/tool-development-workflow.execution.md +++ b/resource/role/luban/execution/tool-development-workflow.execution.md @@ -52,7 +52,49 @@ flowchart TD - 确认沙箱环境兼容性 - 设计错误处理策略 -**Step 1.3: 接口规范设计** +**Step 1.3: 工具说明书设计** +```xml + + + +## 工具名称 +@tool://{tool-name} + +## 简介 +工具功能的一句话简介 + + + +⚠️ **AI重要提醒**: 调用此工具前必须完整阅读本说明书,理解工具功能边界、参数要求和使用限制。禁止在不了解工具功能的情况下盲目调用。 + +## 核心问题定义 +明确描述工具要解决的具体问题 + +## 价值主张 +- 🎯 **解决什么痛点**:具体描述用户痛点 +- 🚀 **带来什么价值**:明确量化收益 +- 🌟 **独特优势**:相比其他方案的优势 + +## 应用边界 +- ✅ **适用场景**:详细列出适用情况 +- ❌ **不适用场景**:明确使用边界 + + + + + + + + + + + + + + +``` + +**Step 1.4: 接口规范设计** ```javascript // 标准工具接口模板 module.exports = { @@ -90,19 +132,122 @@ module.exports = { ```mermaid flowchart LR - A[创建工具文件] --> B[实现接口方法] - B --> C[依赖管理] - C --> D[核心逻辑] - D --> E[错误处理] + A[创建工具文件] --> B[编写说明书] + B --> C[实现接口方法] + C --> D[依赖管理] + D --> E[核心逻辑] + E --> F[错误处理] ``` **Step 2.1: 工具文件创建** ```bash # 标准文件路径 -.promptx/resource/tool/{tool-name}/{tool-name}.tool.js +.promptx/resource/tool/{tool-name}/{tool-name}.tool.js # 给计算机的执行代码 +.promptx/resource/tool/{tool-name}/{tool-name}.tool.md # 给AI的使用说明书 ``` -**Step 2.2: 依赖管理实现** +**Step 2.2: 工具说明书编写** +基于Phase 1的设计,完整编写五组件说明书: + +```xml + + +## 工具名称 +@tool://actual-tool-name + +## 简介 +具体的工具功能描述 + + + +⚠️ **AI重要提醒**: 调用此工具前必须完整阅读本说明书,理解工具功能边界、参数要求和使用限制。禁止在不了解工具功能的情况下盲目调用。 + +## 核心问题定义 +[具体问题描述] + +## 价值主张 +- 🎯 **解决什么痛点**:[具体痛点] +- 🚀 **带来什么价值**:[具体价值] +- 🌟 **独特优势**:[核心优势] + +## 应用边界 +- ✅ **适用场景**:[适用情况] +- ❌ **不适用场景**:[限制条件] + + + +## 使用时机 +[具体使用场景] + +## 操作步骤 +1. **准备阶段**:[准备工作] +2. **执行阶段**:[执行步骤] +3. **验证阶段**:[验证方法] + +## 最佳实践 +- 🎯 **效率提升**:[效率技巧] +- ⚠️ **避免陷阱**:[常见问题] +- 🔧 **故障排除**:[问题解决] + +## 注意事项 +[重要提醒事项] + + + +## 必需参数 +| 参数名 | 类型 | 描述 | 示例 | +|--------|------|------|------| +| [参数] | [类型] | [描述] | [示例] | + +## 可选参数 +| 参数名 | 类型 | 默认值 | 描述 | +|--------|------|--------|------| +| [参数] | [类型] | [默认值] | [描述] | + +## 参数约束 +- **[约束类型]**:[约束说明] + +## 参数示例 +```json +{ + "[参数名]": "[参数值]" +} +``` + + + +## 成功返回格式 +```json +{ + "success": true, + "data": { + "[数据字段]": "[数据说明]" + } +} +``` + +## 错误处理格式 +```json +{ + "success": false, + "error": { + "code": "[错误代码]", + "message": "[错误信息]" + } +} +``` + +## 结果解读指南 +- **[使用方式]**:[说明] + +## 后续动作建议 +- [成功时的建议] +- [失败时的建议] + + +``` + +**Step 2.3: 依赖管理实现** ```javascript getDependencies() { return [ @@ -113,7 +258,7 @@ getDependencies() { } ``` -**Step 2.3: 元信息定义** +**Step 2.4: 元信息定义** ```javascript getMetadata() { return { @@ -127,7 +272,7 @@ getMetadata() { } ``` -**Step 2.4: Schema定义** +**Step 2.5: Schema定义** ```javascript getSchema() { return { diff --git a/resource/role/luban/knowledge/dpml-tool-tagging.knowledge.md b/resource/role/luban/knowledge/dpml-tool-tagging.knowledge.md index 084fc34..35f50ae 100644 --- a/resource/role/luban/knowledge/dpml-tool-tagging.knowledge.md +++ b/resource/role/luban/knowledge/dpml-tool-tagging.knowledge.md @@ -4,11 +4,12 @@ ## 🏷️ DPML工具标签框架深度理解 -### 四组件架构精通 -DPML#工具提示单元 基于四组件架构构建完整的AI工具定义: +### 五组件架构精通 +DPML#工具提示单元 基于五组件架构构建完整的AI工具定义: ```xml + 工具身份 - 工具名称和简介 用途说明 - 明确工具解决什么问题 使用方法 - 详细说明如何正确使用 参数定义 - 明确工具需要什么输入 @@ -23,9 +24,22 @@ DPML#工具提示单元 基于四组件架构构建完整的AI工具定义: ## 📝 标准工具标签编写模板 +### Identity组件编写精要 +```xml + +## 工具名称 +@tool://tool-name + +## 简介 +简洁明确的工具功能描述,一句话说明工具的核心能力 + +``` + ### Purpose组件编写精要 ```xml +⚠️ **AI重要提醒**: 调用此工具前必须完整阅读本说明书,理解工具功能边界、参数要求和使用限制。禁止在不了解工具功能的情况下盲目调用。 + ## 核心问题定义 明确描述工具要解决的具体问题和适用场景 @@ -139,6 +153,12 @@ DPML#工具提示单元 基于四组件架构构建完整的AI工具定义: ## 🎯 工具标签质量标准 +### Identity质量检查 +- ✅ 工具名称符合@tool://格式 +- ✅ 简介简洁明确一句话概括 +- ✅ 体现工具核心能力 +- ✅ 便于快速识别和理解 + ### Purpose质量检查 - ✅ 问题定义清晰具体 - ✅ 价值主张明确量化 @@ -227,15 +247,16 @@ return { ```mermaid flowchart TD - A[用户需求] --> B[编写Purpose] - B --> C[设计Usage] - C --> D[定义Parameter] - D --> E[规划Outcome] - E --> F[生成工具标签] - F --> G[映射到代码接口] - G --> H[实现具体逻辑] - H --> I[测试验证] - I --> J[完整工具交付] + A[用户需求] --> B[定义Identity] + B --> C[编写Purpose] + C --> D[设计Usage] + D --> E[定义Parameter] + E --> F[规划Outcome] + F --> G[生成工具标签] + G --> H[映射到代码接口] + H --> I[实现具体逻辑] + I --> J[测试验证] + J --> K[完整工具交付] ``` ### 开发质量保证 diff --git a/src/lib/tool/ToolSandbox.js b/src/lib/tool/ToolSandbox.js index 6cafbbf..3f03afd 100644 --- a/src/lib/tool/ToolSandbox.js +++ b/src/lib/tool/ToolSandbox.js @@ -211,7 +211,17 @@ class ToolSandbox { const script = new vm.Script(this.toolContent, { filename: `${this.toolId}.js` }); const context = vm.createContext(basicSandbox); - script.runInContext(context); + try { + script.runInContext(context); + } catch (error) { + // 使用智能错误过滤处理require错误 + const filteredError = this._filterRequireError(error); + if (filteredError) { + throw filteredError; + } + // 如果是预期的require错误,继续执行 + } + const exported = context.module.exports; if (!exported) { @@ -241,6 +251,87 @@ class ToolSandbox { this.toolInstance = toolInstance; } + /** + * 智能过滤require错误 + * @param {Error} error - 捕获的错误 + * @returns {Error|null} - 如果是真正的错误则返回Error对象,如果是预期的require错误则返回null + * @private + */ + _filterRequireError(error) { + // 检查是否是MODULE_NOT_FOUND错误 + if (error.code === 'MODULE_NOT_FOUND') { + const missingModule = this._extractMissingModuleName(error.message); + + if (missingModule) { + // 获取已声明的依赖列表 + const declaredDependencies = this._extractDeclaredDependencies(); + + // 检查缺失的模块是否在依赖声明中 + if (this._isDeclaredInDependencies(missingModule, declaredDependencies)) { + console.log(`[ToolSandbox] 依赖 ${missingModule} 未安装,将在prepareDependencies阶段安装`); + return null; // 预期的错误,忽略 + } else { + return new Error(`未声明的依赖: ${missingModule},请在getDependencies()中添加此依赖`); + } + } + } + + // 其他错误直接返回 + return error; + } + + /** + * 从错误信息中提取缺失的模块名 + * @param {string} errorMessage - 错误信息 + * @returns {string|null} - 模块名或null + * @private + */ + _extractMissingModuleName(errorMessage) { + // 匹配 "Cannot find module 'moduleName'" 或 "Cannot resolve module 'moduleName'" + const match = errorMessage.match(/Cannot (?:find|resolve) module ['"]([^'"]+)['"]/); + return match ? match[1] : null; + } + + /** + * 尝试从工具代码中提取已声明的依赖 + * @returns {string[]} - 依赖列表 + * @private + */ + _extractDeclaredDependencies() { + try { + // 尝试通过正则表达式从代码中提取getDependencies的返回值 + const dependencyMatch = this.toolContent.match(/getDependencies\s*\(\s*\)\s*\{[\s\S]*?return\s*\[([\s\S]*?)\]/); + + if (dependencyMatch) { + const dependencyString = dependencyMatch[1]; + // 提取字符串字面量 + const stringMatches = dependencyString.match(/['"]([^'"]+)['"]/g); + if (stringMatches) { + return stringMatches.map(str => str.slice(1, -1)); // 去掉引号 + } + } + } catch (error) { + console.warn(`[ToolSandbox] 无法解析依赖声明: ${error.message}`); + } + + return []; + } + + /** + * 检查模块是否在依赖声明中 + * @param {string} moduleName - 模块名 + * @param {string[]} declaredDependencies - 已声明的依赖列表 + * @returns {boolean} - 是否已声明 + * @private + */ + _isDeclaredInDependencies(moduleName, declaredDependencies) { + return declaredDependencies.some(dep => { + // 支持 "axios@^1.6.0" 格式,提取模块名部分 + const depName = dep.split('@')[0]; + return depName === moduleName; + }); + } + /** * 确保沙箱目录存在 */