diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/chat-history.ts | 24 | ||||
| -rw-r--r-- | src/chat-view.ts | 110 | ||||
| -rw-r--r-- | src/global.d.ts | 7 | ||||
| -rw-r--r-- | src/main.ts | 69 | ||||
| -rw-r--r-- | src/settings.ts | 12 |
5 files changed, 0 insertions, 222 deletions
diff --git a/src/chat-history.ts b/src/chat-history.ts deleted file mode 100644 index ac7c6a8..0000000 --- a/src/chat-history.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { ChatMessage } from "./ollama-client"; -import type { PersistedMessage } from "./settings"; - -export type { PersistedMessage } from "./settings"; - -/** - * Filter ChatMessage[] down to only persistable user/assistant messages. - */ -export function toPersistableMessages(messages: readonly ChatMessage[]): PersistedMessage[] { - const result: PersistedMessage[] = []; - for (const msg of messages) { - if (msg.role === "user" || msg.role === "assistant") { - result.push({ role: msg.role, content: msg.content }); - } - } - return result; -} - -/** - * Convert persisted messages back to ChatMessage[] for the LLM context. - */ -export function toRuntimeMessages(messages: readonly PersistedMessage[]): ChatMessage[] { - return messages.map((m) => ({ role: m.role, content: m.content })); -} diff --git a/src/chat-view.ts b/src/chat-view.ts index dd27c63..55b730d 100644 --- a/src/chat-view.ts +++ b/src/chat-view.ts @@ -7,8 +7,6 @@ import { ToolModal } from "./tool-modal"; import { TOOL_REGISTRY } from "./tools"; import type { OllamaToolDefinition } from "./tools"; import { collectVaultContext, formatVaultContext } from "./vault-context"; -import { toRuntimeMessages, toPersistableMessages } from "./chat-history"; -import type { PersistedMessage } from "./chat-history"; export const VIEW_TYPE_CHAT = "ai-pulse-chat"; @@ -21,7 +19,6 @@ export class ChatView extends ItemView { private toolsButton: HTMLButtonElement | null = null; private abortController: AbortController | null = null; private scrollDebounceTimer: ReturnType<typeof setTimeout> | null = null; - private saveDebounceTimer: ReturnType<typeof setTimeout> | null = null; private bubbleContent: Map<HTMLDivElement, string> = new Map(); private modelBadge: HTMLDivElement | null = null; @@ -116,9 +113,6 @@ export class ChatView extends ItemView { if (this.messageContainer !== null) { this.messageContainer.empty(); } - this.plugin.settings.chatHistory = []; - this.plugin.updateChatSnapshot([]); - void this.plugin.saveSettings(); (document.activeElement as HTMLElement)?.blur(); }); @@ -148,22 +142,12 @@ export class ChatView extends ItemView { // Auto-connect on open void this.plugin.connect(); - - // Restore persisted chat history - void this.restoreChatHistory(); } async onClose(): Promise<void> { if (this.abortController !== null) { this.abortController.abort(); } - if (this.saveDebounceTimer !== null) { - clearTimeout(this.saveDebounceTimer); - this.saveDebounceTimer = null; - } - // Save any pending history before closing - this.plugin.settings.chatHistory = toPersistableMessages(this.messages); - void this.plugin.saveSettings(); this.contentEl.empty(); this.messages = []; this.bubbleContent.clear(); @@ -235,7 +219,6 @@ export class ChatView extends ItemView { // Track in message history this.messages.push({ role: "user", content: text }); - this.saveChatHistoryDebounced(); // Switch to streaming state this.abortController = new AbortController(); @@ -337,7 +320,6 @@ export class ChatView extends ItemView { await this.finalizeBubble(currentBubble); } this.messages.push({ role: "assistant", content: response }); - this.saveChatHistoryDebounced(); this.scrollToBottom(); } catch (err: unknown) { const isAbort = err instanceof DOMException && err.name === "AbortError"; @@ -755,98 +737,6 @@ export class ChatView extends ItemView { } } - /** - * Save chat history with debouncing to avoid excessive writes. - */ - private saveChatHistoryDebounced(): void { - if (this.saveDebounceTimer !== null) { - clearTimeout(this.saveDebounceTimer); - } - this.saveDebounceTimer = setTimeout(() => { - this.saveDebounceTimer = null; - const persistable = toPersistableMessages(this.messages); - this.plugin.settings.chatHistory = persistable; - // Update the plugin's snapshot so the sync checker doesn't treat - // our own save as an external change. - this.plugin.updateChatSnapshot(persistable); - void this.plugin.saveSettings(); - }, 500); - } - - /** - * Restore chat history from the persisted file and render messages. - */ - private async restoreChatHistory(): Promise<void> { - const persisted = this.plugin.settings.chatHistory; - if (persisted.length === 0) return; - - this.messages = toRuntimeMessages(persisted); - this.plugin.updateChatSnapshot(persisted); - await this.renderPersistedMessages(persisted); - this.scrollToBottom(); - } - - /** - * Render persisted messages into the chat container. - * User messages are shown as plain text; assistant messages are rendered as markdown. - */ - private async renderPersistedMessages(messages: PersistedMessage[]): Promise<void> { - if (this.messageContainer === null) return; - - for (const msg of messages) { - if (msg.role === "user") { - this.messageContainer.createDiv({ - cls: "ai-pulse-message user", - text: msg.content, - }); - } else if (msg.role === "assistant") { - const bubble = this.messageContainer.createDiv({ - cls: "ai-pulse-message assistant ai-pulse-markdown", - }); - await MarkdownRenderer.render( - this.plugin.app, - msg.content, - bubble, - "", - this, - ); - - // Wire up internal [[wiki-links]] so they navigate on click - bubble.querySelectorAll("a.internal-link").forEach((link) => { - link.addEventListener("click", (evt) => { - evt.preventDefault(); - const href = link.getAttribute("href"); - if (href !== null) { - void this.plugin.app.workspace.openLinkText(href, "", false); - } - }); - }); - } - } - } - - /** - * Reload chat history from disk (e.g., after an external sync). - * Replaces the current messages and re-renders the UI. - */ - async reloadChatHistory(): Promise<void> { - const persisted = this.plugin.settings.chatHistory; - - // Skip reload if we're currently streaming — avoid disrupting the UI - if (this.abortController !== null) return; - - this.messages = toRuntimeMessages(persisted); - this.bubbleContent.clear(); - if (this.messageContainer !== null) { - this.messageContainer.empty(); - } - - if (persisted.length > 0) { - await this.renderPersistedMessages(persisted); - this.scrollToBottom(); - } - } - private scrollToBottom(): void { if (this.messageContainer === null) return; const lastChild = this.messageContainer.lastElementChild; diff --git a/src/global.d.ts b/src/global.d.ts deleted file mode 100644 index bc5e7ae..0000000 --- a/src/global.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type _moment from "moment"; - -declare global { - interface Window { - moment: typeof _moment; - } -} diff --git a/src/main.ts b/src/main.ts index e09cf56..12dadaf 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,7 +4,6 @@ import { DEFAULT_SETTINGS } from "./settings"; import { ChatView, VIEW_TYPE_CHAT } from "./chat-view"; import { testConnection, listModels } from "./ollama-client"; import { getDefaultToolStates } from "./tools"; -import type { PersistedMessage } from "./chat-history"; export default class AIPulse extends Plugin { settings: AIPulseSettings = DEFAULT_SETTINGS; @@ -14,9 +13,6 @@ export default class AIPulse extends Plugin { connectionMessage = ""; availableModels: string[] = []; - // Snapshot of persisted chat history for sync change detection - private lastChatSnapshot = ""; - async onload(): Promise<void> { await this.loadSettings(); @@ -33,18 +29,6 @@ export default class AIPulse extends Plugin { void this.activateView(); }, }); - - // Detect chat history changes from Obsidian Sync or other devices. - // We check when the app regains visibility (user switches back from another app/device). - this.registerDomEvent(document, "visibilitychange", () => { - if (document.visibilityState === "visible") { - // Reload settings from disk in case Obsidian Sync updated data.json - // while the app was in the background. - void this.loadSettings().then(() => { - this.checkChatHistorySync(); - }); - } - }); } onunload(): void { @@ -88,47 +72,6 @@ export default class AIPulse extends Plugin { await this.saveData(this.settings); } - /** - * Called by Obsidian when data.json is modified externally (e.g., via Sync). - * Reloads settings (which now include chat history) and syncs the chat view. - */ - async onExternalSettingsChange(): Promise<void> { - await this.loadSettings(); - this.checkChatHistorySync(); - } - - /** - * Check if the persisted chat history has changed (e.g., from another device) - * and reload the chat view if needed. - */ - checkChatHistorySync(): void { - try { - const persisted = this.settings.chatHistory; - const snapshot = buildChatSnapshot(persisted); - - if (snapshot === this.lastChatSnapshot) return; - this.lastChatSnapshot = snapshot; - - // Find the active chat view and reload it - const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_CHAT); - for (const leaf of leaves) { - const view = leaf.view; - if (view instanceof ChatView) { - void view.reloadChatHistory(); - } - } - } catch { - // Silently ignore — sync check is best-effort - } - } - - /** - * Update the snapshot after a local save so we don't trigger a false reload. - */ - updateChatSnapshot(messages: PersistedMessage[]): void { - this.lastChatSnapshot = buildChatSnapshot(messages); - } - async connect(): Promise<void> { this.connectionStatus = "connecting"; this.connectionMessage = "Connecting..."; @@ -156,15 +99,3 @@ export default class AIPulse extends Plugin { } } } - -/** - * Build a lightweight snapshot string of chat messages for change detection. - * Uses message count + last message content hash to detect changes - * without deep comparison. - */ -function buildChatSnapshot(messages: PersistedMessage[]): string { - if (messages.length === 0) return "empty"; - const last = messages[messages.length - 1]; - if (last === undefined) return "empty"; - return `${messages.length}:${last.role}:${last.content.length}:${last.content.slice(0, 100)}`; -} diff --git a/src/settings.ts b/src/settings.ts index ab20416..c61af9d 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -1,15 +1,5 @@ import { getDefaultToolStates } from "./tools"; -/** - * A message stored in the persisted chat history. - * Only user and assistant messages are persisted — system and tool messages - * are transient (injected per-request by the agent loop). - */ -export interface PersistedMessage { - role: "user" | "assistant"; - content: string; -} - export interface AIPulseSettings { ollamaUrl: string; model: string; @@ -21,7 +11,6 @@ export interface AIPulseSettings { systemPromptFile: string; injectVaultContext: boolean; vaultContextRecentFiles: number; - chatHistory: PersistedMessage[]; } export const DEFAULT_SETTINGS: AIPulseSettings = { @@ -35,5 +24,4 @@ export const DEFAULT_SETTINGS: AIPulseSettings = { systemPromptFile: "agent.md", injectVaultContext: false, vaultContextRecentFiles: 20, - chatHistory: [], }; |
