ms-vite-plugin 1.1.10 → 1.1.12
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/dist/mcp/tools.js +59 -157
- package/dist/project.js +9 -0
- package/package.json +1 -1
package/dist/mcp/tools.js
CHANGED
|
@@ -270,13 +270,15 @@ function registerDocTools(server) {
|
|
|
270
270
|
*/
|
|
271
271
|
function registerRuntimeTools(server) {
|
|
272
272
|
/**
|
|
273
|
-
* MCP
|
|
273
|
+
* MCP 进程内当前工作目录(仅内存态,不落盘)
|
|
274
|
+
* 说明:用于同一轮 MCP 进程内复用目录,进程重启后需由 AI 再次调用 set_workspace 设置。
|
|
274
275
|
*/
|
|
275
276
|
let currentWorkspacePath;
|
|
276
277
|
/**
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
* @
|
|
278
|
+
* 解析本次调用使用的工作目录
|
|
279
|
+
* 优先级:workspacePath 参数 > set_workspace 记忆值
|
|
280
|
+
* @param workspacePath 可选工作目录
|
|
281
|
+
* @returns 返回生效的绝对路径
|
|
280
282
|
* @example
|
|
281
283
|
* const workspace = resolveWorkspacePath("/Users/demo/project")
|
|
282
284
|
*/
|
|
@@ -288,7 +290,7 @@ function registerRuntimeTools(server) {
|
|
|
288
290
|
if (currentWorkspacePath) {
|
|
289
291
|
return currentWorkspacePath;
|
|
290
292
|
}
|
|
291
|
-
|
|
293
|
+
throw new Error("未设置工作目录:请先调用 set_workspace,或在本次工具调用时传 workspacePath。");
|
|
292
294
|
}
|
|
293
295
|
/**
|
|
294
296
|
* 校验并返回有效工作目录
|
|
@@ -302,48 +304,50 @@ function registerRuntimeTools(server) {
|
|
|
302
304
|
await (0, project_2.ensureValidKuaiJSProject)(workspace);
|
|
303
305
|
return workspace;
|
|
304
306
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
307
|
+
server.registerTool("set_workspace", {
|
|
308
|
+
title: "Set Workspace",
|
|
309
|
+
description: "设置当前 MCP 进程内的默认工作目录。后续 build/run/package 优先使用该目录。",
|
|
310
|
+
inputSchema: {
|
|
311
|
+
workspacePath: z
|
|
312
|
+
.string()
|
|
313
|
+
.min(1)
|
|
314
|
+
.describe("快点JS 项目目录绝对路径(需包含 package.json 与 scripts)"),
|
|
315
|
+
},
|
|
316
|
+
}, async ({ workspacePath }) => {
|
|
317
|
+
const workspace = await ensureWorkspacePath(workspacePath);
|
|
318
|
+
return {
|
|
319
|
+
content: [
|
|
320
|
+
{
|
|
321
|
+
type: "text",
|
|
322
|
+
text: `默认工作目录已设置为: ${workspace}`,
|
|
323
|
+
},
|
|
324
|
+
],
|
|
325
|
+
};
|
|
326
|
+
});
|
|
327
|
+
server.registerTool("get_workspace", {
|
|
328
|
+
title: "Get Workspace",
|
|
329
|
+
description: "查看当前 MCP 进程内记忆的工作目录。",
|
|
330
|
+
inputSchema: {},
|
|
331
|
+
}, async () => {
|
|
332
|
+
if (!currentWorkspacePath) {
|
|
333
|
+
return {
|
|
334
|
+
content: [
|
|
335
|
+
{
|
|
336
|
+
type: "text",
|
|
337
|
+
text: "当前未设置工作目录,请先调用 set_workspace。",
|
|
338
|
+
},
|
|
339
|
+
],
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
return {
|
|
343
|
+
content: [
|
|
344
|
+
{
|
|
345
|
+
type: "text",
|
|
346
|
+
text: `当前工作目录: ${currentWorkspacePath}`,
|
|
347
|
+
},
|
|
348
|
+
],
|
|
349
|
+
};
|
|
350
|
+
});
|
|
347
351
|
/**
|
|
348
352
|
* 解析运行目标:
|
|
349
353
|
* - 显式 transport=ws: 强制走 ws
|
|
@@ -381,41 +385,6 @@ function registerRuntimeTools(server) {
|
|
|
381
385
|
label: `${device.ip}:${device.port}`,
|
|
382
386
|
};
|
|
383
387
|
}
|
|
384
|
-
server.registerTool("set_workspace", {
|
|
385
|
-
title: "Set Workspace",
|
|
386
|
-
description: "设置默认工作目录。后续 build/run/package/watch 等工具会优先使用该目录。",
|
|
387
|
-
inputSchema: {
|
|
388
|
-
workspacePath: z
|
|
389
|
-
.string()
|
|
390
|
-
.min(1)
|
|
391
|
-
.describe("快点JS 项目目录绝对路径(需包含 package.json 与 scripts)"),
|
|
392
|
-
},
|
|
393
|
-
}, async ({ workspacePath }) => {
|
|
394
|
-
const workspace = await ensureWorkspacePath(workspacePath);
|
|
395
|
-
return {
|
|
396
|
-
content: [
|
|
397
|
-
{
|
|
398
|
-
type: "text",
|
|
399
|
-
text: `默认工作目录已设置为: ${workspace}`,
|
|
400
|
-
},
|
|
401
|
-
],
|
|
402
|
-
};
|
|
403
|
-
});
|
|
404
|
-
server.registerTool("get_workspace", {
|
|
405
|
-
title: "Get Workspace",
|
|
406
|
-
description: "查看当前 MCP 生效的工作目录。",
|
|
407
|
-
inputSchema: {},
|
|
408
|
-
}, async () => {
|
|
409
|
-
const workspace = resolveWorkspacePath();
|
|
410
|
-
return {
|
|
411
|
-
content: [
|
|
412
|
-
{
|
|
413
|
-
type: "text",
|
|
414
|
-
text: `当前工作目录: ${workspace}`,
|
|
415
|
-
},
|
|
416
|
-
],
|
|
417
|
-
};
|
|
418
|
-
});
|
|
419
388
|
server.registerTool("set_device", {
|
|
420
389
|
title: "Set Device",
|
|
421
390
|
description: "设置默认设备连接信息。首次配置后,后续 run/stop 可不再传 ip。",
|
|
@@ -635,11 +604,6 @@ function registerRuntimeTools(server) {
|
|
|
635
604
|
title: "Watch Logs",
|
|
636
605
|
description: "通过 SSE 监听设备实时日志。首次可传 ip,也可复用 set_device 保存的默认设备。",
|
|
637
606
|
inputSchema: {
|
|
638
|
-
workspacePath: z
|
|
639
|
-
.string()
|
|
640
|
-
.min(1)
|
|
641
|
-
.optional()
|
|
642
|
-
.describe("可选工作目录;不传时使用 set_workspace 记录值或 MCP 启动目录"),
|
|
643
607
|
ip: z
|
|
644
608
|
.string()
|
|
645
609
|
.min(1)
|
|
@@ -669,8 +633,7 @@ function registerRuntimeTools(server) {
|
|
|
669
633
|
.default(200)
|
|
670
634
|
.describe("最多收集日志条数,默认 200"),
|
|
671
635
|
},
|
|
672
|
-
}, async ({
|
|
673
|
-
await ensureWorkspacePath(workspacePath);
|
|
636
|
+
}, async ({ ip, port, durationSeconds, maxLogs }) => {
|
|
674
637
|
const device = await (0, device_config_1.resolveDeviceConfig)(ip, port);
|
|
675
638
|
const result = await (0, project_1.watchDeviceLogsBySse)(device.ip, device.port, durationSeconds * 1000, maxLogs);
|
|
676
639
|
const logsPreview = result.logs
|
|
@@ -701,7 +664,7 @@ function registerRuntimeTools(server) {
|
|
|
701
664
|
.string()
|
|
702
665
|
.min(1)
|
|
703
666
|
.optional()
|
|
704
|
-
.describe("可选工作目录;不传时使用 set_workspace
|
|
667
|
+
.describe("可选工作目录;不传时使用 set_workspace 记忆值"),
|
|
705
668
|
dev: z
|
|
706
669
|
.boolean()
|
|
707
670
|
.optional()
|
|
@@ -724,7 +687,7 @@ function registerRuntimeTools(server) {
|
|
|
724
687
|
.string()
|
|
725
688
|
.min(1)
|
|
726
689
|
.optional()
|
|
727
|
-
.describe("可选工作目录;不传时使用 set_workspace
|
|
690
|
+
.describe("可选工作目录;不传时使用 set_workspace 记忆值"),
|
|
728
691
|
},
|
|
729
692
|
}, async ({ workspacePath }) => {
|
|
730
693
|
const workspace = await ensureWorkspacePath(workspacePath);
|
|
@@ -771,50 +734,10 @@ function registerRuntimeTools(server) {
|
|
|
771
734
|
.string()
|
|
772
735
|
.min(1)
|
|
773
736
|
.optional()
|
|
774
|
-
.describe("可选工作目录;不传时使用 set_workspace
|
|
775
|
-
watchLogs: z
|
|
776
|
-
.boolean()
|
|
777
|
-
.optional()
|
|
778
|
-
.default(false)
|
|
779
|
-
.describe("是否在运行前启动日志监听,默认 false"),
|
|
780
|
-
logMode: z
|
|
781
|
-
.enum(["single", "continuous"])
|
|
782
|
-
.optional()
|
|
783
|
-
.default("single")
|
|
784
|
-
.describe("日志模式:single=按 runtime_status 收敛,continuous=持续监听"),
|
|
785
|
-
logMaxLogs: z
|
|
786
|
-
.number()
|
|
787
|
-
.int()
|
|
788
|
-
.min(10)
|
|
789
|
-
.max(5000)
|
|
790
|
-
.optional()
|
|
791
|
-
.default(300)
|
|
792
|
-
.describe("日志最大收集条数,默认 300"),
|
|
737
|
+
.describe("可选工作目录;不传时使用 set_workspace 记忆值"),
|
|
793
738
|
},
|
|
794
|
-
}, async ({ transport, ip, port, wsPort, wsWaitMs, workspacePath
|
|
739
|
+
}, async ({ transport, ip, port, wsPort, wsWaitMs, workspacePath }) => {
|
|
795
740
|
const workspace = await ensureWorkspacePath(workspacePath);
|
|
796
|
-
let logPromise;
|
|
797
|
-
let logDeviceIp = "";
|
|
798
|
-
let logDevicePort = 0;
|
|
799
|
-
let logSetupWarning = "";
|
|
800
|
-
let logModeNotice = "";
|
|
801
|
-
if (watchLogs) {
|
|
802
|
-
try {
|
|
803
|
-
const logDevice = await (0, device_config_1.resolveDeviceConfig)(ip, port);
|
|
804
|
-
// 先挂监听,再执行 run,确保拿到启动期实时日志
|
|
805
|
-
logDeviceIp = logDevice.ip;
|
|
806
|
-
logDevicePort = logDevice.port;
|
|
807
|
-
if (logMode === "continuous") {
|
|
808
|
-
logModeNotice = startBackgroundContinuousLogWatch(logDevice.ip, logDevice.port, logMaxLogs);
|
|
809
|
-
}
|
|
810
|
-
else {
|
|
811
|
-
logPromise = (0, project_1.watchDeviceLogsBySse)(logDevice.ip, logDevice.port, 0, logMaxLogs, true, true);
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
catch (error) {
|
|
815
|
-
logSetupWarning = `日志监听未启动: ${error instanceof Error ? error.message : String(error)}`;
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
741
|
const target = await resolvePreferredRuntimeTarget({
|
|
819
742
|
transport,
|
|
820
743
|
ip,
|
|
@@ -835,26 +758,11 @@ function registerRuntimeTools(server) {
|
|
|
835
758
|
transport: "http",
|
|
836
759
|
workspacePath: workspace,
|
|
837
760
|
});
|
|
838
|
-
let logSection = "";
|
|
839
|
-
if (logPromise) {
|
|
840
|
-
const result = await logPromise;
|
|
841
|
-
const sections = [formatRunLogSection(logDeviceIp, logDevicePort, result)];
|
|
842
|
-
if (result.stopReason === "runtime_continuous") {
|
|
843
|
-
sections.push(startBackgroundContinuousLogWatch(logDeviceIp, logDevicePort, logMaxLogs));
|
|
844
|
-
}
|
|
845
|
-
logSection = `\n\n${sections.join("\n")}`;
|
|
846
|
-
}
|
|
847
|
-
else if (logModeNotice) {
|
|
848
|
-
logSection = `\n\n${logModeNotice}`;
|
|
849
|
-
}
|
|
850
|
-
else if (logSetupWarning) {
|
|
851
|
-
logSection = `\n\n${logSetupWarning}`;
|
|
852
|
-
}
|
|
853
761
|
return {
|
|
854
762
|
content: [
|
|
855
763
|
{
|
|
856
764
|
type: "text",
|
|
857
|
-
text: `运行请求已发送到 ${target.label}
|
|
765
|
+
text: `运行请求已发送到 ${target.label}`,
|
|
858
766
|
},
|
|
859
767
|
],
|
|
860
768
|
};
|
|
@@ -897,7 +805,7 @@ function registerRuntimeTools(server) {
|
|
|
897
805
|
.string()
|
|
898
806
|
.min(1)
|
|
899
807
|
.optional()
|
|
900
|
-
.describe("可选工作目录;不传时使用 set_workspace
|
|
808
|
+
.describe("可选工作目录;不传时使用 set_workspace 记忆值"),
|
|
901
809
|
},
|
|
902
810
|
}, async ({ transport, ip, port, wsPort, wsWaitMs, workspacePath }) => {
|
|
903
811
|
const workspace = await ensureWorkspacePath(workspacePath);
|
|
@@ -964,14 +872,8 @@ function registerRuntimeTools(server) {
|
|
|
964
872
|
.max(600000)
|
|
965
873
|
.optional()
|
|
966
874
|
.describe("WS 等待连接超时毫秒(transport=ws 时可选,默认 30000)"),
|
|
967
|
-
workspacePath: z
|
|
968
|
-
.string()
|
|
969
|
-
.min(1)
|
|
970
|
-
.optional()
|
|
971
|
-
.describe("可选工作目录;不传时使用 set_workspace 记录值或 MCP 启动目录"),
|
|
972
875
|
},
|
|
973
|
-
}, async ({ transport, ip, port, wsPort, wsWaitMs
|
|
974
|
-
resolveWorkspacePath(workspacePath);
|
|
876
|
+
}, async ({ transport, ip, port, wsPort, wsWaitMs }) => {
|
|
975
877
|
const target = await resolvePreferredRuntimeTarget({
|
|
976
878
|
transport,
|
|
977
879
|
ip,
|
package/dist/project.js
CHANGED
|
@@ -541,6 +541,7 @@ async function watchDeviceLogsBySse(ip, port, durationMs = 15000, maxLogs = 200,
|
|
|
541
541
|
let stopReason = "unknown";
|
|
542
542
|
let seenRunningStatus = false;
|
|
543
543
|
let runningStatusCount = 0;
|
|
544
|
+
let shouldStopReading = false;
|
|
544
545
|
const timeoutHandle = durationMs > 0
|
|
545
546
|
? setTimeout(() => {
|
|
546
547
|
stopReason = "timeout";
|
|
@@ -562,6 +563,9 @@ async function watchDeviceLogsBySse(ip, port, durationMs = 15000, maxLogs = 200,
|
|
|
562
563
|
const decoder = new TextDecoder("utf-8");
|
|
563
564
|
let buffer = "";
|
|
564
565
|
while (true) {
|
|
566
|
+
if (shouldStopReading) {
|
|
567
|
+
break;
|
|
568
|
+
}
|
|
565
569
|
const { value, done } = await reader.read();
|
|
566
570
|
if (done) {
|
|
567
571
|
if (stopReason === "unknown") {
|
|
@@ -601,6 +605,7 @@ async function watchDeviceLogsBySse(ip, port, durationMs = 15000, maxLogs = 200,
|
|
|
601
605
|
if (stopOnRuntimeContinuous && runningStatusCount >= 2) {
|
|
602
606
|
stopReason = "runtime_continuous";
|
|
603
607
|
controller.abort();
|
|
608
|
+
shouldStopReading = true;
|
|
604
609
|
break;
|
|
605
610
|
}
|
|
606
611
|
}
|
|
@@ -612,6 +617,7 @@ async function watchDeviceLogsBySse(ip, port, durationMs = 15000, maxLogs = 200,
|
|
|
612
617
|
parsed.isRunning === false) {
|
|
613
618
|
stopReason = "runtime_stopped";
|
|
614
619
|
controller.abort();
|
|
620
|
+
shouldStopReading = true;
|
|
615
621
|
break;
|
|
616
622
|
}
|
|
617
623
|
}
|
|
@@ -622,6 +628,9 @@ async function watchDeviceLogsBySse(ip, port, durationMs = 15000, maxLogs = 200,
|
|
|
622
628
|
}
|
|
623
629
|
splitIndex = buffer.search(/\r?\n\r?\n/);
|
|
624
630
|
}
|
|
631
|
+
if (shouldStopReading) {
|
|
632
|
+
break;
|
|
633
|
+
}
|
|
625
634
|
}
|
|
626
635
|
}
|
|
627
636
|
catch (error) {
|