diff --git a/main.js b/main.js index 5a80c12..78b6e17 100644 --- a/main.js +++ b/main.js @@ -31405,6 +31405,11 @@ var ChatView = class extends import_obsidian.ItemView { ...additionalFiles ].filter((f, i, arr) => arr.findIndex((x) => x.path === f.path) === i); 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 = ""; if (contextFiles.length > 0) { 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"); } + if (mpContext) + contextText = mpContext + contextText; const userMsg = { role: "user", content: query, @@ -32045,6 +32052,29 @@ tags: [chat] 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) { listEl.empty(); if (this.historyThreads.length === 0) { @@ -32894,6 +32924,8 @@ Wenn du Fragen beantwortest: useEmbeddings: false, embeddingModel: "TaylorAI/bge-micro-v2", embedExcludeFolders: [], + useMempalace: false, + mempalaceResults: 3, promptButtons: [ { label: "Draft Check", @@ -33077,6 +33109,23 @@ var MemexChatSettingsTab = class extends import_obsidian3.PluginSettingTab { 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" }); 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) => { diff --git a/src/ChatView.ts b/src/ChatView.ts index 0a2b57e..e2f85f8 100644 --- a/src/ChatView.ts +++ b/src/ChatView.ts @@ -357,7 +357,14 @@ export class ChatView extends ItemView { 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 = ""; if (contextFiles.length > 0) { 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"); } + // MemPalace results precede vault notes (higher priority = closer to the query) + if (mpContext) contextText = mpContext + contextText; + // Add user message const userMsg: ChatMessage = { 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 { + 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 { listEl.empty(); if (this.historyThreads.length === 0) { diff --git a/src/SettingsTab.ts b/src/SettingsTab.ts index 56d9c55..3bf0034 100644 --- a/src/SettingsTab.ts +++ b/src/SettingsTab.ts @@ -28,6 +28,8 @@ export interface MemexChatSettings { useEmbeddings: boolean; // use local embedding model instead of TF-IDF embeddingModel: string; // HuggingFace model ID 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 = { @@ -54,6 +56,8 @@ Wenn du Fragen beantwortest: useEmbeddings: false, embeddingModel: "TaylorAI/bge-micro-v2", embedExcludeFolders: [], + useMempalace: false, + mempalaceResults: 3, promptButtons: [ { label: "Draft Check", @@ -284,6 +288,37 @@ export class MemexChatSettingsTab extends PluginSettingTab { 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 (1–10).") + .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 --- containerEl.createEl("h3", { text: "Kontext-Einstellungen" });