sloth-d2c-mcp 1.0.4-beta93 → 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/index.js +46 -10
- package/dist/build/plugin/loader.js +25 -11
- package/dist/build/plugin/manager.js +2 -0
- package/dist/build/server.js +33 -12
- package/dist/build/socket-client.js +1 -1
- package/dist/interceptor-web/dist/build-report.json +3 -3
- package/dist/interceptor-web/dist/detail.html +1 -1
- package/dist/interceptor-web/dist/index.html +1 -1
- package/package.json +5 -4
package/cli/run.js
CHANGED
|
@@ -102,7 +102,7 @@ if (args[0] === 'config') {
|
|
|
102
102
|
const scriptPath = fileURLToPath(import.meta.url);
|
|
103
103
|
|
|
104
104
|
// 后台启动子进程
|
|
105
|
-
const child = spawn(process.execPath, [scriptPath, '--
|
|
105
|
+
const child = spawn(process.execPath, [scriptPath, '--server'], {
|
|
106
106
|
detached: true,
|
|
107
107
|
stdio: 'ignore',
|
|
108
108
|
env: { ...process.env, NODE_ENV: 'cli' }
|
|
@@ -198,6 +198,8 @@ if (args[0] === 'config') {
|
|
|
198
198
|
console.log(`[sloth] 共停止 ${killedCount} 个进程`);
|
|
199
199
|
}
|
|
200
200
|
process.exit(0);
|
|
201
|
+
} else if (args[0] === '--server') {
|
|
202
|
+
process.env.SLOTH_COMMAND = 'server';
|
|
201
203
|
} else {
|
|
202
204
|
// 设置环境变量为CLI模式
|
|
203
205
|
process.env.NODE_ENV = "cli";
|
package/dist/build/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { ConfigManager, defaultConfigData, } from './config-manager/index.js';
|
|
|
7
7
|
import { cleanup as cleanupTauri } from './interceptor/client.js';
|
|
8
8
|
import { cleanup as cleanupVSCode, getUserInputFromVSCode, isVSCodeAvailable } from './interceptor/vscode.js';
|
|
9
9
|
import { cleanup as cleanupWeb, getUserInput } from './interceptor/web.js';
|
|
10
|
-
import { loadConfig, startHttpServer, stopHttpServer, generateComponentId
|
|
10
|
+
import { loadConfig, startHttpServer, stopHttpServer, generateComponentId } from './server.js';
|
|
11
11
|
import { FileManager } from './utils/file-manager.js';
|
|
12
12
|
import { updateImageMapIfNeeded } from './utils/update.js';
|
|
13
13
|
import { Logger } from './utils/logger.js';
|
|
@@ -24,6 +24,22 @@ import * as path from 'path';
|
|
|
24
24
|
import { fileURLToPath } from 'url';
|
|
25
25
|
import { extractCodeAndComponents } from './utils/extract.js';
|
|
26
26
|
import { trackToolCall } from './utils/tj.js';
|
|
27
|
+
const spawnServerProcess = async () => {
|
|
28
|
+
// run 命令:后台运行 sloth --stdio
|
|
29
|
+
const { spawn } = await import('node:child_process');
|
|
30
|
+
const { fileURLToPath } = await import('node:url');
|
|
31
|
+
// 获取当前脚本路径(兼容 Node.js 18)
|
|
32
|
+
const scriptPath = fileURLToPath(import.meta.url);
|
|
33
|
+
// 后台启动子进程
|
|
34
|
+
const child = spawn(process.execPath, [scriptPath, '--server'], {
|
|
35
|
+
detached: true,
|
|
36
|
+
stdio: 'ignore',
|
|
37
|
+
env: { ...process.env, NODE_ENV: 'cli' }
|
|
38
|
+
});
|
|
39
|
+
// 解除父进程对子进程的引用,允许父进程退出
|
|
40
|
+
child.unref();
|
|
41
|
+
console.log(`[sloth] 已在后台启动,PID: ${child.pid}`);
|
|
42
|
+
};
|
|
27
43
|
/**
|
|
28
44
|
* 启动http & socket监听
|
|
29
45
|
* @param init 是否是初始化,初始化时需要连接stdio transport
|
|
@@ -38,9 +54,13 @@ export async function startListening(init = false) {
|
|
|
38
54
|
if (init) {
|
|
39
55
|
const transport = new StdioServerTransport();
|
|
40
56
|
await mcpServer.connect(transport);
|
|
57
|
+
// 单独启动httpServer进程,用于网页访问
|
|
58
|
+
await spawnServerProcess();
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
// 启动 HTTP 服务器 - 仅启用web服务
|
|
62
|
+
await startHttpServer(port, mcpServer, configManager, false);
|
|
41
63
|
}
|
|
42
|
-
// 启动 HTTP 服务器 - 仅启用web服务
|
|
43
|
-
await startHttpServer(port, mcpServer, configManager, false);
|
|
44
64
|
}
|
|
45
65
|
else {
|
|
46
66
|
// 启动 HTTP 服务器 - 这是核心功能,不依赖 VSCode 日志
|
|
@@ -112,7 +132,7 @@ mcpServer.tool('d2c_figma', 'Convert Figma Design File to Code', {
|
|
|
112
132
|
catch (error) {
|
|
113
133
|
Logger.log('获取根目录时出错:', error);
|
|
114
134
|
}
|
|
115
|
-
await startListening()
|
|
135
|
+
// await startListening()
|
|
116
136
|
let userConfirmedChanges;
|
|
117
137
|
let userHtmlDiff; // 存储 HTML diff 文本
|
|
118
138
|
// 没有配置figmaApiKey,非数据推送模式,无法预览,直接唤起配置页面
|
|
@@ -192,9 +212,14 @@ mcpServer.tool('d2c_figma', 'Convert Figma Design File to Code', {
|
|
|
192
212
|
await fileManager.saveAbsoluteHtml(fileKey, nodeId, absoluteHtml, true);
|
|
193
213
|
}
|
|
194
214
|
else {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
215
|
+
try {
|
|
216
|
+
d2cNodeList = flatted.parse(await fileManager.loadFile(fileKey, nodeId, 'nodeList.json'));
|
|
217
|
+
imageMap = flatted.parse(await fileManager.loadFile(fileKey, nodeId, 'imageMap.json'));
|
|
218
|
+
absoluteHtml = await fileManager.loadAbsoluteHtml(fileKey, nodeId);
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
throw new Error('加载本地数据失败, 请检查文件路径:' + fileManager.getFilePathPublic(fileKey, nodeId, 'nodeList.json'));
|
|
222
|
+
}
|
|
198
223
|
await fileManager.saveAbsoluteHtml(fileKey, nodeId, absoluteHtml, true);
|
|
199
224
|
console.log('cache load data');
|
|
200
225
|
}
|
|
@@ -231,6 +256,9 @@ mcpServer.tool('d2c_figma', 'Convert Figma Design File to Code', {
|
|
|
231
256
|
else {
|
|
232
257
|
const configData = JSON.parse(configDataString);
|
|
233
258
|
const { mcp, groupsData, confirmedChanges, htmlDiff, ...rest } = configData;
|
|
259
|
+
pluginManager.executeHook('afterSubmitConfigData', {
|
|
260
|
+
configData,
|
|
261
|
+
});
|
|
234
262
|
userConfirmedChanges = confirmedChanges;
|
|
235
263
|
userHtmlDiff = htmlDiff; // 保存 HTML diff
|
|
236
264
|
// 保存旧配置用于比较
|
|
@@ -473,17 +501,19 @@ mcpServer.tool('d2c_figma', 'Convert Figma Design File to Code', {
|
|
|
473
501
|
Logger.log(`加载组件数据库,共 ${componentsDatabase.length} 个组件`);
|
|
474
502
|
// 构建组件映射提示词(包含组件映射、组件上下文、标记组件和完整组件数据库)
|
|
475
503
|
const componentMappingPrompt = buildComponentMappingPrompt(componentMappings, componentContexts, markedComponents, componentsDatabase);
|
|
504
|
+
const { prompt: pluginFinalPrompt = '' } = await pluginManager.executeHook('beforeFinalPrompt', { configData: config.fileConfigs?.[fileKey] || '' });
|
|
505
|
+
console.log('pluginFinalPrompt', pluginFinalPrompt);
|
|
476
506
|
// 使用提示词(已包含默认值)
|
|
477
507
|
return {
|
|
478
508
|
content: [
|
|
479
509
|
isSupportSampling
|
|
480
510
|
? {
|
|
481
511
|
type: 'text',
|
|
482
|
-
text: finalPrompt + componentMappingPrompt,
|
|
512
|
+
text: finalPrompt + componentMappingPrompt + pluginFinalPrompt,
|
|
483
513
|
}
|
|
484
514
|
: {
|
|
485
515
|
type: 'text',
|
|
486
|
-
text: noSamplingPrompt + componentMappingPrompt,
|
|
516
|
+
text: noSamplingPrompt + componentMappingPrompt + pluginFinalPrompt,
|
|
487
517
|
},
|
|
488
518
|
...codeSnippets.map((code) => {
|
|
489
519
|
return {
|
|
@@ -1128,6 +1158,9 @@ async function main() {
|
|
|
1128
1158
|
}
|
|
1129
1159
|
process.exit(0);
|
|
1130
1160
|
}
|
|
1161
|
+
if (process.env.SLOTH_COMMAND === 'server') {
|
|
1162
|
+
await startListening();
|
|
1163
|
+
}
|
|
1131
1164
|
try {
|
|
1132
1165
|
// 先输出基本启动信息到控制台,确保即使 VSCode 日志失败也能看到启动过程
|
|
1133
1166
|
console.log(`[${new Date().toISOString()}] Starting Figma transcoding interceptor MCP server...`);
|
|
@@ -1179,7 +1212,6 @@ process.on('SIGTERM', async () => {
|
|
|
1179
1212
|
catch (error) {
|
|
1180
1213
|
// 忽略日志错误,确保清理过程继续
|
|
1181
1214
|
}
|
|
1182
|
-
await stopSocketServer();
|
|
1183
1215
|
cleanupTauri();
|
|
1184
1216
|
cleanupWeb();
|
|
1185
1217
|
cleanupVSCode();
|
|
@@ -1290,6 +1322,10 @@ else if (args[0] === 'clear') {
|
|
|
1290
1322
|
// 设置环境变量标识这是 clear 命令
|
|
1291
1323
|
process.env.SLOTH_COMMAND = 'clear';
|
|
1292
1324
|
}
|
|
1325
|
+
else if (args[0] === '--server') {
|
|
1326
|
+
// 设置环境变量标识这是 clear 命令
|
|
1327
|
+
process.env.SLOTH_COMMAND = 'server';
|
|
1328
|
+
}
|
|
1293
1329
|
else {
|
|
1294
1330
|
// 设置环境变量为CLI模式
|
|
1295
1331
|
process.env.NODE_ENV = 'cli';
|
|
@@ -3,6 +3,7 @@ import { promises as fs } from 'fs';
|
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
5
|
import envPaths from 'env-paths';
|
|
6
|
+
import { createRequire } from 'module';
|
|
6
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
8
|
const __dirname = path.dirname(__filename);
|
|
8
9
|
// 检测是否存在 pnpm
|
|
@@ -17,7 +18,7 @@ function hasPnpm() {
|
|
|
17
18
|
}
|
|
18
19
|
// 获取包管理器命令
|
|
19
20
|
function getPackageManager() {
|
|
20
|
-
return
|
|
21
|
+
return 'npm';
|
|
21
22
|
}
|
|
22
23
|
// 使用 env-paths 获取配置目录(与 config-manager 保持一致)
|
|
23
24
|
const paths = envPaths('d2c-mcp');
|
|
@@ -25,7 +26,14 @@ const paths = envPaths('d2c-mcp');
|
|
|
25
26
|
function getGlobalPackageDir() {
|
|
26
27
|
// 在构建后的目录中: dist/build/plugin/loader.js
|
|
27
28
|
// 需要向上三级才能找到包根目录
|
|
28
|
-
return path.resolve(__dirname, '..', '..', '..')
|
|
29
|
+
// return path.resolve(__dirname, '..', '..', '..')
|
|
30
|
+
try {
|
|
31
|
+
const pm = getPackageManager();
|
|
32
|
+
return execSync(`${pm} root -g`, { encoding: 'utf-8' }).trim();
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return '';
|
|
36
|
+
}
|
|
29
37
|
}
|
|
30
38
|
// 获取全局插件配置文件路径(与 config.json 在同一目录)
|
|
31
39
|
function getGlobalPluginsConfigPath() {
|
|
@@ -68,6 +76,12 @@ async function loadWorkspacePluginsConfig(workspaceRoot) {
|
|
|
68
76
|
return { plugins: [] };
|
|
69
77
|
}
|
|
70
78
|
}
|
|
79
|
+
export async function loadPluginFromGlobalDirAsync(packageName) {
|
|
80
|
+
const globalDir = getGlobalPackageDir();
|
|
81
|
+
const require = createRequire(path.join(globalDir));
|
|
82
|
+
const resolvedPath = require.resolve(packageName);
|
|
83
|
+
return await import(resolvedPath);
|
|
84
|
+
}
|
|
71
85
|
/**
|
|
72
86
|
* 解析插件配置项,统一返回 { name, config } 格式
|
|
73
87
|
*/
|
|
@@ -92,7 +106,7 @@ async function checkLocalPlugin(workspaceRoot, pluginName) {
|
|
|
92
106
|
// 检查 npm 包是否已安装
|
|
93
107
|
async function isNpmPackageInstalled(packageName) {
|
|
94
108
|
try {
|
|
95
|
-
await
|
|
109
|
+
await loadPluginFromGlobalDirAsync(packageName);
|
|
96
110
|
return true;
|
|
97
111
|
}
|
|
98
112
|
catch {
|
|
@@ -125,11 +139,11 @@ async function tryInstallNpmPackage(packageName) {
|
|
|
125
139
|
export async function installPlugin(packageName) {
|
|
126
140
|
const globalDir = getGlobalPackageDir();
|
|
127
141
|
console.log(`[sloth] 正在安装插件: ${packageName}`);
|
|
128
|
-
console.log(`[sloth] 安装目录: ${globalDir}`)
|
|
142
|
+
// console.log(`[sloth] 安装目录: ${globalDir}`)
|
|
129
143
|
try {
|
|
130
144
|
const pm = getPackageManager();
|
|
131
145
|
// 在全局包目录下执行安装
|
|
132
|
-
execSync(`${pm} install ${packageName}`, {
|
|
146
|
+
execSync(`${pm} install -g ${packageName}`, {
|
|
133
147
|
cwd: globalDir,
|
|
134
148
|
stdio: 'inherit',
|
|
135
149
|
});
|
|
@@ -239,15 +253,15 @@ export async function loadWorkspacePlugins(workspaceRoot) {
|
|
|
239
253
|
if (!isInstalled) {
|
|
240
254
|
// 尝试安装
|
|
241
255
|
console.log(`[sloth] 插件 ${pluginName} 未安装,尝试安装...`);
|
|
242
|
-
const installSuccess = await tryInstallNpmPackage(pluginName)
|
|
243
|
-
if (!installSuccess) {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
256
|
+
// const installSuccess = await tryInstallNpmPackage(pluginName)
|
|
257
|
+
// if (!installSuccess) {
|
|
258
|
+
// failedPlugins.push(pluginName)
|
|
259
|
+
// continue
|
|
260
|
+
// }
|
|
247
261
|
}
|
|
248
262
|
// 加载 npm 包
|
|
249
263
|
try {
|
|
250
|
-
const pluginModule = await
|
|
264
|
+
const pluginModule = await loadPluginFromGlobalDirAsync(pluginName);
|
|
251
265
|
console.log('pluginModule', pluginModule);
|
|
252
266
|
const plugin = {
|
|
253
267
|
name: pluginName,
|
|
@@ -100,6 +100,7 @@ class PluginManager {
|
|
|
100
100
|
...params,
|
|
101
101
|
...(lastReturnVal || {}),
|
|
102
102
|
_config: context.config,
|
|
103
|
+
workspaceRoot: this.workspaceRoot,
|
|
103
104
|
}, context);
|
|
104
105
|
// 更新上一个插件信息
|
|
105
106
|
lastPlugin = plugin.name;
|
|
@@ -107,6 +108,7 @@ class PluginManager {
|
|
|
107
108
|
...params,
|
|
108
109
|
...(lastReturnVal || {}),
|
|
109
110
|
...(result || {}),
|
|
111
|
+
workspaceRoot: this.workspaceRoot,
|
|
110
112
|
};
|
|
111
113
|
}
|
|
112
114
|
catch (error) {
|
package/dist/build/server.js
CHANGED
|
@@ -21,7 +21,8 @@ import { extractJson } from './utils/extract.js';
|
|
|
21
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
23
|
import { getParam } from './utils/utils.js';
|
|
24
|
-
import {
|
|
24
|
+
import { loadPluginFromGlobalDirAsync } from './plugin/loader.js';
|
|
25
|
+
import { pluginManager } from './plugin/manager.js';
|
|
25
26
|
/**
|
|
26
27
|
* 生成组件 ID(4位随机字符串)
|
|
27
28
|
*/
|
|
@@ -48,7 +49,7 @@ let configManager = null; // 配置管理器实例
|
|
|
48
49
|
const __filename = fileURLToPath(import.meta.url);
|
|
49
50
|
const __dirname = path.dirname(__filename);
|
|
50
51
|
// 获取端口号
|
|
51
|
-
let PORT =
|
|
52
|
+
let PORT = 3100;
|
|
52
53
|
// 导出获取端口号的函数
|
|
53
54
|
export function getPort() {
|
|
54
55
|
return PORT;
|
|
@@ -415,7 +416,8 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
415
416
|
const fileKey = req.query.fileKey;
|
|
416
417
|
const nodeId = req.query.nodeId;
|
|
417
418
|
const framework = req.query.framework;
|
|
418
|
-
const plugins = await listWorkspacePlugins(req.workspaceRoot)
|
|
419
|
+
// const plugins = await listWorkspacePlugins(req.workspaceRoot)
|
|
420
|
+
const plugins = await socketServer?.getTokenExtraField(req.uuid, 'plugins');
|
|
419
421
|
if (fileKey) {
|
|
420
422
|
// 如果提供了 fileKey,返回该 fileKey 的特定配置
|
|
421
423
|
const globalConfig = await configManager.load();
|
|
@@ -449,7 +451,7 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
449
451
|
defaultFramework: globalConfig.defaultFramework || 'react',
|
|
450
452
|
fileKey: fileKey,
|
|
451
453
|
groupsData: groupsData,
|
|
452
|
-
plugins,
|
|
454
|
+
pluginSetting: plugins,
|
|
453
455
|
},
|
|
454
456
|
});
|
|
455
457
|
}
|
|
@@ -494,7 +496,7 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
494
496
|
imageSetting: configStorage.imageSetting || {},
|
|
495
497
|
promptSetting: promptSetting,
|
|
496
498
|
frameworks: frameworks,
|
|
497
|
-
plugins,
|
|
499
|
+
pluginSetting: plugins,
|
|
498
500
|
},
|
|
499
501
|
});
|
|
500
502
|
}
|
|
@@ -931,6 +933,25 @@ export async function startHttpServer(port = PORT, mcpServer, configManagerInsta
|
|
|
931
933
|
message: '日志重连已启动',
|
|
932
934
|
});
|
|
933
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
|
+
});
|
|
934
955
|
// ==================== 组件映射相关接口 ====================
|
|
935
956
|
/**
|
|
936
957
|
* 获取项目根目录
|
|
@@ -1853,9 +1874,9 @@ ${truncatedDiff}
|
|
|
1853
1874
|
// 启动 HTTP 服务器,监听端口
|
|
1854
1875
|
httpServer = app.listen(port, async (err) => {
|
|
1855
1876
|
if (err) {
|
|
1856
|
-
Logger.error('HTTP 服务器启动失败:', err);
|
|
1857
1877
|
httpServer = null;
|
|
1858
|
-
|
|
1878
|
+
Logger.error('HTTP 服务器启动失败:', err, '退出进程');
|
|
1879
|
+
process.exit(0);
|
|
1859
1880
|
}
|
|
1860
1881
|
Logger.log(`HTTP server listening on port ${port}`);
|
|
1861
1882
|
Logger.log(`SSE endpoint available at http://localhost:${port}/sse`);
|
|
@@ -1875,7 +1896,7 @@ ${truncatedDiff}
|
|
|
1875
1896
|
}
|
|
1876
1897
|
catch (error) {
|
|
1877
1898
|
Logger.error('Socket 服务器启动失败:', error);
|
|
1878
|
-
|
|
1899
|
+
process.exit(0);
|
|
1879
1900
|
}
|
|
1880
1901
|
});
|
|
1881
1902
|
// 监听 SIGINT 信号,优雅关闭服务器和所有会话
|
|
@@ -1885,7 +1906,7 @@ ${truncatedDiff}
|
|
|
1885
1906
|
// 清理等待中的认证请求
|
|
1886
1907
|
pendingRequests.clear();
|
|
1887
1908
|
// 关闭 Socket 服务器
|
|
1888
|
-
await
|
|
1909
|
+
await stopHttpServer();
|
|
1889
1910
|
// 关闭所有活跃的 SSE 和 streamable 传输,释放资源
|
|
1890
1911
|
await closeTransports(transports.sse);
|
|
1891
1912
|
await closeTransports(transports.streamable);
|
|
@@ -1941,7 +1962,7 @@ export async function getUserInput(payload) {
|
|
|
1941
1962
|
Logger.log('Socket 客户端已连接');
|
|
1942
1963
|
const workspaceRoot = fileManager.getWorkspaceRoot();
|
|
1943
1964
|
// 注册 token 并等待响应,同时传递 extra 数据给主进程
|
|
1944
|
-
const responsePromise = socketClient.registerToken(token, { workspaceRoot });
|
|
1965
|
+
const responsePromise = socketClient.registerToken(token, { workspaceRoot, plugins: pluginManager.getPlugins() });
|
|
1945
1966
|
// 打开浏览器
|
|
1946
1967
|
await open(authUrl);
|
|
1947
1968
|
// 等待认证响应
|
|
@@ -1975,14 +1996,14 @@ export async function stopSocketServer() {
|
|
|
1975
1996
|
}
|
|
1976
1997
|
// 停止 HTTP 服务器,并关闭所有 SSE 传输
|
|
1977
1998
|
export async function stopHttpServer() {
|
|
1999
|
+
// 关闭 Socket 服务器
|
|
2000
|
+
const closeSocket = stopSocketServer();
|
|
1978
2001
|
if (!httpServer) {
|
|
1979
2002
|
throw new Error('HTTP 服务器未运行');
|
|
1980
2003
|
}
|
|
1981
2004
|
return new Promise((resolve, reject) => {
|
|
1982
2005
|
// 清理等待中的认证请求
|
|
1983
2006
|
pendingRequests.clear();
|
|
1984
|
-
// 关闭 Socket 服务器
|
|
1985
|
-
const closeSocket = stopSocketServer();
|
|
1986
2007
|
httpServer.close((err) => {
|
|
1987
2008
|
if (err) {
|
|
1988
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);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"buildTime": "2026-01-
|
|
2
|
+
"buildTime": "2026-01-25T17:24:40.636Z",
|
|
3
3
|
"mode": "build",
|
|
4
4
|
"pages": {
|
|
5
5
|
"main": {
|
|
6
6
|
"file": "index.html",
|
|
7
|
-
"size":
|
|
7
|
+
"size": 1649150,
|
|
8
8
|
"sizeFormatted": "1.57 MB"
|
|
9
9
|
},
|
|
10
10
|
"detail": {
|
|
@@ -13,6 +13,6 @@
|
|
|
13
13
|
"sizeFormatted": "275.16 KB"
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
|
-
"totalSize":
|
|
16
|
+
"totalSize": 1930916,
|
|
17
17
|
"totalSizeFormatted": "1.84 MB"
|
|
18
18
|
}
|