ms-vite-plugin 1.1.6 → 1.1.7

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
@@ -303,22 +303,29 @@ function registerRuntimeTools(server) {
303
303
  return workspace;
304
304
  }
305
305
  /**
306
- * 格式化日志监听结果,供 run/run_ui 结果文本复用
307
- * @param result 日志监听结果
308
- * @returns 返回可直接拼接到 tool 响应中的文本
306
+ * 在后台启动一次日志监听,不阻塞 run/run_ui 调用返回
307
+ * @param ip 设备 IP
308
+ * @param port 设备端口
309
+ * @param durationSeconds 监听秒数
310
+ * @param maxLogs 最大日志条数
311
+ * @returns 返回监听目标说明文本
309
312
  * @example
310
- * const text = formatWatchLogsResult(result)
313
+ * const tip = startBackgroundLogWatch("192.168.1.10", 9800, 20, 300)
311
314
  */
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");
315
+ function startBackgroundLogWatch(ip, port, durationSeconds, maxLogs) {
316
+ const durationMs = durationSeconds > 0 ? durationSeconds * 1000 : 0;
317
+ void (0, project_1.watchDeviceLogsBySse)(ip, port, durationMs, maxLogs)
318
+ .then((result) => {
319
+ console.log(`[mcp] background logs ${ip}:${port} done, reason=${result.stopReason}, logs=${result.logs.length}, runtime_status=${result.runtimeStatus.length}`);
320
+ })
321
+ .catch((error) => {
322
+ const message = error instanceof Error ? error.message : String(error);
323
+ console.warn(`[mcp] background logs ${ip}:${port} failed: ${message}`);
324
+ });
325
+ if (durationSeconds === 0) {
326
+ return `已在后台启动持续日志监听: ${ip}:${port}(直到连接断开,max ${maxLogs})`;
327
+ }
328
+ return `已在后台启动日志监听: ${ip}:${port}(${durationSeconds}s,max ${maxLogs})`;
322
329
  }
323
330
  /**
324
331
  * 解析运行目标:
@@ -631,11 +638,11 @@ function registerRuntimeTools(server) {
631
638
  durationSeconds: z
632
639
  .number()
633
640
  .int()
634
- .min(1)
641
+ .min(0)
635
642
  .max(300)
636
643
  .optional()
637
644
  .default(15)
638
- .describe("监听时长(秒),默认 15 秒,最大 300 "),
645
+ .describe("监听时长(秒),默认 15 秒;传 0 表示持续监听直到连接断开"),
639
646
  maxLogs: z
640
647
  .number()
641
648
  .int()
@@ -659,7 +666,8 @@ function registerRuntimeTools(server) {
659
666
  type: "text",
660
667
  text: [
661
668
  `监听目标: ${device.ip}:${device.port}`,
662
- `监听时长: ${durationSeconds}s,收集日志: ${result.logs.length} 条,runtime_status: ${result.runtimeStatus.length} 条`,
669
+ `监听模式: ${durationSeconds === 0 ? "持续直到连接断开" : `${durationSeconds}s`}`,
670
+ `结束原因: ${result.stopReason},收集日志: ${result.logs.length} 条,runtime_status: ${result.runtimeStatus.length} 条`,
663
671
  "",
664
672
  "最新日志(最多展示最后20条):",
665
673
  logsPreview || "无日志",
@@ -755,11 +763,11 @@ function registerRuntimeTools(server) {
755
763
  logDurationSeconds: z
756
764
  .number()
757
765
  .int()
758
- .min(1)
766
+ .min(0)
759
767
  .max(300)
760
768
  .optional()
761
- .default(20)
762
- .describe("日志监听时长(秒),默认 20"),
769
+ .default(0)
770
+ .describe("日志监听时长(秒),默认 0;0 表示持续监听直到 runtime_status 失败或连接断开"),
763
771
  logMaxLogs: z
764
772
  .number()
765
773
  .int()
@@ -771,15 +779,13 @@ function registerRuntimeTools(server) {
771
779
  },
772
780
  }, async ({ transport, ip, port, wsPort, wsWaitMs, workspacePath, watchLogs, logDurationSeconds, logMaxLogs, }) => {
773
781
  const workspace = await ensureWorkspacePath(workspacePath);
774
- let logTask;
775
- let logTargetText = "";
782
+ let logNotice = "";
776
783
  let logSetupWarning = "";
777
784
  if (watchLogs) {
778
785
  try {
779
786
  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);
787
+ // 先启动日志监听,再执行 run,且不等待日志结束,避免 run 被阻塞
788
+ logNotice = startBackgroundLogWatch(logDevice.ip, logDevice.port, logDurationSeconds, logMaxLogs);
783
789
  }
784
790
  catch (error) {
785
791
  logSetupWarning = `日志监听未启动: ${error instanceof Error ? error.message : String(error)}`;
@@ -805,8 +811,8 @@ function registerRuntimeTools(server) {
805
811
  transport: "http",
806
812
  workspacePath: workspace,
807
813
  });
808
- const logSection = logTask
809
- ? `\n\n运行前日志监听目标: ${logTargetText}\n${formatWatchLogsResult(await logTask)}`
814
+ const logSection = logNotice
815
+ ? `\n\n${logNotice}`
810
816
  : logSetupWarning
811
817
  ? `\n\n${logSetupWarning}`
812
818
  : "";
@@ -866,11 +872,11 @@ function registerRuntimeTools(server) {
866
872
  logDurationSeconds: z
867
873
  .number()
868
874
  .int()
869
- .min(1)
875
+ .min(0)
870
876
  .max(300)
871
877
  .optional()
872
- .default(20)
873
- .describe("日志监听时长(秒),默认 20"),
878
+ .default(0)
879
+ .describe("日志监听时长(秒),默认 0;0 表示持续监听直到 runtime_status 失败或连接断开"),
874
880
  logMaxLogs: z
875
881
  .number()
876
882
  .int()
@@ -882,15 +888,13 @@ function registerRuntimeTools(server) {
882
888
  },
883
889
  }, async ({ transport, ip, port, wsPort, wsWaitMs, workspacePath, watchLogs, logDurationSeconds, logMaxLogs, }) => {
884
890
  const workspace = await ensureWorkspacePath(workspacePath);
885
- let logTask;
886
- let logTargetText = "";
891
+ let logNotice = "";
887
892
  let logSetupWarning = "";
888
893
  if (watchLogs) {
889
894
  try {
890
895
  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);
896
+ // 先启动日志监听,再执行 run-ui,且不等待日志结束,避免 run-ui 被阻塞
897
+ logNotice = startBackgroundLogWatch(logDevice.ip, logDevice.port, logDurationSeconds, logMaxLogs);
894
898
  }
895
899
  catch (error) {
896
900
  logSetupWarning = `日志监听未启动: ${error instanceof Error ? error.message : String(error)}`;
@@ -916,8 +920,8 @@ function registerRuntimeTools(server) {
916
920
  transport: "http",
917
921
  workspacePath: workspace,
918
922
  });
919
- const logSection = logTask
920
- ? `\n\n预览前日志监听目标: ${logTargetText}\n${formatWatchLogsResult(await logTask)}`
923
+ const logSection = logNotice
924
+ ? `\n\n${logNotice}`
921
925
  : logSetupWarning
922
926
  ? `\n\n${logSetupWarning}`
923
927
  : "";
package/dist/project.d.ts CHANGED
@@ -37,6 +37,8 @@ export interface DeviceLogWatchResult {
37
37
  logs: DeviceLogEntry[];
38
38
  /** 收集到的 runtime_status 条目 */
39
39
  runtimeStatus: DeviceRuntimeStatusEntry[];
40
+ /** 监听结束原因 */
41
+ stopReason: "timeout" | "stream_closed" | "manual_abort" | "unknown";
40
42
  }
41
43
  /**
42
44
  * 在设备上获取截图 JPG 二进制数据(HTTP)
@@ -68,11 +70,11 @@ export declare function getSourceOnDevice(options: DeviceCliOptions, maxDepth?:
68
70
  * 监听设备 SSE 日志并返回原始结果
69
71
  * @param ip 设备 IP 地址
70
72
  * @param port 设备端口
71
- * @param durationMs 监听时长(毫秒),默认 15000
73
+ * @param durationMs 监听时长(毫秒),默认 15000;传 0 表示不设超时,持续监听
72
74
  * @param maxLogs 最多收集日志条数,默认 200
73
75
  * @returns 返回日志与运行状态
74
76
  * @example
75
- * const result = await watchDeviceLogsBySse("192.168.1.10", 9800, 10000, 100)
77
+ * const result = await watchDeviceLogsBySse("192.168.1.10", 9800, 0, 300)
76
78
  */
77
79
  export declare function watchDeviceLogsBySse(ip: string, port: number, durationMs?: number, maxLogs?: number): Promise<DeviceLogWatchResult>;
78
80
  /**
package/dist/project.js CHANGED
@@ -513,11 +513,11 @@ function normalizeLogEntry(payload) {
513
513
  * 监听设备 SSE 日志并返回原始结果
514
514
  * @param ip 设备 IP 地址
515
515
  * @param port 设备端口
516
- * @param durationMs 监听时长(毫秒),默认 15000
516
+ * @param durationMs 监听时长(毫秒),默认 15000;传 0 表示不设超时,持续监听
517
517
  * @param maxLogs 最多收集日志条数,默认 200
518
518
  * @returns 返回日志与运行状态
519
519
  * @example
520
- * const result = await watchDeviceLogsBySse("192.168.1.10", 9800, 10000, 100)
520
+ * const result = await watchDeviceLogsBySse("192.168.1.10", 9800, 0, 300)
521
521
  */
522
522
  async function watchDeviceLogsBySse(ip, port, durationMs = 15000, maxLogs = 200) {
523
523
  if (!ip.trim()) {
@@ -526,7 +526,7 @@ async function watchDeviceLogsBySse(ip, port, durationMs = 15000, maxLogs = 200)
526
526
  if (!Number.isInteger(port) || port < 1 || port > 65535) {
527
527
  throw new Error(`监听日志失败: 无效端口 ${port}`);
528
528
  }
529
- if (!Number.isInteger(durationMs) || durationMs < 1000) {
529
+ if (!Number.isInteger(durationMs) || durationMs < 0) {
530
530
  throw new Error(`监听日志失败: 无效 durationMs ${durationMs}`);
531
531
  }
532
532
  if (!Number.isInteger(maxLogs) || maxLogs < 1) {
@@ -536,9 +536,13 @@ async function watchDeviceLogsBySse(ip, port, durationMs = 15000, maxLogs = 200)
536
536
  const logs = [];
537
537
  const runtimeStatus = [];
538
538
  const controller = new AbortController();
539
- const timeoutHandle = setTimeout(() => {
540
- controller.abort();
541
- }, durationMs);
539
+ let stopReason = "unknown";
540
+ const timeoutHandle = durationMs > 0
541
+ ? setTimeout(() => {
542
+ stopReason = "timeout";
543
+ controller.abort();
544
+ }, durationMs)
545
+ : undefined;
542
546
  try {
543
547
  const response = await fetch(url, {
544
548
  method: "GET",
@@ -556,6 +560,9 @@ async function watchDeviceLogsBySse(ip, port, durationMs = 15000, maxLogs = 200)
556
560
  while (true) {
557
561
  const { value, done } = await reader.read();
558
562
  if (done) {
563
+ if (stopReason === "unknown") {
564
+ stopReason = "stream_closed";
565
+ }
559
566
  break;
560
567
  }
561
568
  buffer += decoder.decode(value, { stream: true });
@@ -569,11 +576,16 @@ async function watchDeviceLogsBySse(ip, port, durationMs = 15000, maxLogs = 200)
569
576
  try {
570
577
  const parsed = JSON.parse(event.data);
571
578
  if (event.event === "log") {
572
- if (logs.length < maxLogs) {
573
- logs.push(normalizeLogEntry(parsed));
579
+ // 日志缓冲使用环形窗口,持续监听时不会无限增长
580
+ if (logs.length >= maxLogs) {
581
+ logs.shift();
574
582
  }
583
+ logs.push(normalizeLogEntry(parsed));
575
584
  }
576
585
  else if (event.event === "runtime_status") {
586
+ if (runtimeStatus.length >= maxLogs) {
587
+ runtimeStatus.shift();
588
+ }
577
589
  runtimeStatus.push({
578
590
  raw: parsed,
579
591
  timestamp: new Date().toISOString(),
@@ -584,10 +596,6 @@ async function watchDeviceLogsBySse(ip, port, durationMs = 15000, maxLogs = 200)
584
596
  // 兼容非 JSON 数据:不抛错,继续监听后续事件
585
597
  }
586
598
  }
587
- if (logs.length >= maxLogs) {
588
- controller.abort();
589
- break;
590
- }
591
599
  splitIndex = buffer.search(/\r?\n\r?\n/);
592
600
  }
593
601
  }
@@ -599,13 +607,19 @@ async function watchDeviceLogsBySse(ip, port, durationMs = 15000, maxLogs = 200)
599
607
  error.message === "The operation was aborted."))) {
600
608
  throw error;
601
609
  }
610
+ if (stopReason === "unknown") {
611
+ stopReason = "manual_abort";
612
+ }
602
613
  }
603
614
  finally {
604
- clearTimeout(timeoutHandle);
615
+ if (timeoutHandle) {
616
+ clearTimeout(timeoutHandle);
617
+ }
605
618
  }
606
619
  return {
607
620
  logs,
608
621
  runtimeStatus,
622
+ stopReason,
609
623
  };
610
624
  }
611
625
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ms-vite-plugin",
3
- "version": "1.1.6",
3
+ "version": "1.1.7",
4
4
  "type": "commonjs",
5
5
  "license": "MIT",
6
6
  "publishConfig": {