From 65eddb96df07184124574d6a91db5ed2584a4013 Mon Sep 17 00:00:00 2001 From: sean Date: Sat, 5 Jul 2025 22:02:35 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=AF=20=E5=AE=9E=E7=8E=B0=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E9=A1=B9=E7=9B=AE=E5=B7=A5=E4=BD=9C=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=EF=BC=9A@project://.promptx/cwd?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 🎯 核心功能 - **统一分析环境**:所有工具分析阶段使用@project://.promptx/cwd作为工作目录 - **保持执行隔离**:工具执行阶段继续使用独立沙箱@user://.promptx/toolbox/{toolId} - **协议路径支持**:新增resolveProtocolPath()方法处理@project://协议 - **自动目录创建**:首次使用时自动创建统一工作目录 ## ✅ 设计价值 ### **语义清晰** - @project://.promptx/cwd 明确表达项目级统一工作目录概念 - 完美融入PromptX资源协议体系,保持架构一致性 ### **功能优化** - 分析阶段:统一环境,所有工具共享相同的工作目录上下文 - 执行阶段:隔离环境,每个工具独立沙箱确保安全性 - 路径可预测:开发者明确知道工具运行的目录环境 ### **架构改进** - 符合奥卡姆剃刀原则:用简洁的协议表达明确的语义 - 符合单一职责:统一工作目录专注于分析环境,沙箱专注于执行隔离 - 易于扩展:未来可轻松扩展@project://.promptx/temp等目录 ## 🔧 技术实现 ### **新增方法** - `resolveProtocolPath(protocolPath)` - 解析@project://等协议路径 - 更新`createSandbox()`默认sandboxPath为`@project://.promptx/cwd` ### **路径映射** ``` 分析阶段: @project://.promptx/cwd → /Users/sean/Management/ContradictionManagement/.promptx/cwd 执行阶段: @user://.promptx/toolbox/{toolId} → /Users/sean/.promptx/toolbox/{toolId} ``` ## 🧪 测试验证 - ✅ 协议路径解析正确 - ✅ 统一工作目录自动创建 - ✅ 工具分析和执行流程正常 - ✅ heywhale-activity-scraper完整测试通过 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/lib/tool/ToolSandbox.js | 69 +++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 11 deletions(-) diff --git a/src/lib/tool/ToolSandbox.js b/src/lib/tool/ToolSandbox.js index 16f03cd..3322237 100644 --- a/src/lib/tool/ToolSandbox.js +++ b/src/lib/tool/ToolSandbox.js @@ -74,7 +74,7 @@ class ToolSandbox { this.toolContent = toolResult.content; - // 3. 设置沙箱路径 + // 3. 设置沙箱路径(工具专用沙箱) this.sandboxPath = await this.resolveSandboxPath(); // 4. 在基础沙箱中分析工具 @@ -207,9 +207,9 @@ class ToolSandbox { * 在基础沙箱中分析工具 */ async analyzeToolInSandbox() { - const sandbox = this.createSandbox({ - supportDependencies: false, - sandboxPath: process.cwd() + const sandbox = await this.createSandbox({ + supportDependencies: false + // 使用默认的@project://.promptx/cwd }); const script = new vm.Script(this.toolContent, { filename: `${this.toolId}.js` }); const context = vm.createContext(sandbox); @@ -445,9 +445,9 @@ class ToolSandbox { * 创建执行沙箱环境 */ async createExecutionSandbox() { - this.sandboxContext = this.createSandbox({ + this.sandboxContext = await this.createSandbox({ supportDependencies: true, - sandboxPath: this.sandboxPath + sandboxPath: this.sandboxPath // 保持使用工具专用沙箱 }); // 在智能沙箱中重新加载工具 @@ -468,24 +468,27 @@ class ToolSandbox { * 创建统一沙箱环境 * @param {Object} options - 沙箱配置 * @param {boolean} options.supportDependencies - 是否支持依赖解析 - * @param {string} options.sandboxPath - 沙箱工作目录 + * @param {string} options.sandboxPath - 沙箱工作目录,支持协议路径 * @returns {Object} 沙箱环境对象 */ - createSandbox(options = {}) { + async createSandbox(options = {}) { const { supportDependencies = false, - sandboxPath = process.cwd() + sandboxPath = '@project://.promptx/cwd' } = options; + // 解析协议路径为实际路径 + const resolvedPath = await this.resolveProtocolPath(sandboxPath); + return { require: supportDependencies ? - this.createSmartRequire(sandboxPath) : + this.createSmartRequire(resolvedPath) : this.createAnalysisRequire(), module: { exports: {} }, exports: {}, console: console, Buffer: Buffer, - process: this.createProcessMock(sandboxPath), + process: this.createProcessMock(resolvedPath), setTimeout: setTimeout, clearTimeout: clearTimeout, setInterval: setInterval, @@ -504,6 +507,50 @@ class ToolSandbox { }; } + /** + * 解析协议路径(支持@project://等协议) + * @param {string} protocolPath - 协议路径,如@project://.promptx/cwd + * @returns {Promise} 解析后的绝对路径 + */ + async resolveProtocolPath(protocolPath) { + // 处理undefined或null的情况 + if (!protocolPath) { + throw new Error('protocolPath is required but was undefined'); + } + + // 如果是协议路径,使用ResourceManager解析 + if (protocolPath.startsWith('@')) { + if (!this.resourceManager) { + throw new Error('ResourceManager not set. Cannot resolve protocol path.'); + } + + const projectProtocol = this.resourceManager.protocols.get('project'); + if (!projectProtocol) { + throw new Error('ProjectProtocol not found. Cannot resolve @project:// path.'); + } + + // 提取协议路径的相对部分 + const relativePath = protocolPath.replace(/^@project:\/\//, ''); + const resolvedPath = await projectProtocol.resolvePath(relativePath, new Map()); + + // 确保目录存在 + const fs = require('fs').promises; + try { + await fs.access(resolvedPath); + } catch (error) { + if (error.code === 'ENOENT') { + await fs.mkdir(resolvedPath, { recursive: true }); + console.log(`[ToolSandbox] 创建统一工作目录: ${resolvedPath}`); + } + } + + return resolvedPath; + } + + // 普通路径直接返回 + return protocolPath; + } + /** * 创建完整的process对象mock * @param {string} sandboxPath - 沙箱工作目录