mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-02-19 03:00:49 +08:00
fix(ui): use fixed-length key masking and fingerprint usage sources
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import type { AmpcodeConfig, AmpcodeModelMapping, ApiKeyEntry } from '@/types';
|
||||
import type { KeyStatBucket, KeyStats } from '@/utils/usage';
|
||||
import { buildCandidateUsageSourceIds, type KeyStatBucket, type KeyStats } from '@/utils/usage';
|
||||
import type { AmpcodeFormState, ModelEntry } from './types';
|
||||
|
||||
export const DISABLE_ALL_MODELS_RULE = '*';
|
||||
@@ -62,33 +62,50 @@ export const buildOpenAIChatCompletionsEndpoint = (baseUrl: string): string => {
|
||||
export const getStatsBySource = (
|
||||
apiKey: string,
|
||||
keyStats: KeyStats,
|
||||
maskFn: (key: string) => string
|
||||
prefix?: string
|
||||
): KeyStatBucket => {
|
||||
const bySource = keyStats.bySource ?? {};
|
||||
const masked = maskFn(apiKey);
|
||||
return bySource[apiKey] || bySource[masked] || { success: 0, failure: 0 };
|
||||
const candidates = buildCandidateUsageSourceIds({ apiKey, prefix });
|
||||
if (!candidates.length) {
|
||||
return { success: 0, failure: 0 };
|
||||
}
|
||||
|
||||
let success = 0;
|
||||
let failure = 0;
|
||||
candidates.forEach((candidate) => {
|
||||
const stats = bySource[candidate];
|
||||
if (!stats) return;
|
||||
success += stats.success;
|
||||
failure += stats.failure;
|
||||
});
|
||||
|
||||
return { success, failure };
|
||||
};
|
||||
|
||||
// 对于 OpenAI 提供商,汇总所有 apiKeyEntries 的统计 - 与旧版逻辑一致
|
||||
export const getOpenAIProviderStats = (
|
||||
apiKeyEntries: ApiKeyEntry[] | undefined,
|
||||
keyStats: KeyStats,
|
||||
maskFn: (key: string) => string
|
||||
providerPrefix?: string
|
||||
): KeyStatBucket => {
|
||||
const bySource = keyStats.bySource ?? {};
|
||||
let totalSuccess = 0;
|
||||
let totalFailure = 0;
|
||||
|
||||
const sourceIds = new Set<string>();
|
||||
buildCandidateUsageSourceIds({ prefix: providerPrefix }).forEach((id) => sourceIds.add(id));
|
||||
(apiKeyEntries || []).forEach((entry) => {
|
||||
const key = entry?.apiKey || '';
|
||||
if (!key) return;
|
||||
const masked = maskFn(key);
|
||||
const stats = bySource[key] || bySource[masked] || { success: 0, failure: 0 };
|
||||
totalSuccess += stats.success;
|
||||
totalFailure += stats.failure;
|
||||
buildCandidateUsageSourceIds({ apiKey: entry?.apiKey }).forEach((id) => sourceIds.add(id));
|
||||
});
|
||||
|
||||
return { success: totalSuccess, failure: totalFailure };
|
||||
let success = 0;
|
||||
let failure = 0;
|
||||
sourceIds.forEach((id) => {
|
||||
const stats = bySource[id];
|
||||
if (!stats) return;
|
||||
success += stats.success;
|
||||
failure += stats.failure;
|
||||
});
|
||||
|
||||
return { success, failure };
|
||||
};
|
||||
|
||||
export const buildApiKeyEntry = (input?: Partial<ApiKeyEntry>): ApiKeyEntry => ({
|
||||
|
||||
Reference in New Issue
Block a user