ms-vite-plugin 1.4.15 → 1.4.17
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/cli.js +707 -9
- package/dist/mcp/doc-tools.d.ts +0 -8
- package/dist/mcp/doc-tools.js +17 -188
- package/dist/mcp/docs-service.d.ts +1 -50
- package/dist/mcp/docs-service.js +0 -105
- package/dist/mcp/httpapi-docs-service.d.ts +8 -32
- package/dist/mcp/httpapi-docs-service.js +8 -89
- package/dist/mcp/httpapi-tools.d.ts +1 -1
- package/dist/mcp/httpapi-tools.js +7 -155
- package/dist/mcp/image-tools.d.ts +69 -0
- package/dist/mcp/image-tools.js +163 -0
- package/dist/mcp/ocr-tools.d.ts +50 -0
- package/dist/mcp/ocr-tools.js +59 -48
- package/dist/mcp/runtime-tools.js +12 -4
- package/dist/mcp/tool-utils.d.ts +0 -12
- package/dist/mcp/tool-utils.js +0 -15
- package/dist/mcp/tools.js +0 -1
- package/dist/mcp/types.d.ts +0 -13
- package/dist/project.d.ts +3 -2
- package/dist/project.js +8 -2
- package/docs/AGENTS.md +54 -52
- package/docs/SKILL.md +52 -45
- package/docs/api/paddleocr.md +11 -33
- package/docs/apicn/paddleocr.md +5 -29
- package/docs/apipython/paddleocr.md +34 -55
- package/docs/mcp-agent-description.md +58 -73
- package/package.json +1 -1
package/dist/mcp/ocr-tools.js
CHANGED
|
@@ -33,13 +33,16 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.APPLE_OCR_LANGUAGES = void 0;
|
|
37
|
+
exports.formatOcrToolText = formatOcrToolText;
|
|
38
|
+
exports.runOcrRecognitionOnDevice = runOcrRecognitionOnDevice;
|
|
36
39
|
exports.registerOcrTools = registerOcrTools;
|
|
37
40
|
const fsExtra = __importStar(require("fs-extra"));
|
|
38
41
|
const os = __importStar(require("os"));
|
|
39
42
|
const path = __importStar(require("path"));
|
|
40
43
|
const z = __importStar(require("zod/v4"));
|
|
41
44
|
const tool_utils_1 = require("./tool-utils");
|
|
42
|
-
|
|
45
|
+
exports.APPLE_OCR_LANGUAGES = [
|
|
43
46
|
"en-US",
|
|
44
47
|
"fr-FR",
|
|
45
48
|
"it-IT",
|
|
@@ -82,21 +85,22 @@ function resolveOcrOutputPath(outputPath) {
|
|
|
82
85
|
* @param ey 区域右下角 y
|
|
83
86
|
* @param texts 查找文本数组
|
|
84
87
|
* @param languages 识别语言数组
|
|
88
|
+
* @param exactMatch 是否完整匹配文本
|
|
85
89
|
* @returns 返回可交给 runScript 的 JavaScript 脚本
|
|
86
90
|
* @example
|
|
87
91
|
* buildAppleOcrScript("recognize", "screen", 0, 0, 0, 0)
|
|
88
92
|
*/
|
|
89
|
-
function buildAppleOcrScript(mode, input, x, y, ex, ey, texts, languages) {
|
|
93
|
+
function buildAppleOcrScript(mode, input, x, y, ex, ey, texts, languages, exactMatch = false) {
|
|
90
94
|
if (mode === "findText") {
|
|
91
95
|
if (!texts || texts.length === 0) {
|
|
92
96
|
throw new Error("findText 模式必须传 texts。");
|
|
93
97
|
}
|
|
94
|
-
return `appleOcr.
|
|
98
|
+
return `appleOcr.findTextAbs(${jsonLiteral(input)}, ${jsonLiteral(texts)}, ${x}, ${y}, ${ex}, ${ey}, ${jsonLiteral(languages)}, ${exactMatch});`;
|
|
95
99
|
}
|
|
96
100
|
if (mode === "numbers") {
|
|
97
|
-
return `appleOcr.
|
|
101
|
+
return `appleOcr.recognizeNumbersAbs(${jsonLiteral(input)}, ${x}, ${y}, ${ex}, ${ey});`;
|
|
98
102
|
}
|
|
99
|
-
return `appleOcr.
|
|
103
|
+
return `appleOcr.recognizeAbs(${jsonLiteral(input)}, ${x}, ${y}, ${ex}, ${ey}, ${jsonLiteral(languages)});`;
|
|
100
104
|
}
|
|
101
105
|
/**
|
|
102
106
|
* 构建 Paddle OCR 运行脚本
|
|
@@ -108,35 +112,22 @@ function buildAppleOcrScript(mode, input, x, y, ex, ey, texts, languages) {
|
|
|
108
112
|
* @param ey 区域右下角 y
|
|
109
113
|
* @param texts 查找文本数组
|
|
110
114
|
* @param confidenceThreshold 置信度阈值
|
|
111
|
-
* @param
|
|
112
|
-
* @param useGpu 是否使用 GPU
|
|
115
|
+
* @param exactMatch 是否完整匹配文本
|
|
113
116
|
* @returns 返回可交给 runScript 的 JavaScript 脚本
|
|
114
117
|
* @example
|
|
115
118
|
* buildPaddleOcrScript("recognize", "screen", 0, 0, 0, 0)
|
|
116
119
|
*/
|
|
117
|
-
function buildPaddleOcrScript(mode, input, x, y, ex, ey, texts, confidenceThreshold,
|
|
120
|
+
function buildPaddleOcrScript(mode, input, x, y, ex, ey, texts, confidenceThreshold, exactMatch) {
|
|
118
121
|
if (mode === "numbers") {
|
|
119
122
|
throw new Error("PaddleOCR 文档未提供 numbers 模式,请使用 appleocr 引擎。");
|
|
120
123
|
}
|
|
121
|
-
const loadScript = `const __loaded = paddleOcr.loadV5(${maxSideLen}, ${useGpu});`;
|
|
122
|
-
const loadFailedScript = 'let __ocrResult; if (!__loaded) { __ocrResult = { success: false, error: "PaddleOCR loadV5 failed" }; }';
|
|
123
124
|
if (mode === "findText") {
|
|
124
125
|
if (!texts || texts.length === 0) {
|
|
125
126
|
throw new Error("findText 模式必须传 texts。");
|
|
126
127
|
}
|
|
127
|
-
return
|
|
128
|
-
loadScript,
|
|
129
|
-
loadFailedScript,
|
|
130
|
-
`if (__loaded) { __ocrResult = paddleOcr.findText(${jsonLiteral(input)}, ${jsonLiteral(texts)}, ${x}, ${y}, ${ex}, ${ey}, ${confidenceThreshold}); }`,
|
|
131
|
-
"__ocrResult;",
|
|
132
|
-
].join("\n");
|
|
128
|
+
return `paddleOcr.findTextAbs(${jsonLiteral(input)}, ${jsonLiteral(texts)}, ${x}, ${y}, ${ex}, ${ey}, ${confidenceThreshold}, ${exactMatch});`;
|
|
133
129
|
}
|
|
134
|
-
return
|
|
135
|
-
loadScript,
|
|
136
|
-
loadFailedScript,
|
|
137
|
-
`if (__loaded) { __ocrResult = paddleOcr.recognize(${jsonLiteral(input)}, ${x}, ${y}, ${ex}, ${ey}, ${confidenceThreshold}); }`,
|
|
138
|
-
"__ocrResult;",
|
|
139
|
-
].join("\n");
|
|
130
|
+
return `paddleOcr.recognizeAbs(${jsonLiteral(input)}, ${x}, ${y}, ${ex}, ${ey}, ${confidenceThreshold});`;
|
|
140
131
|
}
|
|
141
132
|
/**
|
|
142
133
|
* 构建 OCR 运行脚本
|
|
@@ -150,17 +141,16 @@ function buildPaddleOcrScript(mode, input, x, y, ex, ey, texts, confidenceThresh
|
|
|
150
141
|
* @param texts 查找文本数组
|
|
151
142
|
* @param languages Apple OCR 识别语言数组
|
|
152
143
|
* @param confidenceThreshold PaddleOCR 置信度阈值
|
|
153
|
-
* @param
|
|
154
|
-
* @param paddleUseGpu PaddleOCR 是否使用 GPU
|
|
144
|
+
* @param exactMatch 是否完整匹配文本
|
|
155
145
|
* @returns 返回可交给 runScript 的 JavaScript 脚本
|
|
156
146
|
* @example
|
|
157
147
|
* buildOcrScript("appleocr", "recognize", "screen", 0, 0, 0, 0)
|
|
158
148
|
*/
|
|
159
|
-
function buildOcrScript(engine, mode, input, x, y, ex, ey, texts, languages, confidenceThreshold,
|
|
149
|
+
function buildOcrScript(engine, mode, input, x, y, ex, ey, texts, languages, confidenceThreshold, exactMatch) {
|
|
160
150
|
if (engine === "paddleocr") {
|
|
161
|
-
return buildPaddleOcrScript(mode, input, x, y, ex, ey, texts, confidenceThreshold,
|
|
151
|
+
return buildPaddleOcrScript(mode, input, x, y, ex, ey, texts, confidenceThreshold, exactMatch);
|
|
162
152
|
}
|
|
163
|
-
return buildAppleOcrScript(mode, input, x, y, ex, ey, texts, languages);
|
|
153
|
+
return buildAppleOcrScript(mode, input, x, y, ex, ey, texts, languages, exactMatch);
|
|
164
154
|
}
|
|
165
155
|
/**
|
|
166
156
|
* 调用设备 runScript 接口
|
|
@@ -242,6 +232,24 @@ async function formatOcrToolText(response, outputPath) {
|
|
|
242
232
|
responseText,
|
|
243
233
|
].join("\n");
|
|
244
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* 在指定 HTTP 设备上执行 OCR 识别
|
|
237
|
+
* @param target 设备 HTTP 地址
|
|
238
|
+
* @param options OCR 参数
|
|
239
|
+
* @returns 返回 HTTP 状态码、原始结果与格式化文本
|
|
240
|
+
* @example
|
|
241
|
+
* await runOcrRecognitionOnDevice({ ip: "192.168.1.10", port: "9800" }, options)
|
|
242
|
+
*/
|
|
243
|
+
async function runOcrRecognitionOnDevice(target, options) {
|
|
244
|
+
const script = buildOcrScript(options.engine, options.mode, options.input, options.x, options.y, options.ex, options.ey, options.texts, options.languages, options.confidenceThreshold, options.exactMatch);
|
|
245
|
+
const response = await callRunScript(target.ip, target.port, script, options.timeoutMs);
|
|
246
|
+
const text = await formatOcrToolText(response.body, options.outputPath);
|
|
247
|
+
return {
|
|
248
|
+
status: response.status,
|
|
249
|
+
body: response.body,
|
|
250
|
+
text,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
245
253
|
/**
|
|
246
254
|
* 注册 OCR MCP 工具
|
|
247
255
|
* @param server MCP 服务实例
|
|
@@ -252,7 +260,7 @@ async function formatOcrToolText(response, outputPath) {
|
|
|
252
260
|
function registerOcrTools(server) {
|
|
253
261
|
server.registerTool("ocr_recognize", {
|
|
254
262
|
title: "OCR Recognize",
|
|
255
|
-
description: "
|
|
263
|
+
description: "在当前默认设备执行 OCR。支持 appleocr 与 paddleocr,默认 appleocr;返回坐标使用绝对坐标。",
|
|
256
264
|
inputSchema: {
|
|
257
265
|
engine: z
|
|
258
266
|
.enum(["appleocr", "paddleocr"])
|
|
@@ -291,9 +299,14 @@ function registerOcrTools(server) {
|
|
|
291
299
|
.optional()
|
|
292
300
|
.describe("findText 模式要查找的文本数组"),
|
|
293
301
|
languages: z
|
|
294
|
-
.array(z.enum(APPLE_OCR_LANGUAGES))
|
|
302
|
+
.array(z.enum(exports.APPLE_OCR_LANGUAGES))
|
|
295
303
|
.optional()
|
|
296
304
|
.describe('Apple OCR 识别语言数组,默认由运行时使用 ["zh-Hans", "en-US"]'),
|
|
305
|
+
exactMatch: z
|
|
306
|
+
.boolean()
|
|
307
|
+
.optional()
|
|
308
|
+
.default(false)
|
|
309
|
+
.describe("findText 模式是否要求整条识别文本完全匹配目标文本"),
|
|
297
310
|
confidenceThreshold: z
|
|
298
311
|
.number()
|
|
299
312
|
.min(0)
|
|
@@ -301,19 +314,6 @@ function registerOcrTools(server) {
|
|
|
301
314
|
.optional()
|
|
302
315
|
.default(0.6)
|
|
303
316
|
.describe("PaddleOCR 置信度阈值,默认 0.6"),
|
|
304
|
-
paddleMaxSideLen: z
|
|
305
|
-
.number()
|
|
306
|
-
.int()
|
|
307
|
-
.min(32)
|
|
308
|
-
.max(4096)
|
|
309
|
-
.optional()
|
|
310
|
-
.default(640)
|
|
311
|
-
.describe("PaddleOCR loadV5 最大边长,默认 640"),
|
|
312
|
-
paddleUseGpu: z
|
|
313
|
-
.boolean()
|
|
314
|
-
.optional()
|
|
315
|
-
.default(false)
|
|
316
|
-
.describe("PaddleOCR loadV5 是否使用 GPU,默认 false"),
|
|
317
317
|
outputPath: z
|
|
318
318
|
.string()
|
|
319
319
|
.min(1)
|
|
@@ -328,20 +328,31 @@ function registerOcrTools(server) {
|
|
|
328
328
|
.default(60000)
|
|
329
329
|
.describe("runScript 请求超时时间,默认 60000 毫秒"),
|
|
330
330
|
},
|
|
331
|
-
}, async ({ engine, mode, input, x, y, ex, ey, texts, languages,
|
|
331
|
+
}, async ({ engine, mode, input, x, y, ex, ey, texts, languages, exactMatch, confidenceThreshold, outputPath, timeoutMs, }) => {
|
|
332
332
|
const target = await (0, tool_utils_1.resolveRuntimeHttpTarget)();
|
|
333
|
-
const
|
|
334
|
-
|
|
335
|
-
|
|
333
|
+
const response = await runOcrRecognitionOnDevice(target, {
|
|
334
|
+
engine,
|
|
335
|
+
mode,
|
|
336
|
+
input,
|
|
337
|
+
x,
|
|
338
|
+
y,
|
|
339
|
+
ex,
|
|
340
|
+
ey,
|
|
341
|
+
texts,
|
|
342
|
+
languages,
|
|
343
|
+
confidenceThreshold,
|
|
344
|
+
exactMatch,
|
|
345
|
+
outputPath,
|
|
346
|
+
timeoutMs,
|
|
347
|
+
});
|
|
336
348
|
return (0, tool_utils_1.createTextToolResult)([
|
|
337
|
-
text,
|
|
349
|
+
response.text,
|
|
338
350
|
"",
|
|
339
351
|
`device: ${target.label}`,
|
|
340
352
|
`engine: ${engine}`,
|
|
341
353
|
`mode: ${mode}`,
|
|
342
354
|
`input: ${input}`,
|
|
343
355
|
`region: x=${x}, y=${y}, ex=${ex}, ey=${ey}`,
|
|
344
|
-
`runScript: POST /api/runScript`,
|
|
345
356
|
`status: ${response.status}`,
|
|
346
357
|
].join("\n"), response.body.success === false);
|
|
347
358
|
});
|
|
@@ -185,7 +185,7 @@ function registerRuntimeTools(server) {
|
|
|
185
185
|
});
|
|
186
186
|
server.registerTool("get_node_source", {
|
|
187
187
|
title: "Get Node Source",
|
|
188
|
-
description: "获取当前默认设备页面节点 XML
|
|
188
|
+
description: "获取当前默认设备页面节点 XML,写入文件后返回路径,避免长文本响应被截断。",
|
|
189
189
|
inputSchema: {
|
|
190
190
|
maxDepth: z
|
|
191
191
|
.number()
|
|
@@ -203,20 +203,28 @@ function registerRuntimeTools(server) {
|
|
|
203
203
|
.optional()
|
|
204
204
|
.default(120)
|
|
205
205
|
.describe("设备端节点抓取超时秒数,默认 120"),
|
|
206
|
+
mode: z
|
|
207
|
+
.number()
|
|
208
|
+
.int()
|
|
209
|
+
.min(1)
|
|
210
|
+
.max(2)
|
|
211
|
+
.optional()
|
|
212
|
+
.default(1)
|
|
213
|
+
.describe("节点抓取模式:1=完整节点树,2=可见节点优化模式"),
|
|
206
214
|
outputPath: z
|
|
207
215
|
.string()
|
|
208
216
|
.min(1)
|
|
209
217
|
.optional()
|
|
210
218
|
.describe("可选输出文件路径,不传则写入系统临时目录"),
|
|
211
219
|
},
|
|
212
|
-
}, async ({ maxDepth, timeout, outputPath }) => {
|
|
220
|
+
}, async ({ maxDepth, timeout, mode, outputPath }) => {
|
|
213
221
|
const target = await (0, tool_utils_1.resolveRuntimeHttpTarget)();
|
|
214
222
|
const requestOptions = (0, tool_utils_1.createRuntimeHttpRequestOptions)(target);
|
|
215
|
-
const source = await (0, project_1.getSourceOnDevice)(requestOptions, maxDepth, timeout);
|
|
223
|
+
const source = await (0, project_1.getSourceOnDevice)(requestOptions, maxDepth, timeout, mode);
|
|
216
224
|
const targetPath = resolveOutputPath(outputPath, "ms-mcp-node-source", "xml");
|
|
217
225
|
await fsExtra.ensureDir(path.dirname(targetPath));
|
|
218
226
|
await fsExtra.writeFile(targetPath, source, "utf8");
|
|
219
|
-
return (0, tool_utils_1.createTextToolResult)(`节点获取成功: ${target.label}\nmaxDepth: ${maxDepth}\ntimeout: ${timeout}\npath: ${targetPath}\nsize: ${Buffer.byteLength(source, "utf8")} bytes`);
|
|
227
|
+
return (0, tool_utils_1.createTextToolResult)(`节点获取成功: ${target.label}\nmaxDepth: ${maxDepth}\ntimeout: ${timeout}\nmode: ${mode}\npath: ${targetPath}\nsize: ${Buffer.byteLength(source, "utf8")} bytes`);
|
|
220
228
|
});
|
|
221
229
|
server.registerTool("get_logs", {
|
|
222
230
|
title: "Get Device Logs",
|
package/dist/mcp/tool-utils.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { ApiDocsLanguage } from "./types";
|
|
2
1
|
/**
|
|
3
2
|
* MCP 文本响应内容结构
|
|
4
3
|
*/
|
|
@@ -61,14 +60,3 @@ export declare function resolveRuntimeHttpTarget(): Promise<RuntimeHttpTarget>;
|
|
|
61
60
|
* formatRuntimeJsonText({ success: true })
|
|
62
61
|
*/
|
|
63
62
|
export declare function formatRuntimeJsonText(value: unknown): string;
|
|
64
|
-
/**
|
|
65
|
-
* 格式化单条 API 文档摘要
|
|
66
|
-
* @param language 文档语言
|
|
67
|
-
* @param title 文档标题
|
|
68
|
-
* @param slug 文档 slug
|
|
69
|
-
* @param index 列表序号
|
|
70
|
-
* @returns 返回用于列表展示的文本块
|
|
71
|
-
* @example
|
|
72
|
-
* formatApiDocSummary("js", "Tap", "tap", 0)
|
|
73
|
-
*/
|
|
74
|
-
export declare function formatApiDocSummary(language: ApiDocsLanguage, title: string, slug: string, index: number): string;
|
package/dist/mcp/tool-utils.js
CHANGED
|
@@ -4,8 +4,6 @@ exports.createTextToolResult = createTextToolResult;
|
|
|
4
4
|
exports.createRuntimeHttpRequestOptions = createRuntimeHttpRequestOptions;
|
|
5
5
|
exports.resolveRuntimeHttpTarget = resolveRuntimeHttpTarget;
|
|
6
6
|
exports.formatRuntimeJsonText = formatRuntimeJsonText;
|
|
7
|
-
exports.formatApiDocSummary = formatApiDocSummary;
|
|
8
|
-
const docs_service_1 = require("./docs-service");
|
|
9
7
|
const device_config_1 = require("./device-config");
|
|
10
8
|
/**
|
|
11
9
|
* 创建标准 MCP 文本内容对象
|
|
@@ -81,16 +79,3 @@ function formatRuntimeJsonText(value) {
|
|
|
81
79
|
}
|
|
82
80
|
return JSON.stringify(value, null, 2);
|
|
83
81
|
}
|
|
84
|
-
/**
|
|
85
|
-
* 格式化单条 API 文档摘要
|
|
86
|
-
* @param language 文档语言
|
|
87
|
-
* @param title 文档标题
|
|
88
|
-
* @param slug 文档 slug
|
|
89
|
-
* @param index 列表序号
|
|
90
|
-
* @returns 返回用于列表展示的文本块
|
|
91
|
-
* @example
|
|
92
|
-
* formatApiDocSummary("js", "Tap", "tap", 0)
|
|
93
|
-
*/
|
|
94
|
-
function formatApiDocSummary(language, title, slug, index) {
|
|
95
|
-
return `${index + 1}. ${title}\nslug: ${slug}\nuri: ${(0, docs_service_1.getDocUri)(language, slug)}`;
|
|
96
|
-
}
|
package/dist/mcp/tools.js
CHANGED
|
@@ -22,7 +22,6 @@ function createMcpServer() {
|
|
|
22
22
|
name: "ms-vite-plugin-mcp",
|
|
23
23
|
version: version_1.PACKAGE_VERSION,
|
|
24
24
|
});
|
|
25
|
-
(0, doc_tools_1.registerDocResources)(server);
|
|
26
25
|
(0, doc_tools_1.registerDocTools)(server);
|
|
27
26
|
(0, httpapi_tools_1.registerHttpApiTools)(server);
|
|
28
27
|
(0, image_tools_1.registerImageTools)(server);
|
package/dist/mcp/types.d.ts
CHANGED
|
@@ -13,19 +13,6 @@ export type DeviceConfig = {
|
|
|
13
13
|
* 文档语言类型
|
|
14
14
|
*/
|
|
15
15
|
export type ApiDocsLanguage = "js" | "js_zh" | "python";
|
|
16
|
-
/**
|
|
17
|
-
* 文档条目结构
|
|
18
|
-
*/
|
|
19
|
-
export type ApiDocItem = {
|
|
20
|
-
/** 文档分类(即文件名,不含 .md) */
|
|
21
|
-
slug: string;
|
|
22
|
-
/** 文档标题(优先取首个 markdown 标题) */
|
|
23
|
-
title: string;
|
|
24
|
-
/** 文档全文 */
|
|
25
|
-
content: string;
|
|
26
|
-
/** 文档目录绝对路径 */
|
|
27
|
-
filePath: string;
|
|
28
|
-
};
|
|
29
16
|
/**
|
|
30
17
|
* 文档语言显示名映射
|
|
31
18
|
*/
|
package/dist/project.d.ts
CHANGED
|
@@ -39,11 +39,12 @@ export declare function getScreenshotBase64OnDevice(options: DeviceCliOptions):
|
|
|
39
39
|
* @param options 命令选项(transport 仅支持 http)
|
|
40
40
|
* @param maxDepth 节点最大深度,默认 50
|
|
41
41
|
* @param timeout 获取节点超时秒数,默认 120
|
|
42
|
+
* @param mode 节点抓取模式,1=完整节点树,2=可见节点优化模式
|
|
42
43
|
* @returns 返回 XML 字符串
|
|
43
44
|
* @example
|
|
44
|
-
* const xml = await getSourceOnDevice({ ip: "192.168.1.10", port: "9800" }, 50, 120)
|
|
45
|
+
* const xml = await getSourceOnDevice({ ip: "192.168.1.10", port: "9800" }, 50, 120, 1)
|
|
45
46
|
*/
|
|
46
|
-
export declare function getSourceOnDevice(options: DeviceCliOptions, maxDepth?: number, timeout?: number): Promise<string>;
|
|
47
|
+
export declare function getSourceOnDevice(options: DeviceCliOptions, maxDepth?: number, timeout?: number, mode?: number): Promise<string>;
|
|
47
48
|
/**
|
|
48
49
|
* 在设备上获取当前日志文件最新行
|
|
49
50
|
* @param options 命令选项(仅支持 http 传输)
|
package/dist/project.js
CHANGED
|
@@ -428,11 +428,12 @@ async function getScreenshotBase64OnDevice(options) {
|
|
|
428
428
|
* @param options 命令选项(transport 仅支持 http)
|
|
429
429
|
* @param maxDepth 节点最大深度,默认 50
|
|
430
430
|
* @param timeout 获取节点超时秒数,默认 120
|
|
431
|
+
* @param mode 节点抓取模式,1=完整节点树,2=可见节点优化模式
|
|
431
432
|
* @returns 返回 XML 字符串
|
|
432
433
|
* @example
|
|
433
|
-
* const xml = await getSourceOnDevice({ ip: "192.168.1.10", port: "9800" }, 50, 120)
|
|
434
|
+
* const xml = await getSourceOnDevice({ ip: "192.168.1.10", port: "9800" }, 50, 120, 1)
|
|
434
435
|
*/
|
|
435
|
-
async function getSourceOnDevice(options, maxDepth = 50, timeout = 120) {
|
|
436
|
+
async function getSourceOnDevice(options, maxDepth = 50, timeout = 120, mode = 1) {
|
|
436
437
|
const transport = parseTransport(options);
|
|
437
438
|
if (!Number.isInteger(maxDepth) || maxDepth < 1) {
|
|
438
439
|
throw new Error(`无效 maxDepth: ${maxDepth}`);
|
|
@@ -440,12 +441,16 @@ async function getSourceOnDevice(options, maxDepth = 50, timeout = 120) {
|
|
|
440
441
|
if (!Number.isInteger(timeout) || timeout < 1) {
|
|
441
442
|
throw new Error(`无效 timeout: ${timeout}`);
|
|
442
443
|
}
|
|
444
|
+
if (!Number.isInteger(mode) || (mode !== 1 && mode !== 2)) {
|
|
445
|
+
throw new Error(`无效 mode: ${mode}`);
|
|
446
|
+
}
|
|
443
447
|
if (transport === "ws") {
|
|
444
448
|
await ensureWsReady(options);
|
|
445
449
|
const result = await ws_manager_1.WSManager.request("source", {
|
|
446
450
|
max_depth: maxDepth,
|
|
447
451
|
timeout,
|
|
448
452
|
maxDepth,
|
|
453
|
+
mode,
|
|
449
454
|
});
|
|
450
455
|
if (!result.success || typeof result.data !== "string") {
|
|
451
456
|
throw new Error(`获取节点失败: ${String(result.message ?? "unknown")}`);
|
|
@@ -456,6 +461,7 @@ async function getSourceOnDevice(options, maxDepth = 50, timeout = 120) {
|
|
|
456
461
|
const url = new URL(`http://${ip}:${port}/api/source`);
|
|
457
462
|
url.searchParams.set("max_depth", String(maxDepth));
|
|
458
463
|
url.searchParams.set("timeout", String(timeout));
|
|
464
|
+
url.searchParams.set("mode", String(mode));
|
|
459
465
|
const response = await fetch(url.toString(), { method: "GET" });
|
|
460
466
|
if (!response.ok) {
|
|
461
467
|
throw new Error(`获取节点失败,状态码: ${response.status}`);
|
package/docs/AGENTS.md
CHANGED
|
@@ -36,45 +36,44 @@
|
|
|
36
36
|
|
|
37
37
|
## 文档优先
|
|
38
38
|
|
|
39
|
-
回答快点JS API
|
|
39
|
+
回答快点JS API 问题或编写脚本前,必须先获取本地文档路径并直接读取目标语言对应的 markdown 文件。文档随 `ms-vite-plugin` npm 包发布,路径一定存在,不需要额外的文档查询或读取 API。
|
|
40
40
|
|
|
41
|
-
MCP
|
|
41
|
+
MCP 入口:
|
|
42
42
|
|
|
43
|
-
1. 使用 `
|
|
44
|
-
2.
|
|
45
|
-
3.
|
|
46
|
-
4. 只依据已确认的文档内容回答或编写代码。
|
|
43
|
+
1. 使用 `get_docs_paths` 获取本地文档根目录、语言 API 文档目录和 HTTP API 文档路径。
|
|
44
|
+
2. 直接读取对应 markdown 文件。
|
|
45
|
+
3. 只依据已读取的本地文档内容回答或编写代码。
|
|
47
46
|
|
|
48
|
-
|
|
47
|
+
CLI 入口:
|
|
49
48
|
|
|
50
|
-
1.
|
|
51
|
-
2.
|
|
52
|
-
3.
|
|
49
|
+
1. 使用 `npx ms docs paths` 获取同一组本地文档路径。
|
|
50
|
+
2. 直接读取对应 markdown 文件。
|
|
51
|
+
3. 只使用文档中已经确认的 API。
|
|
53
52
|
|
|
54
53
|
## HTTP API 工作流
|
|
55
54
|
|
|
56
|
-
调用设备 HTTP API
|
|
55
|
+
调用设备 HTTP API 前,必须先直接读取 HTTP API 文档。不要猜测接口路径、请求方法或参数名称。
|
|
57
56
|
|
|
58
|
-
MCP
|
|
57
|
+
MCP 入口:
|
|
59
58
|
|
|
60
|
-
1. 使用 `
|
|
61
|
-
2.
|
|
62
|
-
3.
|
|
63
|
-
4. 使用 `http_api_call` 传入文档返回的 `docSlug`、`method`、`path`、`query` 或 `body`。
|
|
59
|
+
1. 使用 `get_docs_paths` 获取 HTTP API 文档路径。
|
|
60
|
+
2. 直接读取 HTTP API markdown,确认 `method`、`path`、参数位置、参数类型和返回结构。
|
|
61
|
+
3. 使用 `http_api_call` 传入 `method`、`path`、`query` 或 `body`。
|
|
64
62
|
|
|
65
|
-
`http_api_call` 只能调用 HTTP API
|
|
63
|
+
`http_api_call` 只能调用 HTTP API 文档中已声明的 `method` 和 `path`。
|
|
66
64
|
|
|
67
|
-
|
|
65
|
+
CLI 入口:
|
|
68
66
|
|
|
69
|
-
1.
|
|
70
|
-
2.
|
|
71
|
-
3.
|
|
67
|
+
1. 使用 `npx ms docs paths` 获取 HTTP API 文档路径。
|
|
68
|
+
2. 直接读取 HTTP API markdown,确认接口存在和参数要求。
|
|
69
|
+
3. 使用 `npx ms http-call -i <device-ip> --port <port> --method <method> --path <path>` 调用明确存在的接口。
|
|
70
|
+
4. 不要把未确认的路径当成可用接口。
|
|
72
71
|
|
|
73
72
|
## 设备与运行
|
|
74
73
|
|
|
75
74
|
设备相关操作以用户指定的设备为准。不要假设设备或工作区已经设置。
|
|
76
75
|
|
|
77
|
-
MCP
|
|
76
|
+
MCP 入口:
|
|
78
77
|
|
|
79
78
|
1. 使用 `get_device` 查看当前默认设备。
|
|
80
79
|
2. 如果未设置设备,使用 `set_device` 设置设备 IP 和端口。
|
|
@@ -84,30 +83,33 @@ MCP 可用时:
|
|
|
84
83
|
6. 使用 `stop_project` 停止当前设备上的项目。
|
|
85
84
|
7. 使用 `package_project` 执行生产打包。
|
|
86
85
|
|
|
87
|
-
|
|
86
|
+
CLI 入口可以使用:
|
|
88
87
|
|
|
89
88
|
```bash
|
|
90
89
|
npx ms --help
|
|
90
|
+
npx ms docs paths
|
|
91
|
+
npx ms http-call -i <device-ip> --port <port> --method GET --path <path>
|
|
91
92
|
npx ms run -i <device-ip> --port <port>
|
|
92
93
|
npx ms run-ui -i <device-ip> --port <port>
|
|
93
94
|
npx ms screenshot -i <device-ip> --port <port> --format file --output <path>
|
|
95
|
+
npx ms source -i <device-ip> --port <port> --mode 1 --output <path>
|
|
96
|
+
npx ms logs -i <device-ip> --port <port> --limit 200
|
|
97
|
+
npx ms ocr -i <device-ip> --port <port> --engine appleocr --mode recognize
|
|
98
|
+
npx ms screen-crop -i <device-ip> --port <port> --x <x> --y <y> --width <w> --height <h> --output <path>
|
|
99
|
+
npx ms screen-pick-color -i <device-ip> --port <port> --x <x> --y <y>
|
|
100
|
+
npx ms image-crop --image <path> --x <x> --y <y> --width <w> --height <h> --output <path>
|
|
101
|
+
npx ms image-transparent --image <path> --output <path>
|
|
94
102
|
npx ms stop -i <device-ip> --port <port>
|
|
95
103
|
npx ms package
|
|
96
104
|
```
|
|
97
105
|
|
|
98
|
-
|
|
106
|
+
`build`、`package`、`run`、`run-ui` 需要在快点JS项目根目录运行,项目根目录通常包含 `package.json` 和 `scripts/`。文档路径、HTTP API 调用、截图、节点、日志、OCR、图片处理、停止和 WS 状态命令可以在任意目录使用。不要用未确认的通用 Node.js、浏览器或 Python 命令替代 MCP 或项目自带 `ms` CLI。
|
|
99
107
|
|
|
100
108
|
## 工具分组
|
|
101
109
|
|
|
102
110
|
### 文档
|
|
103
111
|
|
|
104
|
-
- `
|
|
105
|
-
- `get_docs_language`
|
|
106
|
-
- `list_api_docs`
|
|
107
|
-
- `search_api_docs`
|
|
108
|
-
- `read_api_doc`
|
|
109
|
-
- `search_http_api_docs`
|
|
110
|
-
- `read_http_api_doc`
|
|
112
|
+
- `get_docs_paths`
|
|
111
113
|
|
|
112
114
|
### 工作区与运行
|
|
113
115
|
|
|
@@ -136,33 +138,33 @@ npx ms package
|
|
|
136
138
|
|
|
137
139
|
- `http_api_call`
|
|
138
140
|
|
|
139
|
-
控制、HID、IME、镜像、配置、当前应用、运行脚本等普通设备 HTTP API 通过 `
|
|
141
|
+
控制、HID、IME、镜像、配置、当前应用、运行脚本等普通设备 HTTP API 通过 `get_docs_paths` 和 `http_api_call` 使用,不要恢复为大量独立工具。
|
|
140
142
|
|
|
141
143
|
## 工具选择规则
|
|
142
144
|
|
|
143
|
-
- 写快点JS
|
|
144
|
-
- 调设备 HTTP API
|
|
145
|
-
-
|
|
146
|
-
- 获取节点 XML
|
|
147
|
-
-
|
|
148
|
-
- 从本地图片裁切找图模板:使用 `image_crop`,输出到 `res`。
|
|
149
|
-
- 从当前设备截图裁切找图模板:使用 `screen_crop`,输出到 `res`。
|
|
150
|
-
- 从本地图片指定坐标取色:使用 `image_pick_color`。
|
|
151
|
-
- 从当前设备截图指定坐标取色:使用 `screen_pick_color`。
|
|
152
|
-
- 制作透明找图模板:使用 `image_make_transparent`,输出到 `res`。
|
|
153
|
-
- 执行 OCR 识别、数字识别或查找文字:使用 `ocr_recognize`。
|
|
154
|
-
-
|
|
155
|
-
-
|
|
156
|
-
-
|
|
145
|
+
- 写快点JS脚本代码:先确认项目语言,再读取本地语言 API 文档。
|
|
146
|
+
- 调设备 HTTP API:先读取本地 HTTP API 文档,再调用 `http_api_call` 或 `npx ms http-call`。
|
|
147
|
+
- 获取截图:使用 `take_screenshot` 或 `npx ms screenshot`。
|
|
148
|
+
- 获取节点 XML:使用 `get_node_source` 或 `npx ms source --mode 1`。
|
|
149
|
+
- 查看日志:使用 `get_logs` 或 `npx ms logs`。
|
|
150
|
+
- 从本地图片裁切找图模板:使用 `image_crop` 或 `npx ms image-crop`,输出到 `res`。
|
|
151
|
+
- 从当前设备截图裁切找图模板:使用 `screen_crop` 或 `npx ms screen-crop`,输出到 `res`。
|
|
152
|
+
- 从本地图片指定坐标取色:使用 `image_pick_color` 或 `npx ms image-pick-color`。
|
|
153
|
+
- 从当前设备截图指定坐标取色:使用 `screen_pick_color` 或 `npx ms screen-pick-color`。
|
|
154
|
+
- 制作透明找图模板:使用 `image_make_transparent` 或 `npx ms image-transparent`,输出到 `res`。
|
|
155
|
+
- 执行 OCR 识别、数字识别或查找文字:使用 `ocr_recognize` 或 `npx ms ocr`。
|
|
156
|
+
- 运行项目:使用 `run_project`、`run_ui_project`、`npx ms run` 或 `npx ms run-ui`。
|
|
157
|
+
- 停止项目:使用 `stop_project` 或 `npx ms stop`。
|
|
158
|
+
- 打包项目:使用 `package_project` 或 `npx ms package`。
|
|
157
159
|
|
|
158
160
|
## OCR 规则
|
|
159
161
|
|
|
160
|
-
OCR
|
|
162
|
+
OCR 识别使用 `ocr_recognize`,不要手写未确认的 OCR 调用链路。
|
|
161
163
|
|
|
162
164
|
- `ocr_recognize` 支持 `appleocr` 和 `paddleocr`。
|
|
163
165
|
- 默认使用 `appleocr`。
|
|
164
|
-
- 数字识别优先使用 `appleocr
|
|
165
|
-
-
|
|
166
|
+
- 数字识别优先使用 `appleocr`。
|
|
167
|
+
- PaddleOCR 识别和查找方法会自动加载所需模型,不需要先手动调用 `loadV5`。
|
|
166
168
|
|
|
167
169
|
## 验证要求
|
|
168
170
|
|
|
@@ -170,7 +172,7 @@ OCR 没有独立 HTTP 接口,使用 `ocr_recognize` 通过 `POST /api/runScrip
|
|
|
170
172
|
|
|
171
173
|
1. 使用 MCP `run_project` 或命令 `npx ms run -i <device-ip> --port <port>` 同步并运行项目。
|
|
172
174
|
2. 使用 MCP `take_screenshot` 或命令 `npx ms screenshot ...` 获取截图。
|
|
173
|
-
3. 必要时使用 `get_logs`
|
|
175
|
+
3. 必要时使用 `get_logs` 或命令 `npx ms logs` 查看运行日志。
|
|
174
176
|
4. 在回复中说明截图或日志是否确认了预期行为。
|
|
175
177
|
|
|
176
178
|
UI 预览发起后不需要长时间等待结果,可以通过截图查看当前界面效果。
|
|
@@ -179,12 +181,12 @@ UI 预览发起后不需要长时间等待结果,可以通过截图查看当
|
|
|
179
181
|
|
|
180
182
|
## 禁止事项
|
|
181
183
|
|
|
182
|
-
-
|
|
184
|
+
- 不要在没有读取本地文档的情况下回答 API 用法或编写 API 调用代码。
|
|
183
185
|
- 不要臆造快点JS API、对象、参数、返回值或运行机制。
|
|
184
186
|
- 不要混用 JavaScript 与 Python API。
|
|
185
187
|
- 不要把快点JS当成普通 Node.js、浏览器或通用 Python 环境。
|
|
186
188
|
- 不要对快点JS Python 脚本运行 `py_compile` 或其他 CPython 编译校验。
|
|
187
|
-
-
|
|
189
|
+
- 不要在没有读取本地 HTTP API 文档的情况下调用 `http_api_call` 或 `ms http-call`。
|
|
188
190
|
- 不要把完整 URL 传给 `http_api_call.path`,只能传 `/api/...`、`/logger/...`、`/mirror/...` 这类相对路径。
|
|
189
191
|
- 不要调用 HTTP API 文档中未声明的接口。
|
|
190
192
|
- 不要用 `http_api_call` 替代截图落文件、节点 XML 落文件、日志缓存、项目打包和项目运行等专用工具。
|