@aiyiran/myclaw 1.0.170 → 1.0.171

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 (3) hide show
  1. package/index.js +14 -1
  2. package/package.json +1 -1
  3. package/restrict.js +38 -200
package/index.js CHANGED
@@ -461,12 +461,25 @@ if (-not (Test-Path '${iconPath.replace(/\\/g, '\\\\')}')) {
461
461
  }
462
462
  $ws = New-Object -ComObject WScript.Shell
463
463
  $sc = $ws.CreateShortcut('${lnkPath.replace(/\\/g, '\\\\')}')
464
- $sc.TargetPath = '${batPath.replace(/\\/g, '\\\\')}'
464
+ $sc.TargetPath = '${batPath.replace(/\\/g, '\\\\')}'
465
465
  $sc.WorkingDirectory = '${myClawDir.replace(/\\/g, '\\\\')}'
466
466
  $sc.WindowStyle = 1
467
467
  $sc.IconLocation = '${iconPath.replace(/\\/g, '\\\\')}'
468
468
  $sc.Description = 'OpenClaw'
469
469
  $sc.Save()
470
+
471
+ # 创建「我的私人龙虾」工作目录快捷方式(如不存在)
472
+ $workspaceLnk = '${desktopPath}\\我的私人龙虾.lnk'
473
+ if (-not (Test-Path $workspaceLnk)) {
474
+ $ws2 = New-Object -ComObject WScript.Shell
475
+ $sc2 = $ws2.CreateShortcut($workspaceLnk)
476
+ $sc2.TargetPath = '\\\\wsl.localhost\\OpenClaw\\root\\.openclaw\\workspace'
477
+ $sc2.WorkingDirectory = '\\\\wsl.localhost\\OpenClaw\\root\\.openclaw\\workspace'
478
+ $sc2.Description = 'OpenClaw Workspace'
479
+ $sc2.IconLocation = 'C:\\Windows\\System32\\SHELL32.dll,4'
480
+ $sc2.Save()
481
+ }
482
+
470
483
  Add-Type -TypeDefinition 'using System; using System.Runtime.InteropServices; public class Shell { [DllImport("shell32.dll")] public static extern void SHChangeNotify(int e, int f, IntPtr i1, IntPtr i2); }' -ErrorAction SilentlyContinue
471
484
  [Shell]::SHChangeNotify(0x08000000, 0, [IntPtr]::Zero, [IntPtr]::Zero)
472
485
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiyiran/myclaw",
3
- "version": "1.0.170",
3
+ "version": "1.0.171",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {
package/restrict.js CHANGED
@@ -2,13 +2,11 @@
2
2
 
3
3
  /**
4
4
  * ============================================================================
5
- * MyClaw WSL2 权限封锁(Windows 侧)
5
+ * MyClaw 虚拟机屏蔽(Windows 侧)
6
6
  * ============================================================================
7
7
  *
8
- * Windows 一次性完成:
9
- * 步骤 1: 在 WSL 内创建工作目录 /root/.openclaw/workspace/myclaw
10
- * 步骤 2: 编辑 /etc/wsl.conf 禁用 automount(Linux 看不到 Windows 盘符)
11
- * 步骤 3: 在 Windows 桌面创建快捷方式,指向 \\wsl.localhost\OpenClaw\root\.openclaw\workspace
8
+ * 只做一件事:禁用 WSL2 自动挂载 Windows 盘符
9
+ * 如果已经开启,直接跳过。
12
10
  *
13
11
  * 使用方法:
14
12
  * myclaw safe
@@ -22,10 +20,6 @@ const os = require('os');
22
20
  const fs = require('fs');
23
21
  const path = require('path');
24
22
 
25
- // ============================================================================
26
- // 配置
27
- // ============================================================================
28
-
29
23
  const isWindows = os.platform() === 'win32';
30
24
 
31
25
  const C = isWindows
@@ -33,46 +27,33 @@ const C = isWindows
33
27
  : { r: '\x1b[31m', g: '\x1b[32m', y: '\x1b[33m', b: '\x1b[34m', nc: '\x1b[0m' };
34
28
 
35
29
  const DISTRO_NAME = 'OpenClaw';
36
- const WORKSPACE_PATH = '/root/.openclaw/workspace/myclaw';
37
- const SHORTCUT_TARGET = '/root/.openclaw/workspace';
38
-
39
- // ============================================================================
40
- // 工具函数
41
- // ============================================================================
42
30
 
43
- function printStep(msg) { console.log(C.g + '==>' + C.nc + ' ' + msg); }
44
31
  function printInfo(msg) { console.log(C.b + '[信息]' + C.nc + ' ' + msg); }
45
32
  function printSuccess(msg) { console.log(C.g + '[成功]' + C.nc + ' ' + msg); }
46
33
  function printWarning(msg) { console.log(C.y + '[警告]' + C.nc + ' ' + msg); }
47
34
  function printError(msg) { console.error(C.r + '[错误]' + C.nc + ' ' + msg); }
48
35
 
49
- // 在 WSL 中执行命令,返回 stdout
36
+ // 在 WSL 中执行命令
50
37
  function wslExec(cmd) {
51
38
  try {
52
39
  return execSync('wsl -d ' + DISTRO_NAME + ' -- bash -c "' + cmd + '"', {
53
- encoding: 'utf8',
54
- stdio: ['pipe', 'pipe', 'pipe'],
40
+ encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'],
55
41
  }).trim();
56
42
  } catch {
57
43
  return null;
58
44
  }
59
45
  }
60
46
 
61
- // 写临时 shell 脚本到 Windows,然后让 WSL 执行
62
- // 避免 cmd.exe 转义问题:脚本内容通过文件传递,不走命令行
47
+ // 通过临时脚本文件以 root 执行(只在 automount 未禁用时可用)
63
48
  function wslRunScriptAsRoot(scriptContent) {
64
49
  const tmpDir = path.join(process.env.LOCALAPPDATA || os.tmpdir(), 'myclaw');
65
50
  try { fs.mkdirSync(tmpDir, { recursive: true }); } catch {}
66
51
  const scriptFile = path.join(tmpDir, 'safe-setup.sh');
67
52
  fs.writeFileSync(scriptFile, scriptContent, 'utf8');
68
-
69
- // Windows 路径转 WSL 路径: C:\Users\... → /mnt/c/Users/...
70
53
  const wslPath = '/mnt/' + scriptFile.charAt(0).toLowerCase() + scriptFile.slice(2).replace(/\\/g, '/');
71
-
72
54
  try {
73
55
  execSync('wsl -d ' + DISTRO_NAME + ' -u root -- bash ' + wslPath, {
74
- encoding: 'utf8',
75
- stdio: 'pipe',
56
+ encoding: 'utf8', stdio: 'pipe',
76
57
  });
77
58
  return true;
78
59
  } catch {
@@ -80,76 +61,59 @@ function wslRunScriptAsRoot(scriptContent) {
80
61
  }
81
62
  }
82
63
 
64
+ // 检测是否已开启
65
+ function isAlreadySafe() {
66
+ const conf = wslExec('cat /etc/wsl.conf 2>/dev/null') || '';
67
+ return conf.includes('enabled = false') || conf.includes('enabled=false');
68
+ }
69
+
83
70
  // ============================================================================
84
- // 前置检查
71
+ // 主函数
85
72
  // ============================================================================
86
73
 
87
- function checkPrerequisites() {
74
+ function run() {
88
75
  if (!isWindows) {
89
76
  printError('此命令只能在 Windows 上运行');
90
77
  process.exit(1);
91
78
  }
92
79
 
93
- try {
94
- execSync('wsl --version', { stdio: 'pipe' });
95
- } catch {
80
+ // 检查 WSL + OpenClaw
81
+ try { execSync('wsl --version', { stdio: 'pipe' }); } catch {
96
82
  printError('未检测到 WSL。请先运行: myclaw wsl2');
97
83
  process.exit(1);
98
84
  }
99
-
100
85
  try {
101
86
  const list = execSync('wsl -l -q', { encoding: 'utf16le' });
102
87
  if (!list.includes(DISTRO_NAME)) {
103
- printError('未找到 ' + DISTRO_NAME + ' 发行版。请先运行: myclaw wsl2');
88
+ printError('未找到 ' + DISTRO_NAME + ' 发行版');
104
89
  process.exit(1);
105
90
  }
106
91
  } catch {
107
- printError('无法读取 WSL 发行版列表。请先运行: myclaw wsl2');
92
+ printError('无法读取 WSL 发行版列表');
108
93
  process.exit(1);
109
94
  }
110
95
 
111
- printSuccess('前置检查通过');
112
- }
113
-
114
- // ============================================================================
115
- // 步骤 1: 在 WSL 内创建工作目录
116
- // ============================================================================
117
-
118
- function step1_createWorkspace() {
119
- printStep('步骤 1/3: 在 WSL 内创建工作目录');
120
-
121
- const ok = wslExec('mkdir -p ' + WORKSPACE_PATH + ' && echo ok');
122
-
123
- if (!ok || !ok.includes('ok')) {
124
- printError('创建工作目录失败');
125
- return false;
96
+ // 已开启则跳过
97
+ if (isAlreadySafe()) {
98
+ printSuccess('虚拟机屏蔽已开启,无需重复执行');
99
+ return true;
126
100
  }
127
101
 
128
- printSuccess('工作目录已创建: ' + WORKSPACE_PATH);
129
- return true;
130
- }
131
-
132
- // ============================================================================
133
- // 步骤 2: 禁用 automount — 写 /etc/wsl.conf
134
- // ============================================================================
102
+ // 创建工作目录
103
+ printInfo('创建工作目录...');
104
+ wslExec('mkdir -p /root/.openclaw/workspace/myclaw');
135
105
 
136
- function step2_disableAutomount() {
137
- printStep('步骤 2/3: 禁用自动挂载 Windows 盘符');
106
+ // 写入 /etc/wsl.conf
107
+ printInfo('正在禁用自动挂载...');
138
108
 
139
- // 读取现有配置
140
109
  const existing = wslExec('cat /etc/wsl.conf 2>/dev/null') || '';
141
-
142
110
  let newContent;
143
111
  if (existing.includes('[automount]')) {
144
- newContent = existing.replace(
145
- /\[automount\][^\[]*/,
146
- '[automount]\nenabled = false\n'
147
- );
112
+ newContent = existing.replace(/\[automount\][^\[]*/, '[automount]\nenabled = false\n');
148
113
  } else {
149
114
  newContent = existing + (existing.endsWith('\n') ? '' : '\n') + '[automount]\nenabled = false\n';
150
115
  }
151
116
 
152
- // 构建一个完整的 shell 脚本,在 WSL 内执行
153
117
  const script = [
154
118
  '#!/bin/bash',
155
119
  'cp /etc/wsl.conf /etc/wsl.conf.bak 2>/dev/null || true',
@@ -158,157 +122,31 @@ function step2_disableAutomount() {
158
122
  'MYCLAW_EOF',
159
123
  ].join('\n');
160
124
 
161
- printInfo('正在写入 /etc/wsl.conf ...');
162
125
  const ok = wslRunScriptAsRoot(script);
163
-
164
126
  if (!ok) {
165
127
  printError('写入 wsl.conf 失败');
166
128
  return false;
167
129
  }
168
130
 
169
131
  // 验证
170
- const verify = wslExec('cat /etc/wsl.conf 2>/dev/null') || '';
171
- if (verify.includes('enabled = false') || verify.includes('enabled=false')) {
172
- printSuccess('automount 已禁用');
173
- printInfo('/etc/wsl.conf 内容:');
174
- console.log('---');
175
- console.log(verify);
176
- console.log('---');
177
- return true;
178
- }
179
-
180
- printError('配置验证失败,写入可能不完整');
181
- printInfo('实际内容:');
182
- console.log(verify || '(空)');
183
- return false;
184
- }
185
-
186
- // ============================================================================
187
- // 步骤 3: 在桌面创建快捷方式
188
- // ============================================================================
189
-
190
- function step3_createShortcut() {
191
- printStep('步骤 3/3: 创建桌面快捷方式');
192
-
193
- const wslPath = '\\\\wsl.localhost\\' + DISTRO_NAME + '\\' + SHORTCUT_TARGET.replace(/\//g, '\\');
194
-
195
- const desktopPath = path.join(os.homedir(), 'Desktop');
196
- const desktopPathCN = path.join(os.homedir(), '桌面');
197
- const shortcutDir = fs.existsSync(desktopPath) ? desktopPath
198
- : fs.existsSync(desktopPathCN) ? desktopPathCN : null;
199
-
200
- if (!shortcutDir) {
201
- printError('找不到桌面目录');
132
+ if (!isAlreadySafe()) {
133
+ printError('配置验证失败');
202
134
  return false;
203
135
  }
204
136
 
205
- const shortcutPath = path.join(shortcutDir, '我的私人龙虾.lnk');
206
-
207
- const tmpDir = path.join(process.env.LOCALAPPDATA || os.tmpdir(), 'myclaw');
208
- try { fs.mkdirSync(tmpDir, { recursive: true }); } catch {}
209
- const psFile = path.join(tmpDir, 'create-shortcut.ps1');
210
-
211
- const psContent = [
212
- '$ws = New-Object -ComObject WScript.Shell',
213
- '$sc = $ws.CreateShortcut("' + shortcutPath + '")',
214
- '$sc.TargetPath = "' + wslPath + '"',
215
- '$sc.WorkingDirectory = "' + wslPath + '"',
216
- '$sc.Description = "OpenClaw Workspace"',
217
- '$sc.IconLocation = "C:\\Windows\\System32\\SHELL32.dll,4"',
218
- '$sc.Save()',
219
- '',
220
- 'Write-Host "OK"',
221
- ].join('\r\n');
222
-
223
- fs.writeFileSync(psFile, '\uFEFF' + psContent, 'utf8');
224
-
225
- try {
226
- const result = execSync(
227
- 'powershell -NoProfile -ExecutionPolicy Bypass -File "' + psFile + '"',
228
- { encoding: 'utf8', stdio: 'pipe' }
229
- ).trim();
230
-
231
- if (result.includes('OK')) {
232
- printSuccess('桌面快捷方式已创建: 我的私人龙虾');
233
- printInfo('双击即可打开工作目录');
234
- return true;
235
- }
236
- } catch {
237
- try {
238
- const urlContent = '[InternetShortcut]\r\nURL=file:///' + wslPath.replace(/\\/g, '/') + '\r\n';
239
- fs.writeFileSync(path.join(shortcutDir, '我的私人龙虾.url'), urlContent, 'utf8');
240
- printSuccess('桌面快捷方式已创建 (.url)');
241
- return true;
242
- } catch (err2) {
243
- printError('创建快捷方式失败: ' + err2.message);
244
- return false;
245
- }
246
- }
247
-
248
- return false;
249
- }
250
-
251
- // ============================================================================
252
- // 主函数
253
- // ============================================================================
254
-
255
- function run() {
256
- console.log('');
257
- console.log('========================================');
258
- console.log(' MyClaw 虚拟机屏蔽');
259
- console.log('========================================');
260
- console.log('');
261
- console.log('此操作将:');
262
- console.log(' 1. 在 WSL 内创建工作目录');
263
- console.log(' 2. 禁用 WSL 自动挂载 Windows 盘符');
264
- console.log(' 3. 在桌面创建快捷方式');
265
- console.log('');
266
- console.log('效果:Linux 看不到 Windows 文件,但 Windows');
267
- console.log(' 可以通过桌面快捷方式访问 WSL 工作目录。');
268
- console.log('');
269
-
270
- checkPrerequisites();
271
-
272
- if (!step1_createWorkspace()) { printError('步骤 1 失败'); process.exit(1); }
273
-
274
- if (!step2_disableAutomount()) { printError('步骤 2 失败'); process.exit(1); }
275
-
276
- if (!step3_createShortcut()) {
277
- printWarning('快捷方式创建失败,但不影响权限封锁');
278
- }
279
-
280
- console.log('');
281
- console.log('========================================');
282
- printSuccess('虚拟机屏蔽配置完成!');
283
- console.log('========================================');
284
- console.log('');
285
- printInfo('正在重启 WSL2 使配置生效...');
286
- console.log('');
137
+ printSuccess('automount 已禁用');
287
138
 
139
+ // 重启 WSL 使配置生效
140
+ printInfo('正在重启 WSL2...');
288
141
  try {
289
142
  execSync('wsl --shutdown', { stdio: 'pipe', timeout: 15000 });
290
143
  printSuccess('WSL2 已重启');
291
144
  } catch {
292
- printWarning('自动重启失败,请手动运行: wsl --shutdown');
145
+ printWarning('请手动运行: wsl --shutdown');
293
146
  }
294
147
 
295
- // 验证
296
- console.log('');
297
- console.log('验证中...');
298
- try {
299
- const check = wslExec('ls /mnt/c 2>&1');
300
- if (!check || check.includes('cannot access') || check.includes('No such file')) {
301
- printSuccess('验证通过: /mnt/c 不可访问,屏蔽生效!');
302
- } else {
303
- printWarning('/mnt/c 仍然可访问,可能需要再次 wsl --shutdown');
304
- }
305
- } catch {
306
- printSuccess('验证通过: /mnt/c 不可访问');
307
- }
308
-
309
- console.log('');
310
- printInfo('双击桌面「我的私人龙虾」可打开工作文件夹');
311
- console.log('');
148
+ return true;
312
149
  }
313
150
 
314
- module.exports = { run };
151
+ // 导出检测函数供 start.js 使用
152
+ module.exports = { run, isAlreadySafe };