From 45b0b979de93fe1a8bbeddfd3c00e11a33a383c8 Mon Sep 17 00:00:00 2001 From: Lstmxx <36261034+Lstmxx@users.noreply.github.com> Date: Thu, 15 Jan 2026 16:46:50 +0800 Subject: [PATCH] feat(stage-ui): support custom model (#880) --- .../pages/settings/modules/consciousness.vue | 1 + .../menu/radio-card-many-select.vue | 46 ++++++++++++++++--- .../onboarding/step-model-selection.vue | 1 + 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/packages/stage-pages/src/pages/settings/modules/consciousness.vue b/packages/stage-pages/src/pages/settings/modules/consciousness.vue index 9037581dd..f229907fa 100644 --- a/packages/stage-pages/src/pages/settings/modules/consciousness.vue +++ b/packages/stage-pages/src/pages/settings/modules/consciousness.vue @@ -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 })" diff --git a/packages/stage-ui/src/components/menu/radio-card-many-select.vue b/packages/stage-ui/src/components/menu/radio-card-many-select.vue index 78679fd99..d41868d6f 100644 --- a/packages/stage-ui/src/components/menu/radio-card-many-select.vue +++ b/packages/stage-ui/src/components/menu/radio-card-many-select.vue @@ -24,6 +24,8 @@ interface Props { collapseButtonText?: string showMore?: boolean listClass?: string + allowCustom?: boolean + customOptionDescription?: string } const props = withDefaults(defineProps(), { @@ -37,6 +39,8 @@ const props = withDefaults(defineProps(), { 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) { diff --git a/packages/stage-ui/src/components/scenarios/dialogs/onboarding/step-model-selection.vue b/packages/stage-ui/src/components/scenarios/dialogs/onboarding/step-model-selection.vue index 1229c7330..75f86ecda 100644 --- a/packages/stage-ui/src/components/scenarios/dialogs/onboarding/step-model-selection.vue +++ b/packages/stage-ui/src/components/scenarios/dialogs/onboarding/step-model-selection.vue @@ -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 })"