feat: add model plaza with group-scoped pricing showcase

- public /model-plaza page (standalone + admin-embedded) listing groups
  with discounted effective prices alongside LiteLLM official reference
- faceted platform/group/rate filters: cross-dimension options gray out
  instead of disappearing, platform-tinted chips via accent color-mix
- paid-price columns highlighted with per-platform tint band
- OptionalJWT middleware so anonymous and signed-in users share one route
- admin settings: enable switch, require-auth switch, markdown description
This commit is contained in:
feeeei
2026-07-28 16:19:41 +08:00
parent 2e432173f7
commit 720c405e35
49 changed files with 2612 additions and 11 deletions
+5
View File
@@ -104,6 +104,11 @@ export const FeatureFlags = {
mode: 'opt-in',
label: 'Available Channels',
}),
modelPlaza: defineFlag({
key: 'model_plaza_enabled',
mode: 'opt-in',
label: 'Model Plaza',
}),
payment: defineFlag({
key: 'payment_enabled',
mode: 'opt-out',
+31
View File
@@ -39,6 +39,29 @@ const BORDER: Record<Platform, string> = {
}
const BORDER_DEFAULT = 'border-gray-200 dark:border-dark-700'
// ── Border strong (higher-contrast platform tint, e.g. plaza group cards) ──
const BORDER_STRONG: Record<Platform, string> = {
anthropic: 'border-orange-500/35 dark:border-orange-500/30',
openai: 'border-green-500/35 dark:border-green-500/30',
antigravity: 'border-purple-500/35 dark:border-purple-500/30',
gemini: 'border-blue-500/35 dark:border-blue-500/30',
grok: 'border-zinc-800/35 dark:border-zinc-500/35',
composite: 'border-cyan-500/35 dark:border-cyan-500/30',
}
const BORDER_STRONG_DEFAULT = 'border-gray-300 dark:border-dark-600'
// ── Accent (single raw color per platform; consumers derive washes/tints
// from it via CSS color-mix, e.g. plaza paid-price zone) ──
const ACCENT: Record<Platform, string> = {
anthropic: '#f97316', // orange-500
openai: '#22c55e', // green-500
antigravity: '#a855f7', // purple-500
gemini: '#3b82f6', // blue-500
grok: '#71717a', // zinc-500
composite: '#06b6d4', // cyan-500
}
const ACCENT_DEFAULT = '#14b8a6' // primary-500 (teal)
// ── Accent bar (gradient) ───────────────────────────────────────────
const ACCENT_BAR: Record<Platform, string> = {
anthropic: 'bg-gradient-to-r from-orange-400 to-orange-500',
@@ -144,6 +167,14 @@ export function platformBorderClass(p: string): string {
return isPlatform(p) ? BORDER[p] : BORDER_DEFAULT
}
export function platformBorderStrongClass(p: string): string {
return isPlatform(p) ? BORDER_STRONG[p] : BORDER_STRONG_DEFAULT
}
export function platformAccentColor(p: string): string {
return isPlatform(p) ? ACCENT[p] : ACCENT_DEFAULT
}
export function platformAccentBarClass(p: string): string {
return isPlatform(p) ? ACCENT_BAR[p] : ACCENT_BAR_DEFAULT
}
+16 -5
View File
@@ -1,13 +1,24 @@
/**
* formatScaled formats a per-token (or per-request) USD price scaled by `scale`.
*
* formatScaled(0.000003, 1_000_000) → "$3" // per 1M tokens
* formatScaled(0.5, 1) → "$0.5" // per request
* formatScaled(null, 1_000_000) → "-"
* formatScaled(0.000003, 1_000_000) → "$3" // per 1M tokens
* formatScaled(0.5, 1) → "$0.5" // per request
* formatScaled(null, 1_000_000) → "-"
* formatScaled(0.000003, 1_000_000, 2) → "$3.00" // pad to ≥2 decimals
* formatScaled(1.25e-8, 1_000_000, 2) → "$0.0125" // longer decimals kept as-is
*
* Uses toPrecision(10) then strips trailing zeros to avoid IEEE 754 display noise.
* `minFractionDigits` pads the result back up to a minimum number of decimals.
*/
export function formatScaled(value: number | null, scale: number): string {
export function formatScaled(value: number | null, scale: number, minFractionDigits = 0): string {
if (value == null) return '-'
return `$${(value * scale).toPrecision(10).replace(/\.?0+$/, '')}`
let s = (value * scale).toPrecision(10).replace(/\.?0+$/, '')
if (minFractionDigits > 0 && !s.includes('e')) {
const dot = s.indexOf('.')
const digits = dot === -1 ? 0 : s.length - dot - 1
if (digits < minFractionDigits) {
s = (dot === -1 ? `${s}.` : s) + '0'.repeat(minFractionDigits - digits)
}
}
return `$${s}`
}