|
1 | 1 | <script lang="ts"> |
| 2 | + import { onMount } from "svelte"; |
2 | 3 | import App from "./App.svelte"; |
3 | 4 | import Providers from "./Providers.svelte"; |
4 | 5 |
|
|
20 | 21 | activeTab = tab; |
21 | 22 | closeMobileMenu(); |
22 | 23 | } |
| 24 | + const PROVIDERS_URL = "https://raw.githubusercontent.com/BerriAI/litellm/main/provider_endpoints_support.json"; |
| 25 | + const MODELS_URL = "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json"; |
| 26 | +
|
| 27 | + let providerCount = 0; |
| 28 | + let endpointCount = 0; |
| 29 | + let providerEndpointCount = 0; |
| 30 | + let modelCount = 0; |
| 31 | + let statsLoading = true; |
| 32 | +
|
| 33 | + onMount(async () => { |
| 34 | + try { |
| 35 | + // Fetch provider data |
| 36 | + const providersResponse = await fetch(PROVIDERS_URL); |
| 37 | + const providersData = await providersResponse.json(); |
| 38 | + |
| 39 | + if (providersData.providers) { |
| 40 | + const providers = Object.entries(providersData.providers).map(([provider, info]: [string, any]) => ({ |
| 41 | + provider, |
| 42 | + endpoints: info.endpoints || {} |
| 43 | + })); |
| 44 | + |
| 45 | + providerCount = providers.length; |
| 46 | + |
| 47 | + // Count unique endpoints |
| 48 | + const allEndpoints = new Set<string>(); |
| 49 | + providers.forEach(p => { |
| 50 | + Object.keys(p.endpoints).forEach(e => allEndpoints.add(e)); |
| 51 | + }); |
| 52 | + endpointCount = allEndpoints.size; |
| 53 | + |
| 54 | + // Count provider + endpoint combinations |
| 55 | + providerEndpointCount = providers.reduce((total, provider) => { |
| 56 | + return total + Object.values(provider.endpoints).filter(supported => supported === true).length; |
| 57 | + }, 0); |
| 58 | + } |
| 59 | +
|
| 60 | + // Fetch model data |
| 61 | + const modelsResponse = await fetch(MODELS_URL); |
| 62 | + const modelsText = await modelsResponse.text(); |
| 63 | + const modelsData = JSON.parse(modelsText); |
| 64 | + modelCount = Object.keys(modelsData).length; |
| 65 | + |
| 66 | + statsLoading = false; |
| 67 | + } catch (error) { |
| 68 | + console.error("Failed to load statistics:", error); |
| 69 | + statsLoading = false; |
| 70 | + } |
| 71 | + }); |
23 | 72 | </script> |
24 | 73 |
|
25 | 74 | <div class="app-container"> |
|
93 | 142 | {/if} |
94 | 143 | </header> |
95 | 144 |
|
| 145 | + <!-- Statistics Section --> |
| 146 | + {#if !statsLoading} |
| 147 | + <div class="stats-section"> |
| 148 | + <div class="stats-container"> |
| 149 | + <div class="stat-card"> |
| 150 | + <div class="stat-value">{modelCount}</div> |
| 151 | + <div class="stat-label">Models Supported</div> |
| 152 | + </div> |
| 153 | + <div class="stat-card"> |
| 154 | + <div class="stat-value">{providerCount}</div> |
| 155 | + <div class="stat-label">Providers</div> |
| 156 | + </div> |
| 157 | + <div class="stat-card"> |
| 158 | + <div class="stat-value">{endpointCount}</div> |
| 159 | + <div class="stat-label">Unique Endpoints</div> |
| 160 | + </div> |
| 161 | + <div class="stat-card"> |
| 162 | + <div class="stat-value">{providerEndpointCount}</div> |
| 163 | + <div class="stat-label">Provider + Endpoint Combinations</div> |
| 164 | + </div> |
| 165 | + </div> |
| 166 | + </div> |
| 167 | + {/if} |
| 168 | + |
96 | 169 | <!-- Content --> |
97 | 170 | {#if activeTab === "models"} |
98 | 171 | <App /> |
|
345 | 418 | display: block; |
346 | 419 | } |
347 | 420 | } |
| 421 | +
|
| 422 | + /* Statistics Section */ |
| 423 | + .stats-section { |
| 424 | + max-width: 1400px; |
| 425 | + margin: 1.5rem auto; |
| 426 | + padding: 0 2rem; |
| 427 | + } |
| 428 | +
|
| 429 | + .stats-container { |
| 430 | + display: grid; |
| 431 | + grid-template-columns: repeat(4, 1fr); |
| 432 | + gap: 0.75rem; |
| 433 | + } |
| 434 | +
|
| 435 | + .stat-card { |
| 436 | + background: #fcfcfc; |
| 437 | + border: 1px solid #f5f5f5; |
| 438 | + border-radius: 6px; |
| 439 | + padding: 0.875rem 0.75rem; |
| 440 | + text-align: center; |
| 441 | + transition: background-color 0.2s ease, border-color 0.2s ease; |
| 442 | + } |
| 443 | +
|
| 444 | + .stat-card:hover { |
| 445 | + background-color: #fafafa; |
| 446 | + border-color: #f0f0f0; |
| 447 | + } |
| 448 | +
|
| 449 | + .stat-value { |
| 450 | + font-size: 1.375rem; |
| 451 | + font-weight: 600; |
| 452 | + color: #1a1a1a; |
| 453 | + line-height: 1; |
| 454 | + margin-bottom: 0.25rem; |
| 455 | + } |
| 456 | +
|
| 457 | + .stat-label { |
| 458 | + font-size: 0.6875rem; |
| 459 | + font-weight: 500; |
| 460 | + color: #9ca3af; |
| 461 | + text-transform: uppercase; |
| 462 | + letter-spacing: 0.04em; |
| 463 | + } |
| 464 | +
|
| 465 | + /* Responsive Design */ |
| 466 | + @media (max-width: 1024px) { |
| 467 | + .stats-container { |
| 468 | + grid-template-columns: repeat(2, 1fr); |
| 469 | + } |
| 470 | + } |
| 471 | +
|
| 472 | + @media (max-width: 640px) { |
| 473 | + .stats-container { |
| 474 | + grid-template-columns: 1fr; |
| 475 | + gap: 0.75rem; |
| 476 | + } |
| 477 | +
|
| 478 | + .stat-card { |
| 479 | + padding: 1rem; |
| 480 | + } |
| 481 | +
|
| 482 | + .stat-value { |
| 483 | + font-size: 1.5rem; |
| 484 | + } |
| 485 | +
|
| 486 | + .stat-label { |
| 487 | + font-size: 0.6875rem; |
| 488 | + } |
| 489 | +
|
| 490 | + .tabs { |
| 491 | + width: 100%; |
| 492 | + flex-wrap: wrap; |
| 493 | + } |
| 494 | +
|
| 495 | + .tab { |
| 496 | + font-size: 0.875rem; |
| 497 | + padding: 0.5rem 0.75rem; |
| 498 | + } |
| 499 | + } |
348 | 500 | </style> |
349 | 501 |
|
0 commit comments