@aiyiran/myclaw 1.0.11 → 1.0.13

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/wsl2.js +87 -69
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiyiran/myclaw",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {
package/wsl2.js CHANGED
@@ -7,11 +7,13 @@
7
7
  *
8
8
  * 使用方式: myclaw wsl2
9
9
  *
10
- * 自动检测当前 WSL2 安装状态,分两个阶段完成安装:
11
- * Phase 1: 启用底层 Windows 功能 + 安装 WSL 完整包 → 需要重启
12
- * Phase 2: 导入预制 Linux 环境(tar 包) → 完成
10
+ * 安装过程中会提示:
11
+ * - 有本地文件?拖拽到窗口 + 回车
12
+ * - 没有?直接回车,从 CDN 下载
13
13
  *
14
- * 用户只需反复运行 myclaw wsl2,脚本会自动接续上次的进度。
14
+ * 自动检测安装状态,分两阶段完成:
15
+ * Phase 1: 启用底层 Windows 功能 + 安装 WSL → 需要重启
16
+ * Phase 2: 导入预制 Linux 环境 → 完成
15
17
  * ============================================================================
16
18
  */
17
19
 
@@ -19,20 +21,17 @@ const { execSync } = require('child_process');
19
21
  const os = require('os');
20
22
 
21
23
  // ============================================================================
22
- // 配置 - 所有下载地址集中在这里,方便统一替换
24
+ // 配置
23
25
  // ============================================================================
24
26
 
25
27
  const WSL_CDN = {
26
- // ★ 新版 WSL 完整安装包(243MB,含内核,替代老的 wsl_update_x64.msi 和 wsl --update)
27
28
  wsl: 'https://cdn.yiranlaoshi.com/software/myclaw/wsl.2.7.1.0.x64.msi',
28
- // 预制 rootfs tar 包(内含 Node.js + OpenClaw,用户开箱即用)
29
- // TODO: 替换为你自己的 CDN 地址,制作方法见 README
29
+ // TODO: 替换为你自己的 CDN 地址
30
30
  rootfs: 'https://openclaw.ai/wsl/openclaw-rootfs.tar',
31
31
  };
32
32
 
33
33
  const isWindows = os.platform() === 'win32';
34
34
 
35
- // 颜色(Windows 下禁用避免乱码)
36
35
  const C = isWindows
37
36
  ? { r: '', g: '', y: '', b: '', nc: '' }
38
37
  : { r: '\x1b[31m', g: '\x1b[32m', y: '\x1b[33m', b: '\x1b[34m', nc: '\x1b[0m' };
@@ -41,10 +40,6 @@ const C = isWindows
41
40
  // 工具函数
42
41
  // ============================================================================
43
42
 
44
- /**
45
- * 以管理员权限启动 PowerShell 脚本
46
- * 利用 UTF-16LE Base64 编码避免引号转义地狱
47
- */
48
43
  function launchElevatedPS(script) {
49
44
  const b64 = Buffer.from(script, 'utf16le').toString('base64');
50
45
  try {
@@ -60,33 +55,76 @@ function launchElevatedPS(script) {
60
55
  }
61
56
  }
62
57
 
58
+ /**
59
+ * 生成「拖拽或回车」的 PowerShell 交互代码片段
60
+ * @param {string} prompt 提示文字
61
+ * @param {string} destVar 目标文件变量名(如 $msi, $tarPath)
62
+ * @param {string} cdnUrl CDN 下载地址
63
+ * @param {string} desc 文件描述(如 "WSL 安装包")
64
+ */
65
+ function makeAskLocalOrCDN(prompt, destVar, cdnUrl, desc) {
66
+ return `
67
+ Write-Host ''
68
+ Write-Host ' ┌─────────────────────────────────────────┐'
69
+ Write-Host ' │ 如有 ${desc} 的本地文件: │'
70
+ Write-Host ' │ 请将文件拖拽到此窗口,然后按回车 │'
71
+ Write-Host ' │ │'
72
+ Write-Host ' │ 没有?直接按回车,自动从网络下载 │'
73
+ Write-Host ' └─────────────────────────────────────────┘'
74
+ Write-Host ''
75
+ $userInput = Read-Host ' 拖拽文件或直接回车'
76
+ $userInput = $userInput.Trim().Trim('"')
77
+
78
+ if ($userInput -and (Test-Path $userInput)) {
79
+ Write-Host " 使用本地文件: $userInput"
80
+ Copy-Item $userInput ${destVar} -Force
81
+ Write-Host ' [OK]'
82
+ } elseif ($userInput) {
83
+ Write-Host " [警告] 文件不存在: $userInput"
84
+ Write-Host ' 将改为从网络下载...'
85
+ $userInput = ''
86
+ }
87
+
88
+ if (-Not $userInput) {
89
+ if (-Not (Test-Path ${destVar})) {
90
+ Write-Host ' 正在从网络下载...'
91
+ try {
92
+ [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
93
+ Invoke-WebRequest -Uri '${cdnUrl}' -OutFile ${destVar} -UseBasicParsing
94
+ Write-Host ' 下载完成!'
95
+ } catch {
96
+ Write-Host ' [失败] 下载失败,请检查网络后重试 myclaw wsl2'
97
+ Write-Host ''; Write-Host '按任意键关闭...'
98
+ $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
99
+ exit 1
100
+ }
101
+ } else {
102
+ Write-Host ' 使用上次缓存的文件'
103
+ }
104
+ }
105
+ `;
106
+ }
107
+
63
108
  // ============================================================================
64
109
  // 状态检测
65
110
  // ============================================================================
66
111
 
67
- /**
68
- * 自动检测当前 WSL2 安装状态
69
- * @returns {'ready'|'needs-setup'|'needs-features'}
70
- */
71
112
  function detectState() {
72
- // 1. WSL 已完全可用(有发行版能跑命令)
73
113
  try {
74
114
  execSync('wsl echo ok', { stdio: 'pipe', timeout: 15000 });
75
115
  return 'ready';
76
116
  } catch {}
77
117
 
78
- // 2. WSL 命令可用但没有发行版(功能已启用,重启后的状态)
79
118
  try {
80
119
  execSync('wsl --status', { stdio: 'pipe', timeout: 5000 });
81
120
  return 'needs-setup';
82
121
  } catch {}
83
122
 
84
- // 3. WSL 功能未启用
85
123
  return 'needs-features';
86
124
  }
87
125
 
88
126
  // ============================================================================
89
- // Phase 1: 启用功能 + 安装 WSL 完整包
127
+ // Phase 1: 启用功能 + 安装 WSL
90
128
  // ============================================================================
91
129
 
92
130
  function runPhase1() {
@@ -95,20 +133,25 @@ function runPhase1() {
95
133
  console.log(' WSL 组件 ' + C.r + '[未安装]' + C.nc);
96
134
  console.log(' Linux ' + C.r + '[未安装]' + C.nc);
97
135
  console.log('');
98
- console.log('本次执行 阶段 1/2: 启用底层功能 + 安装 WSL 完整包');
136
+ console.log('阶段 1/2: 启用底层功能 + 安装 WSL');
99
137
  console.log(' 完成后需要 ' + C.y + '重启电脑' + C.nc);
100
- console.log(' 重启后再运行 ' + C.y + 'myclaw wsl2' + C.nc + ' 自动进入阶段 2');
101
138
  console.log('');
102
139
  console.log('[' + C.y + '注意' + C.nc + '] 请在 UAC 弹窗中点击【是】');
103
140
  console.log('');
104
141
 
142
+ const askMsi = makeAskLocalOrCDN(
143
+ '拖拽 WSL 安装包或回车下载',
144
+ '$msi',
145
+ WSL_CDN.wsl,
146
+ 'WSL 安装包 (wsl_full.msi)'
147
+ );
148
+
105
149
  const ps = `
106
150
  $ErrorActionPreference = 'Continue'
107
151
  $Host.UI.RawUI.WindowTitle = 'MyClaw WSL2 Installer - Phase 1'
108
152
  Write-Host ''
109
153
  Write-Host '========================================'
110
154
  Write-Host ' MyClaw WSL2 安装 - 阶段 1/2'
111
- Write-Host ' 启用底层功能 + 安装 WSL 完整包'
112
155
  Write-Host '========================================'
113
156
  Write-Host ''
114
157
 
@@ -124,7 +167,7 @@ try {
124
167
  }
125
168
  Write-Host ''
126
169
 
127
- Write-Host '[2/4] 启用虚拟机平台 (VirtualMachinePlatform)...'
170
+ Write-Host '[2/4] 启用虚拟机平台...'
128
171
  try {
129
172
  dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart | Out-Null
130
173
  Write-Host ' [OK]'
@@ -133,7 +176,8 @@ try {
133
176
  }
134
177
  Write-Host ''
135
178
 
136
- Write-Host '[3/4] 检查并安装 WSL 完整包...'
179
+ Write-Host '[3/4] 获取 WSL 安装包...'
180
+ $msi = "$dir\\wsl_full.msi"
137
181
  $wslInstalled = $false
138
182
  try {
139
183
  $ver = wsl --version 2>&1 | Out-String
@@ -141,33 +185,18 @@ try {
141
185
  } catch {}
142
186
 
143
187
  if ($wslInstalled) {
144
- Write-Host ' WSL 组件已安装,跳过下载 (节省 243MB)'
188
+ Write-Host ' WSL 已安装,跳过'
145
189
  Write-Host ' [OK]'
146
190
  } else {
147
- Write-Host ' WSL 未安装,正在下载完整安装包 (约 243MB)...'
148
- $msi = "$dir\\wsl_full.msi"
149
- if (-Not (Test-Path $msi)) {
150
- try {
151
- [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
152
- Invoke-WebRequest -Uri '${WSL_CDN.wsl}' -OutFile $msi -UseBasicParsing
153
- Write-Host ' 下载完成!'
154
- } catch {
155
- Write-Host ' [失败] 下载失败,请检查网络后重试 myclaw wsl2'
156
- Write-Host ''; Write-Host '按任意键关闭...'
157
- $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
158
- exit 1
159
- }
160
- } else {
161
- Write-Host ' 使用上次缓存的文件'
162
- }
191
+ ${askMsi}
163
192
 
164
193
  Write-Host ''
165
- Write-Host '[4/4] 安装 WSL 完整包...'
194
+ Write-Host '[4/4] 安装 WSL...'
166
195
  try {
167
196
  Start-Process msiexec.exe -ArgumentList "/i \`"$msi\`" /quiet /norestart" -Wait -NoNewWindow
168
- Write-Host ' [OK] 安装成功!'
197
+ Write-Host ' [OK]'
169
198
  } catch {
170
- Write-Host ' [失败] 安装出错'
199
+ Write-Host ' [失败]'
171
200
  Write-Host ''; Write-Host '按任意键关闭...'
172
201
  $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
173
202
  exit 1
@@ -181,7 +210,6 @@ Write-Host ''
181
210
  Write-Host ' >>> 请立即 [重启电脑] <<<'
182
211
  Write-Host ''
183
212
  Write-Host ' 重启后运行: myclaw wsl2'
184
- Write-Host ' 将自动进入阶段 2 完成安装'
185
213
  Write-Host '========================================'
186
214
  Write-Host ''
187
215
  Write-Host '按任意键关闭此窗口...'
@@ -206,10 +234,17 @@ function runPhase2() {
206
234
  console.log(' WSL 组件 ' + C.g + '[OK]' + C.nc);
207
235
  console.log(' Linux ' + C.y + '[待安装]' + C.nc);
208
236
  console.log('');
209
- console.log('即将导入预制 Linux 环境(需要管理员权限)...');
237
+ console.log('即将导入预制 Linux 环境...');
210
238
  console.log('[' + C.y + '注意' + C.nc + '] 请在 UAC 弹窗中点击【是】');
211
239
  console.log('');
212
240
 
241
+ const askTar = makeAskLocalOrCDN(
242
+ '拖拽 tar 包或回车下载',
243
+ '$tarPath',
244
+ WSL_CDN.rootfs,
245
+ 'Linux 环境包 (openclaw-rootfs.tar)'
246
+ );
247
+
213
248
  const ps = `
214
249
  $ErrorActionPreference = 'Continue'
215
250
  $Host.UI.RawUI.WindowTitle = 'MyClaw WSL2 Installer - Phase 2'
@@ -217,7 +252,7 @@ Write-Host ''
217
252
  Write-Host '========================================'
218
253
  Write-Host ' MyClaw WSL2 安装 - 阶段 2/2'
219
254
  Write-Host ' 导入预制 Linux 环境'
220
- Write-Host '========================================'
255
+ Write-Host '========================================'
221
256
  Write-Host ''
222
257
 
223
258
  $dir = "$env:LOCALAPPDATA\\myclaw"
@@ -228,27 +263,13 @@ try { wsl --set-default-version 2 2>$null } catch {}
228
263
  Write-Host ' [OK]'
229
264
  Write-Host ''
230
265
 
231
- Write-Host '[2/3] 下载并导入预制 Linux 环境...'
266
+ Write-Host '[2/3] 获取预制 Linux 环境...'
232
267
  $tarPath = "$dir\\openclaw-rootfs.tar"
233
268
  $distroName = 'OpenClaw'
234
269
  $installDir = "$dir\\OpenClaw"
235
270
  $installed = $false
236
271
 
237
- if (-Not (Test-Path $tarPath)) {
238
- Write-Host ' 正在下载预制环境包...'
239
- try {
240
- [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
241
- Invoke-WebRequest -Uri '${WSL_CDN.rootfs}' -OutFile $tarPath -UseBasicParsing
242
- Write-Host ' 下载完成!'
243
- } catch {
244
- Write-Host ' [失败] 下载失败,请检查网络后重试 myclaw wsl2'
245
- Write-Host ''; Write-Host '按任意键关闭...'
246
- $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
247
- exit 1
248
- }
249
- } else {
250
- Write-Host ' 使用上次缓存的文件'
251
- }
272
+ ${askTar}
252
273
 
253
274
  Write-Host ' 正在导入 (可能需要几分钟)...'
254
275
  try {
@@ -279,10 +300,8 @@ if ($installed) {
279
300
  Write-Host ' [OK] WSL2 + OpenClaw Linux 安装完成!'
280
301
  Write-Host ''
281
302
  Write-Host ' 输入 wsl 即可进入 Linux 环境'
282
- Write-Host ' OpenClaw 已预装就绪'
283
303
  } else {
284
- Write-Host ' [失败] 导入未成功,请检查网络后重试'
285
- Write-Host ' 运行: myclaw wsl2'
304
+ Write-Host ' [失败] 请检查后重试: myclaw wsl2'
286
305
  }
287
306
  Write-Host '========================================'
288
307
  Write-Host ''
@@ -294,7 +313,6 @@ $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
294
313
  console.log('[' + C.g + '已启动' + C.nc + '] 请查看新弹出的蓝色窗口');
295
314
  console.log('');
296
315
  console.log('安装完成后,输入 ' + C.y + 'wsl' + C.nc + ' 即可进入 Linux');
297
- console.log('可随时运行 ' + C.y + 'myclaw wsl2' + C.nc + ' 检查状态');
298
316
  console.log('');
299
317
  }
300
318
  }