weapp-ide-cli 5.2.10 → 5.3.0
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/README.md +51 -0
- package/dist/{commands-5QkUqOoO.js → automator-session-BZzODsJi.js} +1 -330
- package/dist/{cli-pFop_M4C.js → cli-B45DqpiD.js} +14 -4
- package/dist/cli.js +2 -2
- package/dist/commands-BynZfUJ6.js +333 -0
- package/dist/commands-DG-3Zgd0.js +2 -0
- package/dist/index.d.ts +45 -6
- package/dist/index.js +5 -3
- package/dist/run-mcp-DhujWgfX.js +2 -0
- package/dist/run-mcp-TnooVQe8.js +434 -0
- package/package.json +6 -4
- package/dist/commands-DAN1Yl85.js +0 -2
package/README.md
CHANGED
|
@@ -45,6 +45,57 @@ weapp cache --clean all
|
|
|
45
45
|
|
|
46
46
|
`weapp` 与 `weapp-ide-cli` 等价,选择任一前缀即可。
|
|
47
47
|
|
|
48
|
+
## AI / MCP 直接调用
|
|
49
|
+
|
|
50
|
+
`weapp-ide-cli` 内置 MCP Server,可让支持 MCP 的 AI 客户端直接连接微信开发者工具 automator 会话,进入模拟器执行页面检查、元素定位、点击、输入、截图与基础 E2E 验证。
|
|
51
|
+
|
|
52
|
+
AI 客户端建议使用 stdio 配置:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"mcpServers": {
|
|
57
|
+
"weapp-ide-cli": {
|
|
58
|
+
"command": "weapp",
|
|
59
|
+
"args": [
|
|
60
|
+
"mcp",
|
|
61
|
+
"--workspace-root",
|
|
62
|
+
"<repo-root>"
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
也可以直接启动:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
weapp mcp --workspace-root .
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
启动后 AI 可以直接调用这些工具:
|
|
76
|
+
|
|
77
|
+
| MCP Tool | 说明 |
|
|
78
|
+
| ---------------------------- | -------------------------- |
|
|
79
|
+
| `weapp_devtools_connect` | 连接 DevTools 并读取当前页 |
|
|
80
|
+
| `weapp_devtools_active_page` | 获取当前页、尺寸、data |
|
|
81
|
+
| `weapp_devtools_page_stack` | 获取页面栈 |
|
|
82
|
+
| `weapp_runtime_find_node` | 查询单个元素并返回快照 |
|
|
83
|
+
| `weapp_runtime_find_nodes` | 查询多个元素并返回快照 |
|
|
84
|
+
| `weapp_runtime_tap_node` | 点击元素 |
|
|
85
|
+
| `weapp_runtime_input_node` | 向元素输入文本 |
|
|
86
|
+
| `weapp_devtools_capture` | 截取模拟器当前视口 |
|
|
87
|
+
| `weapp_devtools_host_api` | 调用基础 `wx.*` API |
|
|
88
|
+
|
|
89
|
+
推荐调用顺序:
|
|
90
|
+
|
|
91
|
+
1. `weapp_devtools_connect`
|
|
92
|
+
2. `weapp_devtools_active_page`
|
|
93
|
+
3. `weapp_runtime_find_node` / `weapp_runtime_find_nodes`
|
|
94
|
+
4. `weapp_runtime_tap_node` / `weapp_runtime_input_node`
|
|
95
|
+
5. `weapp_devtools_capture`
|
|
96
|
+
|
|
97
|
+
首次使用前请确保微信开发者工具已登录,并已开启「设置 -> 安全设置 -> 服务端口」。
|
|
98
|
+
|
|
48
99
|
从当前版本开始,`weapp-ide-cli` 会在调用微信开发者工具前自动尝试预热本机 DevTools 配置:
|
|
49
100
|
|
|
50
101
|
- 确保安全设置里启用服务端口
|
|
@@ -9,7 +9,6 @@ import path$1 from "pathe";
|
|
|
9
9
|
import logger, { colors } from "@weapp-core/logger";
|
|
10
10
|
import { createHash } from "node:crypto";
|
|
11
11
|
import { acquireSharedMiniProgram, closeSharedMiniProgram, getSharedMiniProgramSessionCount, releaseSharedMiniProgram, withMiniProgram } from "@weapp-vite/devtools-runtime";
|
|
12
|
-
import { PNG } from "pngjs";
|
|
13
12
|
//#region src/utils/path.ts
|
|
14
13
|
/**
|
|
15
14
|
* @description 解析为绝对路径(基于当前工作目录)
|
|
@@ -820,332 +819,4 @@ async function withMiniProgram$1(options, runner) {
|
|
|
820
819
|
return await withMiniProgram(runtimeHooks, options, runner);
|
|
821
820
|
}
|
|
822
821
|
//#endregion
|
|
823
|
-
|
|
824
|
-
function decodeScreenshotBuffer(raw) {
|
|
825
|
-
const buffer = typeof raw === "string" ? Buffer.from(raw, "base64") : Buffer.from(raw);
|
|
826
|
-
if (buffer.length === 0) throw new Error("Failed to capture screenshot");
|
|
827
|
-
return buffer;
|
|
828
|
-
}
|
|
829
|
-
function toPositiveNumber(value) {
|
|
830
|
-
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
|
|
831
|
-
}
|
|
832
|
-
function createScrollPositions(totalHeight, viewportHeight) {
|
|
833
|
-
if (totalHeight <= viewportHeight) return [0];
|
|
834
|
-
const positions = [];
|
|
835
|
-
const lastStart = Math.max(totalHeight - viewportHeight, 0);
|
|
836
|
-
for (let scrollTop = 0; scrollTop < lastStart; scrollTop += viewportHeight) positions.push(scrollTop);
|
|
837
|
-
if (positions[positions.length - 1] !== lastStart) positions.push(lastStart);
|
|
838
|
-
return positions;
|
|
839
|
-
}
|
|
840
|
-
function cropPngRows(source, startRow, rowCount) {
|
|
841
|
-
const cropped = new PNG({
|
|
842
|
-
width: source.width,
|
|
843
|
-
height: rowCount
|
|
844
|
-
});
|
|
845
|
-
const bytesPerRow = source.width * 4;
|
|
846
|
-
for (let row = 0; row < rowCount; row += 1) {
|
|
847
|
-
const sourceStart = (startRow + row) * bytesPerRow;
|
|
848
|
-
const sourceEnd = sourceStart + bytesPerRow;
|
|
849
|
-
cropped.data.set(source.data.subarray(sourceStart, sourceEnd), row * bytesPerRow);
|
|
850
|
-
}
|
|
851
|
-
return cropped;
|
|
852
|
-
}
|
|
853
|
-
async function restoreScrollPosition(miniProgram, page, scrollTop) {
|
|
854
|
-
await miniProgram.pageScrollTo(scrollTop);
|
|
855
|
-
await page.waitFor(150);
|
|
856
|
-
}
|
|
857
|
-
/**
|
|
858
|
-
* @description 通过多次滚动和拼接生成整页长截图。
|
|
859
|
-
*/
|
|
860
|
-
async function captureFullPageScreenshotBuffer(options) {
|
|
861
|
-
const { miniProgram, timeoutMs, runWithTimeout, screenshotTimeoutMessage } = options;
|
|
862
|
-
const page = await miniProgram.currentPage();
|
|
863
|
-
const pageSize = await page.size();
|
|
864
|
-
const systemInfo = await miniProgram.systemInfo();
|
|
865
|
-
const initialScrollTop = typeof page.scrollTop === "function" ? await page.scrollTop() : 0;
|
|
866
|
-
const pageHeight = toPositiveNumber(pageSize.height);
|
|
867
|
-
const viewportHeight = toPositiveNumber(systemInfo.windowHeight);
|
|
868
|
-
if (!pageHeight || !viewportHeight) return decodeScreenshotBuffer(await runWithTimeout(miniProgram.screenshot(), timeoutMs, screenshotTimeoutMessage, "DEVTOOLS_SCREENSHOT_TIMEOUT"));
|
|
869
|
-
const segments = [];
|
|
870
|
-
const positions = createScrollPositions(pageHeight, viewportHeight);
|
|
871
|
-
let coveredUntil = 0;
|
|
872
|
-
let scale = 1;
|
|
873
|
-
try {
|
|
874
|
-
for (const scrollTop of positions) {
|
|
875
|
-
await miniProgram.pageScrollTo(scrollTop);
|
|
876
|
-
await page.waitFor(150);
|
|
877
|
-
const rawScreenshot = await runWithTimeout(miniProgram.screenshot(), timeoutMs, screenshotTimeoutMessage, "DEVTOOLS_SCREENSHOT_TIMEOUT");
|
|
878
|
-
const png = PNG.sync.read(decodeScreenshotBuffer(rawScreenshot));
|
|
879
|
-
if (viewportHeight > 0) scale = png.height / viewportHeight;
|
|
880
|
-
const visibleEnd = Math.min(scrollTop + viewportHeight, pageHeight);
|
|
881
|
-
const cropTopCss = Math.max(coveredUntil - scrollTop, 0);
|
|
882
|
-
const segmentHeightCss = Math.max(visibleEnd - scrollTop - cropTopCss, 0);
|
|
883
|
-
if (segmentHeightCss <= 0) continue;
|
|
884
|
-
const cropTopRows = Math.min(Math.max(Math.round(cropTopCss * scale), 0), png.height);
|
|
885
|
-
const segmentRows = Math.min(Math.max(Math.round(segmentHeightCss * scale), 1), png.height - cropTopRows);
|
|
886
|
-
segments.push(cropPngRows(png, cropTopRows, segmentRows));
|
|
887
|
-
coveredUntil = visibleEnd;
|
|
888
|
-
}
|
|
889
|
-
} finally {
|
|
890
|
-
await restoreScrollPosition(miniProgram, page, initialScrollTop);
|
|
891
|
-
}
|
|
892
|
-
if (segments.length === 0) throw new Error("Failed to capture screenshot");
|
|
893
|
-
const width = segments[0].width;
|
|
894
|
-
const merged = new PNG({
|
|
895
|
-
width,
|
|
896
|
-
height: segments.reduce((sum, segment) => sum + segment.height, 0)
|
|
897
|
-
});
|
|
898
|
-
const bytesPerRow = width * 4;
|
|
899
|
-
let offsetY = 0;
|
|
900
|
-
for (const segment of segments) {
|
|
901
|
-
if (segment.width !== width) throw new Error("Full-page screenshots have inconsistent widths");
|
|
902
|
-
for (let row = 0; row < segment.height; row += 1) {
|
|
903
|
-
const sourceStart = row * bytesPerRow;
|
|
904
|
-
const sourceEnd = sourceStart + bytesPerRow;
|
|
905
|
-
merged.data.set(segment.data.subarray(sourceStart, sourceEnd), (offsetY + row) * bytesPerRow);
|
|
906
|
-
}
|
|
907
|
-
offsetY += segment.height;
|
|
908
|
-
}
|
|
909
|
-
return PNG.sync.write(merged);
|
|
910
|
-
}
|
|
911
|
-
//#endregion
|
|
912
|
-
//#region src/cli/commands.ts
|
|
913
|
-
function createTimeoutError(message, code) {
|
|
914
|
-
const error = new Error(message);
|
|
915
|
-
error.code = code;
|
|
916
|
-
return error;
|
|
917
|
-
}
|
|
918
|
-
function normalizePagePath(page) {
|
|
919
|
-
return page.startsWith("/") ? page : `/${page}`;
|
|
920
|
-
}
|
|
921
|
-
function sleep(ms) {
|
|
922
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
923
|
-
}
|
|
924
|
-
function withCommandTimeout(task, timeoutMs, message, code) {
|
|
925
|
-
return new Promise((resolve, reject) => {
|
|
926
|
-
const timeout = setTimeout(() => {
|
|
927
|
-
reject(createTimeoutError(message, code));
|
|
928
|
-
}, timeoutMs);
|
|
929
|
-
task.then((value) => {
|
|
930
|
-
clearTimeout(timeout);
|
|
931
|
-
resolve(value);
|
|
932
|
-
}).catch((error) => {
|
|
933
|
-
clearTimeout(timeout);
|
|
934
|
-
reject(error);
|
|
935
|
-
});
|
|
936
|
-
});
|
|
937
|
-
}
|
|
938
|
-
async function runRouteCommand(options, startMessage, successMessage, action) {
|
|
939
|
-
await withMiniProgram$1(options, async (miniProgram) => {
|
|
940
|
-
logger_default.info(startMessage);
|
|
941
|
-
await action(miniProgram);
|
|
942
|
-
logger_default.success(successMessage);
|
|
943
|
-
});
|
|
944
|
-
}
|
|
945
|
-
function toPageSnapshot(page) {
|
|
946
|
-
return {
|
|
947
|
-
path: page.path ?? "",
|
|
948
|
-
query: page.query
|
|
949
|
-
};
|
|
950
|
-
}
|
|
951
|
-
function printStructuredResult(result, json, title) {
|
|
952
|
-
if (json) {
|
|
953
|
-
console.log(JSON.stringify(result, null, 2));
|
|
954
|
-
return;
|
|
955
|
-
}
|
|
956
|
-
logger_default.info(title);
|
|
957
|
-
console.log(JSON.stringify(result, null, 2));
|
|
958
|
-
}
|
|
959
|
-
async function requireElement(page, selector) {
|
|
960
|
-
const element = await page.$(selector);
|
|
961
|
-
if (!element) throw new Error(i18nText(`未找到元素: ${selector}`, `Element not found: ${selector}`));
|
|
962
|
-
return element;
|
|
963
|
-
}
|
|
964
|
-
/**
|
|
965
|
-
* @description 执行保留栈页面跳转。
|
|
966
|
-
*/
|
|
967
|
-
async function navigateTo(options) {
|
|
968
|
-
await runRouteCommand(options, i18nText(`正在跳转到 ${colors.cyan(options.url)}...`, `Navigating to ${colors.cyan(options.url)}...`), i18nText(`已跳转到 ${colors.cyan(options.url)}`, `Navigated to ${colors.cyan(options.url)}`), (miniProgram) => miniProgram.navigateTo(options.url));
|
|
969
|
-
}
|
|
970
|
-
/**
|
|
971
|
-
* @description 执行关闭当前页的重定向。
|
|
972
|
-
*/
|
|
973
|
-
async function redirectTo(options) {
|
|
974
|
-
await runRouteCommand(options, i18nText(`正在重定向到 ${colors.cyan(options.url)}...`, `Redirecting to ${colors.cyan(options.url)}...`), i18nText(`已重定向到 ${colors.cyan(options.url)}`, `Redirected to ${colors.cyan(options.url)}`), (miniProgram) => miniProgram.redirectTo(options.url));
|
|
975
|
-
}
|
|
976
|
-
/**
|
|
977
|
-
* @description 返回上一页。
|
|
978
|
-
*/
|
|
979
|
-
async function navigateBack(options) {
|
|
980
|
-
await runRouteCommand(options, i18nText("正在返回上一页...", "Navigating back..."), i18nText("已返回上一页", "Navigated back"), (miniProgram) => miniProgram.navigateBack());
|
|
981
|
-
}
|
|
982
|
-
/**
|
|
983
|
-
* @description 重启到指定页面。
|
|
984
|
-
*/
|
|
985
|
-
async function reLaunch(options) {
|
|
986
|
-
await runRouteCommand(options, i18nText(`正在重启到 ${colors.cyan(options.url)}...`, `Relaunching to ${colors.cyan(options.url)}...`), i18nText(`已重启到 ${colors.cyan(options.url)}`, `Relaunched to ${colors.cyan(options.url)}`), (miniProgram) => miniProgram.reLaunch(options.url));
|
|
987
|
-
}
|
|
988
|
-
/**
|
|
989
|
-
* @description 切换到 tabBar 页面。
|
|
990
|
-
*/
|
|
991
|
-
async function switchTab(options) {
|
|
992
|
-
await runRouteCommand(options, i18nText(`正在切换 tab 到 ${colors.cyan(options.url)}...`, `Switching tab to ${colors.cyan(options.url)}...`), i18nText(`已切换 tab 到 ${colors.cyan(options.url)}`, `Switched tab to ${colors.cyan(options.url)}`), (miniProgram) => miniProgram.switchTab(options.url));
|
|
993
|
-
}
|
|
994
|
-
/**
|
|
995
|
-
* @description 获取页面栈。
|
|
996
|
-
*/
|
|
997
|
-
async function pageStack(options) {
|
|
998
|
-
return await withMiniProgram$1(options, async (miniProgram) => {
|
|
999
|
-
const result = (await miniProgram.pageStack()).map(toPageSnapshot);
|
|
1000
|
-
printStructuredResult(result, options.json, i18nText("页面栈:", "Page stack:"));
|
|
1001
|
-
return result;
|
|
1002
|
-
});
|
|
1003
|
-
}
|
|
1004
|
-
/**
|
|
1005
|
-
* @description 获取当前页面信息。
|
|
1006
|
-
*/
|
|
1007
|
-
async function currentPage(options) {
|
|
1008
|
-
return await withMiniProgram$1(options, async (miniProgram) => {
|
|
1009
|
-
const result = toPageSnapshot(await miniProgram.currentPage());
|
|
1010
|
-
if (options.json) console.log(JSON.stringify(result, null, 2));
|
|
1011
|
-
else logger_default.info(i18nText(`当前页面: ${result.path}${result.query ? ` ${JSON.stringify(result.query)}` : ""}`, `Current page: ${result.path}${result.query ? ` ${JSON.stringify(result.query)}` : ""}`));
|
|
1012
|
-
return result;
|
|
1013
|
-
});
|
|
1014
|
-
}
|
|
1015
|
-
/**
|
|
1016
|
-
* @description 获取系统信息。
|
|
1017
|
-
*/
|
|
1018
|
-
async function systemInfo(options) {
|
|
1019
|
-
return await withMiniProgram$1(options, async (miniProgram) => {
|
|
1020
|
-
const result = await miniProgram.systemInfo();
|
|
1021
|
-
printStructuredResult(result, options.json, i18nText("系统信息:", "System info:"));
|
|
1022
|
-
return result;
|
|
1023
|
-
});
|
|
1024
|
-
}
|
|
1025
|
-
/**
|
|
1026
|
-
* @description 获取当前页面数据。
|
|
1027
|
-
*/
|
|
1028
|
-
async function pageData(options) {
|
|
1029
|
-
return await withMiniProgram$1(options, async (miniProgram) => {
|
|
1030
|
-
const result = await (await miniProgram.currentPage()).data(options.path);
|
|
1031
|
-
printStructuredResult(result, options.json, i18nText("页面数据:", "Page data:"));
|
|
1032
|
-
return result;
|
|
1033
|
-
});
|
|
1034
|
-
}
|
|
1035
|
-
/**
|
|
1036
|
-
* @description 点击页面元素。
|
|
1037
|
-
*/
|
|
1038
|
-
async function tap(options) {
|
|
1039
|
-
await withMiniProgram$1(options, async (miniProgram) => {
|
|
1040
|
-
logger_default.info(i18nText(`正在点击元素 ${colors.cyan(options.selector)}...`, `Tapping element ${colors.cyan(options.selector)}...`));
|
|
1041
|
-
await (await requireElement(await miniProgram.currentPage(), options.selector)).tap();
|
|
1042
|
-
logger_default.success(i18nText(`已点击元素 ${colors.cyan(options.selector)}`, `Tapped element ${colors.cyan(options.selector)}`));
|
|
1043
|
-
});
|
|
1044
|
-
}
|
|
1045
|
-
/**
|
|
1046
|
-
* @description 向页面元素输入文本。
|
|
1047
|
-
*/
|
|
1048
|
-
async function input(options) {
|
|
1049
|
-
await withMiniProgram$1(options, async (miniProgram) => {
|
|
1050
|
-
logger_default.info(i18nText(`正在向 ${colors.cyan(options.selector)} 输入 "${colors.cyan(options.value)}"...`, `Inputting "${colors.cyan(options.value)}" into ${colors.cyan(options.selector)}...`));
|
|
1051
|
-
const element = await requireElement(await miniProgram.currentPage(), options.selector);
|
|
1052
|
-
if (typeof element.input !== "function") throw new TypeError(i18nText(`元素不支持输入: ${options.selector}`, `Element does not support input: ${options.selector}`));
|
|
1053
|
-
await element.input(options.value);
|
|
1054
|
-
logger_default.success(i18nText(`已向 ${colors.cyan(options.selector)} 输入 "${colors.cyan(options.value)}"`, `Inputted "${colors.cyan(options.value)}" into ${colors.cyan(options.selector)}`));
|
|
1055
|
-
});
|
|
1056
|
-
}
|
|
1057
|
-
/**
|
|
1058
|
-
* @description 滚动页面到指定位置。
|
|
1059
|
-
*/
|
|
1060
|
-
async function scrollTo(options) {
|
|
1061
|
-
await withMiniProgram$1(options, async (miniProgram) => {
|
|
1062
|
-
logger_default.info(i18nText(`正在滚动到位置 ${colors.cyan(String(options.scrollTop))}...`, `Scrolling to position ${colors.cyan(String(options.scrollTop))}...`));
|
|
1063
|
-
await miniProgram.pageScrollTo(options.scrollTop);
|
|
1064
|
-
logger_default.success(i18nText(`已滚动到位置 ${colors.cyan(String(options.scrollTop))}`, `Scrolled to position ${colors.cyan(String(options.scrollTop))}`));
|
|
1065
|
-
});
|
|
1066
|
-
}
|
|
1067
|
-
/**
|
|
1068
|
-
* @description 执行体验评分审计。
|
|
1069
|
-
*/
|
|
1070
|
-
async function audit(options) {
|
|
1071
|
-
return await withMiniProgram$1(options, async (miniProgram) => {
|
|
1072
|
-
logger_default.info(i18nText("正在执行体验审计...", "Running experience audit..."));
|
|
1073
|
-
const result = await miniProgram.stopAudits();
|
|
1074
|
-
if (options.outputPath) {
|
|
1075
|
-
await fs.writeFile(options.outputPath, JSON.stringify(result, null, 2));
|
|
1076
|
-
logger_default.success(i18nText(`审计报告已保存到 ${colors.cyan(options.outputPath)}`, `Audit report saved to ${colors.cyan(options.outputPath)}`));
|
|
1077
|
-
return result;
|
|
1078
|
-
}
|
|
1079
|
-
console.log(JSON.stringify(result, null, 2));
|
|
1080
|
-
return result;
|
|
1081
|
-
});
|
|
1082
|
-
}
|
|
1083
|
-
/**
|
|
1084
|
-
* @description 捕获当前页面截图并返回二进制内容。
|
|
1085
|
-
*/
|
|
1086
|
-
async function captureScreenshotBuffer(options) {
|
|
1087
|
-
return await withMiniProgram$1(options, async (miniProgram) => {
|
|
1088
|
-
const commandTimeout = options.timeout ?? 3e4;
|
|
1089
|
-
const screenshotTimeoutMessage = i18nText(`截图请求在 ${commandTimeout}ms 内未收到 DevTools 回包,请检查当前微信开发者工具是否仍停留在目标项目;若近期执行过其他 e2e / screenshot 任务,关闭多余窗口并清理残留 automator 会话后重试。`, `Screenshot request did not receive a DevTools response within ${commandTimeout}ms. Check that the current Wechat DevTools window is still the target project. If you recently ran other e2e or screenshot tasks, close extra windows and clean up stale automator sessions before retrying.`);
|
|
1090
|
-
if (!options.miniProgram) logger_default.info(i18nText(`正在连接 DevTools:${colors.cyan(options.projectPath)}...`, `Connecting to DevTools at ${colors.cyan(options.projectPath)}...`));
|
|
1091
|
-
if (options.page) {
|
|
1092
|
-
const normalizedPage = normalizePagePath(options.page);
|
|
1093
|
-
logger_default.info(i18nText(`正在跳转页面 ${colors.cyan(normalizedPage)}...`, `Navigating to page ${colors.cyan(normalizedPage)}...`));
|
|
1094
|
-
await miniProgram.reLaunch(normalizedPage);
|
|
1095
|
-
if (options.fullPage) await sleep(1e3);
|
|
1096
|
-
}
|
|
1097
|
-
if (options.fullPage) {
|
|
1098
|
-
logger_default.info(i18nText("正在生成整页长截图...", "Capturing full-page screenshot..."));
|
|
1099
|
-
return await captureFullPageScreenshotBuffer({
|
|
1100
|
-
miniProgram,
|
|
1101
|
-
timeoutMs: commandTimeout,
|
|
1102
|
-
runWithTimeout: withCommandTimeout,
|
|
1103
|
-
screenshotTimeoutMessage
|
|
1104
|
-
});
|
|
1105
|
-
}
|
|
1106
|
-
logger_default.info(i18nText("正在截图...", "Taking screenshot..."));
|
|
1107
|
-
const screenshot = await withCommandTimeout(miniProgram.screenshot(), commandTimeout, screenshotTimeoutMessage, "DEVTOOLS_SCREENSHOT_TIMEOUT");
|
|
1108
|
-
const buffer = typeof screenshot === "string" ? Buffer.from(screenshot, "base64") : Buffer.from(screenshot);
|
|
1109
|
-
if (buffer.length === 0) throw new Error(i18nText("截图失败", "Failed to capture screenshot"));
|
|
1110
|
-
return buffer;
|
|
1111
|
-
});
|
|
1112
|
-
}
|
|
1113
|
-
/**
|
|
1114
|
-
* @description 获取当前小程序截图。
|
|
1115
|
-
*/
|
|
1116
|
-
async function takeScreenshot(options) {
|
|
1117
|
-
let screenshotBuffer;
|
|
1118
|
-
try {
|
|
1119
|
-
screenshotBuffer = await captureScreenshotBuffer(options);
|
|
1120
|
-
} catch (error) {
|
|
1121
|
-
const isProtocolTimeout = error instanceof Error && error.message === "DEVTOOLS_PROTOCOL_TIMEOUT";
|
|
1122
|
-
if (!Boolean(options.sharedSession && !options.miniProgram && isProtocolTimeout)) throw error;
|
|
1123
|
-
await closeSharedMiniProgram(options.projectPath);
|
|
1124
|
-
logger_default.warn(i18nText("当前共享 DevTools 会话截图超时,正在改用全新自动化会话重试一次...", "The current shared DevTools session timed out while capturing screenshot. Retrying once with a fresh automation session..."));
|
|
1125
|
-
screenshotBuffer = await captureScreenshotBuffer({
|
|
1126
|
-
...options,
|
|
1127
|
-
preferOpenedSession: false,
|
|
1128
|
-
sharedSession: false
|
|
1129
|
-
});
|
|
1130
|
-
}
|
|
1131
|
-
const base64 = screenshotBuffer.toString("base64");
|
|
1132
|
-
if (options.outputPath) {
|
|
1133
|
-
await fs.writeFile(options.outputPath, screenshotBuffer);
|
|
1134
|
-
logger_default.success(i18nText(`截图已保存到 ${colors.cyan(options.outputPath)}`, `Screenshot saved to ${colors.cyan(options.outputPath)}`));
|
|
1135
|
-
return { path: options.outputPath };
|
|
1136
|
-
}
|
|
1137
|
-
return { base64 };
|
|
1138
|
-
}
|
|
1139
|
-
/**
|
|
1140
|
-
* @description 开关远程调试。
|
|
1141
|
-
*/
|
|
1142
|
-
async function remote(options) {
|
|
1143
|
-
const enable = options.enable ?? true;
|
|
1144
|
-
await withMiniProgram$1(options, async (miniProgram) => {
|
|
1145
|
-
logger_default.info(enable ? i18nText("正在开启远程调试...", "Enabling remote debugging...") : i18nText("正在关闭远程调试...", "Disabling remote debugging..."));
|
|
1146
|
-
await miniProgram.remote(enable);
|
|
1147
|
-
logger_default.success(enable ? i18nText("远程调试已开启", "Remote debugging enabled") : i18nText("远程调试已关闭", "Remote debugging disabled"));
|
|
1148
|
-
});
|
|
1149
|
-
}
|
|
1150
|
-
//#endregion
|
|
1151
|
-
export { readCustomConfig as $, isAutomatorProtocolTimeoutError as A, getConfiguredLocale as B, configureLocaleFromArgv as C, formatAutomatorLoginError as D, connectOpenedAutomator as E, launchAutomator as F, operatingSystemName as G, SupportedPlatformsMap as H, bootstrapWechatDevtoolsSettings as I, createAutoBootstrapDevtoolsConfig as J, colors as K, detectWechatDevtoolsServicePort as L, isDevtoolsExtensionContextInvalidatedError as M, isDevtoolsHttpPortError as N, getAutomatorProtocolTimeoutMethod as O, isRetryableAutomatorLaunchError as P, overwriteCustomConfig as Q, resolveCliPath as R, withMiniProgram$1 as S, validateLocaleOption as T, getDefaultCliPath as U, resolveDevtoolsAutomationDefaults as V, isOperatingSystemSupported as W, createCustomConfig as X, createAutoTrustProjectConfig as Y, createLocaleConfig as Z, acquireSharedMiniProgram$1 as _, navigateBack as a, getSharedMiniProgramSessionCount as b, pageStack as c, remote as d, removeCustomConfigKey as et, scrollTo as f, tap as g, takeScreenshot as h, input as i, isAutomatorWsConnectError as j, isAutomatorLoginError as k, reLaunch as l, systemInfo as m, captureScreenshotBuffer as n, defaultCustomConfigFilePath as nt, navigateTo as o, switchTab as p, logger_default as q, currentPage as r, resolvePath as rt, pageData as s, audit as t, defaultCustomConfigDirPath as tt, redirectTo as u, closeSharedMiniProgram as v, i18nText as w, releaseSharedMiniProgram as x, connectMiniProgram as y, getConfig as z };
|
|
822
|
+
export { colors as A, defaultCustomConfigFilePath as B, getConfig as C, getDefaultCliPath as D, SupportedPlatformsMap as E, createLocaleConfig as F, overwriteCustomConfig as I, readCustomConfig as L, createAutoBootstrapDevtoolsConfig as M, createAutoTrustProjectConfig as N, isOperatingSystemSupported as O, createCustomConfig as P, removeCustomConfigKey as R, resolveCliPath as S, resolveDevtoolsAutomationDefaults as T, resolvePath as V, isDevtoolsHttpPortError as _, releaseSharedMiniProgram as a, bootstrapWechatDevtoolsSettings as b, i18nText as c, formatAutomatorLoginError as d, getAutomatorProtocolTimeoutMethod as f, isDevtoolsExtensionContextInvalidatedError as g, isAutomatorWsConnectError as h, getSharedMiniProgramSessionCount as i, logger_default as j, operatingSystemName as k, validateLocaleOption as l, isAutomatorProtocolTimeoutError as m, closeSharedMiniProgram as n, withMiniProgram$1 as o, isAutomatorLoginError as p, connectMiniProgram as r, configureLocaleFromArgv as s, acquireSharedMiniProgram$1 as t, connectOpenedAutomator as u, isRetryableAutomatorLaunchError as v, getConfiguredLocale as w, detectWechatDevtoolsServicePort as x, launchAutomator as y, defaultCustomConfigDirPath as z };
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { A as colors, B as defaultCustomConfigFilePath, F as createLocaleConfig, I as overwriteCustomConfig, L as readCustomConfig, M as createAutoBootstrapDevtoolsConfig, N as createAutoTrustProjectConfig, O as isOperatingSystemSupported, P as createCustomConfig, R as removeCustomConfigKey, S as resolveCliPath, T as resolveDevtoolsAutomationDefaults, V as resolvePath, b as bootstrapWechatDevtoolsSettings, c as i18nText, j as logger_default, k as operatingSystemName, l as validateLocaleOption, o as withMiniProgram, r as connectMiniProgram, s as configureLocaleFromArgv, w as getConfiguredLocale, x as detectWechatDevtoolsServicePort } from "./automator-session-BZzODsJi.js";
|
|
2
|
+
import { a as navigateBack, c as pageStack, d as remote, f as scrollTo, g as tap, i as input, l as reLaunch, m as systemInfo, n as captureScreenshotBuffer, o as navigateTo, p as switchTab, r as currentPage, s as pageData, t as audit, u as redirectTo } from "./commands-BynZfUJ6.js";
|
|
3
|
+
import "./run-mcp-TnooVQe8.js";
|
|
2
4
|
import fs from "node:fs/promises";
|
|
3
5
|
import path from "node:path";
|
|
4
6
|
import { fs as fs$1 } from "@weapp-core/shared/fs";
|
|
@@ -433,7 +435,7 @@ async function runScreenshot(argv) {
|
|
|
433
435
|
}
|
|
434
436
|
const options = parseScreenshotArgs(argv);
|
|
435
437
|
const isJsonOutput = argv.includes("--json");
|
|
436
|
-
const { takeScreenshot } = await import("./commands-
|
|
438
|
+
const { takeScreenshot } = await import("./commands-DG-3Zgd0.js");
|
|
437
439
|
const result = await takeScreenshot(options);
|
|
438
440
|
if (isJsonOutput) {
|
|
439
441
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -944,11 +946,13 @@ const MINIDEV_NAMESPACE_COMMAND_NAMES = [
|
|
|
944
946
|
"minidev"
|
|
945
947
|
];
|
|
946
948
|
const CONFIG_COMMAND_NAME = "config";
|
|
949
|
+
const MCP_COMMAND_NAME = "mcp";
|
|
947
950
|
const WEAPP_IDE_TOP_LEVEL_COMMAND_NAMES = [
|
|
948
951
|
...WECHAT_CLI_COMMAND_NAMES,
|
|
949
952
|
...AUTOMATOR_COMMAND_NAMES,
|
|
950
953
|
...MINIDEV_NAMESPACE_COMMAND_NAMES,
|
|
951
|
-
CONFIG_COMMAND_NAME
|
|
954
|
+
CONFIG_COMMAND_NAME,
|
|
955
|
+
"mcp"
|
|
952
956
|
];
|
|
953
957
|
const WEAPP_IDE_TOP_LEVEL_COMMAND_SET = new Set(WEAPP_IDE_TOP_LEVEL_COMMAND_NAMES);
|
|
954
958
|
/**
|
|
@@ -2554,6 +2558,7 @@ function createCli() {
|
|
|
2554
2558
|
for (const command of WECHAT_CLI_COMMAND_NAMES) cli.command(command, "微信开发者工具官方命令透传").allowUnknownOptions();
|
|
2555
2559
|
for (const command of MINIDEV_NAMESPACE_COMMAND_NAMES) cli.command(`${command} [...args]`, "支付宝 minidev 命令透传").allowUnknownOptions();
|
|
2556
2560
|
cli.command(`${CONFIG_COMMAND_NAME} [...args]`, "配置 weapp-ide-cli").allowUnknownOptions();
|
|
2561
|
+
cli.command(`mcp [...args]`, "启动 weapp-ide-cli MCP 服务").allowUnknownOptions();
|
|
2557
2562
|
for (const command of AUTOMATOR_COMMAND_NAMES) cli.command(`${command} [...args]`, "automator 增强命令").allowUnknownOptions();
|
|
2558
2563
|
return cli;
|
|
2559
2564
|
}
|
|
@@ -2622,6 +2627,11 @@ async function parse(argv) {
|
|
|
2622
2627
|
await handleConfigCommand(argv.slice(1));
|
|
2623
2628
|
return;
|
|
2624
2629
|
}
|
|
2630
|
+
if (matchedCommand === "mcp") {
|
|
2631
|
+
const { runMcpCommand } = await import("./run-mcp-DhujWgfX.js");
|
|
2632
|
+
await runMcpCommand(argv.slice(1));
|
|
2633
|
+
return;
|
|
2634
|
+
}
|
|
2625
2635
|
if (matchedCommand && isAutomatorCommand(matchedCommand)) {
|
|
2626
2636
|
await runAutomatorCommand(matchedCommand, argv.slice(1));
|
|
2627
2637
|
return;
|
|
@@ -2636,4 +2646,4 @@ async function parse(argv) {
|
|
|
2636
2646
|
await runWechatCliCommand(formattedArgv);
|
|
2637
2647
|
}
|
|
2638
2648
|
//#endregion
|
|
2639
|
-
export { resetWechatIdeFileUtilsByHttp as $, RETRY_CANCEL_KEYS as A, waitForRetryKeypress as B, refreshWechatIdeTicket as C, validateWechatCliCommandArgs as D, uploadWechatIde as E, formatRetryHotkeyPrompt as F, transformArgv as G, execute as H, formatWechatIdeLoginRequiredError as I, runWechatIdeEngineBuildByHttp as J, startForwardConsole as K, isWechatIdeLoginRequiredError as L, RETRY_PROMPT_INITIAL_IGNORE_MS as M, createWechatIdeLoginRequiredExitError as N, runWechatCliWithRetry as O, extractExecutionErrorText as P, requestWechatDevtoolsHttp as Q, promptRetryKeypress as R, quitWechatIde as S,
|
|
2649
|
+
export { resetWechatIdeFileUtilsByHttp as $, RETRY_CANCEL_KEYS as A, waitForRetryKeypress as B, refreshWechatIdeTicket as C, removeOption as Ct, validateWechatCliCommandArgs as D, uploadWechatIde as E, formatRetryHotkeyPrompt as F, transformArgv as G, execute as H, formatWechatIdeLoginRequiredError as I, runWechatIdeEngineBuildByHttp as J, startForwardConsole as K, isWechatIdeLoginRequiredError as L, RETRY_PROMPT_INITIAL_IGNORE_MS as M, createWechatIdeLoginRequiredExitError as N, runWechatCliWithRetry as O, extractExecutionErrorText as P, requestWechatDevtoolsHttp as Q, promptRetryKeypress as R, quitWechatIde as S, readOptionValue as St, setWechatIdeTicket as T, createAlias as U, runMinidev as V, createPathCompat as W, openWechatIdeProjectByHttp as X, WECHAT_DEVTOOLS_ENGINE_BUILD_STATUSES as Y, pollWechatIdeEngineBuildResultByHttp as Z, isWechatIdeLoggedIn as _, printScreenshotHelp as _t, autoReplayWechatIde as a, waitForExclusiveKeypress as at, openWechatIdeOtherProject as b, parseAutomatorArgs as bt, buildWechatIdeIpa as c, MINIDEV_NAMESPACE_COMMAND_NAMES as ct, clearWechatIdeCacheByAutomator as d, isWeappIdeTopLevelCommand as dt, startWechatIdeEngineBuildByHttp as et, closeWechatIdeProject as f, AUTOMATOR_COMMAND_NAMES as ft, getWechatIdeToolInfo as g, parseScreenshotArgs as gt, getWechatIdeTicket as h, runAutomatorCommand as ht, autoPreviewWechatIde as i, runWithSuspendedSharedInput as it, RETRY_CONFIRM_KEYS as j, runRetryableCommand as k, buildWechatIdeNpm as l, WEAPP_IDE_TOP_LEVEL_COMMAND_NAMES as lt, getWechatIdeTestAccounts as m, isAutomatorCommand as mt, parse as n, promptForCliPath as nt, autoWechatIde as o, CONFIG_COMMAND_NAME as ot, compileWechatIdeByAutomator as p, getAutomatorCommandHelp as pt, runWechatIdeEngineBuild as q, dispatchWechatCliCommand as r, createSharedInputSession as rt, buildWechatIdeApk as s, MCP_COMMAND_NAME as st, createCli as t, handleConfigCommand as tt, clearWechatIdeCache as u, WECHAT_CLI_COMMAND_NAMES as ut, loginWechatIde as v, parseCompareArgs as vt, resetWechatIdeFileUtils as w, previewWechatIde as x, readBooleanOption as xt, openWechatIde as y, printCompareHelp as yt, promptWechatIdeLoginRetry as z };
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as parse } from "./cli-
|
|
1
|
+
import { j as logger_default } from "./automator-session-BZzODsJi.js";
|
|
2
|
+
import { n as parse } from "./cli-B45DqpiD.js";
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
//#region src/cli.ts
|
|
5
5
|
const argv = process.argv.slice(2);
|