feat(stage-ui): support custom model (#880)

This commit is contained in:
Lstmxx
2026-01-15 16:46:50 +08:00
committed by GitHub
parent 06b3451849
commit 45b0b979de
3 changed files with 41 additions and 7 deletions
@@ -179,6 +179,7 @@ function handleDeleteProvider(providerId: string) {
v-model:search-query="modelSearchQuery"
:items="providerModels.sort((a, b) => a.id === activeModel ? -1 : b.id === activeModel ? 1 : 0)"
:searchable="true"
:allow-custom="true"
:search-placeholder="t('settings.pages.modules.consciousness.sections.section.provider-model-selection.search_placeholder')"
:search-no-results-title="t('settings.pages.modules.consciousness.sections.section.provider-model-selection.no_search_results')"
:search-no-results-description="t('settings.pages.modules.consciousness.sections.section.provider-model-selection.no_search_results_description', { query: modelSearchQuery })"
@@ -24,6 +24,8 @@ interface Props {
collapseButtonText?: string
showMore?: boolean
listClass?: string
allowCustom?: boolean
customOptionDescription?: string
}
const props = withDefaults(defineProps<Props>(), {
@@ -37,6 +39,8 @@ const props = withDefaults(defineProps<Props>(), {
collapseButtonText: 'Show less',
showMore: true,
listClass: '',
allowCustom: false,
customOptionDescription: 'Custom Value',
})
const emit = defineEmits<{
@@ -50,14 +54,42 @@ const isListExpanded = ref(false)
const customValue = ref('')
const filteredItems = computed(() => {
if (!searchQuery.value)
return props.items
let result = [...props.items]
const query = searchQuery.value.toLowerCase()
return props.items.filter(item =>
item.name.toLowerCase().includes(query)
|| (item.description && item.description.toLowerCase().includes(query)),
)
// If a custom value is selected (and not present in items), add it to the list temporarily
if (modelValue.value && !props.items.some(i => i.id.toLowerCase() === modelValue.value.toLowerCase())) {
result.unshift({
id: modelValue.value,
name: modelValue.value,
description: props.customOptionDescription,
customizable: false,
})
}
if (searchQuery.value) {
const query = searchQuery.value.toLowerCase()
result = result.filter(item =>
item.name.toLowerCase().includes(query)
|| (item.description && item.description.toLowerCase().includes(query)),
)
}
// Add "Use custom: ..." option if searching and custom input is allowed
if (props.allowCustom && searchQuery.value) {
const query = searchQuery.value
// Check against checks if the exact ID exists to avoid duplicates
const exactMatch = result.some(i => i.id.toLowerCase() === query.toLowerCase())
if (!exactMatch) {
result.push({
id: query,
name: query,
description: props.customOptionDescription,
customizable: false,
})
}
}
return result
})
function updateCustomValue(value: string) {
@@ -42,6 +42,7 @@ const {
v-model:search-query="modelSearchQuery"
:items="providerModels.toSorted((a, b) => a.id === activeModel ? -1 : b.id === activeModel ? 1 : 0)"
:searchable="true"
:allow-custom="true"
:search-placeholder="t('settings.pages.modules.consciousness.sections.section.provider-model-selection.search_placeholder')"
:search-no-results-title="t('settings.pages.modules.consciousness.sections.section.provider-model-selection.no_search_results')"
:search-no-results-description="t('settings.pages.modules.consciousness.sections.section.provider-model-selection.no_search_results_description', { query: modelSearchQuery })"