@aiyiran/myclaw 1.0.12 → 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 +74 -120
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiyiran/myclaw",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {
package/wsl2.js CHANGED
@@ -5,13 +5,11 @@
5
5
  * MyClaw WSL2 一键安装器
6
6
  * ============================================================================
7
7
  *
8
- * 使用方式:
9
- * myclaw wsl2 # 在线安装(从 CDN 下载)
10
- * myclaw wsl2 --offline D:\myclaw_pkg # 离线安装(从指定目录读取文件)
8
+ * 使用方式: myclaw wsl2
11
9
  *
12
- * 离线模式所需文件(放到同一目录下):
13
- * - wsl_full.msi → Phase 1 用(WSL 完整安装包)
14
- * - openclaw-rootfs.tar → Phase 2 用(预制 Linux 环境)
10
+ * 安装过程中会提示:
11
+ * - 有本地文件?拖拽到窗口 + 回车
12
+ * - 没有?直接回车,从 CDN 下载
15
13
  *
16
14
  * 自动检测安装状态,分两阶段完成:
17
15
  * Phase 1: 启用底层 Windows 功能 + 安装 WSL → 需要重启
@@ -21,16 +19,13 @@
21
19
 
22
20
  const { execSync } = require('child_process');
23
21
  const os = require('os');
24
- const path = require('path');
25
22
 
26
23
  // ============================================================================
27
24
  // 配置
28
25
  // ============================================================================
29
26
 
30
27
  const WSL_CDN = {
31
- // 新版 WSL 完整安装包(243MB)
32
28
  wsl: 'https://cdn.yiranlaoshi.com/software/myclaw/wsl.2.7.1.0.x64.msi',
33
- // 预制 rootfs tar 包(内含 Node.js + OpenClaw)
34
29
  // TODO: 替换为你自己的 CDN 地址
35
30
  rootfs: 'https://openclaw.ai/wsl/openclaw-rootfs.tar',
36
31
  };
@@ -41,32 +36,6 @@ const C = isWindows
41
36
  ? { r: '', g: '', y: '', b: '', nc: '' }
42
37
  : { r: '\x1b[31m', g: '\x1b[32m', y: '\x1b[33m', b: '\x1b[34m', nc: '\x1b[0m' };
43
38
 
44
- // ============================================================================
45
- // 解析 --offline 参数
46
- // ============================================================================
47
-
48
- function parseOfflineDir() {
49
- const args = process.argv.slice(2);
50
- const idx = args.indexOf('--offline');
51
- if (idx === -1) return null;
52
- const dir = args[idx + 1];
53
- if (!dir) {
54
- console.error('[' + C.r + '错误' + C.nc + '] --offline 后面需要指定目录路径');
55
- console.log('');
56
- console.log('用法: myclaw wsl2 --offline <目录路径>');
57
- console.log('');
58
- console.log('示例:');
59
- console.log(' myclaw wsl2 --offline D:\\');
60
- console.log(' myclaw wsl2 --offline E:\\myclaw_pkg');
61
- console.log('');
62
- console.log('目录下应包含:');
63
- console.log(' wsl_full.msi (Phase 1: WSL 安装包)');
64
- console.log(' openclaw-rootfs.tar (Phase 2: Linux 环境)');
65
- process.exit(1);
66
- }
67
- return dir;
68
- }
69
-
70
39
  // ============================================================================
71
40
  // 工具函数
72
41
  // ============================================================================
@@ -86,6 +55,56 @@ function launchElevatedPS(script) {
86
55
  }
87
56
  }
88
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
+
89
108
  // ============================================================================
90
109
  // 状态检测
91
110
  // ============================================================================
@@ -108,56 +127,24 @@ function detectState() {
108
127
  // Phase 1: 启用功能 + 安装 WSL
109
128
  // ============================================================================
110
129
 
111
- function runPhase1(offlineDir) {
130
+ function runPhase1() {
112
131
  console.log('');
113
132
  console.log('[当前进度] WSL 功能 ' + C.r + '[未启用]' + C.nc);
114
133
  console.log(' WSL 组件 ' + C.r + '[未安装]' + C.nc);
115
134
  console.log(' Linux ' + C.r + '[未安装]' + C.nc);
116
135
  console.log('');
117
- if (offlineDir) {
118
- console.log('[离线模式] 从 ' + C.y + offlineDir + C.nc + ' 读取安装包');
119
- }
120
136
  console.log('阶段 1/2: 启用底层功能 + 安装 WSL');
121
137
  console.log(' 完成后需要 ' + C.y + '重启电脑' + C.nc);
122
138
  console.log('');
123
139
  console.log('[' + C.y + '注意' + C.nc + '] 请在 UAC 弹窗中点击【是】');
124
140
  console.log('');
125
141
 
126
- // 构造文件获取逻辑
127
- let msiSource;
128
- if (offlineDir) {
129
- const localPath = path.join(offlineDir, 'wsl_full.msi').replace(/\\/g, '\\\\');
130
- msiSource = `
131
- $localMsi = '${localPath}'
132
- if (Test-Path $localMsi) {
133
- Write-Host " 从离线目录复制: $localMsi"
134
- Copy-Item $localMsi $msi -Force
135
- Write-Host ' [OK]'
136
- } else {
137
- Write-Host " [失败] 文件不存在: $localMsi"
138
- Write-Host ''; Write-Host '按任意键关闭...'
139
- $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
140
- exit 1
141
- }`;
142
- } else {
143
- msiSource = `
144
- if (-Not (Test-Path $msi)) {
145
- Write-Host ' 正在从 CDN 下载 (约 243MB)...'
146
- try {
147
- [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
148
- Invoke-WebRequest -Uri '${WSL_CDN.wsl}' -OutFile $msi -UseBasicParsing
149
- Write-Host ' 下载完成!'
150
- } catch {
151
- Write-Host ' [失败] 下载失败'
152
- Write-Host ' 提示: 可用 myclaw wsl2 --offline <目录> 指定本地文件'
153
- Write-Host ''; Write-Host '按任意键关闭...'
154
- $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
155
- exit 1
156
- }
157
- } else {
158
- Write-Host ' 使用上次缓存的文件'
159
- }`;
160
- }
142
+ const askMsi = makeAskLocalOrCDN(
143
+ '拖拽 WSL 安装包或回车下载',
144
+ '$msi',
145
+ WSL_CDN.wsl,
146
+ 'WSL 安装包 (wsl_full.msi)'
147
+ );
161
148
 
162
149
  const ps = `
163
150
  $ErrorActionPreference = 'Continue'
@@ -201,7 +188,7 @@ if ($wslInstalled) {
201
188
  Write-Host ' WSL 已安装,跳过'
202
189
  Write-Host ' [OK]'
203
190
  } else {
204
- ${msiSource}
191
+ ${askMsi}
205
192
 
206
193
  Write-Host ''
207
194
  Write-Host '[4/4] 安装 WSL...'
@@ -241,54 +228,22 @@ $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
241
228
  // Phase 2: 导入预制 Linux 环境
242
229
  // ============================================================================
243
230
 
244
- function runPhase2(offlineDir) {
231
+ function runPhase2() {
245
232
  console.log('');
246
233
  console.log('[当前进度] WSL 功能 ' + C.g + '[OK]' + C.nc);
247
234
  console.log(' WSL 组件 ' + C.g + '[OK]' + C.nc);
248
235
  console.log(' Linux ' + C.y + '[待安装]' + C.nc);
249
236
  console.log('');
250
- if (offlineDir) {
251
- console.log('[离线模式] 从 ' + C.y + offlineDir + C.nc + ' 读取安装包');
252
- }
253
237
  console.log('即将导入预制 Linux 环境...');
254
238
  console.log('[' + C.y + '注意' + C.nc + '] 请在 UAC 弹窗中点击【是】');
255
239
  console.log('');
256
240
 
257
- // 构造 tar 获取逻辑
258
- let tarSource;
259
- if (offlineDir) {
260
- const localPath = path.join(offlineDir, 'openclaw-rootfs.tar').replace(/\\/g, '\\\\');
261
- tarSource = `
262
- $localTar = '${localPath}'
263
- if (Test-Path $localTar) {
264
- Write-Host " 从离线目录复制: $localTar"
265
- Copy-Item $localTar $tarPath -Force
266
- Write-Host ' [OK]'
267
- } else {
268
- Write-Host " [失败] 文件不存在: $localTar"
269
- Write-Host ''; Write-Host '按任意键关闭...'
270
- $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
271
- exit 1
272
- }`;
273
- } else {
274
- tarSource = `
275
- if (-Not (Test-Path $tarPath)) {
276
- Write-Host ' 正在从 CDN 下载...'
277
- try {
278
- [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
279
- Invoke-WebRequest -Uri '${WSL_CDN.rootfs}' -OutFile $tarPath -UseBasicParsing
280
- Write-Host ' 下载完成!'
281
- } catch {
282
- Write-Host ' [失败] 下载失败'
283
- Write-Host ' 提示: 可用 myclaw wsl2 --offline <目录> 指定本地文件'
284
- Write-Host ''; Write-Host '按任意键关闭...'
285
- $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
286
- exit 1
287
- }
288
- } else {
289
- Write-Host ' 使用上次缓存的文件'
290
- }`;
291
- }
241
+ const askTar = makeAskLocalOrCDN(
242
+ '拖拽 tar 包或回车下载',
243
+ '$tarPath',
244
+ WSL_CDN.rootfs,
245
+ 'Linux 环境包 (openclaw-rootfs.tar)'
246
+ );
292
247
 
293
248
  const ps = `
294
249
  $ErrorActionPreference = 'Continue'
@@ -297,7 +252,7 @@ Write-Host ''
297
252
  Write-Host '========================================'
298
253
  Write-Host ' MyClaw WSL2 安装 - 阶段 2/2'
299
254
  Write-Host ' 导入预制 Linux 环境'
300
- Write-Host '========================================'
255
+ Write-Host '========================================'
301
256
  Write-Host ''
302
257
 
303
258
  $dir = "$env:LOCALAPPDATA\\myclaw"
@@ -308,13 +263,13 @@ try { wsl --set-default-version 2 2>$null } catch {}
308
263
  Write-Host ' [OK]'
309
264
  Write-Host ''
310
265
 
311
- Write-Host '[2/3] 获取并导入预制 Linux 环境...'
266
+ Write-Host '[2/3] 获取预制 Linux 环境...'
312
267
  $tarPath = "$dir\\openclaw-rootfs.tar"
313
268
  $distroName = 'OpenClaw'
314
269
  $installDir = "$dir\\OpenClaw"
315
270
  $installed = $false
316
271
 
317
- ${tarSource}
272
+ ${askTar}
318
273
 
319
274
  Write-Host ' 正在导入 (可能需要几分钟)...'
320
275
  try {
@@ -372,7 +327,6 @@ function run() {
372
327
  process.exit(0);
373
328
  }
374
329
 
375
- const offlineDir = parseOfflineDir();
376
330
  const bar = '========================================';
377
331
  const state = detectState();
378
332
 
@@ -397,9 +351,9 @@ function run() {
397
351
  }
398
352
 
399
353
  if (state === 'needs-setup') {
400
- runPhase2(offlineDir);
354
+ runPhase2();
401
355
  } else {
402
- runPhase1(offlineDir);
356
+ runPhase1();
403
357
  }
404
358
  }
405
359