@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.
- package/README.md +688 -0
- package/__tests__/helpers.ts +135 -0
- package/__tests__/root-causes.test.ts +858 -0
- package/demo.gif +0 -0
- package/index.ts +21 -0
- package/knip.json +4 -0
- package/npm-shrinkwrap.json +3001 -0
- package/package.json +36 -0
- package/scripts/audit-sessions.ts +88 -0
- package/scripts/benchmark-real-sessions.ts +25 -0
- package/scripts/compare-before-after.ts +36 -0
- package/scripts/dump-branch-output.ts +20 -0
- package/src/commands/pi-vcc.ts +36 -0
- package/src/commands/vcc-recall.ts +65 -0
- package/src/core/brief.ts +497 -0
- package/src/core/build-sections.ts +431 -0
- package/src/core/content.ts +71 -0
- package/src/core/filter-noise.ts +42 -0
- package/src/core/format-recall.ts +177 -0
- package/src/core/format.ts +98 -0
- package/src/core/invisible-continue.ts +172 -0
- package/src/core/lineage.ts +26 -0
- package/src/core/load-messages.ts +40 -0
- package/src/core/normalize.ts +73 -0
- package/src/core/recall-scope.ts +49 -0
- package/src/core/render-entries.ts +58 -0
- package/src/core/report.ts +237 -0
- package/src/core/sanitize.ts +5 -0
- package/src/core/search-entries.ts +375 -0
- package/src/core/settings.ts +190 -0
- package/src/core/skill-collapse.ts +35 -0
- package/src/core/summarize.ts +179 -0
- package/src/core/tool-args.ts +14 -0
- package/src/details.ts +19 -0
- package/src/extract/commits.ts +69 -0
- package/src/extract/goals.ts +79 -0
- package/src/extract/preferences.ts +55 -0
- package/src/extract/shared-symbols.ts +357 -0
- package/src/hooks/before-compact.ts +564 -0
- package/src/hooks/proactive-threshold.ts +131 -0
- package/src/sections.ts +23 -0
- package/src/tools/recall.ts +204 -0
- package/src/types.ts +20 -0
- package/tests/australian-government.test.ts +479 -0
- package/tests/before-compact-hook.test.ts +185 -0
- package/tests/before-compact.test.ts +227 -0
- package/tests/brief.test.ts +215 -0
- package/tests/build-sections.test.ts +59 -0
- package/tests/compile.test.ts +89 -0
- package/tests/content.test.ts +66 -0
- package/tests/deep-extraction.test.ts +313 -0
- package/tests/extract-goals.test.ts +86 -0
- package/tests/extract-preferences.test.ts +30 -0
- package/tests/filter-noise.test.ts +61 -0
- package/tests/fixtures.ts +61 -0
- package/tests/format-recall.test.ts +87 -0
- package/tests/format.test.ts +73 -0
- package/tests/government-domain.test.ts +542 -0
- package/tests/lineage.test.ts +33 -0
- package/tests/load-messages.test.ts +49 -0
- package/tests/model-threshold-hook.test.ts +377 -0
- package/tests/model-threshold.test.ts +223 -0
- package/tests/normalize.test.ts +104 -0
- package/tests/proactive-threshold.test.ts +490 -0
- package/tests/real-sessions.test.ts +38 -0
- package/tests/recall-expand.test.ts +15 -0
- package/tests/recall-scope.test.ts +32 -0
- package/tests/recall-tool-scope.test.ts +67 -0
- package/tests/render-entries.test.ts +92 -0
- package/tests/report.test.ts +58 -0
- package/tests/sanitize.test.ts +24 -0
- package/tests/search-entries.test.ts +233 -0
- package/tests/support/load-session.ts +23 -0
- package/tests/support/real-sessions.ts +51 -0
- package/tests/threshold-integration.test.ts +359 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration tests: proactive threshold + session_before_compact interaction.
|
|
3
|
+
*
|
|
4
|
+
* These tests verify the cross-hook contract:
|
|
5
|
+
* - When proactive trigger calls ctx.compact(), session_before_compact
|
|
6
|
+
* must NOT cancel the compaction even if tokensBefore differs from
|
|
7
|
+
* getContextUsage().
|
|
8
|
+
* - When the global threshold triggers compaction but the model can
|
|
9
|
+
* handle more (per-model threshold not crossed), session_before_compact
|
|
10
|
+
* must cancel.
|
|
11
|
+
*/
|
|
12
|
+
import { describe, test, expect, afterEach, beforeAll, afterAll } from "bun:test";
|
|
13
|
+
import { existsSync, unlinkSync, writeFileSync, mkdtempSync, rmSync } from "fs";
|
|
14
|
+
import { tmpdir } from "os";
|
|
15
|
+
import { join } from "path";
|
|
16
|
+
import { registerBeforeCompactHook } from "../src/hooks/before-compact";
|
|
17
|
+
import { registerProactiveThresholdHook, resetProactiveState } from "../src/hooks/proactive-threshold";
|
|
18
|
+
|
|
19
|
+
let tmpDir: string;
|
|
20
|
+
let CONFIG_PATH: string;
|
|
21
|
+
|
|
22
|
+
beforeAll(() => {
|
|
23
|
+
tmpDir = mkdtempSync(join(tmpdir(), "pi-vcc-test-"));
|
|
24
|
+
CONFIG_PATH = join(tmpDir, "pi-vcc-config.json");
|
|
25
|
+
process.env.PI_VCC_CONFIG_PATH = CONFIG_PATH;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
afterAll(() => {
|
|
29
|
+
delete process.env.PI_VCC_CONFIG_PATH;
|
|
30
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
function setConfig(cfg: Record<string, unknown>) {
|
|
34
|
+
writeFileSync(CONFIG_PATH, JSON.stringify(cfg));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const msg = (id: string, role: "user" | "assistant" | "toolResult", content = "x") => ({
|
|
38
|
+
id,
|
|
39
|
+
type: "message",
|
|
40
|
+
message: { role, content },
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
function createMockPi(
|
|
44
|
+
model?: { id: string; provider?: string; contextWindow?: number },
|
|
45
|
+
usage?: { tokens: number | null; contextWindow: number; percent: number | null },
|
|
46
|
+
) {
|
|
47
|
+
const handlers: Record<string, ((e: any, c: any) => any)[]> = {};
|
|
48
|
+
const compactCalls: number[] = [];
|
|
49
|
+
const notifyCalls: { msg: string; level: string }[] = [];
|
|
50
|
+
|
|
51
|
+
const ctx = {
|
|
52
|
+
hasUI: true,
|
|
53
|
+
model: model ?? undefined,
|
|
54
|
+
ui: {
|
|
55
|
+
notify: (msg: string, level: string) => {
|
|
56
|
+
notifyCalls.push({ msg, level });
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
getContextUsage: () => usage ?? { tokens: null, contextWindow: 0, percent: null },
|
|
60
|
+
compact: () => {
|
|
61
|
+
compactCalls.push(Date.now());
|
|
62
|
+
},
|
|
63
|
+
} as any;
|
|
64
|
+
|
|
65
|
+
const pi = {
|
|
66
|
+
on: (eventName: string, handler: (e: any, c: any) => any) => {
|
|
67
|
+
if (!handlers[eventName]) handlers[eventName] = [];
|
|
68
|
+
handlers[eventName].push(handler);
|
|
69
|
+
},
|
|
70
|
+
} as any;
|
|
71
|
+
|
|
72
|
+
const emit = (eventName: string, event: any = {}) => {
|
|
73
|
+
const hs = handlers[eventName] ?? [];
|
|
74
|
+
let result: any;
|
|
75
|
+
for (const h of hs) result = h(event, ctx);
|
|
76
|
+
return result;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
return { pi, ctx, emit, compactCalls, notifyCalls };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function makeBeforeCompactEvent(branchEntries: any[], customInstructions?: string, tokensBefore = 100000) {
|
|
83
|
+
return {
|
|
84
|
+
type: "session_before_compact",
|
|
85
|
+
customInstructions,
|
|
86
|
+
branchEntries,
|
|
87
|
+
preparation: {
|
|
88
|
+
previousSummary: undefined,
|
|
89
|
+
fileOps: { read: [], written: [], edited: [] },
|
|
90
|
+
tokensBefore,
|
|
91
|
+
},
|
|
92
|
+
signal: new AbortController().signal,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
describe("integration: proactive trigger + before-compact", () => {
|
|
97
|
+
afterEach(() => {
|
|
98
|
+
if (existsSync(CONFIG_PATH)) unlinkSync(CONFIG_PATH);
|
|
99
|
+
resetProactiveState();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("proactive trigger then before-compact: does NOT cancel when proactiveTriggerActive", () => {
|
|
103
|
+
// Scenario: agent_end fires, getContextUsage says 110k tokens,
|
|
104
|
+
// per-model threshold is 95232 (128k - 32768). Proactive triggers compact.
|
|
105
|
+
// Then session_before_compact fires with tokensBefore = 94000
|
|
106
|
+
// (slightly different due to estimation).
|
|
107
|
+
// Without the proactiveTriggerActive guard, this would be cancelled.
|
|
108
|
+
setConfig({
|
|
109
|
+
debug: false,
|
|
110
|
+
overrideDefaultCompaction: true,
|
|
111
|
+
modelThresholds: {
|
|
112
|
+
"neuralwatt/GLM-5.1": { reserveTokens: 32768 },
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
const { pi, ctx, emit, compactCalls } = createMockPi(
|
|
116
|
+
{ id: "GLM-5.1", provider: "neuralwatt", contextWindow: 128000 },
|
|
117
|
+
{ tokens: 110000, contextWindow: 128000, percent: 86 },
|
|
118
|
+
);
|
|
119
|
+
registerProactiveThresholdHook(pi);
|
|
120
|
+
registerBeforeCompactHook(pi);
|
|
121
|
+
|
|
122
|
+
// Step 1: agent_end fires → proactive trigger calls ctx.compact()
|
|
123
|
+
emit("agent_end", { type: "agent_end", messages: [] });
|
|
124
|
+
expect(compactCalls).toHaveLength(1);
|
|
125
|
+
|
|
126
|
+
// Step 2: session_before_compact fires with tokensBefore = 94000
|
|
127
|
+
// (below the 95232 threshold — but we should NOT cancel because
|
|
128
|
+
// we ourselves triggered this compaction)
|
|
129
|
+
const entries = [
|
|
130
|
+
msg("m1", "user", "hello"),
|
|
131
|
+
msg("m2", "assistant", "hi"),
|
|
132
|
+
msg("m3", "user", "do work"),
|
|
133
|
+
msg("m4", "assistant", "done"),
|
|
134
|
+
];
|
|
135
|
+
const result = emit("session_before_compact", makeBeforeCompactEvent(entries, undefined, 94000));
|
|
136
|
+
|
|
137
|
+
// Should NOT cancel — proactiveTriggerActive is true
|
|
138
|
+
expect(result?.cancel).toBeUndefined();
|
|
139
|
+
// Should proceed with compaction (pi-vcc's own summary)
|
|
140
|
+
expect(result?.compaction).toBeDefined();
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test("global trigger + before-compact: CANCELS when per-model threshold not crossed and no proactive trigger", () => {
|
|
144
|
+
// Scenario: pi-core's global threshold triggers compaction,
|
|
145
|
+
// but the model's per-model threshold hasn't been crossed.
|
|
146
|
+
// No proactive trigger was set — this is pi-core's own initiative.
|
|
147
|
+
setConfig({
|
|
148
|
+
debug: false,
|
|
149
|
+
overrideDefaultCompaction: true,
|
|
150
|
+
modelThresholds: {
|
|
151
|
+
"neuralwatt/GLM-5.1": { reserveTokens: 32768 },
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
const { pi, ctx, emit, compactCalls } = createMockPi(
|
|
155
|
+
{ id: "GLM-5.1", provider: "neuralwatt", contextWindow: 128000 },
|
|
156
|
+
// getContextUsage says 80k — well below per-model threshold
|
|
157
|
+
{ tokens: 80000, contextWindow: 128000, percent: 63 },
|
|
158
|
+
);
|
|
159
|
+
registerProactiveThresholdHook(pi);
|
|
160
|
+
registerBeforeCompactHook(pi);
|
|
161
|
+
|
|
162
|
+
// No agent_end fired (global threshold triggered this)
|
|
163
|
+
const entries = [
|
|
164
|
+
msg("m1", "user", "hello"),
|
|
165
|
+
msg("m2", "assistant", "hi"),
|
|
166
|
+
msg("m3", "user", "do work"),
|
|
167
|
+
msg("m4", "assistant", "done"),
|
|
168
|
+
];
|
|
169
|
+
// tokensBefore = 90k < 95232 — should cancel
|
|
170
|
+
const result = emit("session_before_compact", makeBeforeCompactEvent(entries, undefined, 90000));
|
|
171
|
+
expect(result).toEqual({ cancel: true });
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test("proactiveTriggerActive is cleared after session_compact", () => {
|
|
175
|
+
setConfig({
|
|
176
|
+
debug: false,
|
|
177
|
+
overrideDefaultCompaction: true,
|
|
178
|
+
modelThresholds: {
|
|
179
|
+
"neuralwatt/GLM-5.1": { reserveTokens: 32768 },
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
const { pi, ctx, emit, compactCalls } = createMockPi(
|
|
183
|
+
{ id: "GLM-5.1", provider: "neuralwatt", contextWindow: 128000 },
|
|
184
|
+
{ tokens: 110000, contextWindow: 128000, percent: 86 },
|
|
185
|
+
);
|
|
186
|
+
registerProactiveThresholdHook(pi);
|
|
187
|
+
registerBeforeCompactHook(pi);
|
|
188
|
+
|
|
189
|
+
// Step 1: proactive trigger
|
|
190
|
+
emit("agent_end", { type: "agent_end", messages: [] });
|
|
191
|
+
expect(compactCalls).toHaveLength(1);
|
|
192
|
+
|
|
193
|
+
// Step 2: compaction completes
|
|
194
|
+
emit("session_compact", { type: "session_compact", compactionEntry: {} });
|
|
195
|
+
|
|
196
|
+
// Step 3: now a subsequent session_before_compact (e.g., from pi-core
|
|
197
|
+
// also triggering) with tokensBelow below threshold — should CANCEL
|
|
198
|
+
// because proactiveTriggerActive was cleared by session_compact
|
|
199
|
+
const entries = [
|
|
200
|
+
msg("m1", "user", "hello"),
|
|
201
|
+
msg("m2", "assistant", "hi"),
|
|
202
|
+
msg("m3", "user", "do work"),
|
|
203
|
+
msg("m4", "assistant", "done"),
|
|
204
|
+
];
|
|
205
|
+
const result = emit("session_before_compact", makeBeforeCompactEvent(entries, undefined, 90000));
|
|
206
|
+
expect(result).toEqual({ cancel: true });
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
test("explicit /pi-vcc bypasses both the proactive flag AND threshold guard", () => {
|
|
210
|
+
setConfig({
|
|
211
|
+
debug: false,
|
|
212
|
+
overrideDefaultCompaction: true,
|
|
213
|
+
modelThresholds: {
|
|
214
|
+
"neuralwatt/GLM-5.1": { reserveTokens: 32768 },
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
const { pi, ctx, emit } = createMockPi(
|
|
218
|
+
{ id: "GLM-5.1", provider: "neuralwatt", contextWindow: 128000 },
|
|
219
|
+
{ tokens: 50000, contextWindow: 128000, percent: 39 },
|
|
220
|
+
);
|
|
221
|
+
registerProactiveThresholdHook(pi);
|
|
222
|
+
registerBeforeCompactHook(pi);
|
|
223
|
+
|
|
224
|
+
// Direct /pi-vcc with tokens well below threshold — should still proceed
|
|
225
|
+
const entries = [
|
|
226
|
+
msg("m1", "user", "hello"),
|
|
227
|
+
msg("m2", "assistant", "hi"),
|
|
228
|
+
msg("m3", "user", "do work"),
|
|
229
|
+
msg("m4", "assistant", "done"),
|
|
230
|
+
];
|
|
231
|
+
const result = emit("session_before_compact", makeBeforeCompactEvent(entries, "__pi_vcc__", 50000));
|
|
232
|
+
expect(result?.cancel).toBeUndefined();
|
|
233
|
+
expect(result?.compaction).toBeDefined();
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
describe("integration: proactive trigger + before-compact with overrideDefaultCompaction: false", () => {
|
|
238
|
+
afterEach(() => {
|
|
239
|
+
if (existsSync(CONFIG_PATH)) unlinkSync(CONFIG_PATH);
|
|
240
|
+
resetProactiveState();
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
test("proactive trigger fires, before-compact doesn't cancel, then pi-core handles summary", () => {
|
|
244
|
+
// When overrideDefaultCompaction: false, pi-vcc doesn't handle the summary
|
|
245
|
+
// for non-/pi-vcc compactions. But the threshold guard and proactive trigger
|
|
246
|
+
// should still work — the threshold guard controls WHEN compaction triggers,
|
|
247
|
+
// and pi-core handles the actual summary.
|
|
248
|
+
setConfig({
|
|
249
|
+
debug: false,
|
|
250
|
+
overrideDefaultCompaction: false,
|
|
251
|
+
modelThresholds: {
|
|
252
|
+
"neuralwatt/GLM-5.1": { reserveTokens: 32768 },
|
|
253
|
+
},
|
|
254
|
+
});
|
|
255
|
+
const { pi, ctx, emit, compactCalls } = createMockPi(
|
|
256
|
+
{ id: "GLM-5.1", provider: "neuralwatt", contextWindow: 128000 },
|
|
257
|
+
{ tokens: 110000, contextWindow: 128000, percent: 86 },
|
|
258
|
+
);
|
|
259
|
+
registerProactiveThresholdHook(pi);
|
|
260
|
+
registerBeforeCompactHook(pi);
|
|
261
|
+
|
|
262
|
+
// agent_end fires → proactive trigger
|
|
263
|
+
emit("agent_end", { type: "agent_end", messages: [] });
|
|
264
|
+
expect(compactCalls).toHaveLength(1);
|
|
265
|
+
|
|
266
|
+
// session_before_compact fires: threshold is crossed (tokensBefore = 110k
|
|
267
|
+
// > 95232), and our guard allows it because proactiveTriggerActive.
|
|
268
|
+
// Then overrideDefaultCompaction: false means pi-vcc returns undefined,
|
|
269
|
+
// letting pi-core handle the summary.
|
|
270
|
+
const entries = [
|
|
271
|
+
msg("m1", "user", "hello"),
|
|
272
|
+
msg("m2", "assistant", "hi"),
|
|
273
|
+
msg("m3", "user", "do work"),
|
|
274
|
+
msg("m4", "assistant", "done"),
|
|
275
|
+
];
|
|
276
|
+
const result = emit("session_before_compact", makeBeforeCompactEvent(entries, undefined, 110000));
|
|
277
|
+
// pi-vcc doesn't handle it (overrideDefaultCompaction: false) → returns undefined
|
|
278
|
+
// pi-core will handle the summary
|
|
279
|
+
expect(result).toBeUndefined();
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
test("threshold guard cancels even with overrideDefaultCompaction: false", () => {
|
|
283
|
+
setConfig({
|
|
284
|
+
debug: false,
|
|
285
|
+
overrideDefaultCompaction: false,
|
|
286
|
+
modelThresholds: {
|
|
287
|
+
"neuralwatt/GLM-5.1": { reserveTokens: 32768 },
|
|
288
|
+
},
|
|
289
|
+
});
|
|
290
|
+
const { pi, ctx, emit } = createMockPi(
|
|
291
|
+
{ id: "GLM-5.1", provider: "neuralwatt", contextWindow: 128000 },
|
|
292
|
+
{ tokens: 80000, contextWindow: 128000, percent: 63 },
|
|
293
|
+
);
|
|
294
|
+
registerProactiveThresholdHook(pi);
|
|
295
|
+
registerBeforeCompactHook(pi);
|
|
296
|
+
|
|
297
|
+
// No proactive trigger (context below threshold)
|
|
298
|
+
// Pi-core's global threshold triggers compaction, but per-model threshold
|
|
299
|
+
// says the model can handle more → cancel
|
|
300
|
+
const entries = [
|
|
301
|
+
msg("m1", "user", "hello"),
|
|
302
|
+
msg("m2", "assistant", "hi"),
|
|
303
|
+
];
|
|
304
|
+
const result = emit("session_before_compact", makeBeforeCompactEvent(entries, undefined, 80000));
|
|
305
|
+
expect(result).toEqual({ cancel: true });
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
describe("integration: cooldown prevents double compaction", () => {
|
|
310
|
+
afterEach(() => {
|
|
311
|
+
if (existsSync(CONFIG_PATH)) unlinkSync(CONFIG_PATH);
|
|
312
|
+
resetProactiveState();
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
test("agent_end + model_select on same turn: only one compact()", () => {
|
|
316
|
+
setConfig({
|
|
317
|
+
debug: false,
|
|
318
|
+
overrideDefaultCompaction: true,
|
|
319
|
+
modelThresholds: {
|
|
320
|
+
"neuralwatt/GLM-5.1": { reserveTokens: 32768 },
|
|
321
|
+
},
|
|
322
|
+
});
|
|
323
|
+
const { pi, ctx, emit, compactCalls } = createMockPi(
|
|
324
|
+
{ id: "GLM-5.1", provider: "neuralwatt", contextWindow: 128000 },
|
|
325
|
+
{ tokens: 110000, contextWindow: 128000, percent: 86 },
|
|
326
|
+
);
|
|
327
|
+
registerProactiveThresholdHook(pi);
|
|
328
|
+
|
|
329
|
+
// agent_end triggers compact and sets cooldown
|
|
330
|
+
emit("agent_end", { type: "agent_end", messages: [] });
|
|
331
|
+
expect(compactCalls).toHaveLength(1);
|
|
332
|
+
|
|
333
|
+
// model_select fires on same turn — blocked by cooldown
|
|
334
|
+
emit("model_select", { type: "model_select" });
|
|
335
|
+
expect(compactCalls).toHaveLength(1);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
test("two consecutive agent_ends without session_compact: second blocked by cooldown", () => {
|
|
339
|
+
setConfig({
|
|
340
|
+
debug: false,
|
|
341
|
+
overrideDefaultCompaction: true,
|
|
342
|
+
modelThresholds: {
|
|
343
|
+
"neuralwatt/GLM-5.1": { reserveTokens: 32768 },
|
|
344
|
+
},
|
|
345
|
+
});
|
|
346
|
+
const { pi, ctx, emit, compactCalls } = createMockPi(
|
|
347
|
+
{ id: "GLM-5.1", provider: "neuralwatt", contextWindow: 128000 },
|
|
348
|
+
{ tokens: 110000, contextWindow: 128000, percent: 86 },
|
|
349
|
+
);
|
|
350
|
+
registerProactiveThresholdHook(pi);
|
|
351
|
+
|
|
352
|
+
emit("agent_end", { type: "agent_end", messages: [] });
|
|
353
|
+
expect(compactCalls).toHaveLength(1);
|
|
354
|
+
|
|
355
|
+
// No session_compact between — cooldown still active
|
|
356
|
+
emit("agent_end", { type: "agent_end", messages: [] });
|
|
357
|
+
expect(compactCalls).toHaveLength(1);
|
|
358
|
+
});
|
|
359
|
+
});
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"lib": ["ES2023"],
|
|
5
|
+
"module": "NodeNext",
|
|
6
|
+
"moduleResolution": "NodeNext",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
|
11
|
+
"resolveJsonModule": true,
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"outDir": ".tsbuild",
|
|
14
|
+
"rootDir": "."
|
|
15
|
+
},
|
|
16
|
+
"include": [
|
|
17
|
+
"index.ts",
|
|
18
|
+
"src/**/*.ts"
|
|
19
|
+
]
|
|
20
|
+
}
|