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 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 监听设备日志并自动判定异常。首次可传 ip,也可复用 set_device 保存的默认设备。",
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
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ms-vite-plugin",
3
- "version": "1.1.5",
3
+ "version": "1.1.6",
4
4
  "type": "commonjs",
5
5
  "license": "MIT",
6
6
  "publishConfig": {