@becrafter/prompt-manager 0.0.18 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/IFLOW.md +175 -0
- package/README.md +145 -234
- package/app/desktop/assets/app.1.png +0 -0
- package/app/desktop/assets/app.png +0 -0
- package/app/desktop/assets/icons/icon.icns +0 -0
- package/app/desktop/assets/icons/icon.ico +0 -0
- package/app/desktop/assets/icons/icon.png +0 -0
- package/app/desktop/assets/icons/tray.png +0 -0
- package/app/desktop/assets/templates/about.html +147 -0
- package/app/desktop/assets/tray.png +0 -0
- package/app/desktop/main.js +187 -732
- package/app/desktop/package-lock.json +723 -522
- package/app/desktop/package.json +54 -25
- package/app/desktop/preload.js +7 -0
- package/app/desktop/src/core/error-handler.js +108 -0
- package/app/desktop/src/core/event-emitter.js +84 -0
- package/app/desktop/src/core/logger.js +108 -0
- package/app/desktop/src/core/state-manager.js +125 -0
- package/app/desktop/src/services/module-loader.js +214 -0
- package/app/desktop/src/services/runtime-manager.js +301 -0
- package/app/desktop/src/services/service-manager.js +169 -0
- package/app/desktop/src/services/update-manager.js +268 -0
- package/app/desktop/src/ui/about-dialog-manager.js +208 -0
- package/app/desktop/src/ui/admin-window-manager.js +757 -0
- package/app/desktop/src/ui/splash-manager.js +253 -0
- package/app/desktop/src/ui/tray-manager.js +186 -0
- package/app/desktop/src/utils/icon-manager.js +133 -0
- package/app/desktop/src/utils/path-utils.js +58 -0
- package/app/desktop/src/utils/resource-paths.js +49 -0
- package/app/desktop/src/utils/resource-sync.js +260 -0
- package/app/desktop/src/utils/runtime-sync.js +241 -0
- package/app/desktop/src/utils/template-renderer.js +284 -0
- package/app/desktop/src/utils/version-utils.js +59 -0
- package/examples/prompts/engineer/engineer-professional.yaml +92 -0
- package/examples/prompts/engineer/laowang-engineer.yaml +132 -0
- package/examples/prompts/engineer/nekomata-engineer.yaml +123 -0
- package/examples/prompts/engineer/ojousama-engineer.yaml +124 -0
- package/examples/prompts/recommend/human_3-0_growth_diagnostic_coach_prompt.yaml +105 -0
- package/examples/prompts/workflow/sixstep-workflow.yaml +192 -0
- package/package.json +18 -9
- package/packages/admin-ui/.babelrc +3 -0
- package/packages/admin-ui/admin.html +237 -4784
- package/packages/admin-ui/css/main.css +2592 -0
- package/packages/admin-ui/css/recommended-prompts.css +610 -0
- package/packages/admin-ui/package-lock.json +6981 -0
- package/packages/admin-ui/package.json +36 -0
- package/packages/admin-ui/src/codemirror.js +53 -0
- package/packages/admin-ui/src/index.js +3188 -0
- package/packages/admin-ui/webpack.config.js +76 -0
- package/packages/resources/tools/chrome-devtools/README.md +310 -0
- package/packages/resources/tools/chrome-devtools/chrome-devtools.tool.js +1703 -0
- package/packages/resources/tools/file-reader/README.md +289 -0
- package/packages/resources/tools/file-reader/file-reader.tool.js +1545 -0
- package/packages/resources/tools/filesystem/README.md +359 -0
- package/packages/resources/tools/filesystem/filesystem.tool.js +538 -0
- package/packages/resources/tools/ollama-remote/README.md +192 -0
- package/packages/resources/tools/ollama-remote/ollama-remote.tool.js +421 -0
- package/packages/resources/tools/pdf-reader/README.md +236 -0
- package/packages/resources/tools/pdf-reader/pdf-reader.tool.js +565 -0
- package/packages/resources/tools/playwright/README.md +306 -0
- package/packages/resources/tools/playwright/playwright.tool.js +1186 -0
- package/packages/resources/tools/todolist/README.md +394 -0
- package/packages/resources/tools/todolist/todolist.tool.js +1312 -0
- package/packages/server/README.md +142 -0
- package/packages/server/api/admin.routes.js +42 -11
- package/packages/server/api/surge.routes.js +43 -0
- package/packages/server/app.js +119 -14
- package/packages/server/index.js +39 -0
- package/packages/server/mcp/mcp.server.js +346 -28
- package/packages/server/mcp/{mcp.handler.js → prompt.handler.js} +108 -9
- package/packages/server/mcp/sequential-thinking.handler.js +318 -0
- package/packages/server/mcp/think-plan.handler.js +274 -0
- package/packages/server/middlewares/auth.middleware.js +6 -0
- package/packages/server/package.json +51 -0
- package/packages/server/server.js +37 -1
- package/packages/server/toolm/index.js +9 -0
- package/packages/server/toolm/package-installer.service.js +267 -0
- package/packages/server/toolm/test-tools.js +264 -0
- package/packages/server/toolm/tool-context.service.js +334 -0
- package/packages/server/toolm/tool-dependency.service.js +168 -0
- package/packages/server/toolm/tool-description-generator-optimized.service.js +375 -0
- package/packages/server/toolm/tool-description-generator.service.js +312 -0
- package/packages/server/toolm/tool-environment.service.js +200 -0
- package/packages/server/toolm/tool-execution.service.js +277 -0
- package/packages/server/toolm/tool-loader.service.js +219 -0
- package/packages/server/toolm/tool-logger.service.js +223 -0
- package/packages/server/toolm/tool-manager.handler.js +65 -0
- package/packages/server/toolm/tool-manual-generator.service.js +389 -0
- package/packages/server/toolm/tool-mode-handlers.service.js +224 -0
- package/packages/server/toolm/tool-storage.service.js +111 -0
- package/packages/server/toolm/tool-sync.service.js +138 -0
- package/packages/server/toolm/tool-utils.js +20 -0
- package/packages/server/toolm/tool-yaml-parser.service.js +81 -0
- package/packages/server/toolm/validate-system.js +421 -0
- package/packages/server/utils/config.js +49 -5
- package/packages/server/utils/util.js +65 -10
- package/scripts/build-icons.js +135 -0
- package/scripts/build.sh +57 -0
- package/scripts/surge/CNAME +1 -0
- package/scripts/surge/README.md +47 -0
- package/scripts/surge/package-lock.json +34 -0
- package/scripts/surge/package.json +20 -0
- package/scripts/surge/sync-to-surge.js +151 -0
- package/packages/admin-ui/js/closebrackets.min.js +0 -8
- package/packages/admin-ui/js/codemirror.min.js +0 -8
- package/packages/admin-ui/js/js-yaml.min.js +0 -2
- package/packages/admin-ui/js/markdown.min.js +0 -8
- /package/app/desktop/assets/{icon.png → tray.1.png} +0 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PackageInstaller - 基于 Arborist 的完整依赖管理器
|
|
3
|
+
*
|
|
4
|
+
* 使用 npm 官方的 @npmcli/arborist,提供与 npm install 完全一致的行为
|
|
5
|
+
* 自动处理所有传递依赖、版本冲突、循环依赖等复杂场景
|
|
6
|
+
* 不依赖系统 npm,可在 Electron 环境中直接使用
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import fs from 'fs-extra';
|
|
11
|
+
import os from 'os';
|
|
12
|
+
import { logger } from '../utils/logger.js';
|
|
13
|
+
|
|
14
|
+
class PackageInstaller {
|
|
15
|
+
/**
|
|
16
|
+
* 获取最优的npm registry
|
|
17
|
+
* 自动检测用户地区,选择最快的镜像源
|
|
18
|
+
*/
|
|
19
|
+
static async getOptimalRegistry() {
|
|
20
|
+
try {
|
|
21
|
+
// 1. 检查环境变量中的用户配置
|
|
22
|
+
const userRegistry = process.env.NPM_REGISTRY || process.env.npm_config_registry;
|
|
23
|
+
if (userRegistry) {
|
|
24
|
+
logger.info(`[PackageInstaller] Using user configured registry: ${userRegistry}`);
|
|
25
|
+
return userRegistry;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// 2. 检测是否在中国地区(基于时区)
|
|
29
|
+
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
30
|
+
const isChina = timezone?.includes('Shanghai') ||
|
|
31
|
+
timezone?.includes('Hong_Kong') ||
|
|
32
|
+
timezone?.includes('Beijing') ||
|
|
33
|
+
timezone?.includes('Chongqing');
|
|
34
|
+
|
|
35
|
+
if (isChina) {
|
|
36
|
+
// 中国地区使用淘宝镜像
|
|
37
|
+
const chinaRegistry = 'https://registry.npmmirror.com';
|
|
38
|
+
logger.info(`[PackageInstaller] Detected China timezone (${timezone}), using mirror: ${chinaRegistry}`);
|
|
39
|
+
return chinaRegistry;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 3. 默认使用官方源
|
|
43
|
+
const defaultRegistry = 'https://registry.npmjs.org/';
|
|
44
|
+
logger.debug(`[PackageInstaller] Using default registry: ${defaultRegistry}`);
|
|
45
|
+
return defaultRegistry;
|
|
46
|
+
|
|
47
|
+
} catch (error) {
|
|
48
|
+
logger.warn(`[PackageInstaller] Failed to detect optimal registry: ${error.message}`);
|
|
49
|
+
return 'https://registry.npmjs.org/';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 统一的包安装入口 - 使用 Arborist 替代 npm install
|
|
55
|
+
* @param {Object} options - 安装选项
|
|
56
|
+
* @param {string} options.workingDir - 工作目录
|
|
57
|
+
* @param {Object|Array} options.dependencies - 依赖列表
|
|
58
|
+
* @param {number} options.timeout - 超时时间(毫秒)
|
|
59
|
+
* @returns {Promise<Object>} 安装结果
|
|
60
|
+
*/
|
|
61
|
+
static async install({ workingDir, dependencies, timeout = 300000 }) {
|
|
62
|
+
const startTime = Date.now();
|
|
63
|
+
|
|
64
|
+
// 构建依赖列表字符串用于日志
|
|
65
|
+
const depsList = this.buildDependenciesList(dependencies);
|
|
66
|
+
|
|
67
|
+
logger.info(`[PackageInstaller] Starting installation via Arborist: [${depsList}]`);
|
|
68
|
+
logger.debug(`[PackageInstaller] Working directory: ${workingDir}`);
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
// 确保工作目录存在
|
|
72
|
+
await fs.ensureDir(workingDir);
|
|
73
|
+
|
|
74
|
+
// 读取或创建package.json
|
|
75
|
+
const packageJsonPath = path.join(workingDir, 'package.json');
|
|
76
|
+
let manifest;
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
const content = await fs.readFile(packageJsonPath, 'utf8');
|
|
80
|
+
manifest = JSON.parse(content);
|
|
81
|
+
logger.debug(`[PackageInstaller] Found existing package.json`);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
// package.json不存在,创建默认的
|
|
84
|
+
manifest = {
|
|
85
|
+
name: `toolbox-${path.basename(workingDir)}`,
|
|
86
|
+
version: '1.0.0',
|
|
87
|
+
description: `Tool dependencies for ${path.basename(workingDir)}`,
|
|
88
|
+
private: true,
|
|
89
|
+
dependencies: {}
|
|
90
|
+
};
|
|
91
|
+
logger.debug(`[PackageInstaller] Creating new package.json`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// 规范化依赖格式
|
|
95
|
+
const normalizedDeps = this.normalizeDependencies(dependencies);
|
|
96
|
+
|
|
97
|
+
// 更新 manifest 的 dependencies
|
|
98
|
+
manifest.dependencies = { ...manifest.dependencies, ...normalizedDeps };
|
|
99
|
+
await fs.writeFile(packageJsonPath, JSON.stringify(manifest, null, 2));
|
|
100
|
+
|
|
101
|
+
logger.debug(`[PackageInstaller] Installing ${Object.keys(normalizedDeps).length} dependencies using Arborist`);
|
|
102
|
+
|
|
103
|
+
// 使用 Arborist 安装所有依赖(包括传递依赖)
|
|
104
|
+
// @npmcli/arborist 是 CommonJS 模块,使用 createRequire 导入
|
|
105
|
+
const { createRequire } = await import('module');
|
|
106
|
+
const require = createRequire(import.meta.url);
|
|
107
|
+
const { Arborist } = require('@npmcli/arborist');
|
|
108
|
+
|
|
109
|
+
// 获取最优的registry
|
|
110
|
+
const registry = await this.getOptimalRegistry();
|
|
111
|
+
|
|
112
|
+
const arb = new Arborist({
|
|
113
|
+
path: workingDir,
|
|
114
|
+
registry: registry,
|
|
115
|
+
cache: path.join(os.homedir(), '.npm', '_cacache'),
|
|
116
|
+
save: false, // 不需要再次更新 package.json
|
|
117
|
+
omit: [], // 安装所有依赖
|
|
118
|
+
force: false,
|
|
119
|
+
fund: false,
|
|
120
|
+
audit: false,
|
|
121
|
+
legacyPeerDeps: true // 兼容旧包
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// 执行安装 - Arborist 会自动处理所有传递依赖
|
|
125
|
+
await arb.reify({
|
|
126
|
+
add: Object.entries(normalizedDeps).map(([name, version]) => `${name}@${version}`)
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// 加载实际安装的包信息
|
|
130
|
+
const tree = await arb.loadActual();
|
|
131
|
+
const installedPackages = [];
|
|
132
|
+
const installResults = {};
|
|
133
|
+
|
|
134
|
+
// 收集安装的包信息
|
|
135
|
+
for (const [name, node] of tree.children) {
|
|
136
|
+
if (node && node.package) {
|
|
137
|
+
installedPackages.push(name);
|
|
138
|
+
installResults[name] = {
|
|
139
|
+
name: node.package.name,
|
|
140
|
+
version: node.package.version,
|
|
141
|
+
path: node.path
|
|
142
|
+
};
|
|
143
|
+
logger.debug(`[PackageInstaller] ✓ ${name}@${node.package.version} installed`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
148
|
+
logger.info(`[PackageInstaller] Installation completed successfully in ${elapsed}s`);
|
|
149
|
+
logger.info(`[PackageInstaller] Installed ${installedPackages.length} packages with all transitive dependencies`);
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
success: true,
|
|
153
|
+
elapsed: elapsed,
|
|
154
|
+
manifest: manifest,
|
|
155
|
+
environment: 'arborist',
|
|
156
|
+
installedPackages: installedPackages,
|
|
157
|
+
results: installResults
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
} catch (error) {
|
|
161
|
+
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
162
|
+
logger.error(`[PackageInstaller] Installation failed after ${elapsed}s: ${error.message}`);
|
|
163
|
+
|
|
164
|
+
throw new Error(`Arborist installation failed: ${error.message}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* 构建依赖列表字符串用于日志
|
|
170
|
+
* @param {Object|Array} dependencies - 依赖
|
|
171
|
+
* @returns {string} 格式化的依赖列表
|
|
172
|
+
*/
|
|
173
|
+
static buildDependenciesList(dependencies) {
|
|
174
|
+
if (!dependencies) return '';
|
|
175
|
+
|
|
176
|
+
if (typeof dependencies === 'object' && !Array.isArray(dependencies)) {
|
|
177
|
+
// 对象格式:{"package": "version"}
|
|
178
|
+
return Object.keys(dependencies)
|
|
179
|
+
.map(name => `${name}@${dependencies[name]}`)
|
|
180
|
+
.join(', ');
|
|
181
|
+
} else if (Array.isArray(dependencies)) {
|
|
182
|
+
// 数组格式:["package@version"]
|
|
183
|
+
return dependencies.join(', ');
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return String(dependencies);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* 规范化依赖格式为对象
|
|
191
|
+
* @param {Object|Array} dependencies - 原始依赖
|
|
192
|
+
* @returns {Object} 规范化的依赖对象
|
|
193
|
+
*/
|
|
194
|
+
static normalizeDependencies(dependencies) {
|
|
195
|
+
if (!dependencies) return {};
|
|
196
|
+
|
|
197
|
+
if (typeof dependencies === 'object' && !Array.isArray(dependencies)) {
|
|
198
|
+
// 已经是对象格式
|
|
199
|
+
return dependencies;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (Array.isArray(dependencies)) {
|
|
203
|
+
// 数组格式转对象
|
|
204
|
+
const normalized = {};
|
|
205
|
+
for (const dep of dependencies) {
|
|
206
|
+
if (dep.includes('@')) {
|
|
207
|
+
const lastAtIndex = dep.lastIndexOf('@');
|
|
208
|
+
if (lastAtIndex > 0) {
|
|
209
|
+
const name = dep.substring(0, lastAtIndex);
|
|
210
|
+
const version = dep.substring(lastAtIndex + 1);
|
|
211
|
+
normalized[name] = version;
|
|
212
|
+
} else {
|
|
213
|
+
normalized[dep] = 'latest';
|
|
214
|
+
}
|
|
215
|
+
} else {
|
|
216
|
+
normalized[dep] = 'latest';
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return normalized;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return {};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* 检查包是否已安装
|
|
227
|
+
* @param {string} workingDir - 工作目录
|
|
228
|
+
* @param {string} packageName - 包名
|
|
229
|
+
* @returns {Promise<boolean>} 是否已安装
|
|
230
|
+
*/
|
|
231
|
+
static async isPackageInstalled(workingDir, packageName) {
|
|
232
|
+
try {
|
|
233
|
+
const packagePath = packageName.startsWith('@')
|
|
234
|
+
? path.join(workingDir, 'node_modules', ...packageName.split('/'))
|
|
235
|
+
: path.join(workingDir, 'node_modules', packageName);
|
|
236
|
+
|
|
237
|
+
const packageJsonPath = path.join(packagePath, 'package.json');
|
|
238
|
+
await fs.access(packageJsonPath);
|
|
239
|
+
return true;
|
|
240
|
+
} catch {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* 获取已安装包的信息
|
|
247
|
+
* @param {string} workingDir - 工作目录
|
|
248
|
+
* @param {string} packageName - 包名
|
|
249
|
+
* @returns {Promise<Object|null>} 包信息
|
|
250
|
+
*/
|
|
251
|
+
static async getPackageInfo(workingDir, packageName) {
|
|
252
|
+
try {
|
|
253
|
+
const packagePath = packageName.startsWith('@')
|
|
254
|
+
? path.join(workingDir, 'node_modules', ...packageName.split('/'))
|
|
255
|
+
: path.join(workingDir, 'node_modules', packageName);
|
|
256
|
+
|
|
257
|
+
const packageJsonPath = path.join(packagePath, 'package.json');
|
|
258
|
+
const content = await fs.readFile(packageJsonPath, 'utf8');
|
|
259
|
+
return JSON.parse(content);
|
|
260
|
+
} catch {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export default PackageInstaller;
|
|
267
|
+
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 工具系统测试文件
|
|
3
|
+
*
|
|
4
|
+
* 用于验证工具加载、工具管理等功能是否正常工作
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { toolLoaderService } from './tool-loader.service.js';
|
|
8
|
+
import { handleToolM } from './tool-manager.handler.js';
|
|
9
|
+
import { logger } from '../utils/logger.js';
|
|
10
|
+
|
|
11
|
+
// 测试工具加载服务
|
|
12
|
+
async function testToolLoader() {
|
|
13
|
+
console.log('\n========== 测试工具加载服务 ==========\n');
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
// 初始化工具加载器
|
|
17
|
+
console.log('1. 初始化工具加载器...');
|
|
18
|
+
await toolLoaderService.initialize();
|
|
19
|
+
console.log('✓ 工具加载器初始化成功');
|
|
20
|
+
|
|
21
|
+
// 获取所有工具列表
|
|
22
|
+
console.log('\n2. 获取所有工具列表...');
|
|
23
|
+
const tools = toolLoaderService.getAllTools();
|
|
24
|
+
console.log(`✓ 共加载 ${tools.length} 个工具:`);
|
|
25
|
+
tools.forEach(tool => {
|
|
26
|
+
console.log(` - ${tool.name}: ${tool.metadata.description || '无描述'}`);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// 检查 filesystem 工具是否存在
|
|
30
|
+
console.log('\n3. 检查 filesystem 工具是否存在...');
|
|
31
|
+
const hasFilesystem = toolLoaderService.hasTool('filesystem');
|
|
32
|
+
if (hasFilesystem) {
|
|
33
|
+
console.log('✓ filesystem 工具已加载');
|
|
34
|
+
|
|
35
|
+
// 获取 filesystem 工具详情
|
|
36
|
+
const filesystemTool = toolLoaderService.getTool('filesystem');
|
|
37
|
+
console.log(` - 元数据:`, filesystemTool.metadata);
|
|
38
|
+
} else {
|
|
39
|
+
console.log('✗ filesystem 工具未找到');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return true;
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.error('✗ 测试失败:', error.message);
|
|
45
|
+
console.error(error.stack);
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 测试手册模式
|
|
51
|
+
async function testManualMode() {
|
|
52
|
+
console.log('\n========== 测试手册模式 (manual) ==========\n');
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const yamlInput = `tool: tool://filesystem
|
|
56
|
+
mode: manual`;
|
|
57
|
+
|
|
58
|
+
console.log('YAML 输入:');
|
|
59
|
+
console.log(yamlInput);
|
|
60
|
+
console.log('\n执行 handleToolM...');
|
|
61
|
+
|
|
62
|
+
const result = await handleToolM({ yaml: yamlInput });
|
|
63
|
+
|
|
64
|
+
console.log('\n✓ 手册模式执行成功');
|
|
65
|
+
console.log('返回结果类型:', result.content[0].type);
|
|
66
|
+
console.log('手册内容长度:', result.content[0].text.length, '字符');
|
|
67
|
+
console.log('\n手册内容预览(前 500 字符):');
|
|
68
|
+
console.log(result.content[0].text.substring(0, 500));
|
|
69
|
+
console.log('...\n');
|
|
70
|
+
|
|
71
|
+
return true;
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.error('✗ 测试失败:', error.message);
|
|
74
|
+
console.error(error.stack);
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 测试执行模式
|
|
80
|
+
async function testExecuteMode() {
|
|
81
|
+
console.log('\n========== 测试执行模式 (execute) ==========\n');
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
const yamlInput = `tool: tool://filesystem
|
|
85
|
+
mode: execute
|
|
86
|
+
parameters:
|
|
87
|
+
method: list_allowed_directories`;
|
|
88
|
+
|
|
89
|
+
console.log('YAML 输入:');
|
|
90
|
+
console.log(yamlInput);
|
|
91
|
+
console.log('\n执行 handleToolM...');
|
|
92
|
+
|
|
93
|
+
const result = await handleToolM({ yaml: yamlInput });
|
|
94
|
+
|
|
95
|
+
console.log('\n✓ 执行模式测试成功');
|
|
96
|
+
console.log('返回结果:');
|
|
97
|
+
console.log(result.content[0].text);
|
|
98
|
+
|
|
99
|
+
return true;
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.error('✗ 测试失败:', error.message);
|
|
102
|
+
console.error(error.stack);
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// 测试配置模式
|
|
108
|
+
async function testConfigureMode() {
|
|
109
|
+
console.log('\n========== 测试配置模式 (configure) ==========\n');
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
const yamlInput = `tool: tool://filesystem
|
|
113
|
+
mode: configure
|
|
114
|
+
parameters:
|
|
115
|
+
ALLOWED_DIRECTORIES: '["~/.prompt-manager", "/tmp"]'`;
|
|
116
|
+
|
|
117
|
+
console.log('YAML 输入:');
|
|
118
|
+
console.log(yamlInput);
|
|
119
|
+
console.log('\n执行 handleToolM...');
|
|
120
|
+
|
|
121
|
+
const result = await handleToolM({ yaml: yamlInput });
|
|
122
|
+
|
|
123
|
+
console.log('\n✓ 配置模式测试成功');
|
|
124
|
+
console.log('返回结果:');
|
|
125
|
+
console.log(result.content[0].text);
|
|
126
|
+
|
|
127
|
+
return true;
|
|
128
|
+
} catch (error) {
|
|
129
|
+
console.error('✗ 测试失败:', error.message);
|
|
130
|
+
console.error(error.stack);
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// 测试日志模式
|
|
136
|
+
async function testLogMode() {
|
|
137
|
+
console.log('\n========== 测试日志模式 (log) ==========\n');
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
const yamlInput = `tool: tool://filesystem
|
|
141
|
+
mode: log
|
|
142
|
+
parameters:
|
|
143
|
+
action: tail
|
|
144
|
+
lines: 50`;
|
|
145
|
+
|
|
146
|
+
console.log('YAML 输入:');
|
|
147
|
+
console.log(yamlInput);
|
|
148
|
+
console.log('\n执行 handleToolM...');
|
|
149
|
+
|
|
150
|
+
const result = await handleToolM({ yaml: yamlInput });
|
|
151
|
+
|
|
152
|
+
console.log('\n✓ 日志模式测试成功');
|
|
153
|
+
console.log('返回结果:');
|
|
154
|
+
console.log(result.content[0].text);
|
|
155
|
+
|
|
156
|
+
return true;
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.error('✗ 测试失败:', error.message);
|
|
159
|
+
console.error(error.stack);
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// 测试错误处理
|
|
165
|
+
async function testErrorHandling() {
|
|
166
|
+
console.log('\n========== 测试错误处理 ==========\n');
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
console.log('1. 测试不存在的工具...');
|
|
170
|
+
try {
|
|
171
|
+
const yamlInput = `tool: tool://nonexistent
|
|
172
|
+
mode: execute`;
|
|
173
|
+
await handleToolM({ yaml: yamlInput });
|
|
174
|
+
console.log('✗ 应该抛出错误但没有');
|
|
175
|
+
return false;
|
|
176
|
+
} catch (error) {
|
|
177
|
+
console.log('✓ 正确抛出错误:', error.message.split('\n')[0]);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
console.log('\n2. 测试缺少必需参数...');
|
|
181
|
+
try {
|
|
182
|
+
await handleToolM({});
|
|
183
|
+
console.log('✗ 应该抛出错误但没有');
|
|
184
|
+
return false;
|
|
185
|
+
} catch (error) {
|
|
186
|
+
console.log('✓ 正确抛出错误:', error.message);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
console.log('\n3. 测试无效的工具格式...');
|
|
190
|
+
try {
|
|
191
|
+
const yamlInput = `tool: filesystem
|
|
192
|
+
mode: execute`;
|
|
193
|
+
await handleToolM({ yaml: yamlInput });
|
|
194
|
+
console.log('✗ 应该抛出错误但没有');
|
|
195
|
+
return false;
|
|
196
|
+
} catch (error) {
|
|
197
|
+
console.log('✓ 正确抛出错误:', error.message.split('\n')[0]);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return true;
|
|
201
|
+
} catch (error) {
|
|
202
|
+
console.error('✗ 测试失败:', error.message);
|
|
203
|
+
console.error(error.stack);
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// 主测试函数
|
|
209
|
+
async function runAllTests() {
|
|
210
|
+
console.log('\n');
|
|
211
|
+
console.log('╔════════════════════════════════════════════════╗');
|
|
212
|
+
console.log('║ Prompt Manager 工具系统测试套件 ║');
|
|
213
|
+
console.log('╚════════════════════════════════════════════════╝');
|
|
214
|
+
|
|
215
|
+
const results = [];
|
|
216
|
+
|
|
217
|
+
// 运行所有测试
|
|
218
|
+
results.push({ name: '工具加载服务', passed: await testToolLoader() });
|
|
219
|
+
results.push({ name: '手册模式', passed: await testManualMode() });
|
|
220
|
+
results.push({ name: '执行模式', passed: await testExecuteMode() });
|
|
221
|
+
results.push({ name: '配置模式', passed: await testConfigureMode() });
|
|
222
|
+
results.push({ name: '日志模式', passed: await testLogMode() });
|
|
223
|
+
results.push({ name: '错误处理', passed: await testErrorHandling() });
|
|
224
|
+
|
|
225
|
+
// 输出测试总结
|
|
226
|
+
console.log('\n');
|
|
227
|
+
console.log('╔════════════════════════════════════════════════╗');
|
|
228
|
+
console.log('║ 测试结果总结 ║');
|
|
229
|
+
console.log('╚════════════════════════════════════════════════╝');
|
|
230
|
+
console.log('\n');
|
|
231
|
+
|
|
232
|
+
const passed = results.filter(r => r.passed).length;
|
|
233
|
+
const failed = results.filter(r => !r.passed).length;
|
|
234
|
+
|
|
235
|
+
results.forEach(result => {
|
|
236
|
+
const status = result.passed ? '✓ PASS' : '✗ FAIL';
|
|
237
|
+
console.log(`${status} - ${result.name}`);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
console.log('\n');
|
|
241
|
+
console.log(`总计: ${results.length} 个测试`);
|
|
242
|
+
console.log(`通过: ${passed} 个`);
|
|
243
|
+
console.log(`失败: ${failed} 个`);
|
|
244
|
+
console.log('\n');
|
|
245
|
+
|
|
246
|
+
if (failed === 0) {
|
|
247
|
+
console.log('🎉 所有测试通过!工具系统运行正常。');
|
|
248
|
+
} else {
|
|
249
|
+
console.log('⚠️ 部分测试失败,请检查错误信息。');
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return failed === 0;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// 运行测试
|
|
256
|
+
runAllTests()
|
|
257
|
+
.then(success => {
|
|
258
|
+
process.exit(success ? 0 : 1);
|
|
259
|
+
})
|
|
260
|
+
.catch(error => {
|
|
261
|
+
console.error('测试运行失败:', error);
|
|
262
|
+
process.exit(1);
|
|
263
|
+
});
|
|
264
|
+
|