Update AI provider model enums and default configurations

Remove deprecated model versions (Claude 4/4.5/4.6, Gemini 2.5, GPT 5.4 Pro, Mistral latest aliases) and replace with current model identifiers. Add DEFAULT_QUICK_MODEL_BY_PROVIDER configuration, update default models to use Sonnet 4.6 standard and Opus 4.8 for planning, and adjust Mistral agent to use Small model.
This commit is contained in:
Andrew Beal 2026-05-30 16:32:56 +01:00
parent 713d82d5bf
commit e8e3dcd363
12 changed files with 72 additions and 91 deletions

View file

@ -51,7 +51,7 @@ export class MistralAgent {
private async createAgent(): Promise<string> {
const requestBody: MistralAgentCreateRequest = {
model: AIProviderModel.MistralMedium,
model: AIProviderModel.MistralSmall,
name: "VaultKeeper Web Search",
instructions: "You are a web search assistant. **Always** search the web to look up current information before responding and never answer from memory alone.",
tools: [{ type: "web_search" }]

View file

@ -64,36 +64,27 @@ export enum AIProvider {
export enum AIProviderModel {
// Claude models
ClaudeSonnet_4_6 = "claude-sonnet-4-6",
ClaudeSonnet_4_5 = "claude-sonnet-4-5-20250929",
ClaudeSonnet_4 = "claude-sonnet-4-20250514",
ClaudeOpus_4_6 = "claude-opus-4-6",
ClaudeOpus_4_5 = "claude-opus-4-5-20251101",
ClaudeOpus_4_1 = "claude-opus-4-1-20250805",
ClaudeOpus_4 = "claude-opus-4-20250514",
ClaudeOpus_4_8 = "claude-opus-4-8",
ClaudeHaiku_4_5 = "claude-haiku-4-5-20251001",
// Gemini models
GeminiFlash_2_5_Lite = "gemini-2.5-flash-lite",
GeminiFlash_2_5 = "gemini-2.5-flash",
GeminiPro_2_5 = "gemini-2.5-pro",
GeminiFlash_3_Preview = "gemini-3-flash-preview",
GeminiFlash_3_1_Preview_Lite = "gemini-3.1-flash-lite-preview",
GeminiFlash_3_1_Lite = "gemini-3.1-flash-lite",
GeminiFlash_3_Flash = "gemini-3-flash-preview",
GeminiFlash_3_5_Flash = "gemini-3.5-flash",
GeminiPro_3_1_Preview = "gemini-3.1-pro-preview",
// OpenAI models
GPT_5_5 = "gpt-5.5",
GPT_5_4_Pro = "gpt-5.4-pro",
GPT_5_4_Mini = "gpt-5.4-mini",
GPT_5_4_Nano = "gpt-5.4-nano",
// Mistral models
MistralLarge = "mistral-large-latest",
MistralMedium = "mistral-medium-latest",
MistralSmall = "mistral-small-latest",
MistralMedium = "mistral-medium-3-5",
MistralSmall = "mistral-small-2603",
// Conversation naming models (aliases to existing models)
ClaudeNamer = ClaudeHaiku_4_5,
GeminiNamer = GeminiFlash_2_5_Lite,
GeminiNamer = GeminiFlash_3_1_Lite,
OpenAINamer = GPT_5_4_Nano,
MistralNamer = MistralSmall
}
@ -118,16 +109,23 @@ export enum MistralAgentEndpoint {
ConversationsUrl = "https://api.mistral.ai/v1/conversations"
}
export const DEFAULT_MODEL_BY_PROVIDER: Record<AIProvider, AIProviderModel> = {
export const DEFAULT_QUICK_MODEL_BY_PROVIDER: Record<AIProvider, AIProviderModel> = {
[AIProvider.Claude]: AIProviderModel.ClaudeHaiku_4_5,
[AIProvider.Gemini]: AIProviderModel.GeminiFlash_2_5_Lite,
[AIProvider.Gemini]: AIProviderModel.GeminiFlash_3_1_Lite,
[AIProvider.OpenAI]: AIProviderModel.GPT_5_4_Nano,
[AIProvider.Mistral]: AIProviderModel.MistralSmall,
};
}
export const DEFAULT_MODEL_BY_PROVIDER: Record<AIProvider, AIProviderModel> = {
[AIProvider.Claude]: AIProviderModel.ClaudeSonnet_4_6,
[AIProvider.Gemini]: AIProviderModel.GeminiFlash_3_5_Flash,
[AIProvider.OpenAI]: AIProviderModel.GPT_5_5,
[AIProvider.Mistral]: AIProviderModel.MistralMedium,
}
export const DEFAULT_PLANNING_MODEL_BY_PROVIDER: Record<AIProvider, AIProviderModel> = {
[AIProvider.Claude]: AIProviderModel.ClaudeSonnet_4_6,
[AIProvider.Gemini]: AIProviderModel.GeminiPro_2_5,
[AIProvider.OpenAI]: AIProviderModel.GPT_5_4_Pro,
[AIProvider.Mistral]: AIProviderModel.MistralLarge,
};
[AIProvider.Claude]: AIProviderModel.ClaudeOpus_4_8,
[AIProvider.Gemini]: AIProviderModel.GeminiFlash_3_5_Flash,
[AIProvider.OpenAI]: AIProviderModel.GPT_5_5,
[AIProvider.Mistral]: AIProviderModel.MistralMedium,
}

View file

@ -7,29 +7,20 @@ export enum Copy {
// Model Display Names
ClaudeSonnet_4_6 = "Claude Sonnet 4.6",
ClaudeSonnet_4_5 = "Claude Sonnet 4.5",
ClaudeSonnet_4 = "Claude Sonnet 4",
ClaudeOpus_4_6 = "Claude Opus 4.6",
ClaudeOpus_4_5 = "Claude Opus 4.5",
ClaudeOpus_4_1 = "Claude Opus 4.1",
ClaudeOpus_4 = "Claude Opus 4",
ClaudeOpus_4_8 = "Claude Opus 4.8",
ClaudeHaiku_4_5 = "Claude Haiku 4.5",
GeminiFlash_2_5_Lite = "Gemini 2.5 Flash Lite",
GeminiFlash_2_5 = "Gemini 2.5 Flash",
GeminiPro_2_5 = "Gemini 2.5 Pro",
GeminiFlash_3_Preview = "Gemini 3 Flash Preview",
GeminiFlash_3_1_Preview_Lite = "Gemini 3.1 Flash Lite Preview",
GeminiFlash_3_1_Lite = "Gemini 3.1 Flash-Lite",
GeminiFlash_3_Flash = "Gemini 3 Flash",
GeminiFlash_3_5_Flash = "Gemini 3.5 Flash",
GeminiPro_3_1_Preview = "Gemini 3.1 Pro Preview",
GPT_5_5 = "GPT-5.5",
GPT_5_4_Pro = "GPT-5.4 Pro",
GPT_5_4_Mini = "GPT-5.4 Mini",
GPT_5_4_Nano = "GPT-5.4 Nano",
MistralLarge = "Mistral Large (latest)",
MistralMedium = "Mistral Medium (latest)",
MistralSmall = "Mistral Small (latest)",
MistralMedium = "Mistral Medium 3.5",
MistralSmall = "Mistral Small 4",
// AI Provider Groups
ProviderClaude = "Claude",

View file

@ -7,6 +7,7 @@ import {
AIProviderModel,
DEFAULT_MODEL_BY_PROVIDER,
DEFAULT_PLANNING_MODEL_BY_PROVIDER,
DEFAULT_QUICK_MODEL_BY_PROVIDER,
fromModel,
isvalidProvider,
isValidProviderModel,
@ -20,8 +21,8 @@ const DEFAULT_SETTINGS: IVaultkeeperAISettings = {
userInstruction: "",
provider: AIProvider.Claude,
model: AIProviderModel.ClaudeHaiku_4_5,
planningModel: AIProviderModel.ClaudeSonnet_4_6,
model: AIProviderModel.ClaudeSonnet_4_6,
planningModel: AIProviderModel.ClaudeOpus_4_8,
quickActionModel: AIProviderModel.ClaudeHaiku_4_5,
apiKeys: {
@ -187,7 +188,7 @@ export class SettingsService {
}
if (!isValidProviderModel(this.settings.quickActionModel) || !modelMatchesProvider(this.settings.quickActionModel, provider)) {
settings.quickActionModel = DEFAULT_MODEL_BY_PROVIDER[provider];
settings.quickActionModel = DEFAULT_QUICK_MODEL_BY_PROVIDER[provider];
}
});
}

View file

@ -341,12 +341,7 @@ export class VaultkeeperAISettingTab extends PluginSettingTab {
if (!providerFilter || providerFilter === AIProvider.Claude) {
const claudeGroup = select.createEl("optgroup", { attr: { label: Copy.ProviderClaude } });
claudeGroup.createEl("option", { value: AIProviderModel.ClaudeSonnet_4_6, text: Copy.ClaudeSonnet_4_6 });
claudeGroup.createEl("option", { value: AIProviderModel.ClaudeSonnet_4_5, text: Copy.ClaudeSonnet_4_5 });
claudeGroup.createEl("option", { value: AIProviderModel.ClaudeSonnet_4, text: Copy.ClaudeSonnet_4 });
claudeGroup.createEl("option", { value: AIProviderModel.ClaudeOpus_4_6, text: Copy.ClaudeOpus_4_6 });
claudeGroup.createEl("option", { value: AIProviderModel.ClaudeOpus_4_5, text: Copy.ClaudeOpus_4_5 });
claudeGroup.createEl("option", { value: AIProviderModel.ClaudeOpus_4_1, text: Copy.ClaudeOpus_4_1 });
claudeGroup.createEl("option", { value: AIProviderModel.ClaudeOpus_4, text: Copy.ClaudeOpus_4 });
claudeGroup.createEl("option", { value: AIProviderModel.ClaudeOpus_4_8, text: Copy.ClaudeOpus_4_8 });
claudeGroup.createEl("option", { value: AIProviderModel.ClaudeHaiku_4_5, text: Copy.ClaudeHaiku_4_5 });
}
@ -354,7 +349,6 @@ export class VaultkeeperAISettingTab extends PluginSettingTab {
if (!providerFilter || providerFilter === AIProvider.OpenAI) {
const openaiGroup = select.createEl("optgroup", { attr: { label: Copy.ProviderOpenAI } });
openaiGroup.createEl("option", { value: AIProviderModel.GPT_5_5, text: Copy.GPT_5_5 });
openaiGroup.createEl("option", { value: AIProviderModel.GPT_5_4_Pro, text: Copy.GPT_5_4_Pro });
openaiGroup.createEl("option", { value: AIProviderModel.GPT_5_4_Mini, text: Copy.GPT_5_4_Mini });
openaiGroup.createEl("option", { value: AIProviderModel.GPT_5_4_Nano, text: Copy.GPT_5_4_Nano });
}
@ -362,18 +356,15 @@ export class VaultkeeperAISettingTab extends PluginSettingTab {
// Gemini models
if (!providerFilter || providerFilter === AIProvider.Gemini) {
const geminiGroup = select.createEl("optgroup", { attr: { label: Copy.ProviderGemini } });
geminiGroup.createEl("option", { value: AIProviderModel.GeminiFlash_3_1_Lite, text: Copy.GeminiPro_3_1_Preview });
geminiGroup.createEl("option", { value: AIProviderModel.GeminiFlash_3_Flash, text: Copy.GeminiPro_3_1_Preview });
geminiGroup.createEl("option", { value: AIProviderModel.GeminiFlash_3_5_Flash, text: Copy.GeminiPro_3_1_Preview });
geminiGroup.createEl("option", { value: AIProviderModel.GeminiPro_3_1_Preview, text: Copy.GeminiPro_3_1_Preview });
geminiGroup.createEl("option", { value: AIProviderModel.GeminiFlash_3_1_Preview_Lite, text: Copy.GeminiFlash_3_1_Preview_Lite });
geminiGroup.createEl("option", { value: AIProviderModel.GeminiFlash_3_Preview, text: Copy.GeminiFlash_3_Preview });
geminiGroup.createEl("option", { value: AIProviderModel.GeminiPro_2_5, text: Copy.GeminiPro_2_5 });
geminiGroup.createEl("option", { value: AIProviderModel.GeminiFlash_2_5, text: Copy.GeminiFlash_2_5 });
geminiGroup.createEl("option", { value: AIProviderModel.GeminiFlash_2_5_Lite, text: Copy.GeminiFlash_2_5_Lite });
}
// Mistral models
if (!providerFilter || providerFilter === AIProvider.Mistral) {
const mistralGroup = select.createEl("optgroup", { attr: { label: Copy.ProviderMistral } });
mistralGroup.createEl("option", { value: AIProviderModel.MistralLarge, text: Copy.MistralLarge });
mistralGroup.createEl("option", { value: AIProviderModel.MistralMedium, text: Copy.MistralMedium });
mistralGroup.createEl("option", { value: AIProviderModel.MistralSmall, text: Copy.MistralSmall });
}

View file

@ -19,7 +19,7 @@ describe('ClaudeConversationNamingService', () => {
// Mock SettingsService
mockSettingsService = {
settings: {
model: AIProviderModel.ClaudeSonnet_4_5,
model: AIProviderModel.ClaudeSonnet_4_6,
apiKeys: {
claude: 'test-claude-key',
openai: 'test-openai-key',

View file

@ -19,7 +19,7 @@ describe('GeminiConversationNamingService', () => {
// Mock SettingsService
mockSettingsService = {
settings: {
model: AIProviderModel.GeminiFlash_2_5,
model: AIProviderModel.GeminiFlash_3_5_Flash,
apiKeys: {
claude: 'test-claude-key',
openai: 'test-openai-key',

View file

@ -27,7 +27,7 @@ describe('SettingsService', () => {
settingsService = new SettingsService({});
expect(settingsService.settings.firstTimeStart).toBe(true);
expect(settingsService.settings.model).toBe(AIProviderModel.ClaudeHaiku_4_5);
expect(settingsService.settings.model).toBe(AIProviderModel.ClaudeSonnet_4_6);
expect(settingsService.settings.apiKeys).toEqual({
claude: '',
openai: '',
@ -43,8 +43,8 @@ describe('SettingsService', () => {
const loadedSettings: Partial<IVaultkeeperAISettings> = {
firstTimeStart: false,
provider: AIProvider.Gemini,
model: AIProviderModel.GeminiFlash_2_5,
planningModel: AIProviderModel.GeminiPro_2_5,
model: AIProviderModel.GeminiFlash_3_5_Flash,
planningModel: AIProviderModel.GeminiPro_3_1_Preview,
apiKeys: {
claude: 'claude-key-123',
openai: 'openai-key-456',
@ -57,7 +57,7 @@ describe('SettingsService', () => {
settingsService = new SettingsService(loadedSettings as IVaultkeeperAISettings);
expect(settingsService.settings.firstTimeStart).toBe(false);
expect(settingsService.settings.model).toBe(AIProviderModel.GeminiFlash_2_5);
expect(settingsService.settings.model).toBe(AIProviderModel.GeminiFlash_3_5_Flash);
expect(settingsService.settings.apiKeys.claude).toBe('claude-key-123');
expect(settingsService.settings.apiKeys.openai).toBe('openai-key-456');
expect(settingsService.settings.apiKeys.gemini).toBe('gemini-key-789');
@ -92,8 +92,8 @@ describe('SettingsService', () => {
beforeEach(() => {
const loadedSettings: IVaultkeeperAISettings = {
firstTimeStart: false,
model: AIProviderModel.ClaudeSonnet_4_5,
planningModel: AIProviderModel.ClaudeOpus_4,
model: AIProviderModel.ClaudeSonnet_4_6,
planningModel: AIProviderModel.ClaudeOpus_4_8,
apiKeys: {
claude: 'claude-api-key',
openai: 'openai-api-key',
@ -143,8 +143,8 @@ describe('SettingsService', () => {
it('should return Claude key when current model is Claude', () => {
const loadedSettings: IVaultkeeperAISettings = {
firstTimeStart: false,
model: AIProviderModel.ClaudeSonnet_4_5,
planningModel: AIProviderModel.ClaudeOpus_4,
model: AIProviderModel.ClaudeSonnet_4_6,
planningModel: AIProviderModel.ClaudeOpus_4_8,
apiKeys: {
claude: 'claude-key',
openai: 'openai-key',
@ -205,8 +205,8 @@ describe('SettingsService', () => {
it('should return Gemini key when current model is Gemini', () => {
const loadedSettings: IVaultkeeperAISettings = {
firstTimeStart: false,
model: AIProviderModel.GeminiFlash_2_5,
planningModel: AIProviderModel.GeminiPro_2_5,
model: AIProviderModel.GeminiFlash_3_5_Flash,
planningModel: AIProviderModel.GeminiPro_3_1_Preview,
apiKeys: {
claude: 'claude-key',
openai: 'openai-key',
@ -221,7 +221,7 @@ describe('SettingsService', () => {
enableWebSearch: true,
enableWebViewer: false,
provider: AIProvider.Gemini,
quickActionModel: AIProviderModel.GeminiFlash_2_5,
quickActionModel: AIProviderModel.GeminiFlash_3_5_Flash,
enableContextMenuActions: false,
enableToolbarActions: false,
hideDrawerElements: false,
@ -237,7 +237,7 @@ describe('SettingsService', () => {
// Test with various Claude models
settingsService = new SettingsService({
provider: AIProvider.Claude,
model: AIProviderModel.ClaudeOpus_4,
model: AIProviderModel.ClaudeOpus_4_8,
apiKeys: { claude: 'opus-key', openai: '', gemini: '', mistral: '' }
});
expect(settingsService.getApiKeyForCurrentModel()).toBe('opus-key');
@ -245,7 +245,7 @@ describe('SettingsService', () => {
// Test with various Gemini models
settingsService = new SettingsService({
provider: AIProvider.Gemini,
model: AIProviderModel.GeminiPro_2_5,
model: AIProviderModel.GeminiPro_3_1_Preview,
apiKeys: { claude: '', openai: '', gemini: 'pro-key', mistral: '' }
});
expect(settingsService.getApiKeyForCurrentModel()).toBe('pro-key');
@ -264,8 +264,8 @@ describe('SettingsService', () => {
beforeEach(() => {
const loadedSettings: IVaultkeeperAISettings = {
firstTimeStart: false,
model: AIProviderModel.ClaudeSonnet_4_5,
planningModel: AIProviderModel.ClaudeOpus_4,
model: AIProviderModel.ClaudeSonnet_4_6,
planningModel: AIProviderModel.ClaudeOpus_4_8,
apiKeys: {
claude: '',
openai: '',
@ -332,8 +332,8 @@ describe('SettingsService', () => {
beforeEach(() => {
const loadedSettings: IVaultkeeperAISettings = {
firstTimeStart: false,
model: AIProviderModel.ClaudeSonnet_4_5,
planningModel: AIProviderModel.ClaudeOpus_4,
model: AIProviderModel.ClaudeSonnet_4_6,
planningModel: AIProviderModel.ClaudeOpus_4_8,
apiKeys: {
claude: 'test-key',
openai: '',
@ -390,9 +390,9 @@ describe('SettingsService', () => {
describe('Provider Detection from Model Names', () => {
it('should correctly identify Claude models', () => {
const claudeModels = [
AIProviderModel.ClaudeSonnet_4_5,
AIProviderModel.ClaudeSonnet_4,
AIProviderModel.ClaudeOpus_4,
AIProviderModel.ClaudeSonnet_4_6,
AIProviderModel.ClaudeSonnet_4_6,
AIProviderModel.ClaudeOpus_4_8,
AIProviderModel.ClaudeHaiku_4_5
];
@ -408,9 +408,9 @@ describe('SettingsService', () => {
it('should correctly identify Gemini models', () => {
const geminiModels = [
AIProviderModel.GeminiFlash_2_5,
AIProviderModel.GeminiFlash_2_5_Lite,
AIProviderModel.GeminiPro_2_5
AIProviderModel.GeminiFlash_3_1_Lite,
AIProviderModel.GeminiFlash_3_5_Flash,
AIProviderModel.GeminiPro_3_1_Preview
];
geminiModels.forEach(model => {
@ -447,7 +447,7 @@ describe('SettingsService', () => {
describe('Settings Immutability and Reference', () => {
it('should maintain reference to settings object', () => {
settingsService = new SettingsService({
model: AIProviderModel.ClaudeSonnet_4_5,
model: AIProviderModel.ClaudeSonnet_4_6,
apiKeys: { claude: 'key', openai: '', gemini: '', mistral: '' }
});
@ -460,7 +460,7 @@ describe('SettingsService', () => {
it('should allow modification of settings properties via updateSettings', async () => {
settingsService = new SettingsService({
model: AIProviderModel.ClaudeSonnet_4_5,
model: AIProviderModel.ClaudeSonnet_4_6,
apiKeys: { claude: '', openai: '', gemini: '', mistral: '' },
exclusions: []
});

View file

@ -90,8 +90,8 @@ const mockPlugin = {
const mockSettings: IVaultkeeperAISettings = {
firstTimeStart: false,
model: AIProviderModel.ClaudeSonnet_4_5,
planningModel: AIProviderModel.ClaudeSonnet_4_5,
model: AIProviderModel.ClaudeSonnet_4_6,
planningModel: AIProviderModel.ClaudeSonnet_4_6,
apiKeys: {
claude: 'test-claude-key',
openai: 'test-openai-key',

View file

@ -50,8 +50,8 @@ const mockFileManager = {
const mockSettings: IVaultkeeperAISettings = {
firstTimeStart: false,
model: AIProviderModel.ClaudeSonnet_4_5,
planningModel: AIProviderModel.ClaudeSonnet_4_5,
model: AIProviderModel.ClaudeSonnet_4_6,
planningModel: AIProviderModel.ClaudeSonnet_4_6,
apiKeys: {
claude: 'test-claude-key',
openai: 'test-openai-key',

View file

@ -52,8 +52,8 @@ const mockPlugin = {
const mockSettings: IVaultkeeperAISettings = {
firstTimeStart: false,
model: AIProviderModel.ClaudeSonnet_4_5,
planningModel: AIProviderModel.ClaudeSonnet_4_5,
model: AIProviderModel.ClaudeSonnet_4_6,
planningModel: AIProviderModel.ClaudeSonnet_4_6,
apiKeys: {
claude: 'test-claude-key',
openai: 'test-openai-key',

View file

@ -49,8 +49,8 @@ const mockFileManager = {
// Create a mutable settings object that tests can modify
const mockSettings: IVaultkeeperAISettings = {
firstTimeStart: false,
model: AIProviderModel.ClaudeSonnet_4_5,
planningModel: AIProviderModel.ClaudeSonnet_4_5,
model: AIProviderModel.ClaudeSonnet_4_6,
planningModel: AIProviderModel.ClaudeSonnet_4_6,
apiKeys: {
claude: 'test-claude-key',
openai: 'test-openai-key',