diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index c42e3446..64129df3 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -14,8 +14,6 @@ There are a few ways to contribute:
We highly recommend reading [this](https://github.com/microsoft/vscode/wiki/Source-Code-Organization) article on VSCode's sourcecode organization.
-We are currently putting together our own articles on VSCode and Void's sourcecode organization. The best way to get this information right now is by attending a weekly meeting.
-
diff --git a/create-appimage.sh b/create-appimage.sh
new file mode 100644
index 00000000..c79a351c
--- /dev/null
+++ b/create-appimage.sh
@@ -0,0 +1,112 @@
+#!/bin/bash
+set -e # Exit on error
+set -x # Print commands as they are executed
+
+# Configuration
+APP_NAME="void"
+APP_VERSION="1.0.0"
+ARCH="x86_64"
+
+export ARCH
+
+# Check if void binary exists in current directory
+if [ ! -f "./void" ]; then
+ echo "Error: void binary not found in current directory"
+ exit 1
+fi
+
+# Check if icon exists
+if [ ! -f "./void.png" ]; then
+ echo "Error: void.png icon not found in current directory"
+ exit 1
+fi
+
+# Create temporary directory
+TEMP_DIR="$(mktemp -d)"
+echo "Created temporary directory: $TEMP_DIR"
+APP_DIR="$TEMP_DIR/$APP_NAME.AppDir"
+
+# Create basic AppDir structure
+mkdir -pv "$APP_DIR/usr/bin"
+mkdir -pv "$APP_DIR/usr/lib"
+mkdir -pv "$APP_DIR/usr/share/applications"
+mkdir -pv "$APP_DIR/usr/share/icons/hicolor/256x256/apps"
+
+# Exclude create-appimage.sh and appimagetool-x86_64.AppImage from being copied
+echo "Copying files excluding create-appimage.sh and appimagetool-x86_64.AppImage..."
+for file in ./*; do
+ if [[ "$file" != "./create-appimage.sh" && "$file" != "./appimagetool-x86_64.AppImage" ]]; then
+ cp -rv "$file" "$APP_DIR/usr/bin/"
+ fi
+done
+
+# Copy the icon to required locations
+cp -v ./void.png "$APP_DIR/void.png"
+cp -v ./void.png "$APP_DIR/usr/share/icons/hicolor/256x256/apps/void.png"
+
+# Copy dependencies with error checking
+echo "Copying dependencies..."
+for lib in $(ldd ./void | grep "=> /" | awk '{print $3}'); do
+ if [ -f "$lib" ]; then
+ cp -v "$lib" "$APP_DIR/usr/lib/" || echo "Failed to copy $lib"
+ else
+ echo "Warning: Library $lib not found"
+ fi
+done
+
+# Create desktop file with error checking
+echo "Creating desktop file..."
+if ! cat > "$APP_DIR/$APP_NAME.desktop" < "$APP_DIR/AppRun" < {
return null
}
else if (typeof fullError === 'object') {
+ if (Object.keys(fullError).length === 0) return null
return JSON.stringify(fullError, null, 2)
}
else if (typeof fullError === 'string') {
@@ -41,10 +42,10 @@ type _InternalSendFIMMessage = {
}
type SendLLMType = {
- type: 'sendChatMessage';
+ messagesType: 'chatMessages';
messages: LLMChatMessage[];
} | {
- type: 'sendFIMMessage';
+ messagesType: 'FIMMessage';
messages: _InternalSendFIMMessage;
}
diff --git a/src/vs/platform/void/common/refreshModelService.ts b/src/vs/platform/void/common/refreshModelService.ts
index 811db0db..7ef6a068 100644
--- a/src/vs/platform/void/common/refreshModelService.ts
+++ b/src/vs/platform/void/common/refreshModelService.ts
@@ -44,8 +44,8 @@ export type RefreshModelStateOfProvider = Record
-type EventProp = T extends 'globalSettings' ? [T, keyof VoidSettingsState[T]] : T | 'all'
+// type RealVoidSettings = Exclude
+// type EventProp = T extends 'globalSettings' ? [T, keyof VoidSettingsState[T]] : T | 'all'
export interface IVoidSettingsService {
@@ -51,7 +51,7 @@ export interface IVoidSettingsService {
readonly state: VoidSettingsState; // in order to play nicely with react, you should immutably change state
readonly waitForInitState: Promise;
- onDidChangeState: Event;
+ onDidChangeState: Event;
setSettingOfProvider: SetSettingOfProviderFn;
setModelSelectionOfFeature: SetModelSelectionOfFeatureFn;
@@ -64,26 +64,76 @@ export interface IVoidSettingsService {
}
-let _computeModelOptions = (settingsOfProvider: SettingsOfProvider) => {
- let modelOptions: ModelOption[] = []
+
+const _updatedValidatedState = (state: Omit) => {
+
+ let newSettingsOfProvider = state.settingsOfProvider
+
+ // recompute _didFillInProviderSettings
for (const providerName of providerNames) {
- const providerConfig = settingsOfProvider[providerName]
- if (!providerConfig._enabled) continue // if disabled, don't display model options
- for (const { modelName, isHidden } of providerConfig.models) {
- if (isHidden) continue
- modelOptions.push({ name: `${modelName} (${providerName})`, selection: { providerName, modelName } })
+ const settingsAtProvider = newSettingsOfProvider[providerName]
+
+ const didFillInProviderSettings = Object.keys(defaultProviderSettings[providerName]).every(key => !!settingsAtProvider[key as keyof typeof settingsAtProvider])
+
+ if (didFillInProviderSettings === settingsAtProvider._didFillInProviderSettings) continue
+
+ newSettingsOfProvider = {
+ ...newSettingsOfProvider,
+ [providerName]: {
+ ...settingsAtProvider,
+ _didFillInProviderSettings: didFillInProviderSettings,
+ },
}
}
- return modelOptions
+
+ // update model options
+ let newModelOptions: ModelOption[] = []
+ for (const providerName of providerNames) {
+ const providerTitle = displayInfoOfProviderName(providerName).title.toLowerCase() // looks better lowercase, best practice to not use raw providerName
+ if (!newSettingsOfProvider[providerName]._didFillInProviderSettings) continue // if disabled, don't display model options
+ for (const { modelName, isHidden } of newSettingsOfProvider[providerName].models) {
+ if (isHidden) continue
+ newModelOptions.push({ name: `${modelName} (${providerTitle})`, selection: { providerName, modelName } })
+ }
+ }
+
+ // now that model options are updated, make sure the selection is valid
+ // if the user-selected model is no longer in the list, update the selection for each feature that needs it to something relevant (the 0th model available, or null)
+ let newModelSelectionOfFeature = state.modelSelectionOfFeature
+ for (const featureName of featureNames) {
+
+ const modelSelectionAtFeature = newModelSelectionOfFeature[featureName]
+ const selnIdx = modelSelectionAtFeature === null ? -1 : newModelOptions.findIndex(m => modelSelectionsEqual(m.selection, modelSelectionAtFeature))
+
+ if (selnIdx !== -1) continue
+
+ newModelSelectionOfFeature = {
+ ...newModelSelectionOfFeature,
+ [featureName]: newModelOptions.length === 0 ? null : newModelOptions[0].selection
+ }
+ }
+
+
+ const newState = {
+ ...state,
+ settingsOfProvider: newSettingsOfProvider,
+ modelSelectionOfFeature: newModelSelectionOfFeature,
+ _modelOptions: newModelOptions,
+ } satisfies VoidSettingsState
+
+ return newState
}
+
+
+
const defaultState = () => {
const d: VoidSettingsState = {
settingsOfProvider: deepClone(defaultSettingsOfProvider),
modelSelectionOfFeature: { 'Ctrl+L': null, 'Ctrl+K': null, 'Autocomplete': null, 'FastApply': null },
globalSettings: deepClone(defaultGlobalSettings),
- _modelOptions: _computeModelOptions(defaultSettingsOfProvider), // computed
+ _modelOptions: [], // computed later
}
return d
}
@@ -93,8 +143,8 @@ export const IVoidSettingsService = createDecorator('VoidS
class VoidSettingsService extends Disposable implements IVoidSettingsService {
_serviceBrand: undefined;
- 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
+ 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: VoidSettingsState;
waitForInitState: Promise // await this if you need a valid state initially
@@ -118,39 +168,47 @@ class VoidSettingsService extends Disposable implements IVoidSettingsService {
this._readState().then(readS => {
// the stored data structure might be outdated, so we need to update it here (can do a more general solution later when we need to)
- readS = {
- ...readS,
- settingsOfProvider: {
- // A HACK BECAUSE WE ADDED DEEPSEEK (did not exist before, comes before readS)
- ...{ deepseek: defaultSettingsOfProvider.deepseek },
+ const newSettingsOfProvider = {
+ // A HACK BECAUSE WE ADDED DEEPSEEK (did not exist before, comes before readS)
+ ...{ deepseek: defaultSettingsOfProvider.deepseek },
- // A HACK BECAUSE WE ADDED MISTRAL (did not exist before, comes before readS)
- ...{ mistral: defaultSettingsOfProvider.mistral },
+ // A HACK BECAUSE WE ADDED MISTRAL (did not exist before, comes before readS)
+ ...{ mistral: defaultSettingsOfProvider.mistral },
- ...readS.settingsOfProvider,
+ ...readS.settingsOfProvider,
- // A HACK BECAUSE WE ADDED NEW GEMINI MODELS (existed before, comes after readS)
- gemini: {
- ...readS.settingsOfProvider.gemini,
- models: [
- ...readS.settingsOfProvider.gemini.models,
- ...defaultSettingsOfProvider.gemini.models.filter(m => /* if cant find the model in readS (yes this is O(n^2), very small) */ !readS.settingsOfProvider.gemini.models.find(m2 => m2.modelName === m.modelName))
- ]
- }
- },
- modelSelectionOfFeature: {
- // A HACK BECAUSE WE ADDED FastApply
- ...{ 'FastApply': null },
- ...readS.modelSelectionOfFeature,
+ // A HACK BECAUSE WE ADDED NEW GEMINI MODELS (existed before, comes after readS)
+ gemini: {
+ ...readS.settingsOfProvider.gemini,
+ models: [
+ ...readS.settingsOfProvider.gemini.models,
+ ...defaultSettingsOfProvider.gemini.models.filter(m => /* if cant find the model in readS (yes this is O(n^2), very small) */ !readS.settingsOfProvider.gemini.models.find(m2 => m2.modelName === m.modelName))
+ ]
}
}
- this.state = readS
+ const newModelSelectionOfFeature = {
+ // A HACK BECAUSE WE ADDED FastApply
+ ...{ 'FastApply': null },
+ ...readS.modelSelectionOfFeature,
+ }
+
+ readS = {
+ ...readS,
+ settingsOfProvider: newSettingsOfProvider,
+ modelSelectionOfFeature: newModelSelectionOfFeature,
+ }
+
+ this.state = _updatedValidatedState(readS)
+
resolver()
- this._onDidChangeState.fire('all')
+ this._onDidChangeState.fire()
})
+
+
}
+
private async _readState(): Promise {
const encryptedState = this._storageService.get(STORAGE_KEY, StorageScope.APPLICATION)
@@ -172,7 +230,7 @@ class VoidSettingsService extends Disposable implements IVoidSettingsService {
const newModelSelectionOfFeature = this.state.modelSelectionOfFeature
- const newSettingsOfProvider = {
+ const newSettingsOfProvider: SettingsOfProvider = {
...this.state.settingsOfProvider,
[providerName]: {
...this.state.settingsOfProvider[providerName],
@@ -182,38 +240,17 @@ class VoidSettingsService extends Disposable implements IVoidSettingsService {
const newGlobalSettings = this.state.globalSettings
- // if changed models or enabled a provider, recompute models list
- const modelsListChanged = settingName === 'models' || settingName === '_enabled'
- const newModelsList = modelsListChanged ? _computeModelOptions(newSettingsOfProvider) : this.state._modelOptions
-
- const newState: VoidSettingsState = {
+ const newState = {
modelSelectionOfFeature: newModelSelectionOfFeature,
settingsOfProvider: newSettingsOfProvider,
globalSettings: newGlobalSettings,
- _modelOptions: newModelsList,
}
- // this must go above this.setanythingelse()
- this.state = newState
-
- // if the user-selected model is no longer in the list, update the selection for each feature that needs it to something relevant (the 0th model available, or null)
- if (modelsListChanged) {
- for (const featureName of featureNames) {
-
- const currentSelection = newModelSelectionOfFeature[featureName]
- const selnIdx = currentSelection === null ? -1 : newModelsList.findIndex(m => modelSelectionsEqual(m.selection, currentSelection))
-
- if (selnIdx === -1) {
- if (newModelsList.length !== 0)
- this.setModelSelectionOfFeature(featureName, newModelsList[0].selection, { doNotApplyEffects: true })
- else
- this.setModelSelectionOfFeature(featureName, null, { doNotApplyEffects: true })
- }
- }
- }
+ this.state = _updatedValidatedState(newState)
await this._storeState()
- this._onDidChangeState.fire('settingsOfProvider')
+ this._onDidChangeState.fire()
+
}
@@ -227,7 +264,7 @@ class VoidSettingsService extends Disposable implements IVoidSettingsService {
}
this.state = newState
await this._storeState()
- this._onDidChangeState.fire(['globalSettings', settingName])
+ this._onDidChangeState.fire()
}
@@ -247,7 +284,7 @@ class VoidSettingsService extends Disposable implements IVoidSettingsService {
return
await this._storeState()
- this._onDidChangeState.fire('modelSelectionOfFeature')
+ this._onDidChangeState.fire()
}
diff --git a/src/vs/platform/void/common/voidSettingsTypes.ts b/src/vs/platform/void/common/voidSettingsTypes.ts
index 26758593..c9eadefd 100644
--- a/src/vs/platform/void/common/voidSettingsTypes.ts
+++ b/src/vs/platform/void/common/voidSettingsTypes.ts
@@ -4,7 +4,7 @@
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
-
+import { VoidSettingsState } from './voidSettingsService.js'
export type VoidModelInfo = {
@@ -87,10 +87,11 @@ export const defaultDeepseekModels = modelInfoOfDefaultModelNames([
// https://console.groq.com/docs/models
export const defaultGroqModels = modelInfoOfDefaultModelNames([
- "distil-whisper-large-v3-en",
+ "llama3-70b-8192",
"llama-3.3-70b-versatile",
"llama-3.1-8b-instant",
- "gemma2-9b-it"
+ "gemma2-9b-it",
+ "mixtral-8x7b-32768"
])
@@ -186,28 +187,23 @@ export const customSettingNamesOfProvider = (providerName: ProviderName) => {
return Object.keys(defaultProviderSettings[providerName]) as CustomSettingName[]
}
-export const getProvidersWithoutModels = (settingsOfProvider: SettingsOfProvider) => {
- return Object.entries(settingsOfProvider)
- .filter(([name, provider]) => provider._enabled && provider.models.length === 0)
- .map(([name]) => name)
-}
type CommonProviderSettings = {
- _enabled: boolean | undefined, // undefined initially, computed when user types in all fields
+ _didFillInProviderSettings: boolean | undefined, // undefined initially, computed when user types in all fields
models: VoidModelInfo[],
}
-export type SettingsForProvider = CustomProviderSettings & CommonProviderSettings
+export type SettingsAtProvider = CustomProviderSettings & CommonProviderSettings
// part of state
export type SettingsOfProvider = {
- [providerName in ProviderName]: SettingsForProvider
+ [providerName in ProviderName]: SettingsAtProvider
}
-export type SettingName = keyof SettingsForProvider
+export type SettingName = keyof SettingsAtProvider
@@ -231,7 +227,7 @@ export const displayInfoOfProviderName = (providerName: ProviderName): DisplayIn
}
else if (providerName === 'deepseek') {
return {
- title: 'DeepSeek',
+ title: 'DeepSeek.com API',
}
}
else if (providerName === 'openRouter') {
@@ -252,17 +248,17 @@ export const displayInfoOfProviderName = (providerName: ProviderName): DisplayIn
}
else if (providerName === 'gemini') {
return {
- title: 'Gemini',
+ title: 'Gemini API',
}
}
else if (providerName === 'groq') {
return {
- title: 'Groq',
+ title: 'Groq API',
}
}
else if (providerName === 'mistral') {
return {
- title: 'Mistral',
+ title: 'Mistral API',
}
}
@@ -316,7 +312,7 @@ export const displayInfoOfSettingName = (providerName: ProviderName, settingName
undefined,
}
}
- else if (settingName === '_enabled') {
+ else if (settingName === '_didFillInProviderSettings') {
return {
title: '(never)',
placeholder: '(never)',
@@ -380,55 +376,55 @@ export const defaultSettingsOfProvider: SettingsOfProvider = {
...defaultCustomSettings,
...defaultProviderSettings.anthropic,
...voidInitModelOptions.anthropic,
- _enabled: undefined,
+ _didFillInProviderSettings: undefined,
},
openAI: {
...defaultCustomSettings,
...defaultProviderSettings.openAI,
...voidInitModelOptions.openAI,
- _enabled: undefined,
+ _didFillInProviderSettings: undefined,
},
deepseek: {
...defaultCustomSettings,
...defaultProviderSettings.deepseek,
...voidInitModelOptions.deepseek,
- _enabled: undefined,
+ _didFillInProviderSettings: undefined,
},
gemini: {
...defaultCustomSettings,
...defaultProviderSettings.gemini,
...voidInitModelOptions.gemini,
- _enabled: undefined,
+ _didFillInProviderSettings: undefined,
},
mistral: {
...defaultCustomSettings,
...defaultProviderSettings.mistral,
...voidInitModelOptions.mistral,
- _enabled: undefined,
+ _didFillInProviderSettings: undefined,
},
groq: { // aggregator
...defaultCustomSettings,
...defaultProviderSettings.groq,
...voidInitModelOptions.groq,
- _enabled: undefined,
+ _didFillInProviderSettings: undefined,
},
openRouter: { // aggregator
...defaultCustomSettings,
...defaultProviderSettings.openRouter,
...voidInitModelOptions.openRouter,
- _enabled: undefined,
+ _didFillInProviderSettings: undefined,
},
openAICompatible: { // aggregator
...defaultCustomSettings,
...defaultProviderSettings.openAICompatible,
...voidInitModelOptions.openAICompatible,
- _enabled: undefined,
+ _didFillInProviderSettings: undefined,
},
ollama: { // aggregator
...defaultCustomSettings,
...defaultProviderSettings.ollama,
...voidInitModelOptions.ollama,
- _enabled: undefined,
+ _didFillInProviderSettings: undefined,
},
}
@@ -448,20 +444,16 @@ export const displayInfoOfFeatureName = (featureName: FeatureName) => {
if (featureName === 'Autocomplete')
return 'Autocomplete'
else if (featureName === 'Ctrl+K')
- return 'Quick Edit'
+ return 'Quick-Edit'
else if (featureName === 'Ctrl+L')
- return 'Sidebar Chat'
+ return 'Chat'
else if (featureName === 'FastApply')
- return 'Fast Apply'
+ return 'Apply'
else
throw new Error(`Feature Name ${featureName} not allowed`)
}
-
-
-
-
// the models of these can be refreshed (in theory all can, but not all should)
export const refreshableProviderNames = localProviderNames
export type RefreshableProviderName = typeof refreshableProviderNames[number]
@@ -471,6 +463,45 @@ export type RefreshableProviderName = typeof refreshableProviderNames[number]
+// use this in isFeatuerNameDissbled
+export const isProviderNameDisabled = (providerName: ProviderName, settingsState: VoidSettingsState) => {
+
+ const settingsAtProvider = settingsState.settingsOfProvider[providerName]
+ const isAutodetected = (refreshableProviderNames as string[]).includes(providerName)
+
+ const isDisabled = settingsAtProvider.models.length === 0
+ if (isDisabled) {
+ return isAutodetected ? 'providerNotAutoDetected' : (!settingsAtProvider._didFillInProviderSettings ? 'notFilledIn' : 'addModel')
+ }
+ return false
+}
+
+export const isFeatureNameDisabled = (featureName: FeatureName, settingsState: VoidSettingsState) => {
+ // if has a selected provider, check if it's enabled
+ const selectedProvider = settingsState.modelSelectionOfFeature[featureName]
+
+ if (selectedProvider) {
+ const { providerName } = selectedProvider
+ return isProviderNameDisabled(providerName, settingsState)
+ }
+
+ // if there are any models they can turn on, tell them that
+ const canTurnOnAModel = !!providerNames.find(providerName => settingsState.settingsOfProvider[providerName].models.filter(m => m.isHidden).length !== 0)
+ if (canTurnOnAModel) return 'needToEnableModel'
+
+ // if there are any providers filled in, then they just need to add a model
+ const anyFilledIn = !!providerNames.find(providerName => settingsState.settingsOfProvider[providerName]._didFillInProviderSettings)
+ if (anyFilledIn) return 'addModel'
+
+ return 'addProvider'
+}
+
+
+
+
+
+
+
export type GlobalSettings = {
diff --git a/src/vs/platform/void/electron-main/llmMessage/openai.ts b/src/vs/platform/void/electron-main/llmMessage/openai.ts
index 8b7afd94..268eadfb 100644
--- a/src/vs/platform/void/electron-main/llmMessage/openai.ts
+++ b/src/vs/platform/void/electron-main/llmMessage/openai.ts
@@ -99,6 +99,7 @@ export const sendOpenAIFIM: _InternalSendLLMFIMMessageFnType = ({ messages, onTe
.create(options)
.then(async response => {
// TODO!!!
+ console.log('RESPONSE', response)
})
}
diff --git a/src/vs/platform/void/electron-main/llmMessage/sendLLMMessage.ts b/src/vs/platform/void/electron-main/llmMessage/sendLLMMessage.ts
index 8b393f1a..7cea9d5a 100644
--- a/src/vs/platform/void/electron-main/llmMessage/sendLLMMessage.ts
+++ b/src/vs/platform/void/electron-main/llmMessage/sendLLMMessage.ts
@@ -12,6 +12,7 @@ import { sendOpenAIChat } from './openai.js';
import { sendGeminiChat } from './gemini.js';
import { sendGroqChat } from './groq.js';
import { sendMistralChat } from './mistral.js';
+import { displayInfoOfProviderName } from '../../common/voidSettingsTypes.js';
const cleanChatMessages = (messages: LLMChatMessage[]): _InternalLLMChatMessage[] => {
@@ -49,7 +50,7 @@ const cleanChatMessages = (messages: LLMChatMessage[]): _InternalLLMChatMessage[
export const sendLLMMessage = ({
- type,
+ messagesType,
aiInstructions,
messages: messages_,
onText: onText_,
@@ -66,20 +67,20 @@ export const sendLLMMessage = ({
) => {
// messages.unshift({ role: 'system', content: aiInstructions })
- const messagesArr = type === 'sendChatMessage' ? cleanChatMessages(messages_) : []
+ const messagesArr = messagesType === 'chatMessages' ? cleanChatMessages(messages_) : []
// only captures number of messages and message "shape", no actual code, instructions, prompts, etc
const captureLLMEvent = (eventId: string, extras?: object) => {
metricsService.capture(eventId, {
providerName,
modelName,
- ...type === 'sendChatMessage' ? {
+ ...messagesType === 'chatMessages' ? {
numMessages: messagesArr?.length,
messagesShape: messagesArr?.map(msg => ({ role: msg.role, length: msg.content.length })),
origNumMessages: messages_?.length,
origMessagesShape: messages_?.map(msg => ({ role: msg.role, length: msg.content.length })),
- } : type === 'sendFIMMessage' ? {
+ } : messagesType === 'FIMMessage' ? {
prefixLength: messages_.prefix.length,
suffixLength: messages_.suffix.length,
} : {},
@@ -109,6 +110,11 @@ export const sendLLMMessage = ({
const onError: OnError = ({ message: error, fullError }) => {
if (_didAbort) return
console.error('sendLLMMessage onError:', error)
+
+ // handle failed to fetch errors, which give 0 information by design
+ if (error === 'TypeError: fetch failed')
+ error = `Failed to fetch from ${displayInfoOfProviderName(providerName).title}. This likely means you specified the wrong endpoint in Void Settings, or your local model provider like Ollama is powered off.`
+
captureLLMEvent(`${loggingName} - Error`, { error })
onError_({ message: error, fullError })
}
@@ -139,8 +145,8 @@ export const sendLLMMessage = ({
break;
case 'ollama':
if ( // TODO @andrew in future we want to use our own templates instead of using ollamaFIM
- type === 'sendFIMMessage'
- && settingsOfProvider['ollama']._enabled
+ messagesType === 'FIMMessage'
+ && settingsOfProvider['ollama']._didFillInProviderSettings
&& settingsOfProvider['ollama'].models.some(m => !m.isHidden)
)
sendOllamaFIM({ messages: messages_, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter, providerName })
diff --git a/src/vs/workbench/contrib/void/browser/autocompleteService.ts b/src/vs/workbench/contrib/void/browser/autocompleteService.ts
index 64d181f0..6b67c6be 100644
--- a/src/vs/workbench/contrib/void/browser/autocompleteService.ts
+++ b/src/vs/workbench/contrib/void/browser/autocompleteService.ts
@@ -785,13 +785,13 @@ export class AutocompleteService extends Disposable implements IAutocompleteServ
}
console.log('BB')
- console.log(predictionType)
+ console.log('type', predictionType)
// set parameters of `newAutocompletion` appropriately
newAutocompletion.llmPromise = new Promise((resolve, reject) => {
const requestId = this._llmMessageService.sendLLMMessage({
- type: 'sendFIMMessage',
+ messagesType: 'FIMMessage',
messages: {
prefix: llmPrefix,
suffix: llmSuffix,
diff --git a/src/vs/workbench/contrib/void/browser/chatThreadService.ts b/src/vs/workbench/contrib/void/browser/chatThreadService.ts
index 9a0746ed..03683732 100644
--- a/src/vs/workbench/contrib/void/browser/chatThreadService.ts
+++ b/src/vs/workbench/contrib/void/browser/chatThreadService.ts
@@ -80,7 +80,7 @@ export type ThreadsState = {
export type ThreadStreamState = {
[threadId: string]: undefined | {
- error?: { message: string, fullError: Error | null };
+ error?: { message: string, fullError: Error | null, };
messageSoFar?: string;
streamingToken?: string;
}
@@ -311,12 +311,12 @@ class ChatThreadService extends Disposable implements IChatThreadService {
this._setStreamState(threadId, { error: undefined })
const llmCancelToken = this._llmMessageService.sendLLMMessage({
- type: 'sendChatMessage',
+ messagesType: 'chatMessages',
logging: { loggingName: 'Chat' },
useProviderFor: 'Ctrl+L',
messages: [
{ role: 'system', content: chat_systemMessage },
- ...this.getCurrentThread().messages.map(m => ({ role: m.role, content: m.content || '(null)' })),
+ ...this.getCurrentThread().messages.map(m => ({ role: m.role, content: m.content || '(empty model output)' })),
],
onText: ({ newText, fullText }) => {
this._setStreamState(threadId, { messageSoFar: fullText })
diff --git a/src/vs/workbench/contrib/void/browser/inlineDiffsService.ts b/src/vs/workbench/contrib/void/browser/inlineDiffsService.ts
index 09da6af3..d4d7d065 100644
--- a/src/vs/workbench/contrib/void/browser/inlineDiffsService.ts
+++ b/src/vs/workbench/contrib/void/browser/inlineDiffsService.ts
@@ -102,13 +102,13 @@ const getLeadingWhitespacePx = (editor: ICodeEditor, startLine: number): number
// similar to ServiceLLM
export type StartApplyingOpts = {
- featureName: 'Ctrl+K';
+ from: 'QuickEdit';
diffareaid: number; // id of the CtrlK area (contains text selection)
} | {
- featureName: 'Ctrl+L';
+ from: 'Chat';
applyStr: string;
} | {
- featureName: 'Autocomplete';
+ from: 'Autocomplete';
range: IRange;
userMessage: string;
}
@@ -1209,13 +1209,13 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
private _initializeStartApplying(opts: StartApplyingOpts): DiffZone | undefined {
- const { featureName } = opts
+ const { from } = opts
let startLine: number
let endLine: number
let uri: URI
- if (featureName === 'Ctrl+L') {
+ if (from === 'Chat') {
const uri_ = this._getActiveEditorURI()
if (!uri_) return
@@ -1231,7 +1231,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
endLine = numLines
}
- else if (featureName === 'Ctrl+K') {
+ else if (from === 'QuickEdit') {
const { diffareaid } = opts
const ctrlKZone = this.diffAreaOfId[diffareaid]
if (ctrlKZone.type !== 'CtrlKZone') return
@@ -1242,7 +1242,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
endLine = endLine_
}
else {
- throw new Error(`Void: diff.type not recognized on: ${featureName}`)
+ throw new Error(`Void: diff.type not recognized on: ${from}`)
}
const currentFileStr = this._readURI(uri)
@@ -1278,7 +1278,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
this._onDidChangeStreaming.fire({ uri, diffareaid: diffZone.diffareaid })
this._onDidAddOrDeleteDiffZones.fire({ uri })
- if (featureName === 'Ctrl+K') {
+ if (from === 'QuickEdit') {
const { diffareaid } = opts
const ctrlKZone = this.diffAreaOfId[diffareaid]
if (ctrlKZone.type !== 'CtrlKZone') return
@@ -1289,14 +1289,14 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
// now handle messages
let messages: LLMChatMessage[]
- if (featureName === 'Ctrl+L') {
+ if (from === 'Chat') {
const userContent = fastApply_userMessage({ originalCode, applyStr: opts.applyStr, uri })
messages = [
{ role: 'system', content: fastApply_systemMessage, },
{ role: 'user', content: userContent, }
]
}
- else if (featureName === 'Ctrl+K') {
+ else if (from === 'QuickEdit') {
const { diffareaid } = opts
const ctrlKZone = this.diffAreaOfId[diffareaid]
if (ctrlKZone.type !== 'CtrlKZone') return
@@ -1323,14 +1323,14 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
]
// }
}
- else { throw new Error(`featureName ${featureName} is invalid`) }
+ else { throw new Error(`featureName ${from} is invalid`) }
const onDone = (hadError: boolean) => {
diffZone._streamState = { isStreaming: false, }
this._onDidChangeStreaming.fire({ uri, diffareaid: diffZone.diffareaid })
- if (featureName === 'Ctrl+K') {
+ if (from === 'QuickEdit') {
const ctrlKZone = this.diffAreaOfId[opts.diffareaid] as CtrlKZone
ctrlKZone._linkedStreamingDiffZone = null
@@ -1350,11 +1350,11 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
const extractText = (fullText: string, recentlyAddedTextLen: number) => {
- if (featureName === 'Ctrl+K') {
+ if (from === 'QuickEdit') {
if (isOllamaFIM) return fullText
return extractCodeFromFIM({ text: fullText, recentlyAddedTextLen, midTag: modelFimTags.midTag })
}
- else if (featureName === 'Ctrl+L') {
+ else if (from === 'Chat') {
return extractCodeFromRegular({ text: fullText, recentlyAddedTextLen })
}
throw 1
@@ -1367,9 +1367,9 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
let prevIgnoredSuffix = ''
streamRequestIdRef.current = this._llmMessageService.sendLLMMessage({
- type: 'sendChatMessage',
- useProviderFor: opts.featureName === 'Ctrl+L' ? 'FastApply' : 'Ctrl+K',
- logging: { loggingName: `startApplying - ${featureName}` },
+ messagesType: 'chatMessages',
+ useProviderFor: opts.from === 'Chat' ? 'FastApply' : 'Ctrl+K',
+ logging: { loggingName: `startApplying - ${from}` },
messages,
onText: ({ newText: newText_ }) => {
diff --git a/src/vs/workbench/contrib/void/browser/react/src/markdown/ChatMarkdownRender.tsx b/src/vs/workbench/contrib/void/browser/react/src/markdown/ChatMarkdownRender.tsx
index 6d7fc46b..15f67d9a 100644
--- a/src/vs/workbench/contrib/void/browser/react/src/markdown/ChatMarkdownRender.tsx
+++ b/src/vs/workbench/contrib/void/browser/react/src/markdown/ChatMarkdownRender.tsx
@@ -45,7 +45,7 @@ const CodeButtonsOnHover = ({ text }: { text: string }) => {
const onApply = useCallback(() => {
inlineDiffService.startApplying({
- featureName: 'Ctrl+L',
+ from: 'Chat',
applyStr: text,
})
metricsService.capture('Apply Code', { length: text.length }) // capture the length only
@@ -186,18 +186,18 @@ const RenderToken = ({ token, nested = false, noSpace = false }: { token: Token
))}
>
- if (nested)
- return contents
- return {contents}
+ if (nested) return contents
+
+ return
+ {contents}
+
}
if (t.type === "html") {
return (
-
- {``}
+
{t.raw}
- {``}
-
+
)
}
diff --git a/src/vs/workbench/contrib/void/browser/react/src/quick-edit-tsx/QuickEditChat.tsx b/src/vs/workbench/contrib/void/browser/react/src/quick-edit-tsx/QuickEditChat.tsx
index f1a3456a..7edf1e5b 100644
--- a/src/vs/workbench/contrib/void/browser/react/src/quick-edit-tsx/QuickEditChat.tsx
+++ b/src/vs/workbench/contrib/void/browser/react/src/quick-edit-tsx/QuickEditChat.tsx
@@ -7,11 +7,12 @@ import React, { FormEvent, useCallback, useEffect, useRef, useState } from 'reac
import { useSettingsState, useSidebarState, useChatThreadsState, useQuickEditState, useAccessor } from '../util/services.js';
import { TextAreaFns, VoidInputBox2 } from '../util/inputs.js';
import { QuickEditPropsType } from '../../../quickEditActions.js';
-import { ButtonStop, ButtonSubmit, IconX, VoidInputForm } from '../sidebar-tsx/SidebarChat.js';
+import { ButtonStop, ButtonSubmit, IconX, VoidChatArea } from '../sidebar-tsx/SidebarChat.js';
import { ModelDropdown } from '../void-settings-tsx/ModelDropdown.js';
import { VOID_CTRL_K_ACTION_ID } from '../../../actionIDs.js';
import { useRefState } from '../util/helpers.js';
import { useScrollbarStyles } from '../util/useScrollbarStyles.js';
+import { isFeatureNameDisabled } from '../../../../../../../platform/void/common/voidSettingsTypes.js';
export const QuickEditChat = ({
diffareaid,
@@ -42,9 +43,11 @@ export const QuickEditChat = ({
}, [onChangeHeight]);
+ const settingsState = useSettingsState()
+
// state of current message
const [instructionsAreEmpty, setInstructionsAreEmpty] = useState(!(initText ?? '')) // the user's instructions
- const isDisabled = instructionsAreEmpty
+ const isDisabled = instructionsAreEmpty || !!isFeatureNameDisabled('Ctrl+K', settingsState)
const [currStreamingDiffZoneRef, setCurrentlyStreamingDiffZone] = useRefState(initStreamingDiffZoneId)
const isStreaming = currStreamingDiffZoneRef.current !== null
@@ -55,7 +58,7 @@ export const QuickEditChat = ({
textAreaFnsRef.current?.disable()
const id = inlineDiffsService.startApplying({
- featureName: 'Ctrl+K',
+ from: 'QuickEdit',
diffareaid: diffareaid,
})
setCurrentlyStreamingDiffZone(id ?? null)
@@ -78,8 +81,10 @@ export const QuickEditChat = ({
const keybindingString = accessor.get('IKeybindingService').lookupKeybinding(VOID_CTRL_K_ACTION_ID)?.getLabel()
+ const chatAreaRef = useRef(null)
return
- { textAreaRef.current?.focus() }}
>
-
+
diff --git a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/ErrorDisplay.tsx b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/ErrorDisplay.tsx
index 2aa7da49..425ce3c9 100644
--- a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/ErrorDisplay.tsx
+++ b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/ErrorDisplay.tsx
@@ -23,8 +23,9 @@ export const ErrorDisplay = ({
const [isExpanded, setIsExpanded] = useState(false);
const details = errorDetails(fullError)
+ const isExpandable = !!details
- const message = message_ === 'TypeError: fetch failed' ? `TypeError: fetch failed. This likely means you specified the wrong endpoint in Void Settings, or a provider like Ollama is powered off.` : message_ + ''
+ const message = message_ + ''
return (
@@ -45,7 +46,7 @@ export const ErrorDisplay = ({
- {details && (
+ {isExpandable && (
}
@@ -863,8 +873,8 @@ export const SidebarChat = () => {
}
}, [onSubmit])
const inputForm = 0 ? 'absolute bottom-0' : ''}`}>
- {
showProspectiveSelections={prevMessagesHTML.length === 0}
staging={staging}
setStaging={setStaging}
- // onSelectionsChange={chatThreadsService.setStagingSelections.bind(chatThreadsService)}
+ onClickAnywhere={() => { textAreaRef.current?.focus() }}
featureName="Ctrl+L"
>
{
fnsRef={textAreaFnsRef}
multiline={true}
/>
-
+
return
diff --git a/src/vs/workbench/contrib/void/browser/react/src/util/inputs.tsx b/src/vs/workbench/contrib/void/browser/react/src/util/inputs.tsx
index a70859eb..e62e7a9e 100644
--- a/src/vs/workbench/contrib/void/browser/react/src/util/inputs.tsx
+++ b/src/vs/workbench/contrib/void/browser/react/src/util/inputs.tsx
@@ -303,9 +303,9 @@ export const VoidCheckBox = ({ label, value, onClick, className }: { label: stri
-export const VoidCustomSelectBox =
({
+export const VoidCustomDropdownBox = ({
options,
- selectedOption: selectedOption_,
+ selectedOption,
onChangeOption,
getOptionDropdownName,
getOptionDisplayName,
@@ -316,7 +316,7 @@ export const VoidCustomSelectBox = ({
gap = 0,
}: {
options: T[];
- selectedOption?: T;
+ selectedOption: T | undefined;
onChangeOption: (newValue: T) => void;
getOptionDropdownName: (option: T) => string;
getOptionDisplayName: (option: T) => string;
@@ -375,14 +375,12 @@ export const VoidCustomSelectBox = ({
strategy: 'fixed',
});
- // if the selected option is null, use the 0th option
+ // if the selected option is null, set the selection to the 0th option
useEffect(() => {
- if (!options[0]) return
- if (!selectedOption_) {
- onChangeOption(options[0]);
- }
- }, [selectedOption_, options])
- const selectedOption = !selectedOption_ ? options[0] : selectedOption_
+ if (options.length === 0) return
+ if (selectedOption) return
+ onChangeOption(options[0])
+ }, [selectedOption, onChangeOption, options])
// Handle clicks outside
useEffect(() => {
@@ -409,6 +407,9 @@ export const VoidCustomSelectBox = ({
return () => document.removeEventListener('mousedown', handleClickOutside);
}, [isOpen, refs.floating, refs.reference]);
+ if (!selectedOption)
+ return null
+
return (
{/* Hidden measurement div */}
diff --git a/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/ModelDropdown.tsx b/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/ModelDropdown.tsx
index 6b05201f..8016b4b8 100644
--- a/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/ModelDropdown.tsx
+++ b/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/ModelDropdown.tsx
@@ -4,13 +4,14 @@
*--------------------------------------------------------------------------------------*/
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
-import { FeatureName, featureNames, getProvidersWithoutModels, ModelSelection, modelSelectionsEqual, ProviderName, providerNames, SettingsOfProvider } from '../../../../../../../platform/void/common/voidSettingsTypes.js'
+import { FeatureName, featureNames, isFeatureNameDisabled, ModelSelection, modelSelectionsEqual, ProviderName, providerNames, SettingsOfProvider } from '../../../../../../../platform/void/common/voidSettingsTypes.js'
import { useSettingsState, useRefreshModelState, useAccessor } from '../util/services.js'
-import { _VoidSelectBox, VoidCustomSelectBox } from '../util/inputs.js'
+import { _VoidSelectBox, VoidCustomDropdownBox } from '../util/inputs.js'
import { SelectBox } from '../../../../../../../base/browser/ui/selectBox/selectBox.js'
import { IconWarning } from '../sidebar-tsx/SidebarChat.js'
import { VOID_OPEN_SETTINGS_ACTION_ID, VOID_TOGGLE_SETTINGS_ACTION_ID } from '../../../voidSettingsPane.js'
import { ModelOption } from '../../../../../../../platform/void/common/voidSettingsService.js'
+import { WarningBox } from './WarningBox.js'
const optionsEqual = (m1: ModelOption[], m2: ModelOption[]) => {
if (m1.length !== m2.length) return false
@@ -25,13 +26,13 @@ const ModelSelectBox = ({ options, featureName }: { options: ModelOption[], feat
const voidSettingsService = accessor.get('IVoidSettingsService')
const selection = voidSettingsService.state.modelSelectionOfFeature[featureName]
- const selectedOption = selection ? voidSettingsService.state._modelOptions.find(v => modelSelectionsEqual(v.selection, selection)) : options[0]
+ const selectedOption = selection ? voidSettingsService.state._modelOptions.find(v => modelSelectionsEqual(v.selection, selection))! : options[0]
const onChangeOption = useCallback((newOption: ModelOption) => {
voidSettingsService.setModelSelectionOfFeature(featureName, newOption.selection)
}, [voidSettingsService, featureName])
- return
// }
-const MemoizedModelSelectBox = ({ featureName }: { featureName: FeatureName }) => {
+
+
+const MemoizedModelDropdown = ({ featureName }: { featureName: FeatureName }) => {
const settingsState = useSettingsState()
const oldOptionsRef = useRef
([])
const [memoizedOptions, setMemoizedOptions] = useState(oldOptionsRef.current)
+
useEffect(() => {
const oldOptions = oldOptionsRef.current
const newOptions = settingsState._modelOptions
@@ -90,46 +94,22 @@ const MemoizedModelSelectBox = ({ featureName }: { featureName: FeatureName }) =
}
-export const WarningBox = ({ text, onClick, className }: { text: string; onClick?: () => void; className?: string }) => {
-
- return
-
- {text}
-
- // return { }}
- // />
-}
-
export const ModelDropdown = ({ featureName }: { featureName: FeatureName }) => {
const settingsState = useSettingsState()
- const providersWithMissingModels = getProvidersWithoutModels(settingsState.settingsOfProvider)
-
const accessor = useAccessor()
const commandService = accessor.get('ICommandService')
const openSettings = () => { commandService.executeCommand(VOID_OPEN_SETTINGS_ACTION_ID); };
- return <>
- {providersWithMissingModels.length !== 0 ?
-
- : settingsState._modelOptions.length === 0 ?
-
- :
- }
- >
+ const isDisabled = isFeatureNameDisabled(featureName, settingsState)
+ if (isDisabled)
+ return
+
+ return
}
diff --git a/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx b/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx
index 7c5751d7..0cd796e4 100644
--- a/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx
+++ b/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx
@@ -5,17 +5,18 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { InputBox } from '../../../../../../../base/browser/ui/inputbox/inputBox.js'
-import { ProviderName, SettingName, displayInfoOfSettingName, providerNames, VoidModelInfo, globalSettingNames, customSettingNamesOfProvider, RefreshableProviderName, refreshableProviderNames, displayInfoOfProviderName, defaultProviderSettings, nonlocalProviderNames, localProviderNames, GlobalSettingName, featureNames, displayInfoOfFeatureName } from '../../../../../../../platform/void/common/voidSettingsTypes.js'
+import { ProviderName, SettingName, displayInfoOfSettingName, providerNames, VoidModelInfo, globalSettingNames, customSettingNamesOfProvider, RefreshableProviderName, refreshableProviderNames, displayInfoOfProviderName, defaultProviderSettings, nonlocalProviderNames, localProviderNames, GlobalSettingName, featureNames, displayInfoOfFeatureName, isProviderNameDisabled } from '../../../../../../../platform/void/common/voidSettingsTypes.js'
import ErrorBoundary from '../sidebar-tsx/ErrorBoundary.js'
-import { VoidButton, VoidCheckBox, VoidCustomSelectBox, VoidInputBox, VoidInputBox2, VoidSwitch } from '../util/inputs.js'
+import { VoidButton, VoidCheckBox, VoidCustomDropdownBox, VoidInputBox, VoidInputBox2, VoidSwitch } from '../util/inputs.js'
import { useAccessor, useIsDark, useRefreshModelListener, useRefreshModelState, useSettingsState } from '../util/services.js'
import { X, RefreshCw, Loader2, Check, MoveRight } from 'lucide-react'
import { useScrollbarStyles } from '../util/useScrollbarStyles.js'
import { isWindows, isLinux, isMacintosh } from '../../../../../../../base/common/platform.js'
import { URI } from '../../../../../../../base/common/uri.js'
import { env } from '../../../../../../../base/common/process.js'
-import { WarningBox, ModelDropdown } from './ModelDropdown.js'
+import { ModelDropdown } from './ModelDropdown.js'
import { ChatMarkdownRender } from '../markdown/ChatMarkdownRender.js'
+import { WarningBox } from './WarningBox.js'
const SubtleButton = ({ onClick, text, icon, disabled }: { onClick: () => void, text: string, icon: React.ReactNode, disabled: boolean }) => {
@@ -79,7 +80,7 @@ const RefreshableModels = () => {
const buttons = refreshableProviderNames.map(providerName => {
- if (!settingsState.settingsOfProvider[providerName]._enabled) return null
+ if (!settingsState.settingsOfProvider[providerName]._didFillInProviderSettings) return null
return
@@ -112,7 +113,7 @@ const AddModelMenu = ({ onSubmit }: { onSubmit: () => void }) => {
{/* provider */}
-
setProviderName(pn)}
@@ -199,7 +200,7 @@ export const ModelDump = () => {
for (let providerName of providerNames) {
const providerSettings = settingsState.settingsOfProvider[providerName]
// if (!providerSettings.enabled) continue
- modelDump.push(...providerSettings.models.map(model => ({ ...model, providerName, providerEnabled: !!providerSettings._enabled })))
+ modelDump.push(...providerSettings.models.map(model => ({ ...model, providerName, providerEnabled: !!providerSettings._didFillInProviderSettings })))
}
// sort by hidden
@@ -223,7 +224,6 @@ export const ModelDump = () => {
{isNewProviderName ? displayInfoOfProviderName(providerName).title : ''}
{modelName}
- {/* {`${modelName} (${providerName})`} */}
{/* right part is anything that fits */}
@@ -260,7 +260,6 @@ const ProviderSetting = ({ providerName, settingName }: { providerName: Provider
const accessor = useAccessor()
const voidSettingsService = accessor.get('IVoidSettingsService')
- const voidMetricsService = accessor.get('IMetricsService')
let weChangedTextRef = false
@@ -284,25 +283,8 @@ const ProviderSetting = ({ providerName, settingName }: { providerName: Provider
weChangedTextRef = true
instance.value = stateVal as string
weChangedTextRef = false
-
- const isEverySettingPresent = Object.keys(defaultProviderSettings[providerName]).every(key => {
- return !!settingsAtProvider[key as keyof typeof settingsAtProvider]
- })
-
- const shouldEnable = isEverySettingPresent && !settingsAtProvider._enabled // enable if all settings are present and not already enabled
- const shouldDisable = !isEverySettingPresent && settingsAtProvider._enabled
-
- if (shouldEnable) {
- voidSettingsService.setSettingOfProvider(providerName, '_enabled', true)
- voidMetricsService.capture('Enable Provider', { providerName })
- }
-
- if (shouldDisable) {
- voidSettingsService.setSettingOfProvider(providerName, '_enabled', false)
- voidMetricsService.capture('Disable Provider', { providerName })
- }
-
}
+
syncInstance()
const disposable = voidSettingsService.onDidChangeState(syncInstance)
return [disposable]
@@ -318,7 +300,10 @@ const ProviderSetting = ({ providerName, settingName }: { providerName: Provider
}
const SettingsForProvider = ({ providerName }: { providerName: ProviderName }) => {
- // const voidSettingsState = useSettingsState()
+ const voidSettingsState = useSettingsState()
+
+ const needsModel = isProviderNameDisabled(providerName, voidSettingsState) === 'addModel'
+
// const accessor = useAccessor()
// const voidSettingsService = accessor.get('IVoidSettingsService')
@@ -349,6 +334,12 @@ const SettingsForProvider = ({ providerName }: { providerName: ProviderName }) =
{settingNames.map((settingName, i) => {
return
})}
+
+ {needsModel ?
+ providerName === 'ollama' ?
+
+ :
+ : null}
}
diff --git a/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/WarningBox.tsx b/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/WarningBox.tsx
new file mode 100644
index 00000000..43faedd8
--- /dev/null
+++ b/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/WarningBox.tsx
@@ -0,0 +1,26 @@
+import { IconWarning } from '../sidebar-tsx/SidebarChat.js';
+
+
+export const WarningBox = ({ text, onClick, className }: { text: string; onClick?: () => void; className?: string }) => {
+
+ return
+
+ {text}
+
+ // return { }}
+ // />
+}
diff --git a/src/vs/workbench/contrib/void/browser/sidebarActions.ts b/src/vs/workbench/contrib/void/browser/sidebarActions.ts
index f05db4a8..0b60ae8f 100644
--- a/src/vs/workbench/contrib/void/browser/sidebarActions.ts
+++ b/src/vs/workbench/contrib/void/browser/sidebarActions.ts
@@ -140,13 +140,12 @@ registerAction2(class extends Action2 {
const setSelections = (s: StagingSelectionItem[]) => setStaging({ ...staging, selections: s })
// if matches with existing selection, overwrite (since text may change)
- const currentStagingEltIdx = findMatchingStagingIndex(selections, selection)
-
- if (currentStagingEltIdx !== undefined && currentStagingEltIdx !== -1) {
+ const matchingStagingEltIdx = findMatchingStagingIndex(selections, selection)
+ if (matchingStagingEltIdx !== undefined && matchingStagingEltIdx !== -1) {
setSelections([
- ...selections!.slice(0, currentStagingEltIdx),
+ ...selections!.slice(0, matchingStagingEltIdx),
selection,
- ...selections!.slice(currentStagingEltIdx + 1, Infinity)
+ ...selections!.slice(matchingStagingEltIdx + 1, Infinity)
])
}
// if no match, add it