ms-vite-plugin 1.1.4 → 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
@@ -269,6 +269,57 @@ function registerDocTools(server) {
269
269
  * registerRuntimeTools(server)
270
270
  */
271
271
  function registerRuntimeTools(server) {
272
+ /**
273
+ * MCP 进程内当前工作目录(可通过 set_workspace 修改)
274
+ */
275
+ let currentWorkspacePath;
276
+ /**
277
+ * 解析并记忆工作目录
278
+ * @param workspacePath 可选的工作目录
279
+ * @returns 返回本次生效的绝对路径
280
+ * @example
281
+ * const workspace = resolveWorkspacePath("/Users/demo/project")
282
+ */
283
+ function resolveWorkspacePath(workspacePath) {
284
+ if (workspacePath && workspacePath.trim()) {
285
+ currentWorkspacePath = path.resolve(workspacePath.trim());
286
+ return currentWorkspacePath;
287
+ }
288
+ if (currentWorkspacePath) {
289
+ return currentWorkspacePath;
290
+ }
291
+ return process.cwd();
292
+ }
293
+ /**
294
+ * 校验并返回有效工作目录
295
+ * @param workspacePath 可选工作目录
296
+ * @returns 返回校验通过的绝对路径
297
+ * @example
298
+ * const workspace = await ensureWorkspacePath("/Users/demo/project")
299
+ */
300
+ async function ensureWorkspacePath(workspacePath) {
301
+ const workspace = resolveWorkspacePath(workspacePath);
302
+ await (0, project_2.ensureValidKuaiJSProject)(workspace);
303
+ return workspace;
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
+ }
272
323
  /**
273
324
  * 解析运行目标:
274
325
  * - 显式 transport=ws: 强制走 ws
@@ -306,6 +357,41 @@ function registerRuntimeTools(server) {
306
357
  label: `${device.ip}:${device.port}`,
307
358
  };
308
359
  }
360
+ server.registerTool("set_workspace", {
361
+ title: "Set Workspace",
362
+ description: "设置默认工作目录。后续 build/run/package/watch 等工具会优先使用该目录。",
363
+ inputSchema: {
364
+ workspacePath: z
365
+ .string()
366
+ .min(1)
367
+ .describe("快点JS 项目目录绝对路径(需包含 package.json 与 scripts)"),
368
+ },
369
+ }, async ({ workspacePath }) => {
370
+ const workspace = await ensureWorkspacePath(workspacePath);
371
+ return {
372
+ content: [
373
+ {
374
+ type: "text",
375
+ text: `默认工作目录已设置为: ${workspace}`,
376
+ },
377
+ ],
378
+ };
379
+ });
380
+ server.registerTool("get_workspace", {
381
+ title: "Get Workspace",
382
+ description: "查看当前 MCP 生效的工作目录。",
383
+ inputSchema: {},
384
+ }, async () => {
385
+ const workspace = resolveWorkspacePath();
386
+ return {
387
+ content: [
388
+ {
389
+ type: "text",
390
+ text: `当前工作目录: ${workspace}`,
391
+ },
392
+ ],
393
+ };
394
+ });
309
395
  server.registerTool("set_device", {
310
396
  title: "Set Device",
311
397
  description: "设置默认设备连接信息。首次配置后,后续 run/stop 可不再传 ip。",
@@ -523,8 +609,13 @@ function registerRuntimeTools(server) {
523
609
  });
524
610
  server.registerTool("watch_logs", {
525
611
  title: "Watch Logs",
526
- description: "通过 SSE 监听设备日志并自动判定异常。首次可传 ip,也可复用 set_device 保存的默认设备。",
612
+ description: "通过 SSE 监听设备实时日志。首次可传 ip,也可复用 set_device 保存的默认设备。",
527
613
  inputSchema: {
614
+ workspacePath: z
615
+ .string()
616
+ .min(1)
617
+ .optional()
618
+ .describe("可选工作目录;不传时使用 set_workspace 记录值或 MCP 启动目录"),
528
619
  ip: z
529
620
  .string()
530
621
  .min(1)
@@ -554,14 +645,10 @@ function registerRuntimeTools(server) {
554
645
  .default(200)
555
646
  .describe("最多收集日志条数,默认 200"),
556
647
  },
557
- }, async ({ ip, port, durationSeconds, maxLogs }) => {
558
- await (0, project_2.ensureValidKuaiJSProject)(process.cwd());
648
+ }, async ({ workspacePath, ip, port, durationSeconds, maxLogs }) => {
649
+ await ensureWorkspacePath(workspacePath);
559
650
  const device = await (0, device_config_1.resolveDeviceConfig)(ip, port);
560
651
  const result = await (0, project_1.watchDeviceLogsBySse)(device.ip, device.port, durationSeconds * 1000, maxLogs);
561
- const findingsPreview = result.findings
562
- .slice(0, 20)
563
- .map((item, index) => `${index + 1}. [${item.severity}] ${item.rule} | ${item.log.timestamp} | ${item.log.message}`)
564
- .join("\n");
565
652
  const logsPreview = result.logs
566
653
  .slice(-20)
567
654
  .map((log) => `[${log.timestamp}] [${log.level.toUpperCase()}] ${log.message}`)
@@ -573,10 +660,6 @@ function registerRuntimeTools(server) {
573
660
  text: [
574
661
  `监听目标: ${device.ip}:${device.port}`,
575
662
  `监听时长: ${durationSeconds}s,收集日志: ${result.logs.length} 条,runtime_status: ${result.runtimeStatus.length} 条`,
576
- result.summary,
577
- "",
578
- "异常判定(最多展示前20条):",
579
- findingsPreview || "未命中异常规则",
580
663
  "",
581
664
  "最新日志(最多展示最后20条):",
582
665
  logsPreview || "无日志",
@@ -589,14 +672,19 @@ function registerRuntimeTools(server) {
589
672
  title: "Build Project",
590
673
  description: "构建 KuaiJS 项目,支持开发模式与生产模式。",
591
674
  inputSchema: {
675
+ workspacePath: z
676
+ .string()
677
+ .min(1)
678
+ .optional()
679
+ .describe("可选工作目录;不传时使用 set_workspace 记录值或 MCP 启动目录"),
592
680
  dev: z
593
681
  .boolean()
594
682
  .optional()
595
683
  .describe("是否开发模式构建,true=开发模式,false=生产模式"),
596
684
  },
597
- }, async ({ dev }) => {
598
- await (0, project_2.ensureValidKuaiJSProject)(process.cwd());
599
- await (0, build_1.buildAll)(Boolean(dev), process.cwd());
685
+ }, async ({ workspacePath, dev }) => {
686
+ const workspace = await ensureWorkspacePath(workspacePath);
687
+ await (0, build_1.buildAll)(Boolean(dev), workspace);
600
688
  return {
601
689
  content: [
602
690
  { type: "text", text: `构建完成,模式: ${dev ? "dev" : "prod"}` },
@@ -606,10 +694,16 @@ function registerRuntimeTools(server) {
606
694
  server.registerTool("package_project", {
607
695
  title: "Package Project",
608
696
  description: "执行生产构建并加密,返回 enc.msbundle 路径。",
609
- inputSchema: {},
610
- }, async () => {
611
- await (0, project_2.ensureValidKuaiJSProject)(process.cwd());
612
- const encryptedPath = await (0, packager_1.packageProject)(process.cwd());
697
+ inputSchema: {
698
+ workspacePath: z
699
+ .string()
700
+ .min(1)
701
+ .optional()
702
+ .describe("可选工作目录;不传时使用 set_workspace 记录值或 MCP 启动目录"),
703
+ },
704
+ }, async ({ workspacePath }) => {
705
+ const workspace = await ensureWorkspacePath(workspacePath);
706
+ const encryptedPath = await (0, packager_1.packageProject)(workspace);
613
707
  return {
614
708
  content: [{ type: "text", text: `打包完成: ${encryptedPath}` }],
615
709
  };
@@ -648,9 +742,49 @@ function registerRuntimeTools(server) {
648
742
  .max(600000)
649
743
  .optional()
650
744
  .describe("WS 等待连接超时毫秒(transport=ws 时可选,默认 30000)"),
745
+ workspacePath: z
746
+ .string()
747
+ .min(1)
748
+ .optional()
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"),
651
771
  },
652
- }, async ({ transport, ip, port, wsPort, wsWaitMs }) => {
653
- await (0, project_2.ensureValidKuaiJSProject)(process.cwd());
772
+ }, async ({ transport, ip, port, wsPort, wsWaitMs, workspacePath, watchLogs, logDurationSeconds, logMaxLogs, }) => {
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
+ }
654
788
  const target = await resolvePreferredRuntimeTarget({
655
789
  transport,
656
790
  ip,
@@ -663,17 +797,24 @@ function registerRuntimeTools(server) {
663
797
  transport: "ws",
664
798
  wsPort: target.wsPort,
665
799
  wsWaitMs: target.wsWaitMs,
800
+ workspacePath: workspace,
666
801
  }
667
802
  : {
668
803
  ip: target.ip,
669
804
  port: target.port,
670
805
  transport: "http",
806
+ workspacePath: workspace,
671
807
  });
808
+ const logSection = logTask
809
+ ? `\n\n运行前日志监听目标: ${logTargetText}\n${formatWatchLogsResult(await logTask)}`
810
+ : logSetupWarning
811
+ ? `\n\n${logSetupWarning}`
812
+ : "";
672
813
  return {
673
814
  content: [
674
815
  {
675
816
  type: "text",
676
- text: `运行请求已发送到 ${target.label}`,
817
+ text: `运行请求已发送到 ${target.label}${logSection}`,
677
818
  },
678
819
  ],
679
820
  };
@@ -712,9 +853,49 @@ function registerRuntimeTools(server) {
712
853
  .max(600000)
713
854
  .optional()
714
855
  .describe("WS 等待连接超时毫秒(transport=ws 时可选,默认 30000)"),
856
+ workspacePath: z
857
+ .string()
858
+ .min(1)
859
+ .optional()
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"),
715
882
  },
716
- }, async ({ transport, ip, port, wsPort, wsWaitMs }) => {
717
- await (0, project_2.ensureValidKuaiJSProject)(process.cwd());
883
+ }, async ({ transport, ip, port, wsPort, wsWaitMs, workspacePath, watchLogs, logDurationSeconds, logMaxLogs, }) => {
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
+ }
718
899
  const target = await resolvePreferredRuntimeTarget({
719
900
  transport,
720
901
  ip,
@@ -727,17 +908,24 @@ function registerRuntimeTools(server) {
727
908
  transport: "ws",
728
909
  wsPort: target.wsPort,
729
910
  wsWaitMs: target.wsWaitMs,
911
+ workspacePath: workspace,
730
912
  }
731
913
  : {
732
914
  ip: target.ip,
733
915
  port: target.port,
734
916
  transport: "http",
917
+ workspacePath: workspace,
735
918
  });
919
+ const logSection = logTask
920
+ ? `\n\n预览前日志监听目标: ${logTargetText}\n${formatWatchLogsResult(await logTask)}`
921
+ : logSetupWarning
922
+ ? `\n\n${logSetupWarning}`
923
+ : "";
736
924
  return {
737
925
  content: [
738
926
  {
739
927
  type: "text",
740
- text: `UI 预览请求已发送到 ${target.label}`,
928
+ text: `UI 预览请求已发送到 ${target.label}${logSection}`,
741
929
  },
742
930
  ],
743
931
  };
@@ -776,9 +964,14 @@ function registerRuntimeTools(server) {
776
964
  .max(600000)
777
965
  .optional()
778
966
  .describe("WS 等待连接超时毫秒(transport=ws 时可选,默认 30000)"),
967
+ workspacePath: z
968
+ .string()
969
+ .min(1)
970
+ .optional()
971
+ .describe("可选工作目录;不传时使用 set_workspace 记录值或 MCP 启动目录"),
779
972
  },
780
- }, async ({ transport, ip, port, wsPort, wsWaitMs }) => {
781
- await (0, project_2.ensureValidKuaiJSProject)(process.cwd());
973
+ }, async ({ transport, ip, port, wsPort, wsWaitMs, workspacePath }) => {
974
+ resolveWorkspacePath(workspacePath);
782
975
  const target = await resolvePreferredRuntimeTarget({
783
976
  transport,
784
977
  ip,
package/dist/project.d.ts CHANGED
@@ -7,6 +7,7 @@ export interface DeviceCliOptions {
7
7
  transport?: string;
8
8
  wsPort?: string;
9
9
  wsWaitMs?: string;
10
+ workspacePath?: string;
10
11
  }
11
12
  /**
12
13
  * 设备日志条目
@@ -28,17 +29,6 @@ export interface DeviceRuntimeStatusEntry {
28
29
  /** 事件时间戳(本地接收时间) */
29
30
  timestamp: string;
30
31
  }
31
- /**
32
- * 设备日志判定项
33
- */
34
- export interface DeviceLogFinding {
35
- /** 严重级别 */
36
- severity: "error" | "warn";
37
- /** 命中的判定规则 */
38
- rule: string;
39
- /** 证据日志 */
40
- log: DeviceLogEntry;
41
- }
42
32
  /**
43
33
  * SSE 日志监听结果
44
34
  */
@@ -47,10 +37,6 @@ export interface DeviceLogWatchResult {
47
37
  logs: DeviceLogEntry[];
48
38
  /** 收集到的 runtime_status 条目 */
49
39
  runtimeStatus: DeviceRuntimeStatusEntry[];
50
- /** 自动判定结果 */
51
- findings: DeviceLogFinding[];
52
- /** 结果摘要 */
53
- summary: string;
54
40
  }
55
41
  /**
56
42
  * 在设备上获取截图 JPG 二进制数据(HTTP)
@@ -79,20 +65,12 @@ export declare function getScreenshotBase64OnDevice(options: DeviceCliOptions):
79
65
  */
80
66
  export declare function getSourceOnDevice(options: DeviceCliOptions, maxDepth?: number, timeout?: number): Promise<string>;
81
67
  /**
82
- * 基于关键字与日志级别做自动异常判定
83
- * @param logs 待判定日志列表
84
- * @returns 返回判定命中项
85
- * @example
86
- * const findings = analyzeDeviceLogs([{ level: "error", message: "crash", timestamp: "..." }])
87
- */
88
- export declare function analyzeDeviceLogs(logs: DeviceLogEntry[]): DeviceLogFinding[];
89
- /**
90
- * 监听设备 SSE 日志并返回自动判定结果
68
+ * 监听设备 SSE 日志并返回原始结果
91
69
  * @param ip 设备 IP 地址
92
70
  * @param port 设备端口
93
71
  * @param durationMs 监听时长(毫秒),默认 15000
94
72
  * @param maxLogs 最多收集日志条数,默认 200
95
- * @returns 返回日志、运行状态和判定结果
73
+ * @returns 返回日志与运行状态
96
74
  * @example
97
75
  * const result = await watchDeviceLogsBySse("192.168.1.10", 9800, 10000, 100)
98
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
  /**
@@ -709,7 +647,9 @@ async function ensureWsReady(options) {
709
647
  * await runOnDevice({ ip: "192.168.1.10", port: "9800", path: "./demo" })
710
648
  */
711
649
  async function runOnDevice(options) {
712
- const workspacePath = process.cwd();
650
+ const workspacePath = options.workspacePath
651
+ ? path.resolve(options.workspacePath)
652
+ : process.cwd();
713
653
  const transport = parseTransport(options);
714
654
  console.log(`🔧 开始构建项目: ${workspacePath}`);
715
655
  await runDevBuild(workspacePath);
@@ -737,7 +677,9 @@ async function runOnDevice(options) {
737
677
  * await runUIOnDevice({ ip: "192.168.1.10", port: "9800", path: "./demo" })
738
678
  */
739
679
  async function runUIOnDevice(options) {
740
- const workspacePath = process.cwd();
680
+ const workspacePath = options.workspacePath
681
+ ? path.resolve(options.workspacePath)
682
+ : process.cwd();
741
683
  const transport = parseTransport(options);
742
684
  console.log(`🔧 开始构建项目: ${workspacePath}`);
743
685
  await runDevBuild(workspacePath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ms-vite-plugin",
3
- "version": "1.1.4",
3
+ "version": "1.1.6",
4
4
  "type": "commonjs",
5
5
  "license": "MIT",
6
6
  "publishConfig": {