ms-vite-plugin 1.1.7 → 1.1.9

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,29 +303,46 @@ function registerRuntimeTools(server) {
303
303
  return workspace;
304
304
  }
305
305
  /**
306
- * 在后台启动一次日志监听,不阻塞 run/run_ui 调用返回
306
+ * 格式化运行期日志结果(供 run/run_ui 直接回传)
307
307
  * @param ip 设备 IP
308
308
  * @param port 设备端口
309
309
  * @param durationSeconds 监听秒数
310
- * @param maxLogs 最大日志条数
311
- * @returns 返回监听目标说明文本
310
+ * @param result 日志监听结果
311
+ * @returns 可拼接到 tool 响应的文本
312
312
  * @example
313
- * const tip = startBackgroundLogWatch("192.168.1.10", 9800, 20, 300)
313
+ * const text = formatRunLogSection("192.168.1.10", 9800, 10, result)
314
314
  */
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)
315
+ function formatRunLogSection(ip, port, result) {
316
+ const logsPreview = result.logs
317
+ .slice(-20)
318
+ .map((log) => `[${log.timestamp}] [${log.level.toUpperCase()}] ${log.message}`)
319
+ .join("\n");
320
+ return [
321
+ `运行日志来源: ${ip}:${port}`,
322
+ `结束原因: ${result.stopReason},日志: ${result.logs.length} 条,runtime_status: ${result.runtimeStatus.length} 条`,
323
+ "最新日志(最多展示最后20条):",
324
+ logsPreview || "无日志",
325
+ ].join("\n");
326
+ }
327
+ /**
328
+ * 启动持续日志监听(后台,不阻塞当前 tool 返回)
329
+ * @param ip 设备 IP
330
+ * @param port 设备端口
331
+ * @param maxLogs 日志环形缓冲上限
332
+ * @returns 返回提示文本
333
+ * @example
334
+ * const tip = startBackgroundContinuousLogWatch("192.168.1.10", 9800, 300)
335
+ */
336
+ function startBackgroundContinuousLogWatch(ip, port, maxLogs) {
337
+ void (0, project_1.watchDeviceLogsBySse)(ip, port, 0, maxLogs)
318
338
  .then((result) => {
319
- console.log(`[mcp] background logs ${ip}:${port} done, reason=${result.stopReason}, logs=${result.logs.length}, runtime_status=${result.runtimeStatus.length}`);
339
+ console.log(`[mcp] continuous logs ${ip}:${port} ended, reason=${result.stopReason}, logs=${result.logs.length}, runtime_status=${result.runtimeStatus.length}`);
320
340
  })
321
341
  .catch((error) => {
322
342
  const message = error instanceof Error ? error.message : String(error);
323
- console.warn(`[mcp] background logs ${ip}:${port} failed: ${message}`);
343
+ console.warn(`[mcp] continuous logs ${ip}:${port} failed: ${message}`);
324
344
  });
325
- if (durationSeconds === 0) {
326
- return `已在后台启动持续日志监听: ${ip}:${port}(直到连接断开,max ${maxLogs})`;
327
- }
328
- return `已在后台启动日志监听: ${ip}:${port}(${durationSeconds}s,max ${maxLogs})`;
345
+ return `已切换为持续日志监听: ${ip}:${port}(直到连接断开,max ${maxLogs})`;
329
346
  }
330
347
  /**
331
348
  * 解析运行目标:
@@ -758,16 +775,13 @@ function registerRuntimeTools(server) {
758
775
  watchLogs: z
759
776
  .boolean()
760
777
  .optional()
761
- .default(true)
762
- .describe("是否在运行前启动实时日志监听,默认 true"),
763
- logDurationSeconds: z
764
- .number()
765
- .int()
766
- .min(0)
767
- .max(300)
778
+ .default(false)
779
+ .describe("是否在运行前启动日志监听,默认 false"),
780
+ logMode: z
781
+ .enum(["single", "continuous"])
768
782
  .optional()
769
- .default(0)
770
- .describe("日志监听时长(秒),默认 0;0 表示持续监听直到 runtime_status 失败或连接断开"),
783
+ .default("single")
784
+ .describe("日志模式:single=按 runtime_status 收敛,continuous=持续监听"),
771
785
  logMaxLogs: z
772
786
  .number()
773
787
  .int()
@@ -777,15 +791,25 @@ function registerRuntimeTools(server) {
777
791
  .default(300)
778
792
  .describe("日志最大收集条数,默认 300"),
779
793
  },
780
- }, async ({ transport, ip, port, wsPort, wsWaitMs, workspacePath, watchLogs, logDurationSeconds, logMaxLogs, }) => {
794
+ }, async ({ transport, ip, port, wsPort, wsWaitMs, workspacePath, watchLogs, logMode, logMaxLogs, }) => {
781
795
  const workspace = await ensureWorkspacePath(workspacePath);
782
- let logNotice = "";
796
+ let logPromise;
797
+ let logDeviceIp = "";
798
+ let logDevicePort = 0;
783
799
  let logSetupWarning = "";
800
+ let logModeNotice = "";
784
801
  if (watchLogs) {
785
802
  try {
786
803
  const logDevice = await (0, device_config_1.resolveDeviceConfig)(ip, port);
787
- // 先启动日志监听,再执行 run,且不等待日志结束,避免 run 被阻塞
788
- logNotice = startBackgroundLogWatch(logDevice.ip, logDevice.port, logDurationSeconds, logMaxLogs);
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);
812
+ }
789
813
  }
790
814
  catch (error) {
791
815
  logSetupWarning = `日志监听未启动: ${error instanceof Error ? error.message : String(error)}`;
@@ -811,11 +835,17 @@ function registerRuntimeTools(server) {
811
835
  transport: "http",
812
836
  workspacePath: workspace,
813
837
  });
814
- const logSection = logNotice
815
- ? `\n\n${logNotice}`
816
- : logSetupWarning
817
- ? `\n\n${logSetupWarning}`
818
- : "";
838
+ let logSection = "";
839
+ if (logPromise) {
840
+ const result = await logPromise;
841
+ logSection = `\n\n${formatRunLogSection(logDeviceIp, logDevicePort, result)}`;
842
+ }
843
+ else if (logModeNotice) {
844
+ logSection = `\n\n${logModeNotice}`;
845
+ }
846
+ else if (logSetupWarning) {
847
+ logSection = `\n\n${logSetupWarning}`;
848
+ }
819
849
  return {
820
850
  content: [
821
851
  {
@@ -864,42 +894,9 @@ function registerRuntimeTools(server) {
864
894
  .min(1)
865
895
  .optional()
866
896
  .describe("可选工作目录;不传时使用 set_workspace 记录值或 MCP 启动目录"),
867
- watchLogs: z
868
- .boolean()
869
- .optional()
870
- .default(true)
871
- .describe("是否在预览前启动实时日志监听,默认 true"),
872
- logDurationSeconds: z
873
- .number()
874
- .int()
875
- .min(0)
876
- .max(300)
877
- .optional()
878
- .default(0)
879
- .describe("日志监听时长(秒),默认 0;0 表示持续监听直到 runtime_status 失败或连接断开"),
880
- logMaxLogs: z
881
- .number()
882
- .int()
883
- .min(10)
884
- .max(5000)
885
- .optional()
886
- .default(300)
887
- .describe("日志最大收集条数,默认 300"),
888
897
  },
889
- }, async ({ transport, ip, port, wsPort, wsWaitMs, workspacePath, watchLogs, logDurationSeconds, logMaxLogs, }) => {
898
+ }, async ({ transport, ip, port, wsPort, wsWaitMs, workspacePath }) => {
890
899
  const workspace = await ensureWorkspacePath(workspacePath);
891
- let logNotice = "";
892
- let logSetupWarning = "";
893
- if (watchLogs) {
894
- try {
895
- const logDevice = await (0, device_config_1.resolveDeviceConfig)(ip, port);
896
- // 先启动日志监听,再执行 run-ui,且不等待日志结束,避免 run-ui 被阻塞
897
- logNotice = startBackgroundLogWatch(logDevice.ip, logDevice.port, logDurationSeconds, logMaxLogs);
898
- }
899
- catch (error) {
900
- logSetupWarning = `日志监听未启动: ${error instanceof Error ? error.message : String(error)}`;
901
- }
902
- }
903
900
  const target = await resolvePreferredRuntimeTarget({
904
901
  transport,
905
902
  ip,
@@ -920,16 +917,11 @@ function registerRuntimeTools(server) {
920
917
  transport: "http",
921
918
  workspacePath: workspace,
922
919
  });
923
- const logSection = logNotice
924
- ? `\n\n${logNotice}`
925
- : logSetupWarning
926
- ? `\n\n${logSetupWarning}`
927
- : "";
928
920
  return {
929
921
  content: [
930
922
  {
931
923
  type: "text",
932
- text: `UI 预览请求已发送到 ${target.label}${logSection}`,
924
+ text: `UI 预览请求已发送到 ${target.label}`,
933
925
  },
934
926
  ],
935
927
  };
package/dist/project.d.ts CHANGED
@@ -38,7 +38,7 @@ export interface DeviceLogWatchResult {
38
38
  /** 收集到的 runtime_status 条目 */
39
39
  runtimeStatus: DeviceRuntimeStatusEntry[];
40
40
  /** 监听结束原因 */
41
- stopReason: "timeout" | "stream_closed" | "manual_abort" | "unknown";
41
+ stopReason: "timeout" | "runtime_stopped" | "stream_closed" | "manual_abort" | "unknown";
42
42
  }
43
43
  /**
44
44
  * 在设备上获取截图 JPG 二进制数据(HTTP)
@@ -72,11 +72,12 @@ export declare function getSourceOnDevice(options: DeviceCliOptions, maxDepth?:
72
72
  * @param port 设备端口
73
73
  * @param durationMs 监听时长(毫秒),默认 15000;传 0 表示不设超时,持续监听
74
74
  * @param maxLogs 最多收集日志条数,默认 200
75
+ * @param stopOnRuntimeStopped 若为 true,则在运行状态从 true 回落到 false 后结束监听
75
76
  * @returns 返回日志与运行状态
76
77
  * @example
77
- * const result = await watchDeviceLogsBySse("192.168.1.10", 9800, 0, 300)
78
+ * const result = await watchDeviceLogsBySse("192.168.1.10", 9800, 30000, 300, true)
78
79
  */
79
- export declare function watchDeviceLogsBySse(ip: string, port: number, durationMs?: number, maxLogs?: number): Promise<DeviceLogWatchResult>;
80
+ export declare function watchDeviceLogsBySse(ip: string, port: number, durationMs?: number, maxLogs?: number, stopOnRuntimeStopped?: boolean): Promise<DeviceLogWatchResult>;
80
81
  /**
81
82
  * 在设备上运行项目(先同步后运行)
82
83
  * @param options 命令选项
package/dist/project.js CHANGED
@@ -515,11 +515,12 @@ function normalizeLogEntry(payload) {
515
515
  * @param port 设备端口
516
516
  * @param durationMs 监听时长(毫秒),默认 15000;传 0 表示不设超时,持续监听
517
517
  * @param maxLogs 最多收集日志条数,默认 200
518
+ * @param stopOnRuntimeStopped 若为 true,则在运行状态从 true 回落到 false 后结束监听
518
519
  * @returns 返回日志与运行状态
519
520
  * @example
520
- * const result = await watchDeviceLogsBySse("192.168.1.10", 9800, 0, 300)
521
+ * const result = await watchDeviceLogsBySse("192.168.1.10", 9800, 30000, 300, true)
521
522
  */
522
- async function watchDeviceLogsBySse(ip, port, durationMs = 15000, maxLogs = 200) {
523
+ async function watchDeviceLogsBySse(ip, port, durationMs = 15000, maxLogs = 200, stopOnRuntimeStopped = false) {
523
524
  if (!ip.trim()) {
524
525
  throw new Error("监听日志失败: 设备 IP 不能为空");
525
526
  }
@@ -537,6 +538,7 @@ async function watchDeviceLogsBySse(ip, port, durationMs = 15000, maxLogs = 200)
537
538
  const runtimeStatus = [];
538
539
  const controller = new AbortController();
539
540
  let stopReason = "unknown";
541
+ let seenRunningStatus = false;
540
542
  const timeoutHandle = durationMs > 0
541
543
  ? setTimeout(() => {
542
544
  stopReason = "timeout";
@@ -590,6 +592,16 @@ async function watchDeviceLogsBySse(ip, port, durationMs = 15000, maxLogs = 200)
590
592
  raw: parsed,
591
593
  timestamp: new Date().toISOString(),
592
594
  });
595
+ if (parsed.isRunning === true) {
596
+ seenRunningStatus = true;
597
+ }
598
+ if (stopOnRuntimeStopped &&
599
+ seenRunningStatus &&
600
+ parsed.isRunning === false) {
601
+ stopReason = "runtime_stopped";
602
+ controller.abort();
603
+ break;
604
+ }
593
605
  }
594
606
  }
595
607
  catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ms-vite-plugin",
3
- "version": "1.1.7",
3
+ "version": "1.1.9",
4
4
  "type": "commonjs",
5
5
  "license": "MIT",
6
6
  "publishConfig": {