easytouch-windows 1.0.18 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -25
- package/SKILL.md +81 -3
- package/bin/arm64/et.exe +0 -0
- package/bin/x64/et.exe +0 -0
- package/init.js +124 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
# EasyTouch
|
|
2
2
|
|
|
3
|
+
## 中文 | [English](README.en.md)
|
|
4
|
+
|
|
3
5
|
跨平台系统自动化操作工具,支持 Windows、Linux、macOS。提供 CLI 命令行和 MCP 服务器两种使用方式,支持鼠标键盘控制、屏幕截图、窗口管理、系统信息查询等功能。
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
目前支持以下操作系统的 x64 和 ARM64 两种 CPU 架构:
|
|
6
8
|
|
|
7
9
|
- [x] Windows
|
|
8
10
|
|
|
9
11
|
- [x] Linux
|
|
10
|
-
- [
|
|
12
|
+
- [x] MACOS(目前缺少设备验证功能)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
**你能用它做什么?**
|
|
11
17
|
|
|
12
18
|
大家平时使用各类 AI 编程工具,写页面是不是经常碰到 AI 写的页面怎么也不满意,写出来跟设计稿差异很大,这是因为 AI 只能通过读写代码来改进代码,它看不到界面,不像人类有感官。
|
|
13
19
|
|
|
14
|
-
|
|
20
|
+
如果你想通过 OpenClaw 接入微信、飞书,让它截图桌面发给你,但是 OpenClaw 像弱智一样搞不好,或者你希望 AI 能够操作你电脑的设备为你工作,那么 EasyTouch 非常适合你。
|
|
15
21
|
|
|
16
22
|
|
|
17
23
|
|
|
18
|
-
|
|
24
|
+
因为 EasyTouch 是给 AI 装上手和眼睛,它支持以下功能:
|
|
19
25
|
|
|
20
26
|
- 系统信息:系统、CPU、内存、磁盘、进程
|
|
21
27
|
- 屏幕能力:显示器枚举、像素取色、截图
|
|
@@ -29,36 +35,51 @@
|
|
|
29
35
|
|
|
30
36
|
### 安装
|
|
31
37
|
|
|
32
|
-
|
|
38
|
+
推荐安装带自动平台选择能力的启动包;如果你只想安装当前系统,也可以直接安装对应平台包:
|
|
33
39
|
|
|
34
40
|
```bash
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
# 推荐:自动匹配当前平台
|
|
42
|
+
npm i -g @whuanle/easytouch
|
|
37
43
|
|
|
38
|
-
也可以只安装当前操作系统对应的平台包:
|
|
39
|
-
|
|
40
|
-
```
|
|
41
44
|
# Windows
|
|
42
|
-
npm i
|
|
45
|
+
npm i -g easytouch-windows
|
|
43
46
|
|
|
44
47
|
# Linux
|
|
45
|
-
npm i
|
|
48
|
+
npm i -g easytouch-linux
|
|
46
49
|
|
|
47
50
|
# macOS
|
|
48
51
|
npm i -g easytouch-macos
|
|
49
52
|
```
|
|
50
53
|
|
|
51
|
-
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
`@whuanle/easytouch` 会在当前主机上调用对应的平台包;平台包内部同时包含 x64 和 arm64 二进制,安装后会根据当前 CPU 架构自动选择对应程序文件。
|
|
57
|
+
|
|
58
|
+
如果是 Windows,安装后在 `AppData/Roaming/npm` 目录会发现名为 `et` 的文件。
|
|
59
|
+
|
|
60
|
+

|
|
52
61
|
|
|
53
62
|
|
|
54
63
|
|
|
55
64
|
### 使用示例
|
|
56
65
|
|
|
66
|
+
截取屏幕。
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
et screen capture --path a.png
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+

|
|
75
|
+
|
|
57
76
|
|
|
58
77
|
|
|
78
|
+
<img src="images/d4ba9a4e7b88e26b30118b3c76f2dce5.jpg" alt="d4ba9a4e7b88e26b30118b3c76f2dce5" style="zoom: 25%;" />
|
|
59
79
|
|
|
60
80
|
|
|
61
|
-
|
|
81
|
+
|
|
82
|
+
### 作为 Skills 给 AI 使用(推荐)
|
|
62
83
|
|
|
63
84
|
只需要执行命令安装 skills 即可。
|
|
64
85
|
|
|
@@ -66,9 +87,9 @@ npm i -g easytouch-macos
|
|
|
66
87
|
npx skills add https://github.com/whuanle/EasyTouch
|
|
67
88
|
```
|
|
68
89
|
|
|
90
|
+
> 注:skills 里面不带脚本,需提前安装当前平台包,第一次使用 AI 会自动安装,或者手动安装,例如 `npm i -g easytouch-windows`、`npm i -g easytouch-linux` 或 `npm i -g easytouch-macos`。
|
|
69
91
|
|
|
70
92
|
|
|
71
|
-
注:skills 里面不带脚本,需提前使用 `npm i easytouch` 或当前平台包安装工具。
|
|
72
93
|
|
|
73
94
|

|
|
74
95
|
|
|
@@ -78,51 +99,119 @@ npx skills add https://github.com/whuanle/EasyTouch
|
|
|
78
99
|
|
|
79
100
|
如果只是给 AI 工具使用,建议使用 skills 即可,配置 MCP 可能会麻烦一些。
|
|
80
101
|
|
|
81
|
-
在 Claude、Cursor 等工具中,配置 MCP
|
|
102
|
+
在 Claude、Cursor、VS Code、Sidecar 等工具中,配置 MCP 的方式基本一致。通过 npm 安装后,推荐先执行包内 `init.js`,把当前操作系统和 CPU 对应的原生二进制复制成真正的 `et` 程序,然后让 MCP 直接调用这个原生文件。这样可以避免 `et.cmd`、`et.sh`、`npx.cmd` 这类桥接层。
|
|
82
103
|
|
|
83
104
|
|
|
84
105
|
|
|
85
106
|
在配置文件中添加:
|
|
86
107
|
|
|
87
|
-
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
**本地安装后(推荐)**
|
|
111
|
+
|
|
112
|
+
先执行:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
npm i @whuanle/easytouch
|
|
116
|
+
node ./node_modules/@whuanle/easytouch/init.js
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
如果安装的是 `@whuanle/easytouch`,这一步会先自动安装当前系统对应的平台包,再复制出原生 `et` 文件。
|
|
120
|
+
|
|
121
|
+
执行后会生成:
|
|
122
|
+
|
|
123
|
+
- Windows:`./node_modules/@whuanle/easytouch/et.exe`
|
|
124
|
+
- Linux / macOS:`./node_modules/@whuanle/easytouch/et`
|
|
125
|
+
|
|
126
|
+
然后在 MCP 配置里直接指向这个原生文件:
|
|
88
127
|
|
|
89
128
|
```json
|
|
90
129
|
{
|
|
91
130
|
"mcpServers": {
|
|
92
131
|
"easytouch": {
|
|
93
|
-
"command": "
|
|
94
|
-
"args": ["
|
|
132
|
+
"command": "<你的项目路径>/node_modules/@whuanle/easytouch/et",
|
|
133
|
+
"args": ["mcp-stdio"]
|
|
95
134
|
}
|
|
96
135
|
}
|
|
97
136
|
}
|
|
98
137
|
```
|
|
99
138
|
|
|
100
|
-
|
|
139
|
+
> Windows 请把文件名写成 `et.exe`。Linux / macOS 写 `et`。
|
|
140
|
+
|
|
141
|
+
**全局安装后**
|
|
142
|
+
|
|
143
|
+
如果你已经全局安装并且宿主能正确处理 PATH,也仍然可以直接使用全局 `et`。首次运行时,如果平台包还没装好,启动器也会自动补装当前平台包:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
npm i -g @whuanle/easytouch
|
|
147
|
+
```
|
|
101
148
|
|
|
102
149
|
```json
|
|
103
150
|
{
|
|
104
151
|
"mcpServers": {
|
|
105
152
|
"easytouch": {
|
|
106
|
-
"command": "
|
|
107
|
-
"args": ["-
|
|
153
|
+
"command": "et",
|
|
154
|
+
"args": ["mcp-stdio"]
|
|
108
155
|
}
|
|
109
156
|
}
|
|
110
157
|
}
|
|
111
158
|
```
|
|
112
159
|
|
|
113
|
-
|
|
160
|
+
**宿主程序不走 PATH 时(旧方式)**
|
|
161
|
+
|
|
162
|
+
- Windows:把 `command` 改成 `C:\\Users\\<你自己的用户名>\\AppData\\Roaming\\npm\\et.cmd`
|
|
163
|
+
- Linux / macOS:先执行 `npm prefix -g`,然后把 `command` 改成 `<prefix>/bin/et`
|
|
164
|
+
|
|
165
|
+
**不想初始化原生文件时(备用)**
|
|
166
|
+
|
|
167
|
+
如果你不想先执行 `init.js`,也可以临时通过 `npx` 启动。这里同样建议统一使用 `@whuanle/easytouch`,不要再按平台分别写包名。首次运行可能会多花一点时间,因为会自动安装当前平台包。
|
|
168
|
+
|
|
169
|
+
- Windows:`command` 推荐写 `npx.cmd`
|
|
170
|
+
- Linux / macOS:`command` 写 `npx`
|
|
114
171
|
|
|
115
172
|
```json
|
|
116
173
|
{
|
|
117
174
|
"mcpServers": {
|
|
118
175
|
"easytouch": {
|
|
119
|
-
"command": "
|
|
120
|
-
"args": ["
|
|
176
|
+
"command": "npx.cmd",
|
|
177
|
+
"args": ["-y", "@whuanle/easytouch", "mcp-stdio"]
|
|
121
178
|
}
|
|
122
179
|
}
|
|
123
180
|
}
|
|
124
181
|
```
|
|
125
182
|
|
|
183
|
+
> 如果是在 Windows 的 GUI 程序中配置 MCP,直接用 `init.js` 生成的 `et.exe` 最稳。只有在走 `npx` 或全局 npm 命令时,才需要关心 `npx.cmd`、`et.cmd` 这些桥接文件;常见失败表现就是 `LOCAL_PROCESS_ERROR`。
|
|
184
|
+
|
|
185
|
+
Linux / macOS 如果使用这段备用配置,把 `command` 改回 `npx` 即可。
|
|
186
|
+
|
|
187
|
+
### 语义元素定位
|
|
188
|
+
|
|
189
|
+
当截图交给 AI 后,单靠图片反推点击坐标通常不够稳定。EasyTouch 现在支持先读取当前窗口的语义元素树,再按元素查找、等待、点击或 invoke:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
et element tree --output json
|
|
193
|
+
et element find --name "确定" --control-type Button --output json
|
|
194
|
+
et wait element --name "保存" --control-type Button --timeout-ms 5000 --output json
|
|
195
|
+
et element click --element-id root/0/3 --output json
|
|
196
|
+
et element invoke --element-id root/0/3 --output json
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
说明:
|
|
200
|
+
|
|
201
|
+
- `element tree` 默认读取当前前台窗口,也可以通过 `--window-handle` 指定目标窗口。
|
|
202
|
+
- 返回结果里会包含 `element_id`、`control_type`、`automation_id`、`class_name`、`framework_id`、`center`、`bounds` 和 `children`,适合让 AI 像读 HTML DOM 一样选元素。
|
|
203
|
+
- `element find` 会基于 `element_id`、`name`、`automation_id`、`class_name`、`control_type`、`framework_id` 搜索元素树,并返回第一个匹配元素。
|
|
204
|
+
- `wait element` 会轮询元素树,直到匹配元素出现,适合弹窗、延迟渲染按钮、异步加载表单等场景。
|
|
205
|
+
- `element click` 会重新解析 `element_id`,激活目标窗口,再点击元素中心点,不需要 AI 自己从截图里估算坐标。
|
|
206
|
+
- `element invoke` 当前会走平台语义动作或元素中心点击回退,适合让模型统一表达“点这个控件”。
|
|
207
|
+
- 还可以用 `--max-depth`、`--max-children`、`--max-nodes` 控制树的规模,避免把过大的界面树一次性都送给模型。
|
|
208
|
+
|
|
209
|
+
平台说明:
|
|
210
|
+
|
|
211
|
+
- Windows:通过 UI Automation + PowerShell 工作。
|
|
212
|
+
- Linux:依赖 `python3` 或 `python` 能导入 `pyatspi`,点击回退依赖 `xdotool`,当前以 X11/XWayland 会话为主。
|
|
213
|
+
- macOS:依赖 `osascript` + System Events UI Scripting,宿主进程需要授予 Accessibility 和 Automation 权限。
|
|
214
|
+
|
|
126
215
|
|
|
127
216
|
|
|
128
217
|
|
package/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: easytouch
|
|
3
|
-
description:
|
|
3
|
+
description: 跨平台系统自动化操作工具,支持 Windows、Linux、macOS。提供 CLI 命令行和 MCP 服务器两种使用方式,支持鼠标键盘控制、屏幕截图、窗口管理、系统信息查询等功能。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# EasyTouch Skill
|
|
@@ -18,9 +18,21 @@ description: EasyTouch Skill 接入文档(CLI + MCP)。
|
|
|
18
18
|
### npm 安装
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
-
|
|
21
|
+
# 推荐:自动匹配当前平台
|
|
22
|
+
npm install -g @whuanle/easytouch
|
|
23
|
+
|
|
24
|
+
# Windows
|
|
25
|
+
npm install -g easytouch-windows
|
|
26
|
+
|
|
27
|
+
# Linux
|
|
28
|
+
npm install -g easytouch-linux
|
|
29
|
+
|
|
30
|
+
# macOS
|
|
31
|
+
npm install -g easytouch-macos
|
|
22
32
|
```
|
|
23
33
|
|
|
34
|
+
|
|
35
|
+
|
|
24
36
|
安装后命令入口:
|
|
25
37
|
|
|
26
38
|
```bash
|
|
@@ -352,15 +364,81 @@ et mcp-stdio --output json
|
|
|
352
364
|
|
|
353
365
|
### 配置示例
|
|
354
366
|
|
|
367
|
+
优先在安装后执行包内 `init.js`,把真实原生 `et` 程序复制出来,再让 MCP 直接调用这个文件:
|
|
368
|
+
|
|
369
|
+
```bash
|
|
370
|
+
npm i @whuanle/easytouch
|
|
371
|
+
node ./node_modules/@whuanle/easytouch/init.js
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
如果安装的是 `@whuanle/easytouch`,这一步会先自动安装当前系统对应的平台包,再生成原生 `et` 文件。
|
|
375
|
+
|
|
376
|
+
生成后的默认路径:
|
|
377
|
+
|
|
378
|
+
- Windows:`./node_modules/@whuanle/easytouch/et.exe`
|
|
379
|
+
- Linux / macOS:`./node_modules/@whuanle/easytouch/et`
|
|
380
|
+
|
|
381
|
+
推荐配置:
|
|
382
|
+
|
|
355
383
|
```json
|
|
356
384
|
{
|
|
357
385
|
"mcpServers": {
|
|
358
386
|
"easytouch": {
|
|
359
|
-
"command": "et",
|
|
387
|
+
"command": "<你的项目路径>/node_modules/@whuanle/easytouch/et",
|
|
360
388
|
"args": ["mcp-stdio"]
|
|
361
389
|
}
|
|
362
390
|
}
|
|
363
391
|
}
|
|
364
392
|
```
|
|
365
393
|
|
|
394
|
+
Windows 请把文件名写成 `et.exe`。Linux / macOS 写 `et`。
|
|
395
|
+
|
|
396
|
+
如果你已经全局安装并且宿主能正确处理 PATH,也可以继续直接调用全局 `et`。首次运行时,如果平台包缺失,启动器也会自动安装当前平台包。
|
|
397
|
+
|
|
398
|
+
如果宿主程序不能从 PATH 找到命令,旧方式仍可用:
|
|
399
|
+
|
|
400
|
+
- Windows:把 `command` 改成 `C:\Users\<你自己的用户名>\AppData\Roaming\npm\et.cmd`
|
|
401
|
+
- Linux / macOS:先执行 `npm prefix -g`,再把 `command` 改成 `<prefix>/bin/et`
|
|
402
|
+
|
|
403
|
+
如果不想执行 `init.js`,也可以临时通过 `npx` 启动。首次运行可能会稍慢,因为会自动安装当前平台包:
|
|
404
|
+
|
|
405
|
+
- Windows:`command` 推荐写 `npx.cmd`
|
|
406
|
+
- Linux / macOS:`command` 写 `npx`
|
|
407
|
+
|
|
408
|
+
```json
|
|
409
|
+
{
|
|
410
|
+
"mcpServers": {
|
|
411
|
+
"easytouch": {
|
|
412
|
+
"command": "npx.cmd",
|
|
413
|
+
"args": ["-y", "@whuanle/easytouch", "mcp-stdio"]
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
Linux / macOS 如果使用这段备用配置,把 `command` 改回 `npx` 即可。
|
|
420
|
+
|
|
421
|
+
如果 Windows 宿主报 `LOCAL_PROCESS_ERROR`,优先改用 `init.js` 生成的 `et.exe`;如果仍走 npm 命令,再检查这里是不是还写成了 `npx`。
|
|
422
|
+
|
|
423
|
+
### 语义元素树定位
|
|
424
|
+
|
|
425
|
+
当需要更稳定地点击控件时,可以先读取前台窗口的元素树,再按元素查找、等待、点击或 invoke:
|
|
426
|
+
|
|
427
|
+
```bash
|
|
428
|
+
et element tree --output json
|
|
429
|
+
et element find --name "确定" --control-type Button --output json
|
|
430
|
+
et wait element --name "保存" --control-type Button --timeout-ms 5000 --output json
|
|
431
|
+
et element click --element-id root/0/3 --output json
|
|
432
|
+
et element invoke --element-id root/0/3 --output json
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
`element tree` 返回 `element_id`、`control_type`、`automation_id`、`class_name`、`framework_id`、`center`、`bounds`、`children` 等字段,适合让模型先找元素再执行动作。
|
|
436
|
+
|
|
437
|
+
`element find` 支持按 `element_id`、`name`、`automation_id`、`class_name`、`control_type`、`framework_id` 查询元素。`wait element` 会轮询这些条件直到元素出现。`element invoke` 会走平台语义动作或中心点击回退。
|
|
438
|
+
|
|
439
|
+
平台要求:
|
|
440
|
+
|
|
441
|
+
- Windows:UI Automation + PowerShell。
|
|
442
|
+
- Linux:`python3`/`python` + `pyatspi`,点击回退还需要 `xdotool`。
|
|
443
|
+
- macOS:`osascript` + System Events,宿主需要 Accessibility / Automation 权限。
|
|
366
444
|
|
package/bin/arm64/et.exe
CHANGED
|
Binary file
|
package/bin/x64/et.exe
CHANGED
|
Binary file
|
package/init.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require("node:fs");
|
|
4
|
+
const path = require("node:path");
|
|
5
|
+
|
|
6
|
+
const archDirectoryByNodeArch = {
|
|
7
|
+
x64: "x64",
|
|
8
|
+
arm64: "arm64",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
function printUsage() {
|
|
12
|
+
process.stdout.write(
|
|
13
|
+
[
|
|
14
|
+
"Usage:",
|
|
15
|
+
" node init.js [--output <path>] [--force]",
|
|
16
|
+
"",
|
|
17
|
+
"Behavior:",
|
|
18
|
+
" Copies the current Windows binary into the package directory as 'et.exe' by default.",
|
|
19
|
+
" Use --output to write to a different file or directory.",
|
|
20
|
+
].join("\n") + "\n"
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function fail(message) {
|
|
25
|
+
process.stderr.write(`et init: ${message}\n`);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function parseArgs(argv) {
|
|
30
|
+
let output = null;
|
|
31
|
+
let force = false;
|
|
32
|
+
|
|
33
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
34
|
+
const arg = argv[index];
|
|
35
|
+
if (arg === "--help" || arg === "-h") {
|
|
36
|
+
printUsage();
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
if (arg === "--force") {
|
|
40
|
+
force = true;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (arg === "--output") {
|
|
44
|
+
index += 1;
|
|
45
|
+
if (index >= argv.length) {
|
|
46
|
+
fail("Missing value for --output.");
|
|
47
|
+
}
|
|
48
|
+
output = argv[index];
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
fail(`Unknown argument '${arg}'.`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return { output, force };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function getAvailableArchitectures() {
|
|
58
|
+
try {
|
|
59
|
+
return fs
|
|
60
|
+
.readdirSync(path.join(__dirname, "bin"), { withFileTypes: true })
|
|
61
|
+
.filter((entry) => entry.isDirectory())
|
|
62
|
+
.map((entry) => entry.name)
|
|
63
|
+
.sort();
|
|
64
|
+
} catch {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function resolveBinaryPath() {
|
|
70
|
+
const archDirectory = archDirectoryByNodeArch[process.arch];
|
|
71
|
+
if (!archDirectory) {
|
|
72
|
+
fail(`Unsupported architecture '${process.arch}' on platform '${process.platform}'.`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const sourcePath = path.join(__dirname, "bin", archDirectory, "et.exe");
|
|
76
|
+
if (!fs.existsSync(sourcePath)) {
|
|
77
|
+
const availableArchitectures = getAvailableArchitectures();
|
|
78
|
+
const availableMessage = availableArchitectures.length
|
|
79
|
+
? ` Available architectures: ${availableArchitectures.join(", ")}.`
|
|
80
|
+
: "";
|
|
81
|
+
fail(`The package is missing 'et.exe' for architecture '${archDirectory}'.${availableMessage}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return sourcePath;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function resolveOutputPath(requestedOutput) {
|
|
88
|
+
let outputPath = requestedOutput
|
|
89
|
+
? path.resolve(process.cwd(), requestedOutput)
|
|
90
|
+
: path.join(__dirname, "et.exe");
|
|
91
|
+
|
|
92
|
+
if (fs.existsSync(outputPath)) {
|
|
93
|
+
const stat = fs.statSync(outputPath);
|
|
94
|
+
if (stat.isDirectory()) {
|
|
95
|
+
outputPath = path.join(outputPath, "et.exe");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (path.extname(outputPath) === "") {
|
|
100
|
+
outputPath = `${outputPath}.exe`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return outputPath;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function initializeBinary(sourcePath, destinationPath, force) {
|
|
107
|
+
const resolvedSource = path.resolve(sourcePath);
|
|
108
|
+
const resolvedDestination = path.resolve(destinationPath);
|
|
109
|
+
if (resolvedSource === resolvedDestination) {
|
|
110
|
+
process.stdout.write(`et init: binary already available at ${resolvedDestination}\n`);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (fs.existsSync(resolvedDestination) && !force) {
|
|
115
|
+
fail(`Destination '${resolvedDestination}' already exists. Use --force to overwrite it.`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
fs.mkdirSync(path.dirname(resolvedDestination), { recursive: true });
|
|
119
|
+
fs.copyFileSync(resolvedSource, resolvedDestination);
|
|
120
|
+
process.stdout.write(`et init: copied ${resolvedSource} -> ${resolvedDestination}\n`);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const options = parseArgs(process.argv.slice(2));
|
|
124
|
+
initializeBinary(resolveBinaryPath(), resolveOutputPath(options.output), options.force);
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "easytouch-windows",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Windows binary distribution for EasyTouch with x64 and arm64 binaries.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"type": "commonjs",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "https://github.com/whuanle/EasyTouch"
|
|
9
|
+
"url": "git+https://github.com/whuanle/EasyTouch.git"
|
|
10
10
|
},
|
|
11
11
|
"bugs": {
|
|
12
12
|
"url": "https://github.com/whuanle/EasyTouch/issues"
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
],
|
|
21
21
|
"files": [
|
|
22
22
|
"bin/**",
|
|
23
|
+
"init.js",
|
|
23
24
|
"LICENSE.txt",
|
|
24
25
|
"README.md",
|
|
25
26
|
"SKILL.md"
|