nexora-code 1.0.4 → 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 +174 -86
- package/package.json +1 -1
- package/scripts/desktop/config.cjs +36 -0
- package/scripts/desktop/linux.cjs +15 -8
- package/scripts/desktop/macos.cjs +23 -18
- package/scripts/desktop/shortcut.cjs +6 -4
- package/scripts/desktop/windows-wt-profile.cjs +34 -9
- package/scripts/desktop/windows.cjs +98 -65
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 =
|
|
7088
|
+
defaultIgnorableCodePointRegex = /^\p{Default_Ignorable_Code_Point}$/u;
|
|
7089
7089
|
}
|
|
7090
7090
|
});
|
|
7091
7091
|
|
|
@@ -284542,6 +284542,38 @@ 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
|
+
|
|
284545
284577
|
// scripts/desktop/windows-wt-profile.cjs
|
|
284546
284578
|
var require_windows_wt_profile = __commonJS({
|
|
284547
284579
|
"scripts/desktop/windows-wt-profile.cjs"(exports2, module2) {
|
|
@@ -284567,16 +284599,33 @@ var require_windows_wt_profile = __commonJS({
|
|
|
284567
284599
|
}
|
|
284568
284600
|
}) || null;
|
|
284569
284601
|
}
|
|
284570
|
-
|
|
284571
|
-
|
|
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) {
|
|
284572
284622
|
try {
|
|
284573
284623
|
execSync5("where pwsh.exe", { stdio: "pipe" });
|
|
284574
|
-
return { shellExe: "pwsh.exe"
|
|
284624
|
+
return { shellExe: "pwsh.exe" };
|
|
284575
284625
|
} catch {
|
|
284576
284626
|
}
|
|
284577
284627
|
return {
|
|
284578
|
-
shellExe: "powershell.exe"
|
|
284579
|
-
shellArgs: "-NoExit -Command nexora-code"
|
|
284628
|
+
shellExe: "powershell.exe"
|
|
284580
284629
|
};
|
|
284581
284630
|
}
|
|
284582
284631
|
async function repairWTProfile() {
|
|
@@ -284594,9 +284643,11 @@ var require_windows_wt_profile = __commonJS({
|
|
|
284594
284643
|
if (!Array.isArray(profiles)) return;
|
|
284595
284644
|
let modified = false;
|
|
284596
284645
|
for (const profile of profiles) {
|
|
284597
|
-
|
|
284598
|
-
|
|
284599
|
-
|
|
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, "''")}'"`;
|
|
284600
284651
|
modified = true;
|
|
284601
284652
|
console.log(" \u2713 Repaired corrupted Windows Terminal profile.");
|
|
284602
284653
|
console.log(` \u2713 Fixed commandline \u2192 ${profile.commandline}`);
|
|
@@ -284606,7 +284657,7 @@ var require_windows_wt_profile = __commonJS({
|
|
|
284606
284657
|
fs51.writeFileSync(settingsPath, JSON.stringify(settings, null, 4), "utf-8");
|
|
284607
284658
|
}
|
|
284608
284659
|
}
|
|
284609
|
-
module2.exports = { repairWTProfile };
|
|
284660
|
+
module2.exports = { repairWTProfile, resolveNexoraAbsolutePath };
|
|
284610
284661
|
}
|
|
284611
284662
|
});
|
|
284612
284663
|
|
|
@@ -284617,86 +284668,103 @@ var require_windows2 = __commonJS({
|
|
|
284617
284668
|
var { execSync: execSync5 } = require("child_process");
|
|
284618
284669
|
var path55 = require("path");
|
|
284619
284670
|
var fs51 = require("fs");
|
|
284620
|
-
var
|
|
284671
|
+
var os18 = require("os");
|
|
284672
|
+
var { repairWTProfile, resolveNexoraAbsolutePath } = require_windows_wt_profile();
|
|
284673
|
+
var { getNexoraConfig } = require_config();
|
|
284621
284674
|
function detectWindowsTerminal() {
|
|
284622
284675
|
try {
|
|
284623
|
-
const wtPath = execSync5("where wt.exe", { stdio: "pipe" }).toString().trim();
|
|
284676
|
+
const wtPath = execSync5("where wt.exe", { stdio: "pipe" }).toString().trim().split("\n")[0].trim();
|
|
284624
284677
|
if (wtPath) {
|
|
284625
284678
|
try {
|
|
284626
284679
|
execSync5("where pwsh.exe", { stdio: "pipe" });
|
|
284627
|
-
return {
|
|
284628
|
-
label: "Windows Terminal + PowerShell 7",
|
|
284629
|
-
shellExe: wtPath,
|
|
284630
|
-
shellArgs: "pwsh.exe -NoExit -Command nexora-code"
|
|
284631
|
-
};
|
|
284680
|
+
return { label: "Windows Terminal + PowerShell 7", shellExe: wtPath, innerShell: "pwsh.exe" };
|
|
284632
284681
|
} catch {
|
|
284633
|
-
return {
|
|
284634
|
-
label: "Windows Terminal + PowerShell 5",
|
|
284635
|
-
shellExe: wtPath,
|
|
284636
|
-
shellArgs: "powershell.exe -NoExit -Command nexora-code"
|
|
284637
|
-
};
|
|
284682
|
+
return { label: "Windows Terminal + PowerShell 5", shellExe: wtPath, innerShell: "powershell.exe" };
|
|
284638
284683
|
}
|
|
284639
284684
|
}
|
|
284640
284685
|
} catch {
|
|
284641
284686
|
}
|
|
284642
284687
|
try {
|
|
284643
|
-
const pwsh7 = execSync5("where pwsh.exe", { stdio: "pipe" }).toString().trim();
|
|
284644
|
-
if (pwsh7) return {
|
|
284645
|
-
label: "PowerShell 7",
|
|
284646
|
-
shellExe: pwsh7,
|
|
284647
|
-
shellArgs: "-NoExit -Command nexora-code"
|
|
284648
|
-
};
|
|
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 };
|
|
284649
284690
|
} catch {
|
|
284650
284691
|
}
|
|
284651
|
-
const ps5 =
|
|
284652
|
-
return {
|
|
284653
|
-
label: "PowerShell 5",
|
|
284654
|
-
shellExe: ps5,
|
|
284655
|
-
shellArgs: "-NoExit -Command nexora-code"
|
|
284656
|
-
};
|
|
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 };
|
|
284657
284694
|
}
|
|
284658
284695
|
async function createWindowsShortcut(ctx) {
|
|
284659
284696
|
await repairWTProfile();
|
|
284660
|
-
const
|
|
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`);
|
|
284661
284707
|
const iconPath = path55.join(ctx.iconDir, "icon.ico");
|
|
284662
284708
|
const iconExists = fs51.existsSync(iconPath);
|
|
284663
284709
|
const terminal2 = detectWindowsTerminal();
|
|
284664
|
-
|
|
284665
|
-
|
|
284666
|
-
|
|
284667
|
-
|
|
284668
|
-
|
|
284669
|
-
|
|
284670
|
-
|
|
284671
|
-
|
|
284672
|
-
|
|
284673
|
-
`$
|
|
284674
|
-
`$
|
|
284675
|
-
|
|
284676
|
-
|
|
284677
|
-
|
|
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`);
|
|
284678
284740
|
try {
|
|
284741
|
+
fs51.writeFileSync(ps1Path, ps1Content, "utf-8");
|
|
284679
284742
|
execSync5(
|
|
284680
|
-
`powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -
|
|
284743
|
+
`powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "${ps1Path}"`,
|
|
284681
284744
|
{ stdio: "pipe", timeout: 2e4 }
|
|
284682
284745
|
);
|
|
284683
|
-
console.log(` \u2713
|
|
284684
|
-
console.log(` \u2713
|
|
284685
|
-
console.log(` \u2713
|
|
284686
|
-
console.log(` \u2713
|
|
284687
|
-
if (iconExists) console.log(` \u2713 Icon applied: Nexora Code logo`);
|
|
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`);
|
|
284688
284750
|
console.log("");
|
|
284689
|
-
console.log(
|
|
284751
|
+
console.log(` \u2192 Double-click "${displayName}" on your Desktop to launch!`);
|
|
284690
284752
|
console.log("");
|
|
284691
284753
|
} catch (err6) {
|
|
284692
284754
|
throw new Error(`Windows .lnk creation failed: ${err6.message}`);
|
|
284755
|
+
} finally {
|
|
284756
|
+
try {
|
|
284757
|
+
fs51.unlinkSync(ps1Path);
|
|
284758
|
+
} catch {
|
|
284759
|
+
}
|
|
284693
284760
|
}
|
|
284694
284761
|
}
|
|
284695
284762
|
function removeWindowsShortcut(ctx) {
|
|
284696
|
-
const
|
|
284763
|
+
const { displayName } = getNexoraConfig();
|
|
284764
|
+
const shortcutPath = path55.join(ctx.desktopPath, `${displayName}.lnk`);
|
|
284697
284765
|
try {
|
|
284698
284766
|
fs51.unlinkSync(shortcutPath);
|
|
284699
|
-
console.log(
|
|
284767
|
+
console.log(` \u2713 Desktop shortcut removed: ${displayName}.lnk`);
|
|
284700
284768
|
} catch {
|
|
284701
284769
|
}
|
|
284702
284770
|
}
|
|
@@ -284711,11 +284779,11 @@ var require_macos = __commonJS({
|
|
|
284711
284779
|
var { execSync: execSync5 } = require("child_process");
|
|
284712
284780
|
var path55 = require("path");
|
|
284713
284781
|
var fs51 = require("fs");
|
|
284714
|
-
var
|
|
284715
|
-
function
|
|
284782
|
+
var { getNexoraConfig } = require_config();
|
|
284783
|
+
function buildMacTerminalScript(binName) {
|
|
284716
284784
|
if (fs51.existsSync("/Applications/iTerm.app")) {
|
|
284717
284785
|
return `#!/bin/bash
|
|
284718
|
-
open -a iTerm -- bash -c "
|
|
284786
|
+
open -a iTerm -- bash -c "${binName}; exec bash"
|
|
284719
284787
|
`;
|
|
284720
284788
|
}
|
|
284721
284789
|
if (fs51.existsSync("/Applications/Warp.app")) {
|
|
@@ -284733,12 +284801,12 @@ open -a Hyper
|
|
|
284733
284801
|
osascript <<'APPLESCRIPT'
|
|
284734
284802
|
tell application "Terminal"
|
|
284735
284803
|
activate
|
|
284736
|
-
do script "
|
|
284804
|
+
do script "${binName}"
|
|
284737
284805
|
end tell
|
|
284738
284806
|
APPLESCRIPT
|
|
284739
284807
|
`;
|
|
284740
284808
|
}
|
|
284741
|
-
function buildPlist(hasIcon) {
|
|
284809
|
+
function buildPlist(hasIcon, displayName) {
|
|
284742
284810
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
284743
284811
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
|
284744
284812
|
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -284749,9 +284817,9 @@ APPLESCRIPT
|
|
|
284749
284817
|
<key>CFBundleIdentifier</key>
|
|
284750
284818
|
<string>cloud.getnexora.code</string>
|
|
284751
284819
|
<key>CFBundleName</key>
|
|
284752
|
-
<string>${
|
|
284820
|
+
<string>${displayName}</string>
|
|
284753
284821
|
<key>CFBundleDisplayName</key>
|
|
284754
|
-
<string>${
|
|
284822
|
+
<string>${displayName}</string>
|
|
284755
284823
|
<key>CFBundleVersion</key>
|
|
284756
284824
|
<string>1.0.0</string>
|
|
284757
284825
|
<key>CFBundleShortVersionString</key>
|
|
@@ -284770,20 +284838,21 @@ APPLESCRIPT
|
|
|
284770
284838
|
`;
|
|
284771
284839
|
}
|
|
284772
284840
|
function createMacosShortcut(ctx) {
|
|
284773
|
-
const
|
|
284841
|
+
const { binName, displayName } = getNexoraConfig();
|
|
284842
|
+
const appBundlePath = path55.join(ctx.desktopPath, `${displayName}.app`);
|
|
284774
284843
|
const macOSDir = path55.join(appBundlePath, "Contents", "MacOS");
|
|
284775
284844
|
const resourceDir = path55.join(appBundlePath, "Contents", "Resources");
|
|
284776
284845
|
const icnsPath = path55.join(ctx.iconDir, "icon.icns");
|
|
284777
284846
|
const hasIcon = fs51.existsSync(icnsPath);
|
|
284778
284847
|
fs51.mkdirSync(macOSDir, { recursive: true });
|
|
284779
284848
|
fs51.mkdirSync(resourceDir, { recursive: true });
|
|
284780
|
-
const launcherContent =
|
|
284849
|
+
const launcherContent = buildMacTerminalScript(binName);
|
|
284781
284850
|
const launcherPath = path55.join(macOSDir, "nexora-launcher");
|
|
284782
284851
|
fs51.writeFileSync(launcherPath, launcherContent, "utf-8");
|
|
284783
284852
|
fs51.chmodSync(launcherPath, 493);
|
|
284784
284853
|
fs51.writeFileSync(
|
|
284785
284854
|
path55.join(appBundlePath, "Contents", "Info.plist"),
|
|
284786
|
-
buildPlist(hasIcon),
|
|
284855
|
+
buildPlist(hasIcon, displayName),
|
|
284787
284856
|
"utf-8"
|
|
284788
284857
|
);
|
|
284789
284858
|
if (hasIcon) {
|
|
@@ -284798,16 +284867,16 @@ APPLESCRIPT
|
|
|
284798
284867
|
} catch {
|
|
284799
284868
|
}
|
|
284800
284869
|
console.log(` \u2713 App bundle created: ${appBundlePath}`);
|
|
284801
|
-
createCommandFallback(ctx.desktopPath);
|
|
284870
|
+
createCommandFallback(ctx.desktopPath, displayName, binName);
|
|
284802
284871
|
console.log("");
|
|
284803
|
-
console.log(` \u2192 Double-click "${
|
|
284872
|
+
console.log(` \u2192 Double-click "${displayName}" on your Desktop to launch Nexora!`);
|
|
284804
284873
|
console.log("");
|
|
284805
284874
|
}
|
|
284806
|
-
function createCommandFallback(desktopPath) {
|
|
284807
|
-
const commandPath = path55.join(desktopPath, `${
|
|
284875
|
+
function createCommandFallback(desktopPath, displayName, binName) {
|
|
284876
|
+
const commandPath = path55.join(desktopPath, `${displayName} (Terminal).command`);
|
|
284808
284877
|
const commandContent = `#!/bin/bash
|
|
284809
284878
|
clear
|
|
284810
|
-
|
|
284879
|
+
${binName}
|
|
284811
284880
|
exec $SHELL
|
|
284812
284881
|
`;
|
|
284813
284882
|
fs51.writeFileSync(commandPath, commandContent, "utf-8");
|
|
@@ -284815,9 +284884,13 @@ exec $SHELL
|
|
|
284815
284884
|
console.log(` \u2713 .command fallback: ${commandPath}`);
|
|
284816
284885
|
}
|
|
284817
284886
|
function removeMacosShortcut(ctx) {
|
|
284887
|
+
const { binName, displayName } = getNexoraConfig();
|
|
284818
284888
|
const targets = [
|
|
284819
|
-
path55.join(ctx.desktopPath, `${
|
|
284820
|
-
path55.join(ctx.desktopPath, `${
|
|
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")
|
|
284821
284894
|
];
|
|
284822
284895
|
for (const t of targets) {
|
|
284823
284896
|
try {
|
|
@@ -284838,6 +284911,7 @@ var require_linux = __commonJS({
|
|
|
284838
284911
|
var { execSync: execSync5 } = require("child_process");
|
|
284839
284912
|
var path55 = require("path");
|
|
284840
284913
|
var fs51 = require("fs");
|
|
284914
|
+
var { getNexoraConfig } = require_config();
|
|
284841
284915
|
var TERMINAL_CANDIDATES = [
|
|
284842
284916
|
{ bin: "gnome-terminal", args: '-- bash -c "nexora-code; exec bash"' },
|
|
284843
284917
|
{ bin: "konsole", args: '-e bash -c "nexora-code; exec bash"' },
|
|
@@ -284861,26 +284935,27 @@ var require_linux = __commonJS({
|
|
|
284861
284935
|
return null;
|
|
284862
284936
|
}
|
|
284863
284937
|
function createLinuxShortcut(ctx) {
|
|
284938
|
+
const { binName, displayName, description } = getNexoraConfig();
|
|
284864
284939
|
const terminal2 = detectLinuxTerminal();
|
|
284865
284940
|
const iconPath = path55.join(ctx.iconDir, "icon.png");
|
|
284866
284941
|
const iconExists = fs51.existsSync(iconPath);
|
|
284867
|
-
const execLine = terminal2 ? `${terminal2.bin} ${terminal2.args}` :
|
|
284942
|
+
const execLine = terminal2 ? `${terminal2.bin} ${terminal2.args.replace(/nexora-code/g, binName)}` : binName;
|
|
284868
284943
|
const iconLine = iconExists ? iconPath : "utilities-terminal";
|
|
284869
284944
|
const desktopContent = [
|
|
284870
284945
|
"[Desktop Entry]",
|
|
284871
284946
|
"Version=1.0",
|
|
284872
284947
|
"Type=Application",
|
|
284873
|
-
|
|
284948
|
+
`Name=${displayName}`,
|
|
284874
284949
|
"GenericName=AI Developer Workspace",
|
|
284875
|
-
|
|
284950
|
+
`Comment=${description}`,
|
|
284876
284951
|
`Exec=${execLine}`,
|
|
284877
284952
|
`Icon=${iconLine}`,
|
|
284878
284953
|
"Terminal=false",
|
|
284879
284954
|
// false: the terminal emulator handles this
|
|
284880
284955
|
"StartupNotify=true",
|
|
284881
284956
|
"Categories=Development;IDE;",
|
|
284882
|
-
|
|
284883
|
-
|
|
284957
|
+
`Keywords=${binName};code;ai;developer;assistant;cli;`,
|
|
284958
|
+
`StartupWMClass=${binName}`
|
|
284884
284959
|
].join("\n") + "\n";
|
|
284885
284960
|
const desktopFilePath = path55.join(ctx.desktopPath, "nexora-code.desktop");
|
|
284886
284961
|
fs51.writeFileSync(desktopFilePath, desktopContent, "utf-8");
|
|
@@ -284906,16 +284981,20 @@ var require_linux = __commonJS({
|
|
|
284906
284981
|
console.log(" \u26A0 No terminal emulator detected \u2014 using system default.");
|
|
284907
284982
|
}
|
|
284908
284983
|
console.log("");
|
|
284909
|
-
console.log(
|
|
284984
|
+
console.log(` \u2192 Double-click the icon on your Desktop to launch ${displayName}!`);
|
|
284910
284985
|
if (!terminal2) {
|
|
284911
|
-
console.log(
|
|
284986
|
+
console.log(` \u2192 Or run "${binName}" directly in your terminal.`);
|
|
284912
284987
|
}
|
|
284913
284988
|
console.log("");
|
|
284914
284989
|
}
|
|
284915
284990
|
function removeLinuxShortcut(ctx) {
|
|
284991
|
+
const { binName } = getNexoraConfig();
|
|
284916
284992
|
const targets = [
|
|
284917
284993
|
path55.join(ctx.desktopPath, "nexora-code.desktop"),
|
|
284918
|
-
path55.join(ctx.realHomeDir, ".local", "share", "applications", "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`)
|
|
284919
284998
|
];
|
|
284920
284999
|
for (const t of targets) {
|
|
284921
285000
|
try {
|
|
@@ -284999,7 +285078,8 @@ var require_shortcut = __commonJS({
|
|
|
284999
285078
|
const desktopPath = findDesktopPath(realHomeDir, platform2);
|
|
285000
285079
|
const packageDir = getPackageDir();
|
|
285001
285080
|
const iconDir = path55.join(packageDir, "assets");
|
|
285002
|
-
const
|
|
285081
|
+
const { binName } = require_config().getNexoraConfig();
|
|
285082
|
+
const binaryName = platform2 === "windows" ? `${binName}.cmd` : binName;
|
|
285003
285083
|
const npmBinDir = path55.dirname(process.execPath);
|
|
285004
285084
|
const binaryPath = path55.join(npmBinDir, binaryName);
|
|
285005
285085
|
return { platform: platform2, realHomeDir, desktopPath, packageDir, binaryPath, iconDir };
|
|
@@ -285007,8 +285087,9 @@ var require_shortcut = __commonJS({
|
|
|
285007
285087
|
async function createShortcut() {
|
|
285008
285088
|
const ctx = buildUserContext();
|
|
285009
285089
|
if (!ctx.desktopPath) {
|
|
285090
|
+
const { binName } = require_config().getNexoraConfig();
|
|
285010
285091
|
console.log(" \u2139 No desktop found (headless / server / WSL environment).");
|
|
285011
|
-
console.log(
|
|
285092
|
+
console.log(` Run "${binName}" in any terminal to start.`);
|
|
285012
285093
|
return;
|
|
285013
285094
|
}
|
|
285014
285095
|
console.log("");
|
|
@@ -318982,7 +319063,7 @@ function updateNotifier(options) {
|
|
|
318982
319063
|
// package.json
|
|
318983
319064
|
var package_default = {
|
|
318984
319065
|
name: "nexora-code",
|
|
318985
|
-
version: "1.0.
|
|
319066
|
+
version: "1.0.5",
|
|
318986
319067
|
description: "Nexora Code \u2014 World-Class AI Coding Agent CLI. BYOK \xB7 51 tools \xB7 Multi-action \xB7 Streaming \xB7 Session Memory",
|
|
318987
319068
|
author: "Enoch Boadu",
|
|
318988
319069
|
license: "MIT",
|
|
@@ -333344,6 +333425,13 @@ function loadProjectMemory() {
|
|
|
333344
333425
|
// src/index.ts
|
|
333345
333426
|
init_headless();
|
|
333346
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
|
+
});
|
|
333347
333435
|
var VERSION2 = package_default.version || "0.0.0";
|
|
333348
333436
|
import_node_process51.default.on("SIGINT", () => {
|
|
333349
333437
|
console.log(`
|
package/package.json
CHANGED
|
@@ -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
|
-
:
|
|
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
|
-
|
|
59
|
+
`Name=${displayName}`,
|
|
57
60
|
'GenericName=AI Developer Workspace',
|
|
58
|
-
|
|
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
|
-
|
|
65
|
-
|
|
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(
|
|
101
|
+
console.log(` → Double-click the icon on your Desktop to launch ${displayName}!`);
|
|
99
102
|
if (!terminal) {
|
|
100
|
-
console.log(
|
|
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
|
|
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
|
|
17
|
+
function buildMacTerminalScript(binName) {
|
|
18
18
|
if (fs.existsSync('/Applications/iTerm.app')) {
|
|
19
19
|
return `#!/bin/bash
|
|
20
|
-
open -a iTerm -- bash -c "
|
|
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 "
|
|
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>${
|
|
64
|
+
<string>${displayName}</string>
|
|
65
65
|
<key>CFBundleDisplayName</key>
|
|
66
|
-
<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
|
|
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 =
|
|
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 "${
|
|
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, `${
|
|
146
|
-
const commandContent = `#!/bin/bash\nclear\
|
|
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, `${
|
|
158
|
-
path.join(ctx.desktopPath, `${
|
|
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) {
|
|
@@ -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
|
|
91
|
-
const
|
|
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
|
|
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
|
|
|
@@ -105,8 +106,9 @@ 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(
|
|
111
|
+
console.log(` Run "${binName}" in any terminal to start.`);
|
|
110
112
|
return;
|
|
111
113
|
}
|
|
112
114
|
|
|
@@ -18,17 +18,39 @@ function getWTSettingsPath() {
|
|
|
18
18
|
}) || null;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
const { execSync } = require('child_process');
|
|
22
|
+
const { getNexoraConfig } = require('./config.cjs');
|
|
23
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) {
|
|
24
47
|
try {
|
|
25
48
|
execSync('where pwsh.exe', { stdio: 'pipe' });
|
|
26
|
-
return { shellExe: 'pwsh.exe'
|
|
49
|
+
return { shellExe: 'pwsh.exe' };
|
|
27
50
|
} catch { /* not found */ }
|
|
28
51
|
|
|
29
52
|
return {
|
|
30
53
|
shellExe: 'powershell.exe',
|
|
31
|
-
shellArgs: '-NoExit -Command nexora-code',
|
|
32
54
|
};
|
|
33
55
|
}
|
|
34
56
|
|
|
@@ -52,13 +74,16 @@ async function repairWTProfile() {
|
|
|
52
74
|
let modified = false;
|
|
53
75
|
|
|
54
76
|
for (const profile of profiles) {
|
|
55
|
-
|
|
77
|
+
const { binName } = getNexoraConfig();
|
|
78
|
+
// Find any profile where commandline is set to bare "nexora-code" or old binName
|
|
56
79
|
if (
|
|
57
80
|
profile.name === 'Nexora Code' &&
|
|
58
|
-
profile.commandline === 'nexora-code'
|
|
81
|
+
(profile.commandline === 'nexora-code' || profile.commandline === binName)
|
|
59
82
|
) {
|
|
60
|
-
const { shellExe
|
|
61
|
-
|
|
83
|
+
const { shellExe } = detectBestShell(binName);
|
|
84
|
+
const nexoraAbs = await resolveNexoraAbsolutePath(binName);
|
|
85
|
+
|
|
86
|
+
profile.commandline = `${shellExe} -NoExit -Command "& '${nexoraAbs.replace(/\\/g, '\\\\').replace(/'/g, "''")}'"`;
|
|
62
87
|
modified = true;
|
|
63
88
|
|
|
64
89
|
console.log(' ✓ Repaired corrupted Windows Terminal profile.');
|
|
@@ -72,4 +97,4 @@ async function repairWTProfile() {
|
|
|
72
97
|
}
|
|
73
98
|
}
|
|
74
99
|
|
|
75
|
-
module.exports = { repairWTProfile };
|
|
100
|
+
module.exports = { repairWTProfile, resolveNexoraAbsolutePath };
|
|
@@ -4,115 +4,148 @@
|
|
|
4
4
|
// ║ Creates a .lnk file via PowerShell COM (WScript.Shell) — zero deps ║
|
|
5
5
|
// ╚══════════════════════════════════════════════════════════════════════════════╝
|
|
6
6
|
|
|
7
|
-
const { execSync }
|
|
8
|
-
const path
|
|
9
|
-
const fs
|
|
7
|
+
const { execSync } = require('child_process');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const os = require('os');
|
|
10
11
|
|
|
11
|
-
const { repairWTProfile } = require('./windows-wt-profile.cjs');
|
|
12
|
+
const { repairWTProfile, resolveNexoraAbsolutePath } = require('./windows-wt-profile.cjs');
|
|
13
|
+
const { getNexoraConfig } = require('./config.cjs');
|
|
14
|
+
|
|
15
|
+
// ── Terminal detection ────────────────────────────────────────────────────────
|
|
12
16
|
|
|
13
17
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
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.
|
|
16
21
|
*/
|
|
17
22
|
function detectWindowsTerminal() {
|
|
18
23
|
// Windows Terminal (wt.exe) — best experience
|
|
19
24
|
try {
|
|
20
|
-
const wtPath = execSync('where wt.exe', { stdio: 'pipe' }).toString().trim();
|
|
25
|
+
const wtPath = execSync('where wt.exe', { stdio: 'pipe' }).toString().trim().split('\n')[0].trim();
|
|
21
26
|
if (wtPath) {
|
|
22
27
|
try {
|
|
23
28
|
execSync('where pwsh.exe', { stdio: 'pipe' });
|
|
24
|
-
return {
|
|
25
|
-
label: 'Windows Terminal + PowerShell 7',
|
|
26
|
-
shellExe: wtPath,
|
|
27
|
-
shellArgs: 'pwsh.exe -NoExit -Command nexora-code',
|
|
28
|
-
};
|
|
29
|
+
return { label: 'Windows Terminal + PowerShell 7', shellExe: wtPath, innerShell: 'pwsh.exe' };
|
|
29
30
|
} catch {
|
|
30
|
-
return {
|
|
31
|
-
label: 'Windows Terminal + PowerShell 5',
|
|
32
|
-
shellExe: wtPath,
|
|
33
|
-
shellArgs: 'powershell.exe -NoExit -Command nexora-code',
|
|
34
|
-
};
|
|
31
|
+
return { label: 'Windows Terminal + PowerShell 5', shellExe: wtPath, innerShell: 'powershell.exe' };
|
|
35
32
|
}
|
|
36
33
|
}
|
|
37
34
|
} catch { /* wt not found */ }
|
|
38
35
|
|
|
39
|
-
// PowerShell 7+
|
|
36
|
+
// PowerShell 7+
|
|
40
37
|
try {
|
|
41
|
-
const pwsh7 = execSync('where pwsh.exe', { stdio: 'pipe' }).toString().trim();
|
|
42
|
-
if (pwsh7) return {
|
|
43
|
-
label: 'PowerShell 7',
|
|
44
|
-
shellExe: pwsh7,
|
|
45
|
-
shellArgs: '-NoExit -Command nexora-code',
|
|
46
|
-
};
|
|
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 };
|
|
47
40
|
} catch { /* not installed */ }
|
|
48
41
|
|
|
49
|
-
// PowerShell 5
|
|
50
|
-
const ps5 =
|
|
51
|
-
return {
|
|
52
|
-
label: 'PowerShell 5',
|
|
53
|
-
shellExe: ps5,
|
|
54
|
-
shellArgs: '-NoExit -Command nexora-code',
|
|
55
|
-
};
|
|
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 };
|
|
56
45
|
}
|
|
57
46
|
|
|
47
|
+
// ── Main shortcut creator ─────────────────────────────────────────────────────
|
|
48
|
+
|
|
58
49
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
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.
|
|
61
52
|
*/
|
|
62
53
|
async function createWindowsShortcut(ctx) {
|
|
63
|
-
// Repair any bad WT profile from a previous install attempt first
|
|
64
54
|
await repairWTProfile();
|
|
65
55
|
|
|
66
|
-
const
|
|
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`);
|
|
67
70
|
const iconPath = path.join(ctx.iconDir, 'icon.ico');
|
|
68
71
|
const iconExists = fs.existsSync(iconPath);
|
|
69
72
|
const terminal = detectWindowsTerminal();
|
|
70
73
|
|
|
71
|
-
//
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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`);
|
|
89
117
|
|
|
90
118
|
try {
|
|
119
|
+
fs.writeFileSync(ps1Path, ps1Content, 'utf-8');
|
|
120
|
+
|
|
91
121
|
execSync(
|
|
92
|
-
`powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -
|
|
122
|
+
`powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "${ps1Path}"`,
|
|
93
123
|
{ stdio: 'pipe', timeout: 20_000 }
|
|
94
124
|
);
|
|
95
|
-
|
|
96
|
-
console.log(` ✓
|
|
97
|
-
console.log(` ✓
|
|
98
|
-
console.log(` ✓
|
|
99
|
-
if (iconExists) console.log(` ✓ Icon applied:
|
|
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`);
|
|
100
130
|
console.log('');
|
|
101
|
-
console.log(
|
|
131
|
+
console.log(` → Double-click "${displayName}" on your Desktop to launch!`);
|
|
102
132
|
console.log('');
|
|
103
133
|
} catch (err) {
|
|
104
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 */ }
|
|
105
138
|
}
|
|
106
139
|
}
|
|
107
140
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
*/
|
|
141
|
+
// ── Shortcut removal ──────────────────────────────────────────────────────────
|
|
142
|
+
|
|
111
143
|
function removeWindowsShortcut(ctx) {
|
|
112
|
-
const
|
|
144
|
+
const { displayName } = getNexoraConfig();
|
|
145
|
+
const shortcutPath = path.join(ctx.desktopPath, `${displayName}.lnk`);
|
|
113
146
|
try {
|
|
114
147
|
fs.unlinkSync(shortcutPath);
|
|
115
|
-
console.log(
|
|
148
|
+
console.log(` ✓ Desktop shortcut removed: ${displayName}.lnk`);
|
|
116
149
|
} catch {
|
|
117
150
|
// Already removed or never existed — that's fine
|
|
118
151
|
}
|