cicy-desktop 2.1.31 → 2.1.33

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/bin/cicy-desktop CHANGED
@@ -13,6 +13,11 @@ const GLOBAL_CONFIG_FILE = path.join(HOME, "global.json");
13
13
  const STATE_FILE = path.join(HOME, ".cicy-cluster.json");
14
14
  const LOGS_DIR = path.join(HOME, "logs");
15
15
  const PACKAGE_ROOT = path.join(__dirname, "..");
16
+ // CN defaults: a fresh machine has no cached electron binary, so npx's electron
17
+ // postinstall would hit GitHub releases and fail (ECOMPROMISED). Mirror it +
18
+ // the npm registry to npmmirror (overridable via the same-named env vars).
19
+ const ELECTRON_MIRROR = process.env.ELECTRON_MIRROR || "https://npmmirror.com/mirrors/electron/";
20
+ const NPM_REGISTRY = process.env.CICY_NPM_REGISTRY || process.env.npm_config_registry || "https://registry.npmmirror.com";
16
21
  const MASTER_ENTRY = path.join(PACKAGE_ROOT, "src", "master", "master-main.js");
17
22
 
18
23
  // Resolve the electron binary to spawn. Prefers the project-local copy
@@ -346,14 +351,97 @@ function executeCommand(cmd) {
346
351
  }
347
352
  }
348
353
 
354
+ // Drop a double-clickable, CiCy-icon desktop shortcut that relaunches via
355
+ // `npx cicy-desktop`. GUI-launched shortcuts get a minimal PATH (no node), so
356
+ // we bake the dir of the node running this launcher (process.execPath) in.
357
+ function nodeBinDir() {
358
+ try { return path.dirname(process.execPath); } catch { return ""; }
359
+ }
360
+
349
361
  function ensureDesktopCommandFile() {
350
- if (!fs.existsSync(PROJECT_COMMAND_FILE)) {
351
- return;
362
+ try {
363
+ if (process.platform === "darwin") return ensureMacDesktopApp();
364
+ if (process.platform === "linux") return ensureLinuxDesktopEntry();
365
+ if (process.platform === "win32") return ensureWindowsShortcut();
366
+ } catch (e) {
367
+ console.warn(`[shortcut] failed: ${e.message}`);
368
+ }
369
+ }
370
+
371
+ function ensureMacDesktopApp() {
372
+ // Build a REAL AppleScript .app via osacompile. A hand-crafted .app whose
373
+ // executable is a shell script triggers "CiCy Desktop is not responding"
374
+ // (LaunchServices waits for the script to register as a Cocoa app and times
375
+ // out). An osacompile applet's executable IS the AppleScript runtime — a
376
+ // proper Cocoa app — so it launches cleanly, backgrounds `npx cicy-desktop`
377
+ // via `do shell script`, then quits. Icon = the applet's applet.icns.
378
+ const { execFileSync } = require("child_process");
379
+ const appDir = path.join(DESKTOP_DIR, "CiCy Desktop.app");
380
+ const nodeDir = nodeBinDir();
381
+ // do shell script needs node on PATH (GUI launch has a minimal PATH); the
382
+ // trailing & + nohup + </dev/null lets the shell return so the applet quits.
383
+ // ELECTRON_MIRROR + npmmirror: a fresh CN machine has no cached electron
384
+ // binary, so npx's electron postinstall would try GitHub releases and fail
385
+ // (ECOMPROMISED / lock-compromised). Point it at npmmirror's electron mirror.
386
+ // Harmless elsewhere — only consulted when electron actually (re)downloads.
387
+ const ascript =
388
+ `do shell script "export PATH=\\"${nodeDir}:/usr/local/bin:/opt/homebrew/bin:$PATH\\" ; ` +
389
+ `export ELECTRON_MIRROR=\\"${ELECTRON_MIRROR}\\" ; export npm_config_registry=\\"${NPM_REGISTRY}\\" ; ` +
390
+ `nohup npx -y cicy-desktop > /tmp/cicy-desktop.log 2>&1 < /dev/null &"`;
391
+ const tmp = path.join(os.tmpdir(), `cicy-launch-${process.pid}.applescript`);
392
+ fs.writeFileSync(tmp, ascript);
393
+ try {
394
+ fs.rmSync(appDir, { recursive: true, force: true });
395
+ execFileSync("osacompile", ["-o", appDir, tmp], { stdio: "ignore" });
396
+ const icns = path.join(PACKAGE_ROOT, "build", "icon.icns");
397
+ if (fs.existsSync(icns)) {
398
+ fs.copyFileSync(icns, path.join(appDir, "Contents", "Resources", "applet.icns"));
399
+ }
400
+ try { const t = new Date(); fs.utimesSync(appDir, t, t); } catch {}
401
+ console.log(`📎 Desktop shortcut: ${appDir}`);
402
+ } finally {
403
+ try { fs.unlinkSync(tmp); } catch {}
404
+ }
405
+ }
406
+
407
+ function ensureLinuxDesktopEntry() {
408
+ const icon = path.join(PACKAGE_ROOT, "build", "icons", "icon-256.png");
409
+ const file = path.join(DESKTOP_DIR, "cicy-desktop.desktop");
410
+ fs.mkdirSync(DESKTOP_DIR, { recursive: true });
411
+ fs.writeFileSync(file,
412
+ `[Desktop Entry]
413
+ Type=Application
414
+ Name=CiCy Desktop
415
+ Exec=sh -c 'export PATH="${nodeBinDir()}:$PATH"; export ELECTRON_MIRROR="${ELECTRON_MIRROR}"; export npm_config_registry="${NPM_REGISTRY}"; exec npx -y cicy-desktop'
416
+ Icon=${icon}
417
+ Terminal=false
418
+ Categories=Development;
419
+ `);
420
+ fs.chmodSync(file, 0o755);
421
+ console.log(`📎 Desktop shortcut: ${file}`);
422
+ }
423
+
424
+ function ensureWindowsShortcut() {
425
+ // A .cmd is icon-less; a proper .lnk with the CiCy icon is written via a
426
+ // throwaway PowerShell script (WScript.Shell CreateShortcut + IconLocation).
427
+ const ico = path.join(PACKAGE_ROOT, "build", "icon.ico");
428
+ const lnk = path.join(DESKTOP_DIR, "CiCy Desktop.lnk");
429
+ const nodeDir = nodeBinDir();
430
+ const ps = path.join(require("os").tmpdir(), `cicy-shortcut-${process.pid}.ps1`);
431
+ fs.writeFileSync(ps,
432
+ `$ws = New-Object -ComObject WScript.Shell
433
+ $s = $ws.CreateShortcut('${lnk.replace(/'/g, "''")}')
434
+ $s.TargetPath = 'cmd.exe'
435
+ $s.Arguments = '/c set PATH=${nodeDir};%PATH%&& set ELECTRON_MIRROR=${ELECTRON_MIRROR}&& set npm_config_registry=${NPM_REGISTRY}&& npx -y cicy-desktop'
436
+ $s.IconLocation = '${ico.replace(/'/g, "''")}'
437
+ $s.Save()
438
+ `);
439
+ try {
440
+ execSync(`powershell -NoProfile -ExecutionPolicy Bypass -File "${ps}"`, { stdio: "ignore" });
441
+ console.log(`📎 Desktop shortcut: ${lnk}`);
442
+ } finally {
443
+ try { fs.unlinkSync(ps); } catch {}
352
444
  }
353
-
354
- fs.copyFileSync(PROJECT_COMMAND_FILE, DESKTOP_COMMAND_FILE);
355
- fs.chmodSync(DESKTOP_COMMAND_FILE, 0o755);
356
- console.log(`📎 Synced launcher to ${DESKTOP_COMMAND_FILE}`);
357
445
  }
358
446
 
359
447
  function prefixLines(prefix, text) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cicy-desktop",
3
- "version": "2.1.31",
3
+ "version": "2.1.33",
4
4
  "description": "CiCy - AI-powered operating system browser",
5
5
  "main": "src/main.js",
6
6
  "bin": {
@@ -101,19 +101,11 @@ contextBridge.exposeInMainWorld("cicy", {
101
101
  restartSidecar: () => logInvoke("backends:restart-sidecar"),
102
102
  resolveUrl: (id) => logInvoke("backends:resolve-url", id),
103
103
  },
104
+ // cicy-code is installed/run by the sidecar via `npx cicy-code` (mac/linux)
105
+ // or Docker (Windows) — no in-app downloader. Only lifecycle + status remain.
104
106
  sidecar: {
105
107
  status: () => logInvoke("sidecar:status"),
106
- wslStatus: () => logInvoke("sidecar:wsl-status"),
107
- installWsl: () => logInvoke("sidecar:wsl-install"),
108
- checkLatest: () => logInvoke("sidecar:check-latest"),
109
- install: () => logInvoke("sidecar:install"),
110
108
  start: () => logInvoke("sidecar:start"),
111
- cancel: () => logInvoke("sidecar:cancel"),
112
- onProgress: (cb) => {
113
- const handler = (_e, payload) => { try { cb(payload); } catch {} };
114
- ipcRenderer.on("sidecar:progress", handler);
115
- return () => ipcRenderer.removeListener("sidecar:progress", handler);
116
- },
117
109
  },
118
110
  windows: {
119
111
  list: () => logInvoke("windows:list"),