120 lines
3.3 KiB
TypeScript
120 lines
3.3 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
|
|
// Node's type-stripping test runner requires the explicit TypeScript suffix.
|
|
// @ts-expect-error The application compiler intentionally uses extensionless imports.
|
|
import {
|
|
GENERATION_IDLE_MS,
|
|
ROLLING_WINDOW_MS,
|
|
charsToTokensPerSec,
|
|
messageHasToolCalls,
|
|
rollingTokensPerSec,
|
|
shouldFreezeGeneration,
|
|
usageTokensPerSec,
|
|
} from "./speed-metrics.ts";
|
|
|
|
test("rolling window reports the recent rate while characters grow", () => {
|
|
const samples = [
|
|
{ at: 0, chars: 0 },
|
|
{ at: 500, chars: 100 },
|
|
{ at: 1000, chars: 200 },
|
|
];
|
|
const rate = rollingTokensPerSec(samples, 200, 1000, 1000);
|
|
// 200 chars / 1000ms / 2 chars-per-token = 100 tok/s
|
|
assert.equal(rate, 100);
|
|
});
|
|
|
|
test("rolling window drops to 0 when every sample is older than the window", () => {
|
|
const samples = [
|
|
{ at: 0, chars: 0 },
|
|
{ at: 200, chars: 80 },
|
|
{ at: 400, chars: 160 },
|
|
];
|
|
const now = 400 + ROLLING_WINDOW_MS + 50;
|
|
assert.equal(rollingTokensPerSec(samples, 160, now), 0);
|
|
});
|
|
|
|
test("rolling window decays toward 0 after a mid-stream pause", () => {
|
|
const samples = [
|
|
{ at: 0, chars: 0 },
|
|
{ at: 400, chars: 80 },
|
|
];
|
|
const live = rollingTokensPerSec(samples, 80, 500, 1000);
|
|
const paused = rollingTokensPerSec(samples, 80, 900, 1000);
|
|
assert.ok(live > paused);
|
|
assert.ok(paused > 0);
|
|
assert.equal(rollingTokensPerSec(samples, 80, 400 + 1000 + 1, 1000), 0);
|
|
});
|
|
|
|
test("usageTokensPerSec is output tokens over the segment duration", () => {
|
|
assert.equal(usageTokensPerSec(278, 6200), (278 / 6200) * 1000);
|
|
assert.equal(usageTokensPerSec(0, 1000), 0);
|
|
assert.equal(usageTokensPerSec(10, 0), 0);
|
|
});
|
|
|
|
test("charsToTokensPerSec uses the 2-chars-per-token heuristic", () => {
|
|
assert.equal(charsToTokensPerSec(100, 1000), 50);
|
|
});
|
|
|
|
test("shouldFreezeGeneration ends the segment on the next call, tools, idle usage, or run stop", () => {
|
|
const base = {
|
|
endedAt: null,
|
|
isLoading: true,
|
|
isLatestGenerating: true,
|
|
hasToolCalls: false,
|
|
grewThisTick: false,
|
|
lastGrewAt: 1000,
|
|
now: 1100,
|
|
outputTokens: 0,
|
|
};
|
|
|
|
assert.equal(shouldFreezeGeneration(base), false);
|
|
assert.equal(
|
|
shouldFreezeGeneration({ ...base, isLatestGenerating: false }),
|
|
true,
|
|
);
|
|
assert.equal(shouldFreezeGeneration({ ...base, hasToolCalls: true }), true);
|
|
assert.equal(
|
|
shouldFreezeGeneration({
|
|
...base,
|
|
hasToolCalls: true,
|
|
grewThisTick: true,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldFreezeGeneration({
|
|
...base,
|
|
outputTokens: 40,
|
|
now: 1000 + GENERATION_IDLE_MS,
|
|
}),
|
|
true,
|
|
);
|
|
assert.equal(
|
|
shouldFreezeGeneration({
|
|
...base,
|
|
outputTokens: 40,
|
|
now: 1000 + GENERATION_IDLE_MS - 1,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(shouldFreezeGeneration({ ...base, isLoading: false }), true);
|
|
assert.equal(shouldFreezeGeneration({ ...base, endedAt: 1000 }), false);
|
|
});
|
|
|
|
test("messageHasToolCalls reads both top-level and additional_kwargs", () => {
|
|
assert.equal(messageHasToolCalls({}), false);
|
|
assert.equal(
|
|
messageHasToolCalls({
|
|
tool_calls: [{ id: "1", name: "search" }],
|
|
}),
|
|
true,
|
|
);
|
|
assert.equal(
|
|
messageHasToolCalls({
|
|
additional_kwargs: { tool_calls: [{ id: "1" }] },
|
|
}),
|
|
true,
|
|
);
|
|
});
|