diff --git a/AIClasses/Mistral/MistralAgent.ts b/AIClasses/Mistral/MistralAgent.ts index 5fed933..0c48116 100644 --- a/AIClasses/Mistral/MistralAgent.ts +++ b/AIClasses/Mistral/MistralAgent.ts @@ -51,7 +51,7 @@ export class MistralAgent { private async createAgent(): Promise { 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" }] diff --git a/Enums/ApiProvider.ts b/Enums/ApiProvider.ts index 036e4ec..e5a30a8 100644 --- a/Enums/ApiProvider.ts +++ b/Enums/ApiProvider.ts @@ -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 = { +export const DEFAULT_QUICK_MODEL_BY_PROVIDER: Record = { [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.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.Claude]: AIProviderModel.ClaudeSonnet_4_6, - [AIProvider.Gemini]: AIProviderModel.GeminiPro_2_5, - [AIProvider.OpenAI]: AIProviderModel.GPT_5_4_Pro, - [AIProvider.Mistral]: AIProviderModel.MistralLarge, -}; \ No newline at end of file + [AIProvider.Claude]: AIProviderModel.ClaudeOpus_4_8, + [AIProvider.Gemini]: AIProviderModel.GeminiFlash_3_5_Flash, + [AIProvider.OpenAI]: AIProviderModel.GPT_5_5, + [AIProvider.Mistral]: AIProviderModel.MistralMedium, +} \ No newline at end of file diff --git a/Enums/Copy.ts b/Enums/Copy.ts index 9709a9c..1d7efe5 100644 --- a/Enums/Copy.ts +++ b/Enums/Copy.ts @@ -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", diff --git a/Services/SettingsService.ts b/Services/SettingsService.ts index ea51752..9f3b2ca 100644 --- a/Services/SettingsService.ts +++ b/Services/SettingsService.ts @@ -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]; } }); } diff --git a/Views/VaultkeeperAISettingTab.ts b/Views/VaultkeeperAISettingTab.ts index aaa8abc..3e366c5 100644 --- a/Views/VaultkeeperAISettingTab.ts +++ b/Views/VaultkeeperAISettingTab.ts @@ -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 }); } diff --git a/__tests__/AIClasses/ClaudeConversationNamingService.test.ts b/__tests__/AIClasses/ClaudeConversationNamingService.test.ts index 4e7c7c1..0bc10d8 100644 --- a/__tests__/AIClasses/ClaudeConversationNamingService.test.ts +++ b/__tests__/AIClasses/ClaudeConversationNamingService.test.ts @@ -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', diff --git a/__tests__/AIClasses/GeminiConversationNamingService.test.ts b/__tests__/AIClasses/GeminiConversationNamingService.test.ts index 11cb18f..59b5d72 100644 --- a/__tests__/AIClasses/GeminiConversationNamingService.test.ts +++ b/__tests__/AIClasses/GeminiConversationNamingService.test.ts @@ -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', diff --git a/__tests__/Services/SettingsService.test.ts b/__tests__/Services/SettingsService.test.ts index fdb3fea..5b775a5 100644 --- a/__tests__/Services/SettingsService.test.ts +++ b/__tests__/Services/SettingsService.test.ts @@ -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 = { 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: [] }); diff --git a/__tests__/Services/VaultCacheService.performance.test.ts b/__tests__/Services/VaultCacheService.performance.test.ts index cd7fdab..fc61c91 100644 --- a/__tests__/Services/VaultCacheService.performance.test.ts +++ b/__tests__/Services/VaultCacheService.performance.test.ts @@ -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', diff --git a/__tests__/Services/VaultService.pdf.test.ts b/__tests__/Services/VaultService.pdf.test.ts index 075eed8..4534f2c 100644 --- a/__tests__/Services/VaultService.pdf.test.ts +++ b/__tests__/Services/VaultService.pdf.test.ts @@ -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', diff --git a/__tests__/Services/VaultService.performance.test.ts b/__tests__/Services/VaultService.performance.test.ts index f3e5753..74ac5e7 100644 --- a/__tests__/Services/VaultService.performance.test.ts +++ b/__tests__/Services/VaultService.performance.test.ts @@ -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', diff --git a/__tests__/Services/VaultService.test.ts b/__tests__/Services/VaultService.test.ts index b76600b..668717b 100644 --- a/__tests__/Services/VaultService.test.ts +++ b/__tests__/Services/VaultService.test.ts @@ -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',