lacy 1.7.1 → 1.7.3
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/index.mjs +62 -47
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -12,13 +12,38 @@ import {
|
|
|
12
12
|
rmSync,
|
|
13
13
|
} from "fs";
|
|
14
14
|
import { homedir } from "os";
|
|
15
|
-
import { join } from "path";
|
|
15
|
+
import { join, dirname } from "path";
|
|
16
|
+
import { fileURLToPath } from "url";
|
|
16
17
|
|
|
17
18
|
const INSTALL_DIR = join(homedir(), ".lacy");
|
|
18
19
|
const INSTALL_DIR_OLD = join(homedir(), ".lacy-shell");
|
|
19
20
|
const CONFIG_FILE = join(INSTALL_DIR, "config.yaml");
|
|
20
21
|
const REPO_URL = "https://github.com/lacymorrow/lacy.git";
|
|
21
22
|
|
|
23
|
+
// Version — read from installed package.json (single source of truth),
|
|
24
|
+
// fall back to this npm package's own package.json
|
|
25
|
+
function getVersion() {
|
|
26
|
+
// Try the installed copy first
|
|
27
|
+
for (const dir of [INSTALL_DIR, INSTALL_DIR_OLD]) {
|
|
28
|
+
const pkgPath = join(dir, "package.json");
|
|
29
|
+
if (existsSync(pkgPath)) {
|
|
30
|
+
try {
|
|
31
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
32
|
+
if (pkg.version) return pkg.version;
|
|
33
|
+
} catch {}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// Fall back to this package's own version
|
|
37
|
+
try {
|
|
38
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
39
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, "package.json"), "utf-8"));
|
|
40
|
+
if (pkg.version) return pkg.version;
|
|
41
|
+
} catch {}
|
|
42
|
+
return "unknown";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const VERSION = getVersion();
|
|
46
|
+
|
|
22
47
|
// ============================================================================
|
|
23
48
|
// Terminal state safety net
|
|
24
49
|
// ============================================================================
|
|
@@ -220,7 +245,7 @@ function removeLacyFromFile(filePath) {
|
|
|
220
245
|
return true;
|
|
221
246
|
}
|
|
222
247
|
|
|
223
|
-
// Shared uninstall logic — removes RC lines and install dirs
|
|
248
|
+
// Shared uninstall logic — removes RC lines and install dirs completely
|
|
224
249
|
async function doUninstall({ askConfirm = true } = {}) {
|
|
225
250
|
if (askConfirm) {
|
|
226
251
|
const confirm = await p.confirm({
|
|
@@ -234,24 +259,6 @@ async function doUninstall({ askConfirm = true } = {}) {
|
|
|
234
259
|
}
|
|
235
260
|
}
|
|
236
261
|
|
|
237
|
-
// Ask about config
|
|
238
|
-
let keepConfig = false;
|
|
239
|
-
if (existsSync(CONFIG_FILE)) {
|
|
240
|
-
const configChoice = await p.confirm({
|
|
241
|
-
message: "Keep configuration for future reinstall?",
|
|
242
|
-
initialValue: true,
|
|
243
|
-
});
|
|
244
|
-
if (!p.isCancel(configChoice)) {
|
|
245
|
-
keepConfig = configChoice;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// Backup config if keeping
|
|
250
|
-
let configBackup = null;
|
|
251
|
-
if (keepConfig && existsSync(CONFIG_FILE)) {
|
|
252
|
-
configBackup = readFileSync(CONFIG_FILE, "utf-8");
|
|
253
|
-
}
|
|
254
|
-
|
|
255
262
|
// Remove from all possible RC files
|
|
256
263
|
const rcSpinner = p.spinner();
|
|
257
264
|
rcSpinner.start("Removing from shell configs");
|
|
@@ -280,15 +287,7 @@ async function doUninstall({ askConfirm = true } = {}) {
|
|
|
280
287
|
rmSync(INSTALL_DIR_OLD, { recursive: true, force: true });
|
|
281
288
|
}
|
|
282
289
|
|
|
283
|
-
|
|
284
|
-
if (configBackup) {
|
|
285
|
-
mkdirSync(INSTALL_DIR, { recursive: true });
|
|
286
|
-
writeFileSync(CONFIG_FILE, configBackup);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
removeSpinner.stop(
|
|
290
|
-
configBackup ? "Installation removed (config preserved)" : "Installation removed",
|
|
291
|
-
);
|
|
290
|
+
removeSpinner.stop("Installation removed");
|
|
292
291
|
|
|
293
292
|
p.log.success("Lacy Shell uninstalled");
|
|
294
293
|
|
|
@@ -299,7 +298,7 @@ async function doUninstall({ askConfirm = true } = {}) {
|
|
|
299
298
|
|
|
300
299
|
async function uninstall() {
|
|
301
300
|
console.clear();
|
|
302
|
-
p.intro(pc.magenta(pc.bold(` Lacy Shell `)));
|
|
301
|
+
p.intro(pc.magenta(pc.bold(` Lacy Shell `)) + pc.dim(` v${VERSION}`));
|
|
303
302
|
|
|
304
303
|
if (!isInstalled()) {
|
|
305
304
|
p.log.warn("Lacy Shell is not installed");
|
|
@@ -318,7 +317,7 @@ async function uninstall() {
|
|
|
318
317
|
|
|
319
318
|
async function install() {
|
|
320
319
|
console.clear();
|
|
321
|
-
p.intro(pc.magenta(pc.bold(` Lacy Shell `)));
|
|
320
|
+
p.intro(pc.magenta(pc.bold(` Lacy Shell `)) + pc.dim(` v${VERSION}`));
|
|
322
321
|
|
|
323
322
|
// Detect shell
|
|
324
323
|
const shell = detectShell();
|
|
@@ -396,7 +395,7 @@ async function install() {
|
|
|
396
395
|
|
|
397
396
|
try {
|
|
398
397
|
if (commandExists("npm")) {
|
|
399
|
-
execSync("npm install -g
|
|
398
|
+
execSync("npm install -g lashcode", { stdio: "pipe" });
|
|
400
399
|
lashSpinner.stop("lash installed");
|
|
401
400
|
detected.push("lash");
|
|
402
401
|
} else if (commandExists("brew")) {
|
|
@@ -408,13 +407,13 @@ async function install() {
|
|
|
408
407
|
} else {
|
|
409
408
|
lashSpinner.stop("Could not install lash");
|
|
410
409
|
p.log.warn(
|
|
411
|
-
"Please install npm or homebrew, then run: npm install -g
|
|
410
|
+
"Please install npm or homebrew, then run: npm install -g lashcode",
|
|
412
411
|
);
|
|
413
412
|
}
|
|
414
413
|
} catch (e) {
|
|
415
414
|
lashSpinner.stop("lash installation failed");
|
|
416
415
|
p.log.warn(
|
|
417
|
-
"You can install it manually later: npm install -g
|
|
416
|
+
"You can install it manually later: npm install -g lashcode",
|
|
418
417
|
);
|
|
419
418
|
}
|
|
420
419
|
}
|
|
@@ -457,10 +456,22 @@ async function install() {
|
|
|
457
456
|
p.log.info(`Custom command: ${pc.cyan(customCommand)}`);
|
|
458
457
|
}
|
|
459
458
|
|
|
460
|
-
//
|
|
461
|
-
if (selectedTool === "
|
|
459
|
+
// Show which tool auto-detect resolves to
|
|
460
|
+
if (selectedTool === "auto" && detected.length > 0) {
|
|
461
|
+
p.log.info(`Using: ${pc.green("auto-detect")} (currently: ${pc.green(detected[0])})`);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// Offer to install lash if selected but not installed,
|
|
465
|
+
// or if auto-detect was chosen but no tools are available
|
|
466
|
+
const needsLashInstall =
|
|
467
|
+
(selectedTool === "lash" && !commandExists("lash")) ||
|
|
468
|
+
(selectedTool === "auto" && detected.length === 0);
|
|
469
|
+
|
|
470
|
+
if (needsLashInstall) {
|
|
462
471
|
const installLash = await p.confirm({
|
|
463
|
-
message:
|
|
472
|
+
message: selectedTool === "auto"
|
|
473
|
+
? `No AI CLI tools are installed. Would you like to install ${pc.green("lash")} (recommended)?`
|
|
474
|
+
: "lash is not installed. Would you like to install it now?",
|
|
464
475
|
initialValue: true,
|
|
465
476
|
});
|
|
466
477
|
|
|
@@ -475,7 +486,7 @@ async function install() {
|
|
|
475
486
|
|
|
476
487
|
try {
|
|
477
488
|
if (commandExists("npm")) {
|
|
478
|
-
execSync("npm install -g
|
|
489
|
+
execSync("npm install -g lashcode", { stdio: "pipe" });
|
|
479
490
|
lashSpinner.stop("lash installed");
|
|
480
491
|
} else if (commandExists("brew")) {
|
|
481
492
|
execSync("brew tap lacymorrow/tap && brew install lash", {
|
|
@@ -485,13 +496,13 @@ async function install() {
|
|
|
485
496
|
} else {
|
|
486
497
|
lashSpinner.stop("Could not install lash");
|
|
487
498
|
p.log.warn(
|
|
488
|
-
"Please install npm or homebrew, then run: npm install -g
|
|
499
|
+
"Please install npm or homebrew, then run: npm install -g lashcode",
|
|
489
500
|
);
|
|
490
501
|
}
|
|
491
502
|
} catch (e) {
|
|
492
503
|
lashSpinner.stop("lash installation failed");
|
|
493
504
|
p.log.warn(
|
|
494
|
-
"You can install it manually later: npm install -g
|
|
505
|
+
"You can install it manually later: npm install -g lashcode",
|
|
495
506
|
);
|
|
496
507
|
}
|
|
497
508
|
}
|
|
@@ -616,8 +627,11 @@ auto_detection:
|
|
|
616
627
|
configSpinner.stop("Configuration created");
|
|
617
628
|
}
|
|
618
629
|
|
|
630
|
+
// Re-read version after install (repo was just cloned/updated)
|
|
631
|
+
const installedVersion = getVersion();
|
|
632
|
+
|
|
619
633
|
// Success message
|
|
620
|
-
p.log.success(pc.green(
|
|
634
|
+
p.log.success(pc.green(`Installation complete!`) + pc.dim(` v${installedVersion}`));
|
|
621
635
|
|
|
622
636
|
p.note(
|
|
623
637
|
`${pc.cyan("what files are here")} ${pc.dim("→ AI answers")}
|
|
@@ -636,7 +650,7 @@ Commands:
|
|
|
636
650
|
(selectedTool === "auto" && detected.length === 0)
|
|
637
651
|
) {
|
|
638
652
|
p.log.warn("Remember to install an AI CLI tool:");
|
|
639
|
-
console.log(` ${pc.cyan("npm install -g
|
|
653
|
+
console.log(` ${pc.cyan("npm install -g lashcode")}`);
|
|
640
654
|
}
|
|
641
655
|
|
|
642
656
|
await restartShell();
|
|
@@ -658,7 +672,7 @@ async function main() {
|
|
|
658
672
|
const content = readFileSync(infoPath, "utf-8");
|
|
659
673
|
console.log(content);
|
|
660
674
|
} else {
|
|
661
|
-
console.log(`\n${pc.magenta(pc.bold("🔧 Lacy Shell"))} v${
|
|
675
|
+
console.log(`\n${pc.magenta(pc.bold("🔧 Lacy Shell"))} v${VERSION}\n`);
|
|
662
676
|
console.log("Lacy Shell detects natural language and routes it to AI coding agents.\n");
|
|
663
677
|
console.log("Quick tips:");
|
|
664
678
|
console.log(" • Type normally for shell commands");
|
|
@@ -683,7 +697,7 @@ async function main() {
|
|
|
683
697
|
|
|
684
698
|
if (args.includes("--help") || args.includes("-h")) {
|
|
685
699
|
console.log(`
|
|
686
|
-
${pc.magenta(pc.bold("Lacy Shell"))} - Talk directly to your shell
|
|
700
|
+
${pc.magenta(pc.bold("Lacy Shell"))} ${pc.dim(`v${VERSION}`)} - Talk directly to your shell
|
|
687
701
|
|
|
688
702
|
${pc.bold("Usage:")}
|
|
689
703
|
npx lacy Install Lacy Shell
|
|
@@ -710,7 +724,7 @@ ${pc.dim("https://github.com/lacymorrow/lacy")}
|
|
|
710
724
|
// If already installed, show dashboard + menu
|
|
711
725
|
if (isInstalled()) {
|
|
712
726
|
console.clear();
|
|
713
|
-
p.intro(pc.magenta(pc.bold(` Lacy Shell `)));
|
|
727
|
+
p.intro(pc.magenta(pc.bold(` Lacy Shell `)) + pc.dim(` v${VERSION}`));
|
|
714
728
|
|
|
715
729
|
// Show current status
|
|
716
730
|
const active = readConfigValue("active");
|
|
@@ -870,7 +884,7 @@ ${pc.dim("https://github.com/lacymorrow/lacy")}
|
|
|
870
884
|
|
|
871
885
|
const lines = [
|
|
872
886
|
` Installed: ${pc.green(dir)}`,
|
|
873
|
-
|
|
887
|
+
` Version: ${pc.cyan("v" + VERSION)}${sha ? pc.dim(` (${sha})`) : ""}`,
|
|
874
888
|
` Shell: ${pc.cyan(shell)} ${rcConfigured ? pc.green("configured") : pc.yellow("not configured")}`,
|
|
875
889
|
` Config: ${hasConfig ? pc.green("exists") : pc.yellow("missing")}`,
|
|
876
890
|
` Tool: ${pc.cyan(active || "auto-detect")}`,
|
|
@@ -901,7 +915,8 @@ ${pc.dim("https://github.com/lacymorrow/lacy")}
|
|
|
901
915
|
: INSTALL_DIR_OLD;
|
|
902
916
|
try {
|
|
903
917
|
execSync("git pull origin main", { cwd: updateDir, stdio: "pipe" });
|
|
904
|
-
|
|
918
|
+
const updatedVersion = getVersion();
|
|
919
|
+
updateSpinner.stop(`Lacy updated to v${updatedVersion}`);
|
|
905
920
|
p.log.success("Update complete!");
|
|
906
921
|
await restartShell();
|
|
907
922
|
p.outro("Restart your terminal to apply changes.");
|