feat: integrate mempalace

This commit is contained in:
svemagie
2026-04-11 11:39:23 +02:00
parent 29d2b6ccda
commit 12a1dec7d8
3 changed files with 115 additions and 1 deletions
+49
View File
@@ -31405,6 +31405,11 @@ var ChatView = class extends import_obsidian.ItemView {
...additionalFiles ...additionalFiles
].filter((f, i, arr) => arr.findIndex((x) => x.path === f.path) === i); ].filter((f, i, arr) => arr.findIndex((x) => x.path === f.path) === i);
const contextNotes = contextFiles.map((f) => f.path); const contextNotes = contextFiles.map((f) => f.path);
let mpContext = "";
if (this.plugin.settings.useMempalace && query.trim()) {
this.setStatus("MemPalace wird abgefragt\u2026");
mpContext = await this.queryMempalace(query);
}
let contextText = ""; let contextText = "";
if (contextFiles.length > 0) { if (contextFiles.length > 0) {
this.setStatus(`Lade ${contextFiles.length} Notizen\u2026`); this.setStatus(`Lade ${contextFiles.length} Notizen\u2026`);
@@ -31417,6 +31422,8 @@ ${content}`;
); );
contextText = "\n\n---\nKontext aus dem Vault:\n\n" + contents.join("\n\n"); contextText = "\n\n---\nKontext aus dem Vault:\n\n" + contents.join("\n\n");
} }
if (mpContext)
contextText = mpContext + contextText;
const userMsg = { const userMsg = {
role: "user", role: "user",
content: query, content: query,
@@ -32045,6 +32052,29 @@ tags: [chat]
this.renderHistoryList(listEl); this.renderHistoryList(listEl);
} }
} }
/** Query the MemPalace CLI and return formatted context, or "" on error/timeout/not-installed. */
async queryMempalace(query) {
return new Promise((resolve) => {
const { execFile } = require("child_process");
const { existsSync } = require("fs");
if (!existsSync("/usr/local/bin/mempalace")) {
resolve("");
return;
}
execFile(
"/usr/local/bin/mempalace",
["search", query, "--results", String(this.plugin.settings.mempalaceResults ?? 3)],
{ timeout: 1e4 },
(err, stdout) => {
if (err || !stdout?.trim()) {
resolve("");
return;
}
resolve("\n\n---\nMemPalace (Wissens-Archiv):\n\n" + stdout.trim());
}
);
});
}
renderHistoryList(listEl) { renderHistoryList(listEl) {
listEl.empty(); listEl.empty();
if (this.historyThreads.length === 0) { if (this.historyThreads.length === 0) {
@@ -32894,6 +32924,8 @@ Wenn du Fragen beantwortest:
useEmbeddings: false, useEmbeddings: false,
embeddingModel: "TaylorAI/bge-micro-v2", embeddingModel: "TaylorAI/bge-micro-v2",
embedExcludeFolders: [], embedExcludeFolders: [],
useMempalace: false,
mempalaceResults: 3,
promptButtons: [ promptButtons: [
{ {
label: "Draft Check", label: "Draft Check",
@@ -33077,6 +33109,23 @@ var MemexChatSettingsTab = class extends import_obsidian3.PluginSettingTab {
addExclFolder(exclInput.value); addExclFolder(exclInput.value);
} }
}); });
containerEl.createEl("h3", { text: "MemPalace" });
containerEl.createEl("p", {
text: "Reichert jeden Chat mit Ergebnissen aus dem MemPalace-Wissensarchiv an (ben\xF6tigt /usr/local/bin/mempalace).",
cls: "setting-item-description"
});
new import_obsidian3.Setting(containerEl).setName("MemPalace aktivieren").setDesc("F\xFChrt bei jeder Nachricht eine MemPalace-Suche durch und f\xFCgt die Ergebnisse als Kontext ein.").addToggle(
(toggle) => toggle.setValue(this.plugin.settings.useMempalace).onChange(async (value) => {
this.plugin.settings.useMempalace = value;
await this.plugin.saveSettings();
})
);
new import_obsidian3.Setting(containerEl).setName("Anzahl MemPalace-Ergebnisse").setDesc("Wie viele Treffer aus dem MemPalace-Archiv pro Anfrage eingebunden werden (1\u201310).").addSlider(
(slider) => slider.setLimits(1, 10, 1).setValue(this.plugin.settings.mempalaceResults).setDynamicTooltip().onChange(async (value) => {
this.plugin.settings.mempalaceResults = value;
await this.plugin.saveSettings();
})
);
containerEl.createEl("h3", { text: "Kontext-Einstellungen" }); containerEl.createEl("h3", { text: "Kontext-Einstellungen" });
new import_obsidian3.Setting(containerEl).setName("Max. Kontext-Notizen").setDesc("Wie viele Notizen werden automatisch als Kontext hinzugef\xFCgt? (1\u201315)").addSlider( new import_obsidian3.Setting(containerEl).setName("Max. Kontext-Notizen").setDesc("Wie viele Notizen werden automatisch als Kontext hinzugef\xFCgt? (1\u201315)").addSlider(
(slider) => slider.setLimits(1, 15, 1).setValue(this.plugin.settings.maxContextNotes).setDynamicTooltip().onChange(async (value) => { (slider) => slider.setLimits(1, 15, 1).setValue(this.plugin.settings.maxContextNotes).setDynamicTooltip().onChange(async (value) => {
+31 -1
View File
@@ -357,7 +357,14 @@ export class ChatView extends ItemView {
const contextNotes = contextFiles.map((f) => f.path); const contextNotes = contextFiles.map((f) => f.path);
// Build context text // MemPalace context (queried first — prepended so it appears closest to the query)
let mpContext = "";
if (this.plugin.settings.useMempalace && query.trim()) {
this.setStatus("MemPalace wird abgefragt…");
mpContext = await this.queryMempalace(query);
}
// Build vault context text
let contextText = ""; let contextText = "";
if (contextFiles.length > 0) { if (contextFiles.length > 0) {
this.setStatus(`Lade ${contextFiles.length} Notizen…`); this.setStatus(`Lade ${contextFiles.length} Notizen…`);
@@ -370,6 +377,9 @@ export class ChatView extends ItemView {
contextText = "\n\n---\nKontext aus dem Vault:\n\n" + contents.join("\n\n"); contextText = "\n\n---\nKontext aus dem Vault:\n\n" + contents.join("\n\n");
} }
// MemPalace results precede vault notes (higher priority = closer to the query)
if (mpContext) contextText = mpContext + contextText;
// Add user message // Add user message
const userMsg: ChatMessage = { const userMsg: ChatMessage = {
role: "user", role: "user",
@@ -1087,6 +1097,26 @@ export class ChatView extends ItemView {
} }
} }
/** Query the MemPalace CLI and return formatted context, or "" on error/timeout/not-installed. */
private async queryMempalace(query: string): Promise<string> {
return new Promise((resolve) => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { execFile } = require("child_process") as typeof import("child_process");
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { existsSync } = require("fs") as typeof import("fs");
if (!existsSync("/usr/local/bin/mempalace")) { resolve(""); return; }
execFile(
"/usr/local/bin/mempalace",
["search", query, "--results", String(this.plugin.settings.mempalaceResults ?? 3)],
{ timeout: 10_000 },
(err: Error | null, stdout: string) => {
if (err || !stdout?.trim()) { resolve(""); return; }
resolve("\n\n---\nMemPalace (Wissens-Archiv):\n\n" + stdout.trim());
}
);
});
}
private renderHistoryList(listEl: HTMLElement): void { private renderHistoryList(listEl: HTMLElement): void {
listEl.empty(); listEl.empty();
if (this.historyThreads.length === 0) { if (this.historyThreads.length === 0) {
+35
View File
@@ -28,6 +28,8 @@ export interface MemexChatSettings {
useEmbeddings: boolean; // use local embedding model instead of TF-IDF useEmbeddings: boolean; // use local embedding model instead of TF-IDF
embeddingModel: string; // HuggingFace model ID embeddingModel: string; // HuggingFace model ID
embedExcludeFolders: string[]; // vault folders to skip during embedding embedExcludeFolders: string[]; // vault folders to skip during embedding
useMempalace: boolean; // inject MemPalace search results as additional context
mempalaceResults: number; // number of MemPalace results to include
} }
export const DEFAULT_SETTINGS: MemexChatSettings = { export const DEFAULT_SETTINGS: MemexChatSettings = {
@@ -54,6 +56,8 @@ Wenn du Fragen beantwortest:
useEmbeddings: false, useEmbeddings: false,
embeddingModel: "TaylorAI/bge-micro-v2", embeddingModel: "TaylorAI/bge-micro-v2",
embedExcludeFolders: [], embedExcludeFolders: [],
useMempalace: false,
mempalaceResults: 3,
promptButtons: [ promptButtons: [
{ {
label: "Draft Check", label: "Draft Check",
@@ -284,6 +288,37 @@ export class MemexChatSettingsTab extends PluginSettingTab {
if (e.key === "Enter") { e.preventDefault(); addExclFolder(exclInput.value); } if (e.key === "Enter") { e.preventDefault(); addExclFolder(exclInput.value); }
}); });
// --- MemPalace ---
containerEl.createEl("h3", { text: "MemPalace" });
containerEl.createEl("p", {
text: "Reichert jeden Chat mit Ergebnissen aus dem MemPalace-Wissensarchiv an (benötigt /usr/local/bin/mempalace).",
cls: "setting-item-description",
});
new Setting(containerEl)
.setName("MemPalace aktivieren")
.setDesc("Führt bei jeder Nachricht eine MemPalace-Suche durch und fügt die Ergebnisse als Kontext ein.")
.addToggle((toggle) =>
toggle.setValue(this.plugin.settings.useMempalace).onChange(async (value) => {
this.plugin.settings.useMempalace = value;
await this.plugin.saveSettings();
})
);
new Setting(containerEl)
.setName("Anzahl MemPalace-Ergebnisse")
.setDesc("Wie viele Treffer aus dem MemPalace-Archiv pro Anfrage eingebunden werden (110).")
.addSlider((slider) =>
slider
.setLimits(1, 10, 1)
.setValue(this.plugin.settings.mempalaceResults)
.setDynamicTooltip()
.onChange(async (value) => {
this.plugin.settings.mempalaceResults = value;
await this.plugin.saveSettings();
})
);
// --- Context --- // --- Context ---
containerEl.createEl("h3", { text: "Kontext-Einstellungen" }); containerEl.createEl("h3", { text: "Kontext-Einstellungen" });