From 49b43820b28f9ff69fe67ca90c1d57976de6c7e5 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Tue, 10 Dec 2024 23:24:36 -0800 Subject: [PATCH] state - pick a provider/model --- src/vs/platform/void/common/configTypes.ts | 50 ++++------ .../contrib/void/browser/registerConfig.ts | 96 ++++++++++++------- 2 files changed, 84 insertions(+), 62 deletions(-) diff --git a/src/vs/platform/void/common/configTypes.ts b/src/vs/platform/void/common/configTypes.ts index 37da9dd2..df4c8b46 100644 --- a/src/vs/platform/void/common/configTypes.ts +++ b/src/vs/platform/void/common/configTypes.ts @@ -47,7 +47,7 @@ export const voidProviderDefaults = { export const voidInitModelOptions = { anthropic: () => ({ - model: 'claude-3-5-sonnet-20240620', + // model: 'claude-3-5-sonnet-20240620', models: [ 'claude-3-5-sonnet-20240620', 'claude-3-opus-20240229', @@ -56,7 +56,7 @@ export const voidInitModelOptions = { ], }), openAI: () => ({ - model: 'gpt-4o', + // model: 'gpt-4o', models: [ 'o1-preview', 'o1-mini', @@ -78,7 +78,7 @@ export const voidInitModelOptions = { ], }), ollama: () => ({ // TODO make this do a fetch to get the models - model: 'codestral', + // model: 'codestral', models: [ 'codestral', 'qwen2.5-coder', @@ -177,15 +177,15 @@ export const voidInitModelOptions = { ], }), openRouter: () => ({ - model: 'openai/gpt-4o', + // model: 'openai/gpt-4o', models: null, // any }), openAICompatible: () => ({ - model: 'openai/gpt-4o', + // model: 'openai/gpt-4o', models: null, // any }), gemini: () => ({ - model: 'gemini-1.5-flash', + // model: 'gemini-1.5-flash', models: [ 'gemini-1.5-flash', 'gemini-1.5-pro', @@ -194,7 +194,7 @@ export const voidInitModelOptions = { ], }), groq: () => ({ - model: 'mixtral-8x7b-32768', + // model: 'mixtral-8x7b-32768', models: [ "mixtral-8x7b-32768", "llama2-70b-4096", @@ -210,7 +210,8 @@ export const providerNames = Object.keys(voidProviderDefaults) as ProviderName[] -export type VoidProviderState = { +// state +export type SettingsOfProvider = { [providerName in ProviderName]: ( { [optionName in keyof typeof voidProviderDefaults[providerName]]: string @@ -221,14 +222,13 @@ export type VoidProviderState = { maxTokens: string, models: string[] | null, // if null, user can type in any string as a model - model: string, }) } type UnionOfKeys = T extends T ? keyof T : never; -export type ProviderSettingName = UnionOfKeys +export type SettingName = UnionOfKeys @@ -238,7 +238,7 @@ type DisplayInfo = { placeholder: string, } -export const displayInfoOfSettingName = (providerName: ProviderName, settingName: ProviderSettingName): DisplayInfo => { +export const displayInfoOfSettingName = (providerName: ProviderName, settingName: SettingName): DisplayInfo => { if (settingName === 'apiKey') { return { title: 'API Key', @@ -270,13 +270,6 @@ export const displayInfoOfSettingName = (providerName: ProviderName, settingName placeholder: '1024', } } - else if (settingName === 'model') { - return { - title: 'Model', - type: '(never)', - placeholder: '(never)', - } - } else if (settingName === 'enabled') { return { title: 'Enabled?', @@ -298,7 +291,7 @@ export const displayInfoOfSettingName = (providerName: ProviderName, settingName -export const defaultVoidProviderState: VoidProviderState = { +export const defaultVoidProviderState: SettingsOfProvider = { anthropic: { ...voidProviderDefaults.anthropic, ...voidInitModelOptions.anthropic(), @@ -345,22 +338,21 @@ export const defaultVoidProviderState: VoidProviderState = { - - -type VoidFeatureState = { +// this is a state +export type ModelSelectionOfFeature = { 'Ctrl+L': { - provider: ProviderName, - model: string, + providerName: ProviderName, + modelName: string, } | null, 'Ctrl+K': { - provider: ProviderName, - model: string, + providerName: ProviderName, + modelName: string, } | null, 'Autocomplete': { - provider: ProviderName, - model: string, + providerName: ProviderName, + modelName: string, } | null, } -export type FeatureName = keyof VoidFeatureState +export type FeatureName = keyof ModelSelectionOfFeature export const featureNames = ['Ctrl+L', 'Ctrl+K', 'Autocomplete'] as const diff --git a/src/vs/workbench/contrib/void/browser/registerConfig.ts b/src/vs/workbench/contrib/void/browser/registerConfig.ts index a8d1884d..a2a3e504 100644 --- a/src/vs/workbench/contrib/void/browser/registerConfig.ts +++ b/src/vs/workbench/contrib/void/browser/registerConfig.ts @@ -10,26 +10,47 @@ import { IEncryptionService } from '../../../../platform/encryption/common/encry import { registerSingleton, InstantiationType } from '../../../../platform/instantiation/common/extensions.js'; import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js'; import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js'; -import { defaultVoidProviderState, ProviderName, VoidProviderState } from '../../../../platform/void/common/configTypes.js'; +import { defaultVoidProviderState, FeatureName, ProviderName, ModelSelectionOfFeature, SettingsOfProvider } from '../../../../platform/void/common/configTypes.js'; -const VOID_CONFIG_KEY = 'void.partialVoidConfig' +const CONFIG_STORAGE_KEY = 'void.voidConfigStateII' -type SetStateFn = ( +type SetSettingOfProviderFn = ( providerName: K, - option: keyof VoidProviderState[K], + option: keyof SettingsOfProvider[K], newVal: string ) => Promise; +type SetModelSelectionOfFeature = ( + featureName: K, + newVal: ModelSelectionOfFeature[K], +) => Promise; + + +type VoidConfigState = { + settingsOfProvider: SettingsOfProvider; // optionsOfProvider + modelSelectionOfFeature: ModelSelectionOfFeature; // stateOfFeature +} export interface IVoidConfigStateService { readonly _serviceBrand: undefined; - readonly state: VoidProviderState; + readonly state: VoidConfigState; onDidChangeState: Event; - setState: SetStateFn; + setSettingOfProvider: SetSettingOfProviderFn; + setModelSelectionOfFeature: SetModelSelectionOfFeature; } + +const defaultState = () => { + const d: VoidConfigState = { + settingsOfProvider: deepClone(defaultVoidProviderState), + modelSelectionOfFeature: { 'Ctrl+L': null, 'Ctrl+K': null, 'Autocomplete': null } + } + return d +} + + export const IVoidConfigStateService = createDecorator('VoidConfigStateService'); class VoidConfigStateService extends Disposable implements IVoidConfigStateService { _serviceBrand: undefined; @@ -37,13 +58,7 @@ class VoidConfigStateService extends Disposable implements IVoidConfigStateServi private readonly _onDidChangeState = new Emitter(); readonly onDidChangeState: Event = this._onDidChangeState.event; // this is primarily for use in react, so react can listen + update on state changes - state: VoidProviderState; - - // readonly voidConfigInfo: VoidConfigInfo = voidConfigInfo; // just putting this here for simplicity, it's static though - get _defaultState() { - return deepClone(defaultVoidProviderState) - } - + state: VoidConfigState; constructor( @IStorageService private readonly _storageService: IStorageService, @@ -53,50 +68,65 @@ class VoidConfigStateService extends Disposable implements IVoidConfigStateServi ) { super() - // at the start, we haven't read the partial config yet, but we need to set state to something, just treat partialVoidConfig like it's empty - this.state = this._defaultState + // at the start, we haven't read the partial config yet, but we need to set state to something + this.state = defaultState() // read and update the actual state immediately - this._readVoidConfigState().then(voidConfigState => { - this._setState(voidConfigState) - }) + this._readVoidConfigState().then(voidConfigState => { this._setState(voidConfigState) }) } - - - private async _readVoidConfigState(): Promise { - const encryptedPartialConfig = this._storageService.get(VOID_CONFIG_KEY, StorageScope.APPLICATION) + private async _readVoidConfigState(): Promise { + const encryptedPartialConfig = this._storageService.get(CONFIG_STORAGE_KEY, StorageScope.APPLICATION) if (!encryptedPartialConfig) - return this._defaultState + return defaultState() const voidConfigStateStr = await this._encryptionService.decrypt(encryptedPartialConfig) return JSON.parse(voidConfigStateStr) } - private async _storeVoidConfigState(voidConfigState: VoidProviderState) { + private async _storeVoidConfigState(voidConfigState: VoidConfigState) { const encryptedVoidConfigStr = await this._encryptionService.encrypt(JSON.stringify(voidConfigState)) - this._storageService.store(VOID_CONFIG_KEY, encryptedVoidConfigStr, StorageScope.APPLICATION, StorageTarget.USER) + this._storageService.store(CONFIG_STORAGE_KEY, encryptedVoidConfigStr, StorageScope.APPLICATION, StorageTarget.USER) } - - // Set field on PartialVoidConfig - setState: SetStateFn = async (providerName, option, newVal) => { - const newState: VoidProviderState = { + setSettingOfProvider: SetSettingOfProviderFn = async (providerName, option, newVal) => { + const newState: VoidConfigState = { ...this.state, - [providerName]: { - ...this.state[providerName], - [option]: newVal, + settingsOfProvider: { + ...this.state.settingsOfProvider, + [providerName]: { + ...this.state.settingsOfProvider[providerName], + [option]: newVal, + } } } + console.log('NEW STATE I', newState) + await this._storeVoidConfigState(newState) this._setState(newState) } + setModelSelectionOfFeature: SetModelSelectionOfFeature = async (featureName, newVal) => { + const newState: VoidConfigState = { + ...this.state, + modelSelectionOfFeature: { + ...this.state.modelSelectionOfFeature, + [featureName]: newVal + } + } + console.log('NEW STATE II', newState) + + await this._storeVoidConfigState(newState) + this._setState(newState) + } + + + // internal function to update state, should be called every time state changes - private async _setState(voidConfigState: VoidProviderState) { + private async _setState(voidConfigState: VoidConfigState) { this.state = voidConfigState this._onDidChangeState.fire() }