fix: secure assistant generation telemetry

This commit is contained in:
ajnart committed 2026-08-02 09:09:01 +02:00
1 parent 04520cf67c
commit 8bb0ddef42
11 files changed
+181 -10

No files matched your search

@@ -1,5 +1,9 @@
import { fetchWithTrustedCertificatesAsync } from "@homarr/core/infrastructure/http";
const generationTelemetryCache = new Map<string, { expiresAt: number; value: OpenRouterGenerationTelemetry }>();
const generationTelemetryCacheTtlMs = 5 * 60_000;
const generationTelemetryCacheMaxEntries = 512;
export type OpenRouterGenerationTelemetry = {
generationId?: string;
routedProvider?: string;
@@ -50,13 +54,17 @@ export const parseOpenRouterGenerationTelemetry = (value: unknown): OpenRouterGe
const generationTimeMs = asFiniteNonNegativeNumber(data.generation_time);
const providerResponses = Array.isArray(data.provider_responses) ? data.provider_responses : undefined;
const parsedProviderResponses = providerResponses?.map(asRecord).filter((response) => response !== null);
const providerResponseStatuses = parsedProviderResponses?.map((response) =>
asFiniteNonNegativeNumber(response.status),
);
const failedProviderResponses = parsedProviderResponses?.filter((response) => {
const status = asFiniteNonNegativeNumber(response.status);
return status !== undefined && (status < 200 || status >= 300);
});
const fallbackCount = providerResponses
? failedProviderResponses && failedProviderResponses.length > 0
? failedProviderResponses.length
? providerResponseStatuses?.length === providerResponses.length &&
providerResponseStatuses.every((status) => status !== undefined)
? (failedProviderResponses?.length ?? 0)
: Math.max(providerResponses.length - 1, 0)
: undefined;
const fallbackLatencies = failedProviderResponses?.map((response) => asFiniteNonNegativeNumber(response.latency));
@@ -128,12 +136,31 @@ export const fetchOpenRouterGenerationTelemetryAsync = async ({
generationId: string;
headers: Record<string, string>;
}): Promise<OpenRouterGenerationTelemetry | null> => {
const cacheKey = `${baseUrl}\0${generationId}`;
const cached = generationTelemetryCache.get(cacheKey);
if (cached && cached.expiresAt > Date.now()) {
generationTelemetryCache.delete(cacheKey);
generationTelemetryCache.set(cacheKey, cached);
return cached.value;
}
if (cached) generationTelemetryCache.delete(cacheKey);
try {
const endpoint = new URL(`${baseUrl.replace(/\/$/, "")}/generation`);
endpoint.searchParams.set("id", generationId);
const response = await fetchWithTrustedCertificatesAsync(endpoint, { headers, timeout: 3000 });
if (!response.ok) return null;
return parseOpenRouterGenerationTelemetry(await response.json());
const telemetry = parseOpenRouterGenerationTelemetry(await response.json());
if (!telemetry) return null;
if (generationTelemetryCache.size >= generationTelemetryCacheMaxEntries) {
const oldestKey = generationTelemetryCache.keys().next().value;
if (oldestKey !== undefined) generationTelemetryCache.delete(oldestKey);
}
generationTelemetryCache.set(cacheKey, {
expiresAt: Date.now() + generationTelemetryCacheTtlMs,
value: telemetry,
});
return telemetry;
} catch {
return null;
}