show Python setup modal when Python and Homebrew are both missing

This commit is contained in:
Ravi Krishnan 2026-05-13 06:28:19 +09:30
parent 96cc585ace
commit f685144126
4 changed files with 65 additions and 5 deletions

47
main.js
View file

@ -209,9 +209,8 @@ class ManexStudyRoomPlugin extends Plugin {
throw new Error("Python installed but still not found — restart Obsidian and try again.");
}
throw new Error(
"Python 3 is required but not installed. Install it from https://python.org or via Homebrew (brew install python), then restart Obsidian."
);
new PythonSetupModal(this.app).open();
throw new Error("Python 3 not found. See the setup instructions in the Manex Brain dialog.");
}
getVenvPath() {
@ -1013,6 +1012,48 @@ class ManexStudyRoomView extends ItemView {
}
}
class PythonSetupModal extends Modal {
onOpen() {
const { contentEl } = this;
contentEl.empty();
contentEl.createEl("h2", { text: "Python 3 Required" });
contentEl.createEl("p", {
text: "Manex Brain needs Python 3 to run the local AI model. Follow the steps below to get set up."
});
contentEl.createEl("h3", { text: "Step 1 — Install Homebrew" });
contentEl.createEl("p", { text: "Homebrew is a package manager for macOS. Paste this into Terminal:" });
const brewCmd = `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`;
this._codeRow(contentEl, brewCmd, "Copy Homebrew install command");
contentEl.createEl("h3", { text: "Step 2 — Install Python" });
contentEl.createEl("p", { text: "Once Homebrew is installed, run this in Terminal:" });
this._codeRow(contentEl, "brew install python3", "Copy Python install command");
contentEl.createEl("h3", { text: "Step 3 — Restart Obsidian" });
contentEl.createEl("p", { text: "After Python is installed, restart Obsidian and Manex Brain will start automatically." });
const buttonRow = contentEl.createDiv({ cls: "manex-entitlement-actions" });
buttonRow.createEl("button", { text: "Open brew.sh" }).addEventListener("click", () => {
window.open("https://brew.sh", "_blank");
});
buttonRow.createEl("button", { text: "Close" }).addEventListener("click", () => this.close());
}
_codeRow(container, cmd, label) {
const wrap = container.createDiv({ cls: "manex-code-row" });
wrap.createEl("code", { text: cmd });
const btn = wrap.createEl("button", { text: label });
btn.addEventListener("click", () => {
navigator.clipboard.writeText(cmd);
btn.setText("Copied!");
setTimeout(() => btn.setText(label), 2000);
});
}
onClose() { this.contentEl.empty(); }
}
class MemoryModal extends Modal {
constructor(app, options) {
super(app);

View file

@ -1,7 +1,7 @@
{
"id": "manex-brain",
"name": "Manex Brain",
"version": "1.0.2",
"version": "1.0.3",
"minAppVersion": "1.5.0",
"description": "Local AI brain for your vault. Indexes all your notes and answers questions privately using a local Apple Silicon MLX model — no cloud, no API keys.",
"author": "Manex",

View file

@ -334,3 +334,21 @@
width: 100%;
min-height: 160px;
}
.manex-code-row {
display: flex;
align-items: center;
gap: 10px;
margin: 6px 0 14px;
padding: 8px 12px;
border: 1px solid var(--background-modifier-border);
border-radius: 8px;
background: var(--background-secondary);
}
.manex-code-row code {
flex: 1;
font-size: var(--font-ui-smaller);
word-break: break-all;
background: none;
}

View file

@ -1,5 +1,6 @@
{
"1.0.0": "1.5.0",
"1.0.1": "1.5.0",
"1.0.2": "1.5.0"
"1.0.2": "1.5.0",
"1.0.3": "1.5.0"
}