sliding-context 0.3.0

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 (54) hide show
  1. package/README.md +245 -0
  2. package/dist/__tests__/context.test.d.ts +2 -0
  3. package/dist/__tests__/context.test.d.ts.map +1 -0
  4. package/dist/__tests__/context.test.js +441 -0
  5. package/dist/__tests__/context.test.js.map +1 -0
  6. package/dist/__tests__/fixtures/messages.d.ts +9 -0
  7. package/dist/__tests__/fixtures/messages.d.ts.map +1 -0
  8. package/dist/__tests__/fixtures/messages.js +44 -0
  9. package/dist/__tests__/fixtures/messages.js.map +1 -0
  10. package/dist/__tests__/token-counter.test.d.ts +2 -0
  11. package/dist/__tests__/token-counter.test.d.ts.map +1 -0
  12. package/dist/__tests__/token-counter.test.js +123 -0
  13. package/dist/__tests__/token-counter.test.js.map +1 -0
  14. package/dist/__tests__/types.test.d.ts +2 -0
  15. package/dist/__tests__/types.test.d.ts.map +1 -0
  16. package/dist/__tests__/types.test.js +92 -0
  17. package/dist/__tests__/types.test.js.map +1 -0
  18. package/dist/budget.d.ts +16 -0
  19. package/dist/budget.d.ts.map +1 -0
  20. package/dist/budget.js +31 -0
  21. package/dist/budget.js.map +1 -0
  22. package/dist/context.d.ts +16 -0
  23. package/dist/context.d.ts.map +1 -0
  24. package/dist/context.js +245 -0
  25. package/dist/context.js.map +1 -0
  26. package/dist/eviction.d.ts +14 -0
  27. package/dist/eviction.d.ts.map +1 -0
  28. package/dist/eviction.js +78 -0
  29. package/dist/eviction.js.map +1 -0
  30. package/dist/index.d.ts +9 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +23 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/prompt.d.ts +6 -0
  35. package/dist/prompt.d.ts.map +1 -0
  36. package/dist/prompt.js +28 -0
  37. package/dist/prompt.js.map +1 -0
  38. package/dist/serialization.d.ts +12 -0
  39. package/dist/serialization.d.ts.map +1 -0
  40. package/dist/serialization.js +33 -0
  41. package/dist/serialization.js.map +1 -0
  42. package/dist/summarization.d.ts +13 -0
  43. package/dist/summarization.d.ts.map +1 -0
  44. package/dist/summarization.js +23 -0
  45. package/dist/summarization.js.map +1 -0
  46. package/dist/token-counter.d.ts +7 -0
  47. package/dist/token-counter.d.ts.map +1 -0
  48. package/dist/token-counter.js +41 -0
  49. package/dist/token-counter.js.map +1 -0
  50. package/dist/types.d.ts +72 -0
  51. package/dist/types.d.ts.map +1 -0
  52. package/dist/types.js +3 -0
  53. package/dist/types.js.map +1 -0
  54. package/package.json +33 -0
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const token_counter_1 = require("../token-counter");
5
+ (0, vitest_1.describe)('approximateTokenCounter', () => {
6
+ (0, vitest_1.it)('returns 0 for empty string', () => {
7
+ (0, vitest_1.expect)((0, token_counter_1.approximateTokenCounter)('')).toBe(0);
8
+ });
9
+ (0, vitest_1.it)('returns 1 for single character (ceil(1/4))', () => {
10
+ (0, vitest_1.expect)((0, token_counter_1.approximateTokenCounter)('a')).toBe(1);
11
+ });
12
+ (0, vitest_1.it)('returns 1 for exactly 4 characters', () => {
13
+ (0, vitest_1.expect)((0, token_counter_1.approximateTokenCounter)('abcd')).toBe(1);
14
+ });
15
+ (0, vitest_1.it)('returns 2 for 5 characters (ceil(5/4))', () => {
16
+ (0, vitest_1.expect)((0, token_counter_1.approximateTokenCounter)('abcde')).toBe(2);
17
+ });
18
+ (0, vitest_1.it)('returns 25 for 100-character string', () => {
19
+ const str = 'a'.repeat(100);
20
+ (0, vitest_1.expect)((0, token_counter_1.approximateTokenCounter)(str)).toBe(25);
21
+ });
22
+ });
23
+ (0, vitest_1.describe)('DEFAULT_MESSAGE_OVERHEAD', () => {
24
+ (0, vitest_1.it)('is 4', () => {
25
+ (0, vitest_1.expect)(token_counter_1.DEFAULT_MESSAGE_OVERHEAD).toBe(4);
26
+ });
27
+ });
28
+ (0, vitest_1.describe)('countMessageTokens', () => {
29
+ (0, vitest_1.it)('counts basic string content plus overhead', () => {
30
+ const message = { role: 'user', content: 'abcd' }; // 1 token
31
+ const result = (0, token_counter_1.countMessageTokens)(message, token_counter_1.approximateTokenCounter, 4);
32
+ (0, vitest_1.expect)(result).toBe(1 + 4); // 5
33
+ });
34
+ (0, vitest_1.it)('returns messageOverhead for empty content', () => {
35
+ const message = { role: 'user', content: '' };
36
+ const result = (0, token_counter_1.countMessageTokens)(message, token_counter_1.approximateTokenCounter, 4);
37
+ (0, vitest_1.expect)(result).toBe(4);
38
+ });
39
+ (0, vitest_1.it)('adds tool_calls JSON token cost', () => {
40
+ const message = {
41
+ role: 'assistant',
42
+ content: '',
43
+ tool_calls: [
44
+ {
45
+ id: 'call_1',
46
+ type: 'function',
47
+ function: { name: 'fn', arguments: '{}' },
48
+ },
49
+ ],
50
+ };
51
+ const toolCallsJson = JSON.stringify(message.tool_calls);
52
+ const expectedToolTokens = (0, token_counter_1.approximateTokenCounter)(toolCallsJson);
53
+ const result = (0, token_counter_1.countMessageTokens)(message, token_counter_1.approximateTokenCounter, 4);
54
+ (0, vitest_1.expect)(result).toBe(0 + expectedToolTokens + 4);
55
+ });
56
+ (0, vitest_1.it)('adds tool_call_id token cost', () => {
57
+ const message = {
58
+ role: 'tool',
59
+ content: 'result',
60
+ tool_call_id: 'call_abc123',
61
+ };
62
+ const contentTokens = (0, token_counter_1.approximateTokenCounter)('result'); // ceil(6/4) = 2
63
+ const idTokens = (0, token_counter_1.approximateTokenCounter)('call_abc123'); // ceil(11/4) = 3
64
+ const result = (0, token_counter_1.countMessageTokens)(message, token_counter_1.approximateTokenCounter, 4);
65
+ (0, vitest_1.expect)(result).toBe(contentTokens + idTokens + 4);
66
+ });
67
+ (0, vitest_1.it)('uses custom tokenCounter', () => {
68
+ const mockCounter = vitest_1.vi.fn().mockReturnValue(10);
69
+ const message = { role: 'user', content: 'hello world' };
70
+ const result = (0, token_counter_1.countMessageTokens)(message, mockCounter, 2);
71
+ (0, vitest_1.expect)(mockCounter).toHaveBeenCalledWith('hello world');
72
+ (0, vitest_1.expect)(result).toBe(10 + 2);
73
+ });
74
+ (0, vitest_1.it)('uses custom tokenCounter with tool_calls and tool_call_id', () => {
75
+ const mockCounter = vitest_1.vi.fn().mockReturnValue(5);
76
+ const message = {
77
+ role: 'tool',
78
+ content: 'some result',
79
+ tool_call_id: 'call_xyz',
80
+ };
81
+ // Called twice: once for content, once for tool_call_id
82
+ const result = (0, token_counter_1.countMessageTokens)(message, mockCounter, 3);
83
+ (0, vitest_1.expect)(mockCounter).toHaveBeenCalledTimes(2);
84
+ (0, vitest_1.expect)(result).toBe(5 + 5 + 3); // content + id + overhead
85
+ });
86
+ (0, vitest_1.it)('handles array content: text parts summed, image parts use IMAGE_TOKEN_COST', () => {
87
+ // Simulate array content by casting through unknown
88
+ const imageTokenCost = 85;
89
+ const arrayContent = [
90
+ { type: 'text', text: 'abcd' }, // ceil(4/4) = 1 token
91
+ { type: 'image_url', url: 'http://example.com/img.png' }, // 85 tokens
92
+ { type: 'text', text: 'efgh' }, // ceil(4/4) = 1 token
93
+ ];
94
+ const message = {
95
+ role: 'user',
96
+ content: arrayContent,
97
+ };
98
+ const result = (0, token_counter_1.countMessageTokens)(message, token_counter_1.approximateTokenCounter, 4);
99
+ (0, vitest_1.expect)(result).toBe(1 + imageTokenCost + 1 + 4); // 91
100
+ });
101
+ (0, vitest_1.it)('handles array content with only text parts', () => {
102
+ const arrayContent = [
103
+ { type: 'text', text: 'hello' }, // ceil(5/4) = 2
104
+ { type: 'text', text: 'world' }, // ceil(5/4) = 2
105
+ ];
106
+ const message = {
107
+ role: 'user',
108
+ content: arrayContent,
109
+ };
110
+ const result = (0, token_counter_1.countMessageTokens)(message, token_counter_1.approximateTokenCounter, 4);
111
+ (0, vitest_1.expect)(result).toBe(2 + 2 + 4); // 8
112
+ });
113
+ (0, vitest_1.it)('handles array content with undefined type (treated as text)', () => {
114
+ const arrayContent = [{ text: 'abcdefgh' }]; // ceil(8/4) = 2
115
+ const message = {
116
+ role: 'user',
117
+ content: arrayContent,
118
+ };
119
+ const result = (0, token_counter_1.countMessageTokens)(message, token_counter_1.approximateTokenCounter, 4);
120
+ (0, vitest_1.expect)(result).toBe(2 + 4); // 6
121
+ });
122
+ });
123
+ //# sourceMappingURL=token-counter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-counter.test.js","sourceRoot":"","sources":["../../src/__tests__/token-counter.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/types.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ (0, vitest_1.describe)('types', () => {
5
+ (0, vitest_1.describe)('Message', () => {
6
+ (0, vitest_1.it)('accepts role: system', () => {
7
+ const msg = { role: 'system', content: 'You are helpful.' };
8
+ (0, vitest_1.expect)(msg.role).toBe('system');
9
+ (0, vitest_1.expect)(msg.content).toBe('You are helpful.');
10
+ });
11
+ (0, vitest_1.it)('accepts role: user', () => {
12
+ const msg = { role: 'user', content: 'Hello' };
13
+ (0, vitest_1.expect)(msg.role).toBe('user');
14
+ });
15
+ (0, vitest_1.it)('accepts role: assistant', () => {
16
+ const msg = { role: 'assistant', content: 'Hi!' };
17
+ (0, vitest_1.expect)(msg.role).toBe('assistant');
18
+ });
19
+ (0, vitest_1.it)('accepts role: tool', () => {
20
+ const msg = { role: 'tool', content: 'result data', tool_call_id: 'call_1' };
21
+ (0, vitest_1.expect)(msg.role).toBe('tool');
22
+ (0, vitest_1.expect)(msg.tool_call_id).toBe('call_1');
23
+ });
24
+ (0, vitest_1.it)('accepts optional tool_calls', () => {
25
+ const msg = {
26
+ role: 'assistant',
27
+ content: '',
28
+ tool_calls: [
29
+ { id: 'call_1', type: 'function', function: { name: 'fn', arguments: '{}' } },
30
+ ],
31
+ };
32
+ (0, vitest_1.expect)(msg.tool_calls).toHaveLength(1);
33
+ });
34
+ (0, vitest_1.it)('accepts optional name field', () => {
35
+ const msg = { role: 'user', content: 'hi', name: 'alice' };
36
+ (0, vitest_1.expect)(msg.name).toBe('alice');
37
+ });
38
+ });
39
+ (0, vitest_1.describe)('ToolCall', () => {
40
+ (0, vitest_1.it)('has correct shape', () => {
41
+ const tc = {
42
+ id: 'call_xyz',
43
+ type: 'function',
44
+ function: { name: 'search', arguments: '{"q":"test"}' },
45
+ };
46
+ (0, vitest_1.expect)(tc.id).toBe('call_xyz');
47
+ (0, vitest_1.expect)(tc.type).toBe('function');
48
+ (0, vitest_1.expect)(tc.function.name).toBe('search');
49
+ (0, vitest_1.expect)(tc.function.arguments).toBe('{"q":"test"}');
50
+ });
51
+ });
52
+ (0, vitest_1.describe)('SlidingContextOptions', () => {
53
+ (0, vitest_1.it)('requires only tokenBudget', () => {
54
+ const opts = { tokenBudget: 4096 };
55
+ (0, vitest_1.expect)(opts.tokenBudget).toBe(4096);
56
+ });
57
+ (0, vitest_1.it)('accepts all optional fields', () => {
58
+ const opts = {
59
+ tokenBudget: 8192,
60
+ systemPrompt: 'Be helpful',
61
+ strategy: 'incremental',
62
+ maxSummaryTokens: 512,
63
+ minRecentTokens: 256,
64
+ summarizeThresholdTokens: 3000,
65
+ summarizeThresholdMessages: 10,
66
+ messageOverhead: 4,
67
+ summaryRole: 'system',
68
+ maxSummaryRounds: 3,
69
+ maxAnchorTokens: 1024,
70
+ };
71
+ (0, vitest_1.expect)(opts.tokenBudget).toBe(8192);
72
+ (0, vitest_1.expect)(opts.strategy).toBe('incremental');
73
+ (0, vitest_1.expect)(opts.summaryRole).toBe('system');
74
+ });
75
+ });
76
+ (0, vitest_1.describe)('ContextState', () => {
77
+ (0, vitest_1.it)('version is literal 1', () => {
78
+ const state = {
79
+ options: { tokenBudget: 4096 },
80
+ messages: [],
81
+ summary: undefined,
82
+ anchor: [],
83
+ pendingBuffer: [],
84
+ summaryRounds: 0,
85
+ tokenCounts: {},
86
+ version: 1,
87
+ };
88
+ (0, vitest_1.expect)(state.version).toBe(1);
89
+ });
90
+ });
91
+ });
92
+ //# sourceMappingURL=types.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.test.js","sourceRoot":"","sources":["../../src/__tests__/types.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { SlidingContextOptions } from './types';
2
+ export interface BudgetAllocation {
3
+ systemTokens: number;
4
+ summaryTokens: number;
5
+ recentTokens: number;
6
+ }
7
+ /**
8
+ * Allocate token budget across the three context zones.
9
+ *
10
+ * Priority order:
11
+ * 1. System tokens (fixed — caller provides actual count)
12
+ * 2. Summary tokens (capped at maxSummaryTokens; 0 if no summarizer)
13
+ * 3. Recent tokens (remainder, enforcing minRecentTokens)
14
+ */
15
+ export declare function allocateBudget(options: SlidingContextOptions, systemTokensUsed: number): BudgetAllocation;
16
+ //# sourceMappingURL=budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAErD,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,qBAAqB,EAC9B,gBAAgB,EAAE,MAAM,GACvB,gBAAgB,CA4BlB"}
package/dist/budget.js ADDED
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.allocateBudget = allocateBudget;
4
+ /**
5
+ * Allocate token budget across the three context zones.
6
+ *
7
+ * Priority order:
8
+ * 1. System tokens (fixed — caller provides actual count)
9
+ * 2. Summary tokens (capped at maxSummaryTokens; 0 if no summarizer)
10
+ * 3. Recent tokens (remainder, enforcing minRecentTokens)
11
+ */
12
+ function allocateBudget(options, systemTokensUsed) {
13
+ const total = options.tokenBudget;
14
+ const afterSystem = Math.max(0, total - systemTokensUsed);
15
+ const hasSummarizer = typeof options.summarizer === 'function';
16
+ const defaultMaxSummary = Math.floor(total * 0.3);
17
+ const maxSummaryTokens = hasSummarizer
18
+ ? (options.maxSummaryTokens ?? defaultMaxSummary)
19
+ : 0;
20
+ const defaultMinRecent = Math.floor(total * 0.3);
21
+ const minRecentTokens = options.minRecentTokens ?? defaultMinRecent;
22
+ // How much can summary actually use?
23
+ const summaryTokens = Math.min(maxSummaryTokens, Math.max(0, afterSystem - minRecentTokens));
24
+ const recentTokens = Math.max(0, afterSystem - summaryTokens);
25
+ return {
26
+ systemTokens: systemTokensUsed,
27
+ summaryTokens,
28
+ recentTokens,
29
+ };
30
+ }
31
+ //# sourceMappingURL=budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.js","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":";;AAgBA,wCA+BC;AAvCD;;;;;;;GAOG;AACH,SAAgB,cAAc,CAC5B,OAA8B,EAC9B,gBAAwB;IAExB,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC;IAElC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,gBAAgB,CAAC,CAAC;IAE1D,MAAM,aAAa,GAAG,OAAO,OAAO,CAAC,UAAU,KAAK,UAAU,CAAC;IAE/D,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC;IAClD,MAAM,gBAAgB,GAAG,aAAa;QACpC,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,IAAI,iBAAiB,CAAC;QACjD,CAAC,CAAC,CAAC,CAAC;IAEN,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC;IACjD,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,gBAAgB,CAAC;IAEpE,qCAAqC;IACrC,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAC5B,gBAAgB,EAChB,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,eAAe,CAAC,CAC3C,CAAC;IAEF,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,aAAa,CAAC,CAAC;IAE9D,OAAO;QACL,YAAY,EAAE,gBAAgB;QAC9B,aAAa;QACb,YAAY;KACb,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { SlidingContextOptions, SlidingContext } from './types';
2
+ /**
3
+ * Create a new SlidingContext instance.
4
+ */
5
+ export declare function createSlidingContext(options: SlidingContextOptions): SlidingContext;
6
+ /**
7
+ * Serialize a SlidingContext's state to a JSON string suitable for storage.
8
+ */
9
+ export declare function serializeContext(ctx: SlidingContext): string;
10
+ /**
11
+ * Restore a SlidingContext from a JSON string produced by `serializeContext()`.
12
+ * Re-supply function-valued options (summarizer, tokenCounter, hooks) since
13
+ * they cannot be serialized.
14
+ */
15
+ export declare function restoreSlidingContext(data: string, options: SlidingContextOptions): SlidingContext;
16
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,qBAAqB,EAErB,cAAc,EACf,MAAM,SAAS,CAAC;AAmSjB;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,cAAc,CAEnF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,qBAAqB,GAC7B,cAAc,CAGhB"}
@@ -0,0 +1,245 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSlidingContext = createSlidingContext;
4
+ exports.serializeContext = serializeContext;
5
+ exports.restoreSlidingContext = restoreSlidingContext;
6
+ const token_counter_1 = require("./token-counter");
7
+ const eviction_1 = require("./eviction");
8
+ const budget_1 = require("./budget");
9
+ const summarization_1 = require("./summarization");
10
+ const serialization_1 = require("./serialization");
11
+ // ---------------------------------------------------------------------------
12
+ // Shared helpers
13
+ // ---------------------------------------------------------------------------
14
+ function msgTokens(message, opts) {
15
+ const counter = opts.tokenCounter ?? token_counter_1.approximateTokenCounter;
16
+ const overhead = opts.messageOverhead ?? token_counter_1.DEFAULT_MESSAGE_OVERHEAD;
17
+ return (0, token_counter_1.countMessageTokens)(message, counter, overhead);
18
+ }
19
+ function listTokens(messages, opts) {
20
+ return messages.reduce((sum, m) => sum + msgTokens(m, opts), 0);
21
+ }
22
+ // ---------------------------------------------------------------------------
23
+ // Core factory (accepts optional initial state for restore path)
24
+ // ---------------------------------------------------------------------------
25
+ function createWithState(options, initialState) {
26
+ if (!Number.isFinite(options.tokenBudget) || options.tokenBudget < 100) {
27
+ throw new RangeError(`sliding-context: tokenBudget must be a finite number >= 100, got ${options.tokenBudget}`);
28
+ }
29
+ // ---------------------------------------------------------------------------
30
+ // Mutable state
31
+ // ---------------------------------------------------------------------------
32
+ let tokenBudget = options.tokenBudget;
33
+ const systemMessage = options.systemPrompt
34
+ ? { role: 'system', content: options.systemPrompt }
35
+ : null;
36
+ let anchorMessages = initialState
37
+ ? initialState.anchor.slice()
38
+ : options.anchor
39
+ ? options.anchor.slice()
40
+ : [];
41
+ let currentSummary = initialState?.summary;
42
+ let recentMessages = initialState ? initialState.messages.slice() : [];
43
+ let pendingBuffer = initialState ? initialState.pendingBuffer.slice() : [];
44
+ let summaryRounds = initialState?.summaryRounds ?? 0;
45
+ // ---------------------------------------------------------------------------
46
+ // Token accessors
47
+ // ---------------------------------------------------------------------------
48
+ function effectiveOpts() {
49
+ return { ...options, tokenBudget };
50
+ }
51
+ function sysTokens() {
52
+ return systemMessage ? msgTokens(systemMessage, effectiveOpts()) : 0;
53
+ }
54
+ function ancTokens() {
55
+ return listTokens(anchorMessages, effectiveOpts());
56
+ }
57
+ function sumTokens() {
58
+ if (currentSummary === undefined)
59
+ return 0;
60
+ return msgTokens({ role: options.summaryRole ?? 'system', content: currentSummary }, effectiveOpts());
61
+ }
62
+ function recTokens() {
63
+ return listTokens(recentMessages, effectiveOpts());
64
+ }
65
+ function pendTokens() {
66
+ return listTokens(pendingBuffer, effectiveOpts());
67
+ }
68
+ // ---------------------------------------------------------------------------
69
+ // Summarization
70
+ // ---------------------------------------------------------------------------
71
+ async function triggerSummarization() {
72
+ const { summarizer } = options;
73
+ if (!summarizer || pendingBuffer.length === 0)
74
+ return;
75
+ const maxRounds = options.maxSummaryRounds ?? 5;
76
+ if (summaryRounds >= maxRounds)
77
+ return;
78
+ const startMs = Date.now();
79
+ const toSummarize = pendingBuffer.slice();
80
+ const existingSummary = currentSummary;
81
+ const newSummary = await (0, summarization_1.runSummarizer)(toSummarize, summarizer, existingSummary);
82
+ if (newSummary === null)
83
+ return;
84
+ summaryRounds += 1;
85
+ if (options.hooks?.onSummarize) {
86
+ options.hooks.onSummarize(toSummarize, existingSummary, newSummary, Date.now() - startMs);
87
+ }
88
+ if (existingSummary !== undefined && options.hooks?.onSummaryCompressed) {
89
+ options.hooks.onSummaryCompressed(existingSummary, newSummary);
90
+ }
91
+ currentSummary = newSummary;
92
+ pendingBuffer = [];
93
+ }
94
+ // ---------------------------------------------------------------------------
95
+ // Budget enforcement
96
+ // ---------------------------------------------------------------------------
97
+ async function enforceBudget() {
98
+ const opts = effectiveOpts();
99
+ const counter = opts.tokenCounter ?? token_counter_1.approximateTokenCounter;
100
+ const overhead = opts.messageOverhead ?? token_counter_1.DEFAULT_MESSAGE_OVERHEAD;
101
+ const allocation = (0, budget_1.allocateBudget)(opts, sysTokens() + ancTokens() + sumTokens());
102
+ const targetRecent = allocation.recentTokens;
103
+ if (recTokens() <= targetRecent)
104
+ return;
105
+ if (options.hooks?.onBudgetExceeded) {
106
+ const total = sysTokens() + ancTokens() + sumTokens() + recTokens() + pendTokens();
107
+ options.hooks.onBudgetExceeded(total, tokenBudget);
108
+ }
109
+ const { evicted, remaining } = (0, eviction_1.evictMessages)(recentMessages, targetRecent, counter, overhead);
110
+ if (evicted.length > 0) {
111
+ recentMessages = remaining;
112
+ pendingBuffer = [...pendingBuffer, ...evicted];
113
+ if (options.hooks?.onEvict)
114
+ options.hooks.onEvict(evicted, 'budget');
115
+ }
116
+ const thresholdTokens = opts.summarizeThresholdTokens ?? Math.floor(tokenBudget * 0.1);
117
+ const thresholdMessages = opts.summarizeThresholdMessages ?? 6;
118
+ if (pendingBuffer.length >= thresholdMessages ||
119
+ pendTokens() >= thresholdTokens) {
120
+ await triggerSummarization();
121
+ }
122
+ }
123
+ // ---------------------------------------------------------------------------
124
+ // Public API
125
+ // ---------------------------------------------------------------------------
126
+ async function addMessage(message) {
127
+ recentMessages.push(message);
128
+ await enforceBudget();
129
+ }
130
+ function getMessages() {
131
+ const result = [];
132
+ if (systemMessage)
133
+ result.push(systemMessage);
134
+ if (anchorMessages.length > 0)
135
+ result.push(...anchorMessages);
136
+ // Pending messages are older than recent — include before summary/recent.
137
+ if (pendingBuffer.length > 0)
138
+ result.push(...pendingBuffer);
139
+ if (currentSummary !== undefined) {
140
+ result.push({ role: options.summaryRole ?? 'system', content: currentSummary });
141
+ }
142
+ result.push(...recentMessages);
143
+ return result;
144
+ }
145
+ function getSummary() {
146
+ return currentSummary;
147
+ }
148
+ function getTokenCount() {
149
+ return sysTokens() + ancTokens() + sumTokens() + recTokens() + pendTokens();
150
+ }
151
+ function getTokenBreakdown() {
152
+ const system = sysTokens();
153
+ const anchor = ancTokens();
154
+ const summary = sumTokens();
155
+ const recent = recTokens() + pendTokens();
156
+ return { system, anchor, summary, recent, total: system + anchor + summary + recent };
157
+ }
158
+ function getRecentMessageCount() {
159
+ return recentMessages.length + pendingBuffer.length;
160
+ }
161
+ function getTotalMessageCount() {
162
+ let count = recentMessages.length + pendingBuffer.length;
163
+ if (currentSummary !== undefined)
164
+ count += 1;
165
+ if (systemMessage)
166
+ count += 1;
167
+ count += anchorMessages.length;
168
+ return count;
169
+ }
170
+ function setAnchor(messages) {
171
+ anchorMessages = messages.slice();
172
+ }
173
+ function setTokenBudget(budget) {
174
+ if (!Number.isFinite(budget) || budget < 100) {
175
+ throw new RangeError(`sliding-context: tokenBudget must be a finite number >= 100, got ${budget}`);
176
+ }
177
+ tokenBudget = budget;
178
+ void enforceBudget();
179
+ }
180
+ function clear() {
181
+ recentMessages = [];
182
+ pendingBuffer = [];
183
+ currentSummary = undefined;
184
+ summaryRounds = 0;
185
+ anchorMessages = options.anchor ? options.anchor.slice() : [];
186
+ }
187
+ function serialize() {
188
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
189
+ const { summarizer, tokenCounter, hooks, ...serializableOptions } = options;
190
+ return {
191
+ options: { ...serializableOptions, tokenBudget },
192
+ messages: recentMessages.slice(),
193
+ summary: currentSummary,
194
+ anchor: anchorMessages.slice(),
195
+ pendingBuffer: pendingBuffer.slice(),
196
+ summaryRounds,
197
+ tokenCounts: {
198
+ system: sysTokens(),
199
+ anchor: ancTokens(),
200
+ summary: sumTokens(),
201
+ recent: recTokens(),
202
+ pending: pendTokens(),
203
+ },
204
+ version: 1,
205
+ };
206
+ }
207
+ return {
208
+ addMessage,
209
+ getMessages,
210
+ getSummary,
211
+ getTokenCount,
212
+ getTokenBreakdown,
213
+ getRecentMessageCount,
214
+ getTotalMessageCount,
215
+ setAnchor,
216
+ setTokenBudget,
217
+ clear,
218
+ serialize,
219
+ };
220
+ }
221
+ // ---------------------------------------------------------------------------
222
+ // Public exports
223
+ // ---------------------------------------------------------------------------
224
+ /**
225
+ * Create a new SlidingContext instance.
226
+ */
227
+ function createSlidingContext(options) {
228
+ return createWithState(options);
229
+ }
230
+ /**
231
+ * Serialize a SlidingContext's state to a JSON string suitable for storage.
232
+ */
233
+ function serializeContext(ctx) {
234
+ return (0, serialization_1.serialize)(ctx.serialize());
235
+ }
236
+ /**
237
+ * Restore a SlidingContext from a JSON string produced by `serializeContext()`.
238
+ * Re-supply function-valued options (summarizer, tokenCounter, hooks) since
239
+ * they cannot be serialized.
240
+ */
241
+ function restoreSlidingContext(data, options) {
242
+ const state = (0, serialization_1.deserialize)(data);
243
+ return createWithState({ ...options, tokenBudget: state.options.tokenBudget }, state);
244
+ }
245
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { Message, TokenCounter } from './types';
2
+ /**
3
+ * Evict the oldest messages from `messages` until `totalTokens` fits within
4
+ * `targetTokens`. Tool-call pairs are kept atomic: an assistant message with
5
+ * `tool_calls` is always evicted together with all its paired `tool` result
6
+ * messages.
7
+ *
8
+ * Returns `{ evicted, remaining }`.
9
+ */
10
+ export declare function evictMessages(messages: Message[], targetTokens: number, tokenCounter: TokenCounter, overhead: number): {
11
+ evicted: Message[];
12
+ remaining: Message[];
13
+ };
14
+ //# sourceMappingURL=eviction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eviction.d.ts","sourceRoot":"","sources":["../src/eviction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AA+BrD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,OAAO,EAAE,EACnB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,MAAM,GACf;IAAE,OAAO,EAAE,OAAO,EAAE,CAAC;IAAC,SAAS,EAAE,OAAO,EAAE,CAAA;CAAE,CAyD9C"}