From d8260524441c5a1090303018a3c3d40d681c559a Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Sun, 4 May 2025 19:32:28 -0700 Subject: [PATCH] add model overrides --- .../void/browser/autocompleteService.ts | 2 + .../contrib/void/browser/chatThreadService.ts | 2 + .../browser/convertToLLMMessageService.ts | 18 +- .../contrib/void/browser/editCodeService.ts | 108 ++++-- .../react/src/sidebar-tsx/SidebarChat.tsx | 6 +- .../src/void-settings-tsx/ModelDropdown.tsx | 2 +- .../react/src/void-settings-tsx/Settings.tsx | 343 +++++++++++++----- .../contrib/void/common/modelCapabilities.ts | 37 +- .../void/common/sendLLMMessageTypes.ts | 4 +- .../void/common/voidSettingsService.ts | 13 +- .../llmMessage/sendLLMMessage.impl.ts | 30 +- .../llmMessage/sendLLMMessage.ts | 5 +- 12 files changed, 388 insertions(+), 182 deletions(-) diff --git a/src/vs/workbench/contrib/void/browser/autocompleteService.ts b/src/vs/workbench/contrib/void/browser/autocompleteService.ts index bfd62321..22c86eb6 100644 --- a/src/vs/workbench/contrib/void/browser/autocompleteService.ts +++ b/src/vs/workbench/contrib/void/browser/autocompleteService.ts @@ -790,6 +790,7 @@ export class AutocompleteService extends Disposable implements IAutocompleteServ console.log('starting autocomplete...', predictionType) const featureName: FeatureName = 'Autocomplete' + const overridesOfModel = this._settingsService.state.overridesOfModel const modelSelection = this._settingsService.state.modelSelectionOfFeature[featureName] const modelSelectionOptions = modelSelection ? this._settingsService.state.optionsOfModelSelection[featureName][modelSelection.providerName]?.[modelSelection.modelName] : undefined @@ -807,6 +808,7 @@ export class AutocompleteService extends Disposable implements IAutocompleteServ }), modelSelection, modelSelectionOptions, + overridesOfModel, logging: { loggingName: 'Autocomplete' }, onText: () => { }, // unused in FIMMessage // onText: async ({ fullText, newText }) => { diff --git a/src/vs/workbench/contrib/void/browser/chatThreadService.ts b/src/vs/workbench/contrib/void/browser/chatThreadService.ts index 7c9eb899..82dfc7a3 100644 --- a/src/vs/workbench/contrib/void/browser/chatThreadService.ts +++ b/src/vs/workbench/contrib/void/browser/chatThreadService.ts @@ -641,6 +641,7 @@ class ChatThreadService extends Disposable implements IChatThreadService { // above just defines helpers, below starts the actual function const { chatMode } = this._settingsService.state.globalSettings // should not change as we loop even if user changes it, so it goes here + const { overridesOfModel } = this._settingsService.state let nMessagesSent = 0 let shouldSendAnotherMessage = true @@ -694,6 +695,7 @@ class ChatThreadService extends Disposable implements IChatThreadService { messages: messages, modelSelection, modelSelectionOptions, + overridesOfModel, logging: { loggingName: `Chat - ${chatMode}`, loggingExtras: { threadId, nMessagesSent, chatMode } }, separateSystemMessage: separateSystemMessage, onText: ({ fullText, fullReasoning, toolCall }) => { diff --git a/src/vs/workbench/contrib/void/browser/convertToLLMMessageService.ts b/src/vs/workbench/contrib/void/browser/convertToLLMMessageService.ts index 43b91c84..2a57ea7b 100644 --- a/src/vs/workbench/contrib/void/browser/convertToLLMMessageService.ts +++ b/src/vs/workbench/contrib/void/browser/convertToLLMMessageService.ts @@ -607,20 +607,23 @@ class ConvertToLLMMessageService extends Disposable implements IConvertToLLMMess prepareLLMSimpleMessages: IConvertToLLMMessageService['prepareLLMSimpleMessages'] = ({ simpleMessages, systemMessage, modelSelection, featureName }) => { if (modelSelection === null) return { messages: [], separateSystemMessage: undefined } + + const { overridesOfModel } = this.voidSettingsService.state + const { providerName, modelName } = modelSelection const { specialToolFormat, contextWindow, supportsSystemMessage, - } = getModelCapabilities(providerName, modelName) + } = getModelCapabilities(providerName, modelName, overridesOfModel) const modelSelectionOptions = this.voidSettingsService.state.optionsOfModelSelection[featureName][modelSelection.providerName]?.[modelSelection.modelName] // Get combined AI instructions const aiInstructions = this._getCombinedAIInstructions(); - const isReasoningEnabled = getIsReasoningEnabledState(featureName, providerName, modelName, modelSelectionOptions) - const maxOutputTokens = getMaxOutputTokens(providerName, modelName, { isReasoningEnabled }) + const isReasoningEnabled = getIsReasoningEnabledState(featureName, providerName, modelName, modelSelectionOptions, overridesOfModel) + const maxOutputTokens = getMaxOutputTokens(providerName, modelName, { isReasoningEnabled, overridesOfModel }) const { messages, separateSystemMessage } = prepareMessages({ messages: simpleMessages, @@ -637,12 +640,15 @@ class ConvertToLLMMessageService extends Disposable implements IConvertToLLMMess } prepareLLMChatMessages: IConvertToLLMMessageService['prepareLLMChatMessages'] = async ({ chatMessages, chatMode, modelSelection }) => { if (modelSelection === null) return { messages: [], separateSystemMessage: undefined } + + const { overridesOfModel } = this.voidSettingsService.state + const { providerName, modelName } = modelSelection const { specialToolFormat, contextWindow, supportsSystemMessage, - } = getModelCapabilities(providerName, modelName) + } = getModelCapabilities(providerName, modelName, overridesOfModel) const systemMessage = await this._generateChatMessagesSystemMessage(chatMode, specialToolFormat) const modelSelectionOptions = this.voidSettingsService.state.optionsOfModelSelection['Chat'][modelSelection.providerName]?.[modelSelection.modelName] @@ -650,8 +656,8 @@ class ConvertToLLMMessageService extends Disposable implements IConvertToLLMMess // Get combined AI instructions const aiInstructions = this._getCombinedAIInstructions(); - const isReasoningEnabled = getIsReasoningEnabledState('Chat', providerName, modelName, modelSelectionOptions) - const maxOutputTokens = getMaxOutputTokens(providerName, modelName, { isReasoningEnabled }) + const isReasoningEnabled = getIsReasoningEnabledState('Chat', providerName, modelName, modelSelectionOptions, overridesOfModel) + const maxOutputTokens = getMaxOutputTokens(providerName, modelName, { isReasoningEnabled, overridesOfModel }) const llmMessages = this._chatMessagesToSimpleMessages(chatMessages) const { messages, separateSystemMessage } = prepareMessages({ diff --git a/src/vs/workbench/contrib/void/browser/editCodeService.ts b/src/vs/workbench/contrib/void/browser/editCodeService.ts index f099fa25..41f45dce 100644 --- a/src/vs/workbench/contrib/void/browser/editCodeService.ts +++ b/src/vs/workbench/contrib/void/browser/editCodeService.ts @@ -106,37 +106,42 @@ const removeWhitespaceExceptNewlines = (str: string): string => { // finds block.orig in fileContents and return its range in file // startingAtLine is 1-indexed and inclusive -const findTextInCode = (text: string, fileContents: string, canFallbackToRemoveWhitespace: boolean, opts: { startingAtLine?: number, returnType: 'lines' | 'indices' }) => { +// returns 1-indexed lines +const findTextInCode = (text: string, fileContents: string, canFallbackToRemoveWhitespace: boolean, opts: { startingAtLine?: number, returnType: 'lines' }) => { - const startLineIdx = (fileContents: string) => opts?.startingAtLine !== undefined ? + const returnAns = (fileContents: string, idx: number) => { + const startLine = numLinesOfStr(fileContents.substring(0, idx + 1)) + const numLines = numLinesOfStr(text) + const endLine = startLine + numLines - 1 + + return [startLine, endLine] as const + } + + const startingAtLineIdx = (fileContents: string) => opts?.startingAtLine !== undefined ? fileContents.split('\n').slice(0, opts.startingAtLine).join('\n').length // num characters in all lines before startingAtLine : 0 // idx = starting index in fileContents - let idx = fileContents.indexOf(text, startLineIdx(fileContents)) + let idx = fileContents.indexOf(text, startingAtLineIdx(fileContents)) + + // if idx was found + if (idx !== -1) { + return returnAns(fileContents, idx) + } + + if (!canFallbackToRemoveWhitespace) + return 'Not found' as const // try to find it ignoring all whitespace this time - if (idx === -1 && canFallbackToRemoveWhitespace) { - text = removeWhitespaceExceptNewlines(text) - fileContents = removeWhitespaceExceptNewlines(fileContents) - idx = fileContents.indexOf(text, startLineIdx(fileContents)); - } + text = removeWhitespaceExceptNewlines(text) + fileContents = removeWhitespaceExceptNewlines(fileContents) + idx = fileContents.indexOf(text, startingAtLineIdx(fileContents)); if (idx === -1) return 'Not found' as const const lastIdx = fileContents.lastIndexOf(text) if (lastIdx !== idx) return 'Not unique' as const - if (opts.returnType === 'lines') { - const startLine = fileContents.substring(0, idx).split('\n').length - const numLines = numLinesOfStr(text) - const endLine = startLine + numLines - 1 - return [startLine, endLine] as const - } - - else if (opts.returnType === 'indices') { - return [idx, idx + text.length] as const - } - else throw new Error(`findTextInCode: Invalid returnType ${opts.returnType}`) + return returnAns(fileContents, idx) } @@ -1331,6 +1336,7 @@ class EditCodeService extends Disposable implements IEditCodeService { const { from, } = opts const featureName: FeatureName = opts.from === 'ClickApply' ? 'Apply' : 'Ctrl+K' + const overridesOfModel = this._settingsService.state.overridesOfModel const modelSelection = this._settingsService.state.modelSelectionOfFeature[featureName] const modelSelectionOptions = modelSelection ? this._settingsService.state.optionsOfModelSelection[featureName][modelSelection.providerName]?.[modelSelection.modelName] : undefined @@ -1482,6 +1488,7 @@ class EditCodeService extends Disposable implements IEditCodeService { messages, modelSelection, modelSelectionOptions, + overridesOfModel, separateSystemMessage, chatMode: null, // not chat onText: (params) => { @@ -1556,17 +1563,30 @@ class EditCodeService extends Disposable implements IEditCodeService { } - private _errContentOfInvalidStr = (str: 'Not found' | 'Not unique' | 'Has overlap', blockOrig: string) => { - + /** + * Generates a human-readable error message for an invalid ORIGINAL search block. + */ + private _errContentOfInvalidStr = ( + str: 'Not found' | 'Not unique' | 'Has overlap', + blockOrig: string, + ): string => { const problematicCode = `${tripleTick[0]}\n${JSON.stringify(blockOrig)}\n${tripleTick[1]}` - const descStr = str === `Not found` ? - `The edit was not applied. The text in ORIGINAL must EXACTLY match lines of code in the file, but there was no match for:\n${problematicCode}. Ensure you have the latest version of the file, and ensure the ORIGINAL code matches a code excerpt exactly.` - : str === `Not unique` ? - `The edit was not applied. The text in ORIGINAL must be unique in the file being edited, but the following ORIGINAL code appears multiple times in the file:\n${problematicCode}. Ensure you have the latest version of the file, and ensure the ORIGINAL code is unique.` - : str === 'Has overlap' ? - `The edit was not applied. The text in the ORIGINAL blocks must not overlap, but the following ORIGINAL code had overlap with another ORIGINAL string:\n${problematicCode}. Ensure you have the latest version of the file, and ensure the ORIGINAL code blocks do not overlap.` - : `` + // use a switch for better readability / exhaustiveness check + let descStr: string + switch (str) { + case 'Not found': + descStr = `The edit was not applied. The text in ORIGINAL must EXACTLY match lines of code in the file, but there was no match for:\n${problematicCode}. Ensure you have the latest version of the file, and ensure the ORIGINAL code matches a code excerpt exactly.` + break + case 'Not unique': + descStr = `The edit was not applied. The text in ORIGINAL must be unique in the file being edited, but the following ORIGINAL code appears multiple times in the file:\n${problematicCode}. Ensure you have the latest version of the file, and ensure the ORIGINAL code is unique.` + break + case 'Has overlap': + descStr = `The edit was not applied. The text in the ORIGINAL blocks must not overlap, but the following ORIGINAL code had overlap with another ORIGINAL string:\n${problematicCode}. Ensure you have the latest version of the file, and ensure the ORIGINAL code blocks do not overlap.` + break + default: + descStr = '' + } return descStr } @@ -1578,22 +1598,34 @@ class EditCodeService extends Disposable implements IEditCodeService { const { model } = this._voidModelService.getModel(uri) if (!model) throw new Error(`Error applying Search/Replace blocks: File does not exist.`) const modelStr = model.getValue(EndOfLinePreference.LF) + // .split('\n').map(l => '\t' + l).join('\n') // for testing purposes only, remember to remove this + const modelStrLines = modelStr.split('\n') + + const replacements: { origStart: number; origEnd: number; block: ExtractedSearchReplaceBlock }[] = [] for (const b of blocks) { - const res = findTextInCode(b.orig, modelStr, true, { returnType: 'indices' }) + const res = findTextInCode(b.orig, modelStr, true, { returnType: 'lines' }) if (typeof res === 'string') throw new Error(this._errContentOfInvalidStr(res, b.orig)) - const [i, _] = res + let [startLine, endLine] = res + startLine -= 1 // 0-index + endLine -= 1 - replacements.push({ - origStart: i, - origEnd: i + b.orig.length - 1, // INCLUSIVE - block: b, - }) + // including newline before start + const contentBeforeStart = startLine !== 0 ? + modelStrLines.slice(0, startLine).join('\n') + '\n' + : '' + + // including endline at end + const contentUpToEnd = modelStrLines.slice(0, endLine + 1).join('\n') + + const origStart = contentBeforeStart.length; + const origEnd = contentUpToEnd.length; + + replacements.push({ origStart, origEnd, block: b }); } - // sort in increasing order replacements.sort((a, b) => a.origStart - b.origStart) @@ -1610,17 +1642,18 @@ class EditCodeService extends Disposable implements IEditCodeService { const { origStart, origEnd, block } = replacements[i] newCode = newCode.slice(0, origStart) + block.final + newCode.slice(origEnd + 1, Infinity) } + console.log('REPLACEMENTS', replacements, newCode) this._writeURIText(uri, newCode, 'wholeFileRange', { shouldRealignDiffAreas: true } ) - } private _initializeSearchAndReplaceStream(opts: StartApplyingOpts & { from: 'ClickApply' }): [DiffZone, Promise] | undefined { const { from, applyStr, } = opts const featureName: FeatureName = 'Apply' + const overridesOfModel = this._settingsService.state.overridesOfModel const modelSelection = this._settingsService.state.modelSelectionOfFeature[featureName] const modelSelectionOptions = modelSelection ? this._settingsService.state.optionsOfModelSelection[featureName][modelSelection.providerName]?.[modelSelection.modelName] : undefined @@ -1900,6 +1933,7 @@ class EditCodeService extends Disposable implements IEditCodeService { messages, modelSelection, modelSelectionOptions, + overridesOfModel, separateSystemMessage, chatMode: null, // not chat onText: (params) => { diff --git a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx index 568c5aac..a202973f 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx @@ -153,14 +153,16 @@ const ReasoningOptionSlider = ({ featureName }: { featureName: FeatureName }) => const voidSettingsState = useSettingsState() const modelSelection = voidSettingsState.modelSelectionOfFeature[featureName] + const overridesOfModel = voidSettingsState.overridesOfModel + if (!modelSelection) return null const { modelName, providerName } = modelSelection - const { reasoningCapabilities } = getModelCapabilities(providerName, modelName) + const { reasoningCapabilities } = getModelCapabilities(providerName, modelName, overridesOfModel) const { canTurnOffReasoning, reasoningBudgetSlider } = reasoningCapabilities || {} const modelSelectionOptions = voidSettingsState.optionsOfModelSelection[featureName][providerName]?.[modelName] - const isReasoningEnabled = getIsReasoningEnabledState(featureName, providerName, modelName, modelSelectionOptions) + const isReasoningEnabled = getIsReasoningEnabledState(featureName, providerName, modelName, modelSelectionOptions, overridesOfModel) if (canTurnOffReasoning && !reasoningBudgetSlider) { // if it's just a on/off toggle without a power slider (no models right now) return null // unused right now // return
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 87ddf7d6..3facd801 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 @@ -56,7 +56,7 @@ const MemoizedModelDropdown = ({ featureName, className }: { featureName: Featur useEffect(() => { const oldOptions = oldOptionsRef.current - const newOptions = settingsState._modelOptions.filter((o) => filter(o.selection, { chatMode: settingsState.globalSettings.chatMode })) + const newOptions = settingsState._modelOptions.filter((o) => filter(o.selection, { chatMode: settingsState.globalSettings.chatMode, overridesOfModel: settingsState.overridesOfModel })) if (!optionsEqual(oldOptions, newOptions)) { setMemoizedOptions(newOptions) 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 8c9c1461..de93ce27 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 @@ -303,7 +303,7 @@ export const AddModelInputBox = ({ providerName: permanentProviderName, classNam // Import the getModelCapabilities function to access default values -import { defaultModelOptions, getModelCapabilities, ModelOverrideOptions } from '../../../../common/modelCapabilities.js'; +import { getModelCapabilities, ModelOverrideOptions } from '../../../../common/modelCapabilities.js'; // Modal dialog to show model settings const ModelSettingsDialog = ({ @@ -324,45 +324,68 @@ const ModelSettingsDialog = ({ // Get current model capabilities and override settings const modelCapabilities = getModelCapabilities(providerName, modelName, settingsState.overridesOfModel); + const defaultModelCapabilities = getModelCapabilities(providerName, modelName, undefined) // Initialize form state for all potential override options const [formValues, setFormValues] = useState<{ contextWindow: string; maxOutputTokens: string; - supportsTools: 'openai-style' | undefined | ''; - supportsSystemMessage: 'system-role' | 'developer-role' | false | ''; + specialToolFormat: 'openai-style' | 'gemini-style' | 'anthropic-style' | undefined | ''; + supportsSystemMessage: 'system-role' | 'developer-role' | 'separated' | false | ''; supportsFIM: boolean | null; reasoningCapabilities: boolean | null; + canTurnOffReasoning: boolean; + reasoningMaxOutputTokens: string; + openSourceThinkTags: [string, string] | null; }>({ + // start form as default values contextWindow: '', maxOutputTokens: '', - supportsTools: '', + specialToolFormat: '', supportsSystemMessage: '', supportsFIM: null, - reasoningCapabilities: null + reasoningCapabilities: null, + canTurnOffReasoning: false, + reasoningMaxOutputTokens: '', + openSourceThinkTags: null, }); // When dialog opens or model changes, reset form values useEffect(() => { if (isOpen && modelInfo) { - // Get current overrides const overrides = settingsState.overridesOfModel?.[providerName]?.[modelName] || {}; + // Extract reasoning capabilities if available (use any to avoid TS union narrowing issues) + const reasoningCapabilities: any = typeof overrides.reasoningCapabilities === 'object' ? + overrides.reasoningCapabilities : overrides.reasoningCapabilities ? { supportsReasoning: true, canIOReasoning: true } : false; + + // Extract the think tags if they exist + let thinkTags: [string, string] | null = null; + if (typeof reasoningCapabilities === 'object' && reasoningCapabilities.openSourceThinkTags) { + thinkTags = reasoningCapabilities.openSourceThinkTags as [string, string]; + } + + // Only set values that are explicitly overridden, otherwise leave them empty + // to indicate default values should be used setFormValues({ - contextWindow: (overrides.contextWindow !== undefined) ? overrides.contextWindow?.toString() : '', - maxOutputTokens: (overrides.maxOutputTokens !== undefined) ? overrides.maxOutputTokens?.toString() : '', - supportsTools: overrides.supportsTools !== undefined ? overrides.supportsTools : '', + contextWindow: overrides.contextWindow !== undefined ? String(overrides.contextWindow) : '', + maxOutputTokens: overrides.maxOutputTokens !== undefined ? String(overrides.maxOutputTokens) : '', + specialToolFormat: overrides.specialToolFormat !== undefined ? overrides.specialToolFormat : '', supportsSystemMessage: overrides.supportsSystemMessage !== undefined ? overrides.supportsSystemMessage : '', supportsFIM: overrides.supportsFIM !== undefined ? overrides.supportsFIM : null, reasoningCapabilities: overrides.reasoningCapabilities !== undefined ? - !!overrides.reasoningCapabilities : null + !!overrides.reasoningCapabilities : null, + canTurnOffReasoning: typeof reasoningCapabilities === 'object' ? !!reasoningCapabilities.canTurnOffReasoning : false, + reasoningMaxOutputTokens: typeof reasoningCapabilities === 'object' && reasoningCapabilities.reasoningMaxOutputTokens ? + String(reasoningCapabilities.reasoningMaxOutputTokens) : '', + openSourceThinkTags: thinkTags, }); } }, [isOpen, modelInfo, settingsState.overridesOfModel, providerName, modelName]); // Update a single field in the form - const updateField = (field: string, value: any) => { + const updateField = (field: keyof typeof formValues, value: any) => { setFormValues(prev => ({ ...prev, [field]: value @@ -371,52 +394,78 @@ const ModelSettingsDialog = ({ // Handle saving settings const handleSave = async () => { - const settings: ModelOverrideOptions = {}; + // Get current overrides to see what needs to be updated/removed + const currentOverrides = settingsState.overridesOfModel?.[providerName]?.[modelName] || {}; + const newSettings: ModelOverrideOptions = {}; - // Only add fields to the override if they have been changed from defaults - if (formValues.contextWindow) { + // Handle numeric fields - empty strings should remove the override + if (formValues.contextWindow.trim() === '') { + newSettings.contextWindow = defaultModelCapabilities.contextWindow; + } else if (formValues.contextWindow) { const tokens = parseInt(formValues.contextWindow); - if (!isNaN(tokens)) settings.contextWindow = tokens; + if (!isNaN(tokens)) newSettings.contextWindow = tokens; } - if (formValues.maxOutputTokens) { + if (formValues.maxOutputTokens.trim() === '') { + newSettings.maxOutputTokens = defaultModelCapabilities.maxOutputTokens; + } else if (formValues.maxOutputTokens) { const tokens = parseInt(formValues.maxOutputTokens); - if (!isNaN(tokens)) settings.maxOutputTokens = tokens; + if (!isNaN(tokens)) newSettings.maxOutputTokens = tokens; } - if (formValues.supportsTools !== '') { - settings.supportsTools = formValues.supportsTools as any; + // Handle dropdown fields + if (formValues.specialToolFormat === '') { + newSettings.specialToolFormat = defaultModelCapabilities.specialToolFormat + } else { + newSettings.specialToolFormat = formValues.specialToolFormat } - if (formValues.supportsSystemMessage !== '') { - settings.supportsSystemMessage = formValues.supportsSystemMessage as any; + if (formValues.supportsSystemMessage === '') { + newSettings.supportsSystemMessage = defaultModelCapabilities.supportsSystemMessage; + } else { + newSettings.supportsSystemMessage = formValues.supportsSystemMessage as any; } - if (formValues.supportsFIM !== null) { - settings.supportsFIM = formValues.supportsFIM; + if (formValues.supportsFIM === null) { + newSettings.supportsFIM = defaultModelCapabilities.supportsFIM + } else { + newSettings.supportsFIM = formValues.supportsFIM; } - if (formValues.reasoningCapabilities !== null) { - if (formValues.reasoningCapabilities) { - settings.reasoningCapabilities = { - supportsReasoning: true, - canTurnOffReasoning: true, - canIOReasoning: true - }; - } else { - settings.reasoningCapabilities = false; + if (formValues.reasoningCapabilities === null) { + newSettings.reasoningCapabilities = defaultModelCapabilities.reasoningCapabilities; + } else if (formValues.reasoningCapabilities) { + const reasoningSettings: any = { + supportsReasoning: true, + canIOReasoning: true, + canTurnOffReasoning: formValues.canTurnOffReasoning + }; + + // Only add these if they have values + if (formValues.reasoningMaxOutputTokens) { + reasoningSettings.reasoningMaxOutputTokens = parseInt(formValues.reasoningMaxOutputTokens); } + + if (formValues.openSourceThinkTags) { + reasoningSettings.openSourceThinkTags = formValues.openSourceThinkTags; + } + + newSettings.reasoningCapabilities = reasoningSettings; + } else { + newSettings.reasoningCapabilities = false; } - await settingsStateService.setOverridesOfModel(providerName, modelName, settings); + await settingsStateService.setOverridesOfModel(providerName, modelName, newSettings); onClose(); }; + + return (
e.stopPropagation()}>
-

Override defaults for {modelName} ({displayInfoOfProviderName(providerName).title})

+

Change Defaults for {modelName} ({displayInfoOfProviderName(providerName).title})

@@ -429,25 +478,51 @@ const ModelSettingsDialog = ({ {/* Context window */}
Context window (tokens) - updateField('contextWindow', value)} - placeholder={(modelCapabilities.contextWindow || defaultModelOptions.contextWindow) + ''} - compact={true} - className="max-w-24" - /> +
+ { + updateField('contextWindow', enabled ? String(defaultModelCapabilities.contextWindow) : ''); + }} + /> + {formValues.contextWindow === '' ? ( + Default ({defaultModelCapabilities.contextWindow}) + ) : ( + updateField('contextWindow', value)} + placeholder={String(defaultModelCapabilities.contextWindow)} + compact={true} + className="max-w-24" + /> + )} +
{/* Maximum output tokens */}
Maximum output tokens - updateField('maxOutputTokens', value)} - placeholder={(modelCapabilities.maxOutputTokens || defaultModelOptions.maxOutputTokens) + ''} - compact={true} - className="max-w-24" - /> +
+ { + updateField('maxOutputTokens', enabled ? String(defaultModelCapabilities.maxOutputTokens) : ''); + }} + /> + {formValues.maxOutputTokens === '' ? ( + Default ({defaultModelCapabilities.maxOutputTokens}) + ) : ( + updateField('maxOutputTokens', value)} + placeholder={String(defaultModelCapabilities.maxOutputTokens)} + compact={true} + className="max-w-24" + /> + )} +
{/* Supports Tools */} @@ -455,10 +530,10 @@ const ModelSettingsDialog = ({ Supports tools updateField('supportsTools', value)} + selectedOption={formValues.specialToolFormat} + onChangeOption={(value) => updateField('specialToolFormat', value)} getOptionDisplayName={(opt) => { - if (opt === '') return `Default (${modelCapabilities.specialToolFormat || 'No'})`; + if (opt === '') return `Default (${defaultModelCapabilities.specialToolFormat || 'No'})`; return opt; }} getOptionDropdownName={(opt) => { @@ -478,7 +553,7 @@ const ModelSettingsDialog = ({ selectedOption={formValues.supportsSystemMessage} onChangeOption={(value) => updateField('supportsSystemMessage', value)} getOptionDisplayName={(opt) => { - if (opt === '') return `Default (${modelCapabilities.supportsSystemMessage || 'No'})`; + if (opt === '') return `Default (${defaultModelCapabilities.supportsSystemMessage || 'No'})`; if (opt === false) return 'No' if (opt === true) return 'Yes' // should never happen return opt; @@ -502,7 +577,7 @@ const ModelSettingsDialog = ({ selectedOption={formValues.supportsFIM} onChangeOption={(value) => updateField('supportsFIM', value)} getOptionDisplayName={(opt) => { - if (opt === null) return `Default (${modelCapabilities.supportsFIM ? 'Yes' : 'No'})`; + if (opt === null) return `Default (${defaultModelCapabilities.supportsFIM ? 'Yes' : 'No'})`; return opt ? 'Yes' : 'No'; }} getOptionDropdownName={(opt) => { @@ -522,7 +597,7 @@ const ModelSettingsDialog = ({ selectedOption={formValues.reasoningCapabilities} onChangeOption={(value) => updateField('reasoningCapabilities', value)} getOptionDisplayName={(opt) => { - if (opt === null) return `Default (${modelCapabilities.reasoningCapabilities ? 'Yes' : 'No'})`; + if (opt === null) return `Default (${defaultModelCapabilities.reasoningCapabilities ? 'Yes' : 'No'})`; return opt ? 'Yes' : 'No'; }} getOptionDropdownName={(opt) => { @@ -533,6 +608,100 @@ const ModelSettingsDialog = ({ className="max-w-32 text-xs" />
+ + {/* Additional reasoning options - only show when reasoning is enabled */} + {formValues.reasoningCapabilities && ( + <> + {/* Can Turn Off Reasoning */} +
+ Allow turning off reasoning + updateField('canTurnOffReasoning', value)} + getOptionDisplayName={(opt) => opt ? 'Yes' : 'No'} + getOptionDropdownName={(opt) => opt ? 'Yes' : 'No'} + getOptionsEqual={(a, b) => a === b} + className="max-w-32 text-xs" + /> +
+ + {/* Reasoning Max Output Tokens - only shown if canTurnOffReasoning is true */} + {formValues.canTurnOffReasoning && ( +
+ Max output tokens when reasoning +
+ { + // Use a reasonable default value when enabling + const defaultValue = defaultModelCapabilities.maxOutputTokens || 500; + updateField('reasoningMaxOutputTokens', enabled ? String(defaultValue) : ''); + }} + /> + {formValues.reasoningMaxOutputTokens === '' ? ( + Default + ) : ( + updateField('reasoningMaxOutputTokens', value)} + placeholder="Default" + compact={true} + className="max-w-24" + /> + )} +
+
+ )} + + {/* Open Source Think Tags Toggle + Input Fields */} +
+ Open source think tags +
+ { + if (enabled) { + // Enable with default values + updateField('openSourceThinkTags', ['', '']); + } else { + // Disable + updateField('openSourceThinkTags', null); + } + }} + /> + + {formValues.openSourceThinkTags !== null && ( +
+ { + const currentTags = formValues.openSourceThinkTags || ['', '']; + updateField('openSourceThinkTags', [value, currentTags[1]]); + }} + placeholder="" + compact={true} + className="max-w-16" + /> + ... + { + const currentTags = formValues.openSourceThinkTags || ['', '']; + updateField('openSourceThinkTags', [currentTags[0], value]); + }} + placeholder="" + compact={true} + className="max-w-16" + /> +
+ )} +
+
+ + )}
@@ -587,8 +756,8 @@ export const ModelDump = () => { const tooltipName = ( disabled ? `Add ${providerTitle} to enable` - : value === true ? 'Enabled' - : 'Disabled' + : value === true ? 'Show in Dropdown' + : 'Hide from Dropdown' ) @@ -601,50 +770,39 @@ export const ModelDump = () => { return
{/* left part is width:full */} -
+
{isNewProviderName ? providerTitle : ''} - {modelName}{detailAboutModel} + {modelName}
+ {/* right part is anything that fits */} -
- - - {/* {type === 'autodetected' ? '(detected locally)' : type === 'default' ? '' : '(custom model)'} */} - - {/* Settings button - only for custom or locally detected models */} - {(type === 'autodetected' || type === 'custom') && ( -
- -
- )} +
+ + {/* Advanced Settings button - only for custom or locally detected models */} +
+ +
+ + {/* Blue star */} + {detailAboutModel} + {/* Switch */} { settingsStateService.toggleModelHidden(providerName, modelName) }} + onChange={() => { settingsStateService.toggleModelHidden(providerName, modelName); }} disabled={disabled} size='sm' @@ -653,8 +811,9 @@ export const ModelDump = () => { data-tooltip-content={tooltipName} /> + {/* X button */}
- {type === 'default' || type === 'autodetected' ? null : } + {type === 'default' || type === 'autodetected' ? null : }
@@ -1301,7 +1460,7 @@ export const Settings = () => { Only works with FIM models.* diff --git a/src/vs/workbench/contrib/void/common/modelCapabilities.ts b/src/vs/workbench/contrib/void/common/modelCapabilities.ts index cc2a4fce..c30df73a 100644 --- a/src/vs/workbench/contrib/void/common/modelCapabilities.ts +++ b/src/vs/workbench/contrib/void/common/modelCapabilities.ts @@ -173,22 +173,9 @@ export type VoidStaticModelInfo = { // not stateful } -export type ModelOverrideOptions = Partial<{ - contextWindow: number; // input tokens - maxOutputTokens: number; // output tokens, defaults to 4092 - supportsTools: 'openai-style' | undefined; - supportsSystemMessage: 'system-role' | 'developer-role' | false; - supportsFIM: boolean; - reasoningCapabilities: false | { - readonly supportsReasoning: true; - readonly canTurnOffReasoning: boolean; - readonly canIOReasoning: boolean; - readonly reasoningMaxOutputTokens?: number; - readonly openSourceThinkTags?: [string, string]; - } -}> - - +export type ModelOverrideOptions = Partial> @@ -210,7 +197,7 @@ type VoidStaticProviderInfo = { // doesn't change (not stateful) -export const defaultModelOptions = { +const defaultModelOptions = { contextWindow: 4_096, maxOutputTokens: 4_096, cost: { input: 0, output: 0 }, @@ -1155,7 +1142,7 @@ const modelSettingsOfProvider: { [providerName in ProviderName]: VoidStaticProvi export const getModelCapabilities = ( providerName: ProviderName, modelName: string, - overridesOfModel?: OverridesOfModel + overridesOfModel: OverridesOfModel | undefined ): VoidStaticModelInfo & { modelName: string; isUnrecognizedModel: boolean } => { const lowercaseModelName = modelName.toLowerCase() @@ -1201,8 +1188,9 @@ export const getIsReasoningEnabledState = ( providerName: ProviderName, modelName: string, modelSelectionOptions: ModelSelectionOptions | undefined, + overridesOfModel: OverridesOfModel | undefined, ) => { - const { supportsReasoning, canTurnOffReasoning } = getModelCapabilities(providerName, modelName).reasoningCapabilities || {} + const { supportsReasoning, canTurnOffReasoning } = getModelCapabilities(providerName, modelName, overridesOfModel).reasoningCapabilities || {} if (!supportsReasoning) return false // default to enabled if can't turn off, or if the featureName is Chat. @@ -1213,11 +1201,11 @@ export const getIsReasoningEnabledState = ( } -export const getMaxOutputTokens = (providerName: ProviderName, modelName: string, opts: { isReasoningEnabled: boolean }) => { +export const getMaxOutputTokens = (providerName: ProviderName, modelName: string, opts: { isReasoningEnabled: boolean, overridesOfModel: OverridesOfModel | undefined }) => { const { reasoningCapabilities, - maxOutputTokens - } = getModelCapabilities(providerName, modelName) + maxOutputTokens, + } = getModelCapabilities(providerName, modelName, opts.overridesOfModel) return opts.isReasoningEnabled && reasoningCapabilities ? reasoningCapabilities.reasoningMaxOutputTokens : maxOutputTokens } @@ -1227,11 +1215,12 @@ export const getSendableReasoningInfo = ( providerName: ProviderName, modelName: string, modelSelectionOptions: ModelSelectionOptions | undefined, + overridesOfModel: OverridesOfModel | undefined, ): SendableReasoningInfo => { - const { canIOReasoning, reasoningBudgetSlider } = getModelCapabilities(providerName, modelName).reasoningCapabilities || {} + const { canIOReasoning, reasoningBudgetSlider } = getModelCapabilities(providerName, modelName, overridesOfModel).reasoningCapabilities || {} if (!canIOReasoning) return null - const isReasoningEnabled = getIsReasoningEnabledState(featureName, providerName, modelName, modelSelectionOptions) + const isReasoningEnabled = getIsReasoningEnabledState(featureName, providerName, modelName, modelSelectionOptions, overridesOfModel) if (!isReasoningEnabled) return null // check for reasoning budget diff --git a/src/vs/workbench/contrib/void/common/sendLLMMessageTypes.ts b/src/vs/workbench/contrib/void/common/sendLLMMessageTypes.ts index d76d6685..6b7cad52 100644 --- a/src/vs/workbench/contrib/void/common/sendLLMMessageTypes.ts +++ b/src/vs/workbench/contrib/void/common/sendLLMMessageTypes.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------*/ import { ToolName, ToolParamName } from './prompt/prompts.js' -import { ChatMode, ModelSelection, ModelSelectionOptions, ProviderName, RefreshableProviderName, SettingsOfProvider } from './voidSettingsTypes.js' +import { ChatMode, ModelSelection, ModelSelectionOptions, OverridesOfModel, ProviderName, RefreshableProviderName, SettingsOfProvider } from './voidSettingsTypes.js' export const errorDetails = (fullError: Error | null): string | null => { @@ -116,6 +116,7 @@ export type ServiceSendLLMMessageParams = { logging: { loggingName: string, loggingExtras?: { [k: string]: any } }; modelSelection: ModelSelection | null; modelSelectionOptions: ModelSelectionOptions | undefined; + overridesOfModel: OverridesOfModel | undefined; onAbort: OnAbort; } & SendLLMType; @@ -129,6 +130,7 @@ export type SendLLMMessageParams = { modelSelection: ModelSelection; modelSelectionOptions: ModelSelectionOptions | undefined; + overridesOfModel: OverridesOfModel | undefined; settingsOfProvider: SettingsOfProvider; } & SendLLMType diff --git a/src/vs/workbench/contrib/void/common/voidSettingsService.ts b/src/vs/workbench/contrib/void/common/voidSettingsService.ts index 462d7899..f8081b9c 100644 --- a/src/vs/workbench/contrib/void/common/voidSettingsService.ts +++ b/src/vs/workbench/contrib/void/common/voidSettingsService.ts @@ -96,8 +96,15 @@ const _modelsWithSwappedInNewModels = (options: { existingModels: VoidStatefulMo } -export const modelFilterOfFeatureName: { [featureName in FeatureName]: { filter: (o: ModelSelection, opts: { chatMode: ChatMode }) => boolean; emptyMessage: null | { message: string, priority: 'always' | 'fallback' } } } = { - 'Autocomplete': { filter: (o) => getModelCapabilities(o.providerName, o.modelName).supportsFIM, emptyMessage: { message: 'No models support FIM', priority: 'always' } }, +export const modelFilterOfFeatureName: { + [featureName in FeatureName]: { + filter: ( + o: ModelSelection, + opts: { chatMode: ChatMode, overridesOfModel: OverridesOfModel } + ) => boolean; + emptyMessage: null | { message: string, priority: 'always' | 'fallback' } + } } = { + 'Autocomplete': { filter: (o, opts) => getModelCapabilities(o.providerName, o.modelName, opts.overridesOfModel).supportsFIM, emptyMessage: { message: 'No models support FIM', priority: 'always' } }, 'Chat': { filter: o => true, emptyMessage: null, }, 'Ctrl+K': { filter: o => true, emptyMessage: null, }, 'Apply': { filter: o => true, emptyMessage: null, }, @@ -165,7 +172,7 @@ const _validatedModelState = (state: Omit): for (const featureName of featureNames) { const { filter } = modelFilterOfFeatureName[featureName] - const filterOpts = { chatMode: state.globalSettings.chatMode } + const filterOpts = { chatMode: state.globalSettings.chatMode, overridesOfModel: state.overridesOfModel } const modelOptionsForThisFeature = newModelOptions.filter((o) => filter(o.selection, filterOpts)) const modelSelectionAtFeature = newModelSelectionOfFeature[featureName] diff --git a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts index 95b68e45..9b6a51cd 100644 --- a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts +++ b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts @@ -15,7 +15,7 @@ import { GoogleAuth } from 'google-auth-library' /* eslint-enable */ import { AnthropicLLMChatMessage, LLMChatMessage, LLMFIMMessage, ModelListParams, OllamaModelResponse, OnError, OnFinalMessage, OnText, RawToolCallObj, RawToolParamsObj } from '../../common/sendLLMMessageTypes.js'; -import { ChatMode, displayInfoOfProviderName, ModelSelectionOptions, ProviderName, SettingsOfProvider } from '../../common/voidSettingsTypes.js'; +import { ChatMode, displayInfoOfProviderName, ModelSelectionOptions, OverridesOfModel, ProviderName, SettingsOfProvider } from '../../common/voidSettingsTypes.js'; import { getSendableReasoningInfo, getModelCapabilities, getProviderCapabilities, defaultProviderSettings, getMaxOutputTokens } from '../../common/modelCapabilities.js'; import { extractReasoningWrapper, extractXMLToolsWrapper } from './extractGrammar.js'; import { availableTools, InternalToolInfo, isAToolName, ToolParamName, voidTools } from '../../common/prompt/prompts.js'; @@ -39,6 +39,7 @@ type InternalCommonMessageParams = { providerName: ProviderName; settingsOfProvider: SettingsOfProvider; modelSelectionOptions: ModelSelectionOptions | undefined; + overridesOfModel: OverridesOfModel | undefined; modelName: string; _setAborter: (aborter: () => void) => void; } @@ -144,9 +145,9 @@ const newOpenAICompatibleSDK = async ({ settingsOfProvider, providerName, includ } -const _sendOpenAICompatibleFIM = async ({ messages: { prefix, suffix, stopTokens }, onFinalMessage, onError, settingsOfProvider, modelName: modelName_, _setAborter, providerName, }: SendFIMParams_Internal) => { +const _sendOpenAICompatibleFIM = async ({ messages: { prefix, suffix, stopTokens }, onFinalMessage, onError, settingsOfProvider, modelName: modelName_, _setAborter, providerName, overridesOfModel }: SendFIMParams_Internal) => { - const { modelName, supportsFIM } = getModelCapabilities(providerName, modelName_) + const { modelName, supportsFIM } = getModelCapabilities(providerName, modelName_, overridesOfModel) if (!supportsFIM) { if (modelName === modelName_) onError({ message: `Model ${modelName} does not support FIM.`, fullError: null }) @@ -230,18 +231,18 @@ const rawToolCallObjOf = (name: string, toolParamsStr: string, id: string): RawT // ------------ OPENAI-COMPATIBLE ------------ -const _sendOpenAICompatibleChat = async ({ messages, onText, onFinalMessage, onError, settingsOfProvider, modelSelectionOptions, modelName: modelName_, _setAborter, providerName, chatMode, separateSystemMessage }: SendChatParams_Internal) => { +const _sendOpenAICompatibleChat = async ({ messages, onText, onFinalMessage, onError, settingsOfProvider, modelSelectionOptions, modelName: modelName_, _setAborter, providerName, chatMode, separateSystemMessage, overridesOfModel }: SendChatParams_Internal) => { const { modelName, specialToolFormat, reasoningCapabilities, - } = getModelCapabilities(providerName, modelName_) + } = getModelCapabilities(providerName, modelName_, overridesOfModel) const { providerReasoningIOSettings } = getProviderCapabilities(providerName) // reasoning const { canIOReasoning, openSourceThinkTags, } = reasoningCapabilities || {} - const reasoningInfo = getSendableReasoningInfo('Chat', providerName, modelName_, modelSelectionOptions) // user's modelName_ here + const reasoningInfo = getSendableReasoningInfo('Chat', providerName, modelName_, modelSelectionOptions, overridesOfModel) // user's modelName_ here const includeInPayload = providerReasoningIOSettings?.input?.includeInPayload?.(reasoningInfo) || {} // tools @@ -415,21 +416,21 @@ const anthropicToolToRawToolCallObj = (toolBlock: Anthropic.Messages.ToolUseBloc } // ------------ ANTHROPIC ------------ -const sendAnthropicChat = async ({ messages, providerName, onText, onFinalMessage, onError, settingsOfProvider, modelSelectionOptions, modelName: modelName_, _setAborter, separateSystemMessage, chatMode }: SendChatParams_Internal) => { +const sendAnthropicChat = async ({ messages, providerName, onText, onFinalMessage, onError, settingsOfProvider, modelSelectionOptions, overridesOfModel, modelName: modelName_, _setAborter, separateSystemMessage, chatMode }: SendChatParams_Internal) => { const { modelName, specialToolFormat, - } = getModelCapabilities(providerName, modelName_) + } = getModelCapabilities(providerName, modelName_, overridesOfModel) const thisConfig = settingsOfProvider.anthropic const { providerReasoningIOSettings } = getProviderCapabilities(providerName) // reasoning - const reasoningInfo = getSendableReasoningInfo('Chat', providerName, modelName_, modelSelectionOptions) // user's modelName_ here + const reasoningInfo = getSendableReasoningInfo('Chat', providerName, modelName_, modelSelectionOptions, overridesOfModel) // user's modelName_ here const includeInPayload = providerReasoningIOSettings?.input?.includeInPayload?.(reasoningInfo) || {} // anthropic-specific - max tokens - const maxTokens = getMaxOutputTokens(providerName, modelName_, { isReasoningEnabled: !!reasoningInfo?.isReasoningEnabled }) + const maxTokens = getMaxOutputTokens(providerName, modelName_, { isReasoningEnabled: !!reasoningInfo?.isReasoningEnabled, overridesOfModel }) // tools const potentialTools = chatMode !== null ? anthropicTools(chatMode) : null @@ -539,8 +540,8 @@ const sendAnthropicChat = async ({ messages, providerName, onText, onFinalMessag // ------------ MISTRAL ------------ // https://docs.mistral.ai/api/#tag/fim -const sendMistralFIM = ({ messages, onFinalMessage, onError, settingsOfProvider, modelName: modelName_, _setAborter, providerName }: SendFIMParams_Internal) => { - const { modelName, supportsFIM } = getModelCapabilities(providerName, modelName_) +const sendMistralFIM = ({ messages, onFinalMessage, onError, settingsOfProvider, overridesOfModel, modelName: modelName_, _setAborter, providerName }: SendFIMParams_Internal) => { + const { modelName, supportsFIM } = getModelCapabilities(providerName, modelName_, overridesOfModel) if (!supportsFIM) { if (modelName === modelName_) onError({ message: `Model ${modelName} does not support FIM.`, fullError: null }) @@ -679,6 +680,7 @@ const sendGeminiChat = async ({ onFinalMessage, onError, settingsOfProvider, + overridesOfModel, modelName: modelName_, _setAborter, providerName, @@ -694,13 +696,13 @@ const sendGeminiChat = async ({ modelName, specialToolFormat, // reasoningCapabilities, - } = getModelCapabilities(providerName, modelName_) + } = getModelCapabilities(providerName, modelName_, overridesOfModel) const { providerReasoningIOSettings } = getProviderCapabilities(providerName) // reasoning // const { canIOReasoning, openSourceThinkTags, } = reasoningCapabilities || {} - const reasoningInfo = getSendableReasoningInfo('Chat', providerName, modelName_, modelSelectionOptions) // user's modelName_ here + const reasoningInfo = getSendableReasoningInfo('Chat', providerName, modelName_, modelSelectionOptions, overridesOfModel) // user's modelName_ here const includeInPayload = providerReasoningIOSettings?.input?.includeInPayload?.(reasoningInfo) || {} // tools diff --git a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.ts b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.ts index 7c92d9da..969dec8f 100644 --- a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.ts +++ b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.ts @@ -20,6 +20,7 @@ export const sendLLMMessage = async ({ settingsOfProvider, modelSelection, modelSelectionOptions, + overridesOfModel, chatMode, separateSystemMessage, }: SendLLMMessageParams, @@ -106,12 +107,12 @@ export const sendLLMMessage = async ({ } const { sendFIM, sendChat } = implementation if (messagesType === 'chatMessages') { - await sendChat({ messages: messages_, onText, onFinalMessage, onError, settingsOfProvider, modelSelectionOptions, modelName, _setAborter, providerName, separateSystemMessage, chatMode }) + await sendChat({ messages: messages_, onText, onFinalMessage, onError, settingsOfProvider, modelSelectionOptions, overridesOfModel, modelName, _setAborter, providerName, separateSystemMessage, chatMode }) return } if (messagesType === 'FIMMessage') { if (sendFIM) { - await sendFIM({ messages: messages_, onText, onFinalMessage, onError, settingsOfProvider, modelSelectionOptions, modelName, _setAborter, providerName, separateSystemMessage }) + await sendFIM({ messages: messages_, onText, onFinalMessage, onError, settingsOfProvider, modelSelectionOptions, overridesOfModel, modelName, _setAborter, providerName, separateSystemMessage }) return } onError({ message: `Error running Autocomplete with ${providerName} - ${modelName}.`, fullError: null })