mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-06-16 21:03:58 +08:00
refactor(providers): expose model names and priority on the resource view model
The workbench page reached back into resource.raw with brand-specific parsing to derive model names and priority, bypassing the adapter layer. Normalize both in the adapters and consume the typed fields.
This commit is contained in:
@@ -11,7 +11,6 @@ import {
|
||||
type ProviderRecentUsageMap,
|
||||
} from '@/components/providers/utils';
|
||||
import type { OpenAIProviderConfig } from '@/types';
|
||||
import { isRecord } from '@/utils/helpers';
|
||||
import { ProviderHeaderCard } from './components/ProviderHeaderCard';
|
||||
import { ProviderCategoryList } from './components/ProviderCategoryList';
|
||||
import { ProviderResourcePanel } from './components/ProviderResourcePanel';
|
||||
@@ -67,38 +66,6 @@ const matchesFilter = (r: ProviderResource, normalized: string): boolean => {
|
||||
return haystack.some((v) => v.includes(normalized));
|
||||
};
|
||||
|
||||
const getResourceModels = (resource: ProviderResource): string[] => {
|
||||
if (!isRecord(resource.raw)) return [];
|
||||
if (resource.brand === 'ampcode') {
|
||||
const mappings = resource.raw.modelMappings;
|
||||
if (!Array.isArray(mappings)) return [];
|
||||
const seen = new Set<string>();
|
||||
mappings.forEach((mapping) => {
|
||||
if (!isRecord(mapping)) return;
|
||||
const from = typeof mapping.from === 'string' ? mapping.from.trim() : '';
|
||||
const to = typeof mapping.to === 'string' ? mapping.to.trim() : '';
|
||||
if (from) seen.add(from);
|
||||
if (to) seen.add(to);
|
||||
});
|
||||
return Array.from(seen);
|
||||
}
|
||||
const models = resource.raw.models;
|
||||
if (!Array.isArray(models)) return [];
|
||||
const seen = new Set<string>();
|
||||
models.forEach((model) => {
|
||||
if (!isRecord(model)) return;
|
||||
const name = typeof model.name === 'string' ? model.name.trim() : '';
|
||||
if (name) seen.add(name);
|
||||
});
|
||||
return Array.from(seen);
|
||||
};
|
||||
|
||||
const getResourcePriority = (resource: ProviderResource): number => {
|
||||
if (!isRecord(resource.raw)) return 0;
|
||||
const priority = resource.raw.priority;
|
||||
return typeof priority === 'number' && Number.isFinite(priority) ? priority : 0;
|
||||
};
|
||||
|
||||
const getResourceSortName = (resource: ProviderResource): string =>
|
||||
(resource.name ?? resource.identifier ?? resource.apiKeyPreview ?? '').toLowerCase();
|
||||
|
||||
@@ -216,7 +183,7 @@ export function ProvidersWorkbenchPage() {
|
||||
if (!activeGroup) return [];
|
||||
const seen = new Set<string>();
|
||||
activeGroup.resources.forEach((r) => {
|
||||
getResourceModels(r).forEach((name) => seen.add(name));
|
||||
r.models.forEach((name) => seen.add(name));
|
||||
});
|
||||
return Array.from(seen).sort();
|
||||
}, [activeGroup]);
|
||||
@@ -232,10 +199,7 @@ export function ProvidersWorkbenchPage() {
|
||||
const visibleResources = useMemo(() => {
|
||||
let arr = filteredResources;
|
||||
if (selectedModels.size > 0) {
|
||||
arr = arr.filter((r) => {
|
||||
const models = getResourceModels(r);
|
||||
return models.some((name) => selectedModels.has(name));
|
||||
});
|
||||
arr = arr.filter((r) => r.models.some((name) => selectedModels.has(name)));
|
||||
}
|
||||
|
||||
const sorted = [...arr].sort((a, b) => {
|
||||
@@ -243,9 +207,7 @@ export function ProvidersWorkbenchPage() {
|
||||
if (providerSortBy === 'name') {
|
||||
diff = getResourceSortName(a).localeCompare(getResourceSortName(b));
|
||||
} else if (providerSortBy === 'priority') {
|
||||
const ap = getResourcePriority(a);
|
||||
const bp = getResourcePriority(b);
|
||||
diff = ap - bp;
|
||||
diff = a.priority - b.priority;
|
||||
} else {
|
||||
diff =
|
||||
getResourceRecentSuccess(a, usageByProvider) -
|
||||
|
||||
@@ -18,6 +18,29 @@ import type {
|
||||
const countHeaders = (headers?: Record<string, string>): number =>
|
||||
headers ? Object.keys(headers).length : 0;
|
||||
|
||||
const collectModelNames = (models?: Array<{ name?: string }>): string[] => {
|
||||
const seen = new Set<string>();
|
||||
(models ?? []).forEach((model) => {
|
||||
const name = (model?.name ?? '').trim();
|
||||
if (name) seen.add(name);
|
||||
});
|
||||
return Array.from(seen);
|
||||
};
|
||||
|
||||
const collectAmpcodeModelNames = (mappings: AmpcodeConfig['modelMappings']): string[] => {
|
||||
const seen = new Set<string>();
|
||||
(mappings ?? []).forEach((mapping) => {
|
||||
const from = (mapping?.from ?? '').trim();
|
||||
const to = (mapping?.to ?? '').trim();
|
||||
if (from) seen.add(from);
|
||||
if (to) seen.add(to);
|
||||
});
|
||||
return Array.from(seen);
|
||||
};
|
||||
|
||||
const normalizePriority = (priority?: number): number =>
|
||||
typeof priority === 'number' && Number.isFinite(priority) ? priority : 0;
|
||||
|
||||
const buildId = (brand: ProviderBrand, index: number, fragment: string) =>
|
||||
`${brand}:${index}:${fragment || 'item'}`;
|
||||
|
||||
@@ -64,6 +87,8 @@ function providerKeyToResource(
|
||||
proxyUrl: config.proxyUrl ?? null,
|
||||
prefix: config.prefix ?? null,
|
||||
modelCount: config.models?.length ?? 0,
|
||||
models: collectModelNames(config.models),
|
||||
priority: normalizePriority(config.priority),
|
||||
headerCount: countHeaders(config.headers),
|
||||
excludedModelCount: stripDisableAllModelsRule(config.excludedModels).length,
|
||||
apiKeyEntryCount: 0,
|
||||
@@ -110,6 +135,8 @@ export function openaiToResource(
|
||||
proxyUrl: null,
|
||||
prefix: config.prefix ?? null,
|
||||
modelCount: config.models?.length ?? 0,
|
||||
models: collectModelNames(config.models),
|
||||
priority: normalizePriority(config.priority),
|
||||
headerCount: countHeaders(config.headers),
|
||||
excludedModelCount: 0,
|
||||
apiKeyEntryCount: config.apiKeyEntries?.length ?? 0,
|
||||
@@ -139,6 +166,8 @@ export function ampcodeToResource(config?: AmpcodeConfig | null): ProviderResour
|
||||
proxyUrl: null,
|
||||
prefix: null,
|
||||
modelCount: safe.modelMappings?.length ?? 0,
|
||||
models: collectAmpcodeModelNames(safe.modelMappings),
|
||||
priority: 0,
|
||||
headerCount: 0,
|
||||
excludedModelCount: 0,
|
||||
apiKeyEntryCount: upstreamKeyMappingsCount,
|
||||
|
||||
@@ -50,6 +50,10 @@ export interface ProviderResource {
|
||||
proxyUrl: string | null;
|
||||
prefix: string | null;
|
||||
modelCount: number;
|
||||
/** 去重后的模型名(ampcode 为映射两端), 供筛选/搜索用 */
|
||||
models: string[];
|
||||
/** 排序用优先级,未配置时为 0 */
|
||||
priority: number;
|
||||
headerCount: number;
|
||||
excludedModelCount: number;
|
||||
/** 仅 OpenAI 有意义,其它 brand 该字段不展示但保留 */
|
||||
|
||||
Reference in New Issue
Block a user