diff --git a/src/main/presenter/configPresenter/modelConfig.ts b/src/main/presenter/configPresenter/modelConfig.ts index bed26caac..6afeae5c7 100644 --- a/src/main/presenter/configPresenter/modelConfig.ts +++ b/src/main/presenter/configPresenter/modelConfig.ts @@ -8,6 +8,8 @@ const SPECIAL_CONCAT_CHAR = '-_-' export class ModelConfigHelper { private modelConfigStore: ElectronStore> + private memoryCache: Map = new Map() + private cacheInitialized: boolean = false constructor() { this.modelConfigStore = new ElectronStore>({ @@ -15,6 +17,20 @@ export class ModelConfigHelper { }) } + /** + * Initialize memory cache by loading all data from store + * This is called lazily on first access + */ + private initializeCache(): void { + if (this.cacheInitialized) return + + const allConfigs = this.modelConfigStore.store + Object.entries(allConfigs).forEach(([key, value]) => { + this.memoryCache.set(key, value) + }) + this.cacheInitialized = true + } + /** * Get model configuration with priority: user config > provider config > default config * @param modelId - The model ID @@ -22,9 +38,22 @@ export class ModelConfigHelper { * @returns ModelConfig */ getModelConfig(modelId: string, providerId?: string): ModelConfig { + // Initialize cache if not already done + this.initializeCache() + // 1. First try to get user-defined config for this specific provider + model if (providerId) { - const userConfig = this.modelConfigStore.get(providerId + SPECIAL_CONCAT_CHAR + modelId) + const cacheKey = providerId + SPECIAL_CONCAT_CHAR + modelId + let userConfig = this.memoryCache.get(cacheKey) + + // If not in cache, try to load from store and cache it + if (!userConfig) { + userConfig = this.modelConfigStore.get(cacheKey) + if (userConfig) { + this.memoryCache.set(cacheKey, userConfig) + } + } + if (userConfig?.config) { return userConfig.config } @@ -73,11 +102,16 @@ export class ModelConfigHelper { * @param config - The model configuration */ setModelConfig(modelId: string, providerId: string, config: ModelConfig): void { - this.modelConfigStore.set(providerId + SPECIAL_CONCAT_CHAR + modelId, { + const cacheKey = providerId + SPECIAL_CONCAT_CHAR + modelId + const configData: IModelConfig = { id: modelId, providerId: providerId, config: config - }) + } + + // Update both store and cache + this.modelConfigStore.set(cacheKey, configData) + this.memoryCache.set(cacheKey, configData) } /** @@ -86,7 +120,11 @@ export class ModelConfigHelper { * @param providerId - The provider ID */ resetModelConfig(modelId: string, providerId: string): void { - this.modelConfigStore.delete(providerId + SPECIAL_CONCAT_CHAR + modelId) + const cacheKey = providerId + SPECIAL_CONCAT_CHAR + modelId + + // Remove from both store and cache + this.modelConfigStore.delete(cacheKey) + this.memoryCache.delete(cacheKey) } /** @@ -94,7 +132,15 @@ export class ModelConfigHelper { * @returns Record of all configurations */ getAllModelConfigs(): Record { - return this.modelConfigStore.store + // Initialize cache if not already done + this.initializeCache() + + // Return data from cache for better performance + const result: Record = {} + this.memoryCache.forEach((value, key) => { + result[key] = value + }) + return result } /** @@ -126,8 +172,24 @@ export class ModelConfigHelper { * @returns boolean */ hasUserConfig(modelId: string, providerId: string): boolean { - const userConfig = this.modelConfigStore.get(providerId + SPECIAL_CONCAT_CHAR + modelId) - return !!userConfig + // Initialize cache if not already done + this.initializeCache() + + const cacheKey = providerId + SPECIAL_CONCAT_CHAR + modelId + + // Check cache first + if (this.memoryCache.has(cacheKey)) { + return true + } + + // If not in cache, check store and update cache if found + const userConfig = this.modelConfigStore.get(cacheKey) + if (userConfig) { + this.memoryCache.set(cacheKey, userConfig) + return true + } + + return false } /** @@ -137,16 +199,20 @@ export class ModelConfigHelper { */ importConfigs(configs: Record, overwrite: boolean = false): void { if (overwrite) { - // Clear existing configs + // Clear existing configs from both store and cache this.modelConfigStore.clear() + this.memoryCache.clear() } - // Import configs + // Import configs to both store and cache Object.entries(configs).forEach(([key, value]) => { if (overwrite || !this.modelConfigStore.has(key)) { this.modelConfigStore.set(key, value) + this.memoryCache.set(key, value) } }) + + this.cacheInitialized = true } /** @@ -162,6 +228,7 @@ export class ModelConfigHelper { */ clearAllConfigs(): void { this.modelConfigStore.clear() + this.memoryCache.clear() } /** @@ -171,4 +238,12 @@ export class ModelConfigHelper { getStorePath(): string { return this.modelConfigStore.path } + + /** + * Clear memory cache (useful for testing or memory management) + */ + clearMemoryCache(): void { + this.memoryCache.clear() + this.cacheInitialized = false + } } diff --git a/src/main/presenter/githubCopilotDeviceFlow.ts b/src/main/presenter/githubCopilotDeviceFlow.ts index 45ec29dce..30cc9c528 100644 --- a/src/main/presenter/githubCopilotDeviceFlow.ts +++ b/src/main/presenter/githubCopilotDeviceFlow.ts @@ -1,9 +1,8 @@ import { BrowserWindow, shell } from 'electron' -import { exec } from 'child_process'; +import { exec } from 'child_process' import { presenter } from '@/presenter' - -const GITHUB_DEVICE_URL = 'https://github.com/login/device'; +const GITHUB_DEVICE_URL = 'https://github.com/login/device' export interface DeviceFlowConfig { clientId: string @@ -303,18 +302,18 @@ export class GitHubCopilotDeviceFlow { setTimeout(async () => { try { // 使用固定的GitHub设备激活页面 - const url = GITHUB_DEVICE_URL; - console.log('Attempting to open URL:', url); - + const url = GITHUB_DEVICE_URL + console.log('Attempting to open URL:', url) + if (process.platform === 'win32') { // 先尝试使用explorer命令 exec(`explorer "${url}"`, (error) => { if (error) { - console.error('Explorer command failed:', error); + console.error('Explorer command failed:', error) // 如果explorer失败,尝试使用start命令 exec(`start "" "${url}"`, (startError) => { if (startError) { - console.error('Start command failed:', startError); + console.error('Start command failed:', startError) // 使用更安全的方式处理剪贴板操作 instructionWindow.webContents.executeJavaScript(` const shouldCopy = confirm('无法自动打开浏览器。是否复制链接到剪贴板?'); @@ -325,20 +324,20 @@ export class GitHubCopilotDeviceFlow { } else { alert('请手动访问: ${url}'); } - `); + `) } - }); + }) } - }); + }) } else { // 非Windows系统使用默认的shell.openExternal - await shell.openExternal(url); + await shell.openExternal(url) } } catch (error) { - console.error('Failed to open browser:', error); + console.error('Failed to open browser:', error) instructionWindow.webContents.executeJavaScript(` alert('无法自动打开浏览器,请手动访问: ${GITHUB_DEVICE_URL}'); - `); + `) } }, 1000) diff --git a/src/main/presenter/llmProviderPresenter/baseProvider.ts b/src/main/presenter/llmProviderPresenter/baseProvider.ts index 9ab0b8cbf..ed4741ac9 100644 --- a/src/main/presenter/llmProviderPresenter/baseProvider.ts +++ b/src/main/presenter/llmProviderPresenter/baseProvider.ts @@ -11,6 +11,8 @@ import { import { ConfigPresenter } from '../configPresenter' import { DevicePresenter } from '../devicePresenter' import { jsonrepair } from 'jsonrepair' +import { eventBus, SendTarget } from '@/eventbus' +import { CONFIG_EVENTS } from '@/events' /** * 基础LLM提供商抽象类 @@ -43,6 +45,9 @@ export abstract class BaseLLMProvider { this.provider = provider this.configPresenter = configPresenter this.defaultHeaders = DevicePresenter.getDefaultHeaders() + + // Initialize models and customModels from cached config data + this.loadCachedModels() } /** @@ -53,6 +58,37 @@ export abstract class BaseLLMProvider { return BaseLLMProvider.MAX_TOOL_CALLS } + /** + * 从配置中加载缓存的模型数据 + * 在构造函数中调用,避免每次都需要重新获取模型列表 + */ + private loadCachedModels(): void { + try { + // Load cached provider models from config + const cachedModels = this.configPresenter.getProviderModels(this.provider.id) + if (cachedModels && cachedModels.length > 0) { + this.models = cachedModels + console.info( + `Loaded ${cachedModels.length} cached models for provider: ${this.provider.name}` + ) + } + + // Load cached custom models from config + const cachedCustomModels = this.configPresenter.getCustomModels(this.provider.id) + if (cachedCustomModels && cachedCustomModels.length > 0) { + this.customModels = cachedCustomModels + console.info( + `Loaded ${cachedCustomModels.length} cached custom models for provider: ${this.provider.name}` + ) + } + } catch (error) { + console.warn(`Failed to load cached models for provider: ${this.provider.name}`, error) + // Keep default empty arrays if loading fails + this.models = [] + this.customModels = [] + } + } + /** * 初始化提供商 * 包括获取模型列表、配置代理等 @@ -79,9 +115,8 @@ export abstract class BaseLLMProvider { if (!this.models || this.models.length === 0) return const providerId = this.provider.id - // 检查是否有自定义模型 - const customModels = this.configPresenter.getCustomModels(providerId) - if (customModels && customModels.length > 0) return + // 检查是否有自定义模型 (use cached customModels) + if (this.customModels && this.customModels.length > 0) return // 检查是否有任何模型的状态被手动修改过 const hasManuallyModifiedModels = this.models.some((model) => @@ -124,6 +159,22 @@ export abstract class BaseLLMProvider { } } + /** + * 强制刷新模型数据 + * 忽略缓存,重新从网络获取最新的模型列表 + * @returns 模型列表 + */ + public async refreshModels(): Promise { + console.info(`Force refreshing models for provider: ${this.provider.name}`) + await this.fetchModels() + await this.autoEnableModelsIfNeeded() + eventBus.sendToRenderer( + CONFIG_EVENTS.MODEL_LIST_CHANGED, + SendTarget.ALL_WINDOWS, + this.provider.id + ) + } + /** * 获取特定提供商的模型 * 此方法由具体的提供商子类实现 @@ -160,6 +211,9 @@ export abstract class BaseLLMProvider { this.customModels.push(newModel) } + // Sync with config + this.configPresenter.addCustomModel(this.provider.id, newModel) + return newModel } @@ -172,6 +226,8 @@ export abstract class BaseLLMProvider { const index = this.customModels.findIndex((model) => model.id === modelId) if (index !== -1) { this.customModels.splice(index, 1) + // Sync with config + this.configPresenter.removeCustomModel(this.provider.id, modelId) return true } return false @@ -188,6 +244,8 @@ export abstract class BaseLLMProvider { if (model) { // 应用更新 Object.assign(model, updates) + // Sync with config + this.configPresenter.updateCustomModel(this.provider.id, modelId, updates) return true } return false diff --git a/src/main/presenter/llmProviderPresenter/index.ts b/src/main/presenter/llmProviderPresenter/index.ts index ac26caad9..5e55624fa 100644 --- a/src/main/presenter/llmProviderPresenter/index.ts +++ b/src/main/presenter/llmProviderPresenter/index.ts @@ -1045,6 +1045,17 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { return provider.getKeyStatus() } + async refreshModels(providerId: string): Promise { + try { + const provider = this.getProviderInstance(providerId) + await provider.refreshModels() + } catch (error) { + console.error(`Failed to refresh models for provider ${providerId}:`, error) + const errorMessage = error instanceof Error ? error.message : String(error) + throw new Error(`Model refresh failed: ${errorMessage}`) + } + } + async addCustomModel( providerId: string, model: Omit diff --git a/src/main/presenter/llmProviderPresenter/providers/geminiProvider.ts b/src/main/presenter/llmProviderPresenter/providers/geminiProvider.ts index 128e4053d..32485c86e 100644 --- a/src/main/presenter/llmProviderPresenter/providers/geminiProvider.ts +++ b/src/main/presenter/llmProviderPresenter/providers/geminiProvider.ts @@ -24,6 +24,8 @@ import { } from '@shared/presenter' import { ConfigPresenter } from '../../configPresenter' import { BaseLLMProvider, SUMMARY_TITLES_PROMPT } from '../baseProvider' +import { eventBus, SendTarget } from '@/eventbus' +import { CONFIG_EVENTS } from '@/events' // Mapping from simple keys to API HarmCategory constants const keyToHarmCategoryMap: Record = { @@ -295,6 +297,12 @@ export class GeminiProvider extends BaseLLMProvider { // 使用API获取模型列表,如果失败则回退到静态列表 this.models = await this.fetchProviderModels() await this.autoEnableModelsIfNeeded() + // gemini 比较慢,特殊补偿一下 + eventBus.sendToRenderer( + CONFIG_EVENTS.MODEL_LIST_CHANGED, + SendTarget.ALL_WINDOWS, + this.provider.id + ) console.info('Provider initialized successfully:', this.provider.name) } catch (error) { console.warn('Provider initialization failed:', this.provider.name, error) diff --git a/src/renderer/src/components/settings/GeminiSafetyConfig.vue b/src/renderer/src/components/settings/GeminiSafetyConfig.vue index fc6d934a5..79fb4ca44 100644 --- a/src/renderer/src/components/settings/GeminiSafetyConfig.vue +++ b/src/renderer/src/components/settings/GeminiSafetyConfig.vue @@ -13,12 +13,12 @@ t(setting.label, key.charAt(0).toUpperCase() + key.slice(1)) }} {{ - t(levelLabels[safetyLevels[key]], `${levelToValueMap[safetyLevels[key]]}`) + t(getLevelLabel(safetyLevels[key]), getLevelValue(safetyLevels[key])) }} diff --git a/src/renderer/src/components/settings/ProviderApiConfig.vue b/src/renderer/src/components/settings/ProviderApiConfig.vue index 6909b093e..839932735 100644 --- a/src/renderer/src/components/settings/ProviderApiConfig.vue +++ b/src/renderer/src/components/settings/ProviderApiConfig.vue @@ -67,10 +67,17 @@ variant="outline" size="xs" class="text-xs text-normal rounded-lg" - @click="openProviderWebsite" + :disabled="isRefreshing" + @click="refreshModels" > - {{ - t('settings.provider.howToGet') + + {{ + isRefreshing + ? t('settings.provider.refreshingModels') + : t('settings.provider.refreshModels') }} @@ -94,7 +101,7 @@
- {{ t('settings.provider.getKeyTip') }} + {{ t('settings.provider.howToGet') }}: {{ t('settings.provider.getKeyTip') }} {{ provider.name }} @@ -145,6 +152,7 @@ const emit = defineEmits<{ const apiKey = ref(props.provider.apiKey || '') const apiHost = ref(props.provider.baseUrl || '') const keyStatus = ref(null) +const isRefreshing = ref(false) watch( () => props.provider, @@ -163,13 +171,6 @@ const handleApiHostChange = (value: string) => { emit('api-host-change', value) } -const openProviderWebsite = () => { - const url = props.providerWebsites?.apiKey - if (url) { - window.open(url, '_blank') - } -} - const handleOAuthSuccess = () => { emit('oauth-success') } @@ -198,6 +199,19 @@ const getKeyStatus = async () => { } } +const refreshModels = async () => { + if (isRefreshing.value) return + + isRefreshing.value = true + try { + await llmProviderPresenter.refreshModels(props.provider.id) + } catch (error) { + console.error('Failed to refresh models:', error) + } finally { + isRefreshing.value = false + } +} + onMounted(() => { getKeyStatus() }) diff --git a/src/renderer/src/i18n/en-US/settings.json b/src/renderer/src/i18n/en-US/settings.json index 233c0ece4..90959bdd3 100644 --- a/src/renderer/src/i18n/en-US/settings.json +++ b/src/renderer/src/i18n/en-US/settings.json @@ -248,7 +248,11 @@ "localModels": "Local Models", "azureApiVersion": "API Version", "safety": { - "title": "Safety settings" + "title": "Safety settings", + "blockHighest": "Block high risk", + "blockMost": "Block medium risks", + "blockNone": "Not blocked", + "blockSome": "Block low risk" }, "serverList": "Server List", "totalServers": "Total Servers", @@ -270,7 +274,8 @@ "keyStatus": { "remaining": "Remaining amount", "usage": "Used" - } + }, + "refreshingModels": "Refreshing..." }, "knowledgeBase": { "title": "Knowledge Base Settings", diff --git a/src/renderer/src/i18n/fa-IR/settings.json b/src/renderer/src/i18n/fa-IR/settings.json index 662cde6d3..58bbb4023 100644 --- a/src/renderer/src/i18n/fa-IR/settings.json +++ b/src/renderer/src/i18n/fa-IR/settings.json @@ -248,7 +248,11 @@ "localModels": "مدل‌های محلی", "azureApiVersion": "نگارش API", "safety": { - "title": "تنظیمات ایمنی" + "title": "تنظیمات ایمنی", + "blockHighest": "ریسک بالا", + "blockMost": "خطرات متوسط ​​را مسدود کنید", + "blockNone": "مسدود نشده", + "blockSome": "بلوک ریسک کم" }, "serverList": "فهرست کارسازها", "totalServers": "مجموع کارسازها", @@ -270,7 +274,8 @@ "keyStatus": { "remaining": "مقدار باقی مانده", "usage": "مورد استفاده" - } + }, + "refreshingModels": "طراوت ..." }, "knowledgeBase": { "title": "تنظیمات پایگاه دانش", diff --git a/src/renderer/src/i18n/fr-FR/settings.json b/src/renderer/src/i18n/fr-FR/settings.json index 212e11a82..efb74d64a 100644 --- a/src/renderer/src/i18n/fr-FR/settings.json +++ b/src/renderer/src/i18n/fr-FR/settings.json @@ -248,7 +248,11 @@ "localModels": "Modèles locaux", "azureApiVersion": "Version API", "safety": { - "title": "Paramètres de sécurité" + "title": "Paramètres de sécurité", + "blockHighest": "Bloquer un risque élevé", + "blockMost": "Bloquer les risques moyens", + "blockNone": "Non bloqué", + "blockSome": "Bloquer un faible risque" }, "serverList": "Liste des serveurs", "totalServers": "Total des serveurs", @@ -270,7 +274,8 @@ "keyStatus": { "remaining": "Montant restant", "usage": "Utilisé" - } + }, + "refreshingModels": "Rafraîchissant..." }, "knowledgeBase": { "title": "Paramètres de la base de connaissances", diff --git a/src/renderer/src/i18n/ja-JP/settings.json b/src/renderer/src/i18n/ja-JP/settings.json index 3b15f62b6..8c15b0936 100644 --- a/src/renderer/src/i18n/ja-JP/settings.json +++ b/src/renderer/src/i18n/ja-JP/settings.json @@ -248,7 +248,11 @@ "localModels": "ローカルモデル", "azureApiVersion": "APIバージョン", "safety": { - "title": "セキュリティ設定" + "title": "セキュリティ設定", + "blockHighest": "高リスクをブロックします", + "blockMost": "中程度のリスクをブロックします", + "blockNone": "ブロックされていません", + "blockSome": "低リスクをブロックします" }, "serverList": "サーバーリスト", "totalServers": "サーバー総数", @@ -270,7 +274,8 @@ "keyStatus": { "remaining": "残りの金額", "usage": "使用済み" - } + }, + "refreshingModels": "更新中..." }, "knowledgeBase": { "title": "ナレッジベース設定", diff --git a/src/renderer/src/i18n/ko-KR/settings.json b/src/renderer/src/i18n/ko-KR/settings.json index dcb9b7877..2eaa43337 100644 --- a/src/renderer/src/i18n/ko-KR/settings.json +++ b/src/renderer/src/i18n/ko-KR/settings.json @@ -248,7 +248,11 @@ "urlFormat": "API 샘플 : {defaultUrl}", "azureApiVersion": "API 버전", "safety": { - "title": "보안 설정" + "title": "보안 설정", + "blockHighest": "높은 위험을 차단하십시오", + "blockMost": "중간 위험을 차단합니다", + "blockNone": "차단되지 않았습니다", + "blockSome": "낮은 위험을 차단하십시오" }, "serverList": "서버 목록", "totalServers": "총 서버 수", @@ -270,7 +274,8 @@ "keyStatus": { "remaining": "나머지 금액", "usage": "사용된" - } + }, + "refreshingModels": "상쾌한 ..." }, "knowledgeBase": { "title": "지식 베이스 설정", diff --git a/src/renderer/src/i18n/ru-RU/settings.json b/src/renderer/src/i18n/ru-RU/settings.json index 98e08acd2..fb75db93f 100644 --- a/src/renderer/src/i18n/ru-RU/settings.json +++ b/src/renderer/src/i18n/ru-RU/settings.json @@ -248,7 +248,11 @@ "urlFormat": "Образец API: {defaultUrl}", "azureApiVersion": "Версия API", "safety": { - "title": "Настройки безопасности" + "title": "Настройки безопасности", + "blockHighest": "Блок высокий риск", + "blockMost": "Блок средних рисков", + "blockNone": "Не заблокирован", + "blockSome": "Блок низкий риск" }, "serverList": "Список серверов", "totalServers": "Всего серверов", @@ -270,7 +274,8 @@ "keyStatus": { "remaining": "Оставшаяся сумма", "usage": "Использовал" - } + }, + "refreshingModels": "Освежает ..." }, "knowledgeBase": { "title": "Настройки базы знаний", diff --git a/src/renderer/src/i18n/zh-CN/settings.json b/src/renderer/src/i18n/zh-CN/settings.json index f6b54c62f..adee1c25d 100644 --- a/src/renderer/src/i18n/zh-CN/settings.json +++ b/src/renderer/src/i18n/zh-CN/settings.json @@ -165,6 +165,7 @@ "keyPlaceholder": "请输入API Key", "verifyKey": "验证密钥", "howToGet": "如何获取", + "refreshingModels": "刷新中...", "getKeyTip": "请前往", "getKeyTipEnd": "获取API Key", "urlFormat": "API样例:{defaultUrl}", @@ -248,7 +249,11 @@ "localModels": "本地模型", "azureApiVersion": "API 版本", "safety": { - "title": "安全设置" + "title": "安全设置", + "blockNone": "不屏蔽", + "blockSome": "屏蔽低风险", + "blockMost": "屏蔽中风险", + "blockHighest": "屏蔽高风险" }, "serverList": "服务器列表", "totalServers": "服务器总数", diff --git a/src/renderer/src/i18n/zh-HK/settings.json b/src/renderer/src/i18n/zh-HK/settings.json index 138fd970f..24c77146d 100644 --- a/src/renderer/src/i18n/zh-HK/settings.json +++ b/src/renderer/src/i18n/zh-HK/settings.json @@ -248,7 +248,11 @@ "modelsEnabled": "模型已經啟用", "azureApiVersion": "API 版本", "safety": { - "title": "安全設置" + "title": "安全設置", + "blockHighest": "屏蔽高風險", + "blockMost": "屏蔽中風險", + "blockNone": "不屏蔽", + "blockSome": "屏蔽低風險" }, "serverList": "服務器列表", "totalServers": "服務器總數", @@ -270,7 +274,8 @@ "keyStatus": { "remaining": "剩餘額度", "usage": "已使用" - } + }, + "refreshingModels": "刷新中..." }, "knowledgeBase": { "fastgptTitle": "FastGPT知識庫", diff --git a/src/renderer/src/i18n/zh-TW/settings.json b/src/renderer/src/i18n/zh-TW/settings.json index 49b92c9d1..9d7aafe70 100644 --- a/src/renderer/src/i18n/zh-TW/settings.json +++ b/src/renderer/src/i18n/zh-TW/settings.json @@ -248,7 +248,11 @@ "noLocalModels": "沒有本機模型", "azureApiVersion": "API 版本", "safety": { - "title": "安全設置" + "title": "安全設置", + "blockHighest": "屏蔽高風險", + "blockMost": "屏蔽中風險", + "blockNone": "不屏蔽", + "blockSome": "屏蔽低風險" }, "serverList": "伺服器列表", "totalServers": "伺服器總數", @@ -270,7 +274,8 @@ "keyStatus": { "remaining": "剩餘額度", "usage": "已使用" - } + }, + "refreshingModels": "刷新中..." }, "knowledgeBase": { "title": "知識庫設置", diff --git a/src/renderer/src/stores/settings.ts b/src/renderer/src/stores/settings.ts index 0aa15d765..47e8a3b21 100644 --- a/src/renderer/src/stores/settings.ts +++ b/src/renderer/src/stores/settings.ts @@ -532,14 +532,14 @@ export const useSettingsStore = defineStore('settings', () => { try { // 自定义模型直接从配置存储获取,不需要等待provider实例 - await refreshCustomModels(providerId) + refreshCustomModels(providerId) // 标准模型需要provider实例,可能需要等待实例初始化 - await refreshStandardModels(providerId) + refreshStandardModels(providerId) } catch (error) { console.error(`刷新模型失败: ${providerId}`, error) // 如果标准模型刷新失败,至少确保自定义模型可用 - await refreshCustomModels(providerId) + refreshCustomModels(providerId) } } @@ -734,7 +734,7 @@ export const useSettingsStore = defineStore('settings', () => { const success = await llmP.removeCustomModel(providerId, modelId) console.log('removeCustomModel', providerId, modelId, success) if (success) { - await refreshCustomModels(providerId) // 只刷新自定义模型 + refreshCustomModels(providerId) // 只刷新自定义模型 } return success } catch (error) { @@ -753,7 +753,7 @@ export const useSettingsStore = defineStore('settings', () => { // 不包含启用状态的常规更新 const success = await llmP.updateCustomModel(providerId, modelId, updates) if (success) { - await refreshCustomModels(providerId) // 只刷新自定义模型 + refreshCustomModels(providerId) // 只刷新自定义模型 } return success } catch (error) { @@ -770,7 +770,7 @@ export const useSettingsStore = defineStore('settings', () => { try { const newModel = await llmP.addCustomModel(providerId, model) await configP.addCustomModel(providerId, newModel) - await refreshCustomModels(providerId) // 只刷新自定义模型 + refreshCustomModels(providerId) // 只刷新自定义模型 return newModel } catch (error) { console.error('Failed to add custom model:', error) diff --git a/src/shared/presenter.d.ts b/src/shared/presenter.d.ts index d12bd6c2d..c09548b4c 100644 --- a/src/shared/presenter.d.ts +++ b/src/shared/presenter.d.ts @@ -514,6 +514,7 @@ export interface ILlmProviderPresenter { stopStream(eventId: string): Promise check(providerId: string, modelId?: string): Promise<{ isOk: boolean; errorMsg: string | null }> getKeyStatus(providerId: string): Promise + refreshModels(providerId: string): Promise summaryTitles( messages: { role: 'system' | 'user' | 'assistant'; content: string }[], providerId: string,