@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.
- package/package.json +1 -1
- package/wsl2.js +74 -120
package/package.json
CHANGED
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
|
-
* -
|
|
14
|
-
* -
|
|
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(
|
|
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
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
-
${
|
|
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(
|
|
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
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
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]
|
|
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
|
-
${
|
|
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(
|
|
354
|
+
runPhase2();
|
|
401
355
|
} else {
|
|
402
|
-
runPhase1(
|
|
356
|
+
runPhase1();
|
|
403
357
|
}
|
|
404
358
|
}
|
|
405
359
|
|