llm-response-cache 0.1.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.
package/README.md ADDED
@@ -0,0 +1,109 @@
1
+ # llm-response-cache
2
+
3
+ Prompt-hash-keyed LLM response cache with model-aware invalidation, O(1) LRU eviction, and TTL support. Zero runtime dependencies.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install llm-response-cache
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ### createCache / get / set
14
+
15
+ ```typescript
16
+ import { createCache } from 'llm-response-cache';
17
+
18
+ const cache = createCache({
19
+ eviction: {
20
+ maxEntries: 1000, // evict LRU after this many entries
21
+ ttlMs: 60_000, // expire entries after 60 seconds (0 = no TTL)
22
+ },
23
+ pricePerMTokInput: 2.50, // USD per million input tokens (default)
24
+ pricePerMTokOutput: 10.00, // USD per million output tokens (default)
25
+ });
26
+
27
+ const messages = [{ role: 'user', content: 'What is 2+2?' }];
28
+ const model = 'gpt-4';
29
+
30
+ // Manual get/set
31
+ const hit = cache.get(messages, model);
32
+ if (!hit) {
33
+ const response = await openai.chat.completions.create({ model, messages });
34
+ cache.set(messages, model, { model }, {
35
+ content: response.choices[0].message.content!,
36
+ model: response.model,
37
+ usage: {
38
+ inputTokens: response.usage?.prompt_tokens,
39
+ outputTokens: response.usage?.completion_tokens,
40
+ },
41
+ });
42
+ }
43
+ ```
44
+
45
+ ### wrap — transparent caching proxy
46
+
47
+ ```typescript
48
+ import OpenAI from 'openai';
49
+ import { createCache } from 'llm-response-cache';
50
+
51
+ const openai = new OpenAI();
52
+ const cache = createCache();
53
+ const cachedOpenAI = cache.wrap(openai);
54
+
55
+ // First call hits the API; second call is served from cache
56
+ const r1 = await cachedOpenAI.chat.completions.create({ model: 'gpt-4', messages });
57
+ const r2 = await cachedOpenAI.chat.completions.create({ model: 'gpt-4', messages });
58
+ ```
59
+
60
+ ### stats
61
+
62
+ ```typescript
63
+ const s = cache.stats();
64
+ console.log(s.hitRate); // 0–1
65
+ console.log(s.tokensSaved); // cumulative tokens served from cache
66
+ console.log(s.estimatedCostSaved); // USD saved
67
+ ```
68
+
69
+ ### invalidate / clear / delete
70
+
71
+ ```typescript
72
+ cache.invalidate('gpt-4'); // remove all gpt-4 entries
73
+ cache.invalidate(); // remove all entries
74
+ cache.delete(key); // remove by exact cache key
75
+ cache.clear(); // remove everything and reset stats
76
+ ```
77
+
78
+ ### serialize
79
+
80
+ ```typescript
81
+ const state = cache.serialize();
82
+ // { entries: CacheEntry[], stats: { hits, misses }, version: 1 }
83
+ ```
84
+
85
+ ## Cache key
86
+
87
+ Keys are SHA-256 digests of a canonical JSON object containing:
88
+ - Normalized messages (NFC, trimmed, lowercased role)
89
+ - Lowercased model name
90
+ - Output-affecting params only (`temperature`, `top_p`, `max_tokens`, `tools`, `tool_choice`, `response_format`, `stop`, `seed`, `system`, `top_k`)
91
+
92
+ Params that do not affect output (`stream`, `user`, `timeout`, etc.) are excluded from the key.
93
+
94
+ ## API
95
+
96
+ | Method | Description |
97
+ |---|---|
98
+ | `get(messages, model, params?)` | Lookup; returns `CacheEntry` or `null` |
99
+ | `set(messages, model, params, response)` | Store a response |
100
+ | `wrap(client, options?)` | Proxy wrapping `client.chat.completions.create` |
101
+ | `stats()` | Returns `CacheStats` |
102
+ | `invalidate(model?)` | Remove entries (all, or by model) |
103
+ | `clear()` | Clear all entries and reset hit/miss counters |
104
+ | `delete(key)` | Remove entry by key |
105
+ | `has(key)` | Check if key exists |
106
+ | `getByKey(key)` | Retrieve entry by exact key |
107
+ | `buildKey(messages, model, params?)` | Compute the cache key without storing |
108
+ | `serialize()` | Export state as `CacheState` |
109
+ | `size` | Number of stored entries |
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cache.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/cache.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const cache_1 = require("../cache");
5
+ const key_1 = require("../key");
6
+ const msgs = [
7
+ { role: 'user', content: 'Hello, world' },
8
+ ];
9
+ const response = {
10
+ content: 'Hi there!',
11
+ model: 'gpt-4',
12
+ usage: { inputTokens: 10, outputTokens: 5 },
13
+ };
14
+ (0, vitest_1.describe)('buildKey', () => {
15
+ (0, vitest_1.it)('returns the same key for the same messages and model regardless of param order', () => {
16
+ const key1 = (0, key_1.buildKey)(msgs, 'gpt-4', { temperature: 0.7, max_tokens: 100 });
17
+ const key2 = (0, key_1.buildKey)(msgs, 'gpt-4', { max_tokens: 100, temperature: 0.7 });
18
+ (0, vitest_1.expect)(key1).toBe(key2);
19
+ });
20
+ (0, vitest_1.it)('returns a different key for a different model', () => {
21
+ const key1 = (0, key_1.buildKey)(msgs, 'gpt-4');
22
+ const key2 = (0, key_1.buildKey)(msgs, 'gpt-3.5-turbo');
23
+ (0, vitest_1.expect)(key1).not.toBe(key2);
24
+ });
25
+ (0, vitest_1.it)('returns a different key for different messages', () => {
26
+ const msgs2 = [{ role: 'user', content: 'Different message' }];
27
+ const key1 = (0, key_1.buildKey)(msgs, 'gpt-4');
28
+ const key2 = (0, key_1.buildKey)(msgs2, 'gpt-4');
29
+ (0, vitest_1.expect)(key1).not.toBe(key2);
30
+ });
31
+ (0, vitest_1.it)('excludes non-output-affecting params from the key', () => {
32
+ const key1 = (0, key_1.buildKey)(msgs, 'gpt-4', { stream: true });
33
+ const key2 = (0, key_1.buildKey)(msgs, 'gpt-4', { stream: false });
34
+ (0, vitest_1.expect)(key1).toBe(key2);
35
+ });
36
+ (0, vitest_1.it)('normalizes model casing', () => {
37
+ const key1 = (0, key_1.buildKey)(msgs, 'GPT-4');
38
+ const key2 = (0, key_1.buildKey)(msgs, 'gpt-4');
39
+ (0, vitest_1.expect)(key1).toBe(key2);
40
+ });
41
+ (0, vitest_1.it)('normalizes message role casing', () => {
42
+ const key1 = (0, key_1.buildKey)([{ role: 'User', content: 'Hello, world' }], 'gpt-4');
43
+ const key2 = (0, key_1.buildKey)([{ role: 'user', content: 'Hello, world' }], 'gpt-4');
44
+ (0, vitest_1.expect)(key1).toBe(key2);
45
+ });
46
+ (0, vitest_1.it)('returns a 64-char hex string (SHA-256)', () => {
47
+ const key = (0, key_1.buildKey)(msgs, 'gpt-4');
48
+ (0, vitest_1.expect)(key).toMatch(/^[0-9a-f]{64}$/);
49
+ });
50
+ });
51
+ (0, vitest_1.describe)('cache get/set', () => {
52
+ (0, vitest_1.it)('returns null on a miss', () => {
53
+ const cache = (0, cache_1.createCache)();
54
+ const result = cache.get(msgs, 'gpt-4');
55
+ (0, vitest_1.expect)(result).toBeNull();
56
+ });
57
+ (0, vitest_1.it)('returns the entry after set', () => {
58
+ const cache = (0, cache_1.createCache)();
59
+ cache.set(msgs, 'gpt-4', undefined, response);
60
+ const entry = cache.get(msgs, 'gpt-4');
61
+ (0, vitest_1.expect)(entry).not.toBeNull();
62
+ (0, vitest_1.expect)(entry.response.content).toBe('Hi there!');
63
+ });
64
+ (0, vitest_1.it)('increments hitCount on repeated gets', () => {
65
+ const cache = (0, cache_1.createCache)();
66
+ cache.set(msgs, 'gpt-4', undefined, response);
67
+ cache.get(msgs, 'gpt-4');
68
+ cache.get(msgs, 'gpt-4');
69
+ const entry = cache.getByKey((0, key_1.buildKey)(msgs, 'gpt-4'));
70
+ (0, vitest_1.expect)(entry.hitCount).toBe(2);
71
+ });
72
+ });
73
+ (0, vitest_1.describe)('stats', () => {
74
+ (0, vitest_1.it)('increments misses on cache miss', () => {
75
+ const cache = (0, cache_1.createCache)();
76
+ cache.get(msgs, 'gpt-4');
77
+ (0, vitest_1.expect)(cache.stats().misses).toBe(1);
78
+ (0, vitest_1.expect)(cache.stats().hits).toBe(0);
79
+ });
80
+ (0, vitest_1.it)('increments hits on cache hit', () => {
81
+ const cache = (0, cache_1.createCache)();
82
+ cache.set(msgs, 'gpt-4', undefined, response);
83
+ cache.get(msgs, 'gpt-4');
84
+ cache.get(msgs, 'gpt-4');
85
+ (0, vitest_1.expect)(cache.stats().hits).toBe(2);
86
+ (0, vitest_1.expect)(cache.stats().misses).toBe(0);
87
+ });
88
+ (0, vitest_1.it)('computes hitRate correctly', () => {
89
+ const cache = (0, cache_1.createCache)();
90
+ cache.set(msgs, 'gpt-4', undefined, response);
91
+ cache.get(msgs, 'gpt-4'); // hit
92
+ cache.get([{ role: 'user', content: 'other' }], 'gpt-4'); // miss
93
+ (0, vitest_1.expect)(cache.stats().hitRate).toBeCloseTo(0.5);
94
+ });
95
+ (0, vitest_1.it)('hitRate is 0 when no lookups', () => {
96
+ const cache = (0, cache_1.createCache)();
97
+ (0, vitest_1.expect)(cache.stats().hitRate).toBe(0);
98
+ });
99
+ (0, vitest_1.it)('totalEntries reflects stored entries', () => {
100
+ const cache = (0, cache_1.createCache)();
101
+ (0, vitest_1.expect)(cache.stats().totalEntries).toBe(0);
102
+ cache.set(msgs, 'gpt-4', undefined, response);
103
+ (0, vitest_1.expect)(cache.stats().totalEntries).toBe(1);
104
+ });
105
+ });
106
+ (0, vitest_1.describe)('invalidate', () => {
107
+ (0, vitest_1.it)('removes only entries for the specified model', () => {
108
+ const cache = (0, cache_1.createCache)();
109
+ cache.set(msgs, 'gpt-4', undefined, { ...response, model: 'gpt-4' });
110
+ cache.set(msgs, 'gpt-3.5-turbo', undefined, { ...response, model: 'gpt-3.5-turbo' });
111
+ (0, vitest_1.expect)(cache.size).toBe(2);
112
+ const removed = cache.invalidate('gpt-4');
113
+ (0, vitest_1.expect)(removed).toBe(1);
114
+ (0, vitest_1.expect)(cache.size).toBe(1);
115
+ (0, vitest_1.expect)(cache.get(msgs, 'gpt-4')).toBeNull();
116
+ (0, vitest_1.expect)(cache.get(msgs, 'gpt-3.5-turbo')).not.toBeNull();
117
+ });
118
+ (0, vitest_1.it)('removes all entries when no model given', () => {
119
+ const cache = (0, cache_1.createCache)();
120
+ cache.set(msgs, 'gpt-4', undefined, response);
121
+ cache.set([{ role: 'user', content: 'other' }], 'gpt-4', undefined, response);
122
+ const removed = cache.invalidate();
123
+ (0, vitest_1.expect)(removed).toBe(2);
124
+ (0, vitest_1.expect)(cache.size).toBe(0);
125
+ });
126
+ });
127
+ (0, vitest_1.describe)('clear', () => {
128
+ (0, vitest_1.it)('removes all entries and resets stats', () => {
129
+ const cache = (0, cache_1.createCache)();
130
+ cache.set(msgs, 'gpt-4', undefined, response);
131
+ cache.get(msgs, 'gpt-4');
132
+ cache.clear();
133
+ (0, vitest_1.expect)(cache.size).toBe(0);
134
+ const s = cache.stats();
135
+ (0, vitest_1.expect)(s.hits).toBe(0);
136
+ (0, vitest_1.expect)(s.misses).toBe(0);
137
+ });
138
+ });
139
+ (0, vitest_1.describe)('delete / has', () => {
140
+ (0, vitest_1.it)('delete removes a specific entry by key', () => {
141
+ const cache = (0, cache_1.createCache)();
142
+ cache.set(msgs, 'gpt-4', undefined, response);
143
+ const key = (0, key_1.buildKey)(msgs, 'gpt-4');
144
+ (0, vitest_1.expect)(cache.has(key)).toBe(true);
145
+ (0, vitest_1.expect)(cache.delete(key)).toBe(true);
146
+ (0, vitest_1.expect)(cache.has(key)).toBe(false);
147
+ });
148
+ (0, vitest_1.it)('delete returns false for unknown key', () => {
149
+ const cache = (0, cache_1.createCache)();
150
+ (0, vitest_1.expect)(cache.delete('nonexistent')).toBe(false);
151
+ });
152
+ });
153
+ (0, vitest_1.describe)('LRU eviction', () => {
154
+ (0, vitest_1.it)('evicts the LRU entry when maxEntries is exceeded', () => {
155
+ const cache = (0, cache_1.createCache)({ eviction: { maxEntries: 2 } });
156
+ const m1 = [{ role: 'user', content: 'msg1' }];
157
+ const m2 = [{ role: 'user', content: 'msg2' }];
158
+ const m3 = [{ role: 'user', content: 'msg3' }];
159
+ cache.set(m1, 'gpt-4', undefined, response);
160
+ cache.set(m2, 'gpt-4', undefined, response);
161
+ // Access m1 so m2 becomes the LRU
162
+ cache.get(m1, 'gpt-4');
163
+ // Adding m3 should evict m2 (LRU)
164
+ cache.set(m3, 'gpt-4', undefined, response);
165
+ (0, vitest_1.expect)(cache.size).toBe(2);
166
+ (0, vitest_1.expect)(cache.get(m2, 'gpt-4')).toBeNull();
167
+ (0, vitest_1.expect)(cache.get(m1, 'gpt-4')).not.toBeNull();
168
+ (0, vitest_1.expect)(cache.get(m3, 'gpt-4')).not.toBeNull();
169
+ });
170
+ });
171
+ (0, vitest_1.describe)('TTL eviction', () => {
172
+ (0, vitest_1.it)('returns null for an expired entry', async () => {
173
+ vitest_1.vi.useFakeTimers();
174
+ const cache = (0, cache_1.createCache)({ eviction: { ttlMs: 100 } });
175
+ cache.set(msgs, 'gpt-4', undefined, response);
176
+ (0, vitest_1.expect)(cache.get(msgs, 'gpt-4')).not.toBeNull();
177
+ vitest_1.vi.advanceTimersByTime(101);
178
+ (0, vitest_1.expect)(cache.get(msgs, 'gpt-4')).toBeNull();
179
+ vitest_1.vi.useRealTimers();
180
+ });
181
+ (0, vitest_1.it)('returns entry before TTL expires', async () => {
182
+ vitest_1.vi.useFakeTimers();
183
+ const cache = (0, cache_1.createCache)({ eviction: { ttlMs: 500 } });
184
+ cache.set(msgs, 'gpt-4', undefined, response);
185
+ vitest_1.vi.advanceTimersByTime(499);
186
+ (0, vitest_1.expect)(cache.get(msgs, 'gpt-4')).not.toBeNull();
187
+ vitest_1.vi.useRealTimers();
188
+ });
189
+ });
190
+ (0, vitest_1.describe)('serialize', () => {
191
+ (0, vitest_1.it)('returns version 1 with entries and stats', () => {
192
+ const cache = (0, cache_1.createCache)();
193
+ cache.set(msgs, 'gpt-4', undefined, response);
194
+ cache.get(msgs, 'gpt-4');
195
+ cache.get([{ role: 'user', content: 'other' }], 'gpt-4');
196
+ const state = cache.serialize();
197
+ (0, vitest_1.expect)(state.version).toBe(1);
198
+ (0, vitest_1.expect)(state.entries.length).toBe(1);
199
+ (0, vitest_1.expect)(state.stats.hits).toBe(1);
200
+ (0, vitest_1.expect)(state.stats.misses).toBe(1);
201
+ });
202
+ });
203
+ (0, vitest_1.describe)('size', () => {
204
+ (0, vitest_1.it)('reflects the number of stored entries', () => {
205
+ const cache = (0, cache_1.createCache)();
206
+ (0, vitest_1.expect)(cache.size).toBe(0);
207
+ cache.set(msgs, 'gpt-4', undefined, response);
208
+ (0, vitest_1.expect)(cache.size).toBe(1);
209
+ cache.set([{ role: 'user', content: 'another' }], 'gpt-4', undefined, response);
210
+ (0, vitest_1.expect)(cache.size).toBe(2);
211
+ });
212
+ });
213
+ (0, vitest_1.describe)('wrap', () => {
214
+ (0, vitest_1.it)('returns cached response on second call', async () => {
215
+ const cache = (0, cache_1.createCache)();
216
+ const fakeCreate = vitest_1.vi.fn().mockResolvedValue({
217
+ choices: [{ message: { content: 'Hello from API' } }],
218
+ model: 'gpt-4',
219
+ usage: { prompt_tokens: 10, completion_tokens: 5 },
220
+ });
221
+ const fakeClient = {
222
+ chat: {
223
+ completions: {
224
+ create: fakeCreate,
225
+ },
226
+ },
227
+ };
228
+ const wrapped = cache.wrap(fakeClient);
229
+ const params = { messages: msgs, model: 'gpt-4' };
230
+ await wrapped.chat.completions.create(params);
231
+ await wrapped.chat.completions.create(params);
232
+ // API should only be called once; second call served from cache
233
+ (0, vitest_1.expect)(fakeCreate).toHaveBeenCalledTimes(1);
234
+ });
235
+ });
236
+ //# sourceMappingURL=cache.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.test.js","sourceRoot":"","sources":["../../src/__tests__/cache.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ResponseCache, ResponseCacheOptions } from './types';
2
+ export declare function createCache(options?: ResponseCacheOptions): ResponseCache;
3
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAIV,aAAa,EACb,oBAAoB,EACrB,MAAM,SAAS,CAAC;AA8BjB,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,aAAa,CAsJzE"}
package/dist/cache.js ADDED
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createCache = createCache;
4
+ const key_1 = require("./key");
5
+ const lru_store_1 = require("./lru-store");
6
+ function estimateTokens(messages) {
7
+ return messages.reduce((sum, m) => {
8
+ const text = typeof m.content === 'string' ? m.content : JSON.stringify(m.content);
9
+ return sum + Math.ceil(text.length / 4);
10
+ }, 0);
11
+ }
12
+ function extractResponse(result) {
13
+ const r = result;
14
+ const choices = r?.['choices'];
15
+ const contentParts = r?.['content'];
16
+ const usage = r?.['usage'];
17
+ const content = choices?.[0]?.['message']?.['content'] ??
18
+ contentParts?.[0]?.['text'] ??
19
+ JSON.stringify(result);
20
+ return {
21
+ content: typeof content === 'string' ? content : JSON.stringify(content),
22
+ model: r?.['model'] ?? '',
23
+ usage: {
24
+ inputTokens: usage?.['prompt_tokens'] ?? usage?.['input_tokens'],
25
+ outputTokens: usage?.['completion_tokens'] ?? usage?.['output_tokens'],
26
+ },
27
+ };
28
+ }
29
+ function createCache(options) {
30
+ const maxEntries = options?.eviction?.maxEntries ?? 1000;
31
+ const ttlMs = options?.eviction?.ttlMs ?? 0;
32
+ const store = new lru_store_1.LRUStore(maxEntries, ttlMs);
33
+ let hits = 0;
34
+ let misses = 0;
35
+ const cache = {
36
+ get(messages, model, params) {
37
+ const key = (0, key_1.buildKey)(messages, model, params);
38
+ const entry = store.get(key);
39
+ if (entry) {
40
+ hits++;
41
+ entry.hitCount++;
42
+ entry.lastAccessedAt = Date.now();
43
+ return entry;
44
+ }
45
+ misses++;
46
+ return null;
47
+ },
48
+ set(messages, model, params, response) {
49
+ const key = (0, key_1.buildKey)(messages, model, params);
50
+ const entry = {
51
+ key,
52
+ response,
53
+ model: response.model || model,
54
+ createdAt: Date.now(),
55
+ lastAccessedAt: Date.now(),
56
+ hitCount: 0,
57
+ inputTokens: response.usage?.inputTokens ?? estimateTokens(messages),
58
+ outputTokens: response.usage?.outputTokens ?? Math.ceil(response.content.length / 4),
59
+ };
60
+ store.set(key, entry);
61
+ },
62
+ wrap(client, wrapOptions) {
63
+ const defaultExtractMessages = (args) => {
64
+ const callParams = (args[0] ?? {});
65
+ const messages = (callParams['messages'] ?? []);
66
+ const model = (callParams['model'] ?? '');
67
+ return { messages, model, params: callParams };
68
+ };
69
+ const doExtractResponse = wrapOptions?.extractResponse ?? extractResponse;
70
+ const doExtractMessages = wrapOptions?.extractMessages ?? defaultExtractMessages;
71
+ return new Proxy(client, {
72
+ get(target, prop) {
73
+ if (prop === 'chat') {
74
+ const chatTarget = target['chat'];
75
+ return new Proxy(chatTarget, {
76
+ get(ct, chatProp) {
77
+ if (chatProp === 'completions') {
78
+ const compTarget = ct['completions'];
79
+ return new Proxy(compTarget, {
80
+ get(cpt, compProp) {
81
+ if (compProp === 'create') {
82
+ return async (...args) => {
83
+ const { messages, model, params } = doExtractMessages(args);
84
+ const cached = cache.get(messages, model, params);
85
+ if (cached)
86
+ return cached.response;
87
+ const createFn = cpt['create'];
88
+ const result = await createFn(...args);
89
+ cache.set(messages, model, params, doExtractResponse(result));
90
+ return result;
91
+ };
92
+ }
93
+ return cpt[compProp];
94
+ },
95
+ });
96
+ }
97
+ return ct[chatProp];
98
+ },
99
+ });
100
+ }
101
+ return target[prop];
102
+ },
103
+ });
104
+ },
105
+ stats() {
106
+ const total = hits + misses;
107
+ const entries = store.all();
108
+ const priceIn = options?.pricePerMTokInput ?? 2.50;
109
+ const priceOut = options?.pricePerMTokOutput ?? 10.00;
110
+ const tokensSaved = entries.reduce((sum, e) => sum + e.hitCount * (e.inputTokens + e.outputTokens), 0);
111
+ const estimatedCostSaved = entries.reduce((sum, e) => sum +
112
+ e.hitCount * (e.inputTokens / 1_000_000 * priceIn + e.outputTokens / 1_000_000 * priceOut), 0);
113
+ return {
114
+ hits,
115
+ misses,
116
+ hitRate: total > 0 ? hits / total : 0,
117
+ totalEntries: store.size(),
118
+ tokensSaved,
119
+ estimatedCostSaved,
120
+ };
121
+ },
122
+ invalidate(model) {
123
+ return store.invalidate(model);
124
+ },
125
+ clear() {
126
+ store.clear();
127
+ hits = 0;
128
+ misses = 0;
129
+ },
130
+ delete(key) {
131
+ return store.delete(key);
132
+ },
133
+ has(key) {
134
+ return store.get(key) !== null;
135
+ },
136
+ getByKey(key) {
137
+ return store.get(key);
138
+ },
139
+ buildKey: key_1.buildKey,
140
+ serialize() {
141
+ return { entries: store.all(), stats: { hits, misses }, version: 1 };
142
+ },
143
+ get size() {
144
+ return store.size();
145
+ },
146
+ };
147
+ return cache;
148
+ }
149
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { createCache } from './cache';
2
+ export { buildKey, sortedStringify } from './key';
3
+ export type { CacheableMessage, CacheableResponse, CacheEntry, CacheState, CacheStats, EvictionConfig, ResponseCache, ResponseCacheOptions, } from './types';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAClD,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,UAAU,EACV,UAAU,EACV,cAAc,EACd,aAAa,EACb,oBAAoB,GACrB,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sortedStringify = exports.buildKey = exports.createCache = void 0;
4
+ // llm-response-cache - Prompt-hash-keyed LLM response cache with model-aware invalidation
5
+ var cache_1 = require("./cache");
6
+ Object.defineProperty(exports, "createCache", { enumerable: true, get: function () { return cache_1.createCache; } });
7
+ var key_1 = require("./key");
8
+ Object.defineProperty(exports, "buildKey", { enumerable: true, get: function () { return key_1.buildKey; } });
9
+ Object.defineProperty(exports, "sortedStringify", { enumerable: true, get: function () { return key_1.sortedStringify; } });
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,0FAA0F;AAC1F,iCAAsC;AAA7B,oGAAA,WAAW,OAAA;AACpB,6BAAkD;AAAzC,+FAAA,QAAQ,OAAA;AAAE,sGAAA,eAAe,OAAA"}
package/dist/key.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import type { CacheableMessage } from './types';
2
+ export declare function sortedStringify(value: unknown): string;
3
+ export declare function buildKey(messages: CacheableMessage[], model: string, params?: Record<string, unknown>): string;
4
+ //# sourceMappingURL=key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key.d.ts","sourceRoot":"","sources":["../src/key.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAuBhD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAWtD;AAED,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,gBAAgB,EAAE,EAC5B,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,MAAM,CAoBR"}
package/dist/key.js ADDED
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sortedStringify = sortedStringify;
4
+ exports.buildKey = buildKey;
5
+ const crypto_1 = require("crypto");
6
+ // Output-affecting params to include in key
7
+ const INCLUDE_PARAMS = new Set([
8
+ 'temperature', 'top_p', 'max_tokens', 'max_completion_tokens',
9
+ 'tools', 'tool_choice', 'response_format', 'stop', 'seed',
10
+ 'system', 'top_k',
11
+ ]);
12
+ // Params to always exclude (don't affect output)
13
+ const EXCLUDE_PARAMS = new Set([
14
+ 'stream', 'stream_options', 'n', 'user', 'api_key', 'timeout',
15
+ 'request_id', 'idempotency_key', 'organization', 'max_retries',
16
+ ]);
17
+ function normalizeMessage(msg) {
18
+ const role = msg.role.toLowerCase().trim();
19
+ const content = typeof msg.content === 'string'
20
+ ? msg.content.trim().normalize('NFC')
21
+ : msg.content;
22
+ return { role, content };
23
+ }
24
+ function sortedStringify(value) {
25
+ if (value === null || typeof value !== 'object') {
26
+ return JSON.stringify(value);
27
+ }
28
+ if (Array.isArray(value)) {
29
+ return '[' + value.map(sortedStringify).join(',') + ']';
30
+ }
31
+ const sorted = Object.keys(value)
32
+ .sort()
33
+ .map((k) => JSON.stringify(k) + ':' + sortedStringify(value[k]));
34
+ return '{' + sorted.join(',') + '}';
35
+ }
36
+ function buildKey(messages, model, params) {
37
+ const normalizedMessages = messages.map(normalizeMessage);
38
+ const filteredParams = {};
39
+ if (params) {
40
+ for (const [k, v] of Object.entries(params)) {
41
+ if (INCLUDE_PARAMS.has(k) && !EXCLUDE_PARAMS.has(k)) {
42
+ filteredParams[k] = v;
43
+ }
44
+ }
45
+ }
46
+ const canonical = {
47
+ messages: normalizedMessages,
48
+ model: model.toLowerCase().trim(),
49
+ params: filteredParams,
50
+ };
51
+ const digest = (0, crypto_1.createHash)('sha256').update(sortedStringify(canonical)).digest('hex');
52
+ return digest;
53
+ }
54
+ //# sourceMappingURL=key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key.js","sourceRoot":"","sources":["../src/key.ts"],"names":[],"mappings":";;AAwBA,0CAWC;AAED,4BAwBC;AA7DD,mCAAoC;AAGpC,4CAA4C;AAC5C,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,aAAa,EAAE,OAAO,EAAE,YAAY,EAAE,uBAAuB;IAC7D,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM;IACzD,QAAQ,EAAE,OAAO;CAClB,CAAC,CAAC;AAEH,iDAAiD;AACjD,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,QAAQ,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS;IAC7D,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,aAAa;CAC/D,CAAC,CAAC;AAEH,SAAS,gBAAgB,CAAC,GAAqB;IAC7C,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAC3C,MAAM,OAAO,GAAG,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;QAC7C,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC;QACrC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC;IAChB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED,SAAgB,eAAe,CAAC,KAAc;IAC5C,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IAC1D,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAgC,CAAC;SACzD,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,eAAe,CAAE,KAAiC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChG,OAAO,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;AACtC,CAAC;AAED,SAAgB,QAAQ,CACtB,QAA4B,EAC5B,KAAa,EACb,MAAgC;IAEhC,MAAM,kBAAkB,GAAG,QAAQ,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAE1D,MAAM,cAAc,GAA4B,EAAE,CAAC;IACnD,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5C,IAAI,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpD,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG;QAChB,QAAQ,EAAE,kBAAkB;QAC5B,KAAK,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE;QACjC,MAAM,EAAE,cAAc;KACvB,CAAC;IAEF,MAAM,MAAM,GAAG,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACrF,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { CacheEntry } from './types';
2
+ export declare class LRUStore {
3
+ private maxEntries;
4
+ private ttlMs;
5
+ private map;
6
+ private head;
7
+ private tail;
8
+ constructor(maxEntries: number, ttlMs: number);
9
+ private isExpired;
10
+ private removeNode;
11
+ private insertAfterHead;
12
+ get(key: string): CacheEntry | null;
13
+ set(key: string, entry: CacheEntry): void;
14
+ delete(key: string): boolean;
15
+ invalidate(model?: string): number;
16
+ clear(): void;
17
+ all(): CacheEntry[];
18
+ size(): number;
19
+ }
20
+ //# sourceMappingURL=lru-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lru-store.d.ts","sourceRoot":"","sources":["../src/lru-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAc1C,qBAAa,QAAQ;IAMP,OAAO,CAAC,UAAU;IAAU,OAAO,CAAC,KAAK;IALrD,OAAO,CAAC,GAAG,CAA8B;IAEzC,OAAO,CAAC,IAAI,CAAU;IACtB,OAAO,CAAC,IAAI,CAAU;gBAEF,UAAU,EAAE,MAAM,EAAU,KAAK,EAAE,MAAM;IAQ7D,OAAO,CAAC,SAAS;IAKjB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,eAAe;IAOvB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAcnC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI;IAuBzC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAQ5B,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM;IAoBlC,KAAK,IAAI,IAAI;IAMb,GAAG,IAAI,UAAU,EAAE;IAYnB,IAAI,IAAI,MAAM;CAGf"}
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LRUStore = void 0;
4
+ class LRUNode {
5
+ key;
6
+ value;
7
+ prev = null;
8
+ next = null;
9
+ constructor(key, value) {
10
+ this.key = key;
11
+ this.value = value;
12
+ }
13
+ }
14
+ class LRUStore {
15
+ maxEntries;
16
+ ttlMs;
17
+ map = new Map();
18
+ // Doubly-linked list: head.next = MRU, tail.prev = LRU
19
+ head;
20
+ tail;
21
+ constructor(maxEntries, ttlMs) {
22
+ this.maxEntries = maxEntries;
23
+ this.ttlMs = ttlMs;
24
+ // Sentinel nodes
25
+ this.head = new LRUNode('__head__', {});
26
+ this.tail = new LRUNode('__tail__', {});
27
+ this.head.next = this.tail;
28
+ this.tail.prev = this.head;
29
+ }
30
+ isExpired(entry) {
31
+ if (this.ttlMs <= 0)
32
+ return false;
33
+ return Date.now() - entry.createdAt > this.ttlMs;
34
+ }
35
+ removeNode(node) {
36
+ const prev = node.prev;
37
+ const next = node.next;
38
+ prev.next = next;
39
+ next.prev = prev;
40
+ node.prev = null;
41
+ node.next = null;
42
+ }
43
+ insertAfterHead(node) {
44
+ node.prev = this.head;
45
+ node.next = this.head.next;
46
+ this.head.next.prev = node;
47
+ this.head.next = node;
48
+ }
49
+ get(key) {
50
+ const node = this.map.get(key);
51
+ if (!node)
52
+ return null;
53
+ if (this.isExpired(node.value)) {
54
+ this.removeNode(node);
55
+ this.map.delete(key);
56
+ return null;
57
+ }
58
+ // Move to MRU position
59
+ this.removeNode(node);
60
+ this.insertAfterHead(node);
61
+ return node.value;
62
+ }
63
+ set(key, entry) {
64
+ if (this.map.has(key)) {
65
+ const existing = this.map.get(key);
66
+ existing.value = entry;
67
+ this.removeNode(existing);
68
+ this.insertAfterHead(existing);
69
+ return;
70
+ }
71
+ const node = new LRUNode(key, entry);
72
+ this.map.set(key, node);
73
+ this.insertAfterHead(node);
74
+ // Evict LRU if over capacity
75
+ if (this.maxEntries > 0 && this.map.size > this.maxEntries) {
76
+ const lru = this.tail.prev;
77
+ if (lru !== this.head) {
78
+ this.removeNode(lru);
79
+ this.map.delete(lru.key);
80
+ }
81
+ }
82
+ }
83
+ delete(key) {
84
+ const node = this.map.get(key);
85
+ if (!node)
86
+ return false;
87
+ this.removeNode(node);
88
+ this.map.delete(key);
89
+ return true;
90
+ }
91
+ invalidate(model) {
92
+ let count = 0;
93
+ if (model === undefined) {
94
+ count = this.map.size;
95
+ this.clear();
96
+ return count;
97
+ }
98
+ const toDelete = [];
99
+ for (const [key, node] of this.map.entries()) {
100
+ if (node.value.model === model) {
101
+ toDelete.push(key);
102
+ }
103
+ }
104
+ for (const key of toDelete) {
105
+ this.delete(key);
106
+ count++;
107
+ }
108
+ return count;
109
+ }
110
+ clear() {
111
+ this.map.clear();
112
+ this.head.next = this.tail;
113
+ this.tail.prev = this.head;
114
+ }
115
+ all() {
116
+ const result = [];
117
+ let node = this.head.next;
118
+ while (node && node !== this.tail) {
119
+ if (!this.isExpired(node.value)) {
120
+ result.push(node.value);
121
+ }
122
+ node = node.next;
123
+ }
124
+ return result;
125
+ }
126
+ size() {
127
+ return this.map.size;
128
+ }
129
+ }
130
+ exports.LRUStore = LRUStore;
131
+ //# sourceMappingURL=lru-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lru-store.js","sourceRoot":"","sources":["../src/lru-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ export interface CacheableMessage {
2
+ role: string;
3
+ content: string | unknown[];
4
+ }
5
+ export interface CacheableResponse {
6
+ content: string;
7
+ model: string;
8
+ usage?: {
9
+ inputTokens?: number;
10
+ outputTokens?: number;
11
+ totalTokens?: number;
12
+ };
13
+ metadata?: Record<string, unknown>;
14
+ }
15
+ export interface CacheEntry {
16
+ key: string;
17
+ response: CacheableResponse;
18
+ createdAt: number;
19
+ lastAccessedAt: number;
20
+ hitCount: number;
21
+ model: string;
22
+ inputTokens: number;
23
+ outputTokens: number;
24
+ }
25
+ export interface CacheStats {
26
+ hits: number;
27
+ misses: number;
28
+ hitRate: number;
29
+ totalEntries: number;
30
+ tokensSaved: number;
31
+ estimatedCostSaved: number;
32
+ }
33
+ export interface CacheState {
34
+ entries: CacheEntry[];
35
+ stats: {
36
+ hits: number;
37
+ misses: number;
38
+ };
39
+ version: 1;
40
+ }
41
+ export interface EvictionConfig {
42
+ maxEntries?: number;
43
+ ttlMs?: number;
44
+ strategy?: 'lru' | 'ttl' | 'none';
45
+ }
46
+ export interface ResponseCacheOptions {
47
+ eviction?: EvictionConfig;
48
+ pricePerMTokInput?: number;
49
+ pricePerMTokOutput?: number;
50
+ }
51
+ export interface ResponseCache {
52
+ get(messages: CacheableMessage[], model: string, params?: Record<string, unknown>): CacheEntry | null;
53
+ set(messages: CacheableMessage[], model: string, params: Record<string, unknown> | undefined, response: CacheableResponse): void;
54
+ wrap<T extends object>(client: T, options?: {
55
+ extractMessages?: (args: unknown[]) => {
56
+ messages: CacheableMessage[];
57
+ model: string;
58
+ params: Record<string, unknown>;
59
+ };
60
+ extractResponse?: (response: unknown) => CacheableResponse;
61
+ }): T;
62
+ stats(): CacheStats;
63
+ invalidate(model?: string): number;
64
+ clear(): void;
65
+ delete(key: string): boolean;
66
+ has(key: string): boolean;
67
+ getByKey(key: string): CacheEntry | null;
68
+ buildKey(messages: CacheableMessage[], model: string, params?: Record<string, unknown>): string;
69
+ serialize(): CacheState;
70
+ readonly size: number;
71
+ }
72
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "llm-response-cache",
3
+ "version": "0.1.0",
4
+ "description": "Prompt-hash-keyed LLM response cache with model-aware invalidation",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "test": "vitest run",
13
+ "lint": "eslint src/",
14
+ "prepublishOnly": "npm run build"
15
+ },
16
+ "keywords": [],
17
+ "author": "",
18
+ "license": "MIT",
19
+ "engines": {
20
+ "node": ">=18"
21
+ },
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "^25.5.0",
27
+ "@typescript-eslint/eslint-plugin": "^8.57.1",
28
+ "@typescript-eslint/parser": "^8.57.1",
29
+ "eslint": "^10.1.0",
30
+ "typescript": "^5.9.3",
31
+ "vitest": "^4.1.0"
32
+ }
33
+ }