@becrafter/prompt-manager 0.1.22 → 0.2.2
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/package.json +31 -24
- package/packages/resources/tools/agent-browser/README.md +640 -0
- package/packages/resources/tools/agent-browser/agent-browser.tool.js +1389 -0
- package/packages/resources/tools/thinking/README.md +324 -0
- package/packages/resources/tools/thinking/thinking.tool.js +911 -0
- package/packages/server/README.md +3 -4
- package/packages/server/api/admin.routes.js +668 -664
- package/packages/server/api/open.routes.js +68 -67
- package/packages/server/api/surge.routes.js +5 -6
- package/packages/server/api/tool.routes.js +70 -71
- package/packages/server/app.js +70 -73
- package/packages/server/configs/authors.json +40 -0
- package/packages/server/configs/models/built-in/bigmodel.yaml +6 -6
- package/packages/server/configs/models/providers.yaml +4 -4
- package/packages/server/configs/templates/built-in/general-iteration.yaml +1 -1
- package/packages/server/configs/templates/built-in/general-optimize.yaml +1 -1
- package/packages/server/configs/templates/built-in/output-format-optimize.yaml +1 -1
- package/packages/server/index.js +3 -9
- package/packages/server/mcp/heartbeat-patch.js +1 -3
- package/packages/server/mcp/mcp.server.js +64 -134
- package/packages/server/mcp/prompt.handler.js +101 -95
- package/packages/server/middlewares/auth.middleware.js +31 -31
- package/packages/server/server.js +60 -45
- package/packages/server/services/TerminalService.js +156 -70
- package/packages/server/services/WebSocketService.js +35 -34
- package/packages/server/services/author-config.service.js +199 -0
- package/packages/server/services/manager.js +66 -60
- package/packages/server/services/model.service.js +5 -9
- package/packages/server/services/optimization.service.js +25 -22
- package/packages/server/services/template.service.js +3 -8
- package/packages/server/toolm/author-sync.service.js +97 -0
- package/packages/server/toolm/index.js +1 -2
- package/packages/server/toolm/package-installer.service.js +47 -50
- package/packages/server/toolm/tool-context.service.js +64 -62
- package/packages/server/toolm/tool-dependency.service.js +28 -30
- package/packages/server/toolm/tool-description-generator-optimized.service.js +55 -55
- package/packages/server/toolm/tool-description-generator.service.js +20 -23
- package/packages/server/toolm/tool-environment.service.js +45 -44
- package/packages/server/toolm/tool-execution.service.js +49 -48
- package/packages/server/toolm/tool-loader.service.js +13 -18
- package/packages/server/toolm/tool-logger.service.js +33 -39
- package/packages/server/toolm/tool-manager.handler.js +17 -15
- package/packages/server/toolm/tool-manual-generator.service.js +107 -87
- package/packages/server/toolm/tool-mode-handlers.service.js +52 -59
- package/packages/server/toolm/tool-storage.service.js +11 -12
- package/packages/server/toolm/tool-sync.service.js +36 -39
- package/packages/server/toolm/tool-utils.js +0 -1
- package/packages/server/toolm/tool-yaml-parser.service.js +12 -11
- package/packages/server/toolm/validate-system.js +56 -84
- package/packages/server/utils/config.js +97 -12
- package/packages/server/utils/logger.js +1 -1
- package/packages/server/utils/port-checker.js +8 -8
- package/packages/server/utils/util.js +470 -467
- package/packages/resources/tools/cognitive-thinking/README.md +0 -284
- package/packages/resources/tools/cognitive-thinking/cognitive-thinking.tool.js +0 -837
- package/packages/server/mcp/sequential-thinking.handler.js +0 -318
- package/packages/server/mcp/think-plan.handler.js +0 -274
- package/packages/server/mcp/thinking-toolkit.handler.js +0 -380
- package/packages/web/0.d1c5a72339dfc32ad86a.js +0 -1
- package/packages/web/112.8807b976372b2b0541a8.js +0 -1
- package/packages/web/130.584c7e365da413f5d9be.js +0 -1
- package/packages/web/142.72c985bc29720f975cca.js +0 -1
- package/packages/web/165.a05fc53bf84d18db36b8.js +0 -2
- package/packages/web/165.a05fc53bf84d18db36b8.js.LICENSE.txt +0 -9
- package/packages/web/203.724ab9f717b80554c397.js +0 -1
- package/packages/web/241.bf941d4f02866795f64a.js +0 -1
- package/packages/web/249.54cfb224af63f5f5ec55.js +0 -1
- package/packages/web/291.6df35042f8f296fca7cd.js +0 -1
- package/packages/web/319.2fab900a31b29873f666.js +0 -1
- package/packages/web/32.c78d866281995ec33a7b.js +0 -1
- package/packages/web/325.9ca297d0f73f38468ce9.js +0 -1
- package/packages/web/366.2f9b48fdbf8eee039e57.js +0 -1
- package/packages/web/378.6be08c612cd5a3ef97dc.js +0 -1
- package/packages/web/393.7a2f817515c5e90623d7.js +0 -1
- package/packages/web/412.062df5f732d5ba203415.js +0 -1
- package/packages/web/426.08656fef4918b3fb19ad.js +0 -1
- package/packages/web/465.2be8018327130a3bd798.js +0 -1
- package/packages/web/48.8ca96fc93667a715e67a.js +0 -1
- package/packages/web/480.44c1f1a2927486ac3d4f.js +0 -1
- package/packages/web/489.e041a8d0db15dc96d607.js +0 -1
- package/packages/web/490.9ffb26c907de020d671b.js +0 -1
- package/packages/web/492.58781369e348d91fc06a.js +0 -1
- package/packages/web/495.ed63e99791a87167c6b3.js +0 -1
- package/packages/web/510.4cc07ab7d30d5c1cd17f.js +0 -1
- package/packages/web/543.3af155ed4fa237664308.js +0 -1
- package/packages/web/567.f04ab60f8e2c2fb0745a.js +0 -1
- package/packages/web/592.f3ad085fa9c1849daa06.js +0 -1
- package/packages/web/616.b03fb801b3433b17750f.js +0 -1
- package/packages/web/617.d88def54921d2c4dc44c.js +0 -1
- package/packages/web/641.d30787d674f548928261.js +0 -1
- package/packages/web/672.5269c8399fa42a5af95d.js +0 -1
- package/packages/web/731.97cab92b71811c502bda.js +0 -1
- package/packages/web/746.3947c6f0235407e420fb.js +0 -1
- package/packages/web/756.a53233b3f3913900d5ac.js +0 -1
- package/packages/web/77.68801af593a28a631fbf.js +0 -1
- package/packages/web/802.53b2bff3cf2a69f7b80c.js +0 -1
- package/packages/web/815.b6dfab82265f56c7e046.js +0 -1
- package/packages/web/821.f5a13e5c735aac244eb9.js +0 -1
- package/packages/web/846.b9bf97d5f559270675ce.js +0 -1
- package/packages/web/869.7c10403f500e6201407f.js +0 -1
- package/packages/web/885.135050364f99e6924fb5.js +0 -1
- package/packages/web/901.fd5aeb9df630609a2b43.js +0 -1
- package/packages/web/928.f67e590de3caa4daa3ae.js +0 -1
- package/packages/web/955.d833403521ba4dd567ee.js +0 -1
- package/packages/web/981.a45cb745cf424044c8c8.js +0 -1
- package/packages/web/992.645320b60c74c8787482.js +0 -1
- package/packages/web/996.ed9a963dc9e7439eca9a.js +0 -1
- package/packages/web/css/codemirror-theme_xq-light.css +0 -43
- package/packages/web/css/codemirror.css +0 -344
- package/packages/web/css/main.196f434e6a88cd448158.css +0 -7278
- package/packages/web/css/terminal-fix.css +0 -571
- package/packages/web/index.html +0 -3
- package/packages/web/main.dceff50c7307dda04873.js +0 -2
- package/packages/web/main.dceff50c7307dda04873.js.LICENSE.txt +0 -3
|
@@ -1,537 +1,540 @@
|
|
|
1
1
|
import crypto from 'crypto';
|
|
2
|
-
import
|
|
3
|
-
import os from 'os';
|
|
4
|
-
import path from 'path';
|
|
2
|
+
import { logger } from './logger.js';
|
|
5
3
|
import fse from 'fs-extra';
|
|
6
|
-
import yaml from 'js-yaml';
|
|
7
4
|
import { fileURLToPath } from 'url';
|
|
8
|
-
import
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import fs from 'fs';
|
|
7
|
+
import yaml from 'js-yaml';
|
|
8
|
+
import { config } from './config.js';
|
|
9
9
|
|
|
10
|
-
export const GROUP_META_FILENAME = '.groupmeta.json';
|
|
11
10
|
// 允许中文、空格、emoji 等字符,禁止路径分隔符及常见非法文件名字符
|
|
12
11
|
export const GROUP_NAME_REGEX = /^(?![.]{1,2}$)[^\\/:*?"<>|\r\n]{1,64}$/;
|
|
12
|
+
export const GROUP_META_FILENAME = 'group.meta.json';
|
|
13
13
|
|
|
14
14
|
// 获取当前文件的目录路径
|
|
15
15
|
const __filename = fileURLToPath(import.meta.url);
|
|
16
16
|
const __dirname = path.dirname(__filename);
|
|
17
17
|
const projectRoot = path.resolve(__dirname, '../../..');
|
|
18
18
|
const examplesPromptsRoot = path.join(projectRoot, 'examples', 'prompts');
|
|
19
|
-
const promptsDir =
|
|
19
|
+
const promptsDir = config.getPromptsDir();
|
|
20
20
|
|
|
21
21
|
let _promptManager;
|
|
22
22
|
|
|
23
23
|
export class Util {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
try {
|
|
39
|
-
const exists = await fse.pathExists(examplesPromptsRoot);
|
|
40
|
-
if (!exists) {
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
await fse.copy(examplesPromptsRoot, promptsDir, {
|
|
44
|
-
overwrite: false,
|
|
45
|
-
errorOnExist: false,
|
|
46
|
-
recursive: true
|
|
47
|
-
});
|
|
48
|
-
logger.info(`已将示例Prompts同步到 ${promptsDir}`);
|
|
49
|
-
} catch (error) {
|
|
50
|
-
logger.warn('同步示例Prompts失败:', error.message);
|
|
51
|
-
}
|
|
24
|
+
/**
|
|
25
|
+
* 检查并初始化prompts目录,如果目录为空则从示例目录复制内容
|
|
26
|
+
* @returns
|
|
27
|
+
*/
|
|
28
|
+
async seedPromptsIfEmpty() {
|
|
29
|
+
try {
|
|
30
|
+
const entries = await fse.readdir(promptsDir);
|
|
31
|
+
if (entries.length > 0) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
} catch (error) {
|
|
35
|
+
logger.warn('读取Prompts目录失败,尝试同步示例数据:', error.message);
|
|
52
36
|
}
|
|
53
37
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// 确保用户配置目录存在
|
|
71
|
-
await fse.ensureDir(userConfigDir);
|
|
72
|
-
|
|
73
|
-
// 同步模型配置
|
|
74
|
-
const modelsSrc = path.join(builtInConfigsDir, 'models');
|
|
75
|
-
const modelsDst = path.join(userConfigDir, 'models');
|
|
76
|
-
if (await fse.pathExists(modelsSrc)) {
|
|
77
|
-
await fse.copy(modelsSrc, modelsDst, {
|
|
78
|
-
overwrite: false,
|
|
79
|
-
errorOnExist: false,
|
|
80
|
-
recursive: true
|
|
81
|
-
});
|
|
82
|
-
logger.info(`已同步内置模型配置到 ${modelsDst}`);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// 同步模板配置
|
|
86
|
-
const templatesSrc = path.join(builtInConfigsDir, 'templates');
|
|
87
|
-
const templatesDst = path.join(userConfigDir, 'templates');
|
|
88
|
-
if (await fse.pathExists(templatesSrc)) {
|
|
89
|
-
await fse.copy(templatesSrc, templatesDst, {
|
|
90
|
-
overwrite: false,
|
|
91
|
-
errorOnExist: false,
|
|
92
|
-
recursive: true
|
|
93
|
-
});
|
|
94
|
-
logger.info(`已同步内置模板配置到 ${templatesDst}`);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
} catch (error) {
|
|
98
|
-
logger.warn('同步内置配置失败:', error.message);
|
|
99
|
-
}
|
|
38
|
+
try {
|
|
39
|
+
const exists = await fse.pathExists(examplesPromptsRoot);
|
|
40
|
+
if (!exists) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
await fse.copy(examplesPromptsRoot, promptsDir, {
|
|
44
|
+
overwrite: false,
|
|
45
|
+
errorOnExist: false,
|
|
46
|
+
recursive: true
|
|
47
|
+
});
|
|
48
|
+
logger.info(`已将示例Prompts同步到 ${promptsDir}`);
|
|
49
|
+
} catch (error) {
|
|
50
|
+
logger.warn('同步示例Prompts失败:', error.message);
|
|
100
51
|
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 初始化内置配置(如果不存在)
|
|
56
|
+
* 同步内置的模型配置和模板到用户配置目录
|
|
57
|
+
*/
|
|
58
|
+
async seedBuiltInConfigsIfEmpty() {
|
|
59
|
+
try {
|
|
60
|
+
const userConfigDir = config.getConfigsDir();
|
|
61
|
+
const builtInConfigsDir = this.getBuiltInConfigsDir();
|
|
62
|
+
|
|
63
|
+
// 检查内置配置目录是否存在
|
|
64
|
+
const builtInExists = await fse.pathExists(builtInConfigsDir);
|
|
65
|
+
if (!builtInExists) {
|
|
66
|
+
logger.debug('内置配置目录不存在,跳过同步');
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
101
69
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
70
|
+
// 确保用户配置目录存在
|
|
71
|
+
await fse.ensureDir(userConfigDir);
|
|
72
|
+
|
|
73
|
+
// 同步模型配置
|
|
74
|
+
const modelsSrc = path.join(builtInConfigsDir, 'models');
|
|
75
|
+
const modelsDst = path.join(userConfigDir, 'models');
|
|
76
|
+
if (await fse.pathExists(modelsSrc)) {
|
|
77
|
+
await fse.copy(modelsSrc, modelsDst, {
|
|
78
|
+
overwrite: false,
|
|
79
|
+
errorOnExist: false,
|
|
80
|
+
recursive: true
|
|
81
|
+
});
|
|
82
|
+
logger.info(`已同步内置模型配置到 ${modelsDst}`);
|
|
83
|
+
}
|
|
113
84
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
85
|
+
// 同步模板配置
|
|
86
|
+
const templatesSrc = path.join(builtInConfigsDir, 'templates');
|
|
87
|
+
const templatesDst = path.join(userConfigDir, 'templates');
|
|
88
|
+
if (await fse.pathExists(templatesSrc)) {
|
|
89
|
+
await fse.copy(templatesSrc, templatesDst, {
|
|
90
|
+
overwrite: false,
|
|
91
|
+
errorOnExist: false,
|
|
92
|
+
recursive: true
|
|
93
|
+
});
|
|
94
|
+
logger.info(`已同步内置模板配置到 ${templatesDst}`);
|
|
95
|
+
}
|
|
96
|
+
} catch (error) {
|
|
97
|
+
logger.warn('同步内置配置失败:', error.message);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* 生成文件唯一标识码
|
|
103
|
+
* @param {*} relativePath
|
|
104
|
+
* @returns
|
|
105
|
+
*/
|
|
106
|
+
generateUniqueId(relativePath) {
|
|
107
|
+
const hash = crypto.createHash('sha256');
|
|
108
|
+
hash.update(relativePath);
|
|
109
|
+
const hashHex = hash.digest('hex');
|
|
110
|
+
return hashHex.substring(0, 8);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* 从文件中读取提示词
|
|
115
|
+
* @returns
|
|
116
|
+
*/
|
|
117
|
+
getPromptsFromFiles() {
|
|
118
|
+
const prompts = [];
|
|
119
|
+
|
|
120
|
+
const traverseDir = (currentPath, relativeDir = '', inheritedEnabled = true) => {
|
|
121
|
+
let currentEnabled = inheritedEnabled;
|
|
122
|
+
if (relativeDir) {
|
|
123
|
+
const meta = this.readGroupMeta(currentPath);
|
|
124
|
+
currentEnabled = currentEnabled && meta.enabled !== false;
|
|
125
|
+
}
|
|
127
126
|
|
|
127
|
+
try {
|
|
128
|
+
const entries = fs.readdirSync(currentPath, { withFileTypes: true });
|
|
129
|
+
for (const entry of entries) {
|
|
130
|
+
const fullPath = path.join(currentPath, entry.name);
|
|
131
|
+
if (entry.isDirectory()) {
|
|
132
|
+
const childRelativePath = relativeDir ? `${relativeDir}/${entry.name}` : entry.name;
|
|
133
|
+
traverseDir(fullPath, childRelativePath, currentEnabled);
|
|
134
|
+
} else if (entry.isFile() && entry.name.endsWith('.yaml')) {
|
|
128
135
|
try {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
group: topLevelGroup,
|
|
151
|
-
groupPath,
|
|
152
|
-
groupEnabled: currentEnabled
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
} catch (error) {
|
|
156
|
-
logger.error(`Error processing file ${fullPath}:`, error);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
136
|
+
const fileContent = fs.readFileSync(fullPath, 'utf8');
|
|
137
|
+
const prompt = yaml.load(fileContent);
|
|
138
|
+
if (prompt && prompt.name) {
|
|
139
|
+
const relativePath = path.relative(promptsDir, fullPath);
|
|
140
|
+
const normalizedRelativePath = relativePath.split(path.sep).join('/');
|
|
141
|
+
const relativeDirForFile = path.dirname(normalizedRelativePath);
|
|
142
|
+
const topLevelGroup =
|
|
143
|
+
relativeDirForFile && relativeDirForFile !== '.'
|
|
144
|
+
? relativeDirForFile.split('/')[0]
|
|
145
|
+
: prompt.group || 'default';
|
|
146
|
+
const groupPath = relativeDirForFile && relativeDirForFile !== '.' ? relativeDirForFile : topLevelGroup;
|
|
147
|
+
prompts.push({
|
|
148
|
+
...prompt,
|
|
149
|
+
uniqueId: this.generateUniqueId(`${prompt.name}.yaml`),
|
|
150
|
+
fileName: entry.name,
|
|
151
|
+
relativePath: normalizedRelativePath,
|
|
152
|
+
group: topLevelGroup,
|
|
153
|
+
groupPath,
|
|
154
|
+
groupEnabled: currentEnabled
|
|
155
|
+
});
|
|
156
|
+
}
|
|
160
157
|
} catch (error) {
|
|
161
|
-
|
|
158
|
+
logger.error(`Error processing file ${fullPath}:`, error);
|
|
162
159
|
}
|
|
160
|
+
}
|
|
163
161
|
}
|
|
162
|
+
} catch (error) {
|
|
163
|
+
logger.error(`Error reading directory ${currentPath}:`, error);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
164
166
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
// 计算name匹配得分
|
|
186
|
-
if (prompt && prompt.name && typeof prompt.name === 'string') {
|
|
187
|
-
const nameScore = util.getStringMatchScore(searchLower, prompt.name.toLowerCase());
|
|
188
|
-
totalScore += nameScore * fieldWeights.name;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// 计算description匹配得分
|
|
192
|
-
if (prompt.description) {
|
|
193
|
-
const descScore = util.getStringMatchScore(searchLower, prompt.description.toLowerCase());
|
|
194
|
-
totalScore += descScore * fieldWeights.description;
|
|
195
|
-
}
|
|
167
|
+
traverseDir(promptsDir);
|
|
168
|
+
return prompts;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* 计算搜索关键词与prompt的相似度得分
|
|
173
|
+
* @param {string} searchTerm - 搜索关键词
|
|
174
|
+
* @param {Object} prompt - prompt对象
|
|
175
|
+
* @returns {number} 相似度得分 (0-100)
|
|
176
|
+
*/
|
|
177
|
+
calculateSimilarityScore(searchTerm, prompt) {
|
|
178
|
+
let totalScore = 0;
|
|
179
|
+
const searchLower = searchTerm ? searchTerm.toLowerCase() : '';
|
|
180
|
+
|
|
181
|
+
// 搜索字段权重配置(专注于内容搜索,不包含ID检索)
|
|
182
|
+
const fieldWeights = {
|
|
183
|
+
name: 60, // 名称权重高,是主要匹配字段
|
|
184
|
+
description: 40 // 描述权重适中,是辅助匹配字段
|
|
185
|
+
};
|
|
196
186
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
187
|
+
// 计算name匹配得分
|
|
188
|
+
if (prompt && prompt.name && typeof prompt.name === 'string') {
|
|
189
|
+
const nameScore = util.getStringMatchScore(searchLower, prompt.name.toLowerCase());
|
|
190
|
+
totalScore += nameScore * fieldWeights.name;
|
|
200
191
|
}
|
|
201
192
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
*/
|
|
208
|
-
getStringMatchScore(search, target) {
|
|
209
|
-
if (!search || !target) return 0;
|
|
210
|
-
|
|
211
|
-
// 完全匹配得分最高
|
|
212
|
-
if (target === search) return 1.0;
|
|
213
|
-
|
|
214
|
-
// 完全包含得分较高
|
|
215
|
-
if (target.includes(search)) return 0.8;
|
|
216
|
-
|
|
217
|
-
// 部分词匹配
|
|
218
|
-
const searchWords = search.split(/\s+/).filter(word => word.length > 0);
|
|
219
|
-
const targetWords = target.split(/\s+/).filter(word => word.length > 0);
|
|
220
|
-
|
|
221
|
-
let matchedWords = 0;
|
|
222
|
-
for (const searchWord of searchWords) {
|
|
223
|
-
for (const targetWord of targetWords) {
|
|
224
|
-
if (targetWord.includes(searchWord) || searchWord.includes(targetWord)) {
|
|
225
|
-
matchedWords++;
|
|
226
|
-
break;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
193
|
+
// 计算description匹配得分
|
|
194
|
+
if (prompt.description) {
|
|
195
|
+
const descScore = util.getStringMatchScore(searchLower, prompt.description.toLowerCase());
|
|
196
|
+
totalScore += descScore * fieldWeights.description;
|
|
197
|
+
}
|
|
230
198
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
199
|
+
// 标准化得分到0-100范围
|
|
200
|
+
const maxPossibleScore = Object.values(fieldWeights).reduce((sum, weight) => sum + weight, 0);
|
|
201
|
+
return Math.round((totalScore / maxPossibleScore) * 100);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* 计算两个字符串的匹配得分
|
|
206
|
+
* @param {string} search - 搜索词 (已转小写)
|
|
207
|
+
* @param {string} target - 目标字符串 (已转小写)
|
|
208
|
+
* @returns {number} 匹配得分 (0-1)
|
|
209
|
+
*/
|
|
210
|
+
getStringMatchScore(search, target) {
|
|
211
|
+
if (!search || !target) return 0;
|
|
212
|
+
|
|
213
|
+
// 完全匹配得分最高
|
|
214
|
+
if (target === search) return 1.0;
|
|
215
|
+
|
|
216
|
+
// 完全包含得分较高
|
|
217
|
+
if (target.includes(search)) return 0.8;
|
|
218
|
+
|
|
219
|
+
// 部分词匹配
|
|
220
|
+
const searchWords = search.split(/\s+/).filter(word => word.length > 0);
|
|
221
|
+
const targetWords = target.split(/\s+/).filter(word => word.length > 0);
|
|
222
|
+
|
|
223
|
+
let matchedWords = 0;
|
|
224
|
+
for (const searchWord of searchWords) {
|
|
225
|
+
for (const targetWord of targetWords) {
|
|
226
|
+
if (targetWord.includes(searchWord) || searchWord.includes(targetWord)) {
|
|
227
|
+
matchedWords++;
|
|
228
|
+
break;
|
|
234
229
|
}
|
|
235
|
-
|
|
236
|
-
return 0;
|
|
230
|
+
}
|
|
237
231
|
}
|
|
238
232
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
* @param {*} meta
|
|
243
|
-
*/
|
|
244
|
-
writeGroupMeta(dir, meta = {}) {
|
|
245
|
-
const metaPath = this.getGroupMetaPath(dir);
|
|
246
|
-
const data = {
|
|
247
|
-
enabled: meta.enabled !== false
|
|
248
|
-
};
|
|
249
|
-
fs.writeFileSync(metaPath, JSON.stringify(data, null, 2), 'utf8');
|
|
233
|
+
if (searchWords.length > 0) {
|
|
234
|
+
const wordMatchRatio = matchedWords / searchWords.length;
|
|
235
|
+
return wordMatchRatio * 0.6; // 部分词匹配得分
|
|
250
236
|
}
|
|
251
237
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
238
|
+
return 0;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* 更新目录元数据
|
|
243
|
+
* @param {*} dir
|
|
244
|
+
* @param {*} meta
|
|
245
|
+
*/
|
|
246
|
+
writeGroupMeta(dir, meta = {}) {
|
|
247
|
+
const metaPath = this.getGroupMetaPath(dir);
|
|
248
|
+
const data = {
|
|
249
|
+
enabled: meta.enabled !== false
|
|
250
|
+
};
|
|
251
|
+
fs.writeFileSync(metaPath, JSON.stringify(data, null, 2), 'utf8');
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* 验证目录名称是否有效
|
|
256
|
+
* @param {*} name
|
|
257
|
+
* @returns
|
|
258
|
+
*/
|
|
259
|
+
isValidGroupName(name) {
|
|
260
|
+
if (typeof name !== 'string') return false;
|
|
261
|
+
return GROUP_NAME_REGEX.test(name);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* 验证目录名称
|
|
266
|
+
* @param {*} relativePath
|
|
267
|
+
* @returns
|
|
268
|
+
*/
|
|
269
|
+
validateGroupPath(relativePath) {
|
|
270
|
+
if (!relativePath || typeof relativePath !== 'string') {
|
|
271
|
+
return null;
|
|
260
272
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
* @param {*} relativePath
|
|
265
|
-
* @returns
|
|
266
|
-
*/
|
|
267
|
-
validateGroupPath(relativePath) {
|
|
268
|
-
if (!relativePath || typeof relativePath !== 'string') {
|
|
269
|
-
return null;
|
|
270
|
-
}
|
|
271
|
-
const segments = relativePath.split('/').filter(Boolean);
|
|
272
|
-
if (!segments.length) {
|
|
273
|
-
return null;
|
|
274
|
-
}
|
|
275
|
-
for (const segment of segments) {
|
|
276
|
-
if (!this.isValidGroupName(segment)) {
|
|
277
|
-
return null;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
return segments;
|
|
273
|
+
const segments = relativePath.split('/').filter(Boolean);
|
|
274
|
+
if (!segments.length) {
|
|
275
|
+
return null;
|
|
281
276
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
* @returns
|
|
287
|
-
*/
|
|
288
|
-
resolveGroupDir(relativePath) {
|
|
289
|
-
const segments = this.validateGroupPath(relativePath);
|
|
290
|
-
if (!segments) return null;
|
|
291
|
-
const targetPath = path.resolve(promptsDir, ...segments);
|
|
292
|
-
const normalizedPromptsDir = path.resolve(promptsDir);
|
|
293
|
-
if (!targetPath.startsWith(normalizedPromptsDir)) {
|
|
294
|
-
return null;
|
|
295
|
-
}
|
|
296
|
-
return { dir: targetPath, segments };
|
|
277
|
+
for (const segment of segments) {
|
|
278
|
+
if (!this.isValidGroupName(segment)) {
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
297
281
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
282
|
+
return segments;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
*
|
|
287
|
+
* @param {*} relativePath
|
|
288
|
+
* @returns
|
|
289
|
+
*/
|
|
290
|
+
resolveGroupDir(relativePath) {
|
|
291
|
+
const segments = this.validateGroupPath(relativePath);
|
|
292
|
+
if (!segments) return null;
|
|
293
|
+
const targetPath = path.resolve(promptsDir, ...segments);
|
|
294
|
+
const normalizedPromptsDir = path.resolve(promptsDir);
|
|
295
|
+
if (!targetPath.startsWith(normalizedPromptsDir)) {
|
|
296
|
+
return null;
|
|
306
297
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
298
|
+
return { dir: targetPath, segments };
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* 获取目录元数据文件路径
|
|
303
|
+
* @param {*} dir
|
|
304
|
+
* @returns
|
|
305
|
+
*/
|
|
306
|
+
getGroupMetaPath(dir) {
|
|
307
|
+
return path.join(dir, GROUP_META_FILENAME);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* 读取目录元数据
|
|
312
|
+
* @param {*} dir
|
|
313
|
+
* @returns
|
|
314
|
+
*/
|
|
315
|
+
readGroupMeta(dir) {
|
|
316
|
+
try {
|
|
317
|
+
const metaPath = this.getGroupMetaPath(dir);
|
|
318
|
+
if (!fs.existsSync(metaPath)) {
|
|
319
|
+
return { enabled: true };
|
|
320
|
+
}
|
|
321
|
+
const raw = fs.readFileSync(metaPath, 'utf8');
|
|
322
|
+
const data = JSON.parse(raw);
|
|
323
|
+
return {
|
|
324
|
+
enabled: data.enabled !== false
|
|
325
|
+
};
|
|
326
|
+
} catch (error) {
|
|
327
|
+
logger.warn('读取类目元数据失败:', error);
|
|
328
|
+
return { enabled: true };
|
|
328
329
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
nodes.sort((a, b) => a.name.localeCompare(b.name, 'zh-CN'));
|
|
358
|
-
return nodes;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* 获取所有分组(直接从目录读取)
|
|
334
|
+
* @param {*} baseDir
|
|
335
|
+
* @param {*} relativePath
|
|
336
|
+
* @returns
|
|
337
|
+
*/
|
|
338
|
+
buildGroupTree(baseDir, relativePath = '') {
|
|
339
|
+
const nodes = [];
|
|
340
|
+
try {
|
|
341
|
+
const entries = fs.readdirSync(baseDir, { withFileTypes: true });
|
|
342
|
+
for (const entry of entries) {
|
|
343
|
+
if (!entry.isDirectory()) continue;
|
|
344
|
+
if (entry.name.startsWith('.')) continue;
|
|
345
|
+
const childRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
|
|
346
|
+
const childDir = path.join(baseDir, entry.name);
|
|
347
|
+
const children = this.buildGroupTree(childDir, childRelativePath);
|
|
348
|
+
const meta = this.readGroupMeta(childDir);
|
|
349
|
+
nodes.push({
|
|
350
|
+
name: entry.name,
|
|
351
|
+
path: childRelativePath,
|
|
352
|
+
children,
|
|
353
|
+
enabled: meta.enabled !== false
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
} catch (error) {
|
|
357
|
+
logger.error('读取分组目录失败:', error);
|
|
359
358
|
}
|
|
359
|
+
nodes.sort((a, b) => a.name.localeCompare(b.name, 'zh-CN'));
|
|
360
|
+
return nodes;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
async processPromptContent(prompt, args) {
|
|
364
|
+
let content = '';
|
|
365
|
+
|
|
366
|
+
if (prompt.messages && Array.isArray(prompt.messages)) {
|
|
367
|
+
const userMessages = prompt.messages.filter(msg => msg.role === 'user');
|
|
368
|
+
|
|
369
|
+
for (const message of userMessages) {
|
|
370
|
+
if (message.content && typeof message.content.text === 'string') {
|
|
371
|
+
let text = message.content.text;
|
|
360
372
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
for (const message of userMessages) {
|
|
368
|
-
if (message.content && typeof message.content.text === 'string') {
|
|
369
|
-
let text = message.content.text;
|
|
370
|
-
|
|
371
|
-
// Replace arguments
|
|
372
|
-
if (args) {
|
|
373
|
-
for (const [key, value] of Object.entries(args)) {
|
|
374
|
-
const placeholder = new RegExp(`{{${key}}}`, 'g');
|
|
375
|
-
text = text.replace(placeholder, String(value));
|
|
376
|
-
}
|
|
373
|
+
// Replace arguments
|
|
374
|
+
if (args) {
|
|
375
|
+
for (const [key, value] of Object.entries(args)) {
|
|
376
|
+
const placeholder = new RegExp(`{{${key}}}`, 'g');
|
|
377
|
+
text = text.replace(placeholder, String(value));
|
|
377
378
|
}
|
|
378
|
-
|
|
379
|
-
content += text + '\n\n';
|
|
380
379
|
}
|
|
380
|
+
|
|
381
|
+
content += `${text}\n\n`;
|
|
381
382
|
}
|
|
382
383
|
}
|
|
383
|
-
|
|
384
|
-
return content.trim();
|
|
385
384
|
}
|
|
386
385
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
const __dirname = path.dirname(__filename);
|
|
390
|
-
|
|
391
|
-
console.log('🔍 getWebUiRoot() called from:', __dirname);
|
|
386
|
+
return content.trim();
|
|
387
|
+
}
|
|
392
388
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
process.versions.electron;
|
|
389
|
+
getWebUiRoot() {
|
|
390
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
391
|
+
const __dirname = path.dirname(__filename);
|
|
397
392
|
|
|
398
|
-
|
|
399
|
-
if (isElectron && process.resourcesPath) {
|
|
400
|
-
const ourAppAsar = path.join(process.resourcesPath, 'app.asar');
|
|
401
|
-
if (fs.existsSync(ourAppAsar)) {
|
|
402
|
-
const asarPath = path.join(process.resourcesPath, 'app.asar', 'web');
|
|
403
|
-
console.log('📦 Using Electron ASAR path:', asarPath);
|
|
404
|
-
return asarPath;
|
|
405
|
-
}
|
|
406
|
-
}
|
|
393
|
+
console.log('🔍 getWebUiRoot() called from:', __dirname);
|
|
407
394
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
console.log('🔍 Checking dev path:', devWebPath);
|
|
411
|
-
if (this._pathExistsSync(devWebPath)) {
|
|
412
|
-
console.log('✅ Using dev environment path:', devWebPath);
|
|
413
|
-
return devWebPath;
|
|
414
|
-
}
|
|
395
|
+
// 检查是否在 Electron 环境中运行
|
|
396
|
+
const isElectron = typeof process !== 'undefined' && process.versions && process.versions.electron;
|
|
415
397
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
const
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
console.log('🔍 Checking npm package path:', webPath);
|
|
426
|
-
if (this._pathExistsSync(webPath)) {
|
|
427
|
-
console.log('✅ Found web UI in npm package:', webPath);
|
|
428
|
-
return webPath;
|
|
429
|
-
}
|
|
398
|
+
// 检查是否是打包应用
|
|
399
|
+
if (isElectron && process.resourcesPath) {
|
|
400
|
+
const ourAppAsar = path.join(process.resourcesPath, 'app.asar');
|
|
401
|
+
if (fs.existsSync(ourAppAsar)) {
|
|
402
|
+
const asarPath = path.join(process.resourcesPath, 'app.asar', 'web');
|
|
403
|
+
console.log('📦 Using Electron ASAR path:', asarPath);
|
|
404
|
+
return asarPath;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
430
407
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
408
|
+
// 在开发环境中,web UI 位于项目目录中的 packages/web
|
|
409
|
+
const devWebPath = path.join(__dirname, '..', '..', 'web');
|
|
410
|
+
console.log('🔍 Checking dev path:', devWebPath);
|
|
411
|
+
if (this._pathExistsSync(devWebPath)) {
|
|
412
|
+
console.log('✅ Using dev environment path:', devWebPath);
|
|
413
|
+
return devWebPath;
|
|
414
|
+
}
|
|
438
415
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
416
|
+
// 在 npm 包环境中,查找 packages/web
|
|
417
|
+
// 从当前文件位置向上查找可能的包根目录
|
|
418
|
+
let currentDir = __dirname;
|
|
419
|
+
let searchDepth = 0;
|
|
420
|
+
const maxDepth = 5;
|
|
421
|
+
|
|
422
|
+
while (searchDepth < maxDepth) {
|
|
423
|
+
// 检查 packages/web
|
|
424
|
+
const webPath = path.join(currentDir, 'packages', 'web');
|
|
425
|
+
console.log('🔍 Checking npm package path:', webPath);
|
|
426
|
+
if (this._pathExistsSync(webPath)) {
|
|
427
|
+
console.log('✅ Found web UI in npm package:', webPath);
|
|
428
|
+
return webPath;
|
|
429
|
+
}
|
|
448
430
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
431
|
+
// 检查直接的 web 目录(某些打包场景)
|
|
432
|
+
const altWebPath = path.join(currentDir, 'web');
|
|
433
|
+
console.log('🔍 Checking alternative path:', altWebPath);
|
|
434
|
+
if (this._pathExistsSync(altWebPath)) {
|
|
435
|
+
console.log('✅ Found web UI in alternative path:', altWebPath);
|
|
436
|
+
return altWebPath;
|
|
437
|
+
}
|
|
456
438
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
439
|
+
// 向上查找
|
|
440
|
+
const parentDir = path.dirname(currentDir);
|
|
441
|
+
if (parentDir === currentDir) {
|
|
442
|
+
// 已经到达根目录
|
|
443
|
+
break;
|
|
444
|
+
}
|
|
445
|
+
currentDir = parentDir;
|
|
446
|
+
searchDepth++;
|
|
447
|
+
}
|
|
464
448
|
|
|
465
|
-
|
|
466
|
-
|
|
449
|
+
// 如果都找不到,使用当前工作目录作为最后尝试
|
|
450
|
+
const cwdWebPath = path.join(process.cwd(), 'packages', 'web');
|
|
451
|
+
console.log('🔍 Checking CWD path:', cwdWebPath);
|
|
452
|
+
if (this._pathExistsSync(cwdWebPath)) {
|
|
453
|
+
console.log('✅ Found web UI in CWD:', cwdWebPath);
|
|
454
|
+
return cwdWebPath;
|
|
455
|
+
}
|
|
467
456
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
457
|
+
// 最后的fallback
|
|
458
|
+
console.error('❌ Web UI not found in any location. This will cause blank pages.');
|
|
459
|
+
console.error('Current directory:', __dirname);
|
|
460
|
+
console.error('Working directory:', process.cwd());
|
|
461
|
+
console.error('Checked paths:');
|
|
462
|
+
console.error(' - Dev path:', devWebPath);
|
|
463
|
+
console.error(' - CWD path:', cwdWebPath);
|
|
464
|
+
|
|
465
|
+
return devWebPath; // 返回开发路径作为fallback,虽然它不存在
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* 获取内置配置文件目录
|
|
470
|
+
* 兼容开发环境和打包后的环境
|
|
471
|
+
* @returns {string} 配置目录路径
|
|
472
|
+
*/
|
|
473
|
+
getBuiltInConfigsDir() {
|
|
474
|
+
// 检查是否是打包应用
|
|
475
|
+
// 在 macOS 打包应用中,process.resourcesPath 存在
|
|
476
|
+
if (process.resourcesPath) {
|
|
477
|
+
// 在打包应用中,内置配置位于 Resources/runtime/configs/
|
|
478
|
+
const packagedConfigPath = path.join(process.resourcesPath, 'runtime', 'configs');
|
|
479
|
+
if (this._pathExistsSync(packagedConfigPath)) {
|
|
480
|
+
return packagedConfigPath;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
488
483
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
484
|
+
// 在 npm 包环境中,配置位于 node_modules 中的包目录
|
|
485
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
486
|
+
const __dirname = path.dirname(__filename);
|
|
487
|
+
const npmConfigPath = path.resolve(__dirname, '../configs');
|
|
488
|
+
if (this._pathExistsSync(npmConfigPath)) {
|
|
489
|
+
return npmConfigPath;
|
|
490
|
+
}
|
|
496
491
|
|
|
497
|
-
|
|
498
|
-
|
|
492
|
+
// 在开发环境中,配置位于 packages/server/configs/
|
|
493
|
+
return path.resolve(__dirname, '../configs');
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* 获取默认用户配置文件路径
|
|
498
|
+
* @returns {string} 用户配置文件路径
|
|
499
|
+
*/
|
|
500
|
+
getDefaultUserConfigPath() {
|
|
501
|
+
return path.join(this.getBuiltInConfigsDir(), 'authors.json');
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
_pathExistsSync(filePath) {
|
|
505
|
+
try {
|
|
506
|
+
fs.accessSync(filePath, fs.constants.F_OK);
|
|
507
|
+
return true;
|
|
508
|
+
} catch (error) {
|
|
509
|
+
return false;
|
|
499
510
|
}
|
|
500
|
-
|
|
501
|
-
_pathExistsSync(filePath) {
|
|
502
|
-
try {
|
|
503
|
-
fs.accessSync(filePath, fs.constants.F_OK);
|
|
504
|
-
return true;
|
|
505
|
-
} catch (error) {
|
|
506
|
-
return false;
|
|
507
|
-
}
|
|
508
|
-
};
|
|
511
|
+
}
|
|
509
512
|
|
|
510
|
-
|
|
513
|
+
async getPromptManager() {
|
|
511
514
|
if (!_promptManager) {
|
|
515
|
+
try {
|
|
516
|
+
// 首先尝试相对路径导入
|
|
517
|
+
const serviceModule = await import('../services/manager.js');
|
|
518
|
+
_promptManager = serviceModule.promptManager;
|
|
519
|
+
} catch (error) {
|
|
520
|
+
// 如果相对路径导入失败,尝试使用绝对路径
|
|
512
521
|
try {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
const serviceModule = await import(managerPath);
|
|
525
|
-
_promptManager = serviceModule.promptManager;
|
|
526
|
-
} catch (absolutePathError) {
|
|
527
|
-
// 如果绝对路径也失败,记录错误并重新抛出
|
|
528
|
-
console.error('Failed to import promptManager with both relative and absolute paths:', absolutePathError);
|
|
529
|
-
throw absolutePathError;
|
|
530
|
-
}
|
|
522
|
+
const path = await import('path');
|
|
523
|
+
const { fileURLToPath } = await import('url');
|
|
524
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
525
|
+
const __dirname = path.dirname(__filename);
|
|
526
|
+
const managerPath = path.join(__dirname, '..', 'services', 'manager.js');
|
|
527
|
+
const serviceModule = await import(managerPath);
|
|
528
|
+
_promptManager = serviceModule.promptManager;
|
|
529
|
+
} catch (absolutePathError) {
|
|
530
|
+
// 如果绝对路径也失败,记录错误并重新抛出
|
|
531
|
+
console.error('Failed to import promptManager with both relative and absolute paths:', absolutePathError);
|
|
532
|
+
throw absolutePathError;
|
|
531
533
|
}
|
|
534
|
+
}
|
|
532
535
|
}
|
|
533
536
|
return _promptManager;
|
|
534
|
-
|
|
537
|
+
}
|
|
535
538
|
}
|
|
536
539
|
|
|
537
|
-
export const util = new Util()
|
|
540
|
+
export const util = new Util();
|