1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
import { describe, expect, it } from "vitest";
import { computeContextUsage } from "../src/lib/context-window.js";
import type { CacheStats } from "../src/lib/types.js";
function stats(last: CacheStats["last"]): CacheStats {
return {
inputTokens: 0,
outputTokens: 0,
cacheReadTokens: 0,
cacheWriteTokens: 0,
requests: last ? 1 : 0,
last,
};
}
describe("computeContextUsage", () => {
it("derives current context from the LAST request's input + output", () => {
const usage = computeContextUsage(
stats({
inputTokens: 47000,
outputTokens: 1200,
cacheReadTokens: 40000,
cacheWriteTokens: 0,
}),
200000,
);
// 47000 + 1200 — NOT the cumulative totals, and cache tokens are already
// inside inputTokens (not re-added).
expect(usage.current).toBe(48200);
expect(usage.max).toBe(200000);
expect(usage.percent).toBeCloseTo(24.1, 5); // 48200 / 200000 * 100, unrounded
});
it("returns max=null and percent=null when the limit is unknown", () => {
const usage = computeContextUsage(
stats({ inputTokens: 100, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 }),
null,
);
expect(usage.current).toBe(100);
expect(usage.max).toBeNull();
expect(usage.percent).toBeNull();
});
it("treats a non-positive limit as unknown", () => {
const usage = computeContextUsage(
stats({ inputTokens: 100, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 }),
0,
);
expect(usage.max).toBeNull();
expect(usage.percent).toBeNull();
});
it("reports zero usage when no request has completed yet", () => {
expect(computeContextUsage(null, 200000)).toEqual({
current: 0,
max: 200000,
percent: 0,
});
expect(computeContextUsage(stats(null), 200000)).toEqual({
current: 0,
max: 200000,
percent: 0,
});
});
it("clamps percent to 100 when context overflows the window", () => {
const usage = computeContextUsage(
stats({ inputTokens: 250000, outputTokens: 5000, cacheReadTokens: 0, cacheWriteTokens: 0 }),
200000,
);
expect(usage.current).toBe(255000);
expect(usage.percent).toBe(100);
});
it("keeps an unrounded percent so the UI can show 2 decimals", () => {
const usage = computeContextUsage(
stats({ inputTokens: 3690, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 }),
1000000,
);
// 3690 / 1,000,000 * 100 = 0.369 → displayed as "0.37%" (toFixed(2)).
expect(usage.percent).toBeCloseTo(0.369, 6);
expect((usage.percent as number).toFixed(2)).toBe("0.37");
});
});
|