nexora-code 1.0.3 → 1.0.5

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/dist/bundle.cjs CHANGED
@@ -7085,7 +7085,7 @@ var init_string_width = __esm({
7085
7085
  init_get_east_asian_width();
7086
7086
  import_emoji_regex = __toESM(require_emoji_regex(), 1);
7087
7087
  segmenter = new Intl.Segmenter();
7088
- defaultIgnorableCodePointRegex = new RegExp("^\\p{Default_Ignorable_Code_Point}$", "u");
7088
+ defaultIgnorableCodePointRegex = /^\p{Default_Ignorable_Code_Point}$/u;
7089
7089
  }
7090
7090
  });
7091
7091
 
@@ -284542,6 +284542,594 @@ var init_archiver = __esm({
284542
284542
  }
284543
284543
  });
284544
284544
 
284545
+ // scripts/desktop/config.cjs
284546
+ var require_config = __commonJS({
284547
+ "scripts/desktop/config.cjs"(exports2, module2) {
284548
+ "use strict";
284549
+ var path55 = require("path");
284550
+ function getNexoraConfig() {
284551
+ try {
284552
+ const pkgPath = path55.resolve(__dirname, "../../package.json");
284553
+ const pkg = require(pkgPath);
284554
+ let binName = "nexora";
284555
+ if (typeof pkg.bin === "string") {
284556
+ binName = pkg.name;
284557
+ } else if (typeof pkg.bin === "object" && pkg.bin !== null) {
284558
+ binName = Object.keys(pkg.bin)[0];
284559
+ }
284560
+ return {
284561
+ binName,
284562
+ displayName: "Nexora Code",
284563
+ description: "Launch Nexora Code AI Workspace"
284564
+ };
284565
+ } catch {
284566
+ return {
284567
+ binName: "nexora",
284568
+ displayName: "Nexora Code",
284569
+ description: "Launch Nexora Code AI Workspace"
284570
+ };
284571
+ }
284572
+ }
284573
+ module2.exports = { getNexoraConfig };
284574
+ }
284575
+ });
284576
+
284577
+ // scripts/desktop/windows-wt-profile.cjs
284578
+ var require_windows_wt_profile = __commonJS({
284579
+ "scripts/desktop/windows-wt-profile.cjs"(exports2, module2) {
284580
+ "use strict";
284581
+ var fs51 = require("fs");
284582
+ var path55 = require("path");
284583
+ function getWTSettingsPath() {
284584
+ const localAppData = process.env.LOCALAPPDATA || "";
284585
+ const candidates = [
284586
+ // Store version
284587
+ path55.join(localAppData, "Packages", "Microsoft.WindowsTerminal_8wekyb3d8bbwe", "LocalState", "settings.json"),
284588
+ // Preview version
284589
+ path55.join(localAppData, "Packages", "Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe", "LocalState", "settings.json"),
284590
+ // Winget / scoop version
284591
+ path55.join(localAppData, "Microsoft", "Windows Terminal", "settings.json")
284592
+ ];
284593
+ return candidates.find((p) => {
284594
+ try {
284595
+ fs51.accessSync(p);
284596
+ return true;
284597
+ } catch {
284598
+ return false;
284599
+ }
284600
+ }) || null;
284601
+ }
284602
+ var { execSync: execSync5 } = require("child_process");
284603
+ var { getNexoraConfig } = require_config();
284604
+ async function resolveNexoraAbsolutePath(binName) {
284605
+ try {
284606
+ const result = execSync5(`where ${binName}`, { stdio: "pipe" }).toString().trim().split("\n")[0].trim();
284607
+ if (result) return result;
284608
+ } catch {
284609
+ }
284610
+ try {
284611
+ const prefix = execSync5("npm config get prefix", { stdio: "pipe" }).toString().trim();
284612
+ const candidate = path55.join(prefix, `${binName}.cmd`);
284613
+ fs51.accessSync(candidate);
284614
+ return candidate;
284615
+ } catch {
284616
+ }
284617
+ throw new Error(
284618
+ `${binName}.cmd not found. Ensure "npm install -g nexora-code" completed successfully.`
284619
+ );
284620
+ }
284621
+ function detectBestShell(binName) {
284622
+ try {
284623
+ execSync5("where pwsh.exe", { stdio: "pipe" });
284624
+ return { shellExe: "pwsh.exe" };
284625
+ } catch {
284626
+ }
284627
+ return {
284628
+ shellExe: "powershell.exe"
284629
+ };
284630
+ }
284631
+ async function repairWTProfile() {
284632
+ const settingsPath = getWTSettingsPath();
284633
+ if (!settingsPath) return;
284634
+ let settings;
284635
+ try {
284636
+ const raw = fs51.readFileSync(settingsPath, "utf-8");
284637
+ const stripped = raw.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
284638
+ settings = JSON.parse(stripped);
284639
+ } catch {
284640
+ return;
284641
+ }
284642
+ const profiles = settings?.profiles?.list;
284643
+ if (!Array.isArray(profiles)) return;
284644
+ let modified = false;
284645
+ for (const profile of profiles) {
284646
+ const { binName } = getNexoraConfig();
284647
+ if (profile.name === "Nexora Code" && (profile.commandline === "nexora-code" || profile.commandline === binName)) {
284648
+ const { shellExe } = detectBestShell(binName);
284649
+ const nexoraAbs = await resolveNexoraAbsolutePath(binName);
284650
+ profile.commandline = `${shellExe} -NoExit -Command "& '${nexoraAbs.replace(/\\/g, "\\\\").replace(/'/g, "''")}'"`;
284651
+ modified = true;
284652
+ console.log(" \u2713 Repaired corrupted Windows Terminal profile.");
284653
+ console.log(` \u2713 Fixed commandline \u2192 ${profile.commandline}`);
284654
+ }
284655
+ }
284656
+ if (modified) {
284657
+ fs51.writeFileSync(settingsPath, JSON.stringify(settings, null, 4), "utf-8");
284658
+ }
284659
+ }
284660
+ module2.exports = { repairWTProfile, resolveNexoraAbsolutePath };
284661
+ }
284662
+ });
284663
+
284664
+ // scripts/desktop/windows.cjs
284665
+ var require_windows2 = __commonJS({
284666
+ "scripts/desktop/windows.cjs"(exports2, module2) {
284667
+ "use strict";
284668
+ var { execSync: execSync5 } = require("child_process");
284669
+ var path55 = require("path");
284670
+ var fs51 = require("fs");
284671
+ var os18 = require("os");
284672
+ var { repairWTProfile, resolveNexoraAbsolutePath } = require_windows_wt_profile();
284673
+ var { getNexoraConfig } = require_config();
284674
+ function detectWindowsTerminal() {
284675
+ try {
284676
+ const wtPath = execSync5("where wt.exe", { stdio: "pipe" }).toString().trim().split("\n")[0].trim();
284677
+ if (wtPath) {
284678
+ try {
284679
+ execSync5("where pwsh.exe", { stdio: "pipe" });
284680
+ return { label: "Windows Terminal + PowerShell 7", shellExe: wtPath, innerShell: "pwsh.exe" };
284681
+ } catch {
284682
+ return { label: "Windows Terminal + PowerShell 5", shellExe: wtPath, innerShell: "powershell.exe" };
284683
+ }
284684
+ }
284685
+ } catch {
284686
+ }
284687
+ try {
284688
+ const pwsh7 = execSync5("where pwsh.exe", { stdio: "pipe" }).toString().trim().split("\n")[0].trim();
284689
+ if (pwsh7) return { label: "PowerShell 7", shellExe: pwsh7, innerShell: null };
284690
+ } catch {
284691
+ }
284692
+ const ps5 = path55.join(process.env.SystemRoot || "C:\\Windows", "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
284693
+ return { label: "PowerShell 5", shellExe: ps5, innerShell: null };
284694
+ }
284695
+ async function createWindowsShortcut(ctx) {
284696
+ await repairWTProfile();
284697
+ const { binName, displayName, description } = getNexoraConfig();
284698
+ let nexoraAbsPath;
284699
+ try {
284700
+ nexoraAbsPath = await resolveNexoraAbsolutePath(binName);
284701
+ console.log(` \u2713 Binary found at : ${nexoraAbsPath}`);
284702
+ } catch (err6) {
284703
+ console.log(` \u2717 ${err6.message}`);
284704
+ return;
284705
+ }
284706
+ const shortcutPath = path55.join(ctx.desktopPath, `${displayName}.lnk`);
284707
+ const iconPath = path55.join(ctx.iconDir, "icon.ico");
284708
+ const iconExists = fs51.existsSync(iconPath);
284709
+ const terminal2 = detectWindowsTerminal();
284710
+ let targetExe, shortcutArgs;
284711
+ if (terminal2.innerShell) {
284712
+ targetExe = terminal2.shellExe;
284713
+ shortcutArgs = `${terminal2.innerShell} -NoExit -Command "& '${nexoraAbsPath}'"`;
284714
+ } else {
284715
+ targetExe = terminal2.shellExe;
284716
+ shortcutArgs = `-NoExit -Command "& '${nexoraAbsPath}'"`;
284717
+ }
284718
+ const ps1Lines = [
284719
+ `$ws = New-Object -ComObject WScript.Shell`,
284720
+ `$sc = $ws.CreateShortcut(@"`,
284721
+ shortcutPath,
284722
+ `"@)`,
284723
+ `$sc.TargetPath = @"`,
284724
+ targetExe,
284725
+ `"@`,
284726
+ `$sc.Arguments = @"`,
284727
+ shortcutArgs,
284728
+ `"@`,
284729
+ `$sc.WorkingDirectory = $env:USERPROFILE`,
284730
+ `$sc.Description = @"`,
284731
+ description,
284732
+ `"@`
284733
+ ];
284734
+ if (iconExists) {
284735
+ ps1Lines.push(`$sc.IconLocation = @"`, iconPath, `"@`);
284736
+ }
284737
+ ps1Lines.push(`$sc.Save()`);
284738
+ const ps1Content = ps1Lines.join("\r\n") + "\r\n";
284739
+ const ps1Path = path55.join(os18.tmpdir(), `nexora-shortcut-${Date.now()}.ps1`);
284740
+ try {
284741
+ fs51.writeFileSync(ps1Path, ps1Content, "utf-8");
284742
+ execSync5(
284743
+ `powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "${ps1Path}"`,
284744
+ { stdio: "pipe", timeout: 2e4 }
284745
+ );
284746
+ console.log(` \u2713 Desktop shortcut : ${shortcutPath}`);
284747
+ console.log(` \u2713 Terminal : ${terminal2.label}`);
284748
+ console.log(` \u2713 Launches : ${binName}`);
284749
+ if (iconExists) console.log(` \u2713 Icon applied : Nexora Code logo`);
284750
+ console.log("");
284751
+ console.log(` \u2192 Double-click "${displayName}" on your Desktop to launch!`);
284752
+ console.log("");
284753
+ } catch (err6) {
284754
+ throw new Error(`Windows .lnk creation failed: ${err6.message}`);
284755
+ } finally {
284756
+ try {
284757
+ fs51.unlinkSync(ps1Path);
284758
+ } catch {
284759
+ }
284760
+ }
284761
+ }
284762
+ function removeWindowsShortcut(ctx) {
284763
+ const { displayName } = getNexoraConfig();
284764
+ const shortcutPath = path55.join(ctx.desktopPath, `${displayName}.lnk`);
284765
+ try {
284766
+ fs51.unlinkSync(shortcutPath);
284767
+ console.log(` \u2713 Desktop shortcut removed: ${displayName}.lnk`);
284768
+ } catch {
284769
+ }
284770
+ }
284771
+ module2.exports = { createWindowsShortcut, removeWindowsShortcut };
284772
+ }
284773
+ });
284774
+
284775
+ // scripts/desktop/macos.cjs
284776
+ var require_macos = __commonJS({
284777
+ "scripts/desktop/macos.cjs"(exports2, module2) {
284778
+ "use strict";
284779
+ var { execSync: execSync5 } = require("child_process");
284780
+ var path55 = require("path");
284781
+ var fs51 = require("fs");
284782
+ var { getNexoraConfig } = require_config();
284783
+ function buildMacTerminalScript(binName) {
284784
+ if (fs51.existsSync("/Applications/iTerm.app")) {
284785
+ return `#!/bin/bash
284786
+ open -a iTerm -- bash -c "${binName}; exec bash"
284787
+ `;
284788
+ }
284789
+ if (fs51.existsSync("/Applications/Warp.app")) {
284790
+ return `#!/bin/bash
284791
+ open -a Warp
284792
+ osascript -e 'tell application "Warp" to activate'
284793
+ `;
284794
+ }
284795
+ if (fs51.existsSync("/Applications/Hyper.app")) {
284796
+ return `#!/bin/bash
284797
+ open -a Hyper
284798
+ `;
284799
+ }
284800
+ return `#!/bin/bash
284801
+ osascript <<'APPLESCRIPT'
284802
+ tell application "Terminal"
284803
+ activate
284804
+ do script "${binName}"
284805
+ end tell
284806
+ APPLESCRIPT
284807
+ `;
284808
+ }
284809
+ function buildPlist(hasIcon, displayName) {
284810
+ return `<?xml version="1.0" encoding="UTF-8"?>
284811
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
284812
+ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
284813
+ <plist version="1.0">
284814
+ <dict>
284815
+ <key>CFBundleExecutable</key>
284816
+ <string>nexora-launcher</string>
284817
+ <key>CFBundleIdentifier</key>
284818
+ <string>cloud.getnexora.code</string>
284819
+ <key>CFBundleName</key>
284820
+ <string>${displayName}</string>
284821
+ <key>CFBundleDisplayName</key>
284822
+ <string>${displayName}</string>
284823
+ <key>CFBundleVersion</key>
284824
+ <string>1.0.0</string>
284825
+ <key>CFBundleShortVersionString</key>
284826
+ <string>1.0.0</string>
284827
+ <key>CFBundlePackageType</key>
284828
+ <string>APPL</string>
284829
+ ${hasIcon ? "<key>CFBundleIconFile</key>\n <string>AppIcon</string>" : ""}
284830
+ <key>LSMinimumSystemVersion</key>
284831
+ <string>11.0</string>
284832
+ <key>NSHighResolutionCapable</key>
284833
+ <true/>
284834
+ <key>LSUIElement</key>
284835
+ <false/>
284836
+ </dict>
284837
+ </plist>
284838
+ `;
284839
+ }
284840
+ function createMacosShortcut(ctx) {
284841
+ const { binName, displayName } = getNexoraConfig();
284842
+ const appBundlePath = path55.join(ctx.desktopPath, `${displayName}.app`);
284843
+ const macOSDir = path55.join(appBundlePath, "Contents", "MacOS");
284844
+ const resourceDir = path55.join(appBundlePath, "Contents", "Resources");
284845
+ const icnsPath = path55.join(ctx.iconDir, "icon.icns");
284846
+ const hasIcon = fs51.existsSync(icnsPath);
284847
+ fs51.mkdirSync(macOSDir, { recursive: true });
284848
+ fs51.mkdirSync(resourceDir, { recursive: true });
284849
+ const launcherContent = buildMacTerminalScript(binName);
284850
+ const launcherPath = path55.join(macOSDir, "nexora-launcher");
284851
+ fs51.writeFileSync(launcherPath, launcherContent, "utf-8");
284852
+ fs51.chmodSync(launcherPath, 493);
284853
+ fs51.writeFileSync(
284854
+ path55.join(appBundlePath, "Contents", "Info.plist"),
284855
+ buildPlist(hasIcon, displayName),
284856
+ "utf-8"
284857
+ );
284858
+ if (hasIcon) {
284859
+ fs51.copyFileSync(icnsPath, path55.join(resourceDir, "AppIcon.icns"));
284860
+ }
284861
+ try {
284862
+ execSync5(`xattr -dr com.apple.quarantine "${appBundlePath}"`, { stdio: "pipe" });
284863
+ } catch {
284864
+ }
284865
+ try {
284866
+ execSync5(`touch "${appBundlePath}"`, { stdio: "pipe" });
284867
+ } catch {
284868
+ }
284869
+ console.log(` \u2713 App bundle created: ${appBundlePath}`);
284870
+ createCommandFallback(ctx.desktopPath, displayName, binName);
284871
+ console.log("");
284872
+ console.log(` \u2192 Double-click "${displayName}" on your Desktop to launch Nexora!`);
284873
+ console.log("");
284874
+ }
284875
+ function createCommandFallback(desktopPath, displayName, binName) {
284876
+ const commandPath = path55.join(desktopPath, `${displayName} (Terminal).command`);
284877
+ const commandContent = `#!/bin/bash
284878
+ clear
284879
+ ${binName}
284880
+ exec $SHELL
284881
+ `;
284882
+ fs51.writeFileSync(commandPath, commandContent, "utf-8");
284883
+ fs51.chmodSync(commandPath, 493);
284884
+ console.log(` \u2713 .command fallback: ${commandPath}`);
284885
+ }
284886
+ function removeMacosShortcut(ctx) {
284887
+ const { binName, displayName } = getNexoraConfig();
284888
+ const targets = [
284889
+ path55.join(ctx.desktopPath, `${displayName}.app`),
284890
+ path55.join(ctx.desktopPath, `${displayName} (Terminal).command`),
284891
+ // Remove old defaults just in case
284892
+ path55.join(ctx.desktopPath, "Nexora Code.app"),
284893
+ path55.join(ctx.desktopPath, "Nexora Code (Terminal).command")
284894
+ ];
284895
+ for (const t of targets) {
284896
+ try {
284897
+ fs51.rmSync(t, { recursive: true, force: true });
284898
+ console.log(` \u2713 Removed: ${t}`);
284899
+ } catch {
284900
+ }
284901
+ }
284902
+ }
284903
+ module2.exports = { createMacosShortcut, removeMacosShortcut };
284904
+ }
284905
+ });
284906
+
284907
+ // scripts/desktop/linux.cjs
284908
+ var require_linux = __commonJS({
284909
+ "scripts/desktop/linux.cjs"(exports2, module2) {
284910
+ "use strict";
284911
+ var { execSync: execSync5 } = require("child_process");
284912
+ var path55 = require("path");
284913
+ var fs51 = require("fs");
284914
+ var { getNexoraConfig } = require_config();
284915
+ var TERMINAL_CANDIDATES = [
284916
+ { bin: "gnome-terminal", args: '-- bash -c "nexora-code; exec bash"' },
284917
+ { bin: "konsole", args: '-e bash -c "nexora-code; exec bash"' },
284918
+ { bin: "xfce4-terminal", args: `--command="bash -c 'nexora-code; exec bash'"` },
284919
+ { bin: "tilix", args: `-e "bash -c 'nexora-code; exec bash'"` },
284920
+ { bin: "alacritty", args: '-e bash -c "nexora-code; exec bash"' },
284921
+ { bin: "kitty", args: 'bash -c "nexora-code; exec bash"' },
284922
+ { bin: "xterm", args: '-e "nexora-code; bash"' },
284923
+ { bin: "x-terminal-emulator", args: '-e bash -c "nexora-code; exec bash"' }
284924
+ // Debian/Ubuntu alias
284925
+ ];
284926
+ function detectLinuxTerminal() {
284927
+ for (const candidate of TERMINAL_CANDIDATES) {
284928
+ try {
284929
+ execSync5(`which ${candidate.bin}`, { stdio: "pipe" });
284930
+ return candidate;
284931
+ } catch {
284932
+ continue;
284933
+ }
284934
+ }
284935
+ return null;
284936
+ }
284937
+ function createLinuxShortcut(ctx) {
284938
+ const { binName, displayName, description } = getNexoraConfig();
284939
+ const terminal2 = detectLinuxTerminal();
284940
+ const iconPath = path55.join(ctx.iconDir, "icon.png");
284941
+ const iconExists = fs51.existsSync(iconPath);
284942
+ const execLine = terminal2 ? `${terminal2.bin} ${terminal2.args.replace(/nexora-code/g, binName)}` : binName;
284943
+ const iconLine = iconExists ? iconPath : "utilities-terminal";
284944
+ const desktopContent = [
284945
+ "[Desktop Entry]",
284946
+ "Version=1.0",
284947
+ "Type=Application",
284948
+ `Name=${displayName}`,
284949
+ "GenericName=AI Developer Workspace",
284950
+ `Comment=${description}`,
284951
+ `Exec=${execLine}`,
284952
+ `Icon=${iconLine}`,
284953
+ "Terminal=false",
284954
+ // false: the terminal emulator handles this
284955
+ "StartupNotify=true",
284956
+ "Categories=Development;IDE;",
284957
+ `Keywords=${binName};code;ai;developer;assistant;cli;`,
284958
+ `StartupWMClass=${binName}`
284959
+ ].join("\n") + "\n";
284960
+ const desktopFilePath = path55.join(ctx.desktopPath, "nexora-code.desktop");
284961
+ fs51.writeFileSync(desktopFilePath, desktopContent, "utf-8");
284962
+ fs51.chmodSync(desktopFilePath, 493);
284963
+ console.log(` \u2713 Desktop launcher: ${desktopFilePath}`);
284964
+ const appMenuDir = path55.join(ctx.realHomeDir, ".local", "share", "applications");
284965
+ const appMenuPath = path55.join(appMenuDir, "nexora-code.desktop");
284966
+ try {
284967
+ fs51.mkdirSync(appMenuDir, { recursive: true });
284968
+ fs51.writeFileSync(appMenuPath, desktopContent, "utf-8");
284969
+ fs51.chmodSync(appMenuPath, 493);
284970
+ console.log(` \u2713 App menu entry: ${appMenuPath}`);
284971
+ try {
284972
+ execSync5("update-desktop-database ~/.local/share/applications", { stdio: "pipe" });
284973
+ } catch {
284974
+ }
284975
+ } catch (err6) {
284976
+ console.log(` \u26A0 App menu entry skipped: ${err6.message}`);
284977
+ }
284978
+ if (terminal2) {
284979
+ console.log(` \u2713 Terminal detected: ${terminal2.bin}`);
284980
+ } else {
284981
+ console.log(" \u26A0 No terminal emulator detected \u2014 using system default.");
284982
+ }
284983
+ console.log("");
284984
+ console.log(` \u2192 Double-click the icon on your Desktop to launch ${displayName}!`);
284985
+ if (!terminal2) {
284986
+ console.log(` \u2192 Or run "${binName}" directly in your terminal.`);
284987
+ }
284988
+ console.log("");
284989
+ }
284990
+ function removeLinuxShortcut(ctx) {
284991
+ const { binName } = getNexoraConfig();
284992
+ const targets = [
284993
+ path55.join(ctx.desktopPath, "nexora-code.desktop"),
284994
+ path55.join(ctx.realHomeDir, ".local", "share", "applications", "nexora-code.desktop"),
284995
+ // Also remove using the new displayName or binName if applicable
284996
+ path55.join(ctx.desktopPath, `${binName}.desktop`),
284997
+ path55.join(ctx.realHomeDir, ".local", "share", "applications", `${binName}.desktop`)
284998
+ ];
284999
+ for (const t of targets) {
285000
+ try {
285001
+ fs51.unlinkSync(t);
285002
+ console.log(` \u2713 Removed: ${t}`);
285003
+ } catch {
285004
+ }
285005
+ }
285006
+ try {
285007
+ execSync5("update-desktop-database ~/.local/share/applications", { stdio: "pipe" });
285008
+ } catch {
285009
+ }
285010
+ }
285011
+ module2.exports = { createLinuxShortcut, removeLinuxShortcut };
285012
+ }
285013
+ });
285014
+
285015
+ // scripts/desktop/shortcut.cjs
285016
+ var require_shortcut = __commonJS({
285017
+ "scripts/desktop/shortcut.cjs"(exports2, module2) {
285018
+ "use strict";
285019
+ var os18 = require("os");
285020
+ var path55 = require("path");
285021
+ var fs51 = require("fs");
285022
+ function fileExistsSync(p) {
285023
+ try {
285024
+ fs51.accessSync(p);
285025
+ return true;
285026
+ } catch {
285027
+ return false;
285028
+ }
285029
+ }
285030
+ function getRealHomeDir() {
285031
+ if (process.env.SUDO_USER) {
285032
+ const plat = process.platform;
285033
+ if (plat === "linux") return `/home/${process.env.SUDO_USER}`;
285034
+ if (plat === "darwin") return `/Users/${process.env.SUDO_USER}`;
285035
+ }
285036
+ return process.env.USERPROFILE || process.env.HOME || os18.homedir();
285037
+ }
285038
+ function findDesktopPath(homeDir, platform2) {
285039
+ const candidates = [];
285040
+ if (platform2 === "windows") {
285041
+ candidates.push(
285042
+ path55.join(homeDir, "Desktop"),
285043
+ path55.join(homeDir, "OneDrive", "Desktop"),
285044
+ // Very common on Win11 + OneDrive
285045
+ path55.join(homeDir, "OneDrive - Personal", "Desktop")
285046
+ );
285047
+ } else if (platform2 === "macos") {
285048
+ candidates.push(path55.join(homeDir, "Desktop"));
285049
+ } else {
285050
+ const xdgDesktop = process.env.XDG_DESKTOP_DIR;
285051
+ if (xdgDesktop) candidates.push(xdgDesktop);
285052
+ candidates.push(
285053
+ path55.join(homeDir, "Desktop"),
285054
+ path55.join(homeDir, "Escritorio"),
285055
+ // Spanish
285056
+ path55.join(homeDir, "Bureau"),
285057
+ // French
285058
+ path55.join(homeDir, "Schreibtisch"),
285059
+ // German
285060
+ path55.join(homeDir, "\u30C7\u30B9\u30AF\u30C8\u30C3\u30D7"),
285061
+ // Japanese
285062
+ path55.join(homeDir, "\u684C\u9762")
285063
+ // Chinese (Simplified)
285064
+ );
285065
+ }
285066
+ for (const candidate of candidates) {
285067
+ if (fileExistsSync(candidate)) return candidate;
285068
+ }
285069
+ return null;
285070
+ }
285071
+ function getPackageDir() {
285072
+ return path55.resolve(__dirname, "..", "..");
285073
+ }
285074
+ function buildUserContext() {
285075
+ const rawPlatform = process.platform;
285076
+ const platform2 = rawPlatform === "win32" ? "windows" : rawPlatform === "darwin" ? "macos" : "linux";
285077
+ const realHomeDir = getRealHomeDir();
285078
+ const desktopPath = findDesktopPath(realHomeDir, platform2);
285079
+ const packageDir = getPackageDir();
285080
+ const iconDir = path55.join(packageDir, "assets");
285081
+ const { binName } = require_config().getNexoraConfig();
285082
+ const binaryName = platform2 === "windows" ? `${binName}.cmd` : binName;
285083
+ const npmBinDir = path55.dirname(process.execPath);
285084
+ const binaryPath = path55.join(npmBinDir, binaryName);
285085
+ return { platform: platform2, realHomeDir, desktopPath, packageDir, binaryPath, iconDir };
285086
+ }
285087
+ async function createShortcut() {
285088
+ const ctx = buildUserContext();
285089
+ if (!ctx.desktopPath) {
285090
+ const { binName } = require_config().getNexoraConfig();
285091
+ console.log(" \u2139 No desktop found (headless / server / WSL environment).");
285092
+ console.log(` Run "${binName}" in any terminal to start.`);
285093
+ return;
285094
+ }
285095
+ console.log("");
285096
+ console.log(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
285097
+ console.log(" \u2502 Nexora Code \u2014 Desktop Shortcut Setup \u2502");
285098
+ console.log(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
285099
+ console.log("");
285100
+ switch (ctx.platform) {
285101
+ case "windows":
285102
+ await require_windows2().createWindowsShortcut(ctx);
285103
+ break;
285104
+ case "macos":
285105
+ await require_macos().createMacosShortcut(ctx);
285106
+ break;
285107
+ case "linux":
285108
+ await require_linux().createLinuxShortcut(ctx);
285109
+ break;
285110
+ default:
285111
+ console.log(" \u26A0 Unrecognised platform \u2014 skipping shortcut creation.");
285112
+ }
285113
+ }
285114
+ async function removeShortcut() {
285115
+ const ctx = buildUserContext();
285116
+ if (!ctx.desktopPath) return;
285117
+ switch (ctx.platform) {
285118
+ case "windows":
285119
+ await require_windows2().removeWindowsShortcut(ctx);
285120
+ break;
285121
+ case "macos":
285122
+ await require_macos().removeMacosShortcut(ctx);
285123
+ break;
285124
+ case "linux":
285125
+ await require_linux().removeLinuxShortcut(ctx);
285126
+ break;
285127
+ }
285128
+ }
285129
+ module2.exports = { createShortcut, removeShortcut, buildUserContext };
285130
+ }
285131
+ });
285132
+
284545
285133
  // node_modules/pdfjs-dist/legacy/build/pdf.mjs
284546
285134
  var pdf_exports = {};
284547
285135
  __export(pdf_exports, {
@@ -318475,7 +319063,7 @@ function updateNotifier(options) {
318475
319063
  // package.json
318476
319064
  var package_default = {
318477
319065
  name: "nexora-code",
318478
- version: "1.0.3",
319066
+ version: "1.0.5",
318479
319067
  description: "Nexora Code \u2014 World-Class AI Coding Agent CLI. BYOK \xB7 51 tools \xB7 Multi-action \xB7 Streaming \xB7 Session Memory",
318480
319068
  author: "Enoch Boadu",
318481
319069
  license: "MIT",
@@ -332837,6 +333425,13 @@ function loadProjectMemory() {
332837
333425
  // src/index.ts
332838
333426
  init_headless();
332839
333427
  init_keychain();
333428
+ import_node_process51.default.removeAllListeners("warning");
333429
+ import_node_process51.default.on("warning", (warning) => {
333430
+ if (warning.name === "ExperimentalWarning") return;
333431
+ import_node_process51.default.stderr.write(`
333432
+ Warning: ${warning.message}
333433
+ `);
333434
+ });
332840
333435
  var VERSION2 = package_default.version || "0.0.0";
332841
333436
  import_node_process51.default.on("SIGINT", () => {
332842
333437
  console.log(`
@@ -332861,6 +333456,19 @@ var args = import_node_process51.default.argv.slice(2);
332861
333456
  var subcommand = args[0]?.toLowerCase();
332862
333457
  var headless2 = args.includes("--headless");
332863
333458
  async function main2() {
333459
+ if (args.includes("--repair-shortcut")) {
333460
+ const { createShortcut, removeShortcut } = await Promise.resolve().then(() => __toESM(require_shortcut(), 1));
333461
+ console.log("\n Nexora Code \u2014 Repairing desktop shortcut...\n");
333462
+ try {
333463
+ await removeShortcut();
333464
+ await createShortcut();
333465
+ console.log("\n \u2713 Shortcut repaired successfully.\n");
333466
+ import_node_process51.default.exit(0);
333467
+ } catch (err6) {
333468
+ console.error("\n \u2717 Repair failed:", err6.message);
333469
+ import_node_process51.default.exit(1);
333470
+ }
333471
+ }
332864
333472
  const taskIdIndex = args.indexOf("--task-id");
332865
333473
  if (taskIdIndex !== -1 && args[taskIdIndex + 1]) {
332866
333474
  await runBackgroundWorker(args[taskIdIndex + 1]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexora-code",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Nexora Code — World-Class AI Coding Agent CLI. BYOK · 51 tools · Multi-action · Streaming · Session Memory",
5
5
  "author": "Enoch Boadu",
6
6
  "license": "MIT",
@@ -94,4 +94,4 @@
94
94
  "workspaces": [
95
95
  "packages/*"
96
96
  ]
97
- }
97
+ }
@@ -0,0 +1,36 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+
5
+ function getNexoraConfig() {
6
+ try {
7
+ const pkgPath = path.resolve(__dirname, '../../package.json');
8
+ const pkg = require(pkgPath);
9
+
10
+ // Extract the first key from the bin field — that's the terminal command
11
+ let binName = 'nexora'; // fallback
12
+
13
+ if (typeof pkg.bin === 'string') {
14
+ // "bin": "./dist/index.js" — use package name as command
15
+ binName = pkg.name;
16
+ } else if (typeof pkg.bin === 'object' && pkg.bin !== null) {
17
+ // "bin": { "nexora": "./dist/index.js" } — use the key
18
+ binName = Object.keys(pkg.bin)[0];
19
+ }
20
+
21
+ return {
22
+ binName,
23
+ displayName: 'Nexora Code',
24
+ description: 'Launch Nexora Code AI Workspace',
25
+ };
26
+ } catch {
27
+ // If package.json can't be read, fall back to known correct value
28
+ return {
29
+ binName: 'nexora',
30
+ displayName: 'Nexora Code',
31
+ description: 'Launch Nexora Code AI Workspace',
32
+ };
33
+ }
34
+ }
35
+
36
+ module.exports = { getNexoraConfig };
@@ -8,6 +8,8 @@ const { execSync } = require('child_process');
8
8
  const path = require('path');
9
9
  const fs = require('fs');
10
10
 
11
+ const { getNexoraConfig } = require('./config.cjs');
12
+
11
13
  // Ordered by quality of terminal experience (best first)
12
14
  const TERMINAL_CANDIDATES = [
13
15
  { bin: 'gnome-terminal', args: '-- bash -c "nexora-code; exec bash"' },
@@ -38,14 +40,15 @@ function detectLinuxTerminal() {
38
40
  * Creates a .desktop launcher on the desktop and in the app menu.
39
41
  */
40
42
  function createLinuxShortcut(ctx) {
43
+ const { binName, displayName, description } = getNexoraConfig();
41
44
  const terminal = detectLinuxTerminal();
42
45
  const iconPath = path.join(ctx.iconDir, 'icon.png');
43
46
  const iconExists = fs.existsSync(iconPath);
44
47
 
45
48
  // XDG .desktop file spec
46
49
  const execLine = terminal
47
- ? `${terminal.bin} ${terminal.args}`
48
- : 'nexora-code'; // Last resort: hope $TERM is set and system opens a terminal
50
+ ? `${terminal.bin} ${terminal.args.replace(/nexora-code/g, binName)}`
51
+ : binName; // Last resort: hope $TERM is set and system opens a terminal
49
52
 
50
53
  const iconLine = iconExists ? iconPath : 'utilities-terminal';
51
54
 
@@ -53,16 +56,16 @@ function createLinuxShortcut(ctx) {
53
56
  '[Desktop Entry]',
54
57
  'Version=1.0',
55
58
  'Type=Application',
56
- 'Name=Nexora Code',
59
+ `Name=${displayName}`,
57
60
  'GenericName=AI Developer Workspace',
58
- 'Comment=Launch Nexora Code — World-class AI coding assistant',
61
+ `Comment=${description}`,
59
62
  `Exec=${execLine}`,
60
63
  `Icon=${iconLine}`,
61
64
  'Terminal=false', // false: the terminal emulator handles this
62
65
  'StartupNotify=true',
63
66
  'Categories=Development;IDE;',
64
- 'Keywords=nexora;code;ai;developer;assistant;cli;',
65
- 'StartupWMClass=nexora-code',
67
+ `Keywords=${binName};code;ai;developer;assistant;cli;`,
68
+ `StartupWMClass=${binName}`,
66
69
  ].join('\n') + '\n';
67
70
 
68
71
  // 1. Desktop icon
@@ -95,9 +98,9 @@ function createLinuxShortcut(ctx) {
95
98
  }
96
99
 
97
100
  console.log('');
98
- console.log(' → Double-click the icon on your Desktop to launch Nexora Code!');
101
+ console.log(` → Double-click the icon on your Desktop to launch ${displayName}!`);
99
102
  if (!terminal) {
100
- console.log(' → Or run "nexora-code" directly in your terminal.');
103
+ console.log(` → Or run "${binName}" directly in your terminal.`);
101
104
  }
102
105
  console.log('');
103
106
  }
@@ -106,9 +109,13 @@ function createLinuxShortcut(ctx) {
106
109
  * Removes all Nexora Code shortcut files on Linux.
107
110
  */
108
111
  function removeLinuxShortcut(ctx) {
112
+ const { binName } = getNexoraConfig();
109
113
  const targets = [
110
114
  path.join(ctx.desktopPath, 'nexora-code.desktop'),
111
115
  path.join(ctx.realHomeDir, '.local', 'share', 'applications', 'nexora-code.desktop'),
116
+ // Also remove using the new displayName or binName if applicable
117
+ path.join(ctx.desktopPath, `${binName}.desktop`),
118
+ path.join(ctx.realHomeDir, '.local', 'share', 'applications', `${binName}.desktop`),
112
119
  ];
113
120
 
114
121
  for (const t of targets) {
@@ -8,16 +8,16 @@ const { execSync } = require('child_process');
8
8
  const path = require('path');
9
9
  const fs = require('fs');
10
10
 
11
- const APP_NAME = 'Nexora Code';
11
+ const { getNexoraConfig } = require('./config.cjs');
12
12
 
13
13
  /**
14
- * Detect best terminal on macOS.
14
+ * Detect best terminal on macOS and build launch script.
15
15
  * Priority: iTerm2 > Warp > Hyper > Terminal.app (always available)
16
16
  */
17
- function detectMacTerminalScript() {
17
+ function buildMacTerminalScript(binName) {
18
18
  if (fs.existsSync('/Applications/iTerm.app')) {
19
19
  return `#!/bin/bash
20
- open -a iTerm -- bash -c "nexora-code; exec bash"
20
+ open -a iTerm -- bash -c "${binName}; exec bash"
21
21
  `;
22
22
  }
23
23
 
@@ -41,7 +41,7 @@ open -a Hyper
41
41
  osascript <<'APPLESCRIPT'
42
42
  tell application "Terminal"
43
43
  activate
44
- do script "nexora-code"
44
+ do script "${binName}"
45
45
  end tell
46
46
  APPLESCRIPT
47
47
  `;
@@ -50,7 +50,7 @@ APPLESCRIPT
50
50
  /**
51
51
  * Builds the Info.plist content for the .app bundle.
52
52
  */
53
- function buildPlist(hasIcon) {
53
+ function buildPlist(hasIcon, displayName) {
54
54
  return `<?xml version="1.0" encoding="UTF-8"?>
55
55
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
56
56
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
@@ -61,9 +61,9 @@ function buildPlist(hasIcon) {
61
61
  <key>CFBundleIdentifier</key>
62
62
  <string>cloud.getnexora.code</string>
63
63
  <key>CFBundleName</key>
64
- <string>${APP_NAME}</string>
64
+ <string>${displayName}</string>
65
65
  <key>CFBundleDisplayName</key>
66
- <string>${APP_NAME}</string>
66
+ <string>${displayName}</string>
67
67
  <key>CFBundleVersion</key>
68
68
  <string>1.0.0</string>
69
69
  <key>CFBundleShortVersionString</key>
@@ -94,7 +94,8 @@ function buildPlist(hasIcon) {
94
94
  * AppIcon.icns (optional)
95
95
  */
96
96
  function createMacosShortcut(ctx) {
97
- const appBundlePath = path.join(ctx.desktopPath, `${APP_NAME}.app`);
97
+ const { binName, displayName } = getNexoraConfig();
98
+ const appBundlePath = path.join(ctx.desktopPath, `${displayName}.app`);
98
99
  const macOSDir = path.join(appBundlePath, 'Contents', 'MacOS');
99
100
  const resourceDir = path.join(appBundlePath, 'Contents', 'Resources');
100
101
  const icnsPath = path.join(ctx.iconDir, 'icon.icns');
@@ -105,7 +106,7 @@ function createMacosShortcut(ctx) {
105
106
  fs.mkdirSync(resourceDir, { recursive: true });
106
107
 
107
108
  // Write launcher script
108
- const launcherContent = detectMacTerminalScript();
109
+ const launcherContent = buildMacTerminalScript(binName);
109
110
  const launcherPath = path.join(macOSDir, 'nexora-launcher');
110
111
  fs.writeFileSync(launcherPath, launcherContent, 'utf-8');
111
112
  fs.chmodSync(launcherPath, 0o755);
@@ -113,7 +114,7 @@ function createMacosShortcut(ctx) {
113
114
  // Write Info.plist
114
115
  fs.writeFileSync(
115
116
  path.join(appBundlePath, 'Contents', 'Info.plist'),
116
- buildPlist(hasIcon),
117
+ buildPlist(hasIcon, displayName),
117
118
  'utf-8'
118
119
  );
119
120
 
@@ -131,19 +132,19 @@ function createMacosShortcut(ctx) {
131
132
  console.log(` ✓ App bundle created: ${appBundlePath}`);
132
133
 
133
134
  // Also create a simpler .command file as a backup for users who prefer it
134
- createCommandFallback(ctx.desktopPath);
135
+ createCommandFallback(ctx.desktopPath, displayName, binName);
135
136
 
136
137
  console.log('');
137
- console.log(` → Double-click "${APP_NAME}" on your Desktop to launch Nexora!`);
138
+ console.log(` → Double-click "${displayName}" on your Desktop to launch Nexora!`);
138
139
  console.log('');
139
140
  }
140
141
 
141
142
  /**
142
143
  * Creates a fallback .command script (simpler than .app, but always works).
143
144
  */
144
- function createCommandFallback(desktopPath) {
145
- const commandPath = path.join(desktopPath, `${APP_NAME} (Terminal).command`);
146
- const commandContent = `#!/bin/bash\nclear\nnexora-code\nexec $SHELL\n`;
145
+ function createCommandFallback(desktopPath, displayName, binName) {
146
+ const commandPath = path.join(desktopPath, `${displayName} (Terminal).command`);
147
+ const commandContent = `#!/bin/bash\nclear\n${binName}\nexec $SHELL\n`;
147
148
  fs.writeFileSync(commandPath, commandContent, 'utf-8');
148
149
  fs.chmodSync(commandPath, 0o755);
149
150
  console.log(` ✓ .command fallback: ${commandPath}`);
@@ -153,9 +154,13 @@ function createCommandFallback(desktopPath) {
153
154
  * Removes all Nexora Code shortcut files on macOS.
154
155
  */
155
156
  function removeMacosShortcut(ctx) {
157
+ const { binName, displayName } = getNexoraConfig();
156
158
  const targets = [
157
- path.join(ctx.desktopPath, `${APP_NAME}.app`),
158
- path.join(ctx.desktopPath, `${APP_NAME} (Terminal).command`),
159
+ path.join(ctx.desktopPath, `${displayName}.app`),
160
+ path.join(ctx.desktopPath, `${displayName} (Terminal).command`),
161
+ // Remove old defaults just in case
162
+ path.join(ctx.desktopPath, 'Nexora Code.app'),
163
+ path.join(ctx.desktopPath, 'Nexora Code (Terminal).command'),
159
164
  ];
160
165
 
161
166
  for (const t of targets) {
@@ -11,7 +11,7 @@
11
11
 
12
12
  const { createShortcut } = require('./shortcut.cjs');
13
13
 
14
- function main() {
14
+ async function main() {
15
15
  // ── Guard 1: Only run on global installs (-g flag) ──────────────────────────
16
16
  // npm sets npm_config_global=true for `npm install -g` commands.
17
17
  // Local `npm install` inside the project does NOT set this.
@@ -34,7 +34,10 @@ function main() {
34
34
  process.exit(0);
35
35
  }
36
36
 
37
- createShortcut();
37
+ await createShortcut();
38
38
  }
39
39
 
40
- main();
40
+ main().catch(err => {
41
+ // Never let shortcut errors break the install
42
+ process.exit(0);
43
+ });
@@ -8,7 +8,7 @@
8
8
 
9
9
  const { removeShortcut } = require('./shortcut.cjs');
10
10
 
11
- function main() {
11
+ async function main() {
12
12
  // Only clean up after global uninstalls — not local dev uninstalls
13
13
  const isGlobalUninstall = process.env.npm_config_global === 'true';
14
14
  if (!isGlobalUninstall) {
@@ -17,13 +17,11 @@ function main() {
17
17
 
18
18
  console.log('');
19
19
  console.log(' Nexora Code — Cleaning up desktop shortcut...');
20
- removeShortcut();
20
+ await removeShortcut();
21
21
  }
22
22
 
23
23
  // Never let cleanup errors break the uninstall
24
- try {
25
- main();
26
- } catch (err) {
24
+ main().catch(err => {
27
25
  console.log(` ⚠ Cleanup warning: ${err.message}`);
28
26
  process.exit(0);
29
- }
27
+ });
@@ -87,12 +87,13 @@ function buildUserContext() {
87
87
  const packageDir = getPackageDir();
88
88
  const iconDir = path.join(packageDir, 'assets');
89
89
 
90
- // Determine where npm placed the nexora-code binary
91
- const binaryName = platform === 'windows' ? 'nexora-code.cmd' : 'nexora-code';
90
+ // Determine where npm placed the nexora binary (reads bin name from package.json)
91
+ const { binName } = require('./config.cjs').getNexoraConfig();
92
+ const binaryName = platform === 'windows' ? `${binName}.cmd` : binName;
92
93
  // npm puts global bins next to the node executable on Windows,
93
94
  // or in /usr/local/bin (or prefix/bin) on Unix.
94
95
  // process.execPath → e.g. C:\Program Files\nodejs\node.exe
95
- // dirname → C:\Program Files\nodejs\ → that's where nexora-code.cmd lives
96
+ // dirname → C:\Program Files\nodejs\ → that's where nexora.cmd lives
96
97
  const npmBinDir = path.dirname(process.execPath);
97
98
  const binaryPath = path.join(npmBinDir, binaryName);
98
99
 
@@ -101,12 +102,13 @@ function buildUserContext() {
101
102
 
102
103
  // ── Public API ────────────────────────────────────────────────────────────────
103
104
 
104
- function createShortcut() {
105
+ async function createShortcut() {
105
106
  const ctx = buildUserContext();
106
107
 
107
108
  if (!ctx.desktopPath) {
109
+ const { binName } = require('./config.cjs').getNexoraConfig();
108
110
  console.log(' ℹ No desktop found (headless / server / WSL environment).');
109
- console.log(' Run "nexora-code" in any terminal to start.');
111
+ console.log(` Run "${binName}" in any terminal to start.`);
110
112
  return;
111
113
  }
112
114
 
@@ -117,22 +119,22 @@ function createShortcut() {
117
119
  console.log('');
118
120
 
119
121
  switch (ctx.platform) {
120
- case 'windows': require('./windows.cjs').createWindowsShortcut(ctx); break;
121
- case 'macos': require('./macos.cjs').createMacosShortcut(ctx); break;
122
- case 'linux': require('./linux.cjs').createLinuxShortcut(ctx); break;
122
+ case 'windows': await require('./windows.cjs').createWindowsShortcut(ctx); break;
123
+ case 'macos': await require('./macos.cjs').createMacosShortcut(ctx); break;
124
+ case 'linux': await require('./linux.cjs').createLinuxShortcut(ctx); break;
123
125
  default:
124
126
  console.log(' ⚠ Unrecognised platform — skipping shortcut creation.');
125
127
  }
126
128
  }
127
129
 
128
- function removeShortcut() {
130
+ async function removeShortcut() {
129
131
  const ctx = buildUserContext();
130
132
  if (!ctx.desktopPath) return;
131
133
 
132
134
  switch (ctx.platform) {
133
- case 'windows': require('./windows.cjs').removeWindowsShortcut(ctx); break;
134
- case 'macos': require('./macos.cjs').removeMacosShortcut(ctx); break;
135
- case 'linux': require('./linux.cjs').removeLinuxShortcut(ctx); break;
135
+ case 'windows': await require('./windows.cjs').removeWindowsShortcut(ctx); break;
136
+ case 'macos': await require('./macos.cjs').removeMacosShortcut(ctx); break;
137
+ case 'linux': await require('./linux.cjs').removeLinuxShortcut(ctx); break;
136
138
  }
137
139
  }
138
140
 
@@ -0,0 +1,100 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ function getWTSettingsPath() {
7
+ const localAppData = process.env.LOCALAPPDATA || '';
8
+ const candidates = [
9
+ // Store version
10
+ path.join(localAppData, 'Packages', 'Microsoft.WindowsTerminal_8wekyb3d8bbwe', 'LocalState', 'settings.json'),
11
+ // Preview version
12
+ path.join(localAppData, 'Packages', 'Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe', 'LocalState', 'settings.json'),
13
+ // Winget / scoop version
14
+ path.join(localAppData, 'Microsoft', 'Windows Terminal', 'settings.json'),
15
+ ];
16
+ return candidates.find(p => {
17
+ try { fs.accessSync(p); return true; } catch { return false; }
18
+ }) || null;
19
+ }
20
+
21
+ const { execSync } = require('child_process');
22
+ const { getNexoraConfig } = require('./config.cjs');
23
+
24
+ async function resolveNexoraAbsolutePath(binName) {
25
+ // Try where.exe with the correct command name
26
+ try {
27
+ const result = execSync(`where ${binName}`, { stdio: 'pipe' })
28
+ .toString().trim().split('\n')[0].trim();
29
+ if (result) return result;
30
+ } catch { /* not on PATH yet */ }
31
+
32
+ // Fallback: build from npm prefix
33
+ try {
34
+ const prefix = execSync('npm config get prefix', { stdio: 'pipe' }).toString().trim();
35
+ const candidate = path.join(prefix, `${binName}.cmd`);
36
+ fs.accessSync(candidate);
37
+ return candidate;
38
+ } catch { /* not found */ }
39
+
40
+ throw new Error(
41
+ `${binName}.cmd not found. ` +
42
+ `Ensure "npm install -g nexora-code" completed successfully.`
43
+ );
44
+ }
45
+
46
+ function detectBestShell(binName) {
47
+ try {
48
+ execSync('where pwsh.exe', { stdio: 'pipe' });
49
+ return { shellExe: 'pwsh.exe' };
50
+ } catch { /* not found */ }
51
+
52
+ return {
53
+ shellExe: 'powershell.exe',
54
+ };
55
+ }
56
+
57
+ async function repairWTProfile() {
58
+ const settingsPath = getWTSettingsPath();
59
+ if (!settingsPath) return; // WT not installed or can't find settings
60
+
61
+ let settings;
62
+ try {
63
+ const raw = fs.readFileSync(settingsPath, 'utf-8');
64
+ // WT settings.json may have comments — strip them before parsing
65
+ const stripped = raw.replace(/\/\/.*$/gm, '').replace(/\/\*[\s\S]*?\*\//g, '');
66
+ settings = JSON.parse(stripped);
67
+ } catch {
68
+ return; // Can't parse — don't corrupt the file
69
+ }
70
+
71
+ const profiles = settings?.profiles?.list;
72
+ if (!Array.isArray(profiles)) return;
73
+
74
+ let modified = false;
75
+
76
+ for (const profile of profiles) {
77
+ const { binName } = getNexoraConfig();
78
+ // Find any profile where commandline is set to bare "nexora-code" or old binName
79
+ if (
80
+ profile.name === 'Nexora Code' &&
81
+ (profile.commandline === 'nexora-code' || profile.commandline === binName)
82
+ ) {
83
+ const { shellExe } = detectBestShell(binName);
84
+ const nexoraAbs = await resolveNexoraAbsolutePath(binName);
85
+
86
+ profile.commandline = `${shellExe} -NoExit -Command "& '${nexoraAbs.replace(/\\/g, '\\\\').replace(/'/g, "''")}'"`;
87
+ modified = true;
88
+
89
+ console.log(' ✓ Repaired corrupted Windows Terminal profile.');
90
+ console.log(` ✓ Fixed commandline → ${profile.commandline}`);
91
+ }
92
+ }
93
+
94
+ if (modified) {
95
+ // Write back with 4-space indent to match WT's own format
96
+ fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 4), 'utf-8');
97
+ }
98
+ }
99
+
100
+ module.exports = { repairWTProfile, resolveNexoraAbsolutePath };
@@ -4,93 +4,148 @@
4
4
  // ║ Creates a .lnk file via PowerShell COM (WScript.Shell) — zero deps ║
5
5
  // ╚══════════════════════════════════════════════════════════════════════════════╝
6
6
 
7
- const { execSync } = require('child_process');
8
- const path = require('path');
9
- const fs = require('fs');
7
+ const { execSync } = require('child_process');
8
+ const path = require('path');
9
+ const fs = require('fs');
10
+ const os = require('os');
11
+
12
+ const { repairWTProfile, resolveNexoraAbsolutePath } = require('./windows-wt-profile.cjs');
13
+ const { getNexoraConfig } = require('./config.cjs');
14
+
15
+ // ── Terminal detection ────────────────────────────────────────────────────────
10
16
 
11
17
  /**
12
- * Detect the best available terminal on Windows.
13
- * Priority: Windows Terminal > PowerShell 7 > PowerShell 5
18
+ * Returns the best shell exe + base args for launching in that shell.
19
+ * binPath is the absolute path to nexora.cmd passed separately so
20
+ * detectWindowsTerminal doesn't need to know the command name.
14
21
  */
15
22
  function detectWindowsTerminal() {
16
- // Windows Terminal (wt.exe) — best colour/font support
23
+ // Windows Terminal (wt.exe) — best experience
17
24
  try {
18
- execSync('where wt.exe', { stdio: 'pipe' });
19
- return {
20
- exe: 'wt.exe',
21
- args: 'nexora-code',
22
- label: 'Windows Terminal',
23
- };
24
- } catch { /* not installed */ }
25
+ const wtPath = execSync('where wt.exe', { stdio: 'pipe' }).toString().trim().split('\n')[0].trim();
26
+ if (wtPath) {
27
+ try {
28
+ execSync('where pwsh.exe', { stdio: 'pipe' });
29
+ return { label: 'Windows Terminal + PowerShell 7', shellExe: wtPath, innerShell: 'pwsh.exe' };
30
+ } catch {
31
+ return { label: 'Windows Terminal + PowerShell 5', shellExe: wtPath, innerShell: 'powershell.exe' };
32
+ }
33
+ }
34
+ } catch { /* wt not found */ }
25
35
 
26
- // PowerShell 7+ (pwsh.exe) — modern, cross-platform
36
+ // PowerShell 7+
27
37
  try {
28
- execSync('where pwsh.exe', { stdio: 'pipe' });
29
- return {
30
- exe: 'pwsh.exe',
31
- args: '-NoExit -Command nexora-code',
32
- label: 'PowerShell 7',
33
- };
38
+ const pwsh7 = execSync('where pwsh.exe', { stdio: 'pipe' }).toString().trim().split('\n')[0].trim();
39
+ if (pwsh7) return { label: 'PowerShell 7', shellExe: pwsh7, innerShell: null };
34
40
  } catch { /* not installed */ }
35
41
 
36
- // PowerShell 5 (built into all Windows 10/11) — guaranteed fallback
37
- return {
38
- exe: 'powershell.exe',
39
- args: '-NoExit -Command nexora-code',
40
- label: 'PowerShell 5 (built-in)',
41
- };
42
+ // PowerShell 5 guaranteed on Windows 10/11
43
+ const ps5 = path.join(process.env.SystemRoot || 'C:\\Windows', 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe');
44
+ return { label: 'PowerShell 5', shellExe: ps5, innerShell: null };
42
45
  }
43
46
 
47
+ // ── Main shortcut creator ─────────────────────────────────────────────────────
48
+
44
49
  /**
45
- * Creates a Windows .lnk shortcut using PowerShell's WScript.Shell COM object.
46
- * No external libraries required.
50
+ * Builds and executes a PowerShell script file to create the .lnk shortcut.
51
+ * Writing to a .ps1 temp file completely sidesteps all the -Command quoting hell.
47
52
  */
48
- function createWindowsShortcut(ctx) {
49
- const shortcutPath = path.join(ctx.desktopPath, 'Nexora Code.lnk');
53
+ async function createWindowsShortcut(ctx) {
54
+ await repairWTProfile();
55
+
56
+ const { binName, displayName, description } = getNexoraConfig();
57
+
58
+ // ── 1. Resolve the absolute path to nexora.cmd ───────────────────────────
59
+ let nexoraAbsPath;
60
+ try {
61
+ nexoraAbsPath = await resolveNexoraAbsolutePath(binName);
62
+ console.log(` ✓ Binary found at : ${nexoraAbsPath}`);
63
+ } catch (err) {
64
+ console.log(` ✗ ${err.message}`);
65
+ return;
66
+ }
67
+
68
+ // ── 2. Build paths ───────────────────────────────────────────────────────
69
+ const shortcutPath = path.join(ctx.desktopPath, `${displayName}.lnk`);
50
70
  const iconPath = path.join(ctx.iconDir, 'icon.ico');
51
71
  const iconExists = fs.existsSync(iconPath);
52
72
  const terminal = detectWindowsTerminal();
53
73
 
54
- // Escape single-quotes in paths for PowerShell string literals
55
- const safeShortcutPath = shortcutPath.replace(/'/g, "''");
56
- const safeIconPath = iconPath.replace(/'/g, "''");
57
- const safeWorkingDir = '%USERPROFILE%';
58
-
59
- const psLines = [
60
- `$s = New-Object -ComObject WScript.Shell`,
61
- `$lnk = $s.CreateShortcut('${safeShortcutPath}')`,
62
- `$lnk.TargetPath = '${terminal.exe}'`,
63
- `$lnk.Arguments = '${terminal.args}'`,
64
- `$lnk.WorkingDirectory = '$env:USERPROFILE'`,
65
- `$lnk.Description = 'Launch Nexora Code AI Workspace'`,
66
- iconExists ? `$lnk.IconLocation = '${safeIconPath}'` : '',
67
- `$lnk.Save()`,
68
- ].filter(Boolean).join('; ');
74
+ // ── 3. Build the Arguments string ────────────────────────────────────────
75
+ // When using Windows Terminal, wt.exe is the TargetPath and it receives
76
+ // the inner shell as its first argument. When using PS directly, the
77
+ // TargetPath is the shell exe itself.
78
+ let targetExe, shortcutArgs;
79
+
80
+ if (terminal.innerShell) {
81
+ // Windows Terminal: wt.exe powershell.exe -NoExit -Command "& 'C:\path\nexora.cmd'"
82
+ targetExe = terminal.shellExe; // wt.exe
83
+ shortcutArgs = `${terminal.innerShell} -NoExit -Command "& '${nexoraAbsPath}'"`;
84
+ } else {
85
+ // Direct shell: powershell.exe -NoExit -Command "& 'C:\path\nexora.cmd'"
86
+ targetExe = terminal.shellExe;
87
+ shortcutArgs = `-NoExit -Command "& '${nexoraAbsPath}'"`;
88
+ }
89
+
90
+ // ── 4. Write a temp .ps1 script — avoids all inline quoting issues ───────
91
+ // PowerShell here-string (@"..."@) lets us embed any characters safely.
92
+ const ps1Lines = [
93
+ `$ws = New-Object -ComObject WScript.Shell`,
94
+ `$sc = $ws.CreateShortcut(@"`,
95
+ shortcutPath,
96
+ `"@)`,
97
+ `$sc.TargetPath = @"`,
98
+ targetExe,
99
+ `"@`,
100
+ `$sc.Arguments = @"`,
101
+ shortcutArgs,
102
+ `"@`,
103
+ `$sc.WorkingDirectory = $env:USERPROFILE`,
104
+ `$sc.Description = @"`,
105
+ description,
106
+ `"@`,
107
+ ];
108
+
109
+ if (iconExists) {
110
+ ps1Lines.push(`$sc.IconLocation = @"`, iconPath, `"@`);
111
+ }
112
+
113
+ ps1Lines.push(`$sc.Save()`);
114
+
115
+ const ps1Content = ps1Lines.join('\r\n') + '\r\n';
116
+ const ps1Path = path.join(os.tmpdir(), `nexora-shortcut-${Date.now()}.ps1`);
69
117
 
70
118
  try {
119
+ fs.writeFileSync(ps1Path, ps1Content, 'utf-8');
120
+
71
121
  execSync(
72
- `powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -Command "${psLines}"`,
122
+ `powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "${ps1Path}"`,
73
123
  { stdio: 'pipe', timeout: 20_000 }
74
124
  );
75
- console.log(` ✓ Shortcut created: ${shortcutPath}`);
76
- console.log(` ✓ Opens with: ${terminal.label}`);
77
- if (iconExists) console.log(` ✓ Icon applied: Nexora Code logo`);
125
+
126
+ console.log(` ✓ Desktop shortcut : ${shortcutPath}`);
127
+ console.log(` ✓ Terminal : ${terminal.label}`);
128
+ console.log(` ✓ Launches : ${binName}`);
129
+ if (iconExists) console.log(` ✓ Icon applied : Nexora Code logo`);
78
130
  console.log('');
79
- console.log(' → Double-click "Nexora Code" on your Desktop to launch!');
131
+ console.log(` → Double-click "${displayName}" on your Desktop to launch!`);
80
132
  console.log('');
81
133
  } catch (err) {
82
134
  throw new Error(`Windows .lnk creation failed: ${err.message}`);
135
+ } finally {
136
+ // Always clean up the temp file
137
+ try { fs.unlinkSync(ps1Path); } catch { /* already gone */ }
83
138
  }
84
139
  }
85
140
 
86
- /**
87
- * Removes the Nexora Code desktop shortcut on Windows.
88
- */
141
+ // ── Shortcut removal ──────────────────────────────────────────────────────────
142
+
89
143
  function removeWindowsShortcut(ctx) {
90
- const shortcutPath = path.join(ctx.desktopPath, 'Nexora Code.lnk');
144
+ const { displayName } = getNexoraConfig();
145
+ const shortcutPath = path.join(ctx.desktopPath, `${displayName}.lnk`);
91
146
  try {
92
147
  fs.unlinkSync(shortcutPath);
93
- console.log(' ✓ Desktop shortcut removed: Nexora Code.lnk');
148
+ console.log(` ✓ Desktop shortcut removed: ${displayName}.lnk`);
94
149
  } catch {
95
150
  // Already removed or never existed — that's fine
96
151
  }