cicy-desktop 2.1.30 → 2.1.32

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
@@ -346,14 +346,92 @@ function executeCommand(cmd) {
346
346
  }
347
347
  }
348
348
 
349
+ // Drop a double-clickable, CiCy-icon desktop shortcut that relaunches via
350
+ // `npx cicy-desktop`. GUI-launched shortcuts get a minimal PATH (no node), so
351
+ // we bake the dir of the node running this launcher (process.execPath) in.
352
+ function nodeBinDir() {
353
+ try { return path.dirname(process.execPath); } catch { return ""; }
354
+ }
355
+
349
356
  function ensureDesktopCommandFile() {
350
- if (!fs.existsSync(PROJECT_COMMAND_FILE)) {
351
- return;
357
+ try {
358
+ if (process.platform === "darwin") return ensureMacDesktopApp();
359
+ if (process.platform === "linux") return ensureLinuxDesktopEntry();
360
+ if (process.platform === "win32") return ensureWindowsShortcut();
361
+ } catch (e) {
362
+ console.warn(`[shortcut] failed: ${e.message}`);
363
+ }
364
+ }
365
+
366
+ function ensureMacDesktopApp() {
367
+ // Build a REAL AppleScript .app via osacompile. A hand-crafted .app whose
368
+ // executable is a shell script triggers "CiCy Desktop is not responding"
369
+ // (LaunchServices waits for the script to register as a Cocoa app and times
370
+ // out). An osacompile applet's executable IS the AppleScript runtime — a
371
+ // proper Cocoa app — so it launches cleanly, backgrounds `npx cicy-desktop`
372
+ // via `do shell script`, then quits. Icon = the applet's applet.icns.
373
+ const { execFileSync } = require("child_process");
374
+ const appDir = path.join(DESKTOP_DIR, "CiCy Desktop.app");
375
+ const nodeDir = nodeBinDir();
376
+ // do shell script needs node on PATH (GUI launch has a minimal PATH); the
377
+ // trailing & + nohup + </dev/null lets the shell return so the applet quits.
378
+ const ascript =
379
+ `do shell script "export PATH=\\"${nodeDir}:/usr/local/bin:/opt/homebrew/bin:$PATH\\" ; ` +
380
+ `nohup npx -y cicy-desktop > /tmp/cicy-desktop.log 2>&1 < /dev/null &"`;
381
+ const tmp = path.join(os.tmpdir(), `cicy-launch-${process.pid}.applescript`);
382
+ fs.writeFileSync(tmp, ascript);
383
+ try {
384
+ fs.rmSync(appDir, { recursive: true, force: true });
385
+ execFileSync("osacompile", ["-o", appDir, tmp], { stdio: "ignore" });
386
+ const icns = path.join(PACKAGE_ROOT, "build", "icon.icns");
387
+ if (fs.existsSync(icns)) {
388
+ fs.copyFileSync(icns, path.join(appDir, "Contents", "Resources", "applet.icns"));
389
+ }
390
+ try { const t = new Date(); fs.utimesSync(appDir, t, t); } catch {}
391
+ console.log(`📎 Desktop shortcut: ${appDir}`);
392
+ } finally {
393
+ try { fs.unlinkSync(tmp); } catch {}
394
+ }
395
+ }
396
+
397
+ function ensureLinuxDesktopEntry() {
398
+ const icon = path.join(PACKAGE_ROOT, "build", "icons", "icon-256.png");
399
+ const file = path.join(DESKTOP_DIR, "cicy-desktop.desktop");
400
+ fs.mkdirSync(DESKTOP_DIR, { recursive: true });
401
+ fs.writeFileSync(file,
402
+ `[Desktop Entry]
403
+ Type=Application
404
+ Name=CiCy Desktop
405
+ Exec=sh -c 'export PATH="${nodeBinDir()}:$PATH"; exec npx -y cicy-desktop'
406
+ Icon=${icon}
407
+ Terminal=false
408
+ Categories=Development;
409
+ `);
410
+ fs.chmodSync(file, 0o755);
411
+ console.log(`📎 Desktop shortcut: ${file}`);
412
+ }
413
+
414
+ function ensureWindowsShortcut() {
415
+ // A .cmd is icon-less; a proper .lnk with the CiCy icon is written via a
416
+ // throwaway PowerShell script (WScript.Shell CreateShortcut + IconLocation).
417
+ const ico = path.join(PACKAGE_ROOT, "build", "icon.ico");
418
+ const lnk = path.join(DESKTOP_DIR, "CiCy Desktop.lnk");
419
+ const nodeDir = nodeBinDir();
420
+ const ps = path.join(require("os").tmpdir(), `cicy-shortcut-${process.pid}.ps1`);
421
+ fs.writeFileSync(ps,
422
+ `$ws = New-Object -ComObject WScript.Shell
423
+ $s = $ws.CreateShortcut('${lnk.replace(/'/g, "''")}')
424
+ $s.TargetPath = 'cmd.exe'
425
+ $s.Arguments = '/c set PATH=${nodeDir};%PATH% && npx -y cicy-desktop'
426
+ $s.IconLocation = '${ico.replace(/'/g, "''")}'
427
+ $s.Save()
428
+ `);
429
+ try {
430
+ execSync(`powershell -NoProfile -ExecutionPolicy Bypass -File "${ps}"`, { stdio: "ignore" });
431
+ console.log(`📎 Desktop shortcut: ${lnk}`);
432
+ } finally {
433
+ try { fs.unlinkSync(ps); } catch {}
352
434
  }
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
435
  }
358
436
 
359
437
  function prefixLines(prefix, text) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cicy-desktop",
3
- "version": "2.1.30",
3
+ "version": "2.1.32",
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"),