mover-os 4.6.1 → 4.6.2
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 +106 -64
- package/package.json +1 -1
package/install.js
CHANGED
|
@@ -199,15 +199,23 @@ async function printHeader(animate = IS_TTY) {
|
|
|
199
199
|
ln(` ${dim(`v${pkgVer}`)} ${gray("the agentic operating system for obsidian")}${infoRight ? ` ${infoRight}` : ""}`);
|
|
200
200
|
|
|
201
201
|
// Non-blocking update check
|
|
202
|
+
let _updateAvailable = null;
|
|
202
203
|
try {
|
|
203
204
|
const latest = execSync("npm view mover-os version", { encoding: "utf8", timeout: 5000 }).trim();
|
|
204
205
|
if (latest && latest !== pkgVer && compareVersions(latest, pkgVer) > 0) {
|
|
205
|
-
|
|
206
|
+
_updateAvailable = latest;
|
|
206
207
|
}
|
|
207
208
|
} catch {}
|
|
208
209
|
|
|
209
210
|
ln();
|
|
210
|
-
|
|
211
|
+
if (_updateAvailable) {
|
|
212
|
+
ln(` ${yellow("┌──────────────────────────────────────────┐")}`);
|
|
213
|
+
ln(` ${yellow("│")} Update available: ${dim(`v${pkgVer}`)} ${dim("\u2192")} ${green(`v${_updateAvailable}`)}${" ".repeat(Math.max(0, 16 - _updateAvailable.length - pkgVer.length))}${yellow("│")}`);
|
|
214
|
+
ln(` ${yellow("│")} Run ${bold("moveros update")} to get the latest ${yellow("│")}`);
|
|
215
|
+
ln(` ${yellow("└──────────────────────────────────────────┘")}`);
|
|
216
|
+
} else {
|
|
217
|
+
ln(gray(" ─────────────────────────────────────────────"));
|
|
218
|
+
}
|
|
211
219
|
ln();
|
|
212
220
|
}
|
|
213
221
|
|
|
@@ -5827,74 +5835,108 @@ async function main() {
|
|
|
5827
5835
|
}
|
|
5828
5836
|
}
|
|
5829
5837
|
|
|
5830
|
-
// ──
|
|
5838
|
+
// ── Confirmation gate — review and optionally change selections ──
|
|
5831
5839
|
{
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
const cfgPath = path.join(os.homedir(), ".mover", "config.json");
|
|
5838
|
-
let cfg = {};
|
|
5839
|
-
if (fs.existsSync(cfgPath)) { try { cfg = JSON.parse(fs.readFileSync(cfgPath, "utf8")); } catch {} }
|
|
5840
|
-
if (!cfg.settings) cfg.settings = {};
|
|
5840
|
+
let confirmed = false;
|
|
5841
|
+
while (!confirmed) {
|
|
5842
|
+
barLn();
|
|
5843
|
+
question(bold("Review your selections") + dim(" (enter to change, esc to cancel)"));
|
|
5844
|
+
barLn();
|
|
5841
5845
|
|
|
5842
|
-
const
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5846
|
+
const agentNames = selectedAgents.map((a) => a.name).join(", ");
|
|
5847
|
+
const skillsLabel = installSkills && selectedCategories
|
|
5848
|
+
? [...selectedCategories].join(", ")
|
|
5849
|
+
: installSkills ? "all categories" : "none";
|
|
5850
|
+
const slLabel = selectedIds.includes("claude-code") ? (installStatusLine ? "yes" : "no") : null;
|
|
5851
|
+
|
|
5852
|
+
const reviewItems = [
|
|
5853
|
+
{ id: "_install", name: green(bold(" Install")), tier: "Proceed with the selections above" },
|
|
5854
|
+
{ id: "agents", name: `Agents ${dim(agentNames)}`, tier: "Change which AI agents to install for" },
|
|
5855
|
+
{ id: "skills", name: `Skills ${dim(skillsLabel)}`, tier: "Change skill categories" },
|
|
5847
5856
|
];
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
const meta = KNOWN_SETTINGS[settingsPick];
|
|
5851
|
-
if (meta) {
|
|
5852
|
-
if (meta.type === "boolean") {
|
|
5853
|
-
cfg.settings[settingsPick] = !(cfg.settings[settingsPick] !== undefined ? cfg.settings[settingsPick] : meta.defaults);
|
|
5854
|
-
statusLine("ok", settingsPick, cfg.settings[settingsPick] ? "on" : "off");
|
|
5855
|
-
} else {
|
|
5856
|
-
const answer = await textInput({ label: settingsPick, initial: String(cfg.settings[settingsPick] !== undefined ? cfg.settings[settingsPick] : meta.defaults) });
|
|
5857
|
-
if (answer !== null && answer.trim() !== "") {
|
|
5858
|
-
cfg.settings[settingsPick] = meta.type === "number" ? parseInt(answer.trim(), 10) : answer.trim();
|
|
5859
|
-
statusLine("ok", settingsPick, JSON.stringify(cfg.settings[settingsPick]));
|
|
5860
|
-
}
|
|
5861
|
-
}
|
|
5862
|
-
fs.mkdirSync(path.dirname(cfgPath), { recursive: true });
|
|
5863
|
-
fs.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2), "utf8");
|
|
5857
|
+
if (slLabel !== null) {
|
|
5858
|
+
reviewItems.push({ id: "statusline", name: `Status line ${dim(slLabel)}`, tier: "Toggle Claude Code status line" });
|
|
5864
5859
|
}
|
|
5865
|
-
|
|
5866
|
-
}
|
|
5860
|
+
reviewItems.push({ id: "settings", name: `Settings ${dim("enter to configure")}`, tier: "Configure review_day, tracking, friction level" });
|
|
5867
5861
|
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
barLn();
|
|
5871
|
-
question(bold("Review your selections:"));
|
|
5872
|
-
barLn();
|
|
5873
|
-
barLn(` ${bold("Vault:")} ${vaultPath}`);
|
|
5874
|
-
barLn(` ${bold("Agents:")} ${selectedAgents.map((a) => a.name).join(", ")}`);
|
|
5875
|
-
if (installSkills && selectedCategories) {
|
|
5876
|
-
barLn(` ${bold("Skills:")} ${[...selectedCategories].join(", ")}`);
|
|
5877
|
-
} else if (installSkills) {
|
|
5878
|
-
barLn(` ${bold("Skills:")} all categories`);
|
|
5879
|
-
} else {
|
|
5880
|
-
barLn(` ${bold("Skills:")} none`);
|
|
5881
|
-
}
|
|
5882
|
-
if (selectedIds.includes("claude-code")) {
|
|
5883
|
-
barLn(` ${bold("Status line:")} ${installStatusLine ? "yes" : "no"}`);
|
|
5884
|
-
}
|
|
5885
|
-
barLn(` ${bold("Prayer:")} ${prayerSetup ? "yes" : "no"}`);
|
|
5886
|
-
barLn();
|
|
5862
|
+
const pick = await interactiveSelect(reviewItems, { defaultIndex: 0 });
|
|
5863
|
+
if (!pick) { outro("Cancelled."); return; }
|
|
5887
5864
|
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
|
|
5865
|
+
if (pick === "_install") {
|
|
5866
|
+
confirmed = true;
|
|
5867
|
+
} else if (pick === "agents") {
|
|
5868
|
+
barLn();
|
|
5869
|
+
question("Select your AI agents");
|
|
5870
|
+
const agentItems = AGENTS.map((a) => {
|
|
5871
|
+
const detected = a.detect();
|
|
5872
|
+
return { id: a.id, name: `${a.name}${detected ? dim(" (detected)") : ""}`, tier: dim(a.tier), _detected: detected };
|
|
5873
|
+
});
|
|
5874
|
+
const newIds = await interactiveSelect(agentItems, { multi: true, preSelected: selectedIds });
|
|
5875
|
+
if (newIds && newIds.length > 0) {
|
|
5876
|
+
selectedIds.length = 0;
|
|
5877
|
+
newIds.forEach((id) => selectedIds.push(id));
|
|
5878
|
+
selectedAgents.length = 0;
|
|
5879
|
+
AGENTS.filter((a) => selectedIds.includes(a.id)).forEach((a) => selectedAgents.push(a));
|
|
5880
|
+
}
|
|
5881
|
+
} else if (pick === "skills") {
|
|
5882
|
+
barLn();
|
|
5883
|
+
const allSkills = findSkills(bundleDir);
|
|
5884
|
+
const catCounts = {};
|
|
5885
|
+
for (const sk of allSkills) catCounts[sk.category] = (catCounts[sk.category] || 0) + 1;
|
|
5886
|
+
const categoryItems = CATEGORY_META.map((c) => ({
|
|
5887
|
+
id: c.id, name: `${c.name} ${dim(`(${catCounts[c.id] || 0})`)}`, tier: dim(c.desc),
|
|
5888
|
+
}));
|
|
5889
|
+
question("Select skill categories:");
|
|
5890
|
+
const newCats = await interactiveSelect(categoryItems, { multi: true, preSelected: selectedCategories ? [...selectedCategories] : ["development", "obsidian"] });
|
|
5891
|
+
if (newCats) {
|
|
5892
|
+
installSkills = newCats.length > 0;
|
|
5893
|
+
selectedCategories = installSkills ? new Set(newCats) : null;
|
|
5894
|
+
}
|
|
5895
|
+
} else if (pick === "statusline") {
|
|
5896
|
+
installStatusLine = !installStatusLine;
|
|
5897
|
+
} else if (pick === "settings") {
|
|
5898
|
+
// Re-enter settings loop
|
|
5899
|
+
barLn();
|
|
5900
|
+
question("Configure settings " + dim("(enter to toggle/edit, esc to go back)"));
|
|
5901
|
+
barLn();
|
|
5902
|
+
const sCfgPath = path.join(os.homedir(), ".mover", "config.json");
|
|
5903
|
+
let sCfg = {};
|
|
5904
|
+
if (fs.existsSync(sCfgPath)) { try { sCfg = JSON.parse(fs.readFileSync(sCfgPath, "utf8")); } catch {} }
|
|
5905
|
+
if (!sCfg.settings) sCfg.settings = {};
|
|
5906
|
+
const installSettings = [
|
|
5907
|
+
{ key: "track_food", label: "Track food", desc: "Track meals in daily notes" },
|
|
5908
|
+
{ key: "track_sleep", label: "Track sleep", desc: "Track sleep in daily notes" },
|
|
5909
|
+
{ key: "friction_level", label: "Friction level", desc: "AI pushback intensity (1=gentle, 4=hard block)" },
|
|
5910
|
+
{ key: "review_day", label: "Review day", desc: "Day for weekly review" },
|
|
5911
|
+
];
|
|
5912
|
+
let sLoop = true;
|
|
5913
|
+
while (sLoop) {
|
|
5914
|
+
const sItems = installSettings.map((s) => {
|
|
5915
|
+
const meta = KNOWN_SETTINGS[s.key];
|
|
5916
|
+
const val = sCfg.settings[s.key] !== undefined ? sCfg.settings[s.key] : meta.defaults;
|
|
5917
|
+
const display = meta.type === "boolean" ? (val ? green("on") : dim("off")) : String(val);
|
|
5918
|
+
return { id: s.key, name: `${s.label.padEnd(18)}${display}`, tier: s.desc };
|
|
5919
|
+
});
|
|
5920
|
+
const sPick = await interactiveSelect(sItems);
|
|
5921
|
+
if (!sPick) { sLoop = false; break; }
|
|
5922
|
+
const sMeta = KNOWN_SETTINGS[sPick];
|
|
5923
|
+
if (sMeta) {
|
|
5924
|
+
if (sMeta.type === "boolean") {
|
|
5925
|
+
sCfg.settings[sPick] = !(sCfg.settings[sPick] !== undefined ? sCfg.settings[sPick] : sMeta.defaults);
|
|
5926
|
+
} else if (sPick === "friction_level") {
|
|
5927
|
+
const cur = sCfg.settings[sPick] || sMeta.defaults;
|
|
5928
|
+
sCfg.settings[sPick] = cur >= 4 ? 1 : cur + 1;
|
|
5929
|
+
} else if (sPick === "review_day") {
|
|
5930
|
+
const days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
|
|
5931
|
+
const cur = sCfg.settings[sPick] || sMeta.defaults;
|
|
5932
|
+
const idx = days.indexOf(cur);
|
|
5933
|
+
sCfg.settings[sPick] = days[(idx + 1) % days.length];
|
|
5934
|
+
}
|
|
5935
|
+
fs.mkdirSync(path.dirname(sCfgPath), { recursive: true });
|
|
5936
|
+
fs.writeFileSync(sCfgPath, JSON.stringify(sCfg, null, 2), "utf8");
|
|
5937
|
+
}
|
|
5938
|
+
}
|
|
5939
|
+
}
|
|
5898
5940
|
}
|
|
5899
5941
|
}
|
|
5900
5942
|
|