@animalabs/context-manager 0.5.3 → 0.5.5

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 (123) hide show
  1. package/dist/src/adaptive/index.d.ts +6 -0
  2. package/dist/src/adaptive/index.d.ts.map +1 -1
  3. package/dist/src/adaptive/index.js +8 -0
  4. package/dist/src/adaptive/index.js.map +1 -1
  5. package/dist/src/adaptive/kv-cache-sim.d.ts +128 -0
  6. package/dist/src/adaptive/kv-cache-sim.d.ts.map +1 -0
  7. package/dist/src/adaptive/kv-cache-sim.js +0 -0
  8. package/dist/src/adaptive/kv-cache-sim.js.map +1 -0
  9. package/dist/src/adaptive/kv-control.d.ts +166 -0
  10. package/dist/src/adaptive/kv-control.d.ts.map +1 -0
  11. package/dist/src/adaptive/kv-control.js +434 -0
  12. package/dist/src/adaptive/kv-control.js.map +1 -0
  13. package/dist/src/adaptive/kv-replay.d.ts +76 -0
  14. package/dist/src/adaptive/kv-replay.d.ts.map +1 -0
  15. package/dist/src/adaptive/kv-replay.js +175 -0
  16. package/dist/src/adaptive/kv-replay.js.map +1 -0
  17. package/dist/src/adaptive/picker.d.ts +13 -0
  18. package/dist/src/adaptive/picker.d.ts.map +1 -1
  19. package/dist/src/adaptive/picker.js.map +1 -1
  20. package/dist/src/adaptive/render-offsets.d.ts +61 -0
  21. package/dist/src/adaptive/render-offsets.d.ts.map +1 -0
  22. package/dist/src/adaptive/render-offsets.js +88 -0
  23. package/dist/src/adaptive/render-offsets.js.map +1 -0
  24. package/dist/src/adaptive/strategies/kv-stable.d.ts +48 -0
  25. package/dist/src/adaptive/strategies/kv-stable.d.ts.map +1 -0
  26. package/dist/src/adaptive/strategies/kv-stable.js +153 -0
  27. package/dist/src/adaptive/strategies/kv-stable.js.map +1 -0
  28. package/dist/src/adaptive/summary-tree.d.ts +98 -0
  29. package/dist/src/adaptive/summary-tree.d.ts.map +1 -0
  30. package/dist/src/adaptive/summary-tree.js +214 -0
  31. package/dist/src/adaptive/summary-tree.js.map +1 -0
  32. package/dist/src/context-log.d.ts.map +1 -1
  33. package/dist/src/context-log.js +7 -2
  34. package/dist/src/context-log.js.map +1 -1
  35. package/dist/src/context-manager.d.ts +10 -5
  36. package/dist/src/context-manager.d.ts.map +1 -1
  37. package/dist/src/context-manager.js +9 -0
  38. package/dist/src/context-manager.js.map +1 -1
  39. package/dist/src/index.d.ts +1 -0
  40. package/dist/src/index.d.ts.map +1 -1
  41. package/dist/src/index.js +2 -0
  42. package/dist/src/index.js.map +1 -1
  43. package/dist/src/message-store.js +1 -1
  44. package/dist/src/message-store.js.map +1 -1
  45. package/dist/src/phase-channel.d.ts +13 -0
  46. package/dist/src/phase-channel.d.ts.map +1 -0
  47. package/dist/src/phase-channel.js +55 -0
  48. package/dist/src/phase-channel.js.map +1 -0
  49. package/dist/src/strategies/autobiographical.d.ts +107 -44
  50. package/dist/src/strategies/autobiographical.d.ts.map +1 -1
  51. package/dist/src/strategies/autobiographical.js +437 -230
  52. package/dist/src/strategies/autobiographical.js.map +1 -1
  53. package/dist/src/types/index.d.ts +1 -1
  54. package/dist/src/types/index.d.ts.map +1 -1
  55. package/dist/src/types/index.js.map +1 -1
  56. package/dist/src/types/strategy.d.ts +70 -7
  57. package/dist/src/types/strategy.d.ts.map +1 -1
  58. package/dist/src/types/strategy.js +2 -0
  59. package/dist/src/types/strategy.js.map +1 -1
  60. package/dist/test/adaptive/kv-cache-sim.test.d.ts +16 -0
  61. package/dist/test/adaptive/kv-cache-sim.test.d.ts.map +1 -0
  62. package/dist/test/adaptive/kv-cache-sim.test.js +173 -0
  63. package/dist/test/adaptive/kv-cache-sim.test.js.map +1 -0
  64. package/dist/test/adaptive/kv-control.test.d.ts +14 -0
  65. package/dist/test/adaptive/kv-control.test.d.ts.map +1 -0
  66. package/dist/test/adaptive/kv-control.test.js +130 -0
  67. package/dist/test/adaptive/kv-control.test.js.map +1 -0
  68. package/dist/test/adaptive/kv-replay.test.d.ts +15 -0
  69. package/dist/test/adaptive/kv-replay.test.d.ts.map +1 -0
  70. package/dist/test/adaptive/kv-replay.test.js +112 -0
  71. package/dist/test/adaptive/kv-replay.test.js.map +1 -0
  72. package/dist/test/adaptive/kv-stable-strategy.test.d.ts +10 -0
  73. package/dist/test/adaptive/kv-stable-strategy.test.d.ts.map +1 -0
  74. package/dist/test/adaptive/kv-stable-strategy.test.js +89 -0
  75. package/dist/test/adaptive/kv-stable-strategy.test.js.map +1 -0
  76. package/dist/test/adaptive/pin-at-level.test.d.ts +16 -0
  77. package/dist/test/adaptive/pin-at-level.test.d.ts.map +1 -0
  78. package/dist/test/adaptive/pin-at-level.test.js +133 -0
  79. package/dist/test/adaptive/pin-at-level.test.js.map +1 -0
  80. package/dist/test/adaptive/render-offsets.test.d.ts +11 -0
  81. package/dist/test/adaptive/render-offsets.test.d.ts.map +1 -0
  82. package/dist/test/adaptive/render-offsets.test.js +85 -0
  83. package/dist/test/adaptive/render-offsets.test.js.map +1 -0
  84. package/dist/test/adaptive/summary-tree.test.d.ts +5 -0
  85. package/dist/test/adaptive/summary-tree.test.d.ts.map +1 -0
  86. package/dist/test/adaptive/summary-tree.test.js +72 -0
  87. package/dist/test/adaptive/summary-tree.test.js.map +1 -0
  88. package/dist/test/image-strip-render-stats.test.d.ts +2 -0
  89. package/dist/test/image-strip-render-stats.test.d.ts.map +1 -0
  90. package/dist/test/image-strip-render-stats.test.js +130 -0
  91. package/dist/test/image-strip-render-stats.test.js.map +1 -0
  92. package/dist/test/image-stripping.test.d.ts +13 -0
  93. package/dist/test/image-stripping.test.d.ts.map +1 -0
  94. package/dist/test/image-stripping.test.js +104 -0
  95. package/dist/test/image-stripping.test.js.map +1 -0
  96. package/dist/test/pins.test.js +40 -0
  97. package/dist/test/pins.test.js.map +1 -1
  98. package/dist/test/render-stats.test.d.ts +2 -0
  99. package/dist/test/render-stats.test.d.ts.map +1 -0
  100. package/dist/test/render-stats.test.js +91 -0
  101. package/dist/test/render-stats.test.js.map +1 -0
  102. package/dist/test/speculation-cap.test.d.ts +9 -3
  103. package/dist/test/speculation-cap.test.d.ts.map +1 -1
  104. package/dist/test/speculation-cap.test.js +175 -3
  105. package/dist/test/speculation-cap.test.js.map +1 -1
  106. package/dist/tsconfig.tsbuildinfo +1 -1
  107. package/package.json +2 -2
  108. package/src/adaptive/index.ts +48 -0
  109. package/src/adaptive/kv-cache-sim.ts +0 -0
  110. package/src/adaptive/kv-control.ts +574 -0
  111. package/src/adaptive/kv-replay.ts +238 -0
  112. package/src/adaptive/picker.ts +13 -0
  113. package/src/adaptive/render-offsets.ts +116 -0
  114. package/src/adaptive/strategies/kv-stable.ts +161 -0
  115. package/src/adaptive/summary-tree.ts +252 -0
  116. package/src/context-log.ts +7 -2
  117. package/src/context-manager.ts +13 -2
  118. package/src/index.ts +3 -0
  119. package/src/message-store.ts +1 -1
  120. package/src/phase-channel.ts +57 -0
  121. package/src/strategies/autobiographical.ts +453 -282
  122. package/src/types/index.ts +1 -0
  123. package/src/types/strategy.ts +71 -3
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Regression: image stripping must run BEFORE the render-stats snapshot is
3
+ * committed and BEFORE cache markers are placed, so that
4
+ *
5
+ * (a) RenderStats.total reflects the POST-strip context — the real bytes the
6
+ * agent receives — not the pre-strip size that still counts full image
7
+ * weight (≈1600 tok) for images replaced by a short text placeholder.
8
+ * Pre-fix, getRenderStats() over-reported by ~1592 tok per stripped image
9
+ * (and image stripping is on by default: maxLiveImages = 6).
10
+ *
11
+ * (b) cache markers and stripping coexist cleanly: marker positions are
12
+ * structural (content-independent, so deterministic across recompiles)
13
+ * and a stripped image never resurrects across turns — the live-image
14
+ * window is monotonic, so each image strips at most once (one bounded KV
15
+ * perturbation, not per-turn flicker).
16
+ */
17
+ import { describe, it, before, after, beforeEach } from 'node:test';
18
+ import assert from 'node:assert';
19
+ import { rmSync, existsSync } from 'node:fs';
20
+ import { ContextManager, AutobiographicalStrategy } from '../src/index.js';
21
+ const TEST_STORE_PATH = './test-image-strip-render-stats';
22
+ const PLACEHOLDER = 'image dropped from live context';
23
+ function cleanup() {
24
+ if (existsSync(TEST_STORE_PATH))
25
+ rmSync(TEST_STORE_PATH, { recursive: true, force: true });
26
+ }
27
+ /** A message carrying one image plus a text label so we can locate it later. */
28
+ function imageMessage(label, tokenEstimate = 1600) {
29
+ return [
30
+ { type: 'image', source: { type: 'base64', data: 'AAAA', mediaType: 'image/png' }, tokenEstimate },
31
+ { type: 'text', text: label },
32
+ ];
33
+ }
34
+ /** Re-derive rendered tokens from the COMPILED output using the strategy's
35
+ * default estimator (image -> tokenEstimate ?? 1600, text -> ceil(len/4)).
36
+ * The fixtures use only image + text blocks. */
37
+ function renderedTokens(messages) {
38
+ let t = 0;
39
+ for (const m of messages) {
40
+ for (const b of m.content) {
41
+ if (b.type === 'image')
42
+ t += b.tokenEstimate ?? 1600;
43
+ else if (b.type === 'text')
44
+ t += Math.ceil(b.text.length / 4);
45
+ }
46
+ }
47
+ return t;
48
+ }
49
+ function hasLabel(content, label) {
50
+ return content.some((b) => b.type === 'text' && b.text.includes(label));
51
+ }
52
+ describe('image stripping × render stats', () => {
53
+ before(cleanup);
54
+ after(cleanup);
55
+ beforeEach(cleanup);
56
+ it('(a) total reflects the post-strip size, not the pre-strip image weight', async () => {
57
+ // Default live-image policy is ON (maxLiveImages: 6). 10 images => 4 stripped.
58
+ const manager = await ContextManager.open({
59
+ path: TEST_STORE_PATH,
60
+ strategy: new AutobiographicalStrategy({
61
+ adaptiveResolution: true,
62
+ headWindowTokens: 0,
63
+ recentWindowTokens: 1_000_000, // keep everything verbatim; isolate the count cap
64
+ }),
65
+ });
66
+ for (let i = 1; i <= 10; i++)
67
+ manager.addMessage('user', imageMessage(`img-${String(i).padStart(2, '0')}`));
68
+ const compiled = await manager.compile({ maxTokens: 1_000_000, reserveForResponse: 0 });
69
+ const live = compiled.messages.filter((m) => m.content.some((b) => b.type === 'image')).length;
70
+ const stripped = compiled.messages.filter((m) => hasLabel(m.content, PLACEHOLDER)).length;
71
+ assert.equal(live, 6, 'default maxLiveImages keeps 6 images live');
72
+ assert.equal(stripped, 4, 'the other 4 are stripped to placeholders');
73
+ const rs = manager.getRenderStats();
74
+ assert.ok(rs, 'stats present after compile');
75
+ // Decisive assertion: total == the ACTUAL rendered size. Pre-fix this was
76
+ // inflated by the 4 stripped images (~4 * 1592 tok).
77
+ const expected = renderedTokens(compiled.messages);
78
+ assert.equal(rs.total.tokens, expected, 'total.tokens equals the real rendered size');
79
+ // Internal invariant must still hold (total == sum of buckets).
80
+ const s = rs.summaries;
81
+ const bucketSum = rs.head.tokens + rs.tail.tokens + rs.middleRaw.tokens +
82
+ s.l1.tokens + s.l2.tokens + s.l3.tokens;
83
+ assert.equal(rs.total.tokens, bucketSum, 'total == sum of buckets');
84
+ for (const k of ['head', 'tail', 'middleRaw']) {
85
+ assert.ok(rs[k].tokens >= 0, `${k} tokens stay non-negative after the strip credit`);
86
+ }
87
+ // And total must be strictly below the pre-strip size — proves the credit bites.
88
+ const preStrip = expected + stripped * (1600 - Math.ceil('[image dropped from live context]'.length / 4));
89
+ assert.ok(rs.total.tokens < preStrip, 'total is the stripped size, not the pre-strip size');
90
+ manager.close();
91
+ });
92
+ it('(b) cache markers coexist with stripping; stripped images never resurrect', async () => {
93
+ const manager = await ContextManager.open({
94
+ path: TEST_STORE_PATH,
95
+ strategy: new AutobiographicalStrategy({
96
+ adaptiveResolution: true,
97
+ headWindowTokens: 0,
98
+ recentWindowTokens: 1_000_000,
99
+ maxLiveImages: 3,
100
+ imageStripDepthTokens: 0, // isolate the count cap
101
+ }),
102
+ });
103
+ for (let i = 1; i <= 6; i++)
104
+ manager.addMessage('user', imageMessage(`img-${String(i).padStart(2, '0')}`));
105
+ const c1 = await manager.compile({ maxTokens: 1_000_000, reserveForResponse: 0 });
106
+ const markers1 = c1.messages.flatMap((m, i) => (m.cacheBreakpoint ? [i] : []));
107
+ const stripped1 = c1.messages.filter((m) => hasLabel(m.content, PLACEHOLDER)).length;
108
+ assert.ok(markers1.length > 0, 'cache markers are placed');
109
+ assert.equal(stripped1, 3, 'oldest 3 of 6 images stripped under maxLiveImages:3');
110
+ // Re-compile the SAME store: marker placement is structural (head/tail
111
+ // membership + index), so positions are identical even though stripping
112
+ // mutated content. Guards against a future token-sensitive marker pass
113
+ // being fed pre-strip sizes.
114
+ const c1b = await manager.compile({ maxTokens: 1_000_000, reserveForResponse: 0 });
115
+ const markers1b = c1b.messages.flatMap((m, i) => (m.cacheBreakpoint ? [i] : []));
116
+ assert.deepEqual(markers1b, markers1, 'marker positions are deterministic across recompiles');
117
+ // Cross-turn: append a new image so the live window slides forward. Images
118
+ // that were already stripped must STAY stripped — monotonic, no flicker
119
+ // that would churn the cached prefix turn-to-turn.
120
+ manager.addMessage('user', imageMessage('img-07'));
121
+ const c2 = await manager.compile({ maxTokens: 1_000_000, reserveForResponse: 0 });
122
+ for (const label of ['img-01', 'img-02', 'img-03']) {
123
+ const e = c2.messages.find((m) => hasLabel(m.content, label));
124
+ assert.ok(e, `${label} still present`);
125
+ assert.ok(!e.content.some((b) => b.type === 'image'), `${label} stays stripped after a new turn`);
126
+ }
127
+ manager.close();
128
+ });
129
+ });
130
+ //# sourceMappingURL=image-strip-render-stats.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-strip-render-stats.test.js","sourceRoot":"","sources":["../../test/image-strip-render-stats.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACpE,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAG3E,MAAM,eAAe,GAAG,iCAAiC,CAAC;AAC1D,MAAM,WAAW,GAAG,iCAAiC,CAAC;AAEtD,SAAS,OAAO;IACd,IAAI,UAAU,CAAC,eAAe,CAAC;QAAE,MAAM,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAC7F,CAAC;AAED,gFAAgF;AAChF,SAAS,YAAY,CAAC,KAAa,EAAE,aAAa,GAAG,IAAI;IACvD,OAAO;QACL,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,aAAa,EAAkB;QAClH,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE;KAC9B,CAAC;AACJ,CAAC;AAED;;iDAEiD;AACjD,SAAS,cAAc,CAAC,QAAuC;IAC7D,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;YAC1B,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO;gBAAE,CAAC,IAAK,CAAgC,CAAC,aAAa,IAAI,IAAI,CAAC;iBAChF,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;gBAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,QAAQ,CAAC,OAAuB,EAAE,KAAa;IACtD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,MAAM,CAAC,OAAO,CAAC,CAAC;IAChB,KAAK,CAAC,OAAO,CAAC,CAAC;IACf,UAAU,CAAC,OAAO,CAAC,CAAC;IAEpB,EAAE,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;QACtF,+EAA+E;QAC/E,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC;YACxC,IAAI,EAAE,eAAe;YACrB,QAAQ,EAAE,IAAI,wBAAwB,CAAC;gBACrC,kBAAkB,EAAE,IAAI;gBACxB,gBAAgB,EAAE,CAAC;gBACnB,kBAAkB,EAAE,SAAS,EAAE,kDAAkD;aAClF,CAAC;SACH,CAAC,CAAC;QACH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE;YAAE,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,YAAY,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5G,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,EAAE,CAAC,CAAC;QAExF,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;QAC/F,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC;QAC1F,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,2CAA2C,CAAC,CAAC;QACnE,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,EAAE,0CAA0C,CAAC,CAAC;QAEtE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;QACpC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,6BAA6B,CAAC,CAAC;QAE7C,0EAA0E;QAC1E,qDAAqD;QACrD,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACnD,MAAM,CAAC,KAAK,CAAC,EAAG,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,4CAA4C,CAAC,CAAC;QAEvF,gEAAgE;QAChE,MAAM,CAAC,GAAG,EAAG,CAAC,SAAS,CAAC;QACxB,MAAM,SAAS,GACb,EAAG,CAAC,IAAI,CAAC,MAAM,GAAG,EAAG,CAAC,IAAI,CAAC,MAAM,GAAG,EAAG,CAAC,SAAS,CAAC,MAAM;YACxD,CAAC,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,EAAG,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,yBAAyB,CAAC,CAAC;QACrE,KAAK,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAU,EAAE,CAAC;YACvD,MAAM,CAAC,EAAE,CAAC,EAAG,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,EAAE,GAAG,CAAC,kDAAkD,CAAC,CAAC;QACxF,CAAC;QAED,iFAAiF;QACjF,MAAM,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,mCAAmC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QAC1G,MAAM,CAAC,EAAE,CAAC,EAAG,CAAC,KAAK,CAAC,MAAM,GAAG,QAAQ,EAAE,oDAAoD,CAAC,CAAC;QAE7F,OAAO,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;QACzF,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC;YACxC,IAAI,EAAE,eAAe;YACrB,QAAQ,EAAE,IAAI,wBAAwB,CAAC;gBACrC,kBAAkB,EAAE,IAAI;gBACxB,gBAAgB,EAAE,CAAC;gBACnB,kBAAkB,EAAE,SAAS;gBAC7B,aAAa,EAAE,CAAC;gBAChB,qBAAqB,EAAE,CAAC,EAAE,wBAAwB;aACnD,CAAC;SACH,CAAC,CAAC;QACH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;YAAE,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,YAAY,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAE3G,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,EAAE,CAAC,CAAC;QAClF,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAE,CAAmC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAClH,MAAM,SAAS,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC;QAErF,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,0BAA0B,CAAC,CAAC;QAC3D,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,EAAE,qDAAqD,CAAC,CAAC;QAElF,uEAAuE;QACvE,wEAAwE;QACxE,uEAAuE;QACvE,6BAA6B;QAC7B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,EAAE,CAAC,CAAC;QACnF,MAAM,SAAS,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAE,CAAmC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACpH,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,QAAQ,EAAE,sDAAsD,CAAC,CAAC;QAE9F,2EAA2E;QAC3E,wEAAwE;QACxE,mDAAmD;QACnD,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC;QACnD,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,EAAE,CAAC,CAAC;QAClF,KAAK,MAAM,KAAK,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;YACnD,MAAM,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;YAC9D,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,gBAAgB,CAAC,CAAC;YACvC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,GAAG,KAAK,kCAAkC,CAAC,CAAC;QACrG,CAAC;QAED,OAAO,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Tests for the live-image policy in AutobiographicalStrategy:
3
+ *
4
+ * (1) maxLiveImages — a hard count ceiling. Only the N most-recent images
5
+ * survive as real image blocks; older ones become text placeholders.
6
+ * (2) imageStripDepthTokens — a depth cutoff. Images deeper than D tokens
7
+ * from the newest message are stripped even though the surrounding text
8
+ * stays verbatim (so text horizon >> image horizon).
9
+ *
10
+ * Stripped images are replaced by "[image dropped from live context]".
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=image-stripping.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-stripping.test.d.ts","sourceRoot":"","sources":["../../test/image-stripping.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Tests for the live-image policy in AutobiographicalStrategy:
3
+ *
4
+ * (1) maxLiveImages — a hard count ceiling. Only the N most-recent images
5
+ * survive as real image blocks; older ones become text placeholders.
6
+ * (2) imageStripDepthTokens — a depth cutoff. Images deeper than D tokens
7
+ * from the newest message are stripped even though the surrounding text
8
+ * stays verbatim (so text horizon >> image horizon).
9
+ *
10
+ * Stripped images are replaced by "[image dropped from live context]".
11
+ */
12
+ import { describe, it, before, after } from 'node:test';
13
+ import assert from 'node:assert';
14
+ import { rmSync, existsSync } from 'node:fs';
15
+ import { ContextManager, AutobiographicalStrategy } from '../src/index.js';
16
+ const TEST_STORE_PATH = './test-image-stripping';
17
+ function cleanup() {
18
+ if (existsSync(TEST_STORE_PATH))
19
+ rmSync(TEST_STORE_PATH, { recursive: true, force: true });
20
+ }
21
+ /** A message carrying one image plus a text label so we can locate it later. */
22
+ function imageMessage(label, tokenEstimate = 1600) {
23
+ return [
24
+ { type: 'image', source: { type: 'base64', data: 'AAAA', mediaType: 'image/png' }, tokenEstimate },
25
+ { type: 'text', text: label },
26
+ ];
27
+ }
28
+ /** Find the compiled entry whose text contains `label`, and report whether it
29
+ * still holds a real image block or was reduced to the placeholder. */
30
+ function imageState(messages, label) {
31
+ const entry = messages.find((m) => m.content.some((b) => b.type === 'text' && b.text.includes(label)));
32
+ if (!entry)
33
+ return 'missing';
34
+ if (entry.content.some((b) => b.type === 'image'))
35
+ return 'image';
36
+ if (entry.content.some((b) => b.type === 'text' && b.text.includes('image dropped from live context')))
37
+ return 'stripped';
38
+ return 'missing';
39
+ }
40
+ describe('Live image policy', () => {
41
+ before(() => cleanup());
42
+ after(() => cleanup());
43
+ it('keeps only the maxLiveImages most-recent images (count cap)', async () => {
44
+ cleanup();
45
+ const strategy = new AutobiographicalStrategy({
46
+ headWindowTokens: 0,
47
+ recentWindowTokens: 1_000_000, // keep everything verbatim
48
+ hierarchical: true,
49
+ maxLiveImages: 2,
50
+ imageStripDepthTokens: 0, // disable depth strip — isolate the count cap
51
+ });
52
+ const manager = await ContextManager.open({ path: TEST_STORE_PATH, strategy });
53
+ for (let i = 1; i <= 4; i++)
54
+ manager.addMessage('user', imageMessage(`img-0${i}`));
55
+ const compiled = await manager.compile({ maxTokens: 1_000_000, reserveForResponse: 0 });
56
+ // Newest two (img-03, img-04) keep their image; older two are stripped.
57
+ assert.equal(imageState(compiled.messages, 'img-04'), 'image', 'newest image kept');
58
+ assert.equal(imageState(compiled.messages, 'img-03'), 'image', '2nd-newest image kept');
59
+ assert.equal(imageState(compiled.messages, 'img-02'), 'stripped', '3rd-newest stripped by count cap');
60
+ assert.equal(imageState(compiled.messages, 'img-01'), 'stripped', 'oldest stripped by count cap');
61
+ manager.close();
62
+ });
63
+ it('strips images deeper than imageStripDepthTokens (depth cutoff)', async () => {
64
+ cleanup();
65
+ const strategy = new AutobiographicalStrategy({
66
+ headWindowTokens: 0,
67
+ recentWindowTokens: 1_000_000, // text horizon stays huge
68
+ hierarchical: true,
69
+ maxLiveImages: 0, // unlimited count — isolate the depth cutoff
70
+ imageStripDepthTokens: 3500, // ~2 images (1600 each) fit within the window
71
+ });
72
+ const manager = await ContextManager.open({ path: TEST_STORE_PATH, strategy });
73
+ for (let i = 1; i <= 4; i++)
74
+ manager.addMessage('user', imageMessage(`img-0${i}`));
75
+ const compiled = await manager.compile({ maxTokens: 1_000_000, reserveForResponse: 0 });
76
+ // Newest fits inside the depth window; the oldest is well beyond it.
77
+ assert.equal(imageState(compiled.messages, 'img-04'), 'image', 'newest image within depth window');
78
+ assert.equal(imageState(compiled.messages, 'img-01'), 'stripped', 'oldest image beyond depth window');
79
+ // But the text of the stripped message is still present verbatim (text
80
+ // horizon is independent of the image horizon).
81
+ const oldestText = compiled.messages.find((m) => m.content.some((b) => b.type === 'text' && b.text.includes('img-01')));
82
+ assert.ok(oldestText, 'oldest message text survives even though its image was stripped');
83
+ manager.close();
84
+ });
85
+ it('leaves images untouched when the policy is disabled', async () => {
86
+ cleanup();
87
+ const strategy = new AutobiographicalStrategy({
88
+ headWindowTokens: 0,
89
+ recentWindowTokens: 1_000_000,
90
+ hierarchical: true,
91
+ maxLiveImages: 0,
92
+ imageStripDepthTokens: 0,
93
+ });
94
+ const manager = await ContextManager.open({ path: TEST_STORE_PATH, strategy });
95
+ for (let i = 1; i <= 3; i++)
96
+ manager.addMessage('user', imageMessage(`img-0${i}`));
97
+ const compiled = await manager.compile({ maxTokens: 1_000_000, reserveForResponse: 0 });
98
+ for (const label of ['img-01', 'img-02', 'img-03']) {
99
+ assert.equal(imageState(compiled.messages, label), 'image', `${label} kept when policy disabled`);
100
+ }
101
+ manager.close();
102
+ });
103
+ });
104
+ //# sourceMappingURL=image-stripping.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-stripping.test.js","sourceRoot":"","sources":["../../test/image-stripping.test.ts"],"names":[],"mappings":"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"}
@@ -160,5 +160,45 @@ describe('AutobiographicalStrategy — pins / documents (gap #3)', () => {
160
160
  assert.ok(!mainPins.some(p => p.id === forkPin), 'main must NOT see the fork-only pin');
161
161
  manager.close();
162
162
  });
163
+ // ---- V2 dynamic pins: pin-at-level-k / pin-max-level (additive, opt-in) ----
164
+ it('pinAtLevel / level / maxLevel round-trip through listPins and validate', async () => {
165
+ const strategy = new TestableStrategy({ headWindowTokens: 0, recentWindowTokens: 5 });
166
+ const manager = await ContextManager.open({ path: TEST_STORE_PATH, strategy });
167
+ const m1 = manager.addMessage('user', textBlock('fix me at L2'));
168
+ const m2 = manager.addMessage('user', textBlock('cap me at L1'));
169
+ manager.addMessage('user', textBlock('latest'));
170
+ const atId = manager.pinAtLevel(m1, m1, 2, { name: 'at-2' });
171
+ const capId = manager.pinRange(m2, m2, { maxLevel: 1 });
172
+ // Invalid bounds are dropped (a classic raw pin), not persisted as junk.
173
+ const rawId = manager.markDocument(m2, { level: -3 });
174
+ const byId = new Map(manager.listPins().map((p) => [p.id, p]));
175
+ assert.equal(byId.get(atId)?.level, 2, 'pin-at-level stores level');
176
+ assert.equal(byId.get(atId)?.maxLevel, undefined, 'level suppresses maxLevel');
177
+ assert.equal(byId.get(capId)?.maxLevel, 1, 'pin-max-level stores maxLevel');
178
+ assert.equal(byId.get(capId)?.level, undefined, 'no fixed level on a cap pin');
179
+ assert.equal(byId.get(rawId)?.level, undefined, 'invalid level dropped → classic pin');
180
+ assert.equal(byId.get(rawId)?.maxLevel, undefined, 'invalid level dropped → classic pin');
181
+ manager.close();
182
+ });
183
+ it('level bound survives close/reopen', async () => {
184
+ let atId;
185
+ {
186
+ const strategy = new TestableStrategy({ headWindowTokens: 0, recentWindowTokens: 5 });
187
+ const manager = await ContextManager.open({ path: TEST_STORE_PATH, strategy });
188
+ const m1 = manager.addMessage('user', textBlock('survive at L3'));
189
+ manager.addMessage('user', textBlock('latest'));
190
+ atId = manager.pinAtLevel(m1, m1, 3);
191
+ manager.sync();
192
+ manager.close();
193
+ }
194
+ {
195
+ const strategy = new TestableStrategy({ headWindowTokens: 0, recentWindowTokens: 5 });
196
+ const manager = await ContextManager.open({ path: TEST_STORE_PATH, strategy });
197
+ const pin = manager.listPins().find((p) => p.id === atId);
198
+ assert.ok(pin, 'leveled pin reloads');
199
+ assert.equal(pin.level, 3, 'level bound persisted across reopen');
200
+ manager.close();
201
+ }
202
+ });
163
203
  });
164
204
  //# sourceMappingURL=pins.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pins.test.js","sourceRoot":"","sources":["../../test/pins.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pins.test.js","sourceRoot":"","sources":["../../test/pins.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=render-stats.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-stats.test.d.ts","sourceRoot":"","sources":["../../test/render-stats.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * getRenderStats must INSPECT what select() actually rendered, not RECONSTRUCT
3
+ * a hierarchical view. Regression for the adaptive-resolution case where the
4
+ * reconstructed pyramid (head/tail windows + every live summary) bore no
5
+ * relation to the folded output — and had no bucket at all for raw messages the
6
+ * picker kept verbatim in the middle.
7
+ */
8
+ import { describe, it, before, after, beforeEach } from 'node:test';
9
+ import assert from 'node:assert';
10
+ import { rmSync, existsSync } from 'node:fs';
11
+ import { ContextManager, AutobiographicalStrategy } from '../src/index.js';
12
+ const TEST_STORE_PATH = './test-render-stats';
13
+ function cleanup() {
14
+ if (existsSync(TEST_STORE_PATH))
15
+ rmSync(TEST_STORE_PATH, { recursive: true, force: true });
16
+ }
17
+ function text(t) {
18
+ return [{ type: 'text', text: t }];
19
+ }
20
+ function assertConsistent(rs) {
21
+ const s = rs.summaries;
22
+ const sumTokens = rs.head.tokens + rs.tail.tokens + rs.middleRaw.tokens +
23
+ s.l1.tokens + s.l2.tokens + s.l3.tokens;
24
+ assert.strictEqual(rs.total.tokens, sumTokens, 'total.tokens === sum of bucket tokens');
25
+ const sumMsgs = rs.head.messages + rs.tail.messages + rs.middleRaw.messages +
26
+ (s.l1.count + s.l2.count + s.l3.count) * 2;
27
+ assert.strictEqual(rs.total.messages, sumMsgs, 'total.messages === sum of bucket messages');
28
+ }
29
+ describe('getRenderStats — inspect, not reconstruct', () => {
30
+ before(cleanup);
31
+ after(cleanup);
32
+ beforeEach(cleanup);
33
+ it('reflects the actually-rendered raw conversation (every message accounted for once)', async () => {
34
+ const manager = await ContextManager.open({
35
+ path: TEST_STORE_PATH,
36
+ strategy: new AutobiographicalStrategy({ adaptiveResolution: true }),
37
+ });
38
+ const N = 8;
39
+ for (let i = 0; i < N; i++) {
40
+ manager.addMessage(i % 2 ? 'lena' : 'user', text(`message ${i} ${'x'.repeat(20)}`));
41
+ }
42
+ await manager.compile();
43
+ const rs = manager.getRenderStats();
44
+ assert.ok(rs, 'stats present after compile');
45
+ assertConsistent(rs);
46
+ // Small conversation, no membrane => no compression => no summaries.
47
+ assert.strictEqual(rs.summaries.l1.count + rs.summaries.l2.count + rs.summaries.l3.count, 0, 'no summaries for a small raw conversation');
48
+ const rawMsgs = rs.head.messages + rs.tail.messages + rs.middleRaw.messages;
49
+ assert.strictEqual(rawMsgs, N, 'every raw message accounted for exactly once');
50
+ assert.ok(rs.total.tokens > 0, 'non-zero rendered tokens');
51
+ manager.close();
52
+ });
53
+ it('populates middleRaw for mid-conversation messages the picker keeps verbatim', async () => {
54
+ // Small head/recent windows push most messages into the MIDDLE region; with
55
+ // no summaries to fold into, the picker keeps them raw — which the old
56
+ // reconstruction would have reported as 0 middle / all-pyramid.
57
+ const manager = await ContextManager.open({
58
+ path: TEST_STORE_PATH,
59
+ strategy: new AutobiographicalStrategy({
60
+ adaptiveResolution: true,
61
+ headWindowTokens: 100,
62
+ recentWindowTokens: 100,
63
+ }),
64
+ });
65
+ const N = 20;
66
+ for (let i = 0; i < N; i++) {
67
+ manager.addMessage(i % 2 ? 'lena' : 'user', text(`msg ${i} ${'y'.repeat(40)}`));
68
+ }
69
+ // Generous budget so nothing is evicted (and the picker doesn't go over-budget).
70
+ await manager.compile({ maxTokens: 100_000, reserveForResponse: 1_000 });
71
+ const rs = manager.getRenderStats();
72
+ assert.ok(rs, 'stats present');
73
+ assertConsistent(rs);
74
+ assert.ok(rs.middleRaw.messages > 0, 'middle messages kept raw by the picker must show up in middleRaw (inspect, not reconstruct)');
75
+ const rawMsgs = rs.head.messages + rs.tail.messages + rs.middleRaw.messages;
76
+ assert.strictEqual(rawMsgs, N, 'all raw, all accounted for');
77
+ manager.close();
78
+ });
79
+ it('returns a non-null shape (with the new fields) before any compile', async () => {
80
+ const manager = await ContextManager.open({
81
+ path: TEST_STORE_PATH,
82
+ strategy: new AutobiographicalStrategy({ adaptiveResolution: true }),
83
+ });
84
+ manager.addMessage('user', text('hi'));
85
+ const rs = manager.getRenderStats(); // no compile yet -> reconstruction fallback
86
+ assert.ok(rs, 'fallback stats present');
87
+ assert.ok(rs.middleRaw && rs.total, 'fallback includes middleRaw + total');
88
+ manager.close();
89
+ });
90
+ });
91
+ //# sourceMappingURL=render-stats.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-stats.test.js","sourceRoot":"","sources":["../../test/render-stats.test.ts"],"names":[],"mappings":"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"}
@@ -7,9 +7,15 @@
7
7
  * speculatively-built L1s before there was any real budget pressure.
8
8
  *
9
9
  * Post-fix:
10
- * - `maxSpeculativeL1s` caps the count of (unmerged L1s + queued chunks).
11
- * When at cap, `onNewMessage` defers auto-tick — chunks still queue,
12
- * but compression doesn't fire until an explicit tick() / compile().
10
+ * - `maxSpeculativeL1s` caps the count of *produced, unmerged* L1 summaries.
11
+ * When at cap, `onNewMessage` defers auto-tick L1 production — chunks still
12
+ * queue, but compression doesn't fire until merges bring the unmerged count
13
+ * back under the cap (or an explicit tick() / compile()).
14
+ * - The cap does NOT count the pending compression backlog and does NOT gate
15
+ * merges: merges consolidate L1s into L_{k+1} and REDUCE the unmerged count,
16
+ * so gating them would deadlock (too many unmerged L1s blocks the merges that
17
+ * would relieve the cap, and a large backlog blocks the compression that
18
+ * would drain it). See the "does not deadlock" regression suite below.
13
19
  * - `shouldCompressPreflight()` is overridable so subclasses can add
14
20
  * custom predictive scheduling.
15
21
  */
@@ -1 +1 @@
1
- {"version":3,"file":"speculation-cap.test.d.ts","sourceRoot":"","sources":["../../test/speculation-cap.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
1
+ {"version":3,"file":"speculation-cap.test.d.ts","sourceRoot":"","sources":["../../test/speculation-cap.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG"}