sloth-d2c-mcp 1.0.4-beta92 → 1.0.4-beta94
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/cli/run.js +3 -1
- package/dist/build/core/prompt-builder.js +50 -1
- package/dist/build/core/sampling.js +13 -8
- package/dist/build/index.js +54 -14
- package/dist/build/plugin/loader.js +25 -11
- package/dist/build/plugin/manager.js +2 -0
- package/dist/build/server.js +260 -83
- package/dist/build/socket-client.js +1 -1
- package/dist/build/utils/file-manager.js +62 -11
- package/dist/build/utils/prompt-parser.js +46 -0
- package/dist/interceptor-web/dist/build-report.json +5 -5
- package/dist/interceptor-web/dist/detail.html +1 -1
- package/dist/interceptor-web/dist/index.html +1 -1
- package/package.json +5 -4
package/dist/build/server.js
CHANGED
|
@@ -18,8 +18,11 @@ import multer from 'multer';
|
|
|
18
18
|
import { ImageMatcher } from './utils/image-matcher.js';
|
|
19
19
|
import { initOpenCV } from './utils/opencv-loader.js';
|
|
20
20
|
import { extractJson } from './utils/extract.js';
|
|
21
|
-
import { componentAnalysisPrompt, componentAnalysisPromptVue } from 'sloth-d2c-node/convert';
|
|
21
|
+
import { componentAnalysisPrompt, componentAnalysisPromptVue, chunkOptimizeCodePromptKuikly, aggregationOptimizeCodePromptKuikly, finalOptimizeCodePromptKuikly, chunkOptimizeCodePrompt, aggregationOptimizeCodePrompt, finalOptimizeCodePrompt, chunkOptimizeCodePromptVue, aggregationOptimizeCodePromptVue, finalOptimizeCodePromptVue, frameworkPromptKuikly, noSamplingAggregationPrompt, noSamplingAggregationPromptVue, noSamplingAggregationPromptKuikly, chunkOptimizeCodePromptIosOc, aggregationOptimizeCodePromptIosOc, finalOptimizeCodePromptIosOc, noSamplingAggregationPromptIosOc, chunkOptimizeCodePromptIosSwift, aggregationOptimizeCodePromptIosSwift, finalOptimizeCodePromptIosSwift, noSamplingAggregationPromptIosSwift, } from 'sloth-d2c-node/convert';
|
|
22
22
|
import { SocketServer } from './socket-server.js';
|
|
23
|
+
import { getParam } from './utils/utils.js';
|
|
24
|
+
import { loadPluginFromGlobalDirAsync } from './plugin/loader.js';
|
|
25
|
+
import { pluginManager } from './plugin/manager.js';
|
|
23
26
|
/**
|
|
24
27
|
* 生成组件 ID(4位随机字符串)
|
|
25
28
|
*/
|
|
@@ -30,10 +33,6 @@ const upload = multer({
|
|
|
30
33
|
storage,
|
|
31
34
|
limits: { fileSize: 10 * 1024 * 1024 }, // 10MB
|
|
32
35
|
});
|
|
33
|
-
// 导入默认提示词
|
|
34
|
-
import { chunkOptimizeCodePrompt, aggregationOptimizeCodePrompt, finalOptimizeCodePrompt, chunkOptimizeCodePromptVue, aggregationOptimizeCodePromptVue, finalOptimizeCodePromptVue, noSamplingAggregationPrompt, noSamplingAggregationPromptVue, } from 'sloth-d2c-node/convert';
|
|
35
|
-
import { getParam } from './utils/utils.js';
|
|
36
|
-
import { listWorkspacePlugins } from './plugin/loader.js';
|
|
37
36
|
// 保存 HTTP 服务器实例
|
|
38
37
|
export let httpServer = null;
|
|
39
38
|
// 保存 Socket 服务器实例
|
|
@@ -50,7 +49,7 @@ let configManager = null; // 配置管理器实例
|
|
|
50
49
|
const __filename = fileURLToPath(import.meta.url);
|
|
51
50
|
const __dirname = path.dirname(__filename);
|
|
52
51
|
// 获取端口号
|
|
53
|
-
let PORT =
|
|
52
|
+
let PORT = 3100;
|
|
54
53
|
// 导出获取端口号的函数
|
|
55
54
|
export function getPort() {
|
|
56
55
|
return PORT;
|
|
@@ -77,24 +76,26 @@ export async function loadConfig(mcpServer, configManagerInstance) {
|
|
|
77
76
|
Logger.warn(`读取配置文件失败: ${error}`);
|
|
78
77
|
}
|
|
79
78
|
}
|
|
79
|
+
// 默认框架列表
|
|
80
|
+
const defaultFrameworks = [
|
|
81
|
+
{ value: 'react', label: 'React' },
|
|
82
|
+
{ value: 'vue', label: 'Vue' },
|
|
83
|
+
{ value: 'ios-oc', label: 'iOS OC' },
|
|
84
|
+
{ value: 'ios-swift', label: 'iOS Swift' },
|
|
85
|
+
{ value: 'kuikly', label: 'Kuikly' },
|
|
86
|
+
];
|
|
80
87
|
// 初始化默认框架配置
|
|
81
88
|
if (!config.frameworks || config.frameworks.length === 0) {
|
|
82
89
|
Logger.log('初始化默认框架配置...');
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
};
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
if (!config.frameworks.find((fw) => fw.value === 'react') || !config.frameworks.find((fw) => fw.value === 'vue')) {
|
|
96
|
-
const newFrameworks = config.frameworks.filter((fw) => fw.value !== 'react' || fw.value !== 'vue');
|
|
97
|
-
config.frameworks = [{ value: 'react', label: 'React' }, { value: 'vue', label: 'Vue' }, ...newFrameworks];
|
|
90
|
+
config.frameworks = [...defaultFrameworks];
|
|
91
|
+
await configManager.save(config);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
// 检查是否缺少默认框架,补充缺失的
|
|
95
|
+
const existingValues = config.frameworks.map((fw) => fw.value);
|
|
96
|
+
const missingFrameworks = defaultFrameworks.filter((fw) => !existingValues.includes(fw.value));
|
|
97
|
+
if (missingFrameworks.length > 0) {
|
|
98
|
+
config.frameworks = [...config.frameworks, ...missingFrameworks];
|
|
98
99
|
await configManager.save(config);
|
|
99
100
|
}
|
|
100
101
|
}
|
|
@@ -135,6 +136,82 @@ export async function loadConfig(mcpServer, configManagerInstance) {
|
|
|
135
136
|
...(vueConfig || {}),
|
|
136
137
|
});
|
|
137
138
|
}
|
|
139
|
+
// 检查 ios-oc.json 是否存在,如果不存在则创建
|
|
140
|
+
const iosOcConfigExists = await configManager.frameworkConfigExists('ios-oc');
|
|
141
|
+
if (!iosOcConfigExists) {
|
|
142
|
+
await configManager.saveFrameworkConfig('ios-oc', {
|
|
143
|
+
chunkOptimizePrompt: chunkOptimizeCodePromptIosOc,
|
|
144
|
+
aggregationOptimizePrompt: aggregationOptimizeCodePromptIosOc,
|
|
145
|
+
finalOptimizePrompt: finalOptimizeCodePromptIosOc,
|
|
146
|
+
componentAnalysisPrompt: '',
|
|
147
|
+
noSamplingAggregationPrompt: noSamplingAggregationPromptIosOc,
|
|
148
|
+
});
|
|
149
|
+
const iosOcConfigPath = configManager.getFrameworkConfigPath('ios-oc');
|
|
150
|
+
Logger.log(`已创建默认 ios-oc 配置文件: ${iosOcConfigPath}`);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
const iosOcConfig = await configManager.loadFrameworkConfig('ios-oc');
|
|
154
|
+
await configManager.saveFrameworkConfig('ios-oc', {
|
|
155
|
+
chunkOptimizePrompt: chunkOptimizeCodePromptIosOc,
|
|
156
|
+
aggregationOptimizePrompt: aggregationOptimizeCodePromptIosOc,
|
|
157
|
+
finalOptimizePrompt: finalOptimizeCodePromptIosOc,
|
|
158
|
+
componentAnalysisPrompt: '',
|
|
159
|
+
noSamplingAggregationPrompt: noSamplingAggregationPromptIosOc,
|
|
160
|
+
...(iosOcConfig || {}),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
// 检查 ios-swift.json 是否存在,如果不存在则创建
|
|
164
|
+
const iosswiftConfigExists = await configManager.frameworkConfigExists('ios-swift');
|
|
165
|
+
if (!iosswiftConfigExists) {
|
|
166
|
+
await configManager.saveFrameworkConfig('ios-swift', {
|
|
167
|
+
chunkOptimizePrompt: chunkOptimizeCodePromptIosSwift,
|
|
168
|
+
aggregationOptimizePrompt: aggregationOptimizeCodePromptIosSwift,
|
|
169
|
+
finalOptimizePrompt: finalOptimizeCodePromptIosSwift,
|
|
170
|
+
componentAnalysisPrompt: '',
|
|
171
|
+
noSamplingAggregationPrompt: noSamplingAggregationPromptIosSwift,
|
|
172
|
+
});
|
|
173
|
+
const iosswiftConfigPath = configManager.getFrameworkConfigPath('ios-swift');
|
|
174
|
+
Logger.log(`已创建默认 ios-swift 配置文件: ${iosswiftConfigPath}`);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
const iosSwiftConfig = await configManager.loadFrameworkConfig('ios-swift');
|
|
178
|
+
await configManager.saveFrameworkConfig('ios-swift', {
|
|
179
|
+
chunkOptimizePrompt: chunkOptimizeCodePromptIosSwift,
|
|
180
|
+
aggregationOptimizePrompt: aggregationOptimizeCodePromptIosSwift,
|
|
181
|
+
finalOptimizePrompt: finalOptimizeCodePromptIosSwift,
|
|
182
|
+
componentAnalysisPrompt: '',
|
|
183
|
+
noSamplingAggregationPrompt: noSamplingAggregationPromptIosSwift,
|
|
184
|
+
...(iosSwiftConfig || {}),
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
// 检查 kuikly.json 是否存在,如果不存在则创建
|
|
188
|
+
const kuiklyConfigExists = await configManager.frameworkConfigExists('kuikly');
|
|
189
|
+
if (!kuiklyConfigExists) {
|
|
190
|
+
await configManager.saveFrameworkConfig('kuikly', {
|
|
191
|
+
enableFrameworkGuide: true,
|
|
192
|
+
frameworkGuidePrompt: frameworkPromptKuikly,
|
|
193
|
+
chunkOptimizePrompt: chunkOptimizeCodePromptKuikly,
|
|
194
|
+
aggregationOptimizePrompt: aggregationOptimizeCodePromptKuikly,
|
|
195
|
+
finalOptimizePrompt: finalOptimizeCodePromptKuikly,
|
|
196
|
+
componentAnalysisPrompt: '',
|
|
197
|
+
noSamplingAggregationPrompt: noSamplingAggregationPromptKuikly,
|
|
198
|
+
});
|
|
199
|
+
const kuiklyConfigPath = configManager.getFrameworkConfigPath('kuikly');
|
|
200
|
+
Logger.log(`已创建默认 kuikly 配置文件: ${kuiklyConfigPath}`);
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
const kuiklyConfig = await configManager.loadFrameworkConfig('kuikly');
|
|
204
|
+
await configManager.saveFrameworkConfig('kuikly', {
|
|
205
|
+
enableFrameworkGuide: true,
|
|
206
|
+
frameworkGuidePrompt: frameworkPromptKuikly,
|
|
207
|
+
chunkOptimizePrompt: chunkOptimizeCodePromptKuikly,
|
|
208
|
+
aggregationOptimizePrompt: aggregationOptimizeCodePromptKuikly,
|
|
209
|
+
finalOptimizePrompt: finalOptimizeCodePromptKuikly,
|
|
210
|
+
componentAnalysisPrompt: '',
|
|
211
|
+
noSamplingAggregationPrompt: noSamplingAggregationPromptKuikly,
|
|
212
|
+
...(kuiklyConfig || {}),
|
|
213
|
+
});
|
|
214
|
+
}
|
|
138
215
|
}
|
|
139
216
|
catch (error) {
|
|
140
217
|
Logger.error(`获取配置信息时出错: ${error}`);
|
|
@@ -339,7 +416,8 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
339
416
|
const fileKey = req.query.fileKey;
|
|
340
417
|
const nodeId = req.query.nodeId;
|
|
341
418
|
const framework = req.query.framework;
|
|
342
|
-
const plugins = await listWorkspacePlugins(req.workspaceRoot)
|
|
419
|
+
// const plugins = await listWorkspacePlugins(req.workspaceRoot)
|
|
420
|
+
const plugins = await socketServer?.getTokenExtraField(req.uuid, 'plugins');
|
|
343
421
|
if (fileKey) {
|
|
344
422
|
// 如果提供了 fileKey,返回该 fileKey 的特定配置
|
|
345
423
|
const globalConfig = await configManager.load();
|
|
@@ -352,47 +430,16 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
352
430
|
let curFramework = fileConfig?.convertSetting?.framework;
|
|
353
431
|
// 获取框架列表
|
|
354
432
|
const frameworks = await configManager.getFrameworks();
|
|
355
|
-
if (!curFramework || !frameworks.find((fw) => fw.value === curFramework)) {
|
|
356
|
-
curFramework = globalConfig.defaultFramework || 'react';
|
|
357
|
-
}
|
|
358
|
-
const curFrameworkDefaultConfig = (await configManager.loadFrameworkConfig(curFramework)) ||
|
|
359
|
-
(curFramework !== 'vue'
|
|
360
|
-
? {
|
|
361
|
-
chunkOptimizePrompt: chunkOptimizeCodePrompt,
|
|
362
|
-
aggregationOptimizePrompt: aggregationOptimizeCodePrompt,
|
|
363
|
-
finalOptimizePrompt: finalOptimizeCodePrompt,
|
|
364
|
-
componentAnalysisPrompt: componentAnalysisPrompt,
|
|
365
|
-
noSamplingAggregationPrompt: noSamplingAggregationPrompt,
|
|
366
|
-
}
|
|
367
|
-
: {
|
|
368
|
-
chunkOptimizePrompt: chunkOptimizeCodePromptVue,
|
|
369
|
-
aggregationOptimizePrompt: aggregationOptimizeCodePromptVue,
|
|
370
|
-
finalOptimizePrompt: finalOptimizeCodePromptVue,
|
|
371
|
-
componentAnalysisPrompt: componentAnalysisPromptVue,
|
|
372
|
-
noSamplingAggregationPrompt: noSamplingAggregationPromptVue,
|
|
373
|
-
});
|
|
374
433
|
// 如果指定了框架,加载框架配置的提示词
|
|
375
434
|
let promptSetting = {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
435
|
+
enableFrameworkGuide: savedPromptSetting?.frameworkGuidePrompt,
|
|
436
|
+
frameworkGuidePrompt: savedPromptSetting?.frameworkGuidePrompt,
|
|
437
|
+
chunkOptimizePrompt: savedPromptSetting?.chunkOptimizePrompt,
|
|
438
|
+
aggregationOptimizePrompt: savedPromptSetting?.aggregationOptimizePrompt,
|
|
439
|
+
finalOptimizePrompt: savedPromptSetting?.finalOptimizePrompt,
|
|
440
|
+
componentAnalysisPrompt: savedPromptSetting?.componentAnalysisPrompt,
|
|
441
|
+
noSamplingAggregationPrompt: savedPromptSetting?.noSamplingAggregationPrompt,
|
|
381
442
|
};
|
|
382
|
-
if (framework) {
|
|
383
|
-
// 加载框架配置
|
|
384
|
-
const frameworkConfig = await configManager.loadFrameworkConfig(framework);
|
|
385
|
-
if (frameworkConfig && Object.keys(frameworkConfig).length > 0) {
|
|
386
|
-
// 框架配置优先级更高,但如果框架配置为空,则使用已保存的或默认的
|
|
387
|
-
promptSetting = {
|
|
388
|
-
chunkOptimizePrompt: frameworkConfig.chunkOptimizePrompt || promptSetting.chunkOptimizePrompt,
|
|
389
|
-
aggregationOptimizePrompt: frameworkConfig.aggregationOptimizePrompt || promptSetting.aggregationOptimizePrompt,
|
|
390
|
-
finalOptimizePrompt: frameworkConfig.finalOptimizePrompt || promptSetting.finalOptimizePrompt,
|
|
391
|
-
componentAnalysisPrompt: frameworkConfig.componentAnalysisPrompt || promptSetting.componentAnalysisPrompt,
|
|
392
|
-
noSamplingAggregationPrompt: frameworkConfig.noSamplingAggregationPrompt || promptSetting.noSamplingAggregationPrompt,
|
|
393
|
-
};
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
443
|
res.json({
|
|
397
444
|
success: true,
|
|
398
445
|
data: {
|
|
@@ -404,7 +451,7 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
404
451
|
defaultFramework: globalConfig.defaultFramework || 'react',
|
|
405
452
|
fileKey: fileKey,
|
|
406
453
|
groupsData: groupsData,
|
|
407
|
-
plugins,
|
|
454
|
+
pluginSetting: plugins,
|
|
408
455
|
},
|
|
409
456
|
});
|
|
410
457
|
}
|
|
@@ -415,6 +462,8 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
415
462
|
}
|
|
416
463
|
// 如果指定了框架,加载框架配置的提示词
|
|
417
464
|
let promptSetting = {
|
|
465
|
+
enableFrameworkGuide: false,
|
|
466
|
+
frameworkGuidePrompt: '',
|
|
418
467
|
chunkOptimizePrompt: chunkOptimizeCodePrompt,
|
|
419
468
|
aggregationOptimizePrompt: aggregationOptimizeCodePrompt,
|
|
420
469
|
finalOptimizePrompt: finalOptimizeCodePrompt,
|
|
@@ -427,6 +476,8 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
427
476
|
if (frameworkConfig && Object.keys(frameworkConfig).length > 0) {
|
|
428
477
|
// 框架配置优先级更高
|
|
429
478
|
promptSetting = {
|
|
479
|
+
enableFrameworkGuide: frameworkConfig.frameworkGuidePrompt || promptSetting.enableFrameworkGuide ? true : false,
|
|
480
|
+
frameworkGuidePrompt: frameworkConfig.frameworkGuidePrompt || promptSetting.frameworkGuidePrompt,
|
|
430
481
|
chunkOptimizePrompt: frameworkConfig.chunkOptimizePrompt || promptSetting.chunkOptimizePrompt,
|
|
431
482
|
aggregationOptimizePrompt: frameworkConfig.aggregationOptimizePrompt || promptSetting.aggregationOptimizePrompt,
|
|
432
483
|
finalOptimizePrompt: frameworkConfig.finalOptimizePrompt || promptSetting.finalOptimizePrompt,
|
|
@@ -445,7 +496,7 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
445
496
|
imageSetting: configStorage.imageSetting || {},
|
|
446
497
|
promptSetting: promptSetting,
|
|
447
498
|
frameworks: frameworks,
|
|
448
|
-
plugins,
|
|
499
|
+
pluginSetting: plugins,
|
|
449
500
|
},
|
|
450
501
|
});
|
|
451
502
|
}
|
|
@@ -476,6 +527,7 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
476
527
|
let frameworks = (await configManager.getFrameworks()) || [
|
|
477
528
|
{ value: 'react', label: 'React' },
|
|
478
529
|
{ value: 'vue', label: 'Vue' },
|
|
530
|
+
{ value: 'kuikly', label: 'Kuikly' },
|
|
479
531
|
];
|
|
480
532
|
const defaultFramework = globalConfig?.defaultFramework || 'react';
|
|
481
533
|
let promptSetting = {};
|
|
@@ -484,12 +536,12 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
484
536
|
promptSetting[fw] = {
|
|
485
537
|
...frameworkConfig,
|
|
486
538
|
enableFrameworkGuide: frameworkConfig.enableFrameworkGuide || false,
|
|
487
|
-
|
|
488
|
-
chunkOptimizePrompt: frameworkConfig.chunkOptimizePrompt ||
|
|
489
|
-
aggregationOptimizePrompt: frameworkConfig.aggregationOptimizePrompt ||
|
|
490
|
-
finalOptimizePrompt: frameworkConfig.finalOptimizePrompt ||
|
|
491
|
-
componentAnalysisPrompt: frameworkConfig.componentAnalysisPrompt ||
|
|
492
|
-
noSamplingAggregationPrompt: frameworkConfig.noSamplingAggregationPrompt ||
|
|
539
|
+
frameworkGuidePrompt: frameworkConfig.frameworkGuidePrompt || '',
|
|
540
|
+
chunkOptimizePrompt: frameworkConfig.chunkOptimizePrompt || '',
|
|
541
|
+
aggregationOptimizePrompt: frameworkConfig.aggregationOptimizePrompt || '',
|
|
542
|
+
finalOptimizePrompt: frameworkConfig.finalOptimizePrompt || '',
|
|
543
|
+
componentAnalysisPrompt: frameworkConfig.componentAnalysisPrompt || '',
|
|
544
|
+
noSamplingAggregationPrompt: frameworkConfig.noSamplingAggregationPrompt || '',
|
|
493
545
|
};
|
|
494
546
|
res.json({
|
|
495
547
|
success: true,
|
|
@@ -553,6 +605,8 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
553
605
|
return;
|
|
554
606
|
}
|
|
555
607
|
let promptSetting = {
|
|
608
|
+
enableFrameworkGuide: false,
|
|
609
|
+
frameworkGuidePrompt: '',
|
|
556
610
|
chunkOptimizePrompt: chunkOptimizeCodePrompt,
|
|
557
611
|
aggregationOptimizePrompt: aggregationOptimizeCodePrompt,
|
|
558
612
|
finalOptimizePrompt: finalOptimizeCodePrompt,
|
|
@@ -563,6 +617,8 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
563
617
|
if (frameworkConfig && Object.keys(frameworkConfig).length > 0) {
|
|
564
618
|
// 框架配置优先级更高
|
|
565
619
|
promptSetting = {
|
|
620
|
+
enableFrameworkGuide: frameworkConfig.enableFrameworkGuide || promptSetting.enableFrameworkGuide,
|
|
621
|
+
frameworkGuidePrompt: frameworkConfig.frameworkGuidePrompt || promptSetting.frameworkGuidePrompt,
|
|
566
622
|
chunkOptimizePrompt: frameworkConfig.chunkOptimizePrompt || promptSetting.chunkOptimizePrompt,
|
|
567
623
|
aggregationOptimizePrompt: frameworkConfig.aggregationOptimizePrompt || promptSetting.aggregationOptimizePrompt,
|
|
568
624
|
finalOptimizePrompt: frameworkConfig.finalOptimizePrompt || promptSetting.finalOptimizePrompt,
|
|
@@ -598,17 +654,54 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
598
654
|
}
|
|
599
655
|
// 根据框架返回对应的原始默认提示词
|
|
600
656
|
const isVue = framework.toLowerCase() === 'vue';
|
|
657
|
+
const isIosOc = framework.toLowerCase() === 'ios-oc';
|
|
658
|
+
const isIosSwift = framework.toLowerCase() === 'ios-swift';
|
|
659
|
+
const isKuikly = framework.toLowerCase() === 'kuikly';
|
|
601
660
|
const promptSetting = {
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
661
|
+
enableFrameworkGuide: isKuikly ? true : false,
|
|
662
|
+
frameworkGuidePrompt: isKuikly ? frameworkPromptKuikly : '',
|
|
663
|
+
chunkOptimizePrompt: isKuikly
|
|
664
|
+
? chunkOptimizeCodePromptKuikly
|
|
665
|
+
: isIosOc
|
|
666
|
+
? chunkOptimizeCodePromptIosOc
|
|
667
|
+
: isIosSwift
|
|
668
|
+
? chunkOptimizeCodePromptIosSwift
|
|
669
|
+
: isVue
|
|
670
|
+
? chunkOptimizeCodePromptVue
|
|
671
|
+
: chunkOptimizeCodePrompt,
|
|
672
|
+
aggregationOptimizePrompt: isKuikly
|
|
673
|
+
? aggregationOptimizeCodePromptKuikly
|
|
674
|
+
: isIosOc
|
|
675
|
+
? aggregationOptimizeCodePromptIosOc
|
|
676
|
+
: isIosSwift
|
|
677
|
+
? aggregationOptimizeCodePromptIosSwift
|
|
678
|
+
: isVue
|
|
679
|
+
? aggregationOptimizeCodePromptVue
|
|
680
|
+
: aggregationOptimizeCodePrompt,
|
|
681
|
+
finalOptimizePrompt: isKuikly
|
|
682
|
+
? finalOptimizeCodePromptKuikly
|
|
683
|
+
: isIosOc
|
|
684
|
+
? finalOptimizeCodePromptIosOc
|
|
685
|
+
: isIosSwift
|
|
686
|
+
? finalOptimizeCodePromptIosSwift
|
|
687
|
+
: isVue
|
|
688
|
+
? finalOptimizeCodePromptVue
|
|
689
|
+
: finalOptimizeCodePrompt,
|
|
690
|
+
componentAnalysisPrompt: isKuikly ? '' : isIosOc ? '' : isIosSwift ? '' : isVue ? componentAnalysisPromptVue : componentAnalysisPrompt,
|
|
691
|
+
noSamplingAggregationPrompt: isKuikly
|
|
692
|
+
? noSamplingAggregationPromptKuikly
|
|
693
|
+
: isIosOc
|
|
694
|
+
? noSamplingAggregationPromptIosOc
|
|
695
|
+
: isIosSwift
|
|
696
|
+
? noSamplingAggregationPromptIosSwift
|
|
697
|
+
: isVue
|
|
698
|
+
? noSamplingAggregationPromptVue
|
|
699
|
+
: noSamplingAggregationPrompt,
|
|
607
700
|
};
|
|
608
701
|
res.json({
|
|
609
702
|
success: true,
|
|
610
703
|
data: promptSetting,
|
|
611
|
-
message: '获取默认框架配置成功',
|
|
704
|
+
message: '获取默认框架配置成功1',
|
|
612
705
|
});
|
|
613
706
|
}
|
|
614
707
|
catch (error) {
|
|
@@ -620,6 +713,67 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
620
713
|
});
|
|
621
714
|
}
|
|
622
715
|
});
|
|
716
|
+
// 获取项目中的 Markdown 文件列表(扫描 .sloth/doc 目录)
|
|
717
|
+
app.get('/getMarkdownFiles', async (req, res) => {
|
|
718
|
+
try {
|
|
719
|
+
const projectRoot = getProjectRoot(req.fileManager);
|
|
720
|
+
if (!projectRoot) {
|
|
721
|
+
res.json({
|
|
722
|
+
success: true,
|
|
723
|
+
data: [],
|
|
724
|
+
message: '未找到项目根目录',
|
|
725
|
+
});
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
const markdownFiles = [];
|
|
729
|
+
const promptDir = path.join(projectRoot, '.sloth', 'prompt');
|
|
730
|
+
// 检查 .sloth/prompt 目录是否存在
|
|
731
|
+
if (!fs.existsSync(promptDir)) {
|
|
732
|
+
res.json({
|
|
733
|
+
success: true,
|
|
734
|
+
data: [],
|
|
735
|
+
message: '.sloth/prompt 目录不存在',
|
|
736
|
+
});
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
// 递归查找 prompt 目录下的 .md 文件
|
|
740
|
+
const findMarkdownFiles = (dir) => {
|
|
741
|
+
try {
|
|
742
|
+
const items = fs.readdirSync(dir, { withFileTypes: true });
|
|
743
|
+
for (const item of items) {
|
|
744
|
+
const fullPath = path.join(dir, item.name);
|
|
745
|
+
const relativePath = path.relative(promptDir, fullPath);
|
|
746
|
+
if (item.isDirectory()) {
|
|
747
|
+
findMarkdownFiles(fullPath);
|
|
748
|
+
}
|
|
749
|
+
else if (item.isFile() && item.name.endsWith('.md')) {
|
|
750
|
+
markdownFiles.push({
|
|
751
|
+
path: path.join('.sloth', 'prompt', relativePath),
|
|
752
|
+
name: item.name,
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
catch (err) {
|
|
758
|
+
Logger.warn(`无法访问目录: ${dir}`, err);
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
findMarkdownFiles(promptDir);
|
|
762
|
+
res.json({
|
|
763
|
+
success: true,
|
|
764
|
+
data: markdownFiles,
|
|
765
|
+
message: `找到 ${markdownFiles.length} 个文档`,
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
catch (error) {
|
|
769
|
+
Logger.error('获取文档列表失败:', error);
|
|
770
|
+
res.status(500).json({
|
|
771
|
+
success: false,
|
|
772
|
+
message: '获取文档列表失败',
|
|
773
|
+
error: error instanceof Error ? error.message : String(error),
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
});
|
|
623
777
|
// 认证页面
|
|
624
778
|
app.get('/auth-page', (req, res) => {
|
|
625
779
|
try {
|
|
@@ -668,6 +822,7 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
668
822
|
try {
|
|
669
823
|
// 安全地解构请求体,处理可能为空的情况
|
|
670
824
|
const { token, value, fileKey, nodeId } = req.body || {};
|
|
825
|
+
Logger.log('submit req.body', token, value, fileKey, nodeId);
|
|
671
826
|
if (!token || !value) {
|
|
672
827
|
res.status(400).send('请求体中缺少 token 或 value');
|
|
673
828
|
return;
|
|
@@ -698,6 +853,9 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
698
853
|
Logger.log(`已保存 groupsData 到 fileKey "${fileKey}", nodeId "${nodeId}":`, value.groupsData.length, '个分组');
|
|
699
854
|
}
|
|
700
855
|
if (fileKey && value.promptSetting) {
|
|
856
|
+
if (!value.promptSetting.enableFrameworkGuide) {
|
|
857
|
+
value.promptSetting.frameworkGuidePrompt = '';
|
|
858
|
+
}
|
|
701
859
|
await req.fileManager.savePromptSetting(fileKey, nodeId, value.promptSetting);
|
|
702
860
|
Logger.log(`已保存 promptSetting 到 fileKey "${fileKey}", nodeId "${nodeId}"`);
|
|
703
861
|
}
|
|
@@ -775,6 +933,25 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
775
933
|
message: '日志重连已启动',
|
|
776
934
|
});
|
|
777
935
|
});
|
|
936
|
+
// 插件渲染器端点 - 返回JS代码字符串
|
|
937
|
+
app.get('/pluginRenderer', async (req, res) => {
|
|
938
|
+
console.log('pluginRenderer');
|
|
939
|
+
const pluginName = req.query.pluginName;
|
|
940
|
+
let pluginRenderer = null;
|
|
941
|
+
try {
|
|
942
|
+
// @ts-ignore
|
|
943
|
+
pluginRenderer = await loadPluginFromGlobalDirAsync(pluginName);
|
|
944
|
+
}
|
|
945
|
+
catch (error) {
|
|
946
|
+
console.error('加载插件渲染器失败:', error);
|
|
947
|
+
res.type('application/javascript; charset=utf-8').send(`alert(${pluginName}加载失败)`);
|
|
948
|
+
return;
|
|
949
|
+
}
|
|
950
|
+
const renderer = pluginRenderer.default.renderConfigForm;
|
|
951
|
+
console.log('pluginRenderer.default', pluginRenderer.default);
|
|
952
|
+
console.log('renderer', renderer);
|
|
953
|
+
res.type('application/javascript; charset=utf-8').send(renderer);
|
|
954
|
+
});
|
|
778
955
|
// ==================== 组件映射相关接口 ====================
|
|
779
956
|
/**
|
|
780
957
|
* 获取项目根目录
|
|
@@ -1470,8 +1647,8 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
1470
1647
|
}
|
|
1471
1648
|
Logger.log(`分析设计稿变更: old=${oldFileKey}/${oldNodeId}, new=${newFileKey}/${newNodeId}`);
|
|
1472
1649
|
// 1. 加载新旧 HTML 和 imageMap
|
|
1473
|
-
let oldHtml = await fileManager.loadAbsoluteHtml(oldFileKey, oldNodeId);
|
|
1474
|
-
let newHtml = await fileManager.loadAbsoluteHtml(newFileKey, newNodeId);
|
|
1650
|
+
let oldHtml = await fileManager.loadAbsoluteHtml(oldFileKey, oldNodeId, true);
|
|
1651
|
+
let newHtml = await fileManager.loadAbsoluteHtml(newFileKey, newNodeId, true);
|
|
1475
1652
|
Logger.log(`[analyzeChange] 加载 HTML 完成: oldHtml=${oldHtml?.length || 0}字符, newHtml=${newHtml?.length || 0}字符`);
|
|
1476
1653
|
// 加载 imageMap 用于替换图片路径(flatted 格式)
|
|
1477
1654
|
let oldImageMap = {};
|
|
@@ -1697,9 +1874,9 @@ ${truncatedDiff}
|
|
|
1697
1874
|
// 启动 HTTP 服务器,监听端口
|
|
1698
1875
|
httpServer = app.listen(port, async (err) => {
|
|
1699
1876
|
if (err) {
|
|
1700
|
-
Logger.error('HTTP 服务器启动失败:', err);
|
|
1701
1877
|
httpServer = null;
|
|
1702
|
-
|
|
1878
|
+
Logger.error('HTTP 服务器启动失败:', err, '退出进程');
|
|
1879
|
+
process.exit(0);
|
|
1703
1880
|
}
|
|
1704
1881
|
Logger.log(`HTTP server listening on port ${port}`);
|
|
1705
1882
|
Logger.log(`SSE endpoint available at http://localhost:${port}/sse`);
|
|
@@ -1719,7 +1896,7 @@ ${truncatedDiff}
|
|
|
1719
1896
|
}
|
|
1720
1897
|
catch (error) {
|
|
1721
1898
|
Logger.error('Socket 服务器启动失败:', error);
|
|
1722
|
-
|
|
1899
|
+
process.exit(0);
|
|
1723
1900
|
}
|
|
1724
1901
|
});
|
|
1725
1902
|
// 监听 SIGINT 信号,优雅关闭服务器和所有会话
|
|
@@ -1729,7 +1906,7 @@ ${truncatedDiff}
|
|
|
1729
1906
|
// 清理等待中的认证请求
|
|
1730
1907
|
pendingRequests.clear();
|
|
1731
1908
|
// 关闭 Socket 服务器
|
|
1732
|
-
await
|
|
1909
|
+
await stopHttpServer();
|
|
1733
1910
|
// 关闭所有活跃的 SSE 和 streamable 传输,释放资源
|
|
1734
1911
|
await closeTransports(transports.sse);
|
|
1735
1912
|
await closeTransports(transports.streamable);
|
|
@@ -1785,7 +1962,7 @@ export async function getUserInput(payload) {
|
|
|
1785
1962
|
Logger.log('Socket 客户端已连接');
|
|
1786
1963
|
const workspaceRoot = fileManager.getWorkspaceRoot();
|
|
1787
1964
|
// 注册 token 并等待响应,同时传递 extra 数据给主进程
|
|
1788
|
-
const responsePromise = socketClient.registerToken(token, { workspaceRoot });
|
|
1965
|
+
const responsePromise = socketClient.registerToken(token, { workspaceRoot, plugins: pluginManager.getPlugins() });
|
|
1789
1966
|
// 打开浏览器
|
|
1790
1967
|
await open(authUrl);
|
|
1791
1968
|
// 等待认证响应
|
|
@@ -1819,14 +1996,14 @@ export async function stopSocketServer() {
|
|
|
1819
1996
|
}
|
|
1820
1997
|
// 停止 HTTP 服务器,并关闭所有 SSE 传输
|
|
1821
1998
|
export async function stopHttpServer() {
|
|
1999
|
+
// 关闭 Socket 服务器
|
|
2000
|
+
const closeSocket = stopSocketServer();
|
|
1822
2001
|
if (!httpServer) {
|
|
1823
2002
|
throw new Error('HTTP 服务器未运行');
|
|
1824
2003
|
}
|
|
1825
2004
|
return new Promise((resolve, reject) => {
|
|
1826
2005
|
// 清理等待中的认证请求
|
|
1827
2006
|
pendingRequests.clear();
|
|
1828
|
-
// 关闭 Socket 服务器
|
|
1829
|
-
const closeSocket = stopSocketServer();
|
|
1830
2007
|
httpServer.close((err) => {
|
|
1831
2008
|
if (err) {
|
|
1832
2009
|
reject(err);
|
|
@@ -124,7 +124,7 @@ export class SocketClient {
|
|
|
124
124
|
const timeout = setTimeout(() => {
|
|
125
125
|
this.messageHandlers.delete(token);
|
|
126
126
|
reject(new Error('等待认证响应超时'));
|
|
127
|
-
},
|
|
127
|
+
}, 30 * 60 * 1000); // 30分钟超时
|
|
128
128
|
// 注册消息处理器
|
|
129
129
|
this.messageHandlers.set(token, (data) => {
|
|
130
130
|
clearTimeout(timeout);
|