toonify-mcp 0.3.1 → 0.4.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 CHANGED
@@ -18,6 +18,7 @@ Reduces Claude API token usage by **30-65% depending on data structure** through
18
18
 
19
19
  - **30-65% Token Reduction** (typically 50-55%) for JSON, CSV, YAML data
20
20
  - **Multilingual Support** - Accurate token counting for 15+ languages
21
+ - **Enhanced Caching** - LRU cache with TTL expiration and optional disk persistence
21
22
  - **Fully Automatic** - PostToolUse hook intercepts tool results
22
23
  - **Zero Configuration** - Works out of the box with sensible defaults
23
24
  - **Dual Mode** - Works as Plugin (auto) or MCP Server (manual)
@@ -167,6 +168,30 @@ claude mcp call toonify get_stats '{}'
167
168
  # Or check Claude Code output for stats (if TOONIFY_SHOW_STATS=true)
168
169
  ```
169
170
 
171
+ ### Cache Management
172
+
173
+ Toonify v0.4.0+ includes an enhanced LRU cache with TTL expiration:
174
+
175
+ ```bash
176
+ # Get cache statistics
177
+ claude mcp call toonify get_cache_stats '{}'
178
+
179
+ # Clear all cached results
180
+ claude mcp call toonify clear_cache '{}'
181
+
182
+ # Clean up expired entries
183
+ claude mcp call toonify cleanup_expired_cache '{}'
184
+ ```
185
+
186
+ **Cache benefits:**
187
+ - ✅ **50-500x faster** on cache hits (0.1ms vs 5-50ms)
188
+ - ✅ Avoids re-optimizing identical content
189
+ - ✅ Optional disk persistence for cross-session reuse
190
+ - ✅ Automatic LRU eviction when full
191
+ - ✅ TTL expiration (default: 1 hour)
192
+
193
+ See [docs/CACHE.md](docs/CACHE.md) for detailed cache documentation.
194
+
170
195
  ## Troubleshooting
171
196
 
172
197
  ### Hook Not Triggering
@@ -241,6 +266,11 @@ Contributions welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guideli
241
266
 
242
267
  MIT License - see [LICENSE](LICENSE)
243
268
 
269
+ ---
270
+
271
+ 🇹🇼 **Crafted in Taiwan** | 台灣製造
272
+ _Where innovation meets tradition_
273
+
244
274
  ## Changelog
245
275
 
246
276
  ### v0.3.0 (2025-12-26)
@@ -33,4 +33,38 @@ export interface CacheStrategy {
33
33
  shouldCache: (content: string, tokens: number) => boolean;
34
34
  formatCacheStructure: (content: CachedContent) => any;
35
35
  }
36
+ /**
37
+ * LRU Cache Configuration
38
+ */
39
+ export interface LRUCacheConfig {
40
+ enabled: boolean;
41
+ maxSize: number;
42
+ ttl: number;
43
+ persistent: boolean;
44
+ persistPath?: string;
45
+ }
46
+ /**
47
+ * LRU Cache Entry
48
+ */
49
+ export interface LRUCacheEntry<T> {
50
+ key: string;
51
+ value: T;
52
+ timestamp: number;
53
+ lastAccessed: number;
54
+ accessCount: number;
55
+ expiresAt: number;
56
+ }
57
+ /**
58
+ * LRU Cache Statistics
59
+ */
60
+ export interface LRUCacheStats {
61
+ hits: number;
62
+ misses: number;
63
+ evictions: number;
64
+ expirations: number;
65
+ currentSize: number;
66
+ maxSize: number;
67
+ hitRate: number;
68
+ averageAccessCount: number;
69
+ }
36
70
  //# sourceMappingURL=cache-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cache-types.d.ts","sourceRoot":"","sources":["../../../src/optimizer/caching/cache-types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC1C,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,WAAW,GAAG,QAAQ,CAAC;IACjC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAC1D,oBAAoB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,GAAG,CAAC;CACvD"}
1
+ {"version":3,"file":"cache-types.d.ts","sourceRoot":"","sources":["../../../src/optimizer/caching/cache-types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC1C,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,WAAW,GAAG,QAAQ,CAAC;IACjC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAC1D,oBAAoB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,GAAG,CAAC;CACvD;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,CAAC,CAAC;IACT,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB,EAAE,MAAM,CAAC;CAC5B"}
@@ -4,4 +4,6 @@
4
4
  export * from './cache-types.js';
5
5
  export * from './cache-strategies.js';
6
6
  export { CacheOptimizer } from './cache-optimizer.js';
7
+ export { LRUCache } from './lru-cache.js';
8
+ export { PersistentCache } from './persistent-cache.js';
7
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/optimizer/caching/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/optimizer/caching/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
@@ -4,4 +4,6 @@
4
4
  export * from './cache-types.js';
5
5
  export * from './cache-strategies.js';
6
6
  export { CacheOptimizer } from './cache-optimizer.js';
7
+ export { LRUCache } from './lru-cache.js';
8
+ export { PersistentCache } from './persistent-cache.js';
7
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/optimizer/caching/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/optimizer/caching/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * LRU Cache with TTL (Time-to-Live) support
3
+ * Features:
4
+ * - Least Recently Used eviction strategy
5
+ * - TTL-based expiration
6
+ * - Optional disk persistence
7
+ */
8
+ import type { LRUCacheConfig, LRUCacheStats } from './cache-types.js';
9
+ export declare class LRUCache<T = any> {
10
+ private cache;
11
+ private config;
12
+ private stats;
13
+ private persistentCache?;
14
+ private totalAccessCount;
15
+ constructor(config?: Partial<LRUCacheConfig>);
16
+ /**
17
+ * Generate cache key from content using SHA-256
18
+ */
19
+ static generateKey(content: string): string;
20
+ /**
21
+ * Get value from cache
22
+ */
23
+ get(key: string): T | undefined;
24
+ /**
25
+ * Set value in cache
26
+ */
27
+ set(key: string, value: T): void;
28
+ /**
29
+ * Check if entry has expired
30
+ */
31
+ private isExpired;
32
+ /**
33
+ * Evict least recently used entry
34
+ * Since Map maintains insertion order, the first entry is the least recently used
35
+ */
36
+ private evictLRU;
37
+ /**
38
+ * Clear all cache entries
39
+ */
40
+ clear(): void;
41
+ /**
42
+ * Clean up expired entries
43
+ */
44
+ cleanup(): number;
45
+ /**
46
+ * Get cache statistics
47
+ */
48
+ getStats(): LRUCacheStats;
49
+ /**
50
+ * Update hit rate and average access count (O(1) complexity)
51
+ */
52
+ private updateStats;
53
+ /**
54
+ * Load cache from disk
55
+ */
56
+ private loadFromDisk;
57
+ /**
58
+ * Force save all entries to disk and wait for completion
59
+ */
60
+ saveToDisk(): Promise<void>;
61
+ /**
62
+ * Get cache size
63
+ */
64
+ size(): number;
65
+ /**
66
+ * Check if key exists (without updating access time)
67
+ */
68
+ has(key: string): boolean;
69
+ }
70
+ //# sourceMappingURL=lru-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lru-cache.d.ts","sourceRoot":"","sources":["../../../src/optimizer/caching/lru-cache.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAiB,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGrF,qBAAa,QAAQ,CAAC,CAAC,GAAG,GAAG;IAC3B,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,eAAe,CAAC,CAAqB;IAC7C,OAAO,CAAC,gBAAgB,CAAa;gBAEzB,MAAM,GAAE,OAAO,CAAC,cAAc,CAAM;IA6BhD;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAI3C;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAsC/B;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IA8BhC;;OAEG;IACH,OAAO,CAAC,SAAS;IAIjB;;;OAGG;IACH,OAAO,CAAC,QAAQ;IAqBhB;;OAEG;IACH,KAAK,IAAI,IAAI;IAUb;;OAEG;IACH,OAAO,IAAI,MAAM;IAqBjB;;OAEG;IACH,QAAQ,IAAI,aAAa;IAIzB;;OAEG;IACH,OAAO,CAAC,WAAW;IAQnB;;OAEG;IACH,OAAO,CAAC,YAAY;IAsBpB;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAWjC;;OAEG;IACH,IAAI,IAAI,MAAM;IAId;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;CAO1B"}
@@ -0,0 +1,230 @@
1
+ /**
2
+ * LRU Cache with TTL (Time-to-Live) support
3
+ * Features:
4
+ * - Least Recently Used eviction strategy
5
+ * - TTL-based expiration
6
+ * - Optional disk persistence
7
+ */
8
+ import crypto from 'crypto';
9
+ import { PersistentCache } from './persistent-cache.js';
10
+ export class LRUCache {
11
+ cache;
12
+ config;
13
+ stats;
14
+ persistentCache;
15
+ totalAccessCount = 0; // Running total for O(1) average calculation
16
+ constructor(config = {}) {
17
+ this.config = {
18
+ enabled: true,
19
+ maxSize: 500,
20
+ ttl: 3600000, // 1 hour in milliseconds
21
+ persistent: false,
22
+ persistPath: '~/.toonify-mcp/cache/optimization-cache.json',
23
+ ...config
24
+ };
25
+ this.cache = new Map();
26
+ this.stats = {
27
+ hits: 0,
28
+ misses: 0,
29
+ evictions: 0,
30
+ expirations: 0,
31
+ currentSize: 0,
32
+ maxSize: this.config.maxSize,
33
+ hitRate: 0,
34
+ averageAccessCount: 0
35
+ };
36
+ // Initialize persistent cache if enabled
37
+ if (this.config.persistent && this.config.persistPath) {
38
+ this.persistentCache = new PersistentCache(this.config.persistPath);
39
+ this.loadFromDisk();
40
+ }
41
+ }
42
+ /**
43
+ * Generate cache key from content using SHA-256
44
+ */
45
+ static generateKey(content) {
46
+ return crypto.createHash('sha256').update(content).digest('hex');
47
+ }
48
+ /**
49
+ * Get value from cache
50
+ */
51
+ get(key) {
52
+ if (!this.config.enabled) {
53
+ return undefined;
54
+ }
55
+ const entry = this.cache.get(key);
56
+ if (!entry) {
57
+ this.stats.misses++;
58
+ this.updateStats();
59
+ return undefined;
60
+ }
61
+ // Check if expired
62
+ if (this.isExpired(entry)) {
63
+ this.totalAccessCount -= entry.accessCount; // Update running total
64
+ this.cache.delete(key);
65
+ this.stats.expirations++;
66
+ this.stats.misses++;
67
+ this.updateStats();
68
+ return undefined;
69
+ }
70
+ // Update access metadata (LRU)
71
+ entry.lastAccessed = Date.now();
72
+ entry.accessCount++;
73
+ this.totalAccessCount++; // Update running total
74
+ // Delete and re-insert to move to end (most recently used in Map)
75
+ this.cache.delete(key);
76
+ this.cache.set(key, entry);
77
+ this.stats.hits++;
78
+ this.updateStats();
79
+ return entry.value;
80
+ }
81
+ /**
82
+ * Set value in cache
83
+ */
84
+ set(key, value) {
85
+ if (!this.config.enabled) {
86
+ return;
87
+ }
88
+ const now = Date.now();
89
+ // Check if we need to evict (LRU)
90
+ if (this.cache.size >= this.config.maxSize && !this.cache.has(key)) {
91
+ this.evictLRU();
92
+ }
93
+ const entry = {
94
+ key,
95
+ value,
96
+ timestamp: now,
97
+ lastAccessed: now,
98
+ accessCount: 0,
99
+ expiresAt: now + this.config.ttl
100
+ };
101
+ this.cache.set(key, entry);
102
+ this.stats.currentSize = this.cache.size;
103
+ // Persist to disk if enabled
104
+ if (this.persistentCache) {
105
+ this.persistentCache.save(key, entry);
106
+ }
107
+ }
108
+ /**
109
+ * Check if entry has expired
110
+ */
111
+ isExpired(entry) {
112
+ return Date.now() > entry.expiresAt;
113
+ }
114
+ /**
115
+ * Evict least recently used entry
116
+ * Since Map maintains insertion order, the first entry is the least recently used
117
+ */
118
+ evictLRU() {
119
+ // Get first entry (least recently used)
120
+ const firstKey = this.cache.keys().next().value;
121
+ if (firstKey) {
122
+ const entry = this.cache.get(firstKey);
123
+ if (entry) {
124
+ this.totalAccessCount -= entry.accessCount; // Update running total
125
+ }
126
+ this.cache.delete(firstKey);
127
+ this.stats.evictions++;
128
+ this.stats.currentSize = this.cache.size;
129
+ // Remove from disk
130
+ if (this.persistentCache) {
131
+ this.persistentCache.delete(firstKey);
132
+ }
133
+ }
134
+ }
135
+ /**
136
+ * Clear all cache entries
137
+ */
138
+ clear() {
139
+ this.cache.clear();
140
+ this.stats.currentSize = 0;
141
+ this.totalAccessCount = 0; // Reset running total
142
+ if (this.persistentCache) {
143
+ this.persistentCache.clear();
144
+ }
145
+ }
146
+ /**
147
+ * Clean up expired entries
148
+ */
149
+ cleanup() {
150
+ let removed = 0;
151
+ const now = Date.now();
152
+ for (const [key, entry] of this.cache.entries()) {
153
+ if (now > entry.expiresAt) {
154
+ this.totalAccessCount -= entry.accessCount; // Update running total
155
+ this.cache.delete(key);
156
+ this.stats.expirations++;
157
+ removed++;
158
+ if (this.persistentCache) {
159
+ this.persistentCache.delete(key);
160
+ }
161
+ }
162
+ }
163
+ this.stats.currentSize = this.cache.size;
164
+ return removed;
165
+ }
166
+ /**
167
+ * Get cache statistics
168
+ */
169
+ getStats() {
170
+ return { ...this.stats };
171
+ }
172
+ /**
173
+ * Update hit rate and average access count (O(1) complexity)
174
+ */
175
+ updateStats() {
176
+ const total = this.stats.hits + this.stats.misses;
177
+ this.stats.hitRate = total > 0 ? this.stats.hits / total : 0;
178
+ // Calculate average access count using running total (O(1))
179
+ this.stats.averageAccessCount = this.cache.size > 0 ? this.totalAccessCount / this.cache.size : 0;
180
+ }
181
+ /**
182
+ * Load cache from disk
183
+ */
184
+ loadFromDisk() {
185
+ if (!this.persistentCache) {
186
+ return;
187
+ }
188
+ const entries = this.persistentCache.loadAll();
189
+ const now = Date.now();
190
+ for (const entry of entries) {
191
+ // Skip expired entries
192
+ if (now > entry.expiresAt) {
193
+ this.stats.expirations++;
194
+ continue;
195
+ }
196
+ this.cache.set(entry.key, entry);
197
+ this.totalAccessCount += entry.accessCount; // Initialize running total from disk
198
+ }
199
+ this.stats.currentSize = this.cache.size;
200
+ }
201
+ /**
202
+ * Force save all entries to disk and wait for completion
203
+ */
204
+ async saveToDisk() {
205
+ if (!this.persistentCache) {
206
+ return;
207
+ }
208
+ // Flush all pending writes and save current state
209
+ await this.persistentCache.flush();
210
+ await this.persistentCache.saveAll(Array.from(this.cache.values()));
211
+ await this.persistentCache.flush(); // Ensure final save completes
212
+ }
213
+ /**
214
+ * Get cache size
215
+ */
216
+ size() {
217
+ return this.cache.size;
218
+ }
219
+ /**
220
+ * Check if key exists (without updating access time)
221
+ */
222
+ has(key) {
223
+ const entry = this.cache.get(key);
224
+ if (!entry) {
225
+ return false;
226
+ }
227
+ return !this.isExpired(entry);
228
+ }
229
+ }
230
+ //# sourceMappingURL=lru-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lru-cache.js","sourceRoot":"","sources":["../../../src/optimizer/caching/lru-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Persistent Cache: Disk-based cache storage
3
+ * Features:
4
+ * - Save/load cache entries to/from disk
5
+ * - Atomic writes to prevent corruption
6
+ * - Auto-create cache directory
7
+ * - Operation serialization to prevent race conditions
8
+ * - Batched writes to reduce disk I/O
9
+ */
10
+ import type { LRUCacheEntry } from './cache-types.js';
11
+ export declare class PersistentCache<T = any> {
12
+ private filePath;
13
+ private writeQueue;
14
+ private isProcessing;
15
+ private pendingWrites;
16
+ private batchTimer;
17
+ private readonly BATCH_DELAY_MS;
18
+ constructor(filePath: string);
19
+ /**
20
+ * Ensure cache directory exists
21
+ */
22
+ private ensureDirectory;
23
+ /**
24
+ * Load all cache entries from disk
25
+ */
26
+ loadAll(): LRUCacheEntry<T>[];
27
+ /**
28
+ * Save all cache entries to disk synchronously (atomic write)
29
+ * Internal use only
30
+ */
31
+ private saveAllSync;
32
+ /**
33
+ * Save all cache entries to disk (queued)
34
+ */
35
+ saveAll(entries: LRUCacheEntry<T>[]): Promise<void>;
36
+ /**
37
+ * Flush all pending writes immediately
38
+ * Call this before process exit to ensure all writes are persisted
39
+ */
40
+ flush(): Promise<void>;
41
+ /**
42
+ * Queue a write operation
43
+ */
44
+ private queueWrite;
45
+ /**
46
+ * Process the write queue serially
47
+ */
48
+ private processQueue;
49
+ /**
50
+ * Execute a single write operation
51
+ */
52
+ private executeOperation;
53
+ /**
54
+ * Schedule a batched write operation
55
+ */
56
+ private scheduleBatchWrite;
57
+ /**
58
+ * Flush all pending writes to disk
59
+ */
60
+ private flushPendingWrites;
61
+ /**
62
+ * Save a single entry (batched and queued)
63
+ */
64
+ save(key: string, entry: LRUCacheEntry<T>): Promise<void>;
65
+ /**
66
+ * Delete a single entry (queued)
67
+ */
68
+ delete(key: string): Promise<void>;
69
+ /**
70
+ * Clear all cache entries (queued)
71
+ */
72
+ clear(): Promise<void>;
73
+ /**
74
+ * Get cache file size in bytes
75
+ */
76
+ getFileSize(): number;
77
+ /**
78
+ * Check if cache file exists
79
+ */
80
+ exists(): boolean;
81
+ }
82
+ //# sourceMappingURL=persistent-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistent-cache.d.ts","sourceRoot":"","sources":["../../../src/optimizer/caching/persistent-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AActD,qBAAa,eAAe,CAAC,CAAC,GAAG,GAAG;IAClC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,aAAa,CAA4C;IACjE,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAO;gBAE1B,QAAQ,EAAE,MAAM;IAU5B;;OAEG;IACH,OAAO,CAAC,eAAe;IAOvB;;OAEG;IACH,OAAO,IAAI,aAAa,CAAC,CAAC,CAAC,EAAE;IAoB7B;;;OAGG;IACH,OAAO,CAAC,WAAW;IAgBnB;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzD;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAe5B;;OAEG;IACH,OAAO,CAAC,UAAU;IAOlB;;OAEG;YACW,YAAY;IAqB1B;;OAEG;YACW,gBAAgB;IA4C9B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAkB1B;;OAEG;IACG,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/D;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B;;OAEG;IACH,WAAW,IAAI,MAAM;IAYrB;;OAEG;IACH,MAAM,IAAI,OAAO;CAGlB"}