fix(ci): resolve backend type/lint and ui format issues

This commit is contained in:
Evan Yang
2026-03-13 15:55:29 +08:00
parent a63e81db06
commit 11eb20a2d1
3 changed files with 48 additions and 30 deletions
+8 -8
View File
@@ -673,7 +673,7 @@ class UsageAnalyticsStore:
)
if model_updates:
rows = [
model_rows = [
(
minute_ts,
model,
@@ -713,11 +713,11 @@ class UsageAnalyticsStore:
output_tokens = output_tokens + excluded.output_tokens,
total_tokens = total_tokens + excluded.total_tokens
""",
rows,
model_rows,
)
if model_presence_updates:
rows = [
presence_rows = [
(minute_ts, model, count)
for (minute_ts, model), count in model_presence_updates.items()
]
@@ -732,11 +732,11 @@ class UsageAnalyticsStore:
ON CONFLICT(minute_ts, model) DO UPDATE SET
count = count + excluded.count
""",
rows,
presence_rows,
)
if error_type_updates:
rows = [
error_type_rows = [
(minute_ts, error_type, count)
for (minute_ts, error_type), count in error_type_updates.items()
]
@@ -751,7 +751,7 @@ class UsageAnalyticsStore:
ON CONFLICT(minute_ts, error_type) DO UPDATE SET
count = count + excluded.count
""",
rows,
error_type_rows,
)
if error_events:
@@ -1215,9 +1215,9 @@ class UsageAnalyticsStore:
for row in top_model_rows:
bucket_ts = str(row["bucket_ts"])
bucket = bucket_index.get(bucket_ts)
if bucket is None:
if bucket_ts not in bucket_index:
continue
bucket = bucket_index[bucket_ts]
model = str(row["model"])
successful = int(row["successful"])
+14 -4
View File
@@ -12,7 +12,7 @@ import json
import math
import time
from datetime import datetime, timezone
from typing import Any
from typing import Any, TypedDict
from nostr.event import Event
from nostr.key import PrivateKey
@@ -46,6 +46,13 @@ WINDOW_DEFINITIONS: tuple[tuple[str, int, int], ...] = (
)
class PayloadSpec(TypedDict):
period_type: str
period_key: str
d_tag: str
payload: dict[str, Any]
def _event_to_dict(ev: Event) -> dict[str, Any]:
return {
"id": ev.id,
@@ -197,7 +204,10 @@ def _aggregate_top_model_usage(
}
for model, values in model_totals.items()
]
model_rows.sort(key=lambda row: row["successful_requests"], reverse=True)
model_rows.sort(
key=lambda row: _to_int(row.get("successful_requests", 0)),
reverse=True,
)
return model_rows, others
@@ -600,7 +610,7 @@ async def publish_usage_analytics() -> None:
generated_at=now_ts,
)
payload_specs = [
payload_specs: list[PayloadSpec] = [
{
"period_type": "latest",
"period_key": "latest",
@@ -624,7 +634,7 @@ async def publish_usage_analytics() -> None:
to_publish: list[dict[str, Any]] = []
refs: dict[str, dict[str, str]] = {}
for spec in payload_specs:
payload = spec["payload"]
payload: dict[str, Any] = spec["payload"]
payload_hash = _fingerprint_payload(payload)
d_tag = str(spec["d_tag"])
period_type = str(spec["period_type"])
+26 -18
View File
@@ -198,7 +198,11 @@ function detectProviderFromModel(model: string): string {
if (value.includes('claude')) return 'anthropic';
if (value.includes('gpt') || value.includes('openai')) return 'openai';
if (value.includes('gemini')) return 'google';
if (value.includes('grok') || value.includes('x-ai') || value.includes('xai')) {
if (
value.includes('grok') ||
value.includes('x-ai') ||
value.includes('xai')
) {
return 'x-ai';
}
if (value.includes('deepseek')) return 'deepseek';
@@ -206,15 +210,20 @@ function detectProviderFromModel(model: string): string {
if (value.includes('kimi') || value.includes('moonshot')) return 'moonshot';
if (value.includes('mistral')) return 'mistral';
if (value.includes('qwen') || value.includes('alibaba')) return 'alibaba';
if (value.includes('glm') || value.includes('z-ai') || value.includes('z ai')) {
if (
value.includes('glm') ||
value.includes('z-ai') ||
value.includes('z ai')
) {
return 'z-ai';
}
return 'unknown';
}
function getModelPresentation(
model: string
): { displayName: string; provider: string } {
function getModelPresentation(model: string): {
displayName: string;
provider: string;
} {
const trimmed = model.trim();
const slashIndex = trimmed.indexOf('/');
if (slashIndex > 0 && slashIndex < trimmed.length - 1) {
@@ -257,10 +266,7 @@ export function TopModelsUsageChart({
[mix.metrics]
);
const chartModels = useMemo(
() => mixTopModels.slice(0, 20),
[mixTopModels]
);
const chartModels = useMemo(() => mixTopModels.slice(0, 20), [mixTopModels]);
const leaderboardModels = useMemo(
() => mixTopModels.slice(0, 20),
[mixTopModels]
@@ -472,9 +478,7 @@ export function TopModelsUsageChart({
const windowSize = Math.floor(mixMetrics.length / 2);
const previousMetrics =
windowSize > 0
? mixMetrics.slice(-windowSize * 2, -windowSize)
: [];
windowSize > 0 ? mixMetrics.slice(-windowSize * 2, -windowSize) : [];
const currentMetrics =
windowSize > 0 ? mixMetrics.slice(-windowSize) : mixMetrics;
@@ -482,10 +486,10 @@ export function TopModelsUsageChart({
.map((model) => {
const readMetric = (metric: (typeof mixMetrics)[number]): number =>
mode === 'requests'
? (metric.model_counts ?? {})[model] ?? 0
? ((metric.model_counts ?? {})[model] ?? 0)
: mode === 'revenue'
? (metric.model_revenue_msats ?? {})[model] ?? 0
: (metric.model_tokens ?? {})[model] ?? 0;
? ((metric.model_revenue_msats ?? {})[model] ?? 0)
: ((metric.model_tokens ?? {})[model] ?? 0);
const totalRaw = mixMetrics.reduce(
(sum, metric) => sum + readMetric(metric),
@@ -557,7 +561,9 @@ export function TopModelsUsageChart({
<CardHeader className='space-y-3 sm:space-y-4'>
<div className='flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between'>
<div className='min-w-0'>
<CardTitle className='text-base sm:text-lg'>Model Usage</CardTitle>
<CardTitle className='text-base sm:text-lg'>
Model Usage
</CardTitle>
<p className='text-muted-foreground mt-1 text-xs sm:text-sm'>
Stacked requests, revenue, or tokens by model (
{mix.interval_minutes}m buckets).
@@ -689,7 +695,9 @@ export function TopModelsUsageChart({
value,
} satisfies TooltipRow;
})
.filter((row) => Number.isFinite(row.value) && row.value > 0)
.filter(
(row) => Number.isFinite(row.value) && row.value > 0
)
.sort((a, b) => b.value - a.value);
const total = rows.reduce((sum, row) => sum + row.value, 0);
@@ -814,7 +822,7 @@ export function TopModelsUsageChart({
className={cn(
'grid grid-cols-[auto_minmax(0,1fr)_auto_auto] items-center gap-3 rounded-md px-2 py-2 text-xs',
rowIsLinked &&
'cursor-pointer transition hover:bg-muted/25',
'hover:bg-muted/25 cursor-pointer transition',
rowIsActive && 'bg-muted/30',
rowIsDimmed && 'opacity-45'
)}