sloth-d2c-mcp 1.0.4-beta96 → 1.0.4-beta97
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
CHANGED
|
@@ -198,6 +198,133 @@ if (args[0] === 'config') {
|
|
|
198
198
|
console.log(`[sloth] 共停止 ${killedCount} 个进程`);
|
|
199
199
|
}
|
|
200
200
|
process.exit(0);
|
|
201
|
+
} else if (args[0] === 'update') {
|
|
202
|
+
// update 命令:先停止进程,然后更新 sloth
|
|
203
|
+
const { execSync, spawnSync } = await import('node:child_process');
|
|
204
|
+
const os = await import('node:os');
|
|
205
|
+
const { fileURLToPath } = await import('node:url');
|
|
206
|
+
const path = await import('node:path');
|
|
207
|
+
|
|
208
|
+
console.log('[sloth] 正在停止运行中的进程...');
|
|
209
|
+
|
|
210
|
+
// 复用 stop 命令的逻辑
|
|
211
|
+
const ports = [3100, 3101];
|
|
212
|
+
const pidsToKill = new Set();
|
|
213
|
+
|
|
214
|
+
for (const port of ports) {
|
|
215
|
+
try {
|
|
216
|
+
let output = '';
|
|
217
|
+
if (os.platform() === 'win32') {
|
|
218
|
+
output = execSync(`netstat -ano | findstr :${port}`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
219
|
+
const lines = output.trim().split('\n');
|
|
220
|
+
for (const line of lines) {
|
|
221
|
+
const match = line.match(/LISTENING\s+(\d+)/);
|
|
222
|
+
if (match) {
|
|
223
|
+
pidsToKill.add(match[1]);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
} else {
|
|
227
|
+
output = execSync(`lsof -i :${port} -t`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
228
|
+
const pids = output.trim().split('\n').filter(Boolean);
|
|
229
|
+
pids.forEach(pid => pidsToKill.add(pid.trim()));
|
|
230
|
+
}
|
|
231
|
+
} catch {
|
|
232
|
+
// 端口未被占用,忽略错误
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
let killedCount = 0;
|
|
237
|
+
for (const pid of pidsToKill) {
|
|
238
|
+
try {
|
|
239
|
+
let cmdline = '';
|
|
240
|
+
if (os.platform() === 'win32') {
|
|
241
|
+
cmdline = execSync(`wmic process where processid=${pid} get commandline`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
242
|
+
} else {
|
|
243
|
+
cmdline = execSync(`ps -p ${pid} -o command=`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const isSlothProcess = cmdline.includes('sloth') || cmdline.includes('d2c-mcp');
|
|
247
|
+
|
|
248
|
+
if (isSlothProcess) {
|
|
249
|
+
process.kill(Number(pid), 'SIGTERM');
|
|
250
|
+
console.log(`[sloth] 已停止进程 PID: ${pid}`);
|
|
251
|
+
killedCount++;
|
|
252
|
+
}
|
|
253
|
+
} catch (e) {
|
|
254
|
+
// 进程可能已经退出
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (killedCount > 0) {
|
|
259
|
+
console.log(`[sloth] 共停止 ${killedCount} 个进程`);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// 检测包管理器:通过检查 sloth 命令的安装路径来判断
|
|
263
|
+
let packageManager = 'npm'; // 默认使用 npm
|
|
264
|
+
|
|
265
|
+
try {
|
|
266
|
+
// 获取当前脚本的实际路径
|
|
267
|
+
const scriptPath = fileURLToPath(import.meta.url);
|
|
268
|
+
const scriptDir = path.dirname(scriptPath);
|
|
269
|
+
|
|
270
|
+
// 检查路径中是否包含 pnpm 相关目录
|
|
271
|
+
if (scriptDir.includes('pnpm') || scriptDir.includes('.pnpm')) {
|
|
272
|
+
packageManager = 'pnpm';
|
|
273
|
+
} else {
|
|
274
|
+
// 尝试通过 which/where 命令检查 sloth 的安装位置
|
|
275
|
+
try {
|
|
276
|
+
const whichCmd = os.platform() === 'win32' ? 'where sloth' : 'which sloth';
|
|
277
|
+
const slothPath = execSync(whichCmd, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
278
|
+
|
|
279
|
+
if (slothPath.includes('pnpm') || slothPath.includes('.pnpm')) {
|
|
280
|
+
packageManager = 'pnpm';
|
|
281
|
+
}
|
|
282
|
+
} catch {
|
|
283
|
+
// 忽略错误,使用默认的 npm
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// 额外检查:尝试检测全局 pnpm 目录
|
|
287
|
+
if (packageManager === 'npm') {
|
|
288
|
+
try {
|
|
289
|
+
const pnpmRoot = execSync('pnpm root -g', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
290
|
+
if (scriptDir.startsWith(pnpmRoot) || scriptDir.includes(path.dirname(pnpmRoot))) {
|
|
291
|
+
packageManager = 'pnpm';
|
|
292
|
+
}
|
|
293
|
+
} catch {
|
|
294
|
+
// pnpm 未安装或命令失败,使用 npm
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
} catch {
|
|
299
|
+
// 检测失败,使用默认的 npm
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
console.log(`[sloth] 检测到包管理器: ${packageManager}`);
|
|
303
|
+
console.log('[sloth] 正在更新 sloth-d2c-mcp...');
|
|
304
|
+
|
|
305
|
+
// 执行全局安装更新
|
|
306
|
+
const installCmd = packageManager === 'pnpm'
|
|
307
|
+
? 'pnpm install -g sloth-d2c-mcp'
|
|
308
|
+
: 'npm install -g sloth-d2c-mcp';
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
const result = spawnSync(installCmd, {
|
|
312
|
+
shell: true,
|
|
313
|
+
stdio: 'inherit',
|
|
314
|
+
env: process.env
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
if (result.status === 0) {
|
|
318
|
+
console.log('[sloth] 更新完成!');
|
|
319
|
+
} else {
|
|
320
|
+
console.error('[sloth] 更新失败,退出码:', result.status);
|
|
321
|
+
process.exit(result.status || 1);
|
|
322
|
+
}
|
|
323
|
+
} catch (e) {
|
|
324
|
+
console.error('[sloth] 更新失败:', e.message);
|
|
325
|
+
process.exit(1);
|
|
326
|
+
}
|
|
327
|
+
process.exit(0);
|
|
201
328
|
} else if (args[0] === '--server') {
|
|
202
329
|
process.env.SLOTH_COMMAND = 'server';
|
|
203
330
|
} else {
|
package/dist/build/server.js
CHANGED
|
@@ -18,7 +18,7 @@ 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, 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';
|
|
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, chunkOptimizeCodePromptTaro, aggregationOptimizeCodePromptTaro, finalOptimizeCodePromptTaro, noSamplingAggregationPromptTaro, chunkOptimizeCodePromptUniapp, aggregationOptimizeCodePromptUniapp, finalOptimizeCodePromptUniapp, noSamplingAggregationPromptUniapp, } from 'sloth-d2c-node/convert';
|
|
22
22
|
import { SocketServer } from './socket-server.js';
|
|
23
23
|
import { getParam } from './utils/utils.js';
|
|
24
24
|
import { loadPluginFromGlobalDirAsync } from './plugin/loader.js';
|
|
@@ -83,6 +83,8 @@ export async function loadConfig(mcpServer, configManagerInstance) {
|
|
|
83
83
|
{ value: 'ios-oc', label: 'iOS OC' },
|
|
84
84
|
{ value: 'ios-swift', label: 'iOS Swift' },
|
|
85
85
|
{ value: 'kuikly', label: 'Kuikly' },
|
|
86
|
+
{ value: 'taro', label: 'Taro' },
|
|
87
|
+
{ value: 'uniapp', label: 'Uniapp' },
|
|
86
88
|
];
|
|
87
89
|
// 初始化默认框架配置
|
|
88
90
|
if (!config.frameworks || config.frameworks.length === 0) {
|
|
@@ -212,6 +214,54 @@ export async function loadConfig(mcpServer, configManagerInstance) {
|
|
|
212
214
|
...(kuiklyConfig || {}),
|
|
213
215
|
});
|
|
214
216
|
}
|
|
217
|
+
// 检查 taro.json 是否存在,如果不存在则创建
|
|
218
|
+
const taroConfigExists = await configManager.frameworkConfigExists('taro');
|
|
219
|
+
if (!taroConfigExists) {
|
|
220
|
+
await configManager.saveFrameworkConfig('taro', {
|
|
221
|
+
chunkOptimizePrompt: chunkOptimizeCodePromptTaro,
|
|
222
|
+
aggregationOptimizePrompt: aggregationOptimizeCodePromptTaro,
|
|
223
|
+
finalOptimizePrompt: finalOptimizeCodePromptTaro,
|
|
224
|
+
componentAnalysisPrompt: '',
|
|
225
|
+
noSamplingAggregationPrompt: noSamplingAggregationPromptTaro,
|
|
226
|
+
});
|
|
227
|
+
const taroConfigPath = configManager.getFrameworkConfigPath('taro');
|
|
228
|
+
Logger.log(`已创建默认 taro 配置文件: ${taroConfigPath}`);
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
const taroConfig = await configManager.loadFrameworkConfig('taro');
|
|
232
|
+
await configManager.saveFrameworkConfig('taro', {
|
|
233
|
+
chunkOptimizePrompt: chunkOptimizeCodePromptTaro,
|
|
234
|
+
aggregationOptimizePrompt: aggregationOptimizeCodePromptTaro,
|
|
235
|
+
finalOptimizePrompt: finalOptimizeCodePromptTaro,
|
|
236
|
+
componentAnalysisPrompt: '',
|
|
237
|
+
noSamplingAggregationPrompt: noSamplingAggregationPromptTaro,
|
|
238
|
+
...(taroConfig || {}),
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
// 检查 uniapp.json 是否存在,如果不存在则创建
|
|
242
|
+
const uniappConfigExists = await configManager.frameworkConfigExists('uniapp');
|
|
243
|
+
if (!uniappConfigExists) {
|
|
244
|
+
await configManager.saveFrameworkConfig('uniapp', {
|
|
245
|
+
chunkOptimizePrompt: chunkOptimizeCodePromptUniapp,
|
|
246
|
+
aggregationOptimizePrompt: aggregationOptimizeCodePromptUniapp,
|
|
247
|
+
finalOptimizePrompt: finalOptimizeCodePromptUniapp,
|
|
248
|
+
componentAnalysisPrompt: '',
|
|
249
|
+
noSamplingAggregationPrompt: noSamplingAggregationPromptUniapp,
|
|
250
|
+
});
|
|
251
|
+
const uniappConfigPath = configManager.getFrameworkConfigPath('uniapp');
|
|
252
|
+
Logger.log(`已创建默认 uniapp 配置文件: ${uniappConfigPath}`);
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
const uniappConfig = await configManager.loadFrameworkConfig('uniapp');
|
|
256
|
+
await configManager.saveFrameworkConfig('uniapp', {
|
|
257
|
+
chunkOptimizePrompt: chunkOptimizeCodePromptUniapp,
|
|
258
|
+
aggregationOptimizePrompt: aggregationOptimizeCodePromptUniapp,
|
|
259
|
+
finalOptimizePrompt: finalOptimizeCodePromptUniapp,
|
|
260
|
+
componentAnalysisPrompt: '',
|
|
261
|
+
noSamplingAggregationPrompt: noSamplingAggregationPromptUniapp,
|
|
262
|
+
...(uniappConfig || {}),
|
|
263
|
+
});
|
|
264
|
+
}
|
|
215
265
|
}
|
|
216
266
|
catch (error) {
|
|
217
267
|
Logger.error(`获取配置信息时出错: ${error}`);
|
|
@@ -657,7 +707,9 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
657
707
|
const isIosOc = framework.toLowerCase() === 'ios-oc';
|
|
658
708
|
const isIosSwift = framework.toLowerCase() === 'ios-swift';
|
|
659
709
|
const isKuikly = framework.toLowerCase() === 'kuikly';
|
|
660
|
-
const
|
|
710
|
+
const isTaro = framework.toLowerCase() === 'taro';
|
|
711
|
+
const isUniapp = framework.toLowerCase() === 'uniapp';
|
|
712
|
+
let promptSetting = {
|
|
661
713
|
enableFrameworkGuide: isKuikly ? true : false,
|
|
662
714
|
frameworkGuidePrompt: isKuikly ? frameworkPromptKuikly : '',
|
|
663
715
|
chunkOptimizePrompt: isKuikly
|
|
@@ -698,6 +750,24 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
698
750
|
? noSamplingAggregationPromptVue
|
|
699
751
|
: noSamplingAggregationPrompt,
|
|
700
752
|
};
|
|
753
|
+
if (isTaro) {
|
|
754
|
+
promptSetting.enableFrameworkGuide = false;
|
|
755
|
+
promptSetting.frameworkGuidePrompt = '';
|
|
756
|
+
promptSetting.chunkOptimizePrompt = chunkOptimizeCodePromptTaro;
|
|
757
|
+
promptSetting.aggregationOptimizePrompt = aggregationOptimizeCodePromptTaro;
|
|
758
|
+
promptSetting.finalOptimizePrompt = finalOptimizeCodePromptTaro;
|
|
759
|
+
promptSetting.noSamplingAggregationPrompt = noSamplingAggregationPromptTaro;
|
|
760
|
+
promptSetting.componentAnalysisPrompt = componentAnalysisPrompt;
|
|
761
|
+
}
|
|
762
|
+
if (isUniapp) {
|
|
763
|
+
promptSetting.enableFrameworkGuide = false;
|
|
764
|
+
promptSetting.frameworkGuidePrompt = '';
|
|
765
|
+
promptSetting.chunkOptimizePrompt = chunkOptimizeCodePromptUniapp;
|
|
766
|
+
promptSetting.aggregationOptimizePrompt = aggregationOptimizeCodePromptUniapp;
|
|
767
|
+
promptSetting.finalOptimizePrompt = finalOptimizeCodePromptUniapp;
|
|
768
|
+
promptSetting.noSamplingAggregationPrompt = noSamplingAggregationPromptUniapp;
|
|
769
|
+
promptSetting.componentAnalysisPrompt = componentAnalysisPromptVue;
|
|
770
|
+
}
|
|
701
771
|
res.json({
|
|
702
772
|
success: true,
|
|
703
773
|
data: promptSetting,
|
|
@@ -1871,6 +1941,30 @@ ${truncatedDiff}
|
|
|
1871
1941
|
});
|
|
1872
1942
|
}
|
|
1873
1943
|
});
|
|
1944
|
+
app.get('/getVersion', async (req, res) => {
|
|
1945
|
+
try {
|
|
1946
|
+
// 计算 package.json 的正确路径
|
|
1947
|
+
// 从 dist/build/server.js 到根目录的 package.json
|
|
1948
|
+
const packagePath = path.join(__dirname, '../../package.json');
|
|
1949
|
+
const packageContent = await fs.promises.readFile(packagePath, 'utf-8');
|
|
1950
|
+
const packageData = JSON.parse(packageContent);
|
|
1951
|
+
res.json({
|
|
1952
|
+
success: true,
|
|
1953
|
+
data: {
|
|
1954
|
+
version: packageData.version,
|
|
1955
|
+
name: packageData.name,
|
|
1956
|
+
},
|
|
1957
|
+
});
|
|
1958
|
+
}
|
|
1959
|
+
catch (error) {
|
|
1960
|
+
Logger.error('获取版本信息失败:', error);
|
|
1961
|
+
res.status(500).json({
|
|
1962
|
+
success: false,
|
|
1963
|
+
message: '获取版本信息失败',
|
|
1964
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1965
|
+
});
|
|
1966
|
+
}
|
|
1967
|
+
});
|
|
1874
1968
|
// 启动 HTTP 服务器,监听端口
|
|
1875
1969
|
httpServer = app.listen(port, async (err) => {
|
|
1876
1970
|
if (err) {
|