From 480f3ba46949b4d44b1a36fa5a6dcc2699a311d5 Mon Sep 17 00:00:00 2001 From: "Kai (Tam Nhu) Tran" <61256810+kaitranntt@users.noreply.github.com> Date: Sat, 30 May 2026 14:56:17 -0400 Subject: [PATCH 1/2] fix: harden provider alias normalization --- src/cliproxy/quota/quota-manager.ts | 10 +++--- src/management/checks/image-analysis-check.ts | 5 ++- src/web-server/models-dev/pricing-resolver.ts | 28 +++++++-------- tests/unit/data-aggregator.test.ts | 34 +++++++++++++++++++ 4 files changed, 54 insertions(+), 23 deletions(-) diff --git a/src/cliproxy/quota/quota-manager.ts b/src/cliproxy/quota/quota-manager.ts index 8574b079..041e2748 100644 --- a/src/cliproxy/quota/quota-manager.ts +++ b/src/cliproxy/quota/quota-manager.ts @@ -483,9 +483,8 @@ export async function reconcileExhaustedRotationAccounts( return []; } - const { pauseAccountForQuotaCooldown, restoreExpiredQuotaPauses } = await import( - '../accounts/account-safety' - ); + const { pauseAccountForQuotaCooldown, restoreExpiredQuotaPauses } = + await import('../accounts/account-safety'); restoreExpiredQuotaPauses(); const config = loadOrCreateUnifiedConfig(); @@ -593,9 +592,8 @@ export async function preflightCheck(provider: CLIProxyProvider): Promise * Fix image analysis configuration issues */ export async function fixImageAnalysisConfig(): Promise { - const { updateConfig, loadOrCreateUnifiedConfig } = await import( - '../../config/config-loader-facade' - ); + const { updateConfig, loadOrCreateUnifiedConfig } = + await import('../../config/config-loader-facade'); const config = loadOrCreateUnifiedConfig(); let fixed = false; diff --git a/src/web-server/models-dev/pricing-resolver.ts b/src/web-server/models-dev/pricing-resolver.ts index 715e7600..9be07d1b 100644 --- a/src/web-server/models-dev/pricing-resolver.ts +++ b/src/web-server/models-dev/pricing-resolver.ts @@ -18,19 +18,19 @@ export interface ModelsDevPricingLookupOptions { provider?: string; } -const PROVIDER_ALIASES: Record = { - agy: 'google', - antigravity: 'google', - claude: 'anthropic', - codex: 'openai', - copilot: 'github-copilot', - gemini: 'google', - ghcp: 'github-copilot', - github: 'github-copilot', - kimi: 'moonshotai', - moonshot: 'moonshotai', - qwen: 'alibaba', -}; +const PROVIDER_ALIASES = new Map([ + ['agy', 'google'], + ['antigravity', 'google'], + ['claude', 'anthropic'], + ['codex', 'openai'], + ['copilot', 'github-copilot'], + ['gemini', 'google'], + ['ghcp', 'github-copilot'], + ['github', 'github-copilot'], + ['kimi', 'moonshotai'], + ['moonshot', 'moonshotai'], + ['qwen', 'alibaba'], +]); function normalizeId(value: string): string { return value.trim().toLowerCase(); @@ -45,7 +45,7 @@ export function normalizeModelsDevProviderId( ): string | undefined { if (!provider) return undefined; const normalized = normalizeId(provider); - return PROVIDER_ALIASES[normalized] ?? normalized; + return PROVIDER_ALIASES.get(normalized) ?? normalized; } function splitProviderPrefix(model: string): { provider?: string; model: string } { diff --git a/tests/unit/data-aggregator.test.ts b/tests/unit/data-aggregator.test.ts index e15d468c..5aa90210 100644 --- a/tests/unit/data-aggregator.test.ts +++ b/tests/unit/data-aggregator.test.ts @@ -150,6 +150,40 @@ describe('aggregateDailyUsage', () => { expect(result[0].modelBreakdowns[0].provider).toBe('github-copilot'); expect(result[0].modelBreakdowns[0].inputTokens).toBe(3000); }); + + test('handles provider names inherited from Object.prototype', () => { + const entries: RawUsageEntry[] = [ + createEntry({ model: 'model-a', target: '__proto__' }), + createEntry({ model: 'model-b', target: 'constructor' }), + createEntry({ model: 'model-c', target: 'toString' }), + ]; + + const daily = aggregateDailyUsage(entries); + const hourly = aggregateHourlyUsage(entries); + const monthly = aggregateMonthlyUsage(entries); + const session = aggregateSessionUsage(entries); + + expect(daily[0].modelBreakdowns.map((item) => item.provider)).toEqual([ + '__proto__', + 'constructor', + 'tostring', + ]); + expect(hourly[0].modelBreakdowns.map((item) => item.provider)).toEqual([ + '__proto__', + 'constructor', + 'tostring', + ]); + expect(monthly[0].modelBreakdowns.map((item) => item.provider)).toEqual([ + '__proto__', + 'constructor', + 'tostring', + ]); + expect(session[0].modelBreakdowns.map((item) => item.provider)).toEqual([ + '__proto__', + 'constructor', + 'tostring', + ]); + }); }); // ============================================================================ From 0ca3e4b35a356e0bbeabb3cb8b996f6eb71d70f7 Mon Sep 17 00:00:00 2001 From: Tam Nhu Tran Date: Sat, 30 May 2026 15:31:38 -0400 Subject: [PATCH 2/2] style: format provider alias normalization changes --- src/cliproxy/quota/quota-manager.ts | 10 ++++++---- src/management/checks/image-analysis-check.ts | 5 +++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/cliproxy/quota/quota-manager.ts b/src/cliproxy/quota/quota-manager.ts index 041e2748..8574b079 100644 --- a/src/cliproxy/quota/quota-manager.ts +++ b/src/cliproxy/quota/quota-manager.ts @@ -483,8 +483,9 @@ export async function reconcileExhaustedRotationAccounts( return []; } - const { pauseAccountForQuotaCooldown, restoreExpiredQuotaPauses } = - await import('../accounts/account-safety'); + const { pauseAccountForQuotaCooldown, restoreExpiredQuotaPauses } = await import( + '../accounts/account-safety' + ); restoreExpiredQuotaPauses(); const config = loadOrCreateUnifiedConfig(); @@ -592,8 +593,9 @@ export async function preflightCheck(provider: CLIProxyProvider): Promise * Fix image analysis configuration issues */ export async function fixImageAnalysisConfig(): Promise { - const { updateConfig, loadOrCreateUnifiedConfig } = - await import('../../config/config-loader-facade'); + const { updateConfig, loadOrCreateUnifiedConfig } = await import( + '../../config/config-loader-facade' + ); const config = loadOrCreateUnifiedConfig(); let fixed = false;