diff --git a/src/completions/service.ts b/src/completions/service.ts index ebc727e..99cf08d 100644 --- a/src/completions/service.ts +++ b/src/completions/service.ts @@ -2,7 +2,7 @@ import { App, Editor } from "obsidian"; import { ProfileService } from "src/profile/service"; import { ProviderFactory } from "src/providers/factory"; import { Suggestion } from "src/extension"; -import { ProviderOptions, Settings } from "src/settings/settings"; +import { ProfileOptions, Settings } from "src/settings/settings"; import { Provider } from "src/providers/provider"; import preparePrompt from "src/completions/prompt"; import { isVimEnabled, isVimInsertMode } from "src/completions/vim"; @@ -79,15 +79,15 @@ export default class CompletionService { } } - private async *complete(editor: Editor, provider: Provider, prompt: string, options: ProviderOptions): AsyncGenerator { + private async *complete(editor: Editor, provider: Provider, prompt: string, options: ProfileOptions): AsyncGenerator { for await (let text of provider.generate(editor, prompt, options)) { text = text.trim(); - if (options.outputLimit.enabled) { + if (this.settings.suggestionControl.outputLimit.enabled) { const sentences = nlp(text).sentences().out('array'); - if (sentences.length > options.outputLimit.sentences) { + if (sentences.length > this.settings.suggestionControl.outputLimit.sentences) { // Take only the first N sentences - text = sentences.slice(0, options.outputLimit.sentences).join(' '); + text = sentences.slice(0, this.settings.suggestionControl.outputLimit.sentences).join(' '); yield { text: text }; break; } diff --git a/src/profile/service.ts b/src/profile/service.ts index 6edae0a..4ee5acd 100644 --- a/src/profile/service.ts +++ b/src/profile/service.ts @@ -48,8 +48,8 @@ export class ProfileService { getOptions(): InlineCompletionOptions { return { - delayMs: this.activeProfile.delayMs, - splitStrategy: this.activeProfile.splitStrategy + delayMs: this.settings.suggestionControl.delayMs, + splitStrategy: this.settings.suggestionControl.splitStrategy }; } diff --git a/src/providers/gemini/provider.ts b/src/providers/gemini/provider.ts index 649780b..ae06177 100644 --- a/src/providers/gemini/provider.ts +++ b/src/providers/gemini/provider.ts @@ -1,7 +1,7 @@ import { GeminiSettings } from "./settings"; import { Provider } from ".."; import { Editor } from "obsidian"; -import { ProviderOptions } from "src/settings/settings"; +import { ProfileOptions } from "src/settings/settings"; import { GoogleGenAI } from "@google/genai"; export class GeminiProvider implements Provider { @@ -16,7 +16,7 @@ export class GeminiProvider implements Provider { }); } - async * generate(editor: Editor, prompt: string, options: ProviderOptions): AsyncGenerator { + async * generate(editor: Editor, prompt: string, options: ProfileOptions): AsyncGenerator { this.aborted = false; const response = await this.client.models.generateContentStream({ diff --git a/src/providers/ollama/provider.ts b/src/providers/ollama/provider.ts index c224fa8..9e803ac 100644 --- a/src/providers/ollama/provider.ts +++ b/src/providers/ollama/provider.ts @@ -2,7 +2,7 @@ import { ModelResponse, Ollama } from "ollama"; import { OllamaSettings } from "./settings"; import { Provider } from ".."; import { Editor } from "obsidian"; -import { ProviderOptions } from "src/settings/settings"; +import { ProfileOptions } from "src/settings/settings"; export class OllamaProvider implements Provider { client: Ollama @@ -14,7 +14,7 @@ export class OllamaProvider implements Provider { this.client = new Ollama({ host: this.settings.host }); } - async *generate(editor: Editor, prompt: string, options: ProviderOptions): AsyncGenerator { + async *generate(editor: Editor, prompt: string, options: ProfileOptions): AsyncGenerator { this.aborted = false; const completionIterator = await this.client.generate({ diff --git a/src/providers/openai-compat/provider.ts b/src/providers/openai-compat/provider.ts index de3158a..4a3641d 100644 --- a/src/providers/openai-compat/provider.ts +++ b/src/providers/openai-compat/provider.ts @@ -1,7 +1,7 @@ import { Provider } from ".."; import { Editor } from "obsidian"; import { OpenAICompatibleSettings } from "."; -import { ProviderOptions } from "src/settings/settings"; +import { ProfileOptions } from "src/settings/settings"; import OpenAI from "openai"; export class OpenAICompatibleProvider implements Provider { @@ -19,7 +19,7 @@ export class OpenAICompatibleProvider implements Provider { }); } - async *generate(editor: Editor, prompt: string, options: ProviderOptions): AsyncGenerator { + async *generate(editor: Editor, prompt: string, options: ProfileOptions): AsyncGenerator { this.aborted = false; this.abortcontroller = new AbortController(); diff --git a/src/providers/openai/provider.ts b/src/providers/openai/provider.ts index 44224fc..3ad53cc 100644 --- a/src/providers/openai/provider.ts +++ b/src/providers/openai/provider.ts @@ -1,7 +1,7 @@ import { Provider } from ".."; import { Editor } from "obsidian"; import { OpenAISettings } from "."; -import { ProviderOptions } from "src/settings/settings"; +import { ProfileOptions } from "src/settings/settings"; import OpenAI from "openai"; export class OpenAIProvider implements Provider { @@ -18,7 +18,7 @@ export class OpenAIProvider implements Provider { }); } - async *generate(editor: Editor, prompt: string, options: ProviderOptions): AsyncGenerator { + async *generate(editor: Editor, prompt: string, options: ProfileOptions): AsyncGenerator { this.aborted = false; this.abortcontroller = new AbortController(); diff --git a/src/providers/provider.ts b/src/providers/provider.ts index 77d881b..677c2dd 100644 --- a/src/providers/provider.ts +++ b/src/providers/provider.ts @@ -1,5 +1,5 @@ import { Editor } from "obsidian"; -import { ProviderOptions } from "src/settings/settings"; +import { ProfileOptions } from "src/settings/settings"; export enum ProviderType { OLLAMA = "ollama", @@ -11,7 +11,7 @@ export enum ProviderType { // Completer interface for ai integrations export interface Provider { settings: any - generate: (editor: Editor, prompt: string, options: ProviderOptions) => AsyncGenerator; + generate: (editor: Editor, prompt: string, options: ProfileOptions) => AsyncGenerator; abort: () => Promise; fetchModels(): Promise | string[]; connectionTest(): Promise; diff --git a/src/settings/settings.ts b/src/settings/settings.ts index c3578fb..4039598 100644 --- a/src/settings/settings.ts +++ b/src/settings/settings.ts @@ -6,7 +6,7 @@ import { OpenAICompatibleSettings } from "src/providers/openai-compat"; import { GeminiSettings } from "src/providers/gemini"; // Completion options for a profile -export interface ProviderOptions { +export interface ProfileOptions { model: string, userPrompt: string, systemPrompt: string, @@ -17,7 +17,7 @@ export interface ProviderOptions { export interface Profile { name: string, provider: ProviderType, - completionOptions: ProviderOptions, + completionOptions: ProfileOptions, } export type ProfileId = string; diff --git a/src/settings/tab.ts b/src/settings/tab.ts index b9cf0a0..5cc958c 100644 --- a/src/settings/tab.ts +++ b/src/settings/tab.ts @@ -9,7 +9,7 @@ import { createProfile } from "."; export default class InscribeSettingsTab extends PluginSettingTab { private generalSection: GeneralSection; - private suggestionSettingsSection: SuggestionSettingsSection; + private suggestionControlSection: SuggestionControlSection; private providersSection: ProvidersSection; private profilesSection: ProfilesSection; private pathConfigsSection: PathConfigsSection; @@ -25,9 +25,9 @@ export default class InscribeSettingsTab extends PluginSettingTab { const generalContainer = document.createElement("div"); this.containerEl.appendChild(generalContainer); - const suggestionSettingsContainer = document.createElement("div"); - suggestionSettingsContainer.addClass("inscribe-section"); - this.containerEl.appendChild(suggestionSettingsContainer); + const suggestionControlContainer = document.createElement("div"); + suggestionControlContainer.addClass("inscribe-section"); + this.containerEl.appendChild(suggestionControlContainer); const providersContainer = document.createElement("div"); providersContainer.addClass("inscribe-section"); @@ -42,13 +42,13 @@ export default class InscribeSettingsTab extends PluginSettingTab { this.containerEl.appendChild(pathMappingsContainer); this.generalSection = new GeneralSection(generalContainer, this.plugin, this.display.bind(this)); - this.suggestionSettingsSection = new SuggestionSettingsSection(suggestionSettingsContainer, this.plugin); + this.suggestionControlSection = new SuggestionControlSection(suggestionControlContainer, this.plugin); this.providersSection = new ProvidersSection(providersContainer, this.app, this.plugin); this.pathConfigsSection = new PathConfigsSection(pathMappingsContainer, this.plugin); this.profilesSection = new ProfilesSection(profilesContainer, this.plugin, this.pathConfigsSection.render.bind(this.pathConfigsSection)); this.generalSection.render(); - this.suggestionSettingsSection.render(); + this.suggestionControlSection.render(); this.providersSection.render(); this.profilesSection.render(); this.pathConfigsSection.render(); @@ -102,7 +102,7 @@ class GeneralSection { } } -class SuggestionSettingsSection { +class SuggestionControlSection { private container: HTMLElement; private plugin: Inscribe; @@ -117,7 +117,7 @@ class SuggestionSettingsSection { // Heading new Setting(this.container) .setHeading() - .setName("Suggestions experience") + .setName("Suggestion control") .setDesc("Configure how completions are triggered and accepted"); // Acceptance Hotkey @@ -127,9 +127,9 @@ class SuggestionSettingsSection { .addText((text) => { text .setPlaceholder("e.g. Tab") - .setValue(this.plugin.settings.suggestionSettings.acceptanceHotkey) + .setValue(this.plugin.settings.suggestionControl.acceptanceHotkey) .onChange(async (value) => { - this.plugin.settings.suggestionSettings.acceptanceHotkey = value; + this.plugin.settings.suggestionControl.acceptanceHotkey = value; await this.plugin.saveSettings(); }); }); @@ -141,9 +141,9 @@ class SuggestionSettingsSection { .addText((text) => { text .setPlaceholder("e.g. Ctrl+Space") - .setValue(this.plugin.settings.suggestionSettings.manualActivationKey || "") + .setValue(this.plugin.settings.suggestionControl.manualActivationKey || "") .onChange(async (value) => { - this.plugin.settings.suggestionSettings.manualActivationKey = value || undefined; + this.plugin.settings.suggestionControl.manualActivationKey = value || undefined; await this.plugin.saveSettings(); }); }); @@ -158,12 +158,51 @@ class SuggestionSettingsSection { .addOption("sentence", "Sentence by Sentence") .addOption("paragraph", "Paragraph by Paragraph") .addOption("full", "Full Completion") - .setValue(this.plugin.settings.suggestionSettings.splitStrategy) + .setValue(this.plugin.settings.suggestionControl.splitStrategy) .onChange(async (value: SplitStrategy) => { - this.plugin.settings.suggestionSettings.splitStrategy = value; + this.plugin.settings.suggestionControl.splitStrategy = value; await this.plugin.saveSettings(); }); }); + + // Suggestion Delay + new Setting(this.container) + .setName("Suggestion delay") + .setDesc("Delay in milliseconds before fetching suggestions") + .addText((text) => { + text.inputEl.setAttr("type", "number"); + text + .setPlaceholder("500") + .setValue(String(this.plugin.settings.suggestionControl.delayMs)) + .onChange(async (value) => { + this.plugin.settings.suggestionControl.delayMs = parseInt(value) || 0; + await this.plugin.saveSettings(); + }); + }); + + // Output Limit + new Setting(this.container) + .setName("Output limit") + .setDesc("Limit the number of sentences in the output") + .addText((text) => { + text.inputEl.setAttr("type", "number"); + text.inputEl.setAttr("min", "1"); + text + .setValue(String(this.plugin.settings.suggestionControl.outputLimit.sentences)) + .onChange(async (value) => { + this.plugin.settings.suggestionControl.outputLimit.sentences = parseInt(value) || 1; + await this.plugin.saveSettings(); + }); + }) + .addToggle((toggle) => { + toggle + .setValue(this.plugin.settings.suggestionControl.outputLimit.enabled) + .onChange(async (value) => { + this.plugin.settings.suggestionControl.outputLimit.enabled = value; + await this.plugin.saveSettings(); + await this.render(); + }); + }); } } @@ -328,21 +367,6 @@ class ProfilesSection { }); }); - // Suggestion Delay - new Setting(this.container) - .setName("Suggestion delay") - .setDesc(`${profile.name} | Delay in milliseconds before fetching suggestions`) - .addText((text) => { - text.inputEl.setAttr("type", "number"); - text - .setPlaceholder("1000") - .setValue(String(profile.delayMs)) - .onChange(async (value) => { - profile.delayMs = parseInt(value); - await this.plugin.saveSettings(); - }); - }); - // System Prompt new Setting(this.container) .setName("System prompt") @@ -386,30 +410,6 @@ class ProfilesSection { ); }); - // Output Limit - new Setting(this.container) - .setName("Output limit") - .setDesc(`${profile.name} | Limit the number of sentences in the output`) - .addText((text) => { - text.inputEl.setAttr("type", "number"); - text.inputEl.setAttr("min", "1"); - text - .setValue(String(profile.completionOptions.outputLimit.sentences)) - .onChange(async (value) => { - profile.completionOptions.outputLimit.sentences = parseInt(value); - await this.plugin.saveSettings(); - }); - }) - .addToggle((toggle) => { - toggle - .setValue(profile.completionOptions.outputLimit.enabled) - .onChange(async (value) => { - profile.completionOptions.outputLimit.enabled = value; - await this.plugin.saveSettings(); - await this.render(); - }); - }) - } private profileDropdown(dropdown: DropdownComponent): void {