@monotykamary/pi-vcc 0.3.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +688 -0
  2. package/__tests__/helpers.ts +135 -0
  3. package/__tests__/root-causes.test.ts +858 -0
  4. package/demo.gif +0 -0
  5. package/index.ts +21 -0
  6. package/knip.json +4 -0
  7. package/npm-shrinkwrap.json +3001 -0
  8. package/package.json +36 -0
  9. package/scripts/audit-sessions.ts +88 -0
  10. package/scripts/benchmark-real-sessions.ts +25 -0
  11. package/scripts/compare-before-after.ts +36 -0
  12. package/scripts/dump-branch-output.ts +20 -0
  13. package/src/commands/pi-vcc.ts +36 -0
  14. package/src/commands/vcc-recall.ts +65 -0
  15. package/src/core/brief.ts +497 -0
  16. package/src/core/build-sections.ts +431 -0
  17. package/src/core/content.ts +71 -0
  18. package/src/core/filter-noise.ts +42 -0
  19. package/src/core/format-recall.ts +177 -0
  20. package/src/core/format.ts +98 -0
  21. package/src/core/invisible-continue.ts +172 -0
  22. package/src/core/lineage.ts +26 -0
  23. package/src/core/load-messages.ts +40 -0
  24. package/src/core/normalize.ts +73 -0
  25. package/src/core/recall-scope.ts +49 -0
  26. package/src/core/render-entries.ts +58 -0
  27. package/src/core/report.ts +237 -0
  28. package/src/core/sanitize.ts +5 -0
  29. package/src/core/search-entries.ts +375 -0
  30. package/src/core/settings.ts +190 -0
  31. package/src/core/skill-collapse.ts +35 -0
  32. package/src/core/summarize.ts +179 -0
  33. package/src/core/tool-args.ts +14 -0
  34. package/src/details.ts +19 -0
  35. package/src/extract/commits.ts +69 -0
  36. package/src/extract/goals.ts +79 -0
  37. package/src/extract/preferences.ts +55 -0
  38. package/src/extract/shared-symbols.ts +357 -0
  39. package/src/hooks/before-compact.ts +564 -0
  40. package/src/hooks/proactive-threshold.ts +131 -0
  41. package/src/sections.ts +23 -0
  42. package/src/tools/recall.ts +204 -0
  43. package/src/types.ts +20 -0
  44. package/tests/australian-government.test.ts +479 -0
  45. package/tests/before-compact-hook.test.ts +185 -0
  46. package/tests/before-compact.test.ts +227 -0
  47. package/tests/brief.test.ts +215 -0
  48. package/tests/build-sections.test.ts +59 -0
  49. package/tests/compile.test.ts +89 -0
  50. package/tests/content.test.ts +66 -0
  51. package/tests/deep-extraction.test.ts +313 -0
  52. package/tests/extract-goals.test.ts +86 -0
  53. package/tests/extract-preferences.test.ts +30 -0
  54. package/tests/filter-noise.test.ts +61 -0
  55. package/tests/fixtures.ts +61 -0
  56. package/tests/format-recall.test.ts +87 -0
  57. package/tests/format.test.ts +73 -0
  58. package/tests/government-domain.test.ts +542 -0
  59. package/tests/lineage.test.ts +33 -0
  60. package/tests/load-messages.test.ts +49 -0
  61. package/tests/model-threshold-hook.test.ts +377 -0
  62. package/tests/model-threshold.test.ts +223 -0
  63. package/tests/normalize.test.ts +104 -0
  64. package/tests/proactive-threshold.test.ts +490 -0
  65. package/tests/real-sessions.test.ts +38 -0
  66. package/tests/recall-expand.test.ts +15 -0
  67. package/tests/recall-scope.test.ts +32 -0
  68. package/tests/recall-tool-scope.test.ts +67 -0
  69. package/tests/render-entries.test.ts +92 -0
  70. package/tests/report.test.ts +58 -0
  71. package/tests/sanitize.test.ts +24 -0
  72. package/tests/search-entries.test.ts +233 -0
  73. package/tests/support/load-session.ts +23 -0
  74. package/tests/support/real-sessions.ts +51 -0
  75. package/tests/threshold-integration.test.ts +359 -0
  76. package/tsconfig.json +20 -0
@@ -0,0 +1,49 @@
1
+ import { describe, it, expect } from "bun:test";
2
+ import { mkdtempSync, writeFileSync, rmSync } from "fs";
3
+ import { tmpdir } from "os";
4
+ import { join } from "path";
5
+ import { loadAllMessages } from "../src/core/load-messages";
6
+
7
+ describe("loadAllMessages", () => {
8
+ it("loads all message entries when no lineage filter is provided", () => {
9
+ const dir = mkdtempSync(join(tmpdir(), "pi-vcc-load-all-"));
10
+ const file = join(dir, "session.jsonl");
11
+ try {
12
+ const lines = [
13
+ JSON.stringify({ type: "session", id: "s1" }),
14
+ JSON.stringify({ type: "message", id: "m1", message: { role: "user", content: "u1" } }),
15
+ JSON.stringify({ type: "custom", id: "c1", customType: "x", data: {} }),
16
+ JSON.stringify({ type: "message", id: "m2", message: { role: "assistant", content: [{ type: "text", text: "a1" }] } }),
17
+ JSON.stringify({ type: "message", id: "m3", message: { role: "toolResult", toolName: "read", content: [{ type: "text", text: "ok" }] } }),
18
+ ];
19
+ writeFileSync(file, lines.join("\n") + "\n", "utf8");
20
+
21
+ const loaded = loadAllMessages(file, false);
22
+ expect(loaded.rendered).toHaveLength(3);
23
+ expect(loaded.rawMessages).toHaveLength(3);
24
+ expect(loaded.rendered.map((e) => e.index)).toEqual([0, 1, 2]);
25
+ } finally {
26
+ rmSync(dir, { recursive: true, force: true });
27
+ }
28
+ });
29
+
30
+ it("filters messages by allowed lineage entry IDs and preserves original message index", () => {
31
+ const dir = mkdtempSync(join(tmpdir(), "pi-vcc-load-filter-"));
32
+ const file = join(dir, "session.jsonl");
33
+ try {
34
+ const lines = [
35
+ JSON.stringify({ type: "message", id: "m1", message: { role: "user", content: "u1" } }),
36
+ JSON.stringify({ type: "message", id: "m2", message: { role: "assistant", content: [{ type: "text", text: "a1" }] } }),
37
+ JSON.stringify({ type: "message", id: "m3", message: { role: "user", content: "u2" } }),
38
+ ];
39
+ writeFileSync(file, lines.join("\n") + "\n", "utf8");
40
+
41
+ const loaded = loadAllMessages(file, false, new Set(["m2"]));
42
+ expect(loaded.rendered).toHaveLength(1);
43
+ expect(loaded.rawMessages).toHaveLength(1);
44
+ expect(loaded.rendered[0].index).toBe(1);
45
+ } finally {
46
+ rmSync(dir, { recursive: true, force: true });
47
+ }
48
+ });
49
+ });
@@ -0,0 +1,377 @@
1
+ import { describe, test, expect, beforeEach, afterEach, beforeAll, afterAll } from "bun:test";
2
+ import { existsSync, unlinkSync, writeFileSync, readFileSync, mkdtempSync, rmSync } from "fs";
3
+ import { tmpdir } from "os";
4
+ import { join } from "path";
5
+ import { registerBeforeCompactHook, PI_VCC_COMPACT_INSTRUCTION } from "../src/hooks/before-compact";
6
+
7
+ let tmpDir: string;
8
+ let CONFIG_PATH: string;
9
+
10
+ beforeAll(() => {
11
+ tmpDir = mkdtempSync(join(tmpdir(), "pi-vcc-test-"));
12
+ CONFIG_PATH = join(tmpDir, "pi-vcc-config.json");
13
+ process.env.PI_VCC_CONFIG_PATH = CONFIG_PATH;
14
+ });
15
+
16
+ afterAll(() => {
17
+ delete process.env.PI_VCC_CONFIG_PATH;
18
+ rmSync(tmpDir, { recursive: true, force: true });
19
+ });
20
+
21
+ function createMockPi(model?: { id: string; provider?: string; contextWindow?: number }) {
22
+ let handler: ((event: any, ctx: any) => any) | undefined;
23
+ const notifyCalls: Array<{ msg: string; level: string }> = [];
24
+ const ctx = {
25
+ hasUI: true,
26
+ model: model ?? undefined,
27
+ ui: {
28
+ notify: (msg: string, level: string) => {
29
+ notifyCalls.push({ msg, level });
30
+ },
31
+ },
32
+ } as any;
33
+ return {
34
+ pi: {
35
+ on: (eventName: string, h: (e: any, c: any) => any) => {
36
+ if (eventName === "session_before_compact") handler = h;
37
+ },
38
+ } as any,
39
+ invoke: (event: any) => handler!(event, ctx),
40
+ notifyCalls,
41
+ };
42
+ }
43
+
44
+ function setConfig(cfg: Record<string, unknown>) {
45
+ writeFileSync(CONFIG_PATH, JSON.stringify(cfg));
46
+ }
47
+
48
+ function makeEvent(branchEntries: any[], customInstructions?: string, tokensBefore = 100000) {
49
+ return {
50
+ type: "session_before_compact",
51
+ customInstructions,
52
+ branchEntries,
53
+ preparation: {
54
+ previousSummary: undefined,
55
+ fileOps: { read: [], written: [], edited: [] },
56
+ tokensBefore,
57
+ },
58
+ signal: new AbortController().signal,
59
+ };
60
+ }
61
+
62
+ const msg = (id: string, role: "user" | "assistant" | "toolResult", content = "x") => ({
63
+ id,
64
+ type: "message",
65
+ message: { role, content },
66
+ });
67
+
68
+ describe("session_before_compact: per-model threshold", () => {
69
+ afterEach(() => {
70
+ if (existsSync(CONFIG_PATH)) unlinkSync(CONFIG_PATH);
71
+ });
72
+
73
+ test("cancels when context is below per-model threshold (provider/modelId)", () => {
74
+ setConfig({
75
+ debug: false,
76
+ overrideDefaultCompaction: true,
77
+ modelThresholds: {
78
+ "neuralwatt/GLM-5.1": { reserveTokens: 32768 },
79
+ },
80
+ });
81
+ const { pi, invoke, notifyCalls } = createMockPi({
82
+ id: "GLM-5.1",
83
+ provider: "neuralwatt",
84
+ contextWindow: 200000,
85
+ });
86
+ registerBeforeCompactHook(pi);
87
+
88
+ // 100k tokens < 200k - 32768 = 167232 → below threshold
89
+ const entries = [
90
+ msg("m1", "user", "hello"),
91
+ msg("m2", "assistant", "hi"),
92
+ msg("m3", "user", "do work"),
93
+ msg("m4", "assistant", "done"),
94
+ ];
95
+ const result = invoke(makeEvent(entries, undefined, 100000));
96
+ expect(result).toEqual({ cancel: true });
97
+ expect(notifyCalls.length).toBeGreaterThanOrEqual(1);
98
+ expect(notifyCalls[0].msg).toContain("Skipped compaction");
99
+ });
100
+
101
+ test("allows compaction when context exceeds per-model threshold", () => {
102
+ setConfig({
103
+ debug: false,
104
+ overrideDefaultCompaction: true,
105
+ modelThresholds: {
106
+ "neuralwatt/GLM-5.1": { reserveTokens: 32768 },
107
+ },
108
+ });
109
+ const { pi, invoke } = createMockPi({
110
+ id: "GLM-5.1",
111
+ provider: "neuralwatt",
112
+ contextWindow: 200000,
113
+ });
114
+ registerBeforeCompactHook(pi);
115
+
116
+ // 180k tokens > 200k - 32768 = 167232 → above threshold
117
+ const entries = [
118
+ msg("m1", "user", "hello"),
119
+ msg("m2", "assistant", "hi"),
120
+ msg("m3", "user", "do work"),
121
+ msg("m4", "assistant", "done"),
122
+ ];
123
+ const result = invoke(makeEvent(entries, undefined, 180000));
124
+ // Not cancelled — pi-vcc proceeds with its own summary
125
+ expect(result.cancel).toBeUndefined();
126
+ expect(result.compaction).toBeDefined();
127
+ });
128
+
129
+ test("cancels when context is below globalThreshold with compactPercent", () => {
130
+ // compactPercent: 65 → reserve = 128000 * 0.35 = 44800 → threshold = 83200
131
+ setConfig({
132
+ debug: false,
133
+ overrideDefaultCompaction: true,
134
+ globalThreshold: { compactPercent: 65 },
135
+ });
136
+ const { pi, invoke } = createMockPi({
137
+ id: "some-model",
138
+ provider: "some-provider",
139
+ contextWindow: 128000,
140
+ });
141
+ registerBeforeCompactHook(pi);
142
+
143
+ // 50k tokens < 83200 → below threshold
144
+ const entries = [
145
+ msg("m1", "user", "hello"),
146
+ msg("m2", "assistant", "hi"),
147
+ msg("m3", "user", "do work"),
148
+ msg("m4", "assistant", "done"),
149
+ ];
150
+ const result = invoke(makeEvent(entries, undefined, 50000));
151
+ expect(result).toEqual({ cancel: true });
152
+ });
153
+
154
+ test("allows compaction when context exceeds globalThreshold with compactPercent", () => {
155
+ // compactPercent: 65 → reserve = 128000 * 0.35 = 44800 → threshold = 83200
156
+ setConfig({
157
+ debug: false,
158
+ overrideDefaultCompaction: true,
159
+ globalThreshold: { compactPercent: 65 },
160
+ });
161
+ const { pi, invoke } = createMockPi({
162
+ id: "some-model",
163
+ provider: "some-provider",
164
+ contextWindow: 128000,
165
+ });
166
+ registerBeforeCompactHook(pi);
167
+
168
+ // 100k tokens > 83200 → above threshold
169
+ const entries = [
170
+ msg("m1", "user", "hello"),
171
+ msg("m2", "assistant", "hi"),
172
+ msg("m3", "user", "do work"),
173
+ msg("m4", "assistant", "done"),
174
+ ];
175
+ const result = invoke(makeEvent(entries, undefined, 100000));
176
+ expect(result.cancel).toBeUndefined();
177
+ expect(result.compaction).toBeDefined();
178
+ });
179
+
180
+ test("cancels when context is below modelThreshold with compactPercent", () => {
181
+ // compactPercent: 80 → reserve = 200000 * 0.20 = 40000 → threshold = 160000
182
+ setConfig({
183
+ debug: false,
184
+ overrideDefaultCompaction: true,
185
+ modelThresholds: {
186
+ "neuralwatt/GLM-5.1": { compactPercent: 80 },
187
+ },
188
+ });
189
+ const { pi, invoke } = createMockPi({
190
+ id: "GLM-5.1",
191
+ provider: "neuralwatt",
192
+ contextWindow: 200000,
193
+ });
194
+ registerBeforeCompactHook(pi);
195
+
196
+ // 100k tokens < 160000 → below threshold
197
+ const entries = [
198
+ msg("m1", "user", "hello"),
199
+ msg("m2", "assistant", "hi"),
200
+ msg("m3", "user", "do work"),
201
+ msg("m4", "assistant", "done"),
202
+ ];
203
+ const result = invoke(makeEvent(entries, undefined, 100000));
204
+ expect(result).toEqual({ cancel: true });
205
+ });
206
+
207
+ test("globalThreshold with compactPercent falls back from defaultThreshold", () => {
208
+ setConfig({
209
+ debug: false,
210
+ overrideDefaultCompaction: true,
211
+ defaultThreshold: { reserveTokens: 16384 },
212
+ });
213
+ const { pi, invoke } = createMockPi({
214
+ id: "some-model",
215
+ provider: "some-provider",
216
+ contextWindow: 128000,
217
+ });
218
+ registerBeforeCompactHook(pi);
219
+
220
+ // 50k tokens < 128k - 16384 = 111616 → below threshold
221
+ const entries = [
222
+ msg("m1", "user", "hello"),
223
+ msg("m2", "assistant", "hi"),
224
+ ];
225
+ const result = invoke(makeEvent(entries, undefined, 50000));
226
+ expect(result).toEqual({ cancel: true });
227
+ });
228
+
229
+ test("cancels when context is below defaultThreshold", () => {
230
+ setConfig({
231
+ debug: false,
232
+ overrideDefaultCompaction: true,
233
+ defaultThreshold: { reserveTokens: 16384 },
234
+ });
235
+ const { pi, invoke } = createMockPi({
236
+ id: "some-model",
237
+ provider: "some-provider",
238
+ contextWindow: 128000,
239
+ });
240
+ registerBeforeCompactHook(pi);
241
+
242
+ // 50k tokens < 128k - 16384 = 111616 → below threshold
243
+ const entries = [
244
+ msg("m1", "user", "hello"),
245
+ msg("m2", "assistant", "hi"),
246
+ msg("m3", "user", "do work"),
247
+ msg("m4", "assistant", "done"),
248
+ ];
249
+ const result = invoke(makeEvent(entries, undefined, 50000));
250
+ expect(result).toEqual({ cancel: true });
251
+ });
252
+
253
+ test("does NOT cancel on /pi-vcc even when below threshold", () => {
254
+ setConfig({
255
+ debug: false,
256
+ overrideDefaultCompaction: true,
257
+ modelThresholds: {
258
+ "neuralwatt/GLM-5.1": { reserveTokens: 32768 },
259
+ },
260
+ });
261
+ const { pi, invoke } = createMockPi({
262
+ id: "GLM-5.1",
263
+ provider: "neuralwatt",
264
+ contextWindow: 200000,
265
+ });
266
+ registerBeforeCompactHook(pi);
267
+
268
+ // Below threshold, but explicit /pi-vcc command — should NOT cancel
269
+ const entries = [
270
+ msg("m1", "user", "hello"),
271
+ msg("m2", "assistant", "hi"),
272
+ msg("m3", "user", "do work"),
273
+ msg("m4", "assistant", "done"),
274
+ ];
275
+ const result = invoke(makeEvent(entries, PI_VCC_COMPACT_INSTRUCTION, 100000));
276
+ // Not cancelled — explicit /pi-vcc bypasses threshold check
277
+ expect(result.cancel).toBeUndefined();
278
+ expect(result.compaction).toBeDefined();
279
+ });
280
+
281
+ test("does not cancel when no modelThresholds configured", () => {
282
+ setConfig({
283
+ debug: false,
284
+ overrideDefaultCompaction: true,
285
+ });
286
+ const { pi, invoke } = createMockPi({
287
+ id: "GLM-5.1",
288
+ provider: "neuralwatt",
289
+ contextWindow: 200000,
290
+ });
291
+ registerBeforeCompactHook(pi);
292
+
293
+ // No modelThresholds → no threshold override → fall through to normal flow
294
+ const entries = [
295
+ msg("m1", "user", "hello"),
296
+ msg("m2", "assistant", "hi"),
297
+ msg("m3", "user", "do work"),
298
+ msg("m4", "assistant", "done"),
299
+ ];
300
+ const result = invoke(makeEvent(entries, undefined, 100000));
301
+ // Not cancelled by threshold check (may be cancelled by other logic)
302
+ expect(result.cancel === true).toBe(false);
303
+ });
304
+
305
+ test("does not cancel when model is undefined", () => {
306
+ setConfig({
307
+ debug: false,
308
+ overrideDefaultCompaction: true,
309
+ modelThresholds: {
310
+ "GLM-5.1": { reserveTokens: 32768 },
311
+ },
312
+ });
313
+ // No model provided — ctx.model is undefined
314
+ const { pi, invoke } = createMockPi(undefined);
315
+ registerBeforeCompactHook(pi);
316
+
317
+ const entries = [
318
+ msg("m1", "user", "hello"),
319
+ msg("m2", "assistant", "hi"),
320
+ msg("m3", "user", "do work"),
321
+ msg("m4", "assistant", "done"),
322
+ ];
323
+ const result = invoke(makeEvent(entries, undefined, 100000));
324
+ // No model → can't check threshold → fall through to normal flow
325
+ expect(result.cancel === true).toBe(false);
326
+ });
327
+
328
+ test("threshold check also applies when overrideDefaultCompaction is false", () => {
329
+ setConfig({
330
+ debug: false,
331
+ overrideDefaultCompaction: false,
332
+ modelThresholds: {
333
+ "neuralwatt/GLM-5.1": { reserveTokens: 32768 },
334
+ },
335
+ });
336
+ const { pi, invoke } = createMockPi({
337
+ id: "GLM-5.1",
338
+ provider: "neuralwatt",
339
+ contextWindow: 200000,
340
+ });
341
+ registerBeforeCompactHook(pi);
342
+
343
+ // Below threshold → cancel, even though pi-vcc wouldn't handle the summary
344
+ const entries = [
345
+ msg("m1", "user", "hello"),
346
+ msg("m2", "assistant", "hi"),
347
+ ];
348
+ const result = invoke(makeEvent(entries, undefined, 100000));
349
+ expect(result).toEqual({ cancel: true });
350
+ });
351
+
352
+ test("modelId-only key matches when provider/modelId does not", () => {
353
+ setConfig({
354
+ debug: false,
355
+ overrideDefaultCompaction: true,
356
+ modelThresholds: {
357
+ "GLM-5.1": { reserveTokens: 32768 },
358
+ },
359
+ });
360
+ const { pi, invoke } = createMockPi({
361
+ id: "GLM-5.1",
362
+ provider: "neuralwatt",
363
+ contextWindow: 200000,
364
+ });
365
+ registerBeforeCompactHook(pi);
366
+
367
+ // Should match on modelId-only key
368
+ const entries = [
369
+ msg("m1", "user", "hello"),
370
+ msg("m2", "assistant", "hi"),
371
+ msg("m3", "user", "do work"),
372
+ msg("m4", "assistant", "done"),
373
+ ];
374
+ const result = invoke(makeEvent(entries, undefined, 100000));
375
+ expect(result).toEqual({ cancel: true });
376
+ });
377
+ });
@@ -0,0 +1,223 @@
1
+ import { describe, test, expect } from "bun:test";
2
+ import { getModelThreshold, resolveReserveTokens, type PiVccSettings, type ModelThreshold } from "../src/core/settings";
3
+
4
+ const t = (reserveTokens: number, keepRecentTokens?: number): ModelThreshold => ({
5
+ reserveTokens,
6
+ ...(keepRecentTokens !== undefined ? { keepRecentTokens } : {}),
7
+ });
8
+
9
+ describe("getModelThreshold", () => {
10
+ test("returns undefined when no modelThresholds and no defaultThreshold", () => {
11
+ const settings: PiVccSettings = {
12
+ overrideDefaultCompaction: true,
13
+ debug: false,
14
+ };
15
+ expect(getModelThreshold(settings, { id: "GLM-5.1", provider: "neuralwatt" })).toBeUndefined();
16
+ });
17
+
18
+ test("returns undefined when model is undefined and no defaultThreshold", () => {
19
+ const settings: PiVccSettings = {
20
+ overrideDefaultCompaction: true,
21
+ debug: false,
22
+ modelThresholds: { "neuralwatt/GLM-5.1": t(32768) },
23
+ };
24
+ expect(getModelThreshold(settings, undefined)).toBeUndefined();
25
+ });
26
+
27
+ test("returns defaultThreshold when model doesn't match any key", () => {
28
+ const settings: PiVccSettings = {
29
+ overrideDefaultCompaction: true,
30
+ debug: false,
31
+ modelThresholds: { "neuralwatt/GLM-5.1": t(32768) },
32
+ defaultThreshold: t(8192),
33
+ };
34
+ expect(getModelThreshold(settings, { id: "other-model", provider: "other" })).toEqual(t(8192));
35
+ });
36
+
37
+ test("returns defaultThreshold when model is undefined", () => {
38
+ const settings: PiVccSettings = {
39
+ overrideDefaultCompaction: true,
40
+ debug: false,
41
+ defaultThreshold: t(8192),
42
+ };
43
+ expect(getModelThreshold(settings, undefined)).toEqual(t(8192));
44
+ });
45
+
46
+ test("matches on provider/modelId key", () => {
47
+ const threshold = t(32768, 40000);
48
+ const settings: PiVccSettings = {
49
+ overrideDefaultCompaction: true,
50
+ debug: false,
51
+ modelThresholds: {
52
+ "neuralwatt/zai-org/GLM-5.1-FP8": threshold,
53
+ },
54
+ defaultThreshold: t(8192),
55
+ };
56
+ expect(getModelThreshold(settings, { id: "zai-org/GLM-5.1-FP8", provider: "neuralwatt" })).toEqual(threshold);
57
+ });
58
+
59
+ test("matches on modelId-only key when provider/modelId not found", () => {
60
+ const threshold = t(16384);
61
+ const settings: PiVccSettings = {
62
+ overrideDefaultCompaction: true,
63
+ debug: false,
64
+ modelThresholds: {
65
+ "zai-org/GLM-5.1-FP8": threshold,
66
+ },
67
+ defaultThreshold: t(8192),
68
+ };
69
+ // provider/modelId doesn't match, but modelId does
70
+ expect(getModelThreshold(settings, { id: "zai-org/GLM-5.1-FP8", provider: "other-provider" })).toEqual(threshold);
71
+ });
72
+
73
+ test("provider/modelId takes precedence over modelId-only key", () => {
74
+ const providerThreshold = t(32768);
75
+ const modelIdThreshold = t(16384);
76
+ const settings: PiVccSettings = {
77
+ overrideDefaultCompaction: true,
78
+ debug: false,
79
+ modelThresholds: {
80
+ "neuralwatt/GLM-5.1": providerThreshold,
81
+ "GLM-5.1": modelIdThreshold,
82
+ },
83
+ };
84
+ expect(getModelThreshold(settings, { id: "GLM-5.1", provider: "neuralwatt" })).toEqual(providerThreshold);
85
+ });
86
+
87
+ test("falls through to modelId-only when provider is absent", () => {
88
+ const threshold = t(16384);
89
+ const settings: PiVccSettings = {
90
+ overrideDefaultCompaction: true,
91
+ debug: false,
92
+ modelThresholds: {
93
+ "GLM-5.1": threshold,
94
+ },
95
+ };
96
+ expect(getModelThreshold(settings, { id: "GLM-5.1" })).toEqual(threshold);
97
+ });
98
+
99
+ test("falls through to defaultThreshold when neither key matches", () => {
100
+ const settings: PiVccSettings = {
101
+ overrideDefaultCompaction: true,
102
+ debug: false,
103
+ modelThresholds: {
104
+ "neuralwatt/GLM-5.1": t(32768),
105
+ },
106
+ defaultThreshold: t(8192),
107
+ };
108
+ expect(getModelThreshold(settings, { id: "Kimi-K2.6", provider: "neuralwatt" })).toEqual(t(8192));
109
+ });
110
+
111
+ test("returns globalThreshold when model doesn't match any key", () => {
112
+ const threshold: ModelThreshold = { compactPercent: 65 };
113
+ const settings: PiVccSettings = {
114
+ overrideDefaultCompaction: true,
115
+ debug: false,
116
+ modelThresholds: { "neuralwatt/GLM-5.1": t(32768) },
117
+ globalThreshold: threshold,
118
+ };
119
+ expect(getModelThreshold(settings, { id: "other-model", provider: "other" })).toEqual(threshold);
120
+ });
121
+
122
+ test("globalThreshold takes precedence over defaultThreshold", () => {
123
+ const settings: PiVccSettings = {
124
+ overrideDefaultCompaction: true,
125
+ debug: false,
126
+ globalThreshold: t(65536),
127
+ defaultThreshold: t(8192),
128
+ };
129
+ expect(getModelThreshold(settings, { id: "unknown", provider: "other" })).toEqual(t(65536));
130
+ });
131
+
132
+ test("returns globalThreshold when model is undefined", () => {
133
+ const threshold: ModelThreshold = { compactPercent: 70 };
134
+ const settings: PiVccSettings = {
135
+ overrideDefaultCompaction: true,
136
+ debug: false,
137
+ globalThreshold: threshold,
138
+ };
139
+ expect(getModelThreshold(settings, undefined)).toEqual(threshold);
140
+ });
141
+
142
+ test("falls back to defaultThreshold when globalThreshold is not set", () => {
143
+ const settings: PiVccSettings = {
144
+ overrideDefaultCompaction: true,
145
+ debug: false,
146
+ defaultThreshold: t(8192),
147
+ };
148
+ expect(getModelThreshold(settings, { id: "unknown", provider: "other" })).toEqual(t(8192));
149
+ });
150
+
151
+ test("works with multiple modelThresholds entries", () => {
152
+ const settings: PiVccSettings = {
153
+ overrideDefaultCompaction: true,
154
+ debug: false,
155
+ modelThresholds: {
156
+ "neuralwatt/zai-org/GLM-5.1-FP8": t(32768),
157
+ "neuralwatt/moonshotai/Kimi-K2.6": t(65536),
158
+ "makora/deepseek-ai/DeepSeek-V4-Pro": t(32768),
159
+ },
160
+ defaultThreshold: t(16384),
161
+ };
162
+
163
+ expect(getModelThreshold(settings, { id: "zai-org/GLM-5.1-FP8", provider: "neuralwatt" })).toEqual(t(32768));
164
+ expect(getModelThreshold(settings, { id: "moonshotai/Kimi-K2.6", provider: "neuralwatt" })).toEqual(t(65536));
165
+ expect(getModelThreshold(settings, { id: "deepseek-ai/DeepSeek-V4-Pro", provider: "makora" })).toEqual(t(32768));
166
+ expect(getModelThreshold(settings, { id: "unknown-model", provider: "other" })).toEqual(t(16384));
167
+ });
168
+ });
169
+
170
+ describe("resolveReserveTokens", () => {
171
+ test("returns reserveTokens when set", () => {
172
+ expect(resolveReserveTokens({ reserveTokens: 32768 }, 128000)).toBe(32768);
173
+ });
174
+
175
+ test("returns undefined when neither reserveTokens nor compactPercent is set", () => {
176
+ expect(resolveReserveTokens({}, 128000)).toBeUndefined();
177
+ });
178
+
179
+ test("returns undefined when only keepRecentTokens is set", () => {
180
+ expect(resolveReserveTokens({ keepRecentTokens: 20000 }, 128000)).toBeUndefined();
181
+ });
182
+
183
+ test("computes reserveTokens from compactPercent", () => {
184
+ // compactPercent: 65 on 128k window → reserve = 128000 * (1 - 65/100) = 44800
185
+ expect(resolveReserveTokens({ compactPercent: 65 }, 128000)).toBe(44800);
186
+ });
187
+
188
+ test("compactPercent: 50 → reserve is exactly half", () => {
189
+ expect(resolveReserveTokens({ compactPercent: 50 }, 200000)).toBe(100000);
190
+ });
191
+
192
+ test("compactPercent: 80 → reserve is 20%", () => {
193
+ expect(resolveReserveTokens({ compactPercent: 80 }, 200000)).toBe(40000);
194
+ });
195
+
196
+ test("reserveTokens takes precedence over compactPercent", () => {
197
+ expect(resolveReserveTokens({ reserveTokens: 32768, compactPercent: 65 }, 128000)).toBe(32768);
198
+ });
199
+
200
+ test("returns undefined for compactPercent < 1", () => {
201
+ expect(resolveReserveTokens({ compactPercent: 0 }, 128000)).toBeUndefined();
202
+ });
203
+
204
+ test("returns undefined for compactPercent > 99", () => {
205
+ expect(resolveReserveTokens({ compactPercent: 100 }, 128000)).toBeUndefined();
206
+ });
207
+
208
+ test("returns undefined when contextWindow is 0", () => {
209
+ expect(resolveReserveTokens({ compactPercent: 65 }, 0)).toBeUndefined();
210
+ });
211
+
212
+ test("reserveTokens still works when contextWindow is 0", () => {
213
+ expect(resolveReserveTokens({ reserveTokens: 32768 }, 0)).toBe(32768);
214
+ });
215
+
216
+ test("compactPercent = 1 → reserve is 99% of contextWindow", () => {
217
+ expect(resolveReserveTokens({ compactPercent: 1 }, 128000)).toBe(126720);
218
+ });
219
+
220
+ test("compactPercent = 99 → reserve is 1% of contextWindow", () => {
221
+ expect(resolveReserveTokens({ compactPercent: 99 }, 128000)).toBe(1280);
222
+ });
223
+ });