ms-vite-plugin 1.1.5 → 1.1.6
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 +103 -13
- package/dist/project.d.ts +2 -25
- package/dist/project.js +2 -64
- package/package.json +1 -1
package/dist/mcp/tools.js
CHANGED
|
@@ -302,6 +302,24 @@ function registerRuntimeTools(server) {
|
|
|
302
302
|
await (0, project_2.ensureValidKuaiJSProject)(workspace);
|
|
303
303
|
return workspace;
|
|
304
304
|
}
|
|
305
|
+
/**
|
|
306
|
+
* 格式化日志监听结果,供 run/run_ui 结果文本复用
|
|
307
|
+
* @param result 日志监听结果
|
|
308
|
+
* @returns 返回可直接拼接到 tool 响应中的文本
|
|
309
|
+
* @example
|
|
310
|
+
* const text = formatWatchLogsResult(result)
|
|
311
|
+
*/
|
|
312
|
+
function formatWatchLogsResult(result) {
|
|
313
|
+
const logsPreview = result.logs
|
|
314
|
+
.slice(-10)
|
|
315
|
+
.map((log) => `[${log.timestamp}] [${log.level.toUpperCase()}] ${log.message}`)
|
|
316
|
+
.join("\n");
|
|
317
|
+
return [
|
|
318
|
+
`日志监听: 收集 ${result.logs.length} 条,runtime_status ${result.runtimeStatus.length} 条`,
|
|
319
|
+
"最新日志(后10条):",
|
|
320
|
+
logsPreview || "无日志",
|
|
321
|
+
].join("\n");
|
|
322
|
+
}
|
|
305
323
|
/**
|
|
306
324
|
* 解析运行目标:
|
|
307
325
|
* - 显式 transport=ws: 强制走 ws
|
|
@@ -591,7 +609,7 @@ function registerRuntimeTools(server) {
|
|
|
591
609
|
});
|
|
592
610
|
server.registerTool("watch_logs", {
|
|
593
611
|
title: "Watch Logs",
|
|
594
|
-
description: "通过 SSE
|
|
612
|
+
description: "通过 SSE 监听设备实时日志。首次可传 ip,也可复用 set_device 保存的默认设备。",
|
|
595
613
|
inputSchema: {
|
|
596
614
|
workspacePath: z
|
|
597
615
|
.string()
|
|
@@ -631,10 +649,6 @@ function registerRuntimeTools(server) {
|
|
|
631
649
|
await ensureWorkspacePath(workspacePath);
|
|
632
650
|
const device = await (0, device_config_1.resolveDeviceConfig)(ip, port);
|
|
633
651
|
const result = await (0, project_1.watchDeviceLogsBySse)(device.ip, device.port, durationSeconds * 1000, maxLogs);
|
|
634
|
-
const findingsPreview = result.findings
|
|
635
|
-
.slice(0, 20)
|
|
636
|
-
.map((item, index) => `${index + 1}. [${item.severity}] ${item.rule} | ${item.log.timestamp} | ${item.log.message}`)
|
|
637
|
-
.join("\n");
|
|
638
652
|
const logsPreview = result.logs
|
|
639
653
|
.slice(-20)
|
|
640
654
|
.map((log) => `[${log.timestamp}] [${log.level.toUpperCase()}] ${log.message}`)
|
|
@@ -646,10 +660,6 @@ function registerRuntimeTools(server) {
|
|
|
646
660
|
text: [
|
|
647
661
|
`监听目标: ${device.ip}:${device.port}`,
|
|
648
662
|
`监听时长: ${durationSeconds}s,收集日志: ${result.logs.length} 条,runtime_status: ${result.runtimeStatus.length} 条`,
|
|
649
|
-
result.summary,
|
|
650
|
-
"",
|
|
651
|
-
"异常判定(最多展示前20条):",
|
|
652
|
-
findingsPreview || "未命中异常规则",
|
|
653
663
|
"",
|
|
654
664
|
"最新日志(最多展示最后20条):",
|
|
655
665
|
logsPreview || "无日志",
|
|
@@ -737,9 +747,44 @@ function registerRuntimeTools(server) {
|
|
|
737
747
|
.min(1)
|
|
738
748
|
.optional()
|
|
739
749
|
.describe("可选工作目录;不传时使用 set_workspace 记录值或 MCP 启动目录"),
|
|
750
|
+
watchLogs: z
|
|
751
|
+
.boolean()
|
|
752
|
+
.optional()
|
|
753
|
+
.default(true)
|
|
754
|
+
.describe("是否在运行前启动实时日志监听,默认 true"),
|
|
755
|
+
logDurationSeconds: z
|
|
756
|
+
.number()
|
|
757
|
+
.int()
|
|
758
|
+
.min(1)
|
|
759
|
+
.max(300)
|
|
760
|
+
.optional()
|
|
761
|
+
.default(20)
|
|
762
|
+
.describe("日志监听时长(秒),默认 20"),
|
|
763
|
+
logMaxLogs: z
|
|
764
|
+
.number()
|
|
765
|
+
.int()
|
|
766
|
+
.min(10)
|
|
767
|
+
.max(5000)
|
|
768
|
+
.optional()
|
|
769
|
+
.default(300)
|
|
770
|
+
.describe("日志最大收集条数,默认 300"),
|
|
740
771
|
},
|
|
741
|
-
}, async ({ transport, ip, port, wsPort, wsWaitMs, workspacePath }) => {
|
|
772
|
+
}, async ({ transport, ip, port, wsPort, wsWaitMs, workspacePath, watchLogs, logDurationSeconds, logMaxLogs, }) => {
|
|
742
773
|
const workspace = await ensureWorkspacePath(workspacePath);
|
|
774
|
+
let logTask;
|
|
775
|
+
let logTargetText = "";
|
|
776
|
+
let logSetupWarning = "";
|
|
777
|
+
if (watchLogs) {
|
|
778
|
+
try {
|
|
779
|
+
const logDevice = await (0, device_config_1.resolveDeviceConfig)(ip, port);
|
|
780
|
+
logTargetText = `${logDevice.ip}:${logDevice.port}`;
|
|
781
|
+
// 先启动日志监听,再执行 run,确保不会错过启动期日志
|
|
782
|
+
logTask = (0, project_1.watchDeviceLogsBySse)(logDevice.ip, logDevice.port, logDurationSeconds * 1000, logMaxLogs);
|
|
783
|
+
}
|
|
784
|
+
catch (error) {
|
|
785
|
+
logSetupWarning = `日志监听未启动: ${error instanceof Error ? error.message : String(error)}`;
|
|
786
|
+
}
|
|
787
|
+
}
|
|
743
788
|
const target = await resolvePreferredRuntimeTarget({
|
|
744
789
|
transport,
|
|
745
790
|
ip,
|
|
@@ -760,11 +805,16 @@ function registerRuntimeTools(server) {
|
|
|
760
805
|
transport: "http",
|
|
761
806
|
workspacePath: workspace,
|
|
762
807
|
});
|
|
808
|
+
const logSection = logTask
|
|
809
|
+
? `\n\n运行前日志监听目标: ${logTargetText}\n${formatWatchLogsResult(await logTask)}`
|
|
810
|
+
: logSetupWarning
|
|
811
|
+
? `\n\n${logSetupWarning}`
|
|
812
|
+
: "";
|
|
763
813
|
return {
|
|
764
814
|
content: [
|
|
765
815
|
{
|
|
766
816
|
type: "text",
|
|
767
|
-
text: `运行请求已发送到 ${target.label}`,
|
|
817
|
+
text: `运行请求已发送到 ${target.label}${logSection}`,
|
|
768
818
|
},
|
|
769
819
|
],
|
|
770
820
|
};
|
|
@@ -808,9 +858,44 @@ function registerRuntimeTools(server) {
|
|
|
808
858
|
.min(1)
|
|
809
859
|
.optional()
|
|
810
860
|
.describe("可选工作目录;不传时使用 set_workspace 记录值或 MCP 启动目录"),
|
|
861
|
+
watchLogs: z
|
|
862
|
+
.boolean()
|
|
863
|
+
.optional()
|
|
864
|
+
.default(true)
|
|
865
|
+
.describe("是否在预览前启动实时日志监听,默认 true"),
|
|
866
|
+
logDurationSeconds: z
|
|
867
|
+
.number()
|
|
868
|
+
.int()
|
|
869
|
+
.min(1)
|
|
870
|
+
.max(300)
|
|
871
|
+
.optional()
|
|
872
|
+
.default(20)
|
|
873
|
+
.describe("日志监听时长(秒),默认 20"),
|
|
874
|
+
logMaxLogs: z
|
|
875
|
+
.number()
|
|
876
|
+
.int()
|
|
877
|
+
.min(10)
|
|
878
|
+
.max(5000)
|
|
879
|
+
.optional()
|
|
880
|
+
.default(300)
|
|
881
|
+
.describe("日志最大收集条数,默认 300"),
|
|
811
882
|
},
|
|
812
|
-
}, async ({ transport, ip, port, wsPort, wsWaitMs, workspacePath }) => {
|
|
883
|
+
}, async ({ transport, ip, port, wsPort, wsWaitMs, workspacePath, watchLogs, logDurationSeconds, logMaxLogs, }) => {
|
|
813
884
|
const workspace = await ensureWorkspacePath(workspacePath);
|
|
885
|
+
let logTask;
|
|
886
|
+
let logTargetText = "";
|
|
887
|
+
let logSetupWarning = "";
|
|
888
|
+
if (watchLogs) {
|
|
889
|
+
try {
|
|
890
|
+
const logDevice = await (0, device_config_1.resolveDeviceConfig)(ip, port);
|
|
891
|
+
logTargetText = `${logDevice.ip}:${logDevice.port}`;
|
|
892
|
+
// 先启动日志监听,再执行 run-ui,确保不会错过启动期日志
|
|
893
|
+
logTask = (0, project_1.watchDeviceLogsBySse)(logDevice.ip, logDevice.port, logDurationSeconds * 1000, logMaxLogs);
|
|
894
|
+
}
|
|
895
|
+
catch (error) {
|
|
896
|
+
logSetupWarning = `日志监听未启动: ${error instanceof Error ? error.message : String(error)}`;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
814
899
|
const target = await resolvePreferredRuntimeTarget({
|
|
815
900
|
transport,
|
|
816
901
|
ip,
|
|
@@ -831,11 +916,16 @@ function registerRuntimeTools(server) {
|
|
|
831
916
|
transport: "http",
|
|
832
917
|
workspacePath: workspace,
|
|
833
918
|
});
|
|
919
|
+
const logSection = logTask
|
|
920
|
+
? `\n\n预览前日志监听目标: ${logTargetText}\n${formatWatchLogsResult(await logTask)}`
|
|
921
|
+
: logSetupWarning
|
|
922
|
+
? `\n\n${logSetupWarning}`
|
|
923
|
+
: "";
|
|
834
924
|
return {
|
|
835
925
|
content: [
|
|
836
926
|
{
|
|
837
927
|
type: "text",
|
|
838
|
-
text: `UI 预览请求已发送到 ${target.label}`,
|
|
928
|
+
text: `UI 预览请求已发送到 ${target.label}${logSection}`,
|
|
839
929
|
},
|
|
840
930
|
],
|
|
841
931
|
};
|
package/dist/project.d.ts
CHANGED
|
@@ -29,17 +29,6 @@ export interface DeviceRuntimeStatusEntry {
|
|
|
29
29
|
/** 事件时间戳(本地接收时间) */
|
|
30
30
|
timestamp: string;
|
|
31
31
|
}
|
|
32
|
-
/**
|
|
33
|
-
* 设备日志判定项
|
|
34
|
-
*/
|
|
35
|
-
export interface DeviceLogFinding {
|
|
36
|
-
/** 严重级别 */
|
|
37
|
-
severity: "error" | "warn";
|
|
38
|
-
/** 命中的判定规则 */
|
|
39
|
-
rule: string;
|
|
40
|
-
/** 证据日志 */
|
|
41
|
-
log: DeviceLogEntry;
|
|
42
|
-
}
|
|
43
32
|
/**
|
|
44
33
|
* SSE 日志监听结果
|
|
45
34
|
*/
|
|
@@ -48,10 +37,6 @@ export interface DeviceLogWatchResult {
|
|
|
48
37
|
logs: DeviceLogEntry[];
|
|
49
38
|
/** 收集到的 runtime_status 条目 */
|
|
50
39
|
runtimeStatus: DeviceRuntimeStatusEntry[];
|
|
51
|
-
/** 自动判定结果 */
|
|
52
|
-
findings: DeviceLogFinding[];
|
|
53
|
-
/** 结果摘要 */
|
|
54
|
-
summary: string;
|
|
55
40
|
}
|
|
56
41
|
/**
|
|
57
42
|
* 在设备上获取截图 JPG 二进制数据(HTTP)
|
|
@@ -80,20 +65,12 @@ export declare function getScreenshotBase64OnDevice(options: DeviceCliOptions):
|
|
|
80
65
|
*/
|
|
81
66
|
export declare function getSourceOnDevice(options: DeviceCliOptions, maxDepth?: number, timeout?: number): Promise<string>;
|
|
82
67
|
/**
|
|
83
|
-
*
|
|
84
|
-
* @param logs 待判定日志列表
|
|
85
|
-
* @returns 返回判定命中项
|
|
86
|
-
* @example
|
|
87
|
-
* const findings = analyzeDeviceLogs([{ level: "error", message: "crash", timestamp: "..." }])
|
|
88
|
-
*/
|
|
89
|
-
export declare function analyzeDeviceLogs(logs: DeviceLogEntry[]): DeviceLogFinding[];
|
|
90
|
-
/**
|
|
91
|
-
* 监听设备 SSE 日志并返回自动判定结果
|
|
68
|
+
* 监听设备 SSE 日志并返回原始结果
|
|
92
69
|
* @param ip 设备 IP 地址
|
|
93
70
|
* @param port 设备端口
|
|
94
71
|
* @param durationMs 监听时长(毫秒),默认 15000
|
|
95
72
|
* @param maxLogs 最多收集日志条数,默认 200
|
|
96
|
-
* @returns
|
|
73
|
+
* @returns 返回日志与运行状态
|
|
97
74
|
* @example
|
|
98
75
|
* const result = await watchDeviceLogsBySse("192.168.1.10", 9800, 10000, 100)
|
|
99
76
|
*/
|
package/dist/project.js
CHANGED
|
@@ -39,7 +39,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
39
39
|
exports.getScreenshotOnDevice = getScreenshotOnDevice;
|
|
40
40
|
exports.getScreenshotBase64OnDevice = getScreenshotBase64OnDevice;
|
|
41
41
|
exports.getSourceOnDevice = getSourceOnDevice;
|
|
42
|
-
exports.analyzeDeviceLogs = analyzeDeviceLogs;
|
|
43
42
|
exports.watchDeviceLogsBySse = watchDeviceLogsBySse;
|
|
44
43
|
exports.runOnDevice = runOnDevice;
|
|
45
44
|
exports.runUIOnDevice = runUIOnDevice;
|
|
@@ -511,65 +510,12 @@ function normalizeLogEntry(payload) {
|
|
|
511
510
|
};
|
|
512
511
|
}
|
|
513
512
|
/**
|
|
514
|
-
*
|
|
515
|
-
* @param logs 待判定日志列表
|
|
516
|
-
* @returns 返回判定命中项
|
|
517
|
-
* @example
|
|
518
|
-
* const findings = analyzeDeviceLogs([{ level: "error", message: "crash", timestamp: "..." }])
|
|
519
|
-
*/
|
|
520
|
-
function analyzeDeviceLogs(logs) {
|
|
521
|
-
const findings = [];
|
|
522
|
-
const criticalPatterns = [
|
|
523
|
-
{ rule: "崩溃关键词", regex: /\b(crash|fatal|abort|sigabrt|segfault)\b/i },
|
|
524
|
-
{
|
|
525
|
-
rule: "异常关键词",
|
|
526
|
-
regex: /\b(exception|uncaught|assert|error:|failed|failure)\b/i,
|
|
527
|
-
},
|
|
528
|
-
{
|
|
529
|
-
rule: "内存风险关键词",
|
|
530
|
-
regex: /\b(out of memory|oom|memory leak|allocation failed)\b/i,
|
|
531
|
-
},
|
|
532
|
-
{
|
|
533
|
-
rule: "设备离线关键词",
|
|
534
|
-
regex: /\b(timeout|disconnected|connection reset|network error)\b/i,
|
|
535
|
-
},
|
|
536
|
-
];
|
|
537
|
-
for (const log of logs) {
|
|
538
|
-
const level = log.level.toLowerCase();
|
|
539
|
-
const message = log.message;
|
|
540
|
-
if (level === "error") {
|
|
541
|
-
findings.push({
|
|
542
|
-
severity: "error",
|
|
543
|
-
rule: "error 级别日志",
|
|
544
|
-
log,
|
|
545
|
-
});
|
|
546
|
-
}
|
|
547
|
-
else if (level === "warn") {
|
|
548
|
-
findings.push({
|
|
549
|
-
severity: "warn",
|
|
550
|
-
rule: "warn 级别日志",
|
|
551
|
-
log,
|
|
552
|
-
});
|
|
553
|
-
}
|
|
554
|
-
for (const pattern of criticalPatterns) {
|
|
555
|
-
if (pattern.regex.test(message)) {
|
|
556
|
-
findings.push({
|
|
557
|
-
severity: level === "error" ? "error" : "warn",
|
|
558
|
-
rule: pattern.rule,
|
|
559
|
-
log,
|
|
560
|
-
});
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
return findings;
|
|
565
|
-
}
|
|
566
|
-
/**
|
|
567
|
-
* 监听设备 SSE 日志并返回自动判定结果
|
|
513
|
+
* 监听设备 SSE 日志并返回原始结果
|
|
568
514
|
* @param ip 设备 IP 地址
|
|
569
515
|
* @param port 设备端口
|
|
570
516
|
* @param durationMs 监听时长(毫秒),默认 15000
|
|
571
517
|
* @param maxLogs 最多收集日志条数,默认 200
|
|
572
|
-
* @returns
|
|
518
|
+
* @returns 返回日志与运行状态
|
|
573
519
|
* @example
|
|
574
520
|
* const result = await watchDeviceLogsBySse("192.168.1.10", 9800, 10000, 100)
|
|
575
521
|
*/
|
|
@@ -657,17 +603,9 @@ async function watchDeviceLogsBySse(ip, port, durationMs = 15000, maxLogs = 200)
|
|
|
657
603
|
finally {
|
|
658
604
|
clearTimeout(timeoutHandle);
|
|
659
605
|
}
|
|
660
|
-
const findings = analyzeDeviceLogs(logs);
|
|
661
|
-
const errorCount = findings.filter((item) => item.severity === "error").length;
|
|
662
|
-
const warnCount = findings.filter((item) => item.severity === "warn").length;
|
|
663
|
-
const summary = findings.length === 0
|
|
664
|
-
? `日志监听完成:共 ${logs.length} 条日志,未发现明显异常。`
|
|
665
|
-
: `日志监听完成:共 ${logs.length} 条日志,发现 ${errorCount} 条 error 风险、${warnCount} 条 warn 风险。`;
|
|
666
606
|
return {
|
|
667
607
|
logs,
|
|
668
608
|
runtimeStatus,
|
|
669
|
-
findings,
|
|
670
|
-
summary,
|
|
671
609
|
};
|
|
672
610
|
}
|
|
673
611
|
/**
|