toonify-mcp 0.3.0 → 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.
Files changed (37) hide show
  1. package/README.de.md +270 -0
  2. package/README.es.md +1 -1
  3. package/README.fr.md +270 -0
  4. package/README.id.md +1 -1
  5. package/README.ja.md +1 -1
  6. package/README.ko.md +270 -0
  7. package/README.md +31 -1
  8. package/README.pt.md +270 -0
  9. package/README.ru.md +270 -0
  10. package/README.vi.md +1 -1
  11. package/README.zh-CN.md +1 -1
  12. package/README.zh-TW.md +1 -1
  13. package/dist/optimizer/caching/cache-types.d.ts +34 -0
  14. package/dist/optimizer/caching/cache-types.d.ts.map +1 -1
  15. package/dist/optimizer/caching/index.d.ts +2 -0
  16. package/dist/optimizer/caching/index.d.ts.map +1 -1
  17. package/dist/optimizer/caching/index.js +2 -0
  18. package/dist/optimizer/caching/index.js.map +1 -1
  19. package/dist/optimizer/caching/lru-cache.d.ts +70 -0
  20. package/dist/optimizer/caching/lru-cache.d.ts.map +1 -0
  21. package/dist/optimizer/caching/lru-cache.js +230 -0
  22. package/dist/optimizer/caching/lru-cache.js.map +1 -0
  23. package/dist/optimizer/caching/persistent-cache.d.ts +82 -0
  24. package/dist/optimizer/caching/persistent-cache.d.ts.map +1 -0
  25. package/dist/optimizer/caching/persistent-cache.js +237 -0
  26. package/dist/optimizer/caching/persistent-cache.js.map +1 -0
  27. package/dist/optimizer/token-optimizer.d.ts +31 -1
  28. package/dist/optimizer/token-optimizer.d.ts.map +1 -1
  29. package/dist/optimizer/token-optimizer.js +100 -5
  30. package/dist/optimizer/token-optimizer.js.map +1 -1
  31. package/dist/optimizer/types.d.ts +3 -2
  32. package/dist/optimizer/types.d.ts.map +1 -1
  33. package/dist/server/mcp-server.d.ts +8 -0
  34. package/dist/server/mcp-server.d.ts.map +1 -1
  35. package/dist/server/mcp-server.js +112 -40
  36. package/dist/server/mcp-server.js.map +1 -1
  37. package/package.json +1 -1
package/README.ru.md ADDED
@@ -0,0 +1,270 @@
1
+ # 🎯 Toonify MCP
2
+
3
+ **[English](README.md) | [繁體中文](README.zh-TW.md) | [简体中文](README.zh-CN.md) | [日本語](README.ja.md) | [Español](README.es.md) | [Français](README.fr.md) | [Deutsch](README.de.md) | [한국어](README.ko.md) | [Русский](README.ru.md) | [Português](README.pt.md) | [Tiếng Việt](README.vi.md) | [Bahasa Indonesia](README.id.md)**
4
+
5
+ MCP-сервер + плагин Claude Code, обеспечивающий автоматическую оптимизацию токенов для структурированных данных.
6
+ Сокращает использование токенов Claude API на **30-65% в зависимости от структуры данных** благодаря прозрачному преобразованию в формат TOON, с типичной экономией **50-55%** для структурированных данных.
7
+
8
+ ## Что нового в v0.3.0
9
+
10
+ ✨ **Многоязычная оптимизация токенов!**
11
+ - ✅ Точный подсчет токенов для 15+ языков (китайский, японский, корейский, испанский, арабский и др.)
12
+ - ✅ Языково-зависимые множители токенов (2x для китайского, 2.5x для японского, 3x для арабского)
13
+ - ✅ Поддержка смешанных языков с автоматическим определением
14
+ - ✅ Улучшенная точность оптимизации на основе реальных тестов
15
+ - ✅ Подтвержденные данными заявления об экономии токенов (диапазон 30-65%, обычно 50-55%)
16
+
17
+ ## Возможности
18
+
19
+ - **Сокращение токенов на 30-65%** (обычно 50-55%) для данных JSON, CSV, YAML
20
+ - **Многоязычная поддержка** - точный подсчет токенов для 15+ языков
21
+ - **Полностью автоматический режим** - хук PostToolUse перехватывает результаты инструментов
22
+ - **Нулевая конфигурация** - работает из коробки с разумными настройками по умолчанию
23
+ - **Двойной режим** - работает как плагин (авто) или MCP-сервер (вручную)
24
+ - **Встроенные метрики** - отслеживание экономии токенов локально
25
+ - **Тихий откат** - никогда не нарушает ваш рабочий процесс
26
+
27
+ ## Установка
28
+
29
+ ### Вариант A: Плагин Claude Code (Рекомендуется) ⭐
30
+
31
+ **Автоматическая оптимизация токенов без ручных вызовов:**
32
+
33
+ ```bash
34
+ # 1. Установить глобально
35
+ npm install -g toonify-mcp
36
+
37
+ # 2. Добавить как плагин (автоматический режим)
38
+ claude plugin add toonify-mcp
39
+
40
+ # 3. Проверить установку
41
+ claude plugin list
42
+ # Должно показать: toonify-mcp ✓
43
+ ```
44
+
45
+ **Вот и всё!** Хук PostToolUse теперь будет автоматически перехватывать и оптимизировать структурированные данные из инструментов Read, Grep и других файловых инструментов.
46
+
47
+ ### Вариант B: MCP-сервер (Ручной режим)
48
+
49
+ **Для явного контроля или других MCP-клиентов:**
50
+
51
+ ```bash
52
+ # 1. Установить глобально
53
+ npm install -g toonify-mcp
54
+
55
+ # 2. Зарегистрировать как MCP-сервер
56
+ claude mcp add toonify -- toonify-mcp
57
+
58
+ # 3. Проверить
59
+ claude mcp list
60
+ # Должно показать: toonify: toonify-mcp - ✓ Connected
61
+ ```
62
+
63
+ Затем вызывайте инструменты явно:
64
+ ```bash
65
+ claude mcp call toonify optimize_content '{"content": "..."}'
66
+ claude mcp call toonify get_stats '{}'
67
+ ```
68
+
69
+ ## Как это работает
70
+
71
+ ### Режим плагина (Автоматический)
72
+
73
+ ```
74
+ Пользователь: Прочитать большой JSON-файл
75
+
76
+ Claude Code вызывает инструмент Read
77
+
78
+ Хук PostToolUse перехватывает результат
79
+
80
+ Хук определяет JSON, преобразует в TOON
81
+
82
+ Оптимизированный контент отправляется в Claude API
83
+
84
+ Достигается типичное сокращение токенов на 50-55% ✨
85
+ ```
86
+
87
+ ### Режим MCP-сервера (Ручной)
88
+
89
+ ```
90
+ Пользователь: явно вызывает mcp__toonify__optimize_content
91
+
92
+ Контент преобразуется в формат TOON
93
+
94
+ Возвращается оптимизированный результат
95
+ ```
96
+
97
+ ## Конфигурация
98
+
99
+ Создайте `~/.claude/toonify-config.json` (необязательно):
100
+
101
+ ```json
102
+ {
103
+ "enabled": true,
104
+ "minTokensThreshold": 50,
105
+ "minSavingsThreshold": 30,
106
+ "skipToolPatterns": ["Bash", "Write", "Edit"]
107
+ }
108
+ ```
109
+
110
+ ### Параметры
111
+
112
+ - **enabled**: Включить/отключить автоматическую оптимизацию (по умолчанию: `true`)
113
+ - **minTokensThreshold**: Минимальное количество токенов перед оптимизацией (по умолчанию: `50`)
114
+ - **minSavingsThreshold**: Минимальный требуемый процент экономии (по умолчанию: `30%`)
115
+ - **skipToolPatterns**: Инструменты, которые никогда не оптимизировать (по умолчанию: `["Bash", "Write", "Edit"]`)
116
+
117
+ ### Переменные окружения
118
+
119
+ ```bash
120
+ export TOONIFY_ENABLED=true
121
+ export TOONIFY_MIN_TOKENS=50
122
+ export TOONIFY_MIN_SAVINGS=30
123
+ export TOONIFY_SKIP_TOOLS="Bash,Write"
124
+ export TOONIFY_SHOW_STATS=true # Показывать статистику оптимизации в выводе
125
+ ```
126
+
127
+ ## Примеры
128
+
129
+ ### До оптимизации (142 токена)
130
+
131
+ ```json
132
+ {
133
+ "products": [
134
+ {"id": 101, "name": "Laptop Pro", "price": 1299},
135
+ {"id": 102, "name": "Magic Mouse", "price": 79}
136
+ ]
137
+ }
138
+ ```
139
+
140
+ ### После оптимизации (57 токенов, -60%)
141
+
142
+ ```
143
+ [TOON-JSON]
144
+ products[2]{id,name,price}:
145
+ 101,Laptop Pro,1299
146
+ 102,Magic Mouse,79
147
+ ```
148
+
149
+ **Автоматически применяется в режиме плагина - ручные вызовы не нужны!**
150
+
151
+ ## Советы по использованию
152
+
153
+ ### Когда срабатывает автоматическая оптимизация?
154
+
155
+ Хук PostToolUse автоматически оптимизирует, когда:
156
+ - ✅ Контент является валидным JSON, CSV или YAML
157
+ - ✅ Размер контента ≥ `minTokensThreshold` (по умолчанию: 50 токенов)
158
+ - ✅ Предполагаемая экономия ≥ `minSavingsThreshold` (по умолчанию: 30%)
159
+ - ✅ Инструмент НЕ входит в `skipToolPatterns` (например, не Bash/Write/Edit)
160
+
161
+ ### Просмотр статистики оптимизации
162
+
163
+ ```bash
164
+ # В режиме плагина
165
+ claude mcp call toonify get_stats '{}'
166
+
167
+ # Или проверьте вывод Claude Code для статистики (если TOONIFY_SHOW_STATS=true)
168
+ ```
169
+
170
+ ## Устранение неполадок
171
+
172
+ ### Хук не срабатывает
173
+
174
+ ```bash
175
+ # 1. Проверьте, что плагин установлен
176
+ claude plugin list | grep toonify
177
+
178
+ # 2. Проверьте конфигурацию
179
+ cat ~/.claude/toonify-config.json
180
+
181
+ # 3. Включите статистику для просмотра попыток оптимизации
182
+ export TOONIFY_SHOW_STATS=true
183
+ ```
184
+
185
+ ### Оптимизация не применяется
186
+
187
+ - Проверьте `minTokensThreshold` - контент может быть слишком мал
188
+ - Проверьте `minSavingsThreshold` - экономия может быть < 30%
189
+ - Проверьте `skipToolPatterns` - инструмент может быть в списке пропуска
190
+ - Убедитесь, что контент является валидным JSON/CSV/YAML
191
+
192
+ ### Проблемы с производительностью
193
+
194
+ - Уменьшите `minTokensThreshold` для более агрессивной оптимизации
195
+ - Увеличьте `minSavingsThreshold` для пропуска незначительных оптимизаций
196
+ - Добавьте больше инструментов в `skipToolPatterns` при необходимости
197
+
198
+ ## Сравнение: Плагин vs MCP-сервер
199
+
200
+ | Функция | Режим плагина | Режим MCP-сервера |
201
+ |---------|--------------|-------------------|
202
+ | **Активация** | Автоматическая (PostToolUse) | Ручная (вызов инструмента) |
203
+ | **Совместимость** | Только Claude Code | Любой MCP-клиент |
204
+ | **Конфигурация** | Файл конфигурации плагина | Инструменты MCP |
205
+ | **Производительность** | Нулевые накладные расходы | Накладные расходы на вызов |
206
+ | **Сценарий использования** | Ежедневный рабочий процесс | Явный контроль |
207
+
208
+ **Рекомендация**: Используйте режим плагина для автоматической оптимизации. Используйте режим MCP-сервера для явного контроля или других MCP-клиентов.
209
+
210
+ ## Удаление
211
+
212
+ ### Режим плагина
213
+ ```bash
214
+ claude plugin remove toonify-mcp
215
+ rm ~/.claude/toonify-config.json
216
+ ```
217
+
218
+ ### Режим MCP-сервера
219
+ ```bash
220
+ claude mcp remove toonify
221
+ ```
222
+
223
+ ### Пакет
224
+ ```bash
225
+ npm uninstall -g toonify-mcp
226
+ ```
227
+
228
+ ## Ссылки
229
+
230
+ - **GitHub**: https://github.com/kevintseng/toonify-mcp
231
+ - **Issues**: https://github.com/kevintseng/toonify-mcp/issues
232
+ - **NPM**: https://www.npmjs.com/package/toonify-mcp
233
+ - **MCP Docs**: https://code.claude.com/docs/mcp
234
+ - **TOON Format**: https://github.com/toon-format/toon
235
+
236
+ ## Вклад в проект
237
+
238
+ Вклады приветствуются! Пожалуйста, ознакомьтесь с [CONTRIBUTING.md](CONTRIBUTING.md) для получения рекомендаций.
239
+
240
+ ## Лицензия
241
+
242
+ Лицензия MIT - см. [LICENSE](LICENSE)
243
+
244
+ ## Changelog
245
+
246
+ ### v0.3.0 (2025-12-26)
247
+ - ✨ **Многоязычная оптимизация токенов** - точный подсчет для 15+ языков
248
+ - ✨ Языково-зависимые множители токенов (2x китайский, 2.5x японский, 3x арабский и др.)
249
+ - ✨ Определение и оптимизация смешанных языков
250
+ - ✨ Комплексное тестирование с реальной статистикой
251
+ - 📊 Подтвержденные данными заявления об экономии токенов (диапазон 30-65%, обычно 50-55%)
252
+ - ✅ 75+ пройденных тестов, включая многоязычные граничные случаи
253
+ - 📝 Многоязычные версии README
254
+
255
+ ### v0.2.0 (2025-12-25)
256
+ - ✨ Добавлена поддержка плагина Claude Code с хуком PostToolUse
257
+ - ✨ Автоматическая оптимизация токенов (ручные вызовы не нужны)
258
+ - ✨ Система конфигурации плагина
259
+ - ✨ Двойной режим: Плагин (авто) + MCP-сервер (вручную)
260
+ - 📝 Комплексное обновление документации
261
+
262
+ ### v0.1.1 (2024-12-24)
263
+ - 🐛 Исправления ошибок и улучшения
264
+ - 📝 Обновления документации
265
+
266
+ ### v0.1.0 (2024-12-24)
267
+ - 🎉 Первый релиз
268
+ - ✨ Реализация MCP-сервера
269
+ - ✨ Оптимизация формата TOON
270
+ - ✨ Встроенное отслеживание метрик
package/README.vi.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # 🎯 Toonify MCP
2
2
 
3
- **[English](README.md) | [繁體中文](README.zh-TW.md) | [简体中文](README.zh-CN.md) | [日本語](README.ja.md) | [Español](README.es.md) | [Tiếng Việt](README.vi.md) | [Bahasa Indonesia](README.id.md)**
3
+ **[English](README.md) | [繁體中文](README.zh-TW.md) | [简体中文](README.zh-CN.md) | [日本語](README.ja.md) | [Español](README.es.md) | [Français](README.fr.md) | [Deutsch](README.de.md) | [한국어](README.ko.md) | [Русский](README.ru.md) | [Português](README.pt.md) | [Tiếng Việt](README.vi.md) | [Bahasa Indonesia](README.id.md)**
4
4
 
5
5
  Máy chủ MCP + Plugin Claude Code cung cấp tối ưu hóa token tự động cho dữ liệu có cấu trúc.
6
6
  Giảm 30-65% việc sử dụng token của Claude API **tùy thuộc vào cấu trúc dữ liệu** thông qua chuyển đổi định dạng TOON minh bạch, với mức tiết kiệm điển hình **50-55%** cho dữ liệu có cấu trúc.
package/README.zh-CN.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # 🎯 Toonify MCP
2
2
 
3
- **[English](README.md) | [繁體中文](README.zh-TW.md) | [简体中文](README.zh-CN.md) | [日本語](README.ja.md) | [Español](README.es.md) | [Tiếng Việt](README.vi.md) | [Bahasa Indonesia](README.id.md)**
3
+ **[English](README.md) | [繁體中文](README.zh-TW.md) | [简体中文](README.zh-CN.md) | [日本語](README.ja.md) | [Español](README.es.md) | [Français](README.fr.md) | [Deutsch](README.de.md) | [한국어](README.ko.md) | [Русский](README.ru.md) | [Português](README.pt.md) | [Tiếng Việt](README.vi.md) | [Bahasa Indonesia](README.id.md)**
4
4
 
5
5
  MCP 服务器 + Claude Code 插件,提供结构化数据的自动 token 优化。
6
6
  通过透明的 TOON 格式转换,**根据数据结构减少 30-65% 的 Claude API token 使用量**,结构化数据的典型节省率为 **50-55%**。
package/README.zh-TW.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # 🎯 Toonify MCP
2
2
 
3
- **[English](README.md) | [繁體中文](README.zh-TW.md) | [简体中文](README.zh-CN.md) | [日本語](README.ja.md) | [Español](README.es.md) | [Tiếng Việt](README.vi.md) | [Bahasa Indonesia](README.id.md)**
3
+ **[English](README.md) | [繁體中文](README.zh-TW.md) | [简体中文](README.zh-CN.md) | [日本語](README.ja.md) | [Español](README.es.md) | [Français](README.fr.md) | [Deutsch](README.de.md) | [한국어](README.ko.md) | [Русский](README.ru.md) | [Português](README.pt.md) | [Tiếng Việt](README.vi.md) | [Bahasa Indonesia](README.id.md)**
4
4
 
5
5
  MCP 伺服器 + Claude Code 外掛程式,提供結構化數據的自動 token 優化。
6
6
  透過透明的 TOON 格式轉換,**根據數據結構減少 30-65% 的 Claude API token 使用量**,結構化數據的典型節省率為 **50-55%**。
@@ -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