state - pick a provider/model

This commit is contained in:
Andrew Pareles 2024-12-10 23:24:36 -08:00
parent b22bbf9639
commit 49b43820b2
2 changed files with 84 additions and 62 deletions

View file

@ -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> = T extends T ? keyof T : never;
export type ProviderSettingName = UnionOfKeys<VoidProviderState[ProviderName]>
export type SettingName = UnionOfKeys<SettingsOfProvider[ProviderName]>
@ -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

View file

@ -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 = <K extends ProviderName>(
type SetSettingOfProviderFn = <K extends ProviderName>(
providerName: K,
option: keyof VoidProviderState[K],
option: keyof SettingsOfProvider[K],
newVal: string
) => Promise<void>;
type SetModelSelectionOfFeature = <K extends FeatureName>(
featureName: K,
newVal: ModelSelectionOfFeature[K],
) => Promise<void>;
type VoidConfigState = {
settingsOfProvider: SettingsOfProvider; // optionsOfProvider
modelSelectionOfFeature: ModelSelectionOfFeature; // stateOfFeature
}
export interface IVoidConfigStateService {
readonly _serviceBrand: undefined;
readonly state: VoidProviderState;
readonly state: VoidConfigState;
onDidChangeState: Event<void>;
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<IVoidConfigStateService>('VoidConfigStateService');
class VoidConfigStateService extends Disposable implements IVoidConfigStateService {
_serviceBrand: undefined;
@ -37,13 +58,7 @@ class VoidConfigStateService extends Disposable implements IVoidConfigStateServi
private readonly _onDidChangeState = new Emitter<void>();
readonly onDidChangeState: Event<void> = 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<VoidProviderState> {
const encryptedPartialConfig = this._storageService.get(VOID_CONFIG_KEY, StorageScope.APPLICATION)
private async _readVoidConfigState(): Promise<VoidConfigState> {
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()
}