diff --git a/i18n.js b/i18n.js
index 0a5f0f1..7b8b856 100644
--- a/i18n.js
+++ b/i18n.js
@@ -224,6 +224,9 @@ const i18n = {
'ai_providers.openai_models_fetch_error': '获取模型失败',
'ai_providers.openai_models_fetch_back': '返回编辑',
'ai_providers.openai_models_fetch_apply': '添加所选模型',
+ 'ai_providers.openai_models_search_label': '搜索模型',
+ 'ai_providers.openai_models_search_placeholder': '按名称、别名或描述筛选',
+ 'ai_providers.openai_models_search_empty': '没有匹配的模型,请更换关键字试试。',
'ai_providers.openai_models_fetch_invalid_url': '请先填写有效的 Base URL',
'ai_providers.openai_models_fetch_added': '已添加 {count} 个新模型',
'ai_providers.openai_edit_modal_title': '编辑OpenAI兼容提供商',
@@ -843,6 +846,9 @@ const i18n = {
'ai_providers.openai_models_fetch_error': 'Failed to fetch models',
'ai_providers.openai_models_fetch_back': 'Back to edit',
'ai_providers.openai_models_fetch_apply': 'Add selected models',
+ 'ai_providers.openai_models_search_label': 'Search models',
+ 'ai_providers.openai_models_search_placeholder': 'Filter by name, alias, or description',
+ 'ai_providers.openai_models_search_empty': 'No models match your search. Try a different keyword.',
'ai_providers.openai_models_fetch_invalid_url': 'Please enter a valid Base URL first',
'ai_providers.openai_models_fetch_added': '{count} new models added',
'ai_providers.openai_edit_modal_title': 'Edit OpenAI Compatible Provider',
diff --git a/src/modules/ai-providers.js b/src/modules/ai-providers.js
index 6d611d9..0afa989 100644
--- a/src/modules/ai-providers.js
+++ b/src/modules/ai-providers.js
@@ -1152,6 +1152,10 @@ function ensureOpenAIModelDiscoveryCard(manager) {
+
+
+
+
@@ -1174,6 +1178,13 @@ function ensureOpenAIModelDiscoveryCard(manager) {
bind('openai-model-discovery-cancel', () => manager.closeOpenAIModelDiscovery());
bind('openai-model-discovery-refresh', () => manager.refreshOpenAIModelDiscovery());
bind('openai-model-discovery-apply', () => manager.applyOpenAIModelDiscoverySelection());
+ const searchInput = document.getElementById('openai-model-discovery-search');
+ if (searchInput) {
+ searchInput.addEventListener('input', (event) => {
+ const query = event?.target?.value || '';
+ manager.setOpenAIModelDiscoverySearch(query);
+ });
+ }
return overlay;
}
@@ -1185,10 +1196,30 @@ export function setOpenAIModelDiscoveryStatus(message = '', type = 'info') {
status.className = `model-discovery-status ${type}`;
}
+export function setOpenAIModelDiscoverySearch(query = '') {
+ if (!this.openAIModelDiscoveryContext) return;
+ const normalized = (query || '').trim();
+ this.openAIModelDiscoveryContext.modelSearchQuery = normalized;
+ const models = this.openAIModelDiscoveryContext.discoveredModels || [];
+ this.renderOpenAIModelDiscoveryList(models);
+}
+
export function renderOpenAIModelDiscoveryList(models = []) {
const list = document.getElementById('openai-model-discovery-list');
if (!list) return;
+ const context = this.openAIModelDiscoveryContext || {};
+ const filter = (context.modelSearchQuery || '').trim().toLowerCase();
+ const filtered = models
+ .map((model, index) => ({ model, index }))
+ .filter(({ model }) => {
+ if (!filter) return true;
+ const name = (model?.name || '').toLowerCase();
+ const alias = (model?.alias || '').toLowerCase();
+ const desc = (model?.description || '').toLowerCase();
+ return name.includes(filter) || alias.includes(filter) || desc.includes(filter);
+ });
+
if (!models.length) {
list.innerHTML = `
@@ -1199,10 +1230,20 @@ export function renderOpenAIModelDiscoveryList(models = []) {
return;
}
- list.innerHTML = models.map((model, index) => {
- const name = this.escapeHtml(model.name || '');
- const alias = model.alias ? `
${this.escapeHtml(model.alias)}` : '';
- const desc = model.description ? `
${this.escapeHtml(model.description)}
` : '';
+ if (!filtered.length) {
+ list.innerHTML = `
+
+
+ ${i18n.t('ai_providers.openai_models_search_empty')}
+
+ `;
+ return;
+ }
+
+ list.innerHTML = filtered.map(({ model, index }) => {
+ const name = this.escapeHtml(model?.name || '');
+ const alias = model?.alias ? `
${this.escapeHtml(model.alias)}` : '';
+ const desc = model?.description ? `
${this.escapeHtml(model.description)}
` : '';
return `