import { App, Plugin, PluginSettingTab, Setting, moment } from "obsidian"; import { MemoryView, MEMORY_VIEW_TYPE } from "./src/MemoryView"; import { GraphView, GRAPH_VIEW_TYPE } from "./src/GraphView"; import { SearchModal } from "./src/SearchModal"; import { setRuntimeConfig, getApiBase, getApiKey, getRuntimeNamespace, writeMemory } from "./src/api"; const SETTINGS_FILE = "zhiyi-settings.json"; interface ZhiYiSettings { apiUrl: string; apiKey: string; namespace: string; } const DEFAULT_SETTINGS: ZhiYiSettings = { apiUrl: "http://localhost:7821", apiKey: "zhiyi-dev-key-2026", namespace: "hermes-main", }; export default class ZhiYiPlugin extends Plugin { private settings: ZhiYiSettings = { ...DEFAULT_SETTINGS }; private ribbonIcon: HTMLElement | null = null; async onload() { // 加载持久化设置 await this.loadSettings(); // 注册视图 this.registerView(MEMORY_VIEW_TYPE, (leaf) => new MemoryView(leaf)); this.registerView(GRAPH_VIEW_TYPE, (leaf) => new GraphView(leaf)); // ─── 命令 ───────────────────────────────────────────────────── this.addCommand({ id: "zhiyi-open-memory-view", name: "打开织忆记忆面板", callback: () => this.openMemoryView(), }); this.addCommand({ id: "zhiyi-open-graph-view", name: "打开织忆图谱面板", callback: () => this.openGraphView(), }); this.addCommand({ id: "zhiyi-search-memories", name: "搜索织忆记忆", callback: () => this.openSearchModal(), }); // 写记忆(选中文本) this.addCommand({ id: "zhiyi-write-memory", name: "将选中内容写入织忆", editorCallback: (editor) => { const selection = editor.getSelection(); if (selection) { this.openWriteModal(selection); } }, }); // Ribbon 图标 this.ribbonIcon = this.addStatusBarItem(); this.ribbonIcon.setIcon("brain"); this.ribbonIcon.setTooltip("织忆记忆"); this.ribbonIcon.onClick(() => this.openMemoryView()); // 状态栏 this.addStatusBarItem().setText("🧠 织忆 v1.1"); // 设置页 this.addSettingTab(new ZhiYiSettingTab(this.app, this)); } onunload() { this.app.workspace.getLeavesOfType(MEMORY_VIEW_TYPE).forEach((leaf) => leaf.detach()); this.app.workspace.getLeavesOfType(GRAPH_VIEW_TYPE).forEach((leaf) => leaf.detach()); } // ─── 设置读写 ─────────────────────────────────────────────────── async loadSettings() { try { const data = await this.loadData(SETTINGS_FILE); if (data) { this.settings = { ...DEFAULT_SETTINGS, ...data }; } } catch { this.settings = { ...DEFAULT_SETTINGS }; } // 同步到 api 运行时配置 setRuntimeConfig(this.settings.apiUrl, this.settings.apiKey, this.settings.namespace); } async saveSettings() { await this.saveData(this.settings, SETTINGS_FILE); setRuntimeConfig(this.settings.apiUrl, this.settings.apiKey, this.settings.namespace); } getSettings() { return this.settings; } // ─── 视图操作 ──────────────────────────────────────────────────── async openMemoryView() { const leaf = this.app.workspace.getLeaf("right"); await leaf.setViewState({ type: MEMORY_VIEW_TYPE, active: true }); this.app.workspace.revealLeaf(leaf); } async openGraphView() { const leaf = this.app.workspace.getLeaf("right"); await leaf.setViewState({ type: GRAPH_VIEW_TYPE, active: true }); this.app.workspace.revealLeaf(leaf); } openSearchModal() { const modal = new SearchModal(this.app); modal.onSelect = (id, content) => { navigator.clipboard.writeText(content).catch(() => {}); (this.app as unknown as { notify: (m: string) => void }).notify( `已复制: ${content.slice(0, 80)}…` ); }; modal.open(); } // 写入记忆模态框 private openWriteModal(initialContent = "") { const { writeMemory } = require("./src/api"); // 使用 Obsidian 的 PromptModal 或简易 confirm const content = initialContent || window.prompt("输入记忆内容:"); if (!content?.trim()) return; const category = window.prompt("分类(可选,如 normal/user_pref/project):", "normal") || "normal"; writeMemory(content.trim(), category, this.settings.namespace) .then(() => { (this.app as unknown as { notify: (m: string) => void }).notify("✅ 记忆已写入织忆"); }) .catch((e: Error) => { (this.app as unknown as { notify: (m: string) => void }).notify(`❌ 写入失败: ${e.message}`); }); } } // ─── 设置页 ──────────────────────────────────────────────────────────────── class ZhiYiSettingTab extends PluginSettingTab { constructor(app: App, private plugin: ZhiYiPlugin) { super(app, plugin); } display() { const { containerEl } = this; containerEl.empty(); containerEl.createEl("h2", { text: "🧠 织忆设置" }); new Setting(containerEl) .setName("API 地址") .setDesc("织忆 Go API 服务地址(默认 http://localhost:7821)") .addText((text) => { text.setPlaceholder("http://localhost:7821") .setValue(this.plugin.getSettings().apiUrl) .onChange(async (val) => { this.plugin.getSettings().apiUrl = val; await this.plugin.saveSettings(); }); }); new Setting(containerEl) .setName("API Key") .setDesc("织忆认证密钥") .addText((text) => { text.setPlaceholder("zhiyi-dev-key-2026") .setValue(this.plugin.getSettings().apiKey) .onChange(async (val) => { this.plugin.getSettings().apiKey = val; await this.plugin.saveSettings(); }); }); new Setting(containerEl) .setName("默认 Namespace") .setDesc("搜索和查询使用的默认命名空间") .addText((text) => { text.setValue(this.plugin.getSettings().namespace) .onChange(async (val) => { this.plugin.getSettings().namespace = val; await this.plugin.saveSettings(); }); }); new Setting(containerEl) .setName("记忆面板") .addButton((btn) => btn.setButtonText("打开 🧠").onClick(() => { (this.plugin as unknown as { openMemoryView: () => void }).openMemoryView(); }) ); new Setting(containerEl) .setName("图谱面板") .addButton((btn) => btn.setButtonText("打开 📐").onClick(() => { (this.plugin as unknown as { openGraphView: () => void }).openGraphView(); }) ); new Setting(containerEl) .setName("说明") .setDesc("Ctrl+P → 织忆 可快速搜索记忆。选中文字后右键或命令面板选择「将选中内容写入织忆」可保存笔记。"); } }