ms-vite-plugin 1.3.3 → 1.3.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/docs/api/hid.md +2 -3
- package/docs/apicn/hid.md +2 -3
- package/docs/apipython/hid.md +2 -3
- package/package.json +1 -1
- package/dist/device.d.ts +0 -32
- package/dist/device.js +0 -325
- package/dist/mcp/control-tools.d.ts +0 -9
- package/dist/mcp/control-tools.js +0 -201
- package/dist/mcp/hid-tools.d.ts +0 -9
- package/dist/mcp/hid-tools.js +0 -254
- package/dist/mcp/ime-tools.d.ts +0 -9
- package/dist/mcp/ime-tools.js +0 -130
- package/dist/mcp/mirror-tools.d.ts +0 -9
- package/dist/mcp/mirror-tools.js +0 -82
package/docs/api/hid.md
CHANGED
|
@@ -775,7 +775,6 @@ function pressButton(
|
|
|
775
775
|
| "brightnessup"
|
|
776
776
|
| "brightnessdown"
|
|
777
777
|
| "power"
|
|
778
|
-
| "menu"
|
|
779
778
|
| "snapshot",
|
|
780
779
|
): boolean;
|
|
781
780
|
```
|
|
@@ -784,7 +783,7 @@ function pressButton(
|
|
|
784
783
|
|
|
785
784
|
| 参数名 | 类型 | 是否必填 | 默认值 | 描述 |
|
|
786
785
|
| -------- | ------ | -------- | ------ | ------------------------------------------------------------------------------------------------------------------------ |
|
|
787
|
-
| `button` | string | 是 | - | 按钮类型: <br>-`"home"` Home 键 <br>- `"volumeup"` 音量上键 <br>- `"volumedown"` 音量下键 <br>- `"mute"` 静音键 <br>- `"playpause"` 播放/暂停键 <br>- `"next"` 下一首/下一章节 <br>- `"prev"` 上一首/上一章节 <br>- `"eject"` 显示/隐藏键盘 <br>- `"globe"` Globe 键 <br>- `"search"` 搜索键 <br>- `"brightnessup"` 调高屏幕亮度 <br>- `"brightnessdown"` 调低屏幕亮度 <br>- `"power"` 电源/锁屏键 <br>- `"
|
|
786
|
+
| `button` | string | 是 | - | 按钮类型: <br>-`"home"` Home 键 <br>- `"volumeup"` 音量上键 <br>- `"volumedown"` 音量下键 <br>- `"mute"` 静音键 <br>- `"playpause"` 播放/暂停键 <br>- `"next"` 下一首/下一章节 <br>- `"prev"` 上一首/上一章节 <br>- `"eject"` 显示/隐藏键盘 <br>- `"globe"` Globe 键 <br>- `"search"` 搜索键 <br>- `"brightnessup"` 调高屏幕亮度 <br>- `"brightnessdown"` 调低屏幕亮度 <br>- `"power"` 电源/锁屏键 <br>- `"snapshot"` 系统截图键 |
|
|
788
787
|
|
|
789
788
|
**返回值:**
|
|
790
789
|
|
|
@@ -908,7 +907,7 @@ hid.back();
|
|
|
908
907
|
|
|
909
908
|
### recent - 最近应用
|
|
910
909
|
|
|
911
|
-
显示 APP
|
|
910
|
+
双击 Home 显示 APP 切换器。
|
|
912
911
|
|
|
913
912
|
```typescript
|
|
914
913
|
function recent(): boolean;
|
package/docs/apicn/hid.md
CHANGED
|
@@ -775,7 +775,6 @@ function 按键(
|
|
|
775
775
|
| "brightnessup"
|
|
776
776
|
| "brightnessdown"
|
|
777
777
|
| "power"
|
|
778
|
-
| "menu"
|
|
779
778
|
| "snapshot",
|
|
780
779
|
): 布尔值;
|
|
781
780
|
```
|
|
@@ -784,7 +783,7 @@ function 按键(
|
|
|
784
783
|
|
|
785
784
|
| 参数名 | 类型 | 是否必填 | 默认值 | 描述 |
|
|
786
785
|
| ------ | ------ | -------- | ------ | ------------------------------------------------------------------------------------------------------------------------ |
|
|
787
|
-
| `按键` | 字符串 | 是 | - | 按钮类型: <br>-`"home"` Home 键 <br>- `"volumeup"` 音量上键 <br>- `"volumedown"` 音量下键 <br>- `"mute"` 静音键 <br>- `"playpause"` 播放/暂停键 <br>- `"next"` 下一首/下一章节 <br>- `"prev"` 上一首/上一章节 <br>- `"eject"` 显示/隐藏键盘 <br>- `"globe"` Globe 键 <br>- `"search"` 搜索键 <br>- `"brightnessup"` 调高屏幕亮度 <br>- `"brightnessdown"` 调低屏幕亮度 <br>- `"power"` 电源/锁屏键 <br>- `"
|
|
786
|
+
| `按键` | 字符串 | 是 | - | 按钮类型: <br>-`"home"` Home 键 <br>- `"volumeup"` 音量上键 <br>- `"volumedown"` 音量下键 <br>- `"mute"` 静音键 <br>- `"playpause"` 播放/暂停键 <br>- `"next"` 下一首/下一章节 <br>- `"prev"` 上一首/上一章节 <br>- `"eject"` 显示/隐藏键盘 <br>- `"globe"` Globe 键 <br>- `"search"` 搜索键 <br>- `"brightnessup"` 调高屏幕亮度 <br>- `"brightnessdown"` 调低屏幕亮度 <br>- `"power"` 电源/锁屏键 <br>- `"snapshot"` 系统截图键 |
|
|
788
787
|
|
|
789
788
|
**返回值:**
|
|
790
789
|
|
|
@@ -911,7 +910,7 @@ $HID.返回();
|
|
|
911
910
|
|
|
912
911
|
### 最近应用
|
|
913
912
|
|
|
914
|
-
显示 APP
|
|
913
|
+
双击 Home 显示 APP 切换器。
|
|
915
914
|
|
|
916
915
|
```typescript
|
|
917
916
|
function 最近应用(): 布尔值;
|
package/docs/apipython/hid.md
CHANGED
|
@@ -800,7 +800,6 @@ def pressButton(
|
|
|
800
800
|
"brightnessup",
|
|
801
801
|
"brightnessdown",
|
|
802
802
|
"power",
|
|
803
|
-
"menu",
|
|
804
803
|
"snapshot",
|
|
805
804
|
],
|
|
806
805
|
) -> bool
|
|
@@ -810,7 +809,7 @@ def pressButton(
|
|
|
810
809
|
|
|
811
810
|
| 参数名 | 类型 | 是否必填 | 默认值 | 描述 |
|
|
812
811
|
| -------- | ------- | -------- | ------ | ------------------------------------------------------------------------------------------------------------------------ |
|
|
813
|
-
| `button` | Literal | 是 | - | 按钮类型: <br>-`"home"` Home 键 <br>- `"volumeup"` 音量上键 <br>- `"volumedown"` 音量下键 <br>- `"mute"` 静音键 <br>- `"playpause"` 播放/暂停键 <br>- `"next"` 下一首/下一章节 <br>- `"prev"` 上一首/上一章节 <br>- `"eject"` 显示/隐藏键盘 <br>- `"globe"` Globe 键 <br>- `"search"` 搜索键 <br>- `"brightnessup"` 调高屏幕亮度 <br>- `"brightnessdown"` 调低屏幕亮度 <br>- `"power"` 电源/锁屏键 <br>- `"
|
|
812
|
+
| `button` | Literal | 是 | - | 按钮类型: <br>-`"home"` Home 键 <br>- `"volumeup"` 音量上键 <br>- `"volumedown"` 音量下键 <br>- `"mute"` 静音键 <br>- `"playpause"` 播放/暂停键 <br>- `"next"` 下一首/下一章节 <br>- `"prev"` 上一首/上一章节 <br>- `"eject"` 显示/隐藏键盘 <br>- `"globe"` Globe 键 <br>- `"search"` 搜索键 <br>- `"brightnessup"` 调高屏幕亮度 <br>- `"brightnessdown"` 调低屏幕亮度 <br>- `"power"` 电源/锁屏键 <br>- `"snapshot"` 系统截图键 |
|
|
814
813
|
|
|
815
814
|
**返回值:**
|
|
816
815
|
|
|
@@ -932,7 +931,7 @@ hid.back()
|
|
|
932
931
|
|
|
933
932
|
### recent - 最近应用
|
|
934
933
|
|
|
935
|
-
显示 APP
|
|
934
|
+
双击 Home 显示 APP 切换器。
|
|
936
935
|
|
|
937
936
|
```python
|
|
938
937
|
def recent() -> bool
|
package/package.json
CHANGED
package/dist/device.d.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 设备命令选项
|
|
3
|
-
*/
|
|
4
|
-
export interface DeviceCliOptions {
|
|
5
|
-
ip: string;
|
|
6
|
-
port?: string;
|
|
7
|
-
path?: string;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* 在设备上运行项目(先同步后运行)
|
|
11
|
-
* @param options 命令选项
|
|
12
|
-
* @returns 执行完成后返回 Promise<void>
|
|
13
|
-
* @example
|
|
14
|
-
* await runOnDevice({ ip: "192.168.1.10", port: "9800", path: "./demo" })
|
|
15
|
-
*/
|
|
16
|
-
export declare function runOnDevice(options: DeviceCliOptions): Promise<void>;
|
|
17
|
-
/**
|
|
18
|
-
* 在设备上预览 UI(先同步后调用 runUI)
|
|
19
|
-
* @param options 命令选项
|
|
20
|
-
* @returns 执行完成后返回 Promise<void>
|
|
21
|
-
* @example
|
|
22
|
-
* await runUIOnDevice({ ip: "192.168.1.10", port: "9800", path: "./demo" })
|
|
23
|
-
*/
|
|
24
|
-
export declare function runUIOnDevice(options: DeviceCliOptions): Promise<void>;
|
|
25
|
-
/**
|
|
26
|
-
* 停止设备上的项目
|
|
27
|
-
* @param options 命令选项
|
|
28
|
-
* @returns 执行完成后返回 Promise<void>
|
|
29
|
-
* @example
|
|
30
|
-
* await stopOnDevice({ ip: "192.168.1.10", port: "9800" })
|
|
31
|
-
*/
|
|
32
|
-
export declare function stopOnDevice(options: DeviceCliOptions): Promise<void>;
|
package/dist/device.js
DELETED
|
@@ -1,325 +0,0 @@
|
|
|
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.runOnDevice = runOnDevice;
|
|
37
|
-
exports.runUIOnDevice = runUIOnDevice;
|
|
38
|
-
exports.stopOnDevice = stopOnDevice;
|
|
39
|
-
const fsExtra = __importStar(require("fs-extra"));
|
|
40
|
-
const path = __importStar(require("path"));
|
|
41
|
-
const build_js_1 = require("./build.js");
|
|
42
|
-
/**
|
|
43
|
-
* 读取并校验设备连接参数
|
|
44
|
-
* @param options 命令选项
|
|
45
|
-
* @returns 返回标准化后的设备地址信息
|
|
46
|
-
* @example
|
|
47
|
-
* parseDeviceOptions({ ip: "192.168.1.10", port: "9800" })
|
|
48
|
-
*/
|
|
49
|
-
function parseDeviceOptions(options) {
|
|
50
|
-
const ip = options.ip?.trim();
|
|
51
|
-
const portText = (options.port ?? "9800").trim();
|
|
52
|
-
const port = Number.parseInt(portText, 10);
|
|
53
|
-
if (!ip) {
|
|
54
|
-
throw new Error("请通过 --ip 指定设备 IP 地址");
|
|
55
|
-
}
|
|
56
|
-
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
57
|
-
throw new Error(`无效端口: ${portText}`);
|
|
58
|
-
}
|
|
59
|
-
return { ip, port };
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* 计算 Buffer 的 CRC32 值
|
|
63
|
-
* @param input 二进制输入数据
|
|
64
|
-
* @returns CRC32 十六进制字符串(8位)
|
|
65
|
-
* @example
|
|
66
|
-
* calculateCrc32FromBuffer(Buffer.from("hello"))
|
|
67
|
-
*/
|
|
68
|
-
function calculateCrc32FromBuffer(input) {
|
|
69
|
-
let crc = 0xffffffff;
|
|
70
|
-
for (let i = 0; i < input.length; i += 1) {
|
|
71
|
-
crc ^= input[i];
|
|
72
|
-
for (let j = 0; j < 8; j += 1) {
|
|
73
|
-
if ((crc & 1) === 1) {
|
|
74
|
-
crc = (crc >>> 1) ^ 0xedb88320;
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
crc >>>= 1;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
const finalValue = (crc ^ 0xffffffff) >>> 0;
|
|
82
|
-
return finalValue.toString(16).padStart(8, "0");
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* 计算文件的 CRC32 值
|
|
86
|
-
* @param filePath 文件路径
|
|
87
|
-
* @returns CRC32 十六进制字符串(8位)
|
|
88
|
-
* @example
|
|
89
|
-
* await calculateCrc32("/tmp/a.txt")
|
|
90
|
-
*/
|
|
91
|
-
async function calculateCrc32(filePath) {
|
|
92
|
-
const fileBuffer = await fsExtra.readFile(filePath);
|
|
93
|
-
return calculateCrc32FromBuffer(fileBuffer);
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* 递归收集目录中的所有文件
|
|
97
|
-
* @param rootDir 需要遍历的根目录
|
|
98
|
-
* @param bundlePrefix 输出到设备时的目录前缀
|
|
99
|
-
* @returns 返回可同步文件列表(含 size 与 crc32)
|
|
100
|
-
* @example
|
|
101
|
-
* await collectFilesInDir("/tmp/project/ui", "ui")
|
|
102
|
-
*/
|
|
103
|
-
async function collectFilesInDir(rootDir, bundlePrefix) {
|
|
104
|
-
const files = [];
|
|
105
|
-
async function walk(dir) {
|
|
106
|
-
const entries = await fsExtra.readdir(dir, { withFileTypes: true });
|
|
107
|
-
for (const entry of entries) {
|
|
108
|
-
const fullPath = path.join(dir, entry.name);
|
|
109
|
-
if (entry.isDirectory()) {
|
|
110
|
-
await walk(fullPath);
|
|
111
|
-
}
|
|
112
|
-
else if (entry.isFile()) {
|
|
113
|
-
const relPath = path.relative(rootDir, fullPath).replace(/\\/g, "/");
|
|
114
|
-
const stat = await fsExtra.stat(fullPath);
|
|
115
|
-
files.push({
|
|
116
|
-
path: fullPath,
|
|
117
|
-
bundlePath: `${bundlePrefix}/${relPath}`,
|
|
118
|
-
size: stat.size,
|
|
119
|
-
crc32: await calculateCrc32(fullPath),
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
if (await fsExtra.pathExists(rootDir)) {
|
|
125
|
-
await walk(rootDir);
|
|
126
|
-
}
|
|
127
|
-
return files;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* 读取项目运行所需的元信息
|
|
131
|
-
* @param workspacePath 项目根目录
|
|
132
|
-
* @returns 返回 projectName、appVersion 与 packageJsonPath
|
|
133
|
-
* @example
|
|
134
|
-
* await getProjectMeta("/Users/demo/project")
|
|
135
|
-
*/
|
|
136
|
-
async function getProjectMeta(workspacePath) {
|
|
137
|
-
const packageJsonPath = path.join(workspacePath, "package.json");
|
|
138
|
-
const packageJson = await fsExtra.readJSON(packageJsonPath);
|
|
139
|
-
const projectName = packageJson.name;
|
|
140
|
-
const appVersion = packageJson.appVersion;
|
|
141
|
-
if (!projectName) {
|
|
142
|
-
throw new Error("请在 package.json 中添加 name 字段");
|
|
143
|
-
}
|
|
144
|
-
if (!appVersion) {
|
|
145
|
-
throw new Error("请在 package.json 中添加 appVersion 字段");
|
|
146
|
-
}
|
|
147
|
-
return { projectName, appVersion, packageJsonPath };
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* 收集运行前需要同步的文件
|
|
151
|
-
* @param workspacePath 项目根目录
|
|
152
|
-
* @returns 返回项目文件清单(含 size 与 crc32)
|
|
153
|
-
* @example
|
|
154
|
-
* await collectProjectFiles("/Users/demo/project")
|
|
155
|
-
*/
|
|
156
|
-
async function collectProjectFiles(workspacePath) {
|
|
157
|
-
const scriptDistPath = path.join(workspacePath, "dist", "scripts");
|
|
158
|
-
const scriptSrcPath = path.join(workspacePath, "scripts");
|
|
159
|
-
const uiPath = path.join(workspacePath, "ui");
|
|
160
|
-
const resPath = path.join(workspacePath, "res");
|
|
161
|
-
const packageJsonPath = path.join(workspacePath, "package.json");
|
|
162
|
-
const useDistScripts = await fsExtra.pathExists(scriptDistPath);
|
|
163
|
-
const scriptPath = useDistScripts ? scriptDistPath : scriptSrcPath;
|
|
164
|
-
const files = [
|
|
165
|
-
{
|
|
166
|
-
path: packageJsonPath,
|
|
167
|
-
bundlePath: "package.json",
|
|
168
|
-
size: (await fsExtra.stat(packageJsonPath)).size,
|
|
169
|
-
crc32: await calculateCrc32(packageJsonPath),
|
|
170
|
-
},
|
|
171
|
-
];
|
|
172
|
-
const [scriptFiles, uiFiles, resFiles] = await Promise.all([
|
|
173
|
-
collectFilesInDir(scriptPath, "scripts"),
|
|
174
|
-
collectFilesInDir(uiPath, "ui"),
|
|
175
|
-
collectFilesInDir(resPath, "res"),
|
|
176
|
-
]);
|
|
177
|
-
files.push(...scriptFiles, ...uiFiles, ...resFiles);
|
|
178
|
-
return files;
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* 获取设备上的文件列表
|
|
182
|
-
* @param ip 设备 IP 地址
|
|
183
|
-
* @param port 设备端口
|
|
184
|
-
* @param projectName 项目名称
|
|
185
|
-
* @returns 设备当前文件信息列表
|
|
186
|
-
* @example
|
|
187
|
-
* await listDeviceFiles("192.168.1.10", 9800, "demo")
|
|
188
|
-
*/
|
|
189
|
-
async function listDeviceFiles(ip, port, projectName) {
|
|
190
|
-
const url = new URL(`http://${ip}:${port}/api/files`);
|
|
191
|
-
url.searchParams.set("projectName", projectName);
|
|
192
|
-
const response = await fetch(url.toString(), { method: "GET" });
|
|
193
|
-
if (!response.ok) {
|
|
194
|
-
throw new Error(`文件列表请求失败: ${response.statusText}`);
|
|
195
|
-
}
|
|
196
|
-
const data = (await response.json());
|
|
197
|
-
return Array.isArray(data) ? data : [];
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* 将项目文件增量同步到设备
|
|
201
|
-
* @param workspacePath 项目根目录
|
|
202
|
-
* @param ip 设备 IP 地址
|
|
203
|
-
* @param port 设备端口
|
|
204
|
-
* @returns 同步完成后返回 Promise<void>
|
|
205
|
-
* @example
|
|
206
|
-
* await syncProjectToDevice("/Users/demo/project", "192.168.1.10", 9800)
|
|
207
|
-
*/
|
|
208
|
-
async function syncProjectToDevice(workspacePath, ip, port) {
|
|
209
|
-
const { projectName, appVersion } = await getProjectMeta(workspacePath);
|
|
210
|
-
console.log("🔎 正在获取设备文件列表...");
|
|
211
|
-
const deviceFiles = await listDeviceFiles(ip, port, projectName);
|
|
212
|
-
const deviceFileMap = new Map(deviceFiles.map((file) => [file.path, file]));
|
|
213
|
-
console.log("📂 正在分析项目文件...");
|
|
214
|
-
const files = await collectProjectFiles(workspacePath);
|
|
215
|
-
const filesToSync = [];
|
|
216
|
-
for (const file of files) {
|
|
217
|
-
const deviceFile = deviceFileMap.get(file.bundlePath);
|
|
218
|
-
const requireSyncFile = file.bundlePath.includes("main.js") ||
|
|
219
|
-
file.bundlePath.includes("main.py");
|
|
220
|
-
if (!deviceFile) {
|
|
221
|
-
filesToSync.push(file);
|
|
222
|
-
continue;
|
|
223
|
-
}
|
|
224
|
-
const changed = deviceFile.size !== file.size ||
|
|
225
|
-
deviceFile.crc32.toLowerCase() !== file.crc32.toLowerCase();
|
|
226
|
-
if (requireSyncFile || changed) {
|
|
227
|
-
filesToSync.push(file);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
console.log(`📦 发现 ${filesToSync.length} 个文件需要同步`);
|
|
231
|
-
if (filesToSync.length === 0) {
|
|
232
|
-
console.log("✅ 无需同步文件");
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
let syncedCount = 0;
|
|
236
|
-
for (const file of filesToSync) {
|
|
237
|
-
syncedCount += 1;
|
|
238
|
-
console.log(`⬆️ [${syncedCount}/${filesToSync.length}] 同步 ${file.bundlePath}`);
|
|
239
|
-
const binary = await fsExtra.readFile(file.path);
|
|
240
|
-
const url = new URL(`http://${ip}:${port}/debug/patchSync`);
|
|
241
|
-
url.searchParams.set("path", file.bundlePath);
|
|
242
|
-
url.searchParams.set("projectName", projectName);
|
|
243
|
-
url.searchParams.set("appVersion", appVersion);
|
|
244
|
-
const response = await fetch(url.toString(), {
|
|
245
|
-
method: "POST",
|
|
246
|
-
headers: {
|
|
247
|
-
"Content-Type": "application/octet-stream",
|
|
248
|
-
},
|
|
249
|
-
body: binary,
|
|
250
|
-
});
|
|
251
|
-
if (!response.ok) {
|
|
252
|
-
throw new Error(`同步失败: ${file.bundlePath} (状态码: ${response.status})`);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
console.log(`✅ 同步完成,共 ${filesToSync.length} 个文件`);
|
|
256
|
-
}
|
|
257
|
-
/**
|
|
258
|
-
* 发送设备动作请求
|
|
259
|
-
* @param action 动作名称,支持 run 与 stop
|
|
260
|
-
* @param ip 设备 IP 地址
|
|
261
|
-
* @param port 设备端口
|
|
262
|
-
* @returns 请求成功时返回 Promise<void>
|
|
263
|
-
* @example
|
|
264
|
-
* await requestDeviceAction("stop", "192.168.1.10", 9800)
|
|
265
|
-
*/
|
|
266
|
-
async function requestDeviceAction(action, ip, port) {
|
|
267
|
-
const url = `http://${ip}:${port}/api/${action}`;
|
|
268
|
-
const response = await fetch(url, { method: "GET" });
|
|
269
|
-
if (!response.ok) {
|
|
270
|
-
throw new Error(`${action} 失败,状态码: ${response.status}`);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
/**
|
|
274
|
-
* 在设备上运行项目(先同步后运行)
|
|
275
|
-
* @param options 命令选项
|
|
276
|
-
* @returns 执行完成后返回 Promise<void>
|
|
277
|
-
* @example
|
|
278
|
-
* await runOnDevice({ ip: "192.168.1.10", port: "9800", path: "./demo" })
|
|
279
|
-
*/
|
|
280
|
-
async function runOnDevice(options) {
|
|
281
|
-
const workspacePath = options.path
|
|
282
|
-
? path.resolve(options.path)
|
|
283
|
-
: process.cwd();
|
|
284
|
-
const { ip, port } = parseDeviceOptions(options);
|
|
285
|
-
console.log(`🔧 开始构建项目: ${workspacePath}`);
|
|
286
|
-
await (0, build_js_1.buildAll)(true, workspacePath);
|
|
287
|
-
console.log(`📦 开始同步项目到设备: ${ip}:${port}`);
|
|
288
|
-
await syncProjectToDevice(workspacePath, ip, port);
|
|
289
|
-
console.log(`🚀 开始运行项目: ${ip}:${port}`);
|
|
290
|
-
await requestDeviceAction("run", ip, port);
|
|
291
|
-
console.log("✅ 运行请求已发送");
|
|
292
|
-
}
|
|
293
|
-
/**
|
|
294
|
-
* 在设备上预览 UI(先同步后调用 runUI)
|
|
295
|
-
* @param options 命令选项
|
|
296
|
-
* @returns 执行完成后返回 Promise<void>
|
|
297
|
-
* @example
|
|
298
|
-
* await runUIOnDevice({ ip: "192.168.1.10", port: "9800", path: "./demo" })
|
|
299
|
-
*/
|
|
300
|
-
async function runUIOnDevice(options) {
|
|
301
|
-
const workspacePath = options.path
|
|
302
|
-
? path.resolve(options.path)
|
|
303
|
-
: process.cwd();
|
|
304
|
-
const { ip, port } = parseDeviceOptions(options);
|
|
305
|
-
console.log(`🔧 开始构建项目: ${workspacePath}`);
|
|
306
|
-
await (0, build_js_1.buildAll)(true, workspacePath);
|
|
307
|
-
console.log(`📦 开始同步项目到设备: ${ip}:${port}`);
|
|
308
|
-
await syncProjectToDevice(workspacePath, ip, port);
|
|
309
|
-
console.log(`🖼️ 开始预览 UI: ${ip}:${port}`);
|
|
310
|
-
await requestDeviceAction("runUI", ip, port);
|
|
311
|
-
console.log("✅ UI 预览请求已发送");
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* 停止设备上的项目
|
|
315
|
-
* @param options 命令选项
|
|
316
|
-
* @returns 执行完成后返回 Promise<void>
|
|
317
|
-
* @example
|
|
318
|
-
* await stopOnDevice({ ip: "192.168.1.10", port: "9800" })
|
|
319
|
-
*/
|
|
320
|
-
async function stopOnDevice(options) {
|
|
321
|
-
const { ip, port } = parseDeviceOptions(options);
|
|
322
|
-
console.log(`🛑 开始停止项目: ${ip}:${port}`);
|
|
323
|
-
await requestDeviceAction("stop", ip, port);
|
|
324
|
-
console.log("✅ 停止请求已发送");
|
|
325
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
/**
|
|
3
|
-
* 注册 Control API 对应 MCP 工具
|
|
4
|
-
* @param server MCP 服务实例
|
|
5
|
-
* @returns 无返回值
|
|
6
|
-
* @example
|
|
7
|
-
* registerControlTools(server)
|
|
8
|
-
*/
|
|
9
|
-
export declare function registerControlTools(server: McpServer): void;
|
|
@@ -1,201 +0,0 @@
|
|
|
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.registerControlTools = registerControlTools;
|
|
37
|
-
const z = __importStar(require("zod/v4"));
|
|
38
|
-
const tool_utils_1 = require("./tool-utils");
|
|
39
|
-
/**
|
|
40
|
-
* 请求控制路由
|
|
41
|
-
* @param endpoint 控制 API 名称
|
|
42
|
-
* @param query 可选查询参数
|
|
43
|
-
* @returns 返回设备端 JSON 响应
|
|
44
|
-
* @example
|
|
45
|
-
* const payload = await requestControlApi("home")
|
|
46
|
-
*/
|
|
47
|
-
async function requestControlApi(endpoint, query) {
|
|
48
|
-
const target = await (0, tool_utils_1.resolveRuntimeHttpTarget)();
|
|
49
|
-
return (0, tool_utils_1.requestRuntimePathJson)(target, `/api/control/${endpoint}`, query);
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* 将控制类 API 响应格式化为 MCP 文本
|
|
53
|
-
* @param actionName 操作名称
|
|
54
|
-
* @param payload 设备端响应
|
|
55
|
-
* @returns 返回标准文本工具响应
|
|
56
|
-
* @example
|
|
57
|
-
* formatControlResult("返回桌面", { success: true })
|
|
58
|
-
*/
|
|
59
|
-
function formatControlResult(actionName, payload) {
|
|
60
|
-
const success = payload.success === true;
|
|
61
|
-
if ("data" in payload) {
|
|
62
|
-
return (0, tool_utils_1.createTextToolResult)(`${actionName}${success ? "成功" : "失败"}:\n${(0, tool_utils_1.formatRuntimeJsonText)(payload.data)}`, !success);
|
|
63
|
-
}
|
|
64
|
-
return (0, tool_utils_1.createTextToolResult)(`${actionName}${success ? "成功" : "失败"}`, !success);
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* 注册 Control API 对应 MCP 工具
|
|
68
|
-
* @param server MCP 服务实例
|
|
69
|
-
* @returns 无返回值
|
|
70
|
-
* @example
|
|
71
|
-
* registerControlTools(server)
|
|
72
|
-
*/
|
|
73
|
-
function registerControlTools(server) {
|
|
74
|
-
server.registerTool("control_home", {
|
|
75
|
-
title: "Control Home",
|
|
76
|
-
description: "返回桌面。",
|
|
77
|
-
inputSchema: {},
|
|
78
|
-
}, async () => formatControlResult("返回桌面", await requestControlApi("home")));
|
|
79
|
-
server.registerTool("control_click", {
|
|
80
|
-
title: "Control Click",
|
|
81
|
-
description: "点击指定坐标。",
|
|
82
|
-
inputSchema: {
|
|
83
|
-
x: z.number().int().min(0).describe("点击坐标 x"),
|
|
84
|
-
y: z.number().int().min(0).describe("点击坐标 y"),
|
|
85
|
-
duration: z
|
|
86
|
-
.number()
|
|
87
|
-
.int()
|
|
88
|
-
.min(0)
|
|
89
|
-
.optional()
|
|
90
|
-
.describe("按压时长,默认 20"),
|
|
91
|
-
jitter: z.boolean().optional().describe("是否启用抖动,默认 false"),
|
|
92
|
-
},
|
|
93
|
-
}, async ({ x, y, duration, jitter }) => formatControlResult("点击", await requestControlApi("click", { x, y, duration, jitter })));
|
|
94
|
-
server.registerTool("control_double_click", {
|
|
95
|
-
title: "Control Double Click",
|
|
96
|
-
description: "双击指定坐标。",
|
|
97
|
-
inputSchema: {
|
|
98
|
-
x: z.number().int().min(0).describe("双击坐标 x"),
|
|
99
|
-
y: z.number().int().min(0).describe("双击坐标 y"),
|
|
100
|
-
duration: z
|
|
101
|
-
.number()
|
|
102
|
-
.int()
|
|
103
|
-
.min(0)
|
|
104
|
-
.optional()
|
|
105
|
-
.describe("单次按压时长,默认 20"),
|
|
106
|
-
interval: z
|
|
107
|
-
.number()
|
|
108
|
-
.int()
|
|
109
|
-
.min(0)
|
|
110
|
-
.optional()
|
|
111
|
-
.describe("两次点击间隔,默认 20"),
|
|
112
|
-
jitter: z.boolean().optional().describe("是否启用抖动,默认 false"),
|
|
113
|
-
},
|
|
114
|
-
}, async ({ x, y, duration, interval, jitter }) => formatControlResult("双击", await requestControlApi("doubleClick", {
|
|
115
|
-
x,
|
|
116
|
-
y,
|
|
117
|
-
duration,
|
|
118
|
-
interval,
|
|
119
|
-
jitter,
|
|
120
|
-
})));
|
|
121
|
-
server.registerTool("control_swipe", {
|
|
122
|
-
title: "Control Swipe",
|
|
123
|
-
description: "从起点滑动到终点。",
|
|
124
|
-
inputSchema: {
|
|
125
|
-
startX: z.number().int().min(0).describe("起点 x"),
|
|
126
|
-
startY: z.number().int().min(0).describe("起点 y"),
|
|
127
|
-
endX: z.number().int().min(0).describe("终点 x"),
|
|
128
|
-
endY: z.number().int().min(0).describe("终点 y"),
|
|
129
|
-
duration: z
|
|
130
|
-
.number()
|
|
131
|
-
.int()
|
|
132
|
-
.min(0)
|
|
133
|
-
.optional()
|
|
134
|
-
.describe("滑动时长,默认 100"),
|
|
135
|
-
jitter: z.boolean().optional().describe("是否启用抖动,默认 false"),
|
|
136
|
-
steps: z.number().int().min(1).optional().describe("分段步数,默认 6"),
|
|
137
|
-
},
|
|
138
|
-
}, async ({ startX, startY, endX, endY, duration, jitter, steps }) => formatControlResult("滑动", await requestControlApi("swipe", {
|
|
139
|
-
startX,
|
|
140
|
-
startY,
|
|
141
|
-
endX,
|
|
142
|
-
endY,
|
|
143
|
-
duration,
|
|
144
|
-
jitter,
|
|
145
|
-
steps,
|
|
146
|
-
})));
|
|
147
|
-
server.registerTool("control_press_button", {
|
|
148
|
-
title: "Control Press Button",
|
|
149
|
-
description: "按下指定系统按键。",
|
|
150
|
-
inputSchema: {
|
|
151
|
-
button: z.string().min(1).describe("按钮名称"),
|
|
152
|
-
},
|
|
153
|
-
}, async ({ button }) => formatControlResult("按键", await requestControlApi("pressButton", { button })));
|
|
154
|
-
server.registerTool("control_input", {
|
|
155
|
-
title: "Control Input",
|
|
156
|
-
description: "输入文本。",
|
|
157
|
-
inputSchema: {
|
|
158
|
-
text: z.string().min(1).describe("待输入文本"),
|
|
159
|
-
},
|
|
160
|
-
}, async ({ text }) => formatControlResult("输入", await requestControlApi("input", { text })));
|
|
161
|
-
server.registerTool("control_backspace", {
|
|
162
|
-
title: "Control Backspace",
|
|
163
|
-
description: "执行退格操作。",
|
|
164
|
-
inputSchema: {
|
|
165
|
-
count: z.number().int().min(1).optional().describe("退格次数,默认 1"),
|
|
166
|
-
},
|
|
167
|
-
}, async ({ count }) => formatControlResult("退格", await requestControlApi("backspace", { count })));
|
|
168
|
-
server.registerTool("control_enter", {
|
|
169
|
-
title: "Control Enter",
|
|
170
|
-
description: "执行回车操作。",
|
|
171
|
-
inputSchema: {},
|
|
172
|
-
}, async () => formatControlResult("回车", await requestControlApi("enter")));
|
|
173
|
-
server.registerTool("control_start_app", {
|
|
174
|
-
title: "Control Start App",
|
|
175
|
-
description: "启动指定应用。",
|
|
176
|
-
inputSchema: {
|
|
177
|
-
bundleId: z.string().min(1).describe("应用 bundleId"),
|
|
178
|
-
},
|
|
179
|
-
}, async ({ bundleId }) => formatControlResult("启动应用", await requestControlApi("startApp", { bundleId })));
|
|
180
|
-
server.registerTool("control_activate_app", {
|
|
181
|
-
title: "Control Activate App",
|
|
182
|
-
description: "激活指定应用。",
|
|
183
|
-
inputSchema: {
|
|
184
|
-
bundleId: z.string().min(1).describe("应用 bundleId"),
|
|
185
|
-
},
|
|
186
|
-
}, async ({ bundleId }) => formatControlResult("激活应用", await requestControlApi("activateApp", { bundleId })));
|
|
187
|
-
server.registerTool("control_stop_app", {
|
|
188
|
-
title: "Control Stop App",
|
|
189
|
-
description: "停止指定应用。",
|
|
190
|
-
inputSchema: {
|
|
191
|
-
bundleId: z.string().min(1).describe("应用 bundleId"),
|
|
192
|
-
},
|
|
193
|
-
}, async ({ bundleId }) => formatControlResult("停止应用", await requestControlApi("stopApp", { bundleId })));
|
|
194
|
-
server.registerTool("control_open_url", {
|
|
195
|
-
title: "Control Open URL",
|
|
196
|
-
description: "打开指定 URL。",
|
|
197
|
-
inputSchema: {
|
|
198
|
-
url: z.string().min(1).describe("目标 URL"),
|
|
199
|
-
},
|
|
200
|
-
}, async ({ url }) => formatControlResult("打开 URL", await requestControlApi("openURL", { url })));
|
|
201
|
-
}
|
package/dist/mcp/hid-tools.d.ts
DELETED
package/dist/mcp/hid-tools.js
DELETED
|
@@ -1,254 +0,0 @@
|
|
|
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.registerHidTools = registerHidTools;
|
|
37
|
-
const fsExtra = __importStar(require("fs-extra"));
|
|
38
|
-
const os = __importStar(require("os"));
|
|
39
|
-
const path = __importStar(require("path"));
|
|
40
|
-
const z = __importStar(require("zod/v4"));
|
|
41
|
-
const tool_utils_1 = require("./tool-utils");
|
|
42
|
-
/**
|
|
43
|
-
* 请求 HID 路由
|
|
44
|
-
* @param endpoint HID API 名称
|
|
45
|
-
* @param query 可选查询参数
|
|
46
|
-
* @returns 返回设备端 JSON 响应
|
|
47
|
-
* @example
|
|
48
|
-
* const payload = await requestHidApi("home")
|
|
49
|
-
*/
|
|
50
|
-
async function requestHidApi(endpoint, query) {
|
|
51
|
-
const target = await (0, tool_utils_1.resolveRuntimeHttpTarget)();
|
|
52
|
-
return (0, tool_utils_1.requestRuntimePathJson)(target, `/api/hid/${endpoint}`, query);
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* 格式化 HID 类 JSON 响应
|
|
56
|
-
* @param actionName 操作名称
|
|
57
|
-
* @param payload 设备端响应
|
|
58
|
-
* @returns 返回标准文本工具响应
|
|
59
|
-
* @example
|
|
60
|
-
* formatHidResult("打开录屏", { success: true })
|
|
61
|
-
*/
|
|
62
|
-
function formatHidResult(actionName, payload) {
|
|
63
|
-
const success = payload.success === true;
|
|
64
|
-
if ("data" in payload) {
|
|
65
|
-
return (0, tool_utils_1.createTextToolResult)(`${actionName}${success ? "成功" : "失败"}:\n${(0, tool_utils_1.formatRuntimeJsonText)(payload.data)}`, !success);
|
|
66
|
-
}
|
|
67
|
-
return (0, tool_utils_1.createTextToolResult)(`${actionName}${success ? "成功" : "失败"}`, !success);
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* 注册 HID API 对应 MCP 工具
|
|
71
|
-
* @param server MCP 服务实例
|
|
72
|
-
* @returns 无返回值
|
|
73
|
-
* @example
|
|
74
|
-
* registerHidTools(server)
|
|
75
|
-
*/
|
|
76
|
-
function registerHidTools(server) {
|
|
77
|
-
server.registerTool("hid_shortcut_screenshot", {
|
|
78
|
-
title: "HID Shortcut Screenshot",
|
|
79
|
-
description: "获取快捷指令截图。可返回 base64,或落地到文件后返回文件路径(默认写入系统临时目录)。",
|
|
80
|
-
inputSchema: {
|
|
81
|
-
format: z
|
|
82
|
-
.enum(["file", "base64"])
|
|
83
|
-
.optional()
|
|
84
|
-
.default("file")
|
|
85
|
-
.describe("截图返回格式:file=文件路径,base64=图片 base64"),
|
|
86
|
-
outputPath: z
|
|
87
|
-
.string()
|
|
88
|
-
.min(1)
|
|
89
|
-
.optional()
|
|
90
|
-
.describe("当 format=file 时可指定输出路径,不传则写入系统临时目录"),
|
|
91
|
-
},
|
|
92
|
-
}, async ({ format, outputPath }) => {
|
|
93
|
-
const target = await (0, tool_utils_1.resolveRuntimeHttpTarget)();
|
|
94
|
-
const payload = await requestHidApi("shortcutScreenshotBase64");
|
|
95
|
-
const success = payload.success === true;
|
|
96
|
-
const base64 = typeof payload.data === "string" && payload.data ? payload.data : null;
|
|
97
|
-
if (!success || !base64) {
|
|
98
|
-
return (0, tool_utils_1.createTextToolResult)("快捷指令截图失败", true);
|
|
99
|
-
}
|
|
100
|
-
if (format === "base64") {
|
|
101
|
-
return (0, tool_utils_1.createTextToolResult)(`快捷指令截图成功: ${target.label}\nformat: base64\n${base64}`);
|
|
102
|
-
}
|
|
103
|
-
const buffer = Buffer.from(base64, "base64");
|
|
104
|
-
const targetPath = outputPath && outputPath.trim()
|
|
105
|
-
? path.resolve(outputPath.trim())
|
|
106
|
-
: path.join(os.tmpdir(), `ms-mcp-hid-shortcut-screenshot-${Date.now()}-${Math.random()
|
|
107
|
-
.toString(36)
|
|
108
|
-
.slice(2, 8)}.jpg`);
|
|
109
|
-
await fsExtra.ensureDir(path.dirname(targetPath));
|
|
110
|
-
await fsExtra.writeFile(targetPath, buffer);
|
|
111
|
-
return (0, tool_utils_1.createTextToolResult)(`快捷指令截图成功: ${target.label}\nformat: file\npath: ${targetPath}\nsize: ${buffer.length} bytes`);
|
|
112
|
-
});
|
|
113
|
-
server.registerTool("hid_open_record_screen", {
|
|
114
|
-
title: "HID Open Record Screen",
|
|
115
|
-
description: "打开录屏界面。",
|
|
116
|
-
inputSchema: {},
|
|
117
|
-
}, async () => formatHidResult("打开录屏界面", await requestHidApi("openRecordScreen")));
|
|
118
|
-
server.registerTool("hid_is_recording", {
|
|
119
|
-
title: "HID Is Recording",
|
|
120
|
-
description: "检查是否正在录屏。",
|
|
121
|
-
inputSchema: {},
|
|
122
|
-
}, async () => formatHidResult("查询录屏状态", await requestHidApi("isRecording")));
|
|
123
|
-
server.registerTool("hid_move", {
|
|
124
|
-
title: "HID Move",
|
|
125
|
-
description: "移动指针。",
|
|
126
|
-
inputSchema: {
|
|
127
|
-
x: z.number().int().describe("目标坐标 x"),
|
|
128
|
-
y: z.number().int().describe("目标坐标 y"),
|
|
129
|
-
},
|
|
130
|
-
}, async ({ x, y }) => formatHidResult("移动指针", await requestHidApi("move", { x, y })));
|
|
131
|
-
server.registerTool("hid_click", {
|
|
132
|
-
title: "HID Click",
|
|
133
|
-
description: "点击指针。",
|
|
134
|
-
inputSchema: {
|
|
135
|
-
x: z.number().int().describe("点击坐标 x"),
|
|
136
|
-
y: z.number().int().describe("点击坐标 y"),
|
|
137
|
-
duration: z
|
|
138
|
-
.number()
|
|
139
|
-
.int()
|
|
140
|
-
.min(0)
|
|
141
|
-
.optional()
|
|
142
|
-
.describe("按压时长,默认 20"),
|
|
143
|
-
jitter: z.boolean().optional().describe("是否启用抖动,默认 false"),
|
|
144
|
-
},
|
|
145
|
-
}, async ({ x, y, duration, jitter }) => formatHidResult("点击指针", await requestHidApi("click", { x, y, duration, jitter })));
|
|
146
|
-
server.registerTool("hid_double_click", {
|
|
147
|
-
title: "HID Double Click",
|
|
148
|
-
description: "双击指针。",
|
|
149
|
-
inputSchema: {
|
|
150
|
-
x: z.number().int().describe("双击坐标 x"),
|
|
151
|
-
y: z.number().int().describe("双击坐标 y"),
|
|
152
|
-
duration: z
|
|
153
|
-
.number()
|
|
154
|
-
.int()
|
|
155
|
-
.min(0)
|
|
156
|
-
.optional()
|
|
157
|
-
.describe("单次按压时长,默认 20"),
|
|
158
|
-
interval: z
|
|
159
|
-
.number()
|
|
160
|
-
.int()
|
|
161
|
-
.min(0)
|
|
162
|
-
.optional()
|
|
163
|
-
.describe("两次点击间隔,默认 100"),
|
|
164
|
-
jitter: z.boolean().optional().describe("是否启用抖动,默认 false"),
|
|
165
|
-
},
|
|
166
|
-
}, async ({ x, y, duration, interval, jitter }) => formatHidResult("双击指针", await requestHidApi("doubleClick", {
|
|
167
|
-
x,
|
|
168
|
-
y,
|
|
169
|
-
duration,
|
|
170
|
-
interval,
|
|
171
|
-
jitter,
|
|
172
|
-
})));
|
|
173
|
-
server.registerTool("hid_swipe", {
|
|
174
|
-
title: "HID Swipe",
|
|
175
|
-
description: "滑动指针。",
|
|
176
|
-
inputSchema: {
|
|
177
|
-
startX: z.number().int().describe("起点 x"),
|
|
178
|
-
startY: z.number().int().describe("起点 y"),
|
|
179
|
-
endX: z.number().int().describe("终点 x"),
|
|
180
|
-
endY: z.number().int().describe("终点 y"),
|
|
181
|
-
jitter: z.boolean().optional().describe("是否启用抖动,默认 true"),
|
|
182
|
-
steps: z.number().int().min(1).optional().describe("分段步数,默认 10"),
|
|
183
|
-
},
|
|
184
|
-
}, async ({ startX, startY, endX, endY, jitter, steps }) => formatHidResult("滑动指针", await requestHidApi("swipe", {
|
|
185
|
-
startX,
|
|
186
|
-
startY,
|
|
187
|
-
endX,
|
|
188
|
-
endY,
|
|
189
|
-
jitter,
|
|
190
|
-
steps,
|
|
191
|
-
})));
|
|
192
|
-
server.registerTool("hid_home", {
|
|
193
|
-
title: "HID Home",
|
|
194
|
-
description: "返回桌面。",
|
|
195
|
-
inputSchema: {},
|
|
196
|
-
}, async () => formatHidResult("返回桌面", await requestHidApi("home")));
|
|
197
|
-
server.registerTool("hid_recent", {
|
|
198
|
-
title: "HID Recent",
|
|
199
|
-
description: "打开 App 切换器。",
|
|
200
|
-
inputSchema: {},
|
|
201
|
-
}, async () => formatHidResult("打开最近任务", await requestHidApi("recent")));
|
|
202
|
-
server.registerTool("hid_open_url", {
|
|
203
|
-
title: "HID Open URL",
|
|
204
|
-
description: "通过 HID 打开 URL。",
|
|
205
|
-
inputSchema: {
|
|
206
|
-
url: z.string().min(1).describe("目标 URL"),
|
|
207
|
-
},
|
|
208
|
-
}, async ({ url }) => formatHidResult("打开 URL", await requestHidApi("openURL", { url })));
|
|
209
|
-
server.registerTool("hid_open_app", {
|
|
210
|
-
title: "HID Open App",
|
|
211
|
-
description: "打开应用。",
|
|
212
|
-
inputSchema: {
|
|
213
|
-
name: z.string().min(1).describe("应用名称或标识"),
|
|
214
|
-
},
|
|
215
|
-
}, async ({ name }) => formatHidResult("打开应用", await requestHidApi("openApp", { name })));
|
|
216
|
-
server.registerTool("hid_close_app", {
|
|
217
|
-
title: "HID Close App",
|
|
218
|
-
description: "关闭应用。",
|
|
219
|
-
inputSchema: {
|
|
220
|
-
name: z.string().min(1).describe("应用名称或标识"),
|
|
221
|
-
},
|
|
222
|
-
}, async ({ name }) => formatHidResult("关闭应用", await requestHidApi("closeApp", { name })));
|
|
223
|
-
server.registerTool("hid_current_app_info", {
|
|
224
|
-
title: "HID Current App Info",
|
|
225
|
-
description: "获取当前应用信息。",
|
|
226
|
-
inputSchema: {},
|
|
227
|
-
}, async () => formatHidResult("获取当前应用信息", await requestHidApi("currentAppInfo")));
|
|
228
|
-
server.registerTool("hid_input", {
|
|
229
|
-
title: "HID Input",
|
|
230
|
-
description: "执行输入。",
|
|
231
|
-
inputSchema: {
|
|
232
|
-
text: z.string().min(1).describe("待输入文本"),
|
|
233
|
-
},
|
|
234
|
-
}, async ({ text }) => formatHidResult("输入文本", await requestHidApi("input", { text })));
|
|
235
|
-
server.registerTool("hid_input_simple", {
|
|
236
|
-
title: "HID Input Simple",
|
|
237
|
-
description: "执行简单输入。",
|
|
238
|
-
inputSchema: {
|
|
239
|
-
text: z.string().min(1).describe("待输入文本"),
|
|
240
|
-
},
|
|
241
|
-
}, async ({ text }) => formatHidResult("简单输入", await requestHidApi("inputSimple", { text })));
|
|
242
|
-
server.registerTool("hid_backspace", {
|
|
243
|
-
title: "HID Backspace",
|
|
244
|
-
description: "执行退格。",
|
|
245
|
-
inputSchema: {
|
|
246
|
-
count: z.number().int().min(1).optional().describe("退格次数,默认 1"),
|
|
247
|
-
},
|
|
248
|
-
}, async ({ count }) => formatHidResult("退格", await requestHidApi("backspace", { count })));
|
|
249
|
-
server.registerTool("hid_enter", {
|
|
250
|
-
title: "HID Enter",
|
|
251
|
-
description: "执行回车。",
|
|
252
|
-
inputSchema: {},
|
|
253
|
-
}, async () => formatHidResult("回车", await requestHidApi("enter")));
|
|
254
|
-
}
|
package/dist/mcp/ime-tools.d.ts
DELETED
package/dist/mcp/ime-tools.js
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
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.registerImeTools = registerImeTools;
|
|
37
|
-
const z = __importStar(require("zod/v4"));
|
|
38
|
-
const tool_utils_1 = require("./tool-utils");
|
|
39
|
-
/**
|
|
40
|
-
* 请求 IME 路由
|
|
41
|
-
* @param endpoint IME API 名称
|
|
42
|
-
* @param query 可选查询参数
|
|
43
|
-
* @returns 返回设备端 JSON 响应
|
|
44
|
-
* @example
|
|
45
|
-
* const payload = await requestImeApi("getText")
|
|
46
|
-
*/
|
|
47
|
-
async function requestImeApi(endpoint, query) {
|
|
48
|
-
const target = await (0, tool_utils_1.resolveRuntimeHttpTarget)();
|
|
49
|
-
return (0, tool_utils_1.requestRuntimePathJson)(target, `/api/ime/${endpoint}`, query);
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* 格式化 IME 类 JSON 响应
|
|
53
|
-
* @param actionName 操作名称
|
|
54
|
-
* @param payload 设备端响应
|
|
55
|
-
* @returns 返回标准文本工具响应
|
|
56
|
-
* @example
|
|
57
|
-
* formatImeResult("获取文本", { success: true, data: "hello" })
|
|
58
|
-
*/
|
|
59
|
-
function formatImeResult(actionName, payload) {
|
|
60
|
-
const success = payload.success === true;
|
|
61
|
-
if ("data" in payload) {
|
|
62
|
-
return (0, tool_utils_1.createTextToolResult)(`${actionName}${success ? "成功" : "失败"}:\n${(0, tool_utils_1.formatRuntimeJsonText)(payload.data)}`, !success);
|
|
63
|
-
}
|
|
64
|
-
return (0, tool_utils_1.createTextToolResult)(`${actionName}${success ? "成功" : "失败"}`, !success);
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* 注册 IME API 对应 MCP 工具
|
|
68
|
-
* @param server MCP 服务实例
|
|
69
|
-
* @returns 无返回值
|
|
70
|
-
* @example
|
|
71
|
-
* registerImeTools(server)
|
|
72
|
-
*/
|
|
73
|
-
function registerImeTools(server) {
|
|
74
|
-
server.registerTool("ime_is_ok", {
|
|
75
|
-
title: "IME Is OK",
|
|
76
|
-
description: "检查 IME 是否可用。",
|
|
77
|
-
inputSchema: {},
|
|
78
|
-
}, async () => formatImeResult("检查 IME", await requestImeApi("isOk")));
|
|
79
|
-
server.registerTool("ime_input", {
|
|
80
|
-
title: "IME Input",
|
|
81
|
-
description: "执行输入。",
|
|
82
|
-
inputSchema: {
|
|
83
|
-
text: z.string().min(1).describe("待输入文本"),
|
|
84
|
-
},
|
|
85
|
-
}, async ({ text }) => formatImeResult("输入文本", await requestImeApi("input", { text })));
|
|
86
|
-
server.registerTool("ime_get_text", {
|
|
87
|
-
title: "IME Get Text",
|
|
88
|
-
description: "获取当前输入文本。",
|
|
89
|
-
inputSchema: {},
|
|
90
|
-
}, async () => formatImeResult("获取当前文本", await requestImeApi("getText")));
|
|
91
|
-
server.registerTool("ime_clear_text", {
|
|
92
|
-
title: "IME Clear Text",
|
|
93
|
-
description: "清除当前输入文本。",
|
|
94
|
-
inputSchema: {},
|
|
95
|
-
}, async () => formatImeResult("清除文本", await requestImeApi("clearText")));
|
|
96
|
-
server.registerTool("ime_paste", {
|
|
97
|
-
title: "IME Paste",
|
|
98
|
-
description: "粘贴文本。",
|
|
99
|
-
inputSchema: {
|
|
100
|
-
text: z.string().optional().default("").describe("待粘贴文本,可为空字符串"),
|
|
101
|
-
},
|
|
102
|
-
}, async ({ text }) => formatImeResult("粘贴文本", await requestImeApi("paste", { text })));
|
|
103
|
-
server.registerTool("ime_press_del", {
|
|
104
|
-
title: "IME Press Delete",
|
|
105
|
-
description: "按下删除键。",
|
|
106
|
-
inputSchema: {},
|
|
107
|
-
}, async () => formatImeResult("删除字符", await requestImeApi("pressDel")));
|
|
108
|
-
server.registerTool("ime_press_enter", {
|
|
109
|
-
title: "IME Press Enter",
|
|
110
|
-
description: "按下回车键。",
|
|
111
|
-
inputSchema: {},
|
|
112
|
-
}, async () => formatImeResult("按下回车", await requestImeApi("pressEnter")));
|
|
113
|
-
server.registerTool("ime_dismiss", {
|
|
114
|
-
title: "IME Dismiss",
|
|
115
|
-
description: "隐藏 IME。",
|
|
116
|
-
inputSchema: {},
|
|
117
|
-
}, async () => formatImeResult("隐藏 IME", await requestImeApi("dismiss")));
|
|
118
|
-
server.registerTool("ime_get_clipboard", {
|
|
119
|
-
title: "IME Get Clipboard",
|
|
120
|
-
description: "获取剪贴板内容。",
|
|
121
|
-
inputSchema: {},
|
|
122
|
-
}, async () => formatImeResult("获取剪贴板", await requestImeApi("getClipboard")));
|
|
123
|
-
server.registerTool("ime_set_clipboard", {
|
|
124
|
-
title: "IME Set Clipboard",
|
|
125
|
-
description: "设置剪贴板内容。",
|
|
126
|
-
inputSchema: {
|
|
127
|
-
text: z.string().min(1).describe("剪贴板文本"),
|
|
128
|
-
},
|
|
129
|
-
}, async ({ text }) => formatImeResult("设置剪贴板", await requestImeApi("setClipboard", { text })));
|
|
130
|
-
}
|
package/dist/mcp/mirror-tools.js
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
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.registerMirrorTools = registerMirrorTools;
|
|
37
|
-
const z = __importStar(require("zod/v4"));
|
|
38
|
-
const tool_utils_1 = require("./tool-utils");
|
|
39
|
-
/**
|
|
40
|
-
* 注册镜像流相关 MCP 工具
|
|
41
|
-
* @param server MCP 服务实例
|
|
42
|
-
* @returns 无返回值
|
|
43
|
-
* @example
|
|
44
|
-
* registerMirrorTools(server)
|
|
45
|
-
*/
|
|
46
|
-
function registerMirrorTools(server) {
|
|
47
|
-
server.registerTool("get_mirror_mjpeg_url", {
|
|
48
|
-
title: "Get Mirror MJPEG URL",
|
|
49
|
-
description: "生成设备镜像 MJPEG 流地址。MCP 普通文本/图片响应不适合持续显示 MJPEG,建议将返回 URL 交给浏览器或支持 MJPEG 的查看器打开。",
|
|
50
|
-
inputSchema: {
|
|
51
|
-
fps: z.number().int().min(1).max(60).optional().default(10).describe("帧率,默认 10"),
|
|
52
|
-
quality: z
|
|
53
|
-
.number()
|
|
54
|
-
.min(0.1)
|
|
55
|
-
.max(1)
|
|
56
|
-
.optional()
|
|
57
|
-
.default(0.25)
|
|
58
|
-
.describe("压缩质量,默认 0.25"),
|
|
59
|
-
scalingFactor: z
|
|
60
|
-
.number()
|
|
61
|
-
.min(0.1)
|
|
62
|
-
.max(1)
|
|
63
|
-
.optional()
|
|
64
|
-
.default(1)
|
|
65
|
-
.describe("缩放因子,默认 1.0"),
|
|
66
|
-
},
|
|
67
|
-
}, async ({ fps, quality, scalingFactor }) => {
|
|
68
|
-
const target = await (0, tool_utils_1.resolveRuntimeHttpTarget)();
|
|
69
|
-
const url = new URL(`http://${target.ip}:${target.port}/mirror/image`);
|
|
70
|
-
url.searchParams.set("fps", String(fps));
|
|
71
|
-
url.searchParams.set("quality", String(quality));
|
|
72
|
-
url.searchParams.set("scalingFactor", String(scalingFactor));
|
|
73
|
-
return (0, tool_utils_1.createTextToolResult)([
|
|
74
|
-
`MJPEG 地址: ${url.toString()}`,
|
|
75
|
-
`设备: ${target.label}`,
|
|
76
|
-
`fps: ${fps}`,
|
|
77
|
-
`quality: ${quality}`,
|
|
78
|
-
`scalingFactor: ${scalingFactor}`,
|
|
79
|
-
"说明: MCP 工具本身不适合持续渲染 MJPEG 流,建议把这个地址交给浏览器或支持 MJPEG 的播放器打开。",
|
|
80
|
-
].join("\n"));
|
|
81
|
-
});
|
|
82
|
-
}
|