tachibot-mcp 2.0.2

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 (214) hide show
  1. package/.env.example +260 -0
  2. package/CHANGELOG.md +54 -0
  3. package/CODE_OF_CONDUCT.md +56 -0
  4. package/CONTRIBUTING.md +54 -0
  5. package/Dockerfile +36 -0
  6. package/LICENSE +644 -0
  7. package/README.md +201 -0
  8. package/SECURITY.md +95 -0
  9. package/dist/personality/komaai-expressions.js +12 -0
  10. package/dist/profiles/balanced.json +33 -0
  11. package/dist/profiles/code_focus.json +33 -0
  12. package/dist/profiles/full.json +33 -0
  13. package/dist/profiles/minimal.json +33 -0
  14. package/dist/profiles/research_power.json +33 -0
  15. package/dist/scripts/build-profiles.js +46 -0
  16. package/dist/src/application/services/focus/FocusModeRegistry.js +46 -0
  17. package/dist/src/application/services/focus/FocusTool.service.js +109 -0
  18. package/dist/src/application/services/focus/ModeRegistry.js +46 -0
  19. package/dist/src/application/services/focus/modes/focus-deep.mode.js +27 -0
  20. package/dist/src/application/services/focus/modes/status.mode.js +50 -0
  21. package/dist/src/application/services/focus/modes/tachibot-status.mode.js +50 -0
  22. package/dist/src/collaborative-orchestrator.js +391 -0
  23. package/dist/src/config/model-constants.js +188 -0
  24. package/dist/src/config/model-defaults.js +57 -0
  25. package/dist/src/config/model-preferences.js +382 -0
  26. package/dist/src/config/timeout-config.js +130 -0
  27. package/dist/src/config.js +173 -0
  28. package/dist/src/domain/interfaces/IFocusMode.js +5 -0
  29. package/dist/src/domain/interfaces/IProvider.js +6 -0
  30. package/dist/src/domain/interfaces/ITool.js +5 -0
  31. package/dist/src/focus-deep.js +245 -0
  32. package/dist/src/infrastructure/ascii/art/robots.ascii.js +16 -0
  33. package/dist/src/mcp-client.js +90 -0
  34. package/dist/src/memory/index.js +17 -0
  35. package/dist/src/memory/memory-config.js +135 -0
  36. package/dist/src/memory/memory-interface.js +174 -0
  37. package/dist/src/memory/memory-manager.js +383 -0
  38. package/dist/src/memory/providers/devlog-provider.js +385 -0
  39. package/dist/src/memory/providers/hybrid-provider.js +399 -0
  40. package/dist/src/memory/providers/local-provider.js +388 -0
  41. package/dist/src/memory/providers/mem0-provider.js +337 -0
  42. package/dist/src/modes/architect.js +477 -0
  43. package/dist/src/modes/auditor.js +362 -0
  44. package/dist/src/modes/challenger.js +841 -0
  45. package/dist/src/modes/code-reviewer.js +382 -0
  46. package/dist/src/modes/commit-guardian.js +424 -0
  47. package/dist/src/modes/documentation-writer.js +572 -0
  48. package/dist/src/modes/scout.js +587 -0
  49. package/dist/src/modes/shared/helpers/challenger-helpers.js +454 -0
  50. package/dist/src/modes/shared/helpers/index.js +17 -0
  51. package/dist/src/modes/shared/helpers/scout-helpers.js +270 -0
  52. package/dist/src/modes/shared/helpers/verifier-helpers.js +332 -0
  53. package/dist/src/modes/test-architect.js +767 -0
  54. package/dist/src/modes/verifier.js +378 -0
  55. package/dist/src/monitoring/performance-monitor.js +435 -0
  56. package/dist/src/optimization/batch-executor.js +121 -0
  57. package/dist/src/optimization/context-pruner.js +196 -0
  58. package/dist/src/optimization/cost-monitor.js +338 -0
  59. package/dist/src/optimization/index.js +65 -0
  60. package/dist/src/optimization/model-router.js +264 -0
  61. package/dist/src/optimization/result-cache.js +114 -0
  62. package/dist/src/optimization/token-optimizer.js +257 -0
  63. package/dist/src/optimization/token-tracker.js +118 -0
  64. package/dist/src/orchestrator-instructions.js +128 -0
  65. package/dist/src/orchestrator-lite.js +139 -0
  66. package/dist/src/orchestrator.js +191 -0
  67. package/dist/src/orchestrators/collaborative/interfaces/IToolExecutionEngine.js +1 -0
  68. package/dist/src/orchestrators/collaborative/interfaces/IToolExecutionStrategy.js +5 -0
  69. package/dist/src/orchestrators/collaborative/interfaces/IVisualizationRenderer.js +1 -0
  70. package/dist/src/orchestrators/collaborative/registries/ModelProviderRegistry.js +95 -0
  71. package/dist/src/orchestrators/collaborative/registries/ToolAdapterRegistry.js +64 -0
  72. package/dist/src/orchestrators/collaborative/services/tool-execution/ToolExecutionService.js +502 -0
  73. package/dist/src/orchestrators/collaborative/services/visualization/VisualizationService.js +206 -0
  74. package/dist/src/orchestrators/collaborative/types/session-types.js +5 -0
  75. package/dist/src/profiles/balanced.js +37 -0
  76. package/dist/src/profiles/code_focus.js +37 -0
  77. package/dist/src/profiles/debug_intensive.js +59 -0
  78. package/dist/src/profiles/full.js +37 -0
  79. package/dist/src/profiles/minimal.js +37 -0
  80. package/dist/src/profiles/research_code.js +59 -0
  81. package/dist/src/profiles/research_power.js +37 -0
  82. package/dist/src/profiles/types.js +5 -0
  83. package/dist/src/profiles/workflow_builder.js +53 -0
  84. package/dist/src/prompt-engineer-lite.js +78 -0
  85. package/dist/src/prompt-engineer.js +399 -0
  86. package/dist/src/reasoning-chain.js +508 -0
  87. package/dist/src/sequential-thinking.js +291 -0
  88. package/dist/src/server-diagnostic.js +74 -0
  89. package/dist/src/server-raw.js +158 -0
  90. package/dist/src/server-simple.js +58 -0
  91. package/dist/src/server.js +514 -0
  92. package/dist/src/session/session-logger.js +617 -0
  93. package/dist/src/session/session-manager.js +571 -0
  94. package/dist/src/session/session-tools.js +400 -0
  95. package/dist/src/tools/advanced-modes.js +200 -0
  96. package/dist/src/tools/claude-integration.js +356 -0
  97. package/dist/src/tools/consolidated/ai-router.js +174 -0
  98. package/dist/src/tools/consolidated/ai-tool.js +48 -0
  99. package/dist/src/tools/consolidated/brainstorm-tool.js +87 -0
  100. package/dist/src/tools/consolidated/environment-detector.js +80 -0
  101. package/dist/src/tools/consolidated/index.js +50 -0
  102. package/dist/src/tools/consolidated/search-tool.js +110 -0
  103. package/dist/src/tools/consolidated/workflow-tool.js +238 -0
  104. package/dist/src/tools/gemini-tools.js +329 -0
  105. package/dist/src/tools/grok-enhanced.js +376 -0
  106. package/dist/src/tools/grok-tools.js +299 -0
  107. package/dist/src/tools/lmstudio-tools.js +223 -0
  108. package/dist/src/tools/openai-tools.js +498 -0
  109. package/dist/src/tools/openrouter-tools.js +317 -0
  110. package/dist/src/tools/optimized-wrapper.js +204 -0
  111. package/dist/src/tools/perplexity-tools.js +294 -0
  112. package/dist/src/tools/pingpong-tool.js +343 -0
  113. package/dist/src/tools/qwen-wrapper.js +74 -0
  114. package/dist/src/tools/tool-router.js +444 -0
  115. package/dist/src/tools/unified-ai-provider.js +260 -0
  116. package/dist/src/tools/workflow-runner.js +425 -0
  117. package/dist/src/tools/workflow-validator-tool.js +107 -0
  118. package/dist/src/types.js +23 -0
  119. package/dist/src/utils/input-validator.js +130 -0
  120. package/dist/src/utils/model-router.js +91 -0
  121. package/dist/src/utils/progress-stream.js +255 -0
  122. package/dist/src/utils/provider-router.js +88 -0
  123. package/dist/src/utils/smart-api-client.js +146 -0
  124. package/dist/src/utils/table-builder.js +218 -0
  125. package/dist/src/utils/timestamp-formatter.js +134 -0
  126. package/dist/src/utils/tool-compressor.js +257 -0
  127. package/dist/src/utils/tool-config.js +201 -0
  128. package/dist/src/validators/dependency-graph-validator.js +147 -0
  129. package/dist/src/validators/interpolation-validator.js +222 -0
  130. package/dist/src/validators/output-usage-validator.js +151 -0
  131. package/dist/src/validators/syntax-validator.js +102 -0
  132. package/dist/src/validators/tool-registry-validator.js +123 -0
  133. package/dist/src/validators/tool-types.js +97 -0
  134. package/dist/src/validators/types.js +8 -0
  135. package/dist/src/validators/workflow-validator.js +134 -0
  136. package/dist/src/visualizer-lite.js +42 -0
  137. package/dist/src/visualizer.js +179 -0
  138. package/dist/src/workflows/circuit-breaker.js +199 -0
  139. package/dist/src/workflows/custom-workflows.js +451 -0
  140. package/dist/src/workflows/engine/AutoSynthesizer.js +97 -0
  141. package/dist/src/workflows/engine/StepParameterResolver.js +74 -0
  142. package/dist/src/workflows/engine/VariableInterpolator.js +123 -0
  143. package/dist/src/workflows/engine/WorkflowDiscovery.js +125 -0
  144. package/dist/src/workflows/engine/WorkflowExecutionEngine.js +485 -0
  145. package/dist/src/workflows/engine/WorkflowExecutor.js +113 -0
  146. package/dist/src/workflows/engine/WorkflowFileManager.js +244 -0
  147. package/dist/src/workflows/engine/WorkflowHelpers.js +114 -0
  148. package/dist/src/workflows/engine/WorkflowOutputFormatter.js +83 -0
  149. package/dist/src/workflows/engine/events/WorkflowEventBus.js +132 -0
  150. package/dist/src/workflows/engine/events/interfaces/IEventBus.js +5 -0
  151. package/dist/src/workflows/engine/handlers/ErrorRecoveryHandler.js +162 -0
  152. package/dist/src/workflows/engine/handlers/PromptEnhancementHandler.js +115 -0
  153. package/dist/src/workflows/engine/handlers/SessionPersistenceHandler.js +167 -0
  154. package/dist/src/workflows/engine/handlers/StepExecutionHandler.js +231 -0
  155. package/dist/src/workflows/engine/handlers/ToolInvocationHandler.js +46 -0
  156. package/dist/src/workflows/engine/interfaces/IAutoSynthesizer.js +5 -0
  157. package/dist/src/workflows/engine/interfaces/IStepParameterResolver.js +5 -0
  158. package/dist/src/workflows/engine/interfaces/IVariableInterpolator.js +5 -0
  159. package/dist/src/workflows/engine/interfaces/IWorkflowDiscovery.js +4 -0
  160. package/dist/src/workflows/engine/interfaces/IWorkflowFileManager.js +5 -0
  161. package/dist/src/workflows/engine/interfaces/IWorkflowOutputFormatter.js +5 -0
  162. package/dist/src/workflows/engine/state/WorkflowStateMachine.js +194 -0
  163. package/dist/src/workflows/engine/state/interfaces/IStateMachine.js +17 -0
  164. package/dist/src/workflows/fallback-strategies.js +373 -0
  165. package/dist/src/workflows/message-queue.js +455 -0
  166. package/dist/src/workflows/model-router.js +189 -0
  167. package/dist/src/workflows/orchestrator-examples.js +174 -0
  168. package/dist/src/workflows/orchestrator-integration.js +200 -0
  169. package/dist/src/workflows/self-healing.js +524 -0
  170. package/dist/src/workflows/tool-mapper.js +407 -0
  171. package/dist/src/workflows/tool-orchestrator.js +796 -0
  172. package/dist/src/workflows/workflow-engine.js +573 -0
  173. package/dist/src/workflows/workflow-parser.js +283 -0
  174. package/dist/src/workflows/workflow-types.js +95 -0
  175. package/dist/src/workflows.js +568 -0
  176. package/dist/test-workflow-file-output.js +93 -0
  177. package/docs/API_KEYS.md +570 -0
  178. package/docs/CLAUDE_CODE_SETUP.md +181 -0
  179. package/docs/CLAUDE_DESKTOP_MANUAL.md +127 -0
  180. package/docs/CONFIGURATION.md +745 -0
  181. package/docs/FOCUS_MODES.md +240 -0
  182. package/docs/INSTALLATION_BOTH.md +145 -0
  183. package/docs/TERMS.md +352 -0
  184. package/docs/TOOLS_REFERENCE.md +1622 -0
  185. package/docs/TOOL_PARAMETERS.md +496 -0
  186. package/docs/TOOL_PROFILES.md +236 -0
  187. package/docs/WORKFLOWS.md +987 -0
  188. package/docs/WORKFLOW_OUTPUT.md +198 -0
  189. package/docs/WORKFLOW_PROGRESS_TRACKING.md +305 -0
  190. package/docs/workflows/design-brainstorm.md +335 -0
  191. package/package.json +97 -0
  192. package/profiles/balanced.json +37 -0
  193. package/profiles/code_focus.json +37 -0
  194. package/profiles/debug_intensive.json +34 -0
  195. package/profiles/full.json +37 -0
  196. package/profiles/minimal.json +37 -0
  197. package/profiles/research_power.json +37 -0
  198. package/profiles/workflow_builder.json +37 -0
  199. package/smithery.yaml +66 -0
  200. package/start.sh +8 -0
  201. package/tools.config.json +81 -0
  202. package/tsconfig.json +18 -0
  203. package/workflows/accessibility-code-audit.yaml +92 -0
  204. package/workflows/code-architecture-review.yaml +202 -0
  205. package/workflows/code-review.yaml +142 -0
  206. package/workflows/core/iterative-problem-solver.yaml +283 -0
  207. package/workflows/creative-brainstorm-yaml.yaml +215 -0
  208. package/workflows/pingpong.yaml +141 -0
  209. package/workflows/system/README.md +412 -0
  210. package/workflows/system/challenger.yaml +175 -0
  211. package/workflows/system/scout.yaml +164 -0
  212. package/workflows/system/verifier.yaml +133 -0
  213. package/workflows/ultra-creative-brainstorm.yaml +318 -0
  214. package/workflows/ux-research-flow.yaml +92 -0
@@ -0,0 +1,388 @@
1
+ /**
2
+ * Local Memory Provider
3
+ * Local storage implementation using JSON, SQLite, or LevelDB
4
+ */
5
+ import { BaseMemoryProvider } from '../memory-interface.js';
6
+ import * as fs from 'fs/promises';
7
+ import * as path from 'path';
8
+ /**
9
+ * Local provider implementation
10
+ */
11
+ export class LocalProvider extends BaseMemoryProvider {
12
+ constructor(config) {
13
+ super();
14
+ this.name = 'local';
15
+ this.memoryStore = new Map();
16
+ this.indexByTier = new Map();
17
+ this.indexByProject = new Map();
18
+ this.indexByUser = new Map();
19
+ this.autosaveInterval = null;
20
+ this.config = {
21
+ ...config,
22
+ storageType: config.storageType || 'json',
23
+ path: config.path || './.focus-memory',
24
+ maxSizeMB: config.maxSizeMB || 100,
25
+ enableCompression: config.enableCompression !== false
26
+ };
27
+ this.storagePath = path.resolve(this.config.path);
28
+ // Initialize indexes
29
+ const tiers = ['session', 'working', 'project', 'team', 'global'];
30
+ tiers.forEach(tier => this.indexByTier.set(tier, new Set()));
31
+ }
32
+ async doInitialize() {
33
+ try {
34
+ // Ensure storage directory exists
35
+ await fs.mkdir(path.dirname(this.storagePath), { recursive: true });
36
+ // Load existing data
37
+ await this.loadFromDisk();
38
+ // Set up autosave
39
+ this.autosaveInterval = setInterval(() => {
40
+ this.saveToDisk().catch(console.error);
41
+ }, 30000); // Save every 30 seconds
42
+ console.error(`Local provider initialized at ${this.storagePath}`);
43
+ }
44
+ catch (error) {
45
+ console.error('Failed to initialize local provider:', error);
46
+ throw error;
47
+ }
48
+ }
49
+ async store(item) {
50
+ // Generate ID if not provided
51
+ if (!item.id) {
52
+ item.id = this.generateId();
53
+ }
54
+ // Check storage limits
55
+ if (await this.isStorageFull()) {
56
+ // Remove oldest session memories to make space
57
+ await this.cleanupOldestMemories();
58
+ }
59
+ // Store in memory
60
+ this.memoryStore.set(item.id, item);
61
+ // Update indexes
62
+ this.indexByTier.get(item.tier)?.add(item.id);
63
+ if (item.projectId) {
64
+ if (!this.indexByProject.has(item.projectId)) {
65
+ this.indexByProject.set(item.projectId, new Set());
66
+ }
67
+ this.indexByProject.get(item.projectId)?.add(item.id);
68
+ }
69
+ if (item.userId) {
70
+ if (!this.indexByUser.has(item.userId)) {
71
+ this.indexByUser.set(item.userId, new Set());
72
+ }
73
+ this.indexByUser.get(item.userId)?.add(item.id);
74
+ }
75
+ // Update metrics
76
+ this.metrics.totalItems++;
77
+ this.metrics.itemsByTier[item.tier]++;
78
+ // Save to disk (async, don't wait)
79
+ this.saveToDisk().catch(console.error);
80
+ return item.id;
81
+ }
82
+ async retrieve(query) {
83
+ const startTime = Date.now();
84
+ let candidates = new Set();
85
+ // Start with all items if no specific filters
86
+ if (!query.userId && !query.projectId && !query.tiers) {
87
+ candidates = new Set(this.memoryStore.keys());
88
+ }
89
+ // Filter by tier
90
+ if (query.tiers && query.tiers.length > 0) {
91
+ for (const tier of query.tiers) {
92
+ const tierItems = this.indexByTier.get(tier);
93
+ if (tierItems) {
94
+ tierItems.forEach(id => candidates.add(id));
95
+ }
96
+ }
97
+ }
98
+ // Filter by project
99
+ if (query.projectId) {
100
+ const projectItems = this.indexByProject.get(query.projectId) || new Set();
101
+ if (candidates.size > 0) {
102
+ // Intersection
103
+ candidates = new Set([...candidates].filter(id => projectItems.has(id)));
104
+ }
105
+ else {
106
+ candidates = projectItems;
107
+ }
108
+ }
109
+ // Filter by user
110
+ if (query.userId) {
111
+ const userItems = this.indexByUser.get(query.userId) || new Set();
112
+ if (candidates.size > 0) {
113
+ // Intersection
114
+ candidates = new Set([...candidates].filter(id => userItems.has(id)));
115
+ }
116
+ else {
117
+ candidates = userItems;
118
+ }
119
+ }
120
+ // Convert to items
121
+ let items = [];
122
+ candidates.forEach(id => {
123
+ const item = this.memoryStore.get(id);
124
+ if (item) {
125
+ items.push(item);
126
+ }
127
+ });
128
+ // Filter by date range
129
+ if (query.startDate || query.endDate) {
130
+ items = items.filter(item => {
131
+ const itemDate = item.timestamp.getTime();
132
+ if (query.startDate && itemDate < query.startDate.getTime())
133
+ return false;
134
+ if (query.endDate && itemDate > query.endDate.getTime())
135
+ return false;
136
+ return true;
137
+ });
138
+ }
139
+ // Filter by tags
140
+ if (query.tags && query.tags.length > 0) {
141
+ items = items.filter(item => {
142
+ if (!item.tags)
143
+ return false;
144
+ return query.tags.some(tag => item.tags.includes(tag));
145
+ });
146
+ }
147
+ // Text search (simple substring match)
148
+ if (query.text) {
149
+ const searchText = query.text.toLowerCase();
150
+ items = items.filter(item => item.content.toLowerCase().includes(searchText));
151
+ }
152
+ // Sort by recency
153
+ items.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());
154
+ // Apply limit and offset
155
+ if (query.offset) {
156
+ items = items.slice(query.offset);
157
+ }
158
+ if (query.limit) {
159
+ items = items.slice(0, query.limit);
160
+ }
161
+ // Update metrics
162
+ const retrievalTime = Date.now() - startTime;
163
+ this.metrics.avgRetrievalTime =
164
+ (this.metrics.avgRetrievalTime + retrievalTime) / 2;
165
+ // Update access counts
166
+ items.forEach(item => {
167
+ item.accessCount = (item.accessCount || 0) + 1;
168
+ item.lastAccessed = new Date();
169
+ });
170
+ return items;
171
+ }
172
+ async update(id, updates) {
173
+ const item = this.memoryStore.get(id);
174
+ if (!item)
175
+ return false;
176
+ // Update the item
177
+ Object.assign(item, updates);
178
+ // Update indexes if tier changed
179
+ if (updates.tier && updates.tier !== item.tier) {
180
+ this.indexByTier.get(item.tier)?.delete(id);
181
+ this.indexByTier.get(updates.tier)?.add(id);
182
+ }
183
+ // Save to disk
184
+ await this.saveToDisk();
185
+ return true;
186
+ }
187
+ async delete(id) {
188
+ const item = this.memoryStore.get(id);
189
+ if (!item)
190
+ return false;
191
+ // Remove from store
192
+ this.memoryStore.delete(id);
193
+ // Remove from indexes
194
+ this.indexByTier.get(item.tier)?.delete(id);
195
+ if (item.projectId) {
196
+ this.indexByProject.get(item.projectId)?.delete(id);
197
+ }
198
+ if (item.userId) {
199
+ this.indexByUser.get(item.userId)?.delete(id);
200
+ }
201
+ // Update metrics
202
+ this.metrics.totalItems--;
203
+ this.metrics.itemsByTier[item.tier]--;
204
+ // Save to disk
205
+ await this.saveToDisk();
206
+ return true;
207
+ }
208
+ async cleanup() {
209
+ const now = Date.now();
210
+ let cleaned = 0;
211
+ // Clean up expired items based on TTL
212
+ const itemsToDelete = [];
213
+ this.memoryStore.forEach((item, id) => {
214
+ if (item.ttl && item.ttl > 0) {
215
+ const expiryTime = item.timestamp.getTime() + (item.ttl * 60 * 1000);
216
+ if (now > expiryTime) {
217
+ itemsToDelete.push(id);
218
+ }
219
+ }
220
+ });
221
+ // Delete expired items
222
+ for (const id of itemsToDelete) {
223
+ if (await this.delete(id)) {
224
+ cleaned++;
225
+ }
226
+ }
227
+ // Save to disk after cleanup
228
+ await this.saveToDisk();
229
+ return cleaned;
230
+ }
231
+ async export() {
232
+ return Array.from(this.memoryStore.values());
233
+ }
234
+ async import(items) {
235
+ let imported = 0;
236
+ for (const item of items) {
237
+ try {
238
+ await this.store(item);
239
+ imported++;
240
+ }
241
+ catch (error) {
242
+ console.error(`Failed to import item ${item.id}:`, error);
243
+ }
244
+ }
245
+ return imported;
246
+ }
247
+ async close() {
248
+ // Save final state
249
+ await this.saveToDisk();
250
+ // Clear autosave interval
251
+ if (this.autosaveInterval) {
252
+ clearInterval(this.autosaveInterval);
253
+ this.autosaveInterval = null;
254
+ }
255
+ // Clear memory
256
+ this.memoryStore.clear();
257
+ this.indexByTier.clear();
258
+ this.indexByProject.clear();
259
+ this.indexByUser.clear();
260
+ await super.close();
261
+ }
262
+ /**
263
+ * Persistence methods
264
+ */
265
+ async loadFromDisk() {
266
+ try {
267
+ const dataFile = this.getDataFilePath();
268
+ // Check if file exists
269
+ try {
270
+ await fs.access(dataFile);
271
+ }
272
+ catch {
273
+ // File doesn't exist, start fresh
274
+ return;
275
+ }
276
+ // Read and parse data
277
+ const data = await fs.readFile(dataFile, 'utf-8');
278
+ let parsedData;
279
+ if (this.config.enableCompression) {
280
+ // Decompress if needed (simplified - real implementation would use zlib)
281
+ parsedData = JSON.parse(data);
282
+ }
283
+ else {
284
+ parsedData = JSON.parse(data);
285
+ }
286
+ // Restore memory store
287
+ if (parsedData.items) {
288
+ for (const item of parsedData.items) {
289
+ // Convert dates
290
+ item.timestamp = new Date(item.timestamp);
291
+ if (item.lastAccessed) {
292
+ item.lastAccessed = new Date(item.lastAccessed);
293
+ }
294
+ // Store without triggering save
295
+ this.memoryStore.set(item.id, item);
296
+ // Rebuild indexes
297
+ this.indexByTier.get(item.tier)?.add(item.id);
298
+ if (item.projectId) {
299
+ if (!this.indexByProject.has(item.projectId)) {
300
+ this.indexByProject.set(item.projectId, new Set());
301
+ }
302
+ this.indexByProject.get(item.projectId)?.add(item.id);
303
+ }
304
+ if (item.userId) {
305
+ if (!this.indexByUser.has(item.userId)) {
306
+ this.indexByUser.set(item.userId, new Set());
307
+ }
308
+ this.indexByUser.get(item.userId)?.add(item.id);
309
+ }
310
+ }
311
+ }
312
+ // Restore metrics
313
+ if (parsedData.metrics) {
314
+ this.metrics = parsedData.metrics;
315
+ }
316
+ console.error(`Loaded ${this.memoryStore.size} memories from disk`);
317
+ }
318
+ catch (error) {
319
+ console.error('Failed to load from disk:', error);
320
+ }
321
+ }
322
+ async saveToDisk() {
323
+ try {
324
+ const dataFile = this.getDataFilePath();
325
+ // Prepare data
326
+ const data = {
327
+ version: '1.0',
328
+ timestamp: new Date().toISOString(),
329
+ items: Array.from(this.memoryStore.values()),
330
+ metrics: this.metrics
331
+ };
332
+ // Serialize
333
+ let serialized = JSON.stringify(data, null, 2);
334
+ if (this.config.enableCompression) {
335
+ // Compress if needed (simplified - real implementation would use zlib)
336
+ // For now, just use regular JSON
337
+ }
338
+ // Write to temp file first
339
+ const tempFile = `${dataFile}.tmp`;
340
+ await fs.writeFile(tempFile, serialized, 'utf-8');
341
+ // Atomic rename
342
+ await fs.rename(tempFile, dataFile);
343
+ }
344
+ catch (error) {
345
+ console.error('Failed to save to disk:', error);
346
+ }
347
+ }
348
+ getDataFilePath() {
349
+ if (this.config.storageType === 'json') {
350
+ return `${this.storagePath}.json`;
351
+ }
352
+ // For SQLite or LevelDB, would return appropriate file
353
+ return `${this.storagePath}.db`;
354
+ }
355
+ async isStorageFull() {
356
+ if (!this.config.maxSizeMB)
357
+ return false;
358
+ try {
359
+ const dataFile = this.getDataFilePath();
360
+ const stats = await fs.stat(dataFile);
361
+ const sizeMB = stats.size / (1024 * 1024);
362
+ return sizeMB >= this.config.maxSizeMB;
363
+ }
364
+ catch {
365
+ return false;
366
+ }
367
+ }
368
+ async cleanupOldestMemories() {
369
+ // Remove oldest session memories first
370
+ const sessionMemories = Array.from(this.indexByTier.get('session') || [])
371
+ .map(id => this.memoryStore.get(id))
372
+ .filter(item => item)
373
+ .sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
374
+ // Remove oldest 10% of session memories
375
+ const toRemove = Math.ceil(sessionMemories.length * 0.1);
376
+ for (let i = 0; i < toRemove && i < sessionMemories.length; i++) {
377
+ await this.delete(sessionMemories[i].id);
378
+ }
379
+ }
380
+ }
381
+ /**
382
+ * Factory function to create local provider
383
+ */
384
+ export async function createLocalProvider(config) {
385
+ const provider = new LocalProvider(config);
386
+ await provider.initialize();
387
+ return provider;
388
+ }