mover-os 4.4.0 → 4.4.1
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/install.js +78 -7
- package/package.json +1 -1
package/install.js
CHANGED
|
@@ -420,8 +420,8 @@ function interactiveSelect(items, { multi = false, preSelected = [], defaultInde
|
|
|
420
420
|
lines++;
|
|
421
421
|
|
|
422
422
|
const hint = multi
|
|
423
|
-
? dim(" ↑↓ navigate space select a all enter confirm")
|
|
424
|
-
: dim(" ↑↓ navigate enter select");
|
|
423
|
+
? dim(" ↑↓ navigate space select a all enter confirm esc back")
|
|
424
|
+
: dim(" ↑↓ navigate enter select esc back");
|
|
425
425
|
w(`\x1b[2K${BAR_COLOR}│${S.reset}${hint}\n`);
|
|
426
426
|
lines++;
|
|
427
427
|
|
|
@@ -467,6 +467,20 @@ function interactiveSelect(items, { multi = false, preSelected = [], defaultInde
|
|
|
467
467
|
}
|
|
468
468
|
return;
|
|
469
469
|
}
|
|
470
|
+
else if (data === "\x1b" || data === "\x1b\x1b" || (!multi && data === "q")) {
|
|
471
|
+
// Escape — go back / cancel
|
|
472
|
+
stdin.removeListener("data", handler);
|
|
473
|
+
stdin.setRawMode(false);
|
|
474
|
+
stdin.pause();
|
|
475
|
+
if (prevLines > 0) {
|
|
476
|
+
w(`\x1b[${prevLines}A`);
|
|
477
|
+
for (let i = 0; i < prevLines; i++) w("\x1b[2K\n");
|
|
478
|
+
w(`\x1b[${prevLines}A`);
|
|
479
|
+
}
|
|
480
|
+
w(S.show);
|
|
481
|
+
resolve(null);
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
470
484
|
else if (data === "\x03") { cleanup(); ln(); process.exit(0); }
|
|
471
485
|
|
|
472
486
|
render();
|
|
@@ -655,6 +669,7 @@ function parseArgs() {
|
|
|
655
669
|
if (a === "--key" && args[i + 1]) { opts.key = args[++i]; continue; }
|
|
656
670
|
// Backward compat: --update / -u → command 'update'
|
|
657
671
|
if (a === "--update" || a === "-u") { opts.command = "update"; continue; }
|
|
672
|
+
if (a === "--_self-updated") { opts._selfUpdated = true; continue; }
|
|
658
673
|
if (a === "--help" || a === "-h") {
|
|
659
674
|
ln();
|
|
660
675
|
ln(` ${bold("moveros")} ${dim("— the Mover OS companion CLI")}`);
|
|
@@ -708,6 +723,17 @@ function detectObsidianVaults() {
|
|
|
708
723
|
}
|
|
709
724
|
}
|
|
710
725
|
|
|
726
|
+
function compareVersions(a, b) {
|
|
727
|
+
const pa = a.split(".").map(Number);
|
|
728
|
+
const pb = b.split(".").map(Number);
|
|
729
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
730
|
+
const va = pa[i] || 0, vb = pb[i] || 0;
|
|
731
|
+
if (va > vb) return 1;
|
|
732
|
+
if (va < vb) return -1;
|
|
733
|
+
}
|
|
734
|
+
return 0;
|
|
735
|
+
}
|
|
736
|
+
|
|
711
737
|
// ─── Change detection (update mode) ─────────────────────────────────────────
|
|
712
738
|
function detectChanges(bundleDir, vaultPath, selectedAgentIds) {
|
|
713
739
|
const home = os.homedir();
|
|
@@ -2995,6 +3021,7 @@ async function cmdCapture(opts) {
|
|
|
2995
3021
|
{ id: "link", name: "Link", tier: "URL with optional note" },
|
|
2996
3022
|
{ id: "dump", name: "Brain dump", tier: "Free-form text" },
|
|
2997
3023
|
], { multi: false });
|
|
3024
|
+
if (!type) return;
|
|
2998
3025
|
}
|
|
2999
3026
|
content = await textInput({ label: `Enter ${type}:` });
|
|
3000
3027
|
}
|
|
@@ -3052,6 +3079,7 @@ async function cmdWho(opts) {
|
|
|
3052
3079
|
{ id: "yes", name: "Create stub", tier: `Creates ${name}.md in People/` },
|
|
3053
3080
|
{ id: "no", name: "Skip", tier: "" },
|
|
3054
3081
|
], { multi: false });
|
|
3082
|
+
if (!create) return;
|
|
3055
3083
|
if (create === "yes") {
|
|
3056
3084
|
const peopleDir = path.join(entitiesDir, "People");
|
|
3057
3085
|
fs.mkdirSync(peopleDir, { recursive: true });
|
|
@@ -3503,6 +3531,8 @@ async function cmdPrayer(opts) {
|
|
|
3503
3531
|
barLn();
|
|
3504
3532
|
const choice = await interactiveSelect(items, { multi: false });
|
|
3505
3533
|
|
|
3534
|
+
if (!choice || choice === "back") return;
|
|
3535
|
+
|
|
3506
3536
|
if (choice === "fetch") {
|
|
3507
3537
|
barLn();
|
|
3508
3538
|
const city = await textInput({ label: "City", placeholder: "London" });
|
|
@@ -3649,7 +3679,7 @@ async function cmdBackup(opts) {
|
|
|
3649
3679
|
];
|
|
3650
3680
|
|
|
3651
3681
|
const choices = await interactiveSelect(items, { multi: true, preSelected: ["engine"] });
|
|
3652
|
-
if (choices.length === 0) { barLn(dim(" Cancelled.")); return; }
|
|
3682
|
+
if (!choices || choices.length === 0) { barLn(dim(" Cancelled.")); return; }
|
|
3653
3683
|
|
|
3654
3684
|
const now = new Date();
|
|
3655
3685
|
const ts = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}_${String(now.getHours()).padStart(2, "0")}${String(now.getMinutes()).padStart(2, "0")}`;
|
|
@@ -4215,6 +4245,39 @@ async function main() {
|
|
|
4215
4245
|
process.exit(1);
|
|
4216
4246
|
}
|
|
4217
4247
|
|
|
4248
|
+
// ── CLI self-update check ──
|
|
4249
|
+
if (opts.command === "update" && !opts._selfUpdated) {
|
|
4250
|
+
try {
|
|
4251
|
+
const localVer = require("./package.json").version;
|
|
4252
|
+
const npmVer = execSync("npm view mover-os version", { encoding: "utf8", timeout: 10000 }).trim();
|
|
4253
|
+
if (npmVer && npmVer !== localVer && compareVersions(npmVer, localVer) > 0) {
|
|
4254
|
+
barLn(`${yellow("CLI update available:")} ${dim(localVer)} ${dim("\u2192")} ${green(npmVer)}`);
|
|
4255
|
+
const sp = spinner("Updating CLI");
|
|
4256
|
+
try {
|
|
4257
|
+
execSync("npm i -g mover-os", { stdio: "ignore", timeout: 60000 });
|
|
4258
|
+
sp.stop(`CLI updated to ${npmVer}`);
|
|
4259
|
+
barLn(dim(" Re-running with updated CLI..."));
|
|
4260
|
+
barLn();
|
|
4261
|
+
// Re-exec with new code — pass args through, add flag to prevent loop
|
|
4262
|
+
const args = process.argv.slice(2).concat("--_self-updated");
|
|
4263
|
+
const { spawnSync } = require("child_process");
|
|
4264
|
+
const result = spawnSync(process.argv[0], [process.argv[1], ...args], {
|
|
4265
|
+
stdio: "inherit", cwd: process.cwd(),
|
|
4266
|
+
});
|
|
4267
|
+
process.exit(result.status || 0);
|
|
4268
|
+
} catch (e) {
|
|
4269
|
+
sp.stop(yellow(`CLI self-update failed: ${e.message}`));
|
|
4270
|
+
barLn(dim(" Continuing with current version..."));
|
|
4271
|
+
}
|
|
4272
|
+
} else {
|
|
4273
|
+
barLn(`${green("\u2713")} ${dim("CLI is up to date")} ${dim(`(${localVer})`)}`);
|
|
4274
|
+
}
|
|
4275
|
+
} catch {
|
|
4276
|
+
barLn(dim(" Could not check for CLI updates (offline?)"));
|
|
4277
|
+
}
|
|
4278
|
+
barLn();
|
|
4279
|
+
}
|
|
4280
|
+
|
|
4218
4281
|
// ── Headless quick update ──
|
|
4219
4282
|
if (opts.command === "update") {
|
|
4220
4283
|
// Validate stored key
|
|
@@ -4433,6 +4496,7 @@ async function main() {
|
|
|
4433
4496
|
});
|
|
4434
4497
|
|
|
4435
4498
|
const selected = await interactiveSelect(vaultItems, { multi: false });
|
|
4499
|
+
if (!selected) return;
|
|
4436
4500
|
|
|
4437
4501
|
if (selected === "__manual__") {
|
|
4438
4502
|
vaultPath = await textInput({
|
|
@@ -4483,6 +4547,7 @@ async function main() {
|
|
|
4483
4547
|
],
|
|
4484
4548
|
{ multi: false, defaultIndex: 0 }
|
|
4485
4549
|
);
|
|
4550
|
+
if (!installMode) return;
|
|
4486
4551
|
}
|
|
4487
4552
|
|
|
4488
4553
|
// ── Uninstall flow ──
|
|
@@ -4522,7 +4587,7 @@ async function main() {
|
|
|
4522
4587
|
preSelected: ["engine"],
|
|
4523
4588
|
});
|
|
4524
4589
|
|
|
4525
|
-
if (backupChoices.length > 0 && !(backupChoices.length === 1 && backupChoices.includes("skip"))) {
|
|
4590
|
+
if (backupChoices && backupChoices.length > 0 && !(backupChoices.length === 1 && backupChoices.includes("skip"))) {
|
|
4526
4591
|
const now = new Date();
|
|
4527
4592
|
const ts = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}_${String(now.getHours()).padStart(2, "0")}${String(now.getMinutes()).padStart(2, "0")}`;
|
|
4528
4593
|
const archivesDir = path.join(vaultPath, "04_Archives");
|
|
@@ -4685,12 +4750,13 @@ async function main() {
|
|
|
4685
4750
|
multi: true,
|
|
4686
4751
|
preSelected: detectedIds,
|
|
4687
4752
|
});
|
|
4753
|
+
if (!selectedIds) return;
|
|
4688
4754
|
const selectedAgents = AGENTS.filter((a) => selectedIds.includes(a.id));
|
|
4689
4755
|
|
|
4690
4756
|
if (selectedAgents.length === 0) {
|
|
4691
4757
|
barLn(yellow("No agents selected."));
|
|
4692
4758
|
outro("Cancelled.");
|
|
4693
|
-
|
|
4759
|
+
return;
|
|
4694
4760
|
}
|
|
4695
4761
|
|
|
4696
4762
|
// ── Change detection + selection (update mode only) ──
|
|
@@ -4735,9 +4801,9 @@ async function main() {
|
|
|
4735
4801
|
{ multi: false, defaultIndex: 0 }
|
|
4736
4802
|
);
|
|
4737
4803
|
|
|
4738
|
-
if (applyChoice === "cancel") {
|
|
4804
|
+
if (!applyChoice || applyChoice === "cancel") {
|
|
4739
4805
|
outro("Cancelled.");
|
|
4740
|
-
|
|
4806
|
+
return;
|
|
4741
4807
|
}
|
|
4742
4808
|
|
|
4743
4809
|
if (applyChoice === "select") {
|
|
@@ -4771,6 +4837,7 @@ async function main() {
|
|
|
4771
4837
|
multi: true,
|
|
4772
4838
|
preSelected: changedPreSelected,
|
|
4773
4839
|
});
|
|
4840
|
+
if (!selectedFileIds) return;
|
|
4774
4841
|
|
|
4775
4842
|
// Build workflow filter Set
|
|
4776
4843
|
const selectedWfFiles = selectedFileIds
|
|
@@ -4817,6 +4884,7 @@ async function main() {
|
|
|
4817
4884
|
multi: true,
|
|
4818
4885
|
preSelected,
|
|
4819
4886
|
});
|
|
4887
|
+
if (!selectedCatIds) return;
|
|
4820
4888
|
|
|
4821
4889
|
installSkills = selectedCatIds.length > 0;
|
|
4822
4890
|
if (installSkills) {
|
|
@@ -4843,6 +4911,7 @@ async function main() {
|
|
|
4843
4911
|
],
|
|
4844
4912
|
{ multi: false, defaultIndex: 0 }
|
|
4845
4913
|
);
|
|
4914
|
+
if (!slChoice) return;
|
|
4846
4915
|
installStatusLine = slChoice === "yes";
|
|
4847
4916
|
}
|
|
4848
4917
|
|
|
@@ -4862,6 +4931,7 @@ async function main() {
|
|
|
4862
4931
|
],
|
|
4863
4932
|
{ multi: false, defaultIndex: 1 }
|
|
4864
4933
|
);
|
|
4934
|
+
if (!ptChoice) return;
|
|
4865
4935
|
if (ptChoice === "yes") {
|
|
4866
4936
|
prayerSetup = true;
|
|
4867
4937
|
barLn();
|
|
@@ -4876,6 +4946,7 @@ async function main() {
|
|
|
4876
4946
|
],
|
|
4877
4947
|
{ multi: false, defaultIndex: 0 }
|
|
4878
4948
|
);
|
|
4949
|
+
if (!method || method === "later") { /* skip */ }
|
|
4879
4950
|
|
|
4880
4951
|
const moverDir = path.join(os.homedir(), ".mover");
|
|
4881
4952
|
if (!fs.existsSync(moverDir)) fs.mkdirSync(moverDir, { recursive: true, mode: 0o700 });
|