Files
OmniRoute/tests/unit/generation-throughput.test.ts
Ravi Tharuma 3d2bcc9f12 feat(api): emit gateway-measured tokens-per-second excluding TTFT (#12631)
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.
2026-09-03 23:38:37 -03:00

85 lines
3.4 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import {
attachTokensPerSecond,
generationDurationMs,
tokensPerSecond,
} from "../../open-sse/utils/generationThroughput.ts";
import { filterUsageForFormat } from "../../open-sse/utils/usageTracking.ts";
import { FORMATS } from "../../open-sse/translator/formats.ts";
import { createStreamTiming } from "../../open-sse/utils/streamTiming.ts";
import {
buildOmniRouteResponseMetaHeaders,
buildOmniRouteSseMetadataComment,
} from "../../src/domain/omnirouteResponseMeta.ts";
import { OMNIROUTE_RESPONSE_HEADERS } from "../../src/shared/constants/headers.ts";
test("#12616 tok/s excludes TTFT (200 tokens over 2s generation after 3s TTFT)", () => {
const generationMs = generationDurationMs(5000, 3000);
assert.equal(generationMs, 2000);
assert.equal(tokensPerSecond(200, generationMs), 100);
});
test("#12616 tok/s is omitted when TTFT is unknown (do not use tokens/total_latency)", () => {
assert.equal(generationDurationMs(5000, null), null);
assert.equal(tokensPerSecond(200, null), null);
const usage = attachTokensPerSecond({ prompt_tokens: 10, completion_tokens: 200 }, null);
assert.equal((usage as { tokens_per_second?: number }).tokens_per_second, undefined);
});
test("#12616 tok/s is omitted when generation duration is not positive", () => {
assert.equal(generationDurationMs(3000, 3000), null);
assert.equal(generationDurationMs(2000, 3000), null);
assert.equal(tokensPerSecond(0, 2000), null);
});
test("#12616 filterUsageForFormat keeps tokens_per_second for OpenAI and Claude", () => {
const usage = { prompt_tokens: 10, completion_tokens: 20, tokens_per_second: 42.5 };
const openai = filterUsageForFormat(usage, FORMATS.OPENAI) as Record<string, unknown>;
const claude = filterUsageForFormat(
{ input_tokens: 10, output_tokens: 20, tokens_per_second: 42.5 },
FORMATS.CLAUDE
) as Record<string, unknown>;
assert.equal(openai.tokens_per_second, 42.5);
assert.equal(claude.tokens_per_second, 42.5);
});
test("#12616 headers omit tok/s without ttftMs and emit it when TTFT is known", () => {
const without = buildOmniRouteResponseMetaHeaders({
provider: "openai",
model: "gpt-4o-mini",
latencyMs: 5000,
usage: { prompt_tokens: 11, completion_tokens: 200 },
});
assert.equal(without[OMNIROUTE_RESPONSE_HEADERS.tokensPerSecond], undefined);
const withTtft = buildOmniRouteResponseMetaHeaders({
provider: "openai",
model: "gpt-4o-mini",
latencyMs: 5000,
ttftMs: 3000,
usage: { prompt_tokens: 11, completion_tokens: 200 },
});
assert.equal(withTtft[OMNIROUTE_RESPONSE_HEADERS.tokensPerSecond], "100.000");
});
test("#12616 SSE comment carries tok/s from usage.tokens_per_second when TTFT is unknown", () => {
const comment = buildOmniRouteSseMetadataComment({
provider: "openai",
model: "gpt-4o-mini",
latencyMs: 50,
usage: { prompt_tokens: 4, completion_tokens: 2, tokens_per_second: 12.5 },
});
assert.match(comment, /^: x-omniroute-tokens-per-second=12.500/m);
});
test("#12616 StreamTiming.withTps attaches tok/s after first forward", async () => {
const t = createStreamTiming();
t.markForward();
await new Promise((r) => setTimeout(r, 25));
const usage = t.withTps({ prompt_tokens: 1, completion_tokens: 100 });
const tps = (usage as { tokens_per_second?: number }).tokens_per_second;
assert.equal(typeof tps, "number");
assert.ok(tps! > 0);
});