From 25c198d5ea1bcfe7804e2a39f9a527be53383527 Mon Sep 17 00:00:00 2001 From: chrarnoldus <12196001+chrarnoldus@users.noreply.github.com> Date: Wed, 17 Jun 2026 08:32:49 +0000 Subject: [PATCH] fix(ai-gateway): defer model retirement labels Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com> --- .../providers/openrouter/index.test.ts | 21 +++++++++++++++---- .../ai-gateway/providers/openrouter/index.ts | 16 ++++++++------ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/apps/web/src/lib/ai-gateway/providers/openrouter/index.test.ts b/apps/web/src/lib/ai-gateway/providers/openrouter/index.test.ts index 23e790e8f..7cf97fa7a 100644 --- a/apps/web/src/lib/ai-gateway/providers/openrouter/index.test.ts +++ b/apps/web/src/lib/ai-gateway/providers/openrouter/index.test.ts @@ -59,6 +59,14 @@ function buildModel(overrides: Partial = {}): OpenRouterModel { describe('formatName', () => { const NOT_PREFERRED = -1; + beforeEach(() => { + jest.useFakeTimers().setSystemTime(new Date('2026-06-17T00:00:00Z')); + }); + + afterEach(() => { + jest.useRealTimers(); + }); + it('appends ($$$$) for expensive models', () => { const model = buildModel({ pricing: { prompt: '0.00001', completion: '0' } }); expect(formatName(model, NOT_PREFERRED)).toBe('Test Model ($$$$)'); @@ -98,14 +106,19 @@ describe('formatName', () => { expect(formatName(model, 0)).toBe('Test Model'); }); - it('appends the retirement date in UTC when an expiration date is set', () => { - const model = buildModel({ expiration_date: '2026-12-01' }); - expect(formatName(model, NOT_PREFERRED)).toBe('Test Model (retires Dec 1)'); + it('appends the retirement date in UTC when it is within one month', () => { + const model = buildModel({ expiration_date: '2026-07-01' }); + expect(formatName(model, NOT_PREFERRED)).toBe('Test Model (retires Jul 1)'); + }); + + it('does not append the retirement date when it is more than one month away', () => { + const model = buildModel({ expiration_date: '2026-07-18' }); + expect(formatName(model, NOT_PREFERRED)).toBe('Test Model'); }); it('prefers the (new) marker over the retirement marker', () => { const recentlyCreated = Math.floor(Date.now() / 1000) - 24 * 3600; - const model = buildModel({ created: recentlyCreated, expiration_date: '2026-12-01' }); + const model = buildModel({ created: recentlyCreated, expiration_date: '2026-07-01' }); expect(formatName(model, 0)).toBe('Test Model (new)'); }); diff --git a/apps/web/src/lib/ai-gateway/providers/openrouter/index.ts b/apps/web/src/lib/ai-gateway/providers/openrouter/index.ts index fce62b548..05058fd31 100644 --- a/apps/web/src/lib/ai-gateway/providers/openrouter/index.ts +++ b/apps/web/src/lib/ai-gateway/providers/openrouter/index.ts @@ -28,6 +28,7 @@ import { getTerminalBenchSummaries, terminalBenchFor } from '@/lib/model-stats/t import { isFreeNemotronModel, NVIDIA_TRIAL_TOS } from '@/lib/ai-gateway/providers/nvidia'; import { applyCustomPricingToModel } from '@/lib/ai-gateway/custom-pricing'; import { isFableModel } from '@/lib/ai-gateway/providers/anthropic.constants'; +import { addMonths } from 'date-fns'; // Re-export from shared module for backwards compatibility export { normalizeModelId } from '@/lib/ai-gateway/model-utils'; @@ -88,12 +89,15 @@ export function formatName(model: OpenRouterModel, preferredIndex: number) { const isNew = preferredIndex >= 0 && ageDays >= 0 && ageDays < 7; if (isNew) return model.name + ' (new)'; if (model.expiration_date) { - const suffix = new Date(model.expiration_date).toLocaleDateString('en-US', { - month: 'short', - day: 'numeric', - timeZone: 'UTC', - }); - return model.name + ' (retires ' + suffix + ')'; + const expirationDate = new Date(model.expiration_date); + if (expirationDate <= addMonths(new Date(), 1)) { + const suffix = expirationDate.toLocaleDateString('en-US', { + month: 'short', + day: 'numeric', + timeZone: 'UTC', + }); + return model.name + ' (retires ' + suffix + ')'; + } } return model.name; }