@aiyiran/myclaw 1.0.163 → 1.0.165
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/index.js +1 -1
- package/package.json +1 -1
- package/restrict.js +68 -49
- package/start.js +19 -0
- package/wsl2.js +15 -5
package/index.js
CHANGED
|
@@ -1131,7 +1131,7 @@ function showHelp() {
|
|
|
1131
1131
|
console.log(' up 升级 + 刷新桌面快捷方式 (= update + bat)');
|
|
1132
1132
|
console.log(' open 打开浏览器控制台(自动带 token)');
|
|
1133
1133
|
console.log(' fix 兜底修复(自动补装 WSL + Chrome,仅限 Windows)');
|
|
1134
|
-
console.log(' wsl2 WSL2 一键安装/修复 (仅限 Windows, 可选: --cli)');
|
|
1134
|
+
console.log(' wsl2 WSL2 一键安装/修复 (仅限 Windows, 可选: --cli, --remote)');
|
|
1135
1135
|
console.log(' safe 开启虚拟机屏蔽 (禁止自动挂载 Windows 盘符)');
|
|
1136
1136
|
console.log(' bat 在桌面生成一键启动脚本 (仅限 Windows)');
|
|
1137
1137
|
console.log(' list 查看注入资源管理列表(智能体/技能/配置)');
|
package/package.json
CHANGED
package/restrict.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* 步骤 3: 在 Windows 桌面创建快捷方式,指向 \\wsl.localhost\OpenClaw\root\.openclaw\workspace
|
|
12
12
|
*
|
|
13
13
|
* 使用方法:
|
|
14
|
-
* myclaw
|
|
14
|
+
* myclaw safe
|
|
15
15
|
*
|
|
16
16
|
* 前提:OpenClaw WSL2 发行版已安装(myclaw wsl2 完成)
|
|
17
17
|
* ============================================================================
|
|
@@ -33,8 +33,8 @@ const C = isWindows
|
|
|
33
33
|
: { r: '\x1b[31m', g: '\x1b[32m', y: '\x1b[33m', b: '\x1b[34m', nc: '\x1b[0m' };
|
|
34
34
|
|
|
35
35
|
const DISTRO_NAME = 'OpenClaw';
|
|
36
|
-
const WORKSPACE_PATH = '/root/.openclaw/workspace/myclaw';
|
|
37
|
-
const SHORTCUT_TARGET = '/root/.openclaw/workspace';
|
|
36
|
+
const WORKSPACE_PATH = '/root/.openclaw/workspace/myclaw';
|
|
37
|
+
const SHORTCUT_TARGET = '/root/.openclaw/workspace';
|
|
38
38
|
|
|
39
39
|
// ============================================================================
|
|
40
40
|
// 工具函数
|
|
@@ -46,10 +46,10 @@ function printSuccess(msg) { console.log(C.g + '[成功]' + C.nc + ' ' + msg); }
|
|
|
46
46
|
function printWarning(msg) { console.log(C.y + '[警告]' + C.nc + ' ' + msg); }
|
|
47
47
|
function printError(msg) { console.error(C.r + '[错误]' + C.nc + ' ' + msg); }
|
|
48
48
|
|
|
49
|
-
// 在 WSL
|
|
49
|
+
// 在 WSL 中执行命令,返回 stdout
|
|
50
50
|
function wslExec(cmd) {
|
|
51
51
|
try {
|
|
52
|
-
return execSync('wsl -d ' + DISTRO_NAME + ' --
|
|
52
|
+
return execSync('wsl -d ' + DISTRO_NAME + ' -- ' + cmd, {
|
|
53
53
|
encoding: 'utf8',
|
|
54
54
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
55
55
|
}).trim();
|
|
@@ -58,10 +58,21 @@ function wslExec(cmd) {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
//
|
|
62
|
-
|
|
61
|
+
// 写临时 shell 脚本到 WSL 内,然后以 root 执行
|
|
62
|
+
// 这样避免 Windows cmd.exe 对管道/重定向的干扰
|
|
63
|
+
function wslRunScriptAsRoot(scriptContent) {
|
|
64
|
+
// 把脚本写到 WSL 的 /tmp 下
|
|
65
|
+
const tmpScript = '/tmp/myclaw_safe_setup.sh';
|
|
66
|
+
const b64 = Buffer.from(scriptContent).toString('base64');
|
|
67
|
+
|
|
63
68
|
try {
|
|
64
|
-
|
|
69
|
+
// 写入脚本
|
|
70
|
+
execSync('wsl -d ' + DISTRO_NAME + ' -u root -- bash -c "echo ' + b64 + ' | base64 -d > ' + tmpScript + '"', {
|
|
71
|
+
encoding: 'utf8',
|
|
72
|
+
stdio: 'pipe',
|
|
73
|
+
});
|
|
74
|
+
// 执行脚本
|
|
75
|
+
execSync('wsl -d ' + DISTRO_NAME + ' -u root -- bash ' + tmpScript, {
|
|
65
76
|
encoding: 'utf8',
|
|
66
77
|
stdio: 'pipe',
|
|
67
78
|
});
|
|
@@ -81,7 +92,6 @@ function checkPrerequisites() {
|
|
|
81
92
|
process.exit(1);
|
|
82
93
|
}
|
|
83
94
|
|
|
84
|
-
// 检查 wsl 命令
|
|
85
95
|
try {
|
|
86
96
|
execSync('wsl --version', { stdio: 'pipe' });
|
|
87
97
|
} catch {
|
|
@@ -89,7 +99,6 @@ function checkPrerequisites() {
|
|
|
89
99
|
process.exit(1);
|
|
90
100
|
}
|
|
91
101
|
|
|
92
|
-
// 检查 OpenClaw 发行版
|
|
93
102
|
try {
|
|
94
103
|
const list = execSync('wsl -l -q', { encoding: 'utf16le' });
|
|
95
104
|
if (!list.includes(DISTRO_NAME)) {
|
|
@@ -129,28 +138,30 @@ function step1_createWorkspace() {
|
|
|
129
138
|
function step2_disableAutomount() {
|
|
130
139
|
printStep('步骤 2/3: 禁用自动挂载 Windows 盘符');
|
|
131
140
|
|
|
132
|
-
// 备份
|
|
133
|
-
wslExecRoot('cp /etc/wsl.conf /etc/wsl.conf.bak 2>/dev/null || true');
|
|
134
|
-
|
|
135
141
|
// 读取现有配置
|
|
136
142
|
const existing = wslExec('cat /etc/wsl.conf 2>/dev/null') || '';
|
|
137
143
|
|
|
138
144
|
let newContent;
|
|
139
145
|
if (existing.includes('[automount]')) {
|
|
140
|
-
// 替换已有 automount 段
|
|
141
146
|
newContent = existing.replace(
|
|
142
147
|
/\[automount\][^\[]*/,
|
|
143
148
|
'[automount]\nenabled = false\n'
|
|
144
149
|
);
|
|
145
150
|
} else {
|
|
146
|
-
// 追加
|
|
147
151
|
newContent = existing + (existing.endsWith('\n') ? '' : '\n') + '[automount]\nenabled = false\n';
|
|
148
152
|
}
|
|
149
153
|
|
|
150
|
-
//
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
+
// 构建一个完整的 shell 脚本,在 WSL 内执行
|
|
155
|
+
const script = [
|
|
156
|
+
'#!/bin/bash',
|
|
157
|
+
'cp /etc/wsl.conf /etc/wsl.conf.bak 2>/dev/null || true',
|
|
158
|
+
'cat > /etc/wsl.conf << \'MYCLAW_EOF\'',
|
|
159
|
+
newContent,
|
|
160
|
+
'MYCLAW_EOF',
|
|
161
|
+
].join('\n');
|
|
162
|
+
|
|
163
|
+
printInfo('正在写入 /etc/wsl.conf ...');
|
|
164
|
+
const ok = wslRunScriptAsRoot(script);
|
|
154
165
|
|
|
155
166
|
if (!ok) {
|
|
156
167
|
printError('写入 wsl.conf 失败');
|
|
@@ -161,10 +172,16 @@ function step2_disableAutomount() {
|
|
|
161
172
|
const verify = wslExec('cat /etc/wsl.conf 2>/dev/null') || '';
|
|
162
173
|
if (verify.includes('enabled = false') || verify.includes('enabled=false')) {
|
|
163
174
|
printSuccess('automount 已禁用');
|
|
175
|
+
printInfo('/etc/wsl.conf 内容:');
|
|
176
|
+
console.log('---');
|
|
177
|
+
console.log(verify);
|
|
178
|
+
console.log('---');
|
|
164
179
|
return true;
|
|
165
180
|
}
|
|
166
181
|
|
|
167
|
-
printError('
|
|
182
|
+
printError('配置验证失败,写入可能不完整');
|
|
183
|
+
printInfo('实际内容:');
|
|
184
|
+
console.log(verify || '(空)');
|
|
168
185
|
return false;
|
|
169
186
|
}
|
|
170
187
|
|
|
@@ -175,10 +192,8 @@ function step2_disableAutomount() {
|
|
|
175
192
|
function step3_createShortcut() {
|
|
176
193
|
printStep('步骤 3/3: 创建桌面快捷方式');
|
|
177
194
|
|
|
178
|
-
// \\wsl.localhost\OpenClaw\root\.openclaw\workspace
|
|
179
195
|
const wslPath = '\\\\wsl.localhost\\' + DISTRO_NAME + '\\' + SHORTCUT_TARGET.replace(/\//g, '\\');
|
|
180
196
|
|
|
181
|
-
// 找桌面路径(兼容中英文)
|
|
182
197
|
const desktopPath = path.join(os.homedir(), 'Desktop');
|
|
183
198
|
const desktopPathCN = path.join(os.homedir(), '桌面');
|
|
184
199
|
const shortcutDir = fs.existsSync(desktopPath) ? desktopPath
|
|
@@ -189,9 +204,8 @@ function step3_createShortcut() {
|
|
|
189
204
|
return false;
|
|
190
205
|
}
|
|
191
206
|
|
|
192
|
-
const shortcutPath = path.join(shortcutDir, '
|
|
207
|
+
const shortcutPath = path.join(shortcutDir, '我的私人龙虾.lnk');
|
|
193
208
|
|
|
194
|
-
// 写临时 .ps1 文件来创建快捷方式(避免复杂的命令行转义)
|
|
195
209
|
const tmpDir = path.join(process.env.LOCALAPPDATA || os.tmpdir(), 'myclaw');
|
|
196
210
|
try { fs.mkdirSync(tmpDir, { recursive: true }); } catch {}
|
|
197
211
|
const psFile = path.join(tmpDir, 'create-shortcut.ps1');
|
|
@@ -203,22 +217,12 @@ function step3_createShortcut() {
|
|
|
203
217
|
'$sc.Arguments = "' + wslPath + '"',
|
|
204
218
|
'$sc.WorkingDirectory = "' + wslPath + '"',
|
|
205
219
|
'$sc.Description = "OpenClaw Workspace"',
|
|
220
|
+
'$sc.IconLocation = "C:\\Windows\\explorer.exe,0"',
|
|
206
221
|
'$sc.Save()',
|
|
207
222
|
'',
|
|
208
|
-
'# 尝试下载图标',
|
|
209
|
-
'$iconDir = "' + tmpDir + '"',
|
|
210
|
-
'$iconPath = "$iconDir\\openclaw.ico"',
|
|
211
|
-
'try {',
|
|
212
|
-
' Invoke-WebRequest -Uri "https://cdn.yiranlaoshi.com/software/myclaw/openclaw.ico" -OutFile $iconPath -UseBasicParsing',
|
|
213
|
-
' $sc2 = $ws.CreateShortcut("' + shortcutPath + '")',
|
|
214
|
-
' $sc2.IconLocation = "$iconPath,0"',
|
|
215
|
-
' $sc2.Save()',
|
|
216
|
-
'} catch {}',
|
|
217
|
-
'',
|
|
218
223
|
'Write-Host "OK"',
|
|
219
224
|
].join('\r\n');
|
|
220
225
|
|
|
221
|
-
// UTF-8 BOM
|
|
222
226
|
fs.writeFileSync(psFile, '\uFEFF' + psContent, 'utf8');
|
|
223
227
|
|
|
224
228
|
try {
|
|
@@ -228,15 +232,14 @@ function step3_createShortcut() {
|
|
|
228
232
|
).trim();
|
|
229
233
|
|
|
230
234
|
if (result.includes('OK')) {
|
|
231
|
-
printSuccess('桌面快捷方式已创建:
|
|
235
|
+
printSuccess('桌面快捷方式已创建: 我的私人龙虾');
|
|
232
236
|
printInfo('双击即可打开工作目录');
|
|
233
237
|
return true;
|
|
234
238
|
}
|
|
235
239
|
} catch {
|
|
236
|
-
// 回退:创建 .url 文件
|
|
237
240
|
try {
|
|
238
241
|
const urlContent = '[InternetShortcut]\r\nURL=file:///' + wslPath.replace(/\\/g, '/') + '\r\n';
|
|
239
|
-
fs.writeFileSync(path.join(shortcutDir, '
|
|
242
|
+
fs.writeFileSync(path.join(shortcutDir, '我的私人龙虾.url'), urlContent, 'utf8');
|
|
240
243
|
printSuccess('桌面快捷方式已创建 (.url)');
|
|
241
244
|
return true;
|
|
242
245
|
} catch (err2) {
|
|
@@ -255,13 +258,13 @@ function step3_createShortcut() {
|
|
|
255
258
|
function run() {
|
|
256
259
|
console.log('');
|
|
257
260
|
console.log('========================================');
|
|
258
|
-
console.log(' MyClaw
|
|
261
|
+
console.log(' MyClaw 虚拟机屏蔽');
|
|
259
262
|
console.log('========================================');
|
|
260
263
|
console.log('');
|
|
261
264
|
console.log('此操作将:');
|
|
262
265
|
console.log(' 1. 在 WSL 内创建工作目录');
|
|
263
266
|
console.log(' 2. 禁用 WSL 自动挂载 Windows 盘符');
|
|
264
|
-
console.log(' 3. 在桌面创建快捷方式
|
|
267
|
+
console.log(' 3. 在桌面创建快捷方式');
|
|
265
268
|
console.log('');
|
|
266
269
|
console.log('效果:Linux 看不到 Windows 文件,但 Windows');
|
|
267
270
|
console.log(' 可以通过桌面快捷方式访问 WSL 工作目录。');
|
|
@@ -277,21 +280,37 @@ function run() {
|
|
|
277
280
|
printWarning('快捷方式创建失败,但不影响权限封锁');
|
|
278
281
|
}
|
|
279
282
|
|
|
280
|
-
// 完成提示
|
|
281
283
|
console.log('');
|
|
282
284
|
console.log('========================================');
|
|
283
|
-
printSuccess('
|
|
285
|
+
printSuccess('虚拟机屏蔽配置完成!');
|
|
284
286
|
console.log('========================================');
|
|
285
287
|
console.log('');
|
|
286
|
-
|
|
288
|
+
printInfo('正在重启 WSL2 使配置生效...');
|
|
287
289
|
console.log('');
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
290
|
+
|
|
291
|
+
try {
|
|
292
|
+
execSync('wsl --shutdown', { stdio: 'pipe', timeout: 15000 });
|
|
293
|
+
printSuccess('WSL2 已重启');
|
|
294
|
+
} catch {
|
|
295
|
+
printWarning('自动重启失败,请手动运行: wsl --shutdown');
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// 验证
|
|
299
|
+
console.log('');
|
|
300
|
+
console.log('验证中...');
|
|
301
|
+
try {
|
|
302
|
+
const check = wslExec('ls /mnt/c 2>&1');
|
|
303
|
+
if (!check || check.includes('cannot access') || check.includes('No such file')) {
|
|
304
|
+
printSuccess('验证通过: /mnt/c 不可访问,屏蔽生效!');
|
|
305
|
+
} else {
|
|
306
|
+
printWarning('/mnt/c 仍然可访问,可能需要再次 wsl --shutdown');
|
|
307
|
+
}
|
|
308
|
+
} catch {
|
|
309
|
+
printSuccess('验证通过: /mnt/c 不可访问');
|
|
310
|
+
}
|
|
311
|
+
|
|
291
312
|
console.log('');
|
|
292
|
-
|
|
293
|
-
console.log(' - WSL 内 ls /mnt/c → 应显示不存在');
|
|
294
|
-
console.log(' - 双击桌面「myclaw」→ 打开工作文件夹');
|
|
313
|
+
printInfo('双击桌面「我的私人龙虾」可打开工作文件夹');
|
|
295
314
|
console.log('');
|
|
296
315
|
}
|
|
297
316
|
|
package/start.js
CHANGED
|
@@ -66,6 +66,25 @@ function startWindows() {
|
|
|
66
66
|
}
|
|
67
67
|
console.log('');
|
|
68
68
|
|
|
69
|
+
// Step 2.5: 自动检测虚拟机屏蔽(safe)
|
|
70
|
+
console.log('[safe] 虚拟机屏蔽...');
|
|
71
|
+
try {
|
|
72
|
+
const conf = execSync('wsl -d OpenClaw -u root -- cat /etc/wsl.conf 2>/dev/null', {
|
|
73
|
+
encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'],
|
|
74
|
+
});
|
|
75
|
+
if (conf.includes('enabled = false') || conf.includes('enabled=false')) {
|
|
76
|
+
console.log(' ' + C.g + '[已开启]' + C.nc);
|
|
77
|
+
} else {
|
|
78
|
+
console.log(' ' + C.y + '[未开启,正在启用...]' + C.nc);
|
|
79
|
+
try { execSync('myclaw safe', { stdio: 'inherit', timeout: 30000 }); } catch {}
|
|
80
|
+
}
|
|
81
|
+
} catch {
|
|
82
|
+
// wsl.conf 不存在,说明还没开启
|
|
83
|
+
console.log(' ' + C.y + '[未开启,正在启用...]' + C.nc);
|
|
84
|
+
try { execSync('myclaw safe', { stdio: 'inherit', timeout: 30000 }); } catch {}
|
|
85
|
+
}
|
|
86
|
+
console.log('');
|
|
87
|
+
|
|
69
88
|
// Step 3: 检查 Gateway
|
|
70
89
|
console.log('[3/4] Gateway...');
|
|
71
90
|
let gatewayRunning = false;
|
package/wsl2.js
CHANGED
|
@@ -506,10 +506,11 @@ function runCliMode() {
|
|
|
506
506
|
console.log(' 1. 重新安装 Phase 1 (启用功能 + 下载)');
|
|
507
507
|
console.log(' 2. 重新安装 Phase 2 (导入 Linux 环境)');
|
|
508
508
|
console.log(' 3. 重新设置安装包路径');
|
|
509
|
+
console.log(' 4. WSL2虚拟机重装 (强制远程 + 阶段1重启)');
|
|
509
510
|
console.log(' 0. 退出');
|
|
510
511
|
console.log('');
|
|
511
512
|
|
|
512
|
-
const choice = await question('请输入选项 (0-
|
|
513
|
+
const choice = await question('请输入选项 (0-4): ');
|
|
513
514
|
|
|
514
515
|
switch (choice.trim()) {
|
|
515
516
|
case '1':
|
|
@@ -517,7 +518,7 @@ function runCliMode() {
|
|
|
517
518
|
console.log('[' + C.y + '执行' + C.nc + '] 开始 Phase 1 安装...');
|
|
518
519
|
setState('needs-features');
|
|
519
520
|
rl.close();
|
|
520
|
-
runPhase1();
|
|
521
|
+
runPhase1(false);
|
|
521
522
|
break;
|
|
522
523
|
|
|
523
524
|
case '2':
|
|
@@ -525,7 +526,7 @@ function runCliMode() {
|
|
|
525
526
|
console.log('[' + C.y + '执行' + C.nc + '] 开始 Phase 2 安装...');
|
|
526
527
|
setState('phase1-done');
|
|
527
528
|
rl.close();
|
|
528
|
-
runPhase2();
|
|
529
|
+
runPhase2(false);
|
|
529
530
|
break;
|
|
530
531
|
|
|
531
532
|
case '3':
|
|
@@ -543,6 +544,15 @@ function runCliMode() {
|
|
|
543
544
|
rl.close();
|
|
544
545
|
break;
|
|
545
546
|
|
|
547
|
+
case '4':
|
|
548
|
+
console.log('');
|
|
549
|
+
console.log('[' + C.y + '执行' + C.nc + '] WSL2虚拟机重装 (强制远程下载)...');
|
|
550
|
+
console.log('');
|
|
551
|
+
setState('needs-features');
|
|
552
|
+
rl.close();
|
|
553
|
+
runPhase1(true);
|
|
554
|
+
break;
|
|
555
|
+
|
|
546
556
|
case '0':
|
|
547
557
|
console.log('');
|
|
548
558
|
console.log('已退出。');
|
|
@@ -626,9 +636,9 @@ function run() {
|
|
|
626
636
|
}
|
|
627
637
|
|
|
628
638
|
if (state === 'phase1-done') {
|
|
629
|
-
runPhase2();
|
|
639
|
+
runPhase2(forceRemote);
|
|
630
640
|
} else {
|
|
631
|
-
runPhase1();
|
|
641
|
+
runPhase1(forceRemote);
|
|
632
642
|
}
|
|
633
643
|
}
|
|
634
644
|
|