diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..46eaad0 --- /dev/null +++ b/src/config.ts @@ -0,0 +1,114 @@ +import { Ollama } from 'ollama/browser'; +import * as vscode from 'vscode'; + +const CONFIG_NAMESPACE = 'ai-code'; + +const KEY_OLLAMA_HOST = 'ollamaHost'; +const KEY_INLINE_COMPLETION_MODEL = 'inlineCompletion.model'; +const KEY_INLINE_COMPLETION_PREFIX_START = 'inlineCompletion.prefixStart'; +const KEY_INLINE_COMPLETION_PREFIX_END = 'inlineCompletion.prefixEnd'; +const KEY_INLINE_COMPLETION_SUFFIX_START = 'inlineCompletion.suffixStart'; +const KEY_INLINE_COMPLETION_SUFFIX_END = 'inlineCompletion.suffixEnd'; +const KEY_INLINE_COMPLETION_MAX_TOKENS = 'inlineCompletion.maxTokens'; +const KEY_INLINE_COMPLETION_GENERATION_TIMEOUT = 'inlineCompletion.generationTimeout'; +const KEY_INLINE_COMPLETION_TRIE_PRUNE_TIMEOUT = 'inlineCompletion.triePruneTimeout'; + +const MODEL = 'deepseek-coder:6.7b'; + +const PREFIX_START = ''; +const PREFIX_ENDS = ['', '', '', '']; + +const SUFFIX_START = ''; +const SUFFIX_END = ''; + +const MAX_TOKENS = 50; +const GENERATION_TIMEOUT = 200; +const TRIE_PRUNE_TIMEOUT = 10000; + +interface ExtensionConfiguration { + ollamaHost: string | undefined + inlineCompletion: { + model: string + prefixStart: string + prefixEnds: string[] + suffixStart: string + suffixEnd: string + maxTokens: number + generationTimeout: number + triePruneTimeout: number + } +}; + +export interface ExtensionState { + configuration: ExtensionConfiguration + ollama: Ollama +} + +export const getExtensionState = (): ExtensionState => { + const extensionConfig = vscode.workspace.getConfiguration(CONFIG_NAMESPACE); + + const configuration: ExtensionConfiguration = { + ollamaHost: extensionConfig.get(KEY_OLLAMA_HOST), + inlineCompletion: { + model: extensionConfig.get(KEY_INLINE_COMPLETION_MODEL) ?? MODEL, + prefixStart: extensionConfig.get(KEY_INLINE_COMPLETION_PREFIX_START) ?? PREFIX_START, + prefixEnds: extensionConfig.get(KEY_INLINE_COMPLETION_PREFIX_END)?.split(',') ?? PREFIX_ENDS, + suffixStart: extensionConfig.get(KEY_INLINE_COMPLETION_SUFFIX_START) ?? SUFFIX_START, + suffixEnd: extensionConfig.get(KEY_INLINE_COMPLETION_SUFFIX_END) ?? SUFFIX_END, + maxTokens: extensionConfig.get(KEY_INLINE_COMPLETION_MAX_TOKENS) ?? MAX_TOKENS, + generationTimeout: extensionConfig.get(KEY_INLINE_COMPLETION_GENERATION_TIMEOUT) ?? GENERATION_TIMEOUT, + triePruneTimeout: extensionConfig.get(KEY_INLINE_COMPLETION_TRIE_PRUNE_TIMEOUT) ?? TRIE_PRUNE_TIMEOUT, + }, + }; + + const state: ExtensionState = { + ollama: new Ollama({ + host: configuration.ollamaHost, + }), + configuration, + }; + + + vscode.workspace.onDidChangeConfiguration((event) => { + if (event.affectsConfiguration(`${CONFIG_NAMESPACE}.${KEY_OLLAMA_HOST}`)) { + configuration.ollamaHost = extensionConfig.get(KEY_OLLAMA_HOST); + state.ollama = new Ollama({ + host: configuration.ollamaHost, + }); + } + + if (event.affectsConfiguration(`${CONFIG_NAMESPACE}.${KEY_INLINE_COMPLETION_MODEL}`)) { + configuration.inlineCompletion.model = extensionConfig.get(KEY_INLINE_COMPLETION_MODEL) ?? MODEL; + } + + if (event.affectsConfiguration(`${CONFIG_NAMESPACE}.${KEY_INLINE_COMPLETION_PREFIX_START}`)) { + configuration.inlineCompletion.prefixStart = extensionConfig.get(KEY_INLINE_COMPLETION_PREFIX_START) ?? PREFIX_START; + } + + if (event.affectsConfiguration(`${CONFIG_NAMESPACE}.${KEY_INLINE_COMPLETION_PREFIX_END}`)) { + configuration.inlineCompletion.prefixEnds = extensionConfig.get(KEY_INLINE_COMPLETION_PREFIX_END)?.split(',') ?? PREFIX_ENDS; + } + + if (event.affectsConfiguration(`${CONFIG_NAMESPACE}.${KEY_INLINE_COMPLETION_SUFFIX_START}`)) { + configuration.inlineCompletion.suffixStart = extensionConfig.get(KEY_INLINE_COMPLETION_SUFFIX_START) ?? SUFFIX_START; + } + + if (event.affectsConfiguration(`${CONFIG_NAMESPACE}.${KEY_INLINE_COMPLETION_SUFFIX_END}`)) { + configuration.inlineCompletion.suffixEnd = extensionConfig.get(KEY_INLINE_COMPLETION_SUFFIX_END) ?? SUFFIX_END; + } + + if (event.affectsConfiguration(`${CONFIG_NAMESPACE}.${KEY_INLINE_COMPLETION_MAX_TOKENS}`)) { + configuration.inlineCompletion.maxTokens = extensionConfig.get(KEY_INLINE_COMPLETION_MAX_TOKENS) ?? MAX_TOKENS; + } + + if (event.affectsConfiguration(`${CONFIG_NAMESPACE}.${KEY_INLINE_COMPLETION_GENERATION_TIMEOUT}`)) { + configuration.inlineCompletion.generationTimeout = extensionConfig.get(KEY_INLINE_COMPLETION_GENERATION_TIMEOUT) ?? GENERATION_TIMEOUT; + } + + if (event.affectsConfiguration(`${CONFIG_NAMESPACE}.${KEY_INLINE_COMPLETION_TRIE_PRUNE_TIMEOUT}`)) { + configuration.inlineCompletion.triePruneTimeout = extensionConfig.get(KEY_INLINE_COMPLETION_TRIE_PRUNE_TIMEOUT) ?? TRIE_PRUNE_TIMEOUT; + } + }); + + return state; +}; diff --git a/src/extension.ts b/src/extension.ts index 05632e1..5591d49 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,108 +1,8 @@ // The module 'vscode' contains the VS Code extensibility API // Import the module and reference it with the alias vscode in your code below import * as vscode from 'vscode'; -import { Ollama } from 'ollama/browser'; import { flattenTrie, trieInsert, trieLookup, TrieNode, triePrune } from './trie'; - -const MODEL = 'deepseek-coder:6.7b'; - -const PREFIX_START = ''; -const PREFIX_ENDS = ['', '', '', '']; - -const SUFFIX_START = ''; -const SUFFIX_END = ''; - -const MAX_TOKENS = 50; -const GENERATION_TIMEOUT = 200; -const TRIE_PRUNE_TIMEOUT = 10000; - -interface ExtensionConfiguration { - ollamaHost: string | undefined - inlineCompletion: { - model: string - prefixStart: string - prefixEnds: string[] - suffixStart: string - suffixEnd: string - maxTokens: number - generationTimeout: number - triePruneTimeout: number - } -}; - -interface ExtensionState { - configuration: ExtensionConfiguration - ollama: Ollama -} - -const getExtensionState = (): ExtensionState => { - const extensionConfig = vscode.workspace.getConfiguration('ai-code'); - - const configuration: ExtensionConfiguration = { - ollamaHost: extensionConfig.get('ollamaHost'), - inlineCompletion: { - model: extensionConfig.get('inlineCompletion.prefixStart') ?? MODEL, - prefixStart: extensionConfig.get('inlineCompletion.prefixStart') ?? PREFIX_START, - prefixEnds: extensionConfig.get('inlineCompletion.prefixEnd')?.split(',') ?? PREFIX_ENDS, - suffixStart: extensionConfig.get('inlineCompletion.suffixStart') ?? SUFFIX_START, - suffixEnd: extensionConfig.get('inlineCompletion.suffixEnd') ?? SUFFIX_END, - maxTokens: extensionConfig.get('inlineCompletion.maxTokens') ?? MAX_TOKENS, - generationTimeout: extensionConfig.get('inlineCompletion.generationTimeout') ?? GENERATION_TIMEOUT, - triePruneTimeout: extensionConfig.get('inlineCompletion.triePruneTimeout') ?? TRIE_PRUNE_TIMEOUT, - }, - }; - - const state: ExtensionState = { - ollama: new Ollama({ - host: configuration.ollamaHost, - }), - configuration, - }; - - - vscode.workspace.onDidChangeConfiguration((event) => { - if (event.affectsConfiguration("ai-code.ollamaHost")) { - configuration.ollamaHost = extensionConfig.get('ollamaHost'); - state.ollama = new Ollama({ - host: configuration.ollamaHost, - }); - } - - if (event.affectsConfiguration("inlineCompletion.prefixStart")) { - configuration.inlineCompletion.model = extensionConfig.get('inlineCompletion.prefixStart') ?? MODEL; - } - - if (event.affectsConfiguration("inlineCompletion.prefixStart")) { - configuration.inlineCompletion.prefixStart = extensionConfig.get('inlineCompletion.prefixStart') ?? PREFIX_START; - } - - if (event.affectsConfiguration("inlineCompletion.prefixEnd")) { - configuration.inlineCompletion.prefixEnds = extensionConfig.get('inlineCompletion.prefixEnd')?.split(',') ?? PREFIX_ENDS; - } - - if (event.affectsConfiguration("inlineCompletion.suffixStart")) { - configuration.inlineCompletion.suffixStart = extensionConfig.get('inlineCompletion.suffixStart') ?? SUFFIX_START; - } - - if (event.affectsConfiguration("inlineCompletion.suffixEnd")) { - configuration.inlineCompletion.suffixEnd = extensionConfig.get('inlineCompletion.suffixEnd') ?? SUFFIX_END; - } - - if (event.affectsConfiguration("inlineCompletion.maxTokens")) { - configuration.inlineCompletion.maxTokens = extensionConfig.get('inlineCompletion.maxTokens') ?? MAX_TOKENS; - } - - if (event.affectsConfiguration("inlineCompletion.generationTimeout")) { - configuration.inlineCompletion.generationTimeout = extensionConfig.get('inlineCompletion.generationTimeout') ?? GENERATION_TIMEOUT; - } - - if (event.affectsConfiguration("inlineCompletion.triePruneTimeout")) { - configuration.inlineCompletion.triePruneTimeout = extensionConfig.get('inlineCompletion.triePruneTimeout') ?? TRIE_PRUNE_TIMEOUT; - } - }); - - return state; -}; +import { ExtensionState, getExtensionState } from './config'; const getModelSupportsSuffix = async (extension: ExtensionState, model: string) => { // TODO: get if model supports suffixes and use that if available