diff --git a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarSettings.tsx b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarSettings.tsx index d0f91037..e0d7b664 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarSettings.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarSettings.tsx @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import React, { useEffect, useState } from 'react'; import { useConfigState, useService } from '../util/services.js'; -import { IVoidConfigStateService, nonDefaultConfigFields, PartialVoidConfig, VoidConfig, VoidConfigField, VoidConfigInfo, SetFieldFnType, ConfigState } from '../../../registerConfig.js'; +import { IVoidConfigStateService, allowedProviders, PartialVoidConfig, VoidConfig, VoidConfigField, VoidConfigInfo, SetFieldFnType, ConfigState } from '../../../registerConfig.js'; const SettingOfFieldAndParam = ({ field, param, configState, configStateService }: @@ -93,7 +93,7 @@ export const SidebarSettings = () => {
{/* render all fields, but hide the ones not visible for fast tab switching */} - {nonDefaultConfigFields.map(field => { + {allowedProviders.map(field => { return
{ case 'anthropic': case 'openAI': case 'gemini': - // case 'greptile': + // case 'greptile': + // case 'azure': case 'openRouter': case 'openAICompatible': - case 'azure': default: return `\ You are given the START and END to a piece of code. Please FILL IN THE MIDDLE between the START and END. @@ -496,9 +496,9 @@ export const getFimPrompt: getFimPrompt = ({ voidConfig, prefix, suffix }) => { case 'openAI': case 'gemini': // case 'greptile': + // case 'azure': case 'openRouter': case 'openAICompatible': - case 'azure': default: return `\ ## START: diff --git a/src/vs/workbench/contrib/void/browser/registerConfig.ts b/src/vs/workbench/contrib/void/browser/registerConfig.ts index e86b7724..eff58f6b 100644 --- a/src/vs/workbench/contrib/void/browser/registerConfig.ts +++ b/src/vs/workbench/contrib/void/browser/registerConfig.ts @@ -19,52 +19,15 @@ const _uiConfig = (description: string, defau } -// fields you can customize (don't forget 'default' - it isn't included here!) -export const nonDefaultConfigFields = [ - 'anthropic', - 'openAI', - 'gemini', - // 'greptile', - 'ollama', - 'openRouter', - 'openAICompatible', - 'azure', -] as const - - - -const voidConfigInfo: Record< - typeof nonDefaultConfigFields[number] | 'default', { - [prop: string]: { - description: string; - enumArr?: readonly string[] | undefined; - defaultVal: string; - }; - } -> = { - default: { - whichApi: _uiConfig( - 'API Provider.', - 'anthropic', - nonDefaultConfigFields, - ), - - maxTokens: _uiConfig( - 'Max number of tokens to output.', - '1024', - [ - 'default', // this will be parseInt'd into NaN and ignored by the API. Anything that's not a number has this behavior. - '1024', - '2048', - '4096', - '8192' - ] as const, - ), - - }, +const voidProviderOptions = { anthropic: { - apikey: _uiConfig('Anthropic API key.', ''), - model: _uiConfig( + providerOptions: { + apikey: _uiConfig( + 'Anthropic API key.', + '' + ), + }, + modelOptions: _uiConfig( 'Anthropic model to use.', 'claude-3-5-sonnet-20240620', [ @@ -76,8 +39,13 @@ const voidConfigInfo: Record< ), }, openAI: { - apikey: _uiConfig('OpenAI API key.', ''), - model: _uiConfig( + providerOptions: { + apikey: _uiConfig( + 'OpenAI API key.', + '' + ), + }, + modelOptions: _uiConfig( 'OpenAI model to use.', 'gpt-4o', [ @@ -100,29 +68,70 @@ const voidConfigInfo: Record< 'gpt-3.5-turbo-1106' ] as const ), + }, ollama: { - endpoint: _uiConfig( - 'The endpoint of your Ollama instance.', - 'http://127.0.0.1:11434' - ), - model: _uiConfig( + providerOptions: { + endpoint: _uiConfig( + 'The endpoint of your Ollama instance.', + 'http://127.0.0.1:11434' + ), + }, + modelOptions: _uiConfig( 'Ollama model to use.', 'codestral', ['codestral', 'qwen2.5-coder', 'qwen2.5-coder:0.5b', 'qwen2.5-coder:1.5b', 'qwen2.5-coder:3b', 'qwen2.5-coder:7b', 'qwen2.5-coder:14b', 'qwen2.5-coder:32b', 'codegemma', 'codegemma:2b', 'codegemma:7b', 'codellama', 'codellama:7b', 'codellama:13b', 'codellama:34b', 'codellama:70b', 'codellama:code', 'codellama:python', 'command-r', 'command-r:35b', 'command-r-plus', 'command-r-plus:104b', 'deepseek-coder-v2', 'deepseek-coder-v2:16b', 'deepseek-coder-v2:236b', 'falcon2', 'falcon2:11b', 'firefunction-v2', 'firefunction-v2:70b', 'gemma', 'gemma:2b', 'gemma:7b', 'gemma2', 'gemma2:2b', 'gemma2:9b', 'gemma2:27b', 'llama2', 'llama2:7b', 'llama2:13b', 'llama2:70b', 'llama3', 'llama3:8b', 'llama3:70b', 'llama3-chatqa', 'llama3-chatqa:8b', 'llama3-chatqa:70b', 'llama3-gradient', 'llama3-gradient:8b', 'llama3-gradient:70b', 'llama3.1', 'llama3.1:8b', 'llama3.1:70b', 'llama3.1:405b', 'llava', 'llava:7b', 'llava:13b', 'llava:34b', 'llava-llama3', 'llava-llama3:8b', 'llava-phi3', 'llava-phi3:3.8b', 'mistral', 'mistral:7b', 'mistral-large', 'mistral-large:123b', 'mistral-nemo', 'mistral-nemo:12b', 'mixtral', 'mixtral:8x7b', 'mixtral:8x22b', 'moondream', 'moondream:1.8b', 'openhermes', 'openhermes:v2.5', 'phi3', 'phi3:3.8b', 'phi3:14b', 'phi3.5', 'phi3.5:3.8b', 'qwen', 'qwen:7b', 'qwen:14b', 'qwen:32b', 'qwen:72b', 'qwen:110b', 'qwen2', 'qwen2:0.5b', 'qwen2:1.5b', 'qwen2:7b', 'qwen2:72b', 'smollm', 'smollm:135m', 'smollm:360m', 'smollm:1.7b'] as const ), + }, openRouter: { - model: _uiConfig( + providerOptions: { + apikey: _uiConfig( + 'OpenRouter API key.', + '' + ), + }, + modelOptions: _uiConfig( 'OpenRouter model to use.', 'openai/gpt-4o' ), - apikey: _uiConfig('OpenRouter API key.', ''), + }, openAICompatible: { - endpoint: _uiConfig('The baseUrl (exluding /chat/completions).', 'http://127.0.0.1:11434/v1'), - model: _uiConfig('The name of the model to use.', 'gpt-4o'), - apikey: _uiConfig('Your API key.', ''), + providerOptions: { + apikey: _uiConfig( + 'Your API key.', + '' + ), + endpoint: _uiConfig( + 'The baseUrl (exluding /chat/completions).', + 'http://127.0.0.1:11434/v1' + ), + }, + modelOptions: _uiConfig( + 'The name of the model to use.', + 'gpt-4o' + ), + + }, + gemini: { + providerOptions: { + apikey: _uiConfig( + 'Google API key.', + '' + ), + }, + modelOptions: _uiConfig( + 'Gemini model to use.', + 'gemini-1.5-flash', + [ + 'gemini-1.5-flash', + 'gemini-1.5-pro', + 'gemini-1.5-flash-8b', + 'gemini-1.0-pro' + ] as const + ), + }, // greptile: { @@ -141,74 +150,141 @@ const voidConfigInfo: Record< // }, - azure: { - // 'void.azure.apiKey': { - // 'type': 'string', - // 'description': 'Azure API key.' - // }, - // 'void.azure.deploymentId': { - // 'type': 'string', - // 'description': 'Azure API deployment ID.' - // }, - // 'void.azure.resourceName': { - // 'type': 'string', - // 'description': 'Name of the Azure OpenAI resource. Either this or `baseURL` can be used. \nThe resource name is used in the assembled URL: `https://{resourceName}.openai.azure.com/openai/deployments/{modelId}{path}`' - // }, - // 'void.azure.providerSettings': { - // 'type': 'object', - // 'properties': { - // 'baseURL': { - // 'type': 'string', - // 'default': 'https://${resourceName}.openai.azure.com/openai/deployments', - // 'description': 'Azure API base URL.' - // }, - // 'headers': { - // 'type': 'object', - // 'description': 'Custom headers to include in the requests.' - // } - // } - // }, + // azure: { + // 'void.azure.apiKey': { + // 'type': 'string', + // 'description': 'Azure API key.' + // }, + // 'void.azure.deploymentId': { + // 'type': 'string', + // 'description': 'Azure API deployment ID.' + // }, + // 'void.azure.resourceName': { + // 'type': 'string', + // 'description': 'Name of the Azure OpenAI resource. Either this or `baseURL` can be used. \nThe resource name is used in the assembled URL: `https://{resourceName}.openai.azure.com/openai/deployments/{modelId}{path}`' + // }, + // 'void.azure.providerSettings': { + // 'type': 'object', + // 'properties': { + // 'baseURL': { + // 'type': 'string', + // 'default': 'https://${resourceName}.openai.azure.com/openai/deployments', + // 'description': 'Azure API base URL.' + // }, + // 'headers': { + // 'type': 'object', + // 'description': 'Custom headers to include in the requests.' + // } + // } + // }, + // }, +} as const + +type ProviderName = keyof typeof voidProviderOptions + +const allowedProviders = Object.keys(voidProviderOptions) as ProviderName[] + + +// was whichApi: +const providerOptions = _uiConfig( + 'API Provider.', + 'anthropic', + allowedProviders, +) + +const voidFeatureOptions = { + maxTokens: _uiConfig( + 'Max number of tokens to output.', + 'undefined', + [ + 'undefined', + '1024', + '2048', + '4096', + '8192' + ] as const, + ) +} as const + + +type AllVoidProvidersState = { + [providerName in ProviderName]: { + [option in keyof typeof voidProviderOptions[providerName]['providerOptions']]: string // optionName (e.g. apikey) -> string + } +} + + +// const features = ['ctrl+L', 'ctrl+K', 'autocomplete'] as const +// type FeatureName = (typeof features)[number] + + +// not very important (remember past user options): +// type AllVoidFeaturesState = { +// [featureName in FeatureName]: { +// [providerName in ProviderName]: { +// [modelName in (typeof voidProviderOptions)[providerName]['modelOptions']['defaultVal']]: { +// options: { [option in keyof typeof voidProviderOptions[providerName]]: string } +// } +// } +// } +// } + +type VoidFeatureState< + CtrlLProvider extends ProviderName, + CtrlKProvider extends ProviderName, + AutocompleteProvider extends ProviderName, +> = { + 'ctrl+L': { + provider: CtrlLProvider, + model: (typeof voidProviderOptions)[CtrlLProvider]['modelOptions']['defaultVal'], + // promptTemplate? + // systemTemplate? + // maxTokens? }, - gemini: { - apikey: _uiConfig('Google API key.', ''), - model: _uiConfig( - 'Gemini model to use.', - 'gemini-1.5-flash', - [ - 'gemini-1.5-flash', - 'gemini-1.5-pro', - 'gemini-1.5-flash-8b', - 'gemini-1.0-pro' - ] as const - ), + 'ctrl+K': { + provider: CtrlKProvider, + model: (typeof voidProviderOptions)[CtrlKProvider]['modelOptions']['defaultVal'], + }, + 'autocomplete': { + provider: AutocompleteProvider, + model: (typeof voidProviderOptions)[AutocompleteProvider]['modelOptions']['defaultVal'], }, } + + +const PartialVoidState = { + +} + +const VoidState = {} + + // this is the type that comes with metadata like desc, default val, etc -export type VoidConfigInfo = typeof voidConfigInfo -export type VoidConfigField = keyof typeof voidConfigInfo // typeof configFields[number] +export type VoidConfigInfo = typeof voidProviderOptions +export type VoidConfigField = keyof typeof voidProviderOptions // typeof configFields[number] // this is the type that specifies the user's actual config export type PartialVoidConfig = { - [K in keyof typeof voidConfigInfo]?: { - [P in keyof typeof voidConfigInfo[K]]?: typeof voidConfigInfo[K][P]['defaultVal'] + [K in keyof typeof voidProviderOptions]?: { + [P in keyof typeof voidProviderOptions[K]]?: typeof voidProviderOptions[K][P]['defaultVal'] } } export type VoidConfig = { - [K in keyof typeof voidConfigInfo]: { - [P in keyof typeof voidConfigInfo[K]]: typeof voidConfigInfo[K][P]['defaultVal'] + [K in keyof typeof voidProviderOptions]: { + [P in keyof typeof voidProviderOptions[K]]: typeof voidProviderOptions[K][P]['defaultVal'] } } const getVoidConfig = (partialVoidConfig: PartialVoidConfig): VoidConfig => { const config = {} as PartialVoidConfig - for (const field of [...nonDefaultConfigFields, 'default'] as const) { + for (const field of [...allowedProviders, 'default'] as const) { config[field] = {} - for (const prop in voidConfigInfo[field]) { - config[field][prop] = partialVoidConfig[field]?.[prop]?.trim() || voidConfigInfo[field][prop].defaultVal + for (const prop in voidProviderOptions[field]) { + config[field][prop] = partialVoidConfig[field]?.[prop]?.trim() || voidProviderOptions[field][prop].defaultVal } } return config as VoidConfig @@ -240,7 +316,7 @@ class VoidConfigStateService extends Disposable implements IVoidConfigStateServi readonly onDidChangeState: Event = this._onDidChangeState.event; // this is primarily for use in react, so react can listen + update on state changes state: ConfigState; - readonly voidConfigInfo: VoidConfigInfo = voidConfigInfo; // just putting this here for simplicity, it's static though + readonly voidConfigInfo: VoidConfigInfo = voidProviderOptions; // just putting this here for simplicity, it's static though constructor( @IStorageService private readonly _storageService: IStorageService,