diff --git a/AIClasses/BaseAIClass.ts b/AIClasses/BaseAIClass.ts index 934c5da..b96002b 100644 --- a/AIClasses/BaseAIClass.ts +++ b/AIClasses/BaseAIClass.ts @@ -27,8 +27,6 @@ export abstract class BaseAIClass implements IAIClass { protected readonly settingsService: SettingsService; protected readonly streamingService: StreamingService; - private readonly settingsSubscription: object; - private _systemPrompt: string = ""; private _userInstruction: string = ""; private _agentType: AgentType = AgentType.Main; @@ -42,16 +40,9 @@ export abstract class BaseAIClass implements IAIClass { this.settingsService = Resolve(Services.SettingsService); this.streamingService = Resolve(Services.StreamingService); - this.settingsSubscription = this.settingsService.subscribeToSettingsChanged(() => { - this.apiKey = this.settingsService.getApiKeyForProvider(provider); - }); this.apiKey = this.settingsService.getApiKeyForProvider(provider); } - public dispose(): void { - this.settingsService.unsubscribe(this.settingsSubscription); - } - public get currentProvider(): AIProvider { return this.provider; } diff --git a/Components/ChatInput.svelte b/Components/ChatInput.svelte index 4f22a67..62c5e90 100644 --- a/Components/ChatInput.svelte +++ b/Components/ChatInput.svelte @@ -73,11 +73,13 @@ const diffClosedRef: EventRef = eventService.on(Event.DiffClosed, () => { inputMode = InputMode.Normal; focusInput(); }); const rateLimitCountdownRef: EventRef = eventService.on(Event.RateLimitCountdown, (delayMs: number) => { startCountdown(delayMs); }); - const settingsSubscription: object = settingsService.subscribeToSettingsChanged(() => { - chatMode = settingsService.settings.chatMode; - editsAllowed = chatModeAllowsEdits(chatMode); - if (chatModeButton){ - setIcon(chatModeButton, iconForChatMode(chatMode)); + const settingsSubscription: object = settingsService.subscribeToSettingsChanged(changed => { + if (changed.includes("chatMode")) { + chatMode = settingsService.settings.chatMode; + editsAllowed = chatModeAllowsEdits(chatMode); + if (chatModeButton) { + setIcon(chatModeButton, iconForChatMode(chatMode)); + } } }); diff --git a/Components/ChatModeSelector.svelte b/Components/ChatModeSelector.svelte index d6df2b7..0a31ce6 100644 --- a/Components/ChatModeSelector.svelte +++ b/Components/ChatModeSelector.svelte @@ -12,7 +12,11 @@ const settingsService: SettingsService = Resolve(Services.SettingsService); - const settingsSubscription: object = settingsService.subscribeToSettingsChanged(() => currentChatMode = settingsService.settings.chatMode); + const settingsSubscription: object = settingsService.subscribeToSettingsChanged(changed => { + if (changed.includes("chatMode")) { + currentChatMode = settingsService.settings.chatMode; + } + }); onDestroy(() => settingsService.unsubscribe(settingsSubscription)); diff --git a/Services/ServiceRegistration.ts b/Services/ServiceRegistration.ts index d875bd0..089da2d 100644 --- a/Services/ServiceRegistration.ts +++ b/Services/ServiceRegistration.ts @@ -102,7 +102,7 @@ export function RegisterDependencies() { RegisterAiProvider(); } -function RegisterAiProvider() { +export function RegisterAiProvider() { const settingsService = Resolve(Services.SettingsService); const provider = fromModel(settingsService.settings.model); diff --git a/Services/SettingsService.ts b/Services/SettingsService.ts index 65593e8..ea51752 100644 --- a/Services/SettingsService.ts +++ b/Services/SettingsService.ts @@ -81,12 +81,15 @@ export interface IVaultkeeperAISettings { hideDrawerElements: boolean; } +type SettingKey = keyof IVaultkeeperAISettings; +type SettingsChangedCallback = ((changedKeys: SettingKey[]) => void) | ((changedKeys: SettingKey[]) => Promise); + export class SettingsService { public readonly settings: Readonly; private readonly plugin: VaultkeeperAIPlugin; - private readonly subscribers: WeakMap void) | (() => Promise)> = new WeakMap(); + private readonly subscribers: WeakMap = new WeakMap(); private readonly subscriberRefs: Set> = new Set(); private settingsSnapshot: string; @@ -98,7 +101,7 @@ export class SettingsService { this.ensureValidModels(); } - public subscribeToSettingsChanged(callback: (() => void) | (() => Promise)): object { + public subscribeToSettingsChanged(callback: SettingsChangedCallback): object { const token = {}; this.subscribers.set(token, callback); this.subscriberRefs.add(new WeakRef(token)); @@ -150,17 +153,19 @@ export class SettingsService { } private async saveSettings() { + const oldSettings = JSON.parse(this.settingsSnapshot) as IVaultkeeperAISettings; await this.plugin.saveData(this.settings); - const snapshot = JSON.stringify(this.settings); - if (this.settingsSnapshot !== snapshot) { - this.settingsSnapshot = snapshot; + const changedKeys = (Object.keys(this.settings) as SettingKey[]) + .filter(key => JSON.stringify(this.settings[key]) !== JSON.stringify(oldSettings[key])); + if (changedKeys.length > 0) { + this.settingsSnapshot = JSON.stringify(this.settings); for (const ref of this.subscriberRefs) { const subscriber = ref.deref(); - if (!subscriber) { + if (!subscriber) { this.subscriberRefs.delete(ref); continue; } - await this.subscribers.get(subscriber)?.(); + await this.subscribers.get(subscriber)?.(changedKeys); } } } diff --git a/Views/VaultkeeperAISettingTab.ts b/Views/VaultkeeperAISettingTab.ts index ceb4c6a..39fb90b 100644 --- a/Views/VaultkeeperAISettingTab.ts +++ b/Views/VaultkeeperAISettingTab.ts @@ -11,6 +11,7 @@ import type { SettingsService } from "Services/SettingsService"; import { Services } from "Services/Services"; import { closePluginSettings } from "Helpers/Helpers"; import type { MemoriesService } from "Services/MemoriesService"; +import { RegisterAiProvider } from "Services/ServiceRegistration"; export class VaultkeeperAISettingTab extends PluginSettingTab { private readonly plugin: VaultkeeperAIPlugin; @@ -63,6 +64,7 @@ export class VaultkeeperAISettingTab extends PluginSettingTab { } this.updateFileDisclaimer(); await this.updateModelDropdowns(); + RegisterAiProvider(); }); }); @@ -87,6 +89,7 @@ export class VaultkeeperAISettingTab extends PluginSettingTab { await this.settingsService.updateSettings(settings => { settings.planningModel = value; }); + RegisterAiProvider(); }); }); @@ -105,6 +108,7 @@ export class VaultkeeperAISettingTab extends PluginSettingTab { await this.settingsService.updateSettings(settings => { settings.quickActionModel = value; }); + RegisterAiProvider(); }); }); @@ -120,6 +124,7 @@ export class VaultkeeperAISettingTab extends PluginSettingTab { await this.settingsService.setApiKeyForProvider(fromModel(settings.model), value); }); this.highlightApiKey(); + RegisterAiProvider(); }); text.inputEl.type = "password"; this.apiKeyInputEl = text.inputEl;