refactor(source): extract buildSourceInfoMap

This commit is contained in:
Supra4E8C
2026-02-22 16:08:06 +08:00
parent 095f13bf4c
commit c25e7556ed
3 changed files with 74 additions and 136 deletions
@@ -7,9 +7,9 @@ import { Select } from '@/components/ui/Select';
import { authFilesApi } from '@/services/api/authFiles';
import type { GeminiKeyConfig, ProviderKeyConfig, OpenAIProviderConfig } from '@/types';
import type { AuthFileItem } from '@/types/authFile';
import type { CredentialInfo, SourceInfo } from '@/types/sourceInfo';
import type { CredentialInfo } from '@/types/sourceInfo';
import { buildSourceInfoMap } from '@/utils/sourceResolver';
import {
buildCandidateUsageSourceIds,
collectUsageDetails,
extractTotalTokens,
normalizeAuthIndex
@@ -102,75 +102,17 @@ export function RequestEventsDetailsCard({
};
}, []);
const sourceInfoMap = useMemo(() => {
const map = new Map<string, SourceInfo>();
const registerSource = (sourceId: string, displayName: string, type: string) => {
if (!sourceId || !displayName) return;
if (map.has(sourceId)) return;
map.set(sourceId, { displayName, type });
};
const registerCandidates = (
displayName: string,
type: string,
candidates: string[]
) => {
candidates.forEach((sourceId) => registerSource(sourceId, displayName, type));
};
geminiKeys.forEach((config, index) => {
const displayName = config.prefix?.trim() || `Gemini #${index + 1}`;
registerCandidates(
displayName,
'gemini',
buildCandidateUsageSourceIds({ apiKey: config.apiKey, prefix: config.prefix })
);
});
claudeConfigs.forEach((config, index) => {
const displayName = config.prefix?.trim() || `Claude #${index + 1}`;
registerCandidates(
displayName,
'claude',
buildCandidateUsageSourceIds({ apiKey: config.apiKey, prefix: config.prefix })
);
});
codexConfigs.forEach((config, index) => {
const displayName = config.prefix?.trim() || `Codex #${index + 1}`;
registerCandidates(
displayName,
'codex',
buildCandidateUsageSourceIds({ apiKey: config.apiKey, prefix: config.prefix })
);
});
vertexConfigs.forEach((config, index) => {
const displayName = config.prefix?.trim() || `Vertex #${index + 1}`;
registerCandidates(
displayName,
'vertex',
buildCandidateUsageSourceIds({ apiKey: config.apiKey, prefix: config.prefix })
);
});
openaiProviders.forEach((provider, providerIndex) => {
const displayName = provider.prefix?.trim() || provider.name || `OpenAI #${providerIndex + 1}`;
const candidates = new Set<string>();
buildCandidateUsageSourceIds({ prefix: provider.prefix }).forEach((sourceId) =>
candidates.add(sourceId)
);
(provider.apiKeyEntries || []).forEach((entry) => {
buildCandidateUsageSourceIds({ apiKey: entry.apiKey }).forEach((sourceId) =>
candidates.add(sourceId)
);
});
registerCandidates(displayName, 'openai', Array.from(candidates));
});
return map;
}, [claudeConfigs, codexConfigs, geminiKeys, openaiProviders, vertexConfigs]);
const sourceInfoMap = useMemo(
() =>
buildSourceInfoMap({
geminiApiKeys: geminiKeys,
claudeApiKeys: claudeConfigs,
codexApiKeys: codexConfigs,
vertexApiKeys: vertexConfigs,
openaiCompatibility: openaiProviders,
}),
[claudeConfigs, codexConfigs, geminiKeys, openaiProviders, vertexConfigs]
);
const rows = useMemo<RequestEventRow[]>(() => {
const details = collectUsageDetails(usage);
+2 -65
View File
@@ -28,8 +28,8 @@ import { copyToClipboard } from '@/utils/clipboard';
import { downloadBlob } from '@/utils/download';
import { MANAGEMENT_API_PREFIX } from '@/utils/constants';
import { formatUnixTimestamp } from '@/utils/format';
import { buildSourceInfoMap } from '@/utils/sourceResolver';
import {
buildCandidateUsageSourceIds,
collectUsageDetailsWithEndpoint,
normalizeAuthIndex,
type UsageDetailWithEndpoint
@@ -519,70 +519,7 @@ export function LogsPage() {
const latestTimestampRef = useRef<number>(0);
const disableControls = connectionStatus !== 'connected';
const traceSourceInfoMap = useMemo(() => {
const map = new Map<string, SourceInfo>();
const registerSource = (sourceId: string, displayName: string, type: string) => {
if (!sourceId || !displayName || map.has(sourceId)) return;
map.set(sourceId, { displayName, type });
};
const registerCandidates = (displayName: string, type: string, candidates: string[]) => {
candidates.forEach((sourceId) => registerSource(sourceId, displayName, type));
};
(config?.geminiApiKeys || []).forEach((item, index) => {
const displayName = item.prefix?.trim() || `Gemini #${index + 1}`;
registerCandidates(
displayName,
'gemini',
buildCandidateUsageSourceIds({ apiKey: item.apiKey, prefix: item.prefix })
);
});
(config?.claudeApiKeys || []).forEach((item, index) => {
const displayName = item.prefix?.trim() || `Claude #${index + 1}`;
registerCandidates(
displayName,
'claude',
buildCandidateUsageSourceIds({ apiKey: item.apiKey, prefix: item.prefix })
);
});
(config?.codexApiKeys || []).forEach((item, index) => {
const displayName = item.prefix?.trim() || `Codex #${index + 1}`;
registerCandidates(
displayName,
'codex',
buildCandidateUsageSourceIds({ apiKey: item.apiKey, prefix: item.prefix })
);
});
(config?.vertexApiKeys || []).forEach((item, index) => {
const displayName = item.prefix?.trim() || `Vertex #${index + 1}`;
registerCandidates(
displayName,
'vertex',
buildCandidateUsageSourceIds({ apiKey: item.apiKey, prefix: item.prefix })
);
});
(config?.openaiCompatibility || []).forEach((provider, providerIndex) => {
const displayName = provider.prefix?.trim() || provider.name || `OpenAI #${providerIndex + 1}`;
const candidates = new Set<string>();
buildCandidateUsageSourceIds({ prefix: provider.prefix }).forEach((sourceId) =>
candidates.add(sourceId)
);
(provider.apiKeyEntries || []).forEach((entry) => {
buildCandidateUsageSourceIds({ apiKey: entry.apiKey }).forEach((sourceId) =>
candidates.add(sourceId)
);
});
registerCandidates(displayName, 'openai', Array.from(candidates));
});
return map;
}, [config]);
const traceSourceInfoMap = useMemo(() => buildSourceInfoMap(config ?? {}), [config]);
const isNearBottom = (node: HTMLDivElement | null) => {
if (!node) return true;
+59
View File
@@ -0,0 +1,59 @@
import type { GeminiKeyConfig, OpenAIProviderConfig, ProviderKeyConfig } from '@/types';
import type { SourceInfo } from '@/types/sourceInfo';
import { buildCandidateUsageSourceIds } from '@/utils/usage';
export interface SourceInfoMapInput {
geminiApiKeys?: GeminiKeyConfig[];
claudeApiKeys?: ProviderKeyConfig[];
codexApiKeys?: ProviderKeyConfig[];
vertexApiKeys?: ProviderKeyConfig[];
openaiCompatibility?: OpenAIProviderConfig[];
}
export function buildSourceInfoMap(input: SourceInfoMapInput): Map<string, SourceInfo> {
const map = new Map<string, SourceInfo>();
const registerSource = (sourceId: string, displayName: string, type: string) => {
if (!sourceId || !displayName || map.has(sourceId)) return;
map.set(sourceId, { displayName, type });
};
const registerCandidates = (displayName: string, type: string, candidates: string[]) => {
candidates.forEach((sourceId) => registerSource(sourceId, displayName, type));
};
const providers: Array<{
items: Array<{ apiKey?: string; prefix?: string }>;
type: string;
label: string;
}> = [
{ items: input.geminiApiKeys || [], type: 'gemini', label: 'Gemini' },
{ items: input.claudeApiKeys || [], type: 'claude', label: 'Claude' },
{ items: input.codexApiKeys || [], type: 'codex', label: 'Codex' },
{ items: input.vertexApiKeys || [], type: 'vertex', label: 'Vertex' },
];
providers.forEach(({ items, type, label }) => {
items.forEach((item, index) => {
const displayName = item.prefix?.trim() || `${label} #${index + 1}`;
registerCandidates(
displayName,
type,
buildCandidateUsageSourceIds({ apiKey: item.apiKey, prefix: item.prefix })
);
});
});
// OpenAI 特殊处理:多 apiKeyEntries
(input.openaiCompatibility || []).forEach((provider, providerIndex) => {
const displayName = provider.prefix?.trim() || provider.name || `OpenAI #${providerIndex + 1}`;
const candidates = new Set<string>();
buildCandidateUsageSourceIds({ prefix: provider.prefix }).forEach((id) => candidates.add(id));
(provider.apiKeyEntries || []).forEach((entry) => {
buildCandidateUsageSourceIds({ apiKey: entry.apiKey }).forEach((id) => candidates.add(id));
});
registerCandidates(displayName, 'openai', Array.from(candidates));
});
return map;
}