cicy-desktop 2.1.291 → 2.1.292

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cicy-desktop",
3
- "version": "2.1.291",
3
+ "version": "2.1.292",
4
4
  "description": "CiCy - AI-powered operating system browser",
5
5
  "main": "src/main.js",
6
6
  "bin": {
@@ -629,20 +629,21 @@ async function wslMissing() {
629
629
  });
630
630
  }
631
631
 
632
- // True iff a Windows optional feature reports State : Enabled. NOTE: dism
633
- // /get-featureinfo prints NOTHING when the caller is not elevated (the desktop
634
- // normally runs at medium integrity even for an admin account), so an empty
635
- // answer must not be read as "disabled" fall back to the functional probe.
632
+ // True iff a Windows optional feature is enabled. Primary source: WMI
633
+ // Win32_OptionalFeature (InstallState 1=Enabled, 2=Disabled) readable WITHOUT
634
+ // elevation, unlike `dism /get-featureinfo`, which prints nothing at medium
635
+ // integrity (the desktop normally runs unelevated even for admin accounts) and
636
+ // was being misread as "disabled". dism stays as the fallback when WMI is unavailable.
636
637
  function featureEnabled(feature) {
637
638
  return new Promise((resolve) => {
638
- execFile("dism", ["/english", "/online", "/get-featureinfo", `/featurename:${feature}`],
639
- { timeout: 30000, windowsHide: true },
640
- async (_e, out) => {
641
- const text = String(out || "");
642
- if (/State\s*:\s*Enabled/i.test(text)) return resolve(true);
643
- if (/State\s*:\s*Disabled/i.test(text)) return resolve(false);
644
- resolve(await wslFunctional()); // no answer (not elevated) → ask WSL itself
645
- });
639
+ const ps = `(Get-CimInstance Win32_OptionalFeature -Filter "Name='${feature}'").InstallState`;
640
+ execFile("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", ps], { timeout: 30000, windowsHide: true }, (err, out) => {
641
+ const v = String(out || "").trim();
642
+ if (!err && /^[0-9]+$/.test(v)) return resolve(v === "1");
643
+ execFile("dism", ["/english", "/online", "/get-featureinfo", `/featurename:${feature}`],
644
+ { timeout: 30000, windowsHide: true },
645
+ (_e, out2) => resolve(/State\s*:\s*Enabled/i.test(String(out2 || ""))));
646
+ });
646
647
  });
647
648
  }
648
649
 
@@ -240,8 +240,20 @@ function importTarball(dest, installDir) {
240
240
  // `wsl` call then blocks and the app goes 未响应). Bound it short so we FAIL FAST
241
241
  // and the caller can `wsl --shutdown` + retry instead of hanging 10 minutes.
242
242
  execFile("wsl", ["--import", DISTRO, installDir, dest, "--version", "2"],
243
- { timeout: 240000, windowsHide: true },
244
- (err, _so, se) => { if (err) { err.stderr = String(se || ""); return reject(err); } resolve(); });
243
+ { timeout: 240000, windowsHide: true, encoding: "buffer" },
244
+ (err, _so, se) => {
245
+ if (err) {
246
+ // wsl.exe 的报错是 UTF-16 输出(常见:「请启用'虚拟机平台'Windows 功能并确保在 BIOS 中
247
+ // 启用虚拟化」);解码后拼进 message,抽屉才能显示真正原因而不是「Command failed」。
248
+ let text = "";
249
+ try { text = Buffer.isBuffer(se) ? se.toString("utf16le") : String(se || ""); } catch {}
250
+ text = text.replace(/\u0000/g, "").replace(/\s+/g, " ").trim();
251
+ if (text) err.message = `${err.message.split("\n")[0]} — ${text.slice(0, 300)}`;
252
+ err.stderr = text;
253
+ return reject(err);
254
+ }
255
+ resolve();
256
+ });
245
257
  });
246
258
  }
247
259
 
@@ -19,10 +19,16 @@ test("bootstrap failures land in lastError and pause the auto-bootstrap loop unt
19
19
  assert.match(src, /logFile: _logFile/);
20
20
  });
21
21
 
22
- test("featureEnabled does not treat dism's empty (unelevated) output as disabled", () => {
22
+ test("featureEnabled reads Win32_OptionalFeature (works unelevated), dism only as fallback", () => {
23
23
  const src = read("src/sidecar/docker.js");
24
- assert.match(src, /if \(\/State\\s\*:\\s\*Disabled\/i\.test\(text\)\) return resolve\(false\);\n\s+resolve\(await wslFunctional\(\)\)/);
25
- assert.match(src, /function wslFunctional\(\)/);
24
+ assert.match(src, /Get-CimInstance Win32_OptionalFeature -Filter "Name='\$\{feature\}'"\)\.InstallState/);
25
+ assert.match(src, /resolve\(v === "1"\)/);
26
+ });
27
+
28
+ test("wsl --import failures carry wsl.exe's decoded message into the drawer", () => {
29
+ const src = read("src/sidecar/wsl-docker.js");
30
+ assert.match(src, /encoding: "buffer"/);
31
+ assert.match(src, /se\.toString\("utf16le"\)/);
26
32
  });
27
33
 
28
34
  test("keepalive logon task degrades to LeastPrivilege / HKCU Run when not elevated", () => {