🎯 实现统一项目工作目录:@project://.promptx/cwd
## 🎯 核心功能 - **统一分析环境**:所有工具分析阶段使用@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 <noreply@anthropic.com>
This commit is contained in:
@ -74,7 +74,7 @@ class ToolSandbox {
|
|||||||
|
|
||||||
this.toolContent = toolResult.content;
|
this.toolContent = toolResult.content;
|
||||||
|
|
||||||
// 3. 设置沙箱路径
|
// 3. 设置沙箱路径(工具专用沙箱)
|
||||||
this.sandboxPath = await this.resolveSandboxPath();
|
this.sandboxPath = await this.resolveSandboxPath();
|
||||||
|
|
||||||
// 4. 在基础沙箱中分析工具
|
// 4. 在基础沙箱中分析工具
|
||||||
@ -207,9 +207,9 @@ class ToolSandbox {
|
|||||||
* 在基础沙箱中分析工具
|
* 在基础沙箱中分析工具
|
||||||
*/
|
*/
|
||||||
async analyzeToolInSandbox() {
|
async analyzeToolInSandbox() {
|
||||||
const sandbox = this.createSandbox({
|
const sandbox = await this.createSandbox({
|
||||||
supportDependencies: false,
|
supportDependencies: false
|
||||||
sandboxPath: process.cwd()
|
// 使用默认的@project://.promptx/cwd
|
||||||
});
|
});
|
||||||
const script = new vm.Script(this.toolContent, { filename: `${this.toolId}.js` });
|
const script = new vm.Script(this.toolContent, { filename: `${this.toolId}.js` });
|
||||||
const context = vm.createContext(sandbox);
|
const context = vm.createContext(sandbox);
|
||||||
@ -445,9 +445,9 @@ class ToolSandbox {
|
|||||||
* 创建执行沙箱环境
|
* 创建执行沙箱环境
|
||||||
*/
|
*/
|
||||||
async createExecutionSandbox() {
|
async createExecutionSandbox() {
|
||||||
this.sandboxContext = this.createSandbox({
|
this.sandboxContext = await this.createSandbox({
|
||||||
supportDependencies: true,
|
supportDependencies: true,
|
||||||
sandboxPath: this.sandboxPath
|
sandboxPath: this.sandboxPath // 保持使用工具专用沙箱
|
||||||
});
|
});
|
||||||
|
|
||||||
// 在智能沙箱中重新加载工具
|
// 在智能沙箱中重新加载工具
|
||||||
@ -468,24 +468,27 @@ class ToolSandbox {
|
|||||||
* 创建统一沙箱环境
|
* 创建统一沙箱环境
|
||||||
* @param {Object} options - 沙箱配置
|
* @param {Object} options - 沙箱配置
|
||||||
* @param {boolean} options.supportDependencies - 是否支持依赖解析
|
* @param {boolean} options.supportDependencies - 是否支持依赖解析
|
||||||
* @param {string} options.sandboxPath - 沙箱工作目录
|
* @param {string} options.sandboxPath - 沙箱工作目录,支持协议路径
|
||||||
* @returns {Object} 沙箱环境对象
|
* @returns {Object} 沙箱环境对象
|
||||||
*/
|
*/
|
||||||
createSandbox(options = {}) {
|
async createSandbox(options = {}) {
|
||||||
const {
|
const {
|
||||||
supportDependencies = false,
|
supportDependencies = false,
|
||||||
sandboxPath = process.cwd()
|
sandboxPath = '@project://.promptx/cwd'
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
|
// 解析协议路径为实际路径
|
||||||
|
const resolvedPath = await this.resolveProtocolPath(sandboxPath);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
require: supportDependencies ?
|
require: supportDependencies ?
|
||||||
this.createSmartRequire(sandboxPath) :
|
this.createSmartRequire(resolvedPath) :
|
||||||
this.createAnalysisRequire(),
|
this.createAnalysisRequire(),
|
||||||
module: { exports: {} },
|
module: { exports: {} },
|
||||||
exports: {},
|
exports: {},
|
||||||
console: console,
|
console: console,
|
||||||
Buffer: Buffer,
|
Buffer: Buffer,
|
||||||
process: this.createProcessMock(sandboxPath),
|
process: this.createProcessMock(resolvedPath),
|
||||||
setTimeout: setTimeout,
|
setTimeout: setTimeout,
|
||||||
clearTimeout: clearTimeout,
|
clearTimeout: clearTimeout,
|
||||||
setInterval: setInterval,
|
setInterval: setInterval,
|
||||||
@ -504,6 +507,50 @@ class ToolSandbox {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析协议路径(支持@project://等协议)
|
||||||
|
* @param {string} protocolPath - 协议路径,如@project://.promptx/cwd
|
||||||
|
* @returns {Promise<string>} 解析后的绝对路径
|
||||||
|
*/
|
||||||
|
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
|
* 创建完整的process对象mock
|
||||||
* @param {string} sandboxPath - 沙箱工作目录
|
* @param {string} sandboxPath - 沙箱工作目录
|
||||||
|
|||||||
Reference in New Issue
Block a user