mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-14 10:52:17 +03:00
Validado em lote numa worktree combinada com os 10 PRs desta leva sobre o tip de `release/v3.8.51`: `typecheck:core` limpo, `check-file-size` OK e **241/242** nos 29 arquivos de teste que os PRs tocam. A única "falha" não é falha: `tests/unit/autoCombo/strict-zero-cost-filter.test.ts` é um teste em estilo Vitest que eu incluí por engano na invocação do runner nativo do Node — ele quebra no import (`@vitest/runner`), não numa asserção. Ao investigar, descobri que esse arquivo não roda em nenhum dos dois runners hoje (o glob do `test:unit` não lista `autoCombo` e o `include` do Vitest só pega `.tsx` nessa pasta); é um problema pré-existente do repositório, sem relação com esta leva, e vou registrá-lo separadamente. O #12636 conflitava apenas na lista de testes do `@omniroute/opencode-plugin/package.json`, de forma aditiva: o tip já tinha `models-fetcher.test.ts` (do #12607, irmão desta mesma leva) e o #12636 acrescenta `telemetry.test.ts`. Fiz a união dos dois lados (25 arquivos contra 24 de cada) em vez de escolher um, o que teria removido um arquivo da suíte do plugin em silêncio. Obrigado, @RaviTharuma.
45 lines
1.8 KiB
TypeScript
45 lines
1.8 KiB
TypeScript
/**
|
|
* Gateway-measured generation throughput (#12616).
|
|
*
|
|
* tok/s MUST exclude TTFT. `output_tokens / total_latency` includes queueing and
|
|
* first-token wait and is not generation speed. When TTFT is unknown (typical
|
|
* non-streaming JSON), omit the field rather than guessing.
|
|
*/
|
|
export function generationDurationMs(
|
|
totalMs: number,
|
|
ttftMs: number | null | undefined
|
|
): number | null {
|
|
if (!Number.isFinite(totalMs) || totalMs <= 0) return null;
|
|
if (ttftMs == null || !Number.isFinite(ttftMs) || ttftMs < 0) return null;
|
|
const generationMs = totalMs - ttftMs;
|
|
return generationMs > 0 ? generationMs : null;
|
|
}
|
|
|
|
export function tokensPerSecond(
|
|
outputTokens: number,
|
|
generationMs: number | null | undefined
|
|
): number | null {
|
|
if (generationMs == null || !Number.isFinite(generationMs) || generationMs <= 0) return null;
|
|
if (!Number.isFinite(outputTokens) || outputTokens <= 0) return null;
|
|
return outputTokens / (generationMs / 1000);
|
|
}
|
|
|
|
function outputTokenCount(usage: Record<string, unknown>): number {
|
|
const raw =
|
|
usage.completion_tokens ??
|
|
usage.output_tokens ??
|
|
usage.candidatesTokenCount ??
|
|
usage.outputTokens ??
|
|
usage.completionTokens;
|
|
const n = typeof raw === "number" ? raw : typeof raw === "string" ? Number(raw) : NaN;
|
|
return Number.isFinite(n) ? n : 0;
|
|
}
|
|
|
|
/** Attach `tokens_per_second` when generation duration (excluding TTFT) is known. */
|
|
export function attachTokensPerSecond<T>(usage: T, generationMs: number | null | undefined): T {
|
|
if (!usage || typeof usage !== "object" || Array.isArray(usage)) return usage;
|
|
const tps = tokensPerSecond(outputTokenCount(usage as Record<string, unknown>), generationMs);
|
|
if (tps == null) return usage;
|
|
return { ...(usage as Record<string, unknown>), tokens_per_second: Number(tps.toFixed(3)) } as T;
|
|
}
|