ms-vite-plugin 1.1.2 → 1.1.4
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/build.js +6 -0
- package/dist/cli.js +91 -1
- package/dist/mcp/device-config.d.ts +55 -0
- package/dist/mcp/device-config.js +183 -0
- package/dist/mcp/docs-service.d.ts +65 -0
- package/dist/mcp/docs-service.js +168 -0
- package/dist/mcp/project.d.ts +16 -0
- package/dist/mcp/project.js +74 -0
- package/dist/mcp/tools.d.ts +18 -0
- package/dist/mcp/tools.js +825 -0
- package/dist/mcp/types.d.ts +32 -0
- package/dist/mcp/types.js +11 -0
- package/dist/mcp-server.d.ts +2 -0
- package/dist/mcp-server.js +86 -0
- package/dist/project.d.ts +89 -0
- package/dist/project.js +306 -0
- package/dist/version.d.ts +12 -0
- package/dist/version.js +63 -0
- package/docs/api/action.md +922 -0
- package/docs/api/appleocr.md +229 -0
- package/docs/api/config.md +122 -0
- package/docs/api/cryptoUtils.md +232 -0
- package/docs/api/device.md +374 -0
- package/docs/api/file.md +516 -0
- package/docs/api/global.md +617 -0
- package/docs/api/hid.md +1032 -0
- package/docs/api/hotUpdate.md +166 -0
- package/docs/api/http.md +548 -0
- package/docs/api/image.md +907 -0
- package/docs/api/ime.md +290 -0
- package/docs/api/logger.md +324 -0
- package/docs/api/media.md +248 -0
- package/docs/api/mysql.md +441 -0
- package/docs/api/netCard.md +200 -0
- package/docs/api/node.md +353 -0
- package/docs/api/paddleocr.md +246 -0
- package/docs/api/pip.md +242 -0
- package/docs/api/system.md +572 -0
- package/docs/api/thread.md +269 -0
- package/docs/api/tomatoocr.md +425 -0
- package/docs/api/tts.md +334 -0
- package/docs/api/ui.md +947 -0
- package/docs/api/utils.md +265 -0
- package/docs/api/yolo.md +310 -0
- package/docs/apicn/action.md +919 -0
- package/docs/apicn/appleocr.md +233 -0
- package/docs/apicn/config.md +120 -0
- package/docs/apicn/device.md +385 -0
- package/docs/apicn/file.md +511 -0
- package/docs/apicn/global.md +613 -0
- package/docs/apicn/hid.md +1033 -0
- package/docs/apicn/hotUpdate.md +170 -0
- package/docs/apicn/http.md +672 -0
- package/docs/apicn/image.md +924 -0
- package/docs/apicn/ime.md +290 -0
- package/docs/apicn/logger.md +332 -0
- package/docs/apicn/media.md +252 -0
- package/docs/apicn/mysql.md +445 -0
- package/docs/apicn/netCard.md +200 -0
- package/docs/apicn/node.md +362 -0
- package/docs/apicn/paddleocr.md +255 -0
- package/docs/apicn/pip.md +242 -0
- package/docs/apicn/system.md +575 -0
- package/docs/apicn/thread.md +269 -0
- package/docs/apicn/tts.md +338 -0
- package/docs/apicn/ui.md +933 -0
- package/docs/apicn/utils.md +265 -0
- package/docs/apicn/yolo.md +314 -0
- package/docs/apipython/action.md +901 -0
- package/docs/apipython/appleocr.md +226 -0
- package/docs/apipython/config.md +126 -0
- package/docs/apipython/cryptoUtils.md +246 -0
- package/docs/apipython/device.md +365 -0
- package/docs/apipython/file.md +476 -0
- package/docs/apipython/g.md +154 -0
- package/docs/apipython/hid.md +1059 -0
- package/docs/apipython/hotUpdate.md +154 -0
- package/docs/apipython/image.md +938 -0
- package/docs/apipython/ime.md +306 -0
- package/docs/apipython/logger.md +330 -0
- package/docs/apipython/media.md +221 -0
- package/docs/apipython/mysql.md +432 -0
- package/docs/apipython/netCard.md +219 -0
- package/docs/apipython/node.md +331 -0
- package/docs/apipython/overview.md +66 -0
- package/docs/apipython/paddleocr.md +211 -0
- package/docs/apipython/pip.md +231 -0
- package/docs/apipython/system.md +458 -0
- package/docs/apipython/tomatoocr.md +444 -0
- package/docs/apipython/tts.md +331 -0
- package/docs/apipython/ui.md +949 -0
- package/docs/apipython/utils.md +284 -0
- package/docs/apipython/yolo.md +281 -0
- package/package.json +8 -4
package/dist/build.js
CHANGED
|
@@ -43,6 +43,12 @@ const fsExtra = __importStar(require("fs-extra"));
|
|
|
43
43
|
const os = __importStar(require("os"));
|
|
44
44
|
const path = __importStar(require("path"));
|
|
45
45
|
const vite_plugin_bundle_obfuscator_1 = __importDefault(require("vite-plugin-bundle-obfuscator"));
|
|
46
|
+
/**
|
|
47
|
+
* 压缩目录
|
|
48
|
+
* @param source 源目录路径
|
|
49
|
+
* @param out 输出文件路径
|
|
50
|
+
* @returns 压缩完成后的 Promise
|
|
51
|
+
*/
|
|
46
52
|
async function zipDirectory(source, out) {
|
|
47
53
|
const archive = (0, archiver_1.default)("zip", { zlib: { level: 9 } });
|
|
48
54
|
const stream = fsExtra.createWriteStream(out);
|
package/dist/cli.js
CHANGED
|
@@ -42,6 +42,7 @@ const fsExtra = __importStar(require("fs-extra"));
|
|
|
42
42
|
const project_1 = require("./project");
|
|
43
43
|
const packager_1 = require("./packager");
|
|
44
44
|
const ws_manager_1 = require("./ws-manager");
|
|
45
|
+
const version_1 = require("./version");
|
|
45
46
|
/**
|
|
46
47
|
* WS 状态持久化文件路径(用于跨进程查询 ws-status)
|
|
47
48
|
*/
|
|
@@ -183,6 +184,70 @@ async function stopCommand(options) {
|
|
|
183
184
|
process.exit(1);
|
|
184
185
|
}
|
|
185
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* screenshot 命令处理函数
|
|
189
|
+
* @param options 命令选项
|
|
190
|
+
* @returns 请求完成后退出
|
|
191
|
+
* @example
|
|
192
|
+
* ms screenshot --ip 192.168.1.100 --port 9800 --output ./screen.jpg
|
|
193
|
+
*/
|
|
194
|
+
async function screenshotCommand(options) {
|
|
195
|
+
try {
|
|
196
|
+
await ensureValidKuaiJSProject(process.cwd());
|
|
197
|
+
const format = options.format ?? "file";
|
|
198
|
+
if (format === "base64") {
|
|
199
|
+
const base64 = await (0, project_1.getScreenshotBase64OnDevice)(options);
|
|
200
|
+
console.log(base64);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const image = await (0, project_1.getScreenshotOnDevice)(options);
|
|
204
|
+
const outputPath = options.output?.trim()
|
|
205
|
+
? path.resolve(options.output.trim())
|
|
206
|
+
: path.resolve(process.cwd(), "screenshot.jpg");
|
|
207
|
+
await fsExtra.ensureDir(path.dirname(outputPath));
|
|
208
|
+
await fsExtra.writeFile(outputPath, image);
|
|
209
|
+
console.log(`✅ 截图成功: ${outputPath} (${image.length} bytes)`);
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
console.error("❌ 截图失败:", error instanceof Error ? error.message : error);
|
|
213
|
+
process.exit(1);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* source 命令处理函数
|
|
218
|
+
* @param options 命令选项
|
|
219
|
+
* @returns 请求完成后退出
|
|
220
|
+
* @example
|
|
221
|
+
* ms source --ip 192.168.1.100 --port 9800 --max-depth 50 --timeout 120
|
|
222
|
+
*/
|
|
223
|
+
async function sourceCommand(options) {
|
|
224
|
+
try {
|
|
225
|
+
await ensureValidKuaiJSProject(process.cwd());
|
|
226
|
+
const maxDepthText = (options.maxDepth ?? "50").trim();
|
|
227
|
+
const timeoutText = (options.timeout ?? "120").trim();
|
|
228
|
+
const maxDepth = Number.parseInt(maxDepthText, 10);
|
|
229
|
+
const timeout = Number.parseInt(timeoutText, 10);
|
|
230
|
+
if (!Number.isInteger(maxDepth) || maxDepth < 1) {
|
|
231
|
+
throw new Error(`无效 max-depth: ${maxDepthText}`);
|
|
232
|
+
}
|
|
233
|
+
if (!Number.isInteger(timeout) || timeout < 1) {
|
|
234
|
+
throw new Error(`无效 timeout: ${timeoutText}`);
|
|
235
|
+
}
|
|
236
|
+
const source = await (0, project_1.getSourceOnDevice)(options, maxDepth, timeout);
|
|
237
|
+
if (options.output?.trim()) {
|
|
238
|
+
const outputPath = path.resolve(options.output.trim());
|
|
239
|
+
await fsExtra.ensureDir(path.dirname(outputPath));
|
|
240
|
+
await fsExtra.writeFile(outputPath, source, "utf8");
|
|
241
|
+
console.log(`✅ 节点已保存: ${outputPath}`);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
console.log(source);
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
console.error("❌ 获取节点失败:", error instanceof Error ? error.message : error);
|
|
248
|
+
process.exit(1);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
186
251
|
/**
|
|
187
252
|
* ws-start 命令处理函数
|
|
188
253
|
* @param options 命令选项
|
|
@@ -365,7 +430,7 @@ function renderDetailedCommandHelp() {
|
|
|
365
430
|
return lines.join("\n");
|
|
366
431
|
}
|
|
367
432
|
// 配置 CLI 程序
|
|
368
|
-
commander_1.program.name("ms-cli").description("快点JS 构建工具").version(
|
|
433
|
+
commander_1.program.name("ms-cli").description("快点JS 构建工具").version(version_1.PACKAGE_VERSION);
|
|
369
434
|
commander_1.program.addHelpText("after", renderDetailedCommandHelp);
|
|
370
435
|
// 构建命令
|
|
371
436
|
commander_1.program
|
|
@@ -408,6 +473,31 @@ commander_1.program
|
|
|
408
473
|
.option("--ws-port <wsPort>", "WS 服务端口", "31111")
|
|
409
474
|
.option("--ws-wait-ms <wsWaitMs>", "WS 等待设备连接时间(毫秒)", "30000")
|
|
410
475
|
.action(stopCommand);
|
|
476
|
+
// 截图命令
|
|
477
|
+
commander_1.program
|
|
478
|
+
.command("screenshot")
|
|
479
|
+
.description("获取设备截图(JPG)")
|
|
480
|
+
.option("-i, --ip <ip>", "设备 IP 地址(transport=http 时必填)")
|
|
481
|
+
.option("--port <port>", "设备端口", "9800")
|
|
482
|
+
.option("-t, --transport <transport>", "传输方式: http|ws", "http")
|
|
483
|
+
.option("--ws-port <wsPort>", "WS 服务端口", "31111")
|
|
484
|
+
.option("--ws-wait-ms <wsWaitMs>", "WS 等待设备连接时间(毫秒)", "30000")
|
|
485
|
+
.option("--format <format>", "返回格式: file|base64", "file")
|
|
486
|
+
.option("--output <output>", "截图输出文件路径(format=file 时生效)")
|
|
487
|
+
.action(screenshotCommand);
|
|
488
|
+
// 节点命令
|
|
489
|
+
commander_1.program
|
|
490
|
+
.command("source")
|
|
491
|
+
.description("获取设备当前页面节点 XML")
|
|
492
|
+
.option("-i, --ip <ip>", "设备 IP 地址(transport=http 时必填)")
|
|
493
|
+
.option("--port <port>", "设备端口", "9800")
|
|
494
|
+
.option("-t, --transport <transport>", "传输方式: http|ws", "http")
|
|
495
|
+
.option("--ws-port <wsPort>", "WS 服务端口", "31111")
|
|
496
|
+
.option("--ws-wait-ms <wsWaitMs>", "WS 等待设备连接时间(毫秒)", "30000")
|
|
497
|
+
.option("--max-depth <maxDepth>", "节点最大深度", "50")
|
|
498
|
+
.option("--timeout <timeout>", "节点抓取超时秒数", "120")
|
|
499
|
+
.option("--output <output>", "节点 XML 输出文件路径(可选)")
|
|
500
|
+
.action(sourceCommand);
|
|
411
501
|
// WS 服务启动命令
|
|
412
502
|
commander_1.program
|
|
413
503
|
.command("ws-start")
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { DeviceConfig } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* 默认设备端口
|
|
4
|
+
*/
|
|
5
|
+
export declare const DEFAULT_DEVICE_PORT = 9800;
|
|
6
|
+
/**
|
|
7
|
+
* 设备连接配置持久化文件
|
|
8
|
+
* - 使用系统临时目录,避免污染项目源码目录
|
|
9
|
+
* - 文件名包含 pid/时间戳/随机串,确保并发窗口与多次启动互不冲突
|
|
10
|
+
*/
|
|
11
|
+
export declare const DEVICE_CONFIG_FILE: string;
|
|
12
|
+
/**
|
|
13
|
+
* 将端口标准化为字符串(内部沿用 DeviceCliOptions 字符串端口)
|
|
14
|
+
* @param port 端口号
|
|
15
|
+
* @returns 返回标准端口字符串
|
|
16
|
+
* @example
|
|
17
|
+
* const textPort = normalizePort(9800)
|
|
18
|
+
*/
|
|
19
|
+
export declare function normalizePort(port: number): string;
|
|
20
|
+
/**
|
|
21
|
+
* 读取已保存的设备配置
|
|
22
|
+
* @returns 若存在有效配置则返回配置对象,否则返回 null
|
|
23
|
+
* @example
|
|
24
|
+
* const cfg = await readDeviceConfig()
|
|
25
|
+
*/
|
|
26
|
+
export declare function readDeviceConfig(): Promise<DeviceConfig | null>;
|
|
27
|
+
/**
|
|
28
|
+
* 保存设备配置
|
|
29
|
+
* @param config 需要保存的设备配置
|
|
30
|
+
* @returns 保存完成后返回 Promise<void>
|
|
31
|
+
* @example
|
|
32
|
+
* await writeDeviceConfig({ ip: "192.168.1.100", port: 9800, updatedAt: Date.now() })
|
|
33
|
+
*/
|
|
34
|
+
export declare function writeDeviceConfig(config: DeviceConfig): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* 构建并保存设备配置
|
|
37
|
+
* @param ip 设备 IP
|
|
38
|
+
* @param port 设备端口(可选)
|
|
39
|
+
* @returns 返回保存后的设备配置
|
|
40
|
+
* @example
|
|
41
|
+
* const cfg = await setDeviceConfig("192.168.1.100", 9800)
|
|
42
|
+
*/
|
|
43
|
+
export declare function setDeviceConfig(ip: string, port?: number): Promise<DeviceConfig>;
|
|
44
|
+
/**
|
|
45
|
+
* 获取最终生效的设备配置
|
|
46
|
+
* - 若调用参数携带 ip,则优先使用调用参数并落盘
|
|
47
|
+
* - 若只传 port,则复用已保存 ip,并更新 port 后落盘
|
|
48
|
+
* - 若都不传,则读取已保存配置
|
|
49
|
+
* @param ip 调用参数中的设备 ip(可选)
|
|
50
|
+
* @param port 调用参数中的设备端口(可选)
|
|
51
|
+
* @returns 返回可直接用于请求设备的配置
|
|
52
|
+
* @example
|
|
53
|
+
* const target = await resolveDeviceConfig(undefined, undefined)
|
|
54
|
+
*/
|
|
55
|
+
export declare function resolveDeviceConfig(ip?: string, port?: number): Promise<DeviceConfig>;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.DEVICE_CONFIG_FILE = exports.DEFAULT_DEVICE_PORT = void 0;
|
|
37
|
+
exports.normalizePort = normalizePort;
|
|
38
|
+
exports.readDeviceConfig = readDeviceConfig;
|
|
39
|
+
exports.writeDeviceConfig = writeDeviceConfig;
|
|
40
|
+
exports.setDeviceConfig = setDeviceConfig;
|
|
41
|
+
exports.resolveDeviceConfig = resolveDeviceConfig;
|
|
42
|
+
const fsExtra = __importStar(require("fs-extra"));
|
|
43
|
+
const os = __importStar(require("os"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
/**
|
|
46
|
+
* 默认设备端口
|
|
47
|
+
*/
|
|
48
|
+
exports.DEFAULT_DEVICE_PORT = 9800;
|
|
49
|
+
/**
|
|
50
|
+
* 设备连接配置持久化文件
|
|
51
|
+
* - 使用系统临时目录,避免污染项目源码目录
|
|
52
|
+
* - 文件名包含 pid/时间戳/随机串,确保并发窗口与多次启动互不冲突
|
|
53
|
+
*/
|
|
54
|
+
exports.DEVICE_CONFIG_FILE = path.join(os.tmpdir(), `ms-cli-mcp-device-${process.pid}-${Date.now()}-${Math.random()
|
|
55
|
+
.toString(36)
|
|
56
|
+
.slice(2, 10)}.json`);
|
|
57
|
+
/**
|
|
58
|
+
* 将端口标准化为字符串(内部沿用 DeviceCliOptions 字符串端口)
|
|
59
|
+
* @param port 端口号
|
|
60
|
+
* @returns 返回标准端口字符串
|
|
61
|
+
* @example
|
|
62
|
+
* const textPort = normalizePort(9800)
|
|
63
|
+
*/
|
|
64
|
+
function normalizePort(port) {
|
|
65
|
+
return String(port);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* 校验并标准化 IP 字符串
|
|
69
|
+
* @param ip 原始 ip 输入
|
|
70
|
+
* @returns 返回去空格后的 ip
|
|
71
|
+
* @example
|
|
72
|
+
* const normalizedIp = normalizeIp(" 192.168.1.100 ")
|
|
73
|
+
*/
|
|
74
|
+
function normalizeIp(ip) {
|
|
75
|
+
const normalizedIp = ip.trim();
|
|
76
|
+
if (!normalizedIp) {
|
|
77
|
+
throw new Error("设备 IP 不能为空");
|
|
78
|
+
}
|
|
79
|
+
return normalizedIp;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* 校验并标准化端口
|
|
83
|
+
* @param port 原始端口(可选)
|
|
84
|
+
* @returns 返回有效端口,默认 9800
|
|
85
|
+
* @example
|
|
86
|
+
* const normalizedPort = normalizeDevicePort(undefined)
|
|
87
|
+
*/
|
|
88
|
+
function normalizeDevicePort(port) {
|
|
89
|
+
const targetPort = port ?? exports.DEFAULT_DEVICE_PORT;
|
|
90
|
+
if (!Number.isInteger(targetPort) || targetPort < 1 || targetPort > 65535) {
|
|
91
|
+
throw new Error(`无效设备端口: ${String(port)}`);
|
|
92
|
+
}
|
|
93
|
+
return targetPort;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* 读取已保存的设备配置
|
|
97
|
+
* @returns 若存在有效配置则返回配置对象,否则返回 null
|
|
98
|
+
* @example
|
|
99
|
+
* const cfg = await readDeviceConfig()
|
|
100
|
+
*/
|
|
101
|
+
async function readDeviceConfig() {
|
|
102
|
+
try {
|
|
103
|
+
if (!(await fsExtra.pathExists(exports.DEVICE_CONFIG_FILE))) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
const data = (await fsExtra.readJSON(exports.DEVICE_CONFIG_FILE));
|
|
107
|
+
const ip = typeof data.ip === "string" ? data.ip.trim() : "";
|
|
108
|
+
const port = typeof data.port === "number" ? data.port : Number.parseInt(String(data.port), 10);
|
|
109
|
+
if (!ip || !Number.isInteger(port) || port < 1 || port > 65535) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
ip,
|
|
114
|
+
port,
|
|
115
|
+
updatedAt: typeof data.updatedAt === "number" && Number.isFinite(data.updatedAt)
|
|
116
|
+
? data.updatedAt
|
|
117
|
+
: Date.now(),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* 保存设备配置
|
|
126
|
+
* @param config 需要保存的设备配置
|
|
127
|
+
* @returns 保存完成后返回 Promise<void>
|
|
128
|
+
* @example
|
|
129
|
+
* await writeDeviceConfig({ ip: "192.168.1.100", port: 9800, updatedAt: Date.now() })
|
|
130
|
+
*/
|
|
131
|
+
async function writeDeviceConfig(config) {
|
|
132
|
+
await fsExtra.writeJSON(exports.DEVICE_CONFIG_FILE, config, { spaces: 2 });
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* 构建并保存设备配置
|
|
136
|
+
* @param ip 设备 IP
|
|
137
|
+
* @param port 设备端口(可选)
|
|
138
|
+
* @returns 返回保存后的设备配置
|
|
139
|
+
* @example
|
|
140
|
+
* const cfg = await setDeviceConfig("192.168.1.100", 9800)
|
|
141
|
+
*/
|
|
142
|
+
async function setDeviceConfig(ip, port) {
|
|
143
|
+
const config = {
|
|
144
|
+
ip: normalizeIp(ip),
|
|
145
|
+
port: normalizeDevicePort(port),
|
|
146
|
+
updatedAt: Date.now(),
|
|
147
|
+
};
|
|
148
|
+
await writeDeviceConfig(config);
|
|
149
|
+
return config;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* 获取最终生效的设备配置
|
|
153
|
+
* - 若调用参数携带 ip,则优先使用调用参数并落盘
|
|
154
|
+
* - 若只传 port,则复用已保存 ip,并更新 port 后落盘
|
|
155
|
+
* - 若都不传,则读取已保存配置
|
|
156
|
+
* @param ip 调用参数中的设备 ip(可选)
|
|
157
|
+
* @param port 调用参数中的设备端口(可选)
|
|
158
|
+
* @returns 返回可直接用于请求设备的配置
|
|
159
|
+
* @example
|
|
160
|
+
* const target = await resolveDeviceConfig(undefined, undefined)
|
|
161
|
+
*/
|
|
162
|
+
async function resolveDeviceConfig(ip, port) {
|
|
163
|
+
const savedConfig = await readDeviceConfig();
|
|
164
|
+
if (ip !== undefined) {
|
|
165
|
+
return setDeviceConfig(ip, port);
|
|
166
|
+
}
|
|
167
|
+
if (port !== undefined) {
|
|
168
|
+
if (!savedConfig) {
|
|
169
|
+
throw new Error("尚未配置设备 IP。请先调用 set_device 设置 ip,或在本次 run 调用里传入 ip。");
|
|
170
|
+
}
|
|
171
|
+
const nextConfig = {
|
|
172
|
+
ip: savedConfig.ip,
|
|
173
|
+
port: normalizeDevicePort(port),
|
|
174
|
+
updatedAt: Date.now(),
|
|
175
|
+
};
|
|
176
|
+
await writeDeviceConfig(nextConfig);
|
|
177
|
+
return nextConfig;
|
|
178
|
+
}
|
|
179
|
+
if (savedConfig) {
|
|
180
|
+
return savedConfig;
|
|
181
|
+
}
|
|
182
|
+
throw new Error("未找到可用设备配置。请先调用 set_device 设置 ip,或在 run/run_ui/stop 调用里传入 ip。");
|
|
183
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { ApiDocItem, ApiDocsLanguage } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* 获取当前文档语言
|
|
4
|
+
* @returns 返回当前语言
|
|
5
|
+
* @example
|
|
6
|
+
* const language = getCurrentDocsLanguage()
|
|
7
|
+
*/
|
|
8
|
+
export declare function getCurrentDocsLanguage(): ApiDocsLanguage;
|
|
9
|
+
/**
|
|
10
|
+
* 设置当前文档语言
|
|
11
|
+
* @param language 目标语言
|
|
12
|
+
* @returns 设置后的语言
|
|
13
|
+
* @example
|
|
14
|
+
* const language = setCurrentDocsLanguage("python")
|
|
15
|
+
*/
|
|
16
|
+
export declare function setCurrentDocsLanguage(language: ApiDocsLanguage): ApiDocsLanguage;
|
|
17
|
+
/**
|
|
18
|
+
* 根据可选入参解析实际使用的文档语言
|
|
19
|
+
* @param language 工具调用时传入的语言(可选)
|
|
20
|
+
* @returns 返回最终生效的语言
|
|
21
|
+
* @example
|
|
22
|
+
* const activeLanguage = resolveDocsLanguage(undefined)
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveDocsLanguage(language?: ApiDocsLanguage): ApiDocsLanguage;
|
|
25
|
+
/**
|
|
26
|
+
* 获取 docs 根目录
|
|
27
|
+
* @returns 返回 docs 目录绝对路径
|
|
28
|
+
* @example
|
|
29
|
+
* const docsRoot = getDocsRootDir()
|
|
30
|
+
*/
|
|
31
|
+
export declare function getDocsRootDir(): string;
|
|
32
|
+
/**
|
|
33
|
+
* 获取某语言对应的文档目录
|
|
34
|
+
* @param language 文档语言
|
|
35
|
+
* @returns 返回文档目录绝对路径
|
|
36
|
+
* @example
|
|
37
|
+
* const dir = getDocsDirByLanguage("js_zh")
|
|
38
|
+
*/
|
|
39
|
+
export declare function getDocsDirByLanguage(language: ApiDocsLanguage): string;
|
|
40
|
+
/**
|
|
41
|
+
* 读取指定语言的 API 文档列表
|
|
42
|
+
* @param language 文档语言
|
|
43
|
+
* @returns 返回文档条目数组(按 slug 升序)
|
|
44
|
+
* @example
|
|
45
|
+
* const docs = await getApiDocsByLanguage("python")
|
|
46
|
+
*/
|
|
47
|
+
export declare function getApiDocsByLanguage(language: ApiDocsLanguage): Promise<ApiDocItem[]>;
|
|
48
|
+
/**
|
|
49
|
+
* 对文档按查询词打分,用于检索排序
|
|
50
|
+
* @param doc 文档条目
|
|
51
|
+
* @param normalizedQuery 已转小写的查询词
|
|
52
|
+
* @returns 分数,0 表示不命中
|
|
53
|
+
* @example
|
|
54
|
+
* const score = scoreApiDoc(doc, "click")
|
|
55
|
+
*/
|
|
56
|
+
export declare function scoreApiDoc(doc: ApiDocItem, normalizedQuery: string): number;
|
|
57
|
+
/**
|
|
58
|
+
* 生成文档 URI(用于资源与文本返回)
|
|
59
|
+
* @param language 文档语言
|
|
60
|
+
* @param slug 文档分类
|
|
61
|
+
* @returns 返回 MCP 资源 URI 字符串
|
|
62
|
+
* @example
|
|
63
|
+
* const uri = getDocUri("js_zh", "device")
|
|
64
|
+
*/
|
|
65
|
+
export declare function getDocUri(language: ApiDocsLanguage, slug: string): string;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.getCurrentDocsLanguage = getCurrentDocsLanguage;
|
|
37
|
+
exports.setCurrentDocsLanguage = setCurrentDocsLanguage;
|
|
38
|
+
exports.resolveDocsLanguage = resolveDocsLanguage;
|
|
39
|
+
exports.getDocsRootDir = getDocsRootDir;
|
|
40
|
+
exports.getDocsDirByLanguage = getDocsDirByLanguage;
|
|
41
|
+
exports.getApiDocsByLanguage = getApiDocsByLanguage;
|
|
42
|
+
exports.scoreApiDoc = scoreApiDoc;
|
|
43
|
+
exports.getDocUri = getDocUri;
|
|
44
|
+
const fsExtra = __importStar(require("fs-extra"));
|
|
45
|
+
const path = __importStar(require("path"));
|
|
46
|
+
/**
|
|
47
|
+
* 当前 MCP 进程默认文档语言
|
|
48
|
+
*/
|
|
49
|
+
let currentDocsLanguage = "js_zh";
|
|
50
|
+
/**
|
|
51
|
+
* 获取当前文档语言
|
|
52
|
+
* @returns 返回当前语言
|
|
53
|
+
* @example
|
|
54
|
+
* const language = getCurrentDocsLanguage()
|
|
55
|
+
*/
|
|
56
|
+
function getCurrentDocsLanguage() {
|
|
57
|
+
return currentDocsLanguage;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 设置当前文档语言
|
|
61
|
+
* @param language 目标语言
|
|
62
|
+
* @returns 设置后的语言
|
|
63
|
+
* @example
|
|
64
|
+
* const language = setCurrentDocsLanguage("python")
|
|
65
|
+
*/
|
|
66
|
+
function setCurrentDocsLanguage(language) {
|
|
67
|
+
currentDocsLanguage = language;
|
|
68
|
+
return currentDocsLanguage;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 根据可选入参解析实际使用的文档语言
|
|
72
|
+
* @param language 工具调用时传入的语言(可选)
|
|
73
|
+
* @returns 返回最终生效的语言
|
|
74
|
+
* @example
|
|
75
|
+
* const activeLanguage = resolveDocsLanguage(undefined)
|
|
76
|
+
*/
|
|
77
|
+
function resolveDocsLanguage(language) {
|
|
78
|
+
return language ?? currentDocsLanguage;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* 获取 docs 根目录
|
|
82
|
+
* @returns 返回 docs 目录绝对路径
|
|
83
|
+
* @example
|
|
84
|
+
* const docsRoot = getDocsRootDir()
|
|
85
|
+
*/
|
|
86
|
+
function getDocsRootDir() {
|
|
87
|
+
return path.resolve(__dirname, "..", "..", "docs");
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* 获取某语言对应的文档目录
|
|
91
|
+
* @param language 文档语言
|
|
92
|
+
* @returns 返回文档目录绝对路径
|
|
93
|
+
* @example
|
|
94
|
+
* const dir = getDocsDirByLanguage("js_zh")
|
|
95
|
+
*/
|
|
96
|
+
function getDocsDirByLanguage(language) {
|
|
97
|
+
if (language === "js") {
|
|
98
|
+
return path.join(getDocsRootDir(), "api");
|
|
99
|
+
}
|
|
100
|
+
if (language === "js_zh") {
|
|
101
|
+
return path.join(getDocsRootDir(), "apicn");
|
|
102
|
+
}
|
|
103
|
+
return path.join(getDocsRootDir(), "apipython");
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* 读取指定语言的 API 文档列表
|
|
107
|
+
* @param language 文档语言
|
|
108
|
+
* @returns 返回文档条目数组(按 slug 升序)
|
|
109
|
+
* @example
|
|
110
|
+
* const docs = await getApiDocsByLanguage("python")
|
|
111
|
+
*/
|
|
112
|
+
async function getApiDocsByLanguage(language) {
|
|
113
|
+
const docsDir = getDocsDirByLanguage(language);
|
|
114
|
+
if (!(await fsExtra.pathExists(docsDir))) {
|
|
115
|
+
throw new Error(`文档目录不存在: ${docsDir}`);
|
|
116
|
+
}
|
|
117
|
+
const fileNames = await fsExtra.readdir(docsDir);
|
|
118
|
+
const mdFiles = fileNames
|
|
119
|
+
.filter((name) => name.toLowerCase().endsWith(".md"))
|
|
120
|
+
.sort();
|
|
121
|
+
const docs = [];
|
|
122
|
+
for (const fileName of mdFiles) {
|
|
123
|
+
const filePath = path.join(docsDir, fileName);
|
|
124
|
+
const content = await fsExtra.readFile(filePath, "utf8");
|
|
125
|
+
const slug = path.basename(fileName, ".md");
|
|
126
|
+
const titleMatch = content.match(/^#\s+(.+)$/m);
|
|
127
|
+
const title = titleMatch?.[1]?.trim() || slug;
|
|
128
|
+
docs.push({
|
|
129
|
+
slug,
|
|
130
|
+
title,
|
|
131
|
+
content,
|
|
132
|
+
filePath,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
return docs;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* 对文档按查询词打分,用于检索排序
|
|
139
|
+
* @param doc 文档条目
|
|
140
|
+
* @param normalizedQuery 已转小写的查询词
|
|
141
|
+
* @returns 分数,0 表示不命中
|
|
142
|
+
* @example
|
|
143
|
+
* const score = scoreApiDoc(doc, "click")
|
|
144
|
+
*/
|
|
145
|
+
function scoreApiDoc(doc, normalizedQuery) {
|
|
146
|
+
let score = 0;
|
|
147
|
+
if (doc.title.toLowerCase().includes(normalizedQuery)) {
|
|
148
|
+
score += 50;
|
|
149
|
+
}
|
|
150
|
+
if (doc.slug.toLowerCase().includes(normalizedQuery)) {
|
|
151
|
+
score += 40;
|
|
152
|
+
}
|
|
153
|
+
if (doc.content.toLowerCase().includes(normalizedQuery)) {
|
|
154
|
+
score += 10;
|
|
155
|
+
}
|
|
156
|
+
return score;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* 生成文档 URI(用于资源与文本返回)
|
|
160
|
+
* @param language 文档语言
|
|
161
|
+
* @param slug 文档分类
|
|
162
|
+
* @returns 返回 MCP 资源 URI 字符串
|
|
163
|
+
* @example
|
|
164
|
+
* const uri = getDocUri("js_zh", "device")
|
|
165
|
+
*/
|
|
166
|
+
function getDocUri(language, slug) {
|
|
167
|
+
return `kuaijs://docs/${language}/${slug}`;
|
|
168
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 检查工作目录是否为有效的 KuaiJS 项目
|
|
3
|
+
* @param workspacePath 工作目录路径
|
|
4
|
+
* @returns 若目录包含 package.json 与 scripts 目录则返回 true,否则返回 false
|
|
5
|
+
* @example
|
|
6
|
+
* const ok = await isValidKuaiJSProject(process.cwd())
|
|
7
|
+
*/
|
|
8
|
+
export declare function isValidKuaiJSProject(workspacePath: string): Promise<boolean>;
|
|
9
|
+
/**
|
|
10
|
+
* 校验当前目录是否是可执行构建/运行的 KuaiJS 项目
|
|
11
|
+
* @param workspacePath 待校验目录
|
|
12
|
+
* @returns 校验通过时返回 Promise<void>,失败时抛出异常
|
|
13
|
+
* @example
|
|
14
|
+
* await ensureValidKuaiJSProject("/Users/demo/project")
|
|
15
|
+
*/
|
|
16
|
+
export declare function ensureValidKuaiJSProject(workspacePath: string): Promise<void>;
|