Skip to content

Commit 4f63d89

Browse files
committed
docs add counter
1 parent 544bee8 commit 4f63d89

File tree

2 files changed

+158
-86
lines changed

2 files changed

+158
-86
lines changed

src/Main.svelte

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,60 @@
11
<script lang="ts">
2+
import { onMount } from "svelte";
23
import App from "./App.svelte";
34
import Providers from "./Providers.svelte";
45
56
let activeTab: "models" | "providers" = "models";
67
78
const GITHUB_URL = "https://github.com/BerriAI/litellm";
89
const DOCS_URL = "https://docs.litellm.ai";
10+
const PROVIDERS_URL = "https://raw.githubusercontent.com/BerriAI/litellm/main/provider_endpoints_support.json";
11+
const MODELS_URL = "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json";
12+
13+
let providerCount = 0;
14+
let endpointCount = 0;
15+
let providerEndpointCount = 0;
16+
let modelCount = 0;
17+
let statsLoading = true;
18+
19+
onMount(async () => {
20+
try {
21+
// Fetch provider data
22+
const providersResponse = await fetch(PROVIDERS_URL);
23+
const providersData = await providersResponse.json();
24+
25+
if (providersData.providers) {
26+
const providers = Object.entries(providersData.providers).map(([provider, info]: [string, any]) => ({
27+
provider,
28+
endpoints: info.endpoints || {}
29+
}));
30+
31+
providerCount = providers.length;
32+
33+
// Count unique endpoints
34+
const allEndpoints = new Set<string>();
35+
providers.forEach(p => {
36+
Object.keys(p.endpoints).forEach(e => allEndpoints.add(e));
37+
});
38+
endpointCount = allEndpoints.size;
39+
40+
// Count provider + endpoint combinations
41+
providerEndpointCount = providers.reduce((total, provider) => {
42+
return total + Object.values(provider.endpoints).filter(supported => supported === true).length;
43+
}, 0);
44+
}
45+
46+
// Fetch model data
47+
const modelsResponse = await fetch(MODELS_URL);
48+
const modelsText = await modelsResponse.text();
49+
const modelsData = JSON.parse(modelsText);
50+
modelCount = Object.keys(modelsData).length;
51+
52+
statsLoading = false;
53+
} catch (error) {
54+
console.error("Failed to load statistics:", error);
55+
statsLoading = false;
56+
}
57+
});
958
</script>
1059

1160
<div class="app-container">
@@ -41,6 +90,30 @@
4190
</div>
4291
</header>
4392

93+
<!-- Statistics Section -->
94+
{#if !statsLoading}
95+
<div class="stats-section">
96+
<div class="stats-container">
97+
<div class="stat-card">
98+
<div class="stat-value">{modelCount}</div>
99+
<div class="stat-label">Models Supported</div>
100+
</div>
101+
<div class="stat-card">
102+
<div class="stat-value">{providerCount}</div>
103+
<div class="stat-label">Providers</div>
104+
</div>
105+
<div class="stat-card">
106+
<div class="stat-value">{endpointCount}</div>
107+
<div class="stat-label">Unique Endpoints</div>
108+
</div>
109+
<div class="stat-card">
110+
<div class="stat-value">{providerEndpointCount}</div>
111+
<div class="stat-label">Provider + Endpoint Combinations</div>
112+
</div>
113+
</div>
114+
</div>
115+
{/if}
116+
44117
<!-- Content -->
45118
{#if activeTab === "models"}
46119
<App />
@@ -162,5 +235,90 @@
162235
.nav-link:hover {
163236
color: var(--litellm-primary);
164237
}
238+
239+
/* Statistics Section */
240+
.stats-section {
241+
max-width: 1400px;
242+
margin: 1.5rem auto;
243+
padding: 0 2rem;
244+
}
245+
246+
.stats-container {
247+
display: grid;
248+
grid-template-columns: repeat(4, 1fr);
249+
gap: 0.75rem;
250+
}
251+
252+
.stat-card {
253+
background: #fcfcfc;
254+
border: 1px solid #f5f5f5;
255+
border-radius: 6px;
256+
padding: 0.875rem 0.75rem;
257+
text-align: center;
258+
transition: background-color 0.2s ease, border-color 0.2s ease;
259+
}
260+
261+
.stat-card:hover {
262+
background-color: #fafafa;
263+
border-color: #f0f0f0;
264+
}
265+
266+
.stat-value {
267+
font-size: 1.375rem;
268+
font-weight: 600;
269+
color: #1a1a1a;
270+
line-height: 1;
271+
margin-bottom: 0.25rem;
272+
}
273+
274+
.stat-label {
275+
font-size: 0.6875rem;
276+
font-weight: 500;
277+
color: #9ca3af;
278+
text-transform: uppercase;
279+
letter-spacing: 0.04em;
280+
}
281+
282+
/* Responsive Design */
283+
@media (max-width: 1024px) {
284+
.stats-container {
285+
grid-template-columns: repeat(2, 1fr);
286+
}
287+
}
288+
289+
@media (max-width: 640px) {
290+
.stats-container {
291+
grid-template-columns: 1fr;
292+
gap: 0.75rem;
293+
}
294+
295+
.stat-card {
296+
padding: 1rem;
297+
}
298+
299+
.stat-value {
300+
font-size: 1.5rem;
301+
}
302+
303+
.stat-label {
304+
font-size: 0.6875rem;
305+
}
306+
307+
.left-section {
308+
flex-direction: column;
309+
align-items: flex-start;
310+
gap: 1rem;
311+
}
312+
313+
.tabs {
314+
width: 100%;
315+
flex-wrap: wrap;
316+
}
317+
318+
.tab {
319+
font-size: 0.875rem;
320+
padding: 0.5rem 0.75rem;
321+
}
322+
}
165323
</style>
166324

src/Providers.svelte

Lines changed: 0 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,6 @@
130130
];
131131
}
132132
133-
// Calculate statistics
134-
$: providerCount = providers.length;
135-
$: endpointCount = endpointColumns.length;
136-
$: providerEndpointCount = providers.reduce((total, provider) => {
137-
return total + Object.values(provider.endpoints).filter(supported => supported === true).length;
138-
}, 0);
139133
</script>
140134

141135
<main>
@@ -146,26 +140,6 @@
146140
</div>
147141
</div>
148142

149-
<!-- Statistics Cards -->
150-
{#if !loading}
151-
<div class="stats-section">
152-
<div class="stats-container">
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-
169143
<!-- Search and Filters -->
170144
<div class="search-section">
171145
<div class="filters-row">
@@ -425,49 +399,6 @@
425399
line-height: 1.6;
426400
}
427401
428-
/* Statistics Section */
429-
.stats-section {
430-
max-width: 1400px;
431-
margin: 0 auto 3rem;
432-
padding: 0 2rem;
433-
}
434-
435-
.stats-container {
436-
display: grid;
437-
grid-template-columns: repeat(3, 1fr);
438-
gap: 1.5rem;
439-
}
440-
441-
.stat-card {
442-
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
443-
border-radius: 12px;
444-
padding: 2rem;
445-
text-align: center;
446-
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);
447-
transition: transform 0.2s ease, box-shadow 0.2s ease;
448-
}
449-
450-
.stat-card:hover {
451-
transform: translateY(-2px);
452-
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(0, 0, 0, 0.1);
453-
}
454-
455-
.stat-value {
456-
font-size: 3rem;
457-
font-weight: 700;
458-
color: #ffffff;
459-
line-height: 1;
460-
margin-bottom: 0.5rem;
461-
}
462-
463-
.stat-label {
464-
font-size: 1rem;
465-
font-weight: 500;
466-
color: rgba(255, 255, 255, 0.9);
467-
text-transform: uppercase;
468-
letter-spacing: 0.05em;
469-
}
470-
471402
/* Search Section */
472403
.search-section {
473404
max-width: 1400px;
@@ -882,23 +813,6 @@
882813
font-size: 1rem;
883814
}
884815
885-
.stats-container {
886-
grid-template-columns: 1fr;
887-
gap: 1rem;
888-
}
889-
890-
.stat-card {
891-
padding: 1.5rem;
892-
}
893-
894-
.stat-value {
895-
font-size: 2.5rem;
896-
}
897-
898-
.stat-label {
899-
font-size: 0.875rem;
900-
}
901-
902816
.view-section {
903817
flex-direction: column;
904818
align-items: stretch;

0 commit comments

Comments
 (0)