diff --git a/src/renderer/settings/components/ProviderModelList.vue b/src/renderer/settings/components/ProviderModelList.vue index 431005094..fe03599e5 100644 --- a/src/renderer/settings/components/ProviderModelList.vue +++ b/src/renderer/settings/components/ProviderModelList.vue @@ -227,8 +227,9 @@ -
+
{ const statusSortWeight = (model: RENDERER_MODEL_META) => (model.enabled ? 0 : 1) +const getModelKey = (model: RENDERER_MODEL_META) => `${model.providerId}:${model.id}` +const statusSortOrder = ref>({}) + +const buildStatusSortOrder = () => { + const models = [ + ...props.customModels, + ...props.providerModels.flatMap((provider) => provider.models) + ] + const nextOrder: Record = {} + const orderedModels = [...models].sort((left, right) => { + const statusDifference = statusSortWeight(left) - statusSortWeight(right) + if (statusDifference !== 0) { + return statusDifference + } + + return modelNameCollator.compare(left.name, right.name) + }) + + orderedModels.forEach((model, index) => { + nextOrder[getModelKey(model)] = index + }) + + statusSortOrder.value = nextOrder +} + +const modelStructureSignature = computed(() => + JSON.stringify({ + customModels: props.customModels.map((model) => ({ + providerId: model.providerId, + id: model.id, + name: model.name, + group: model.group, + type: model.type ?? ModelType.Chat, + capabilities: getModelCapabilityValues(model) + })), + providerModels: props.providerModels.map((provider) => ({ + providerId: provider.providerId, + models: provider.models.map((model) => ({ + id: model.id, + name: model.name, + group: model.group, + type: model.type ?? ModelType.Chat, + capabilities: getModelCapabilityValues(model) + })) + })) + }) +) + +watch(modelStructureSignature, buildStatusSortOrder, { immediate: true }) + const sortModels = (models: RENDERER_MODEL_META[]) => [...models].sort((left, right) => { if (filterState.sort === 'name') { return modelNameCollator.compare(left.name, right.name) } - const statusDifference = statusSortWeight(left) - statusSortWeight(right) - if (statusDifference !== 0) { - return statusDifference + const leftRank = statusSortOrder.value[getModelKey(left)] + const rightRank = statusSortOrder.value[getModelKey(right)] + + if (leftRank !== undefined || rightRank !== undefined) { + if (leftRank === undefined) { + return 1 + } + + if (rightRank === undefined) { + return -1 + } + + if (leftRank !== rightRank) { + return leftRank - rightRank + } } return modelNameCollator.compare(left.name, right.name) @@ -634,6 +697,9 @@ const removeFilterToken = (token: FilterToken) => { } const setSort = (sort: ModelSortKey) => { + if (sort === 'status') { + buildStatusSortOrder() + } filterState.sort = sort sortPopoverOpen.value = false } diff --git a/src/renderer/src/components/settings/ModelConfigItem.vue b/src/renderer/src/components/settings/ModelConfigItem.vue index 5f2a87d6b..f3a370183 100644 --- a/src/renderer/src/components/settings/ModelConfigItem.vue +++ b/src/renderer/src/components/settings/ModelConfigItem.vue @@ -35,6 +35,7 @@