ms-vite-plugin 1.4.47 → 1.4.49
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 +1 -292
- package/dist/cli.js +6 -1234
- package/dist/mcp/device-config.d.ts +0 -47
- package/dist/mcp/device-config.js +1 -183
- package/dist/mcp/device-log.d.ts +0 -8
- package/dist/mcp/device-log.js +3 -27
- package/dist/mcp/doc-tools.d.ts +0 -7
- package/dist/mcp/doc-tools.js +2 -39
- package/dist/mcp/docs-service.d.ts +0 -13
- package/dist/mcp/docs-service.js +1 -63
- package/dist/mcp/httpapi-docs-service.d.ts +0 -31
- package/dist/mcp/httpapi-docs-service.js +1 -122
- package/dist/mcp/httpapi-tools.d.ts +0 -7
- package/dist/mcp/httpapi-tools.js +4 -222
- package/dist/mcp/image-tools.d.ts +0 -62
- package/dist/mcp/image-tools.js +8 -607
- package/dist/mcp/ocr-tools.d.ts +0 -25
- package/dist/mcp/ocr-tools.js +5 -413
- package/dist/mcp/project.d.ts +0 -14
- package/dist/mcp/project.js +1 -74
- package/dist/mcp/runtime-tools.d.ts +0 -7
- package/dist/mcp/runtime-tools.js +11 -308
- package/dist/mcp/tool-utils.d.ts +0 -40
- package/dist/mcp/tool-utils.js +1 -81
- package/dist/mcp/tools.d.ts +0 -12
- package/dist/mcp/tools.js +1 -31
- package/dist/mcp/types.d.ts +0 -12
- package/dist/mcp/types.js +1 -11
- package/dist/mcp-server.js +1 -85
- package/dist/packager.d.ts +0 -7
- package/dist/packager.js +1 -125
- package/dist/project.d.ts +0 -61
- package/dist/project.js +1 -619
- package/dist/stopGuardPlugin.d.ts +0 -6
- package/dist/stopGuardPlugin.js +1 -165
- package/dist/version.d.ts +0 -10
- package/dist/version.js +1 -63
- package/dist/ws-manager.d.ts +0 -95
- package/dist/ws-manager.js +1 -392
- package/docs/api/image.md +249 -25
- package/docs/apicn/image.md +245 -19
- package/docs/apipython/image.md +238 -18
- package/package.json +3 -2
package/dist/mcp/ocr-tools.js
CHANGED
|
@@ -1,413 +1,5 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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.APPLE_OCR_LANGUAGES = exports.PADDLE_OCR_DEFAULT_MAX_SIDE_LEN = exports.PADDLE_OCR_MODELS = void 0;
|
|
37
|
-
exports.formatOcrToolText = formatOcrToolText;
|
|
38
|
-
exports.runOcrRecognitionOnDevice = runOcrRecognitionOnDevice;
|
|
39
|
-
exports.registerOcrTools = registerOcrTools;
|
|
40
|
-
const fsExtra = __importStar(require("fs-extra"));
|
|
41
|
-
const os = __importStar(require("os"));
|
|
42
|
-
const path = __importStar(require("path"));
|
|
43
|
-
const z = __importStar(require("zod/v4"));
|
|
44
|
-
const tool_utils_1 = require("./tool-utils");
|
|
45
|
-
/** PaddleOCR 内置可切换模型 ID;同一时间只保留一个 active 模型。 */
|
|
46
|
-
exports.PADDLE_OCR_MODELS = [
|
|
47
|
-
"ppocr-v6-tiny",
|
|
48
|
-
"ppocr-v6-small",
|
|
49
|
-
"ppocr-v5",
|
|
50
|
-
];
|
|
51
|
-
/** PaddleOCR 检测阶段默认最大边长,与运行时一致;传 0 或负数时回落到该值。 */
|
|
52
|
-
exports.PADDLE_OCR_DEFAULT_MAX_SIDE_LEN = 768;
|
|
53
|
-
exports.APPLE_OCR_LANGUAGES = [
|
|
54
|
-
"en-US",
|
|
55
|
-
"fr-FR",
|
|
56
|
-
"it-IT",
|
|
57
|
-
"de-DE",
|
|
58
|
-
"es-ES",
|
|
59
|
-
"pt-BR",
|
|
60
|
-
"zh-Hans",
|
|
61
|
-
"zh-Hant",
|
|
62
|
-
];
|
|
63
|
-
/**
|
|
64
|
-
* 生成安全的 JavaScript 字面量
|
|
65
|
-
* @param value 任意 JSON 兼容值
|
|
66
|
-
* @returns 返回可嵌入脚本的 JSON 字面量
|
|
67
|
-
* @example
|
|
68
|
-
* jsonLiteral(["zh-Hans", "en-US"])
|
|
69
|
-
*/
|
|
70
|
-
function jsonLiteral(value) {
|
|
71
|
-
return JSON.stringify(value);
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* 解析 OCR 输出文件路径
|
|
75
|
-
* @param outputPath 用户指定的可选路径
|
|
76
|
-
* @returns 返回最终输出文件绝对路径
|
|
77
|
-
* @example
|
|
78
|
-
* resolveOcrOutputPath(undefined)
|
|
79
|
-
*/
|
|
80
|
-
function resolveOcrOutputPath(outputPath) {
|
|
81
|
-
if (outputPath && outputPath.trim()) {
|
|
82
|
-
return path.resolve(outputPath.trim());
|
|
83
|
-
}
|
|
84
|
-
return path.join(os.tmpdir(), `ms-mcp-ocr-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.json`);
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* 构建 Apple OCR 运行脚本
|
|
88
|
-
* @param mode OCR 模式
|
|
89
|
-
* @param input 输入源
|
|
90
|
-
* @param x 区域左上角 x
|
|
91
|
-
* @param y 区域左上角 y
|
|
92
|
-
* @param ex 区域右下角 x
|
|
93
|
-
* @param ey 区域右下角 y
|
|
94
|
-
* @param texts 查找文本数组
|
|
95
|
-
* @param languages 识别语言数组
|
|
96
|
-
* @param exactMatch 是否完整匹配文本
|
|
97
|
-
* @returns 返回可交给 runScript 的 JavaScript 脚本
|
|
98
|
-
* @example
|
|
99
|
-
* buildAppleOcrScript("recognize", "screen", 0, 0, 0, 0)
|
|
100
|
-
*/
|
|
101
|
-
function buildAppleOcrScript(mode, input, x, y, ex, ey, texts, languages, exactMatch = false) {
|
|
102
|
-
if (mode === "findText") {
|
|
103
|
-
if (!texts || texts.length === 0) {
|
|
104
|
-
throw new Error("findText 模式必须传 texts。");
|
|
105
|
-
}
|
|
106
|
-
return `appleOcr.findTextAbs(${jsonLiteral(input)}, ${jsonLiteral(texts)}, ${x}, ${y}, ${ex}, ${ey}, ${jsonLiteral(languages)}, ${exactMatch});`;
|
|
107
|
-
}
|
|
108
|
-
if (mode === "numbers") {
|
|
109
|
-
return `appleOcr.recognizeNumbersAbs(${jsonLiteral(input)}, ${x}, ${y}, ${ex}, ${ey});`;
|
|
110
|
-
}
|
|
111
|
-
return `appleOcr.recognizeAbs(${jsonLiteral(input)}, ${x}, ${y}, ${ex}, ${ey}, ${jsonLiteral(languages)});`;
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* 构建 Paddle OCR 运行脚本
|
|
115
|
-
* @param mode OCR 模式
|
|
116
|
-
* @param input 输入源
|
|
117
|
-
* @param x 区域左上角 x
|
|
118
|
-
* @param y 区域左上角 y
|
|
119
|
-
* @param ex 区域右下角 x
|
|
120
|
-
* @param ey 区域右下角 y
|
|
121
|
-
* @param texts 查找文本数组
|
|
122
|
-
* @param confidenceThreshold 置信度阈值
|
|
123
|
-
* @param exactMatch 是否完整匹配文本
|
|
124
|
-
* @param paddleModel 可选切换的 PaddleOCR 模型 ID
|
|
125
|
-
* @param maxSideLen 可选检测阶段最大边长
|
|
126
|
-
* @param useGpu loadModel 时是否启用 GPU
|
|
127
|
-
* @returns 返回可交给 runScript 的 JavaScript 脚本
|
|
128
|
-
* @example
|
|
129
|
-
* buildPaddleOcrScript("recognize", "screen", 0, 0, 0, 0, undefined, 0.6, false)
|
|
130
|
-
*/
|
|
131
|
-
function buildPaddleOcrScript(mode, input, x, y, ex, ey, texts, confidenceThreshold, exactMatch, paddleModel, maxSideLen, useGpu) {
|
|
132
|
-
if (mode === "numbers") {
|
|
133
|
-
throw new Error("PaddleOCR 文档未提供 numbers 模式,请使用 appleocr 引擎。");
|
|
134
|
-
}
|
|
135
|
-
// 先设置检测长边,再切换模型;loadModel 会沿用当前长边加载目标模型。
|
|
136
|
-
const setup = [];
|
|
137
|
-
if (maxSideLen !== undefined) {
|
|
138
|
-
setup.push(`paddleOcr.setMaxSideLen(${maxSideLen});`);
|
|
139
|
-
}
|
|
140
|
-
if (paddleModel) {
|
|
141
|
-
setup.push(`paddleOcr.loadModel(${jsonLiteral(paddleModel)}, ${useGpu ?? false});`);
|
|
142
|
-
}
|
|
143
|
-
let call;
|
|
144
|
-
if (mode === "findText") {
|
|
145
|
-
if (!texts || texts.length === 0) {
|
|
146
|
-
throw new Error("findText 模式必须传 texts。");
|
|
147
|
-
}
|
|
148
|
-
call = `paddleOcr.findTextAbs(${jsonLiteral(input)}, ${jsonLiteral(texts)}, ${x}, ${y}, ${ex}, ${ey}, ${confidenceThreshold}, ${exactMatch});`;
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
call = `paddleOcr.recognizeAbs(${jsonLiteral(input)}, ${x}, ${y}, ${ex}, ${ey}, ${confidenceThreshold});`;
|
|
152
|
-
}
|
|
153
|
-
return [...setup, call].join("\n");
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* 构建 OCR 运行脚本
|
|
157
|
-
* @param engine OCR 引擎
|
|
158
|
-
* @param mode OCR 模式
|
|
159
|
-
* @param input 输入源
|
|
160
|
-
* @param x 区域左上角 x
|
|
161
|
-
* @param y 区域左上角 y
|
|
162
|
-
* @param ex 区域右下角 x
|
|
163
|
-
* @param ey 区域右下角 y
|
|
164
|
-
* @param texts 查找文本数组
|
|
165
|
-
* @param languages Apple OCR 识别语言数组
|
|
166
|
-
* @param confidenceThreshold PaddleOCR 置信度阈值
|
|
167
|
-
* @param exactMatch 是否完整匹配文本
|
|
168
|
-
* @param paddleModel 可选切换的 PaddleOCR 模型 ID
|
|
169
|
-
* @param maxSideLen 可选 PaddleOCR 检测阶段最大边长
|
|
170
|
-
* @param useGpu PaddleOCR loadModel 时是否启用 GPU
|
|
171
|
-
* @returns 返回可交给 runScript 的 JavaScript 脚本
|
|
172
|
-
* @example
|
|
173
|
-
* buildOcrScript("appleocr", "recognize", "screen", 0, 0, 0, 0)
|
|
174
|
-
*/
|
|
175
|
-
function buildOcrScript(engine, mode, input, x, y, ex, ey, texts, languages, confidenceThreshold, exactMatch, paddleModel, maxSideLen, useGpu) {
|
|
176
|
-
if (engine === "paddleocr") {
|
|
177
|
-
return buildPaddleOcrScript(mode, input, x, y, ex, ey, texts, confidenceThreshold, exactMatch, paddleModel, maxSideLen, useGpu);
|
|
178
|
-
}
|
|
179
|
-
if (paddleModel !== undefined ||
|
|
180
|
-
maxSideLen !== undefined ||
|
|
181
|
-
useGpu !== undefined) {
|
|
182
|
-
throw new Error("paddleModel / maxSideLen / useGpu 仅适用于 paddleocr 引擎。");
|
|
183
|
-
}
|
|
184
|
-
return buildAppleOcrScript(mode, input, x, y, ex, ey, texts, languages, exactMatch);
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* 调用设备 runScript 接口
|
|
188
|
-
* @param ip 设备 IP
|
|
189
|
-
* @param port 设备端口
|
|
190
|
-
* @param script JavaScript 脚本文本
|
|
191
|
-
* @param timeoutMs 超时时间
|
|
192
|
-
* @returns 返回 runScript 的 JSON 响应
|
|
193
|
-
* @example
|
|
194
|
-
* await callRunScript("192.168.1.10", "9800", "1 + 1;", 30000)
|
|
195
|
-
*/
|
|
196
|
-
async function callRunScript(ip, port, script, timeoutMs) {
|
|
197
|
-
const controller = new AbortController();
|
|
198
|
-
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
199
|
-
try {
|
|
200
|
-
const response = await fetch(`http://${ip}:${port}/api/runScript`, {
|
|
201
|
-
method: "POST",
|
|
202
|
-
signal: controller.signal,
|
|
203
|
-
headers: {
|
|
204
|
-
"Content-Type": "application/json",
|
|
205
|
-
},
|
|
206
|
-
body: JSON.stringify({ script }),
|
|
207
|
-
});
|
|
208
|
-
const text = await response.text();
|
|
209
|
-
let body;
|
|
210
|
-
try {
|
|
211
|
-
body = JSON.parse(text);
|
|
212
|
-
}
|
|
213
|
-
catch {
|
|
214
|
-
throw new Error(`runScript 响应不是有效 JSON: ${text}`);
|
|
215
|
-
}
|
|
216
|
-
if (!response.ok) {
|
|
217
|
-
throw new Error(`runScript HTTP ${response.status}: ${text}`);
|
|
218
|
-
}
|
|
219
|
-
return {
|
|
220
|
-
status: response.status,
|
|
221
|
-
body,
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
catch (error) {
|
|
225
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
226
|
-
throw new Error(`runScript 请求超时: ${timeoutMs}ms`);
|
|
227
|
-
}
|
|
228
|
-
throw error;
|
|
229
|
-
}
|
|
230
|
-
finally {
|
|
231
|
-
clearTimeout(timeout);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* 格式化 OCR 工具结果
|
|
236
|
-
* @param response runScript 响应
|
|
237
|
-
* @param outputPath 可选输出文件路径
|
|
238
|
-
* @returns 返回 MCP 文本内容
|
|
239
|
-
* @example
|
|
240
|
-
* await formatOcrToolText({ success: true, result: [] })
|
|
241
|
-
*/
|
|
242
|
-
async function formatOcrToolText(response, outputPath) {
|
|
243
|
-
const resultCount = Array.isArray(response.result)
|
|
244
|
-
? response.result.length
|
|
245
|
-
: undefined;
|
|
246
|
-
const responseText = (0, tool_utils_1.formatRuntimeJsonText)(response);
|
|
247
|
-
if (outputPath || responseText.length > 12000) {
|
|
248
|
-
const targetPath = resolveOcrOutputPath(outputPath);
|
|
249
|
-
await fsExtra.ensureDir(path.dirname(targetPath));
|
|
250
|
-
await fsExtra.writeJson(targetPath, response, { spaces: 2 });
|
|
251
|
-
return [
|
|
252
|
-
"OCR 执行成功",
|
|
253
|
-
...(resultCount === undefined ? [] : [`resultCount: ${resultCount}`]),
|
|
254
|
-
`resultType: ${response.resultType ?? "unknown"}`,
|
|
255
|
-
`output: ${targetPath}`,
|
|
256
|
-
].join("\n");
|
|
257
|
-
}
|
|
258
|
-
return [
|
|
259
|
-
"OCR 执行成功",
|
|
260
|
-
...(resultCount === undefined ? [] : [`resultCount: ${resultCount}`]),
|
|
261
|
-
`resultType: ${response.resultType ?? "unknown"}`,
|
|
262
|
-
"",
|
|
263
|
-
responseText,
|
|
264
|
-
].join("\n");
|
|
265
|
-
}
|
|
266
|
-
/**
|
|
267
|
-
* 在指定 HTTP 设备上执行 OCR 识别
|
|
268
|
-
* @param target 设备 HTTP 地址
|
|
269
|
-
* @param options OCR 参数
|
|
270
|
-
* @returns 返回 HTTP 状态码、原始结果与格式化文本
|
|
271
|
-
* @example
|
|
272
|
-
* await runOcrRecognitionOnDevice({ ip: "192.168.1.10", port: "9800" }, options)
|
|
273
|
-
*/
|
|
274
|
-
async function runOcrRecognitionOnDevice(target, options) {
|
|
275
|
-
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, options.paddleModel, options.maxSideLen, options.useGpu);
|
|
276
|
-
const response = await callRunScript(target.ip, target.port, script, options.timeoutMs);
|
|
277
|
-
const text = await formatOcrToolText(response.body, options.outputPath);
|
|
278
|
-
return {
|
|
279
|
-
status: response.status,
|
|
280
|
-
body: response.body,
|
|
281
|
-
text,
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* 注册 OCR MCP 工具
|
|
286
|
-
* @param server MCP 服务实例
|
|
287
|
-
* @returns 无返回值
|
|
288
|
-
* @example
|
|
289
|
-
* registerOcrTools(server)
|
|
290
|
-
*/
|
|
291
|
-
function registerOcrTools(server) {
|
|
292
|
-
server.registerTool("ocr_recognize", {
|
|
293
|
-
title: "OCR Recognize",
|
|
294
|
-
description: "在当前默认设备执行 OCR。支持 appleocr 与 paddleocr,默认 appleocr;返回坐标使用绝对坐标。",
|
|
295
|
-
inputSchema: {
|
|
296
|
-
engine: z
|
|
297
|
-
.enum(["appleocr", "paddleocr"])
|
|
298
|
-
.optional()
|
|
299
|
-
.default("appleocr")
|
|
300
|
-
.describe("OCR 引擎:appleocr=Apple Vision,paddleocr=PaddleOCR"),
|
|
301
|
-
mode: z
|
|
302
|
-
.enum(["recognize", "numbers", "findText"])
|
|
303
|
-
.optional()
|
|
304
|
-
.default("recognize")
|
|
305
|
-
.describe("OCR 模式:recognize=识别文本,numbers=识别数字,findText=查找文本"),
|
|
306
|
-
input: z
|
|
307
|
-
.string()
|
|
308
|
-
.min(1)
|
|
309
|
-
.optional()
|
|
310
|
-
.default("screen")
|
|
311
|
-
.describe('输入源,默认 "screen",也可传图片路径、URL 或 imageId'),
|
|
312
|
-
x: z.number().int().min(0).optional().default(0).describe("区域左上角 x"),
|
|
313
|
-
y: z.number().int().min(0).optional().default(0).describe("区域左上角 y"),
|
|
314
|
-
ex: z
|
|
315
|
-
.number()
|
|
316
|
-
.int()
|
|
317
|
-
.min(0)
|
|
318
|
-
.optional()
|
|
319
|
-
.default(0)
|
|
320
|
-
.describe("区域右下角 x;全屏可传 0"),
|
|
321
|
-
ey: z
|
|
322
|
-
.number()
|
|
323
|
-
.int()
|
|
324
|
-
.min(0)
|
|
325
|
-
.optional()
|
|
326
|
-
.default(0)
|
|
327
|
-
.describe("区域右下角 y;全屏可传 0"),
|
|
328
|
-
texts: z
|
|
329
|
-
.array(z.string().min(1))
|
|
330
|
-
.optional()
|
|
331
|
-
.describe("findText 模式要查找的文本数组"),
|
|
332
|
-
languages: z
|
|
333
|
-
.array(z.enum(exports.APPLE_OCR_LANGUAGES))
|
|
334
|
-
.optional()
|
|
335
|
-
.describe('Apple OCR 识别语言数组,默认由运行时使用 ["zh-Hans", "en-US"]'),
|
|
336
|
-
exactMatch: z
|
|
337
|
-
.boolean()
|
|
338
|
-
.optional()
|
|
339
|
-
.default(false)
|
|
340
|
-
.describe("findText 模式是否要求整条识别文本完全匹配目标文本"),
|
|
341
|
-
confidenceThreshold: z
|
|
342
|
-
.number()
|
|
343
|
-
.min(0)
|
|
344
|
-
.max(1)
|
|
345
|
-
.optional()
|
|
346
|
-
.default(0.6)
|
|
347
|
-
.describe("PaddleOCR 置信度阈值,默认 0.6"),
|
|
348
|
-
paddleModel: z
|
|
349
|
-
.enum(exports.PADDLE_OCR_MODELS)
|
|
350
|
-
.optional()
|
|
351
|
-
.describe("仅 paddleocr:切换内置模型,识别前执行 loadModel;不传则使用当前 active 模型,未加载时自动加载 ppocr-v6-small"),
|
|
352
|
-
maxSideLen: z
|
|
353
|
-
.number()
|
|
354
|
-
.int()
|
|
355
|
-
.min(0)
|
|
356
|
-
.optional()
|
|
357
|
-
.describe(`仅 paddleocr:检测阶段最大边长,识别前执行 setMaxSideLen;不传保持运行时当前值,0 回落到默认 ${exports.PADDLE_OCR_DEFAULT_MAX_SIDE_LEN}`),
|
|
358
|
-
useGpu: z
|
|
359
|
-
.boolean()
|
|
360
|
-
.optional()
|
|
361
|
-
.describe("仅 paddleocr:配合 paddleModel 切换模型时是否启用 GPU,默认 false"),
|
|
362
|
-
outputPath: z
|
|
363
|
-
.string()
|
|
364
|
-
.min(1)
|
|
365
|
-
.optional()
|
|
366
|
-
.describe("可选输出 JSON 路径;不传且结果很长时写入系统临时目录"),
|
|
367
|
-
timeoutMs: z
|
|
368
|
-
.number()
|
|
369
|
-
.int()
|
|
370
|
-
.min(1000)
|
|
371
|
-
.max(600000)
|
|
372
|
-
.optional()
|
|
373
|
-
.default(60000)
|
|
374
|
-
.describe("runScript 请求超时时间,默认 60000 毫秒"),
|
|
375
|
-
},
|
|
376
|
-
}, async ({ engine, mode, input, x, y, ex, ey, texts, languages, exactMatch, confidenceThreshold, paddleModel, maxSideLen, useGpu, outputPath, timeoutMs, }) => {
|
|
377
|
-
const target = await (0, tool_utils_1.resolveRuntimeHttpTarget)();
|
|
378
|
-
const response = await runOcrRecognitionOnDevice(target, {
|
|
379
|
-
engine,
|
|
380
|
-
mode,
|
|
381
|
-
input,
|
|
382
|
-
x,
|
|
383
|
-
y,
|
|
384
|
-
ex,
|
|
385
|
-
ey,
|
|
386
|
-
texts,
|
|
387
|
-
languages,
|
|
388
|
-
confidenceThreshold,
|
|
389
|
-
exactMatch,
|
|
390
|
-
paddleModel,
|
|
391
|
-
maxSideLen,
|
|
392
|
-
useGpu,
|
|
393
|
-
outputPath,
|
|
394
|
-
timeoutMs,
|
|
395
|
-
});
|
|
396
|
-
return (0, tool_utils_1.createTextToolResult)([
|
|
397
|
-
response.text,
|
|
398
|
-
"",
|
|
399
|
-
`device: ${target.label}`,
|
|
400
|
-
`engine: ${engine}`,
|
|
401
|
-
`mode: ${mode}`,
|
|
402
|
-
`input: ${input}`,
|
|
403
|
-
`region: x=${x}, y=${y}, ex=${ex}, ey=${ey}`,
|
|
404
|
-
...(engine === "paddleocr" && paddleModel
|
|
405
|
-
? [`paddleModel: ${paddleModel}`]
|
|
406
|
-
: []),
|
|
407
|
-
...(engine === "paddleocr" && maxSideLen !== undefined
|
|
408
|
-
? [`maxSideLen: ${maxSideLen}`]
|
|
409
|
-
: []),
|
|
410
|
-
`status: ${response.status}`,
|
|
411
|
-
].join("\n"), response.body.success === false);
|
|
412
|
-
});
|
|
413
|
-
}
|
|
1
|
+
"use strict";var D=exports&&exports.__createBinding||(Object.create?(function(r,e,i,t){t===void 0&&(t=i);var n=Object.getOwnPropertyDescriptor(e,i);(!n||("get"in n?!e.__esModule:n.writable||n.configurable))&&(n={enumerable:!0,get:function(){return e[i]}}),Object.defineProperty(r,t,n)}):(function(r,e,i,t){t===void 0&&(t=i),r[t]=e[i]})),R=exports&&exports.__setModuleDefault||(Object.create?(function(r,e){Object.defineProperty(r,"default",{enumerable:!0,value:e})}):function(r,e){r.default=e}),O=exports&&exports.__importStar||(function(){var r=function(e){return r=Object.getOwnPropertyNames||function(i){var t=[];for(var n in i)Object.prototype.hasOwnProperty.call(i,n)&&(t[t.length]=n);return t},r(e)};return function(e){if(e&&e.__esModule)return e;var i={};if(e!=null)for(var t=r(e),n=0;n<t.length;n++)t[n]!=="default"&&D(i,e,t[n]);return R(i,e),i}})();Object.defineProperty(exports,"__esModule",{value:!0}),exports.APPLE_OCR_LANGUAGES=exports.PADDLE_OCR_DEFAULT_MAX_SIDE_LEN=exports.PADDLE_OCR_MODELS=void 0,exports.formatOcrToolText=E,exports.runOcrRecognitionOnDevice=w,exports.registerOcrTools=x;const T=O(require("fs-extra")),P=O(require("os")),_=O(require("path")),o=O(require("zod/v4")),g=require("./tool-utils");exports.PADDLE_OCR_MODELS=["ppocr-v6-tiny","ppocr-v6-small","ppocr-v5"],exports.PADDLE_OCR_DEFAULT_MAX_SIDE_LEN=768,exports.APPLE_OCR_LANGUAGES=["en-US","fr-FR","it-IT","de-DE","es-ES","pt-BR","zh-Hans","zh-Hant"];function f(r){return JSON.stringify(r)}function L(r){return r&&r.trim()?_.resolve(r.trim()):_.join(P.tmpdir(),`ms-mcp-ocr-${Date.now()}-${Math.random().toString(36).slice(2,8)}.json`)}function C(r,e,i,t,n,u,a,c,l=!1){if(r==="findText"){if(!a||a.length===0)throw new Error("findText \u6A21\u5F0F\u5FC5\u987B\u4F20 texts\u3002");return`appleOcr.findTextAbs(${f(e)}, ${f(a)}, ${i}, ${t}, ${n}, ${u}, ${f(c)}, ${l});`}return r==="numbers"?`appleOcr.recognizeNumbersAbs(${f(e)}, ${i}, ${t}, ${n}, ${u});`:`appleOcr.recognizeAbs(${f(e)}, ${i}, ${t}, ${n}, ${u}, ${f(c)});`}function v(r,e,i,t,n,u,a,c,l,b,p,$){if(r==="numbers")throw new Error("PaddleOCR \u6587\u6863\u672A\u63D0\u4F9B numbers \u6A21\u5F0F\uFF0C\u8BF7\u4F7F\u7528 appleocr \u5F15\u64CE\u3002");const s=[];p!==void 0&&s.push(`paddleOcr.setMaxSideLen(${p});`),b&&s.push(`paddleOcr.loadModel(${f(b)}, ${$??!1});`);let d;if(r==="findText"){if(!a||a.length===0)throw new Error("findText \u6A21\u5F0F\u5FC5\u987B\u4F20 texts\u3002");d=`paddleOcr.findTextAbs(${f(e)}, ${f(a)}, ${i}, ${t}, ${n}, ${u}, ${c}, ${l});`}else d=`paddleOcr.recognizeAbs(${f(e)}, ${i}, ${t}, ${n}, ${u}, ${c});`;return[...s,d].join(`
|
|
2
|
+
`)}function M(r,e,i,t,n,u,a,c,l,b,p,$,s,d){if(r==="paddleocr")return v(e,i,t,n,u,a,c,b,p,$,s,d);if($!==void 0||s!==void 0||d!==void 0)throw new Error("paddleModel / maxSideLen / useGpu \u4EC5\u9002\u7528\u4E8E paddleocr \u5F15\u64CE\u3002");return C(e,i,t,n,u,a,c,l,p)}async function j(r,e,i,t){const n=new AbortController,u=setTimeout(()=>n.abort(),t);try{const a=await fetch(`http://${r}:${e}/api/runScript`,{method:"POST",signal:n.signal,headers:{"Content-Type":"application/json"},body:JSON.stringify({script:i})}),c=await a.text();let l;try{l=JSON.parse(c)}catch{throw new Error(`runScript \u54CD\u5E94\u4E0D\u662F\u6709\u6548 JSON: ${c}`)}if(!a.ok)throw new Error(`runScript HTTP ${a.status}: ${c}`);return{status:a.status,body:l}}catch(a){throw a instanceof Error&&a.name==="AbortError"?new Error(`runScript \u8BF7\u6C42\u8D85\u65F6: ${t}ms`):a}finally{clearTimeout(u)}}async function E(r,e){const i=Array.isArray(r.result)?r.result.length:void 0,t=(0,g.formatRuntimeJsonText)(r);if(e||t.length>12e3){const n=L(e);return await T.ensureDir(_.dirname(n)),await T.writeJson(n,r,{spaces:2}),["OCR \u6267\u884C\u6210\u529F",...i===void 0?[]:[`resultCount: ${i}`],`resultType: ${r.resultType??"unknown"}`,`output: ${n}`].join(`
|
|
3
|
+
`)}return["OCR \u6267\u884C\u6210\u529F",...i===void 0?[]:[`resultCount: ${i}`],`resultType: ${r.resultType??"unknown"}`,"",t].join(`
|
|
4
|
+
`)}async function w(r,e){const i=M(e.engine,e.mode,e.input,e.x,e.y,e.ex,e.ey,e.texts,e.languages,e.confidenceThreshold,e.exactMatch,e.paddleModel,e.maxSideLen,e.useGpu),t=await j(r.ip,r.port,i,e.timeoutMs),n=await E(t.body,e.outputPath);return{status:t.status,body:t.body,text:n}}function x(r){r.registerTool("ocr_recognize",{title:"OCR Recognize",description:"\u5728\u5F53\u524D\u9ED8\u8BA4\u8BBE\u5907\u6267\u884C OCR\u3002\u652F\u6301 appleocr \u4E0E paddleocr\uFF0C\u9ED8\u8BA4 appleocr\uFF1B\u8FD4\u56DE\u5750\u6807\u4F7F\u7528\u7EDD\u5BF9\u5750\u6807\u3002",inputSchema:{engine:o.enum(["appleocr","paddleocr"]).optional().default("appleocr").describe("OCR \u5F15\u64CE\uFF1Aappleocr=Apple Vision\uFF0Cpaddleocr=PaddleOCR"),mode:o.enum(["recognize","numbers","findText"]).optional().default("recognize").describe("OCR \u6A21\u5F0F\uFF1Arecognize=\u8BC6\u522B\u6587\u672C\uFF0Cnumbers=\u8BC6\u522B\u6570\u5B57\uFF0CfindText=\u67E5\u627E\u6587\u672C"),input:o.string().min(1).optional().default("screen").describe('\u8F93\u5165\u6E90\uFF0C\u9ED8\u8BA4 "screen"\uFF0C\u4E5F\u53EF\u4F20\u56FE\u7247\u8DEF\u5F84\u3001URL \u6216 imageId'),x:o.number().int().min(0).optional().default(0).describe("\u533A\u57DF\u5DE6\u4E0A\u89D2 x"),y:o.number().int().min(0).optional().default(0).describe("\u533A\u57DF\u5DE6\u4E0A\u89D2 y"),ex:o.number().int().min(0).optional().default(0).describe("\u533A\u57DF\u53F3\u4E0B\u89D2 x\uFF1B\u5168\u5C4F\u53EF\u4F20 0"),ey:o.number().int().min(0).optional().default(0).describe("\u533A\u57DF\u53F3\u4E0B\u89D2 y\uFF1B\u5168\u5C4F\u53EF\u4F20 0"),texts:o.array(o.string().min(1)).optional().describe("findText \u6A21\u5F0F\u8981\u67E5\u627E\u7684\u6587\u672C\u6570\u7EC4"),languages:o.array(o.enum(exports.APPLE_OCR_LANGUAGES)).optional().describe('Apple OCR \u8BC6\u522B\u8BED\u8A00\u6570\u7EC4\uFF0C\u9ED8\u8BA4\u7531\u8FD0\u884C\u65F6\u4F7F\u7528 ["zh-Hans", "en-US"]'),exactMatch:o.boolean().optional().default(!1).describe("findText \u6A21\u5F0F\u662F\u5426\u8981\u6C42\u6574\u6761\u8BC6\u522B\u6587\u672C\u5B8C\u5168\u5339\u914D\u76EE\u6807\u6587\u672C"),confidenceThreshold:o.number().min(0).max(1).optional().default(.6).describe("PaddleOCR \u7F6E\u4FE1\u5EA6\u9608\u503C\uFF0C\u9ED8\u8BA4 0.6"),paddleModel:o.enum(exports.PADDLE_OCR_MODELS).optional().describe("\u4EC5 paddleocr\uFF1A\u5207\u6362\u5185\u7F6E\u6A21\u578B\uFF0C\u8BC6\u522B\u524D\u6267\u884C loadModel\uFF1B\u4E0D\u4F20\u5219\u4F7F\u7528\u5F53\u524D active \u6A21\u578B\uFF0C\u672A\u52A0\u8F7D\u65F6\u81EA\u52A8\u52A0\u8F7D ppocr-v6-small"),maxSideLen:o.number().int().min(0).optional().describe(`\u4EC5 paddleocr\uFF1A\u68C0\u6D4B\u9636\u6BB5\u6700\u5927\u8FB9\u957F\uFF0C\u8BC6\u522B\u524D\u6267\u884C setMaxSideLen\uFF1B\u4E0D\u4F20\u4FDD\u6301\u8FD0\u884C\u65F6\u5F53\u524D\u503C\uFF0C0 \u56DE\u843D\u5230\u9ED8\u8BA4 ${exports.PADDLE_OCR_DEFAULT_MAX_SIDE_LEN}`),useGpu:o.boolean().optional().describe("\u4EC5 paddleocr\uFF1A\u914D\u5408 paddleModel \u5207\u6362\u6A21\u578B\u65F6\u662F\u5426\u542F\u7528 GPU\uFF0C\u9ED8\u8BA4 false"),outputPath:o.string().min(1).optional().describe("\u53EF\u9009\u8F93\u51FA JSON \u8DEF\u5F84\uFF1B\u4E0D\u4F20\u4E14\u7ED3\u679C\u5F88\u957F\u65F6\u5199\u5165\u7CFB\u7EDF\u4E34\u65F6\u76EE\u5F55"),timeoutMs:o.number().int().min(1e3).max(6e5).optional().default(6e4).describe("runScript \u8BF7\u6C42\u8D85\u65F6\u65F6\u95F4\uFF0C\u9ED8\u8BA4 60000 \u6BEB\u79D2")}},async({engine:e,mode:i,input:t,x:n,y:u,ex:a,ey:c,texts:l,languages:b,exactMatch:p,confidenceThreshold:$,paddleModel:s,maxSideLen:d,useGpu:A,outputPath:S,timeoutMs:y})=>{const h=await(0,g.resolveRuntimeHttpTarget)(),m=await w(h,{engine:e,mode:i,input:t,x:n,y:u,ex:a,ey:c,texts:l,languages:b,confidenceThreshold:$,exactMatch:p,paddleModel:s,maxSideLen:d,useGpu:A,outputPath:S,timeoutMs:y});return(0,g.createTextToolResult)([m.text,"",`device: ${h.label}`,`engine: ${e}`,`mode: ${i}`,`input: ${t}`,`region: x=${n}, y=${u}, ex=${a}, ey=${c}`,...e==="paddleocr"&&s?[`paddleModel: ${s}`]:[],...e==="paddleocr"&&d!==void 0?[`maxSideLen: ${d}`]:[],`status: ${m.status}`].join(`
|
|
5
|
+
`),m.body.success===!1)})}
|
package/dist/mcp/project.d.ts
CHANGED
|
@@ -1,16 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 检查工作目录是否为有效的 KuaiJS 项目
|
|
3
|
-
* @param workspacePath 工作目录路径
|
|
4
|
-
* @returns 若目录包含 package.json 与 scripts 目录则返回 true,否则返回 false
|
|
5
|
-
* @example
|
|
6
|
-
* const ok = await isValidKuaiJSProject(process.cwd())
|
|
7
|
-
*/
|
|
8
1
|
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
2
|
export declare function ensureValidKuaiJSProject(workspacePath: string): Promise<void>;
|
package/dist/mcp/project.js
CHANGED
|
@@ -1,74 +1 @@
|
|
|
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.isValidKuaiJSProject = isValidKuaiJSProject;
|
|
37
|
-
exports.ensureValidKuaiJSProject = ensureValidKuaiJSProject;
|
|
38
|
-
const fsExtra = __importStar(require("fs-extra"));
|
|
39
|
-
const path = __importStar(require("path"));
|
|
40
|
-
/**
|
|
41
|
-
* 检查工作目录是否为有效的 KuaiJS 项目
|
|
42
|
-
* @param workspacePath 工作目录路径
|
|
43
|
-
* @returns 若目录包含 package.json 与 scripts 目录则返回 true,否则返回 false
|
|
44
|
-
* @example
|
|
45
|
-
* const ok = await isValidKuaiJSProject(process.cwd())
|
|
46
|
-
*/
|
|
47
|
-
async function isValidKuaiJSProject(workspacePath) {
|
|
48
|
-
try {
|
|
49
|
-
const packageJsonPath = path.join(workspacePath, "package.json");
|
|
50
|
-
const scriptsPath = path.join(workspacePath, "scripts");
|
|
51
|
-
const [packageExists, scriptsExists] = await Promise.all([
|
|
52
|
-
fsExtra.pathExists(packageJsonPath),
|
|
53
|
-
fsExtra.pathExists(scriptsPath),
|
|
54
|
-
]);
|
|
55
|
-
return packageExists && scriptsExists;
|
|
56
|
-
}
|
|
57
|
-
catch {
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* 校验当前目录是否是可执行构建/运行的 KuaiJS 项目
|
|
63
|
-
* @param workspacePath 待校验目录
|
|
64
|
-
* @returns 校验通过时返回 Promise<void>,失败时抛出异常
|
|
65
|
-
* @example
|
|
66
|
-
* await ensureValidKuaiJSProject("/Users/demo/project")
|
|
67
|
-
*/
|
|
68
|
-
async function ensureValidKuaiJSProject(workspacePath) {
|
|
69
|
-
const valid = await isValidKuaiJSProject(workspacePath);
|
|
70
|
-
if (valid) {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
throw new Error("当前目录不是有效的 快点JS 项目,请确保目录包含 package.json 与 scripts/");
|
|
74
|
-
}
|
|
1
|
+
"use strict";var o=exports&&exports.__createBinding||(Object.create?(function(r,e,i,t){t===void 0&&(t=i);var n=Object.getOwnPropertyDescriptor(e,i);(!n||("get"in n?!e.__esModule:n.writable||n.configurable))&&(n={enumerable:!0,get:function(){return e[i]}}),Object.defineProperty(r,t,n)}):(function(r,e,i,t){t===void 0&&(t=i),r[t]=e[i]})),f=exports&&exports.__setModuleDefault||(Object.create?(function(r,e){Object.defineProperty(r,"default",{enumerable:!0,value:e})}):function(r,e){r.default=e}),a=exports&&exports.__importStar||(function(){var r=function(e){return r=Object.getOwnPropertyNames||function(i){var t=[];for(var n in i)Object.prototype.hasOwnProperty.call(i,n)&&(t[t.length]=n);return t},r(e)};return function(e){if(e&&e.__esModule)return e;var i={};if(e!=null)for(var t=r(e),n=0;n<t.length;n++)t[n]!=="default"&&o(i,e,t[n]);return f(i,e),i}})();Object.defineProperty(exports,"__esModule",{value:!0}),exports.isValidKuaiJSProject=s,exports.ensureValidKuaiJSProject=l;const u=a(require("fs-extra")),c=a(require("path"));async function s(r){try{const e=c.join(r,"package.json"),i=c.join(r,"scripts"),[t,n]=await Promise.all([u.pathExists(e),u.pathExists(i)]);return t&&n}catch{return!1}}async function l(r){if(!await s(r))throw new Error("\u5F53\u524D\u76EE\u5F55\u4E0D\u662F\u6709\u6548\u7684 \u5FEB\u70B9JS \u9879\u76EE\uFF0C\u8BF7\u786E\u4FDD\u76EE\u5F55\u5305\u542B package.json \u4E0E scripts/")}
|