claude-flow 2.7.23 → 2.7.24
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/bin/claude-flow +1 -1
- package/dist/src/cli/simple-cli.js.map +1 -1
- package/dist/src/cli/simple-commands/config.js +115 -257
- package/dist/src/cli/simple-commands/config.js.map +1 -1
- package/dist/src/core/version.js +1 -1
- package/dist/src/core/version.js.map +1 -1
- package/dist/src/utils/metrics-reader.js +0 -10
- package/docs/OPTIONAL_LOCAL_EMBEDDINGS.md +462 -0
- package/package.json +3 -2
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
# Optional: Local Semantic Search with Transformers.js
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
By default, the memory system works perfectly **without any embeddings** using database pattern matching. This optional enhancement adds true semantic search using local AI models.
|
|
6
|
+
|
|
7
|
+
## Current Default Behavior ✅
|
|
8
|
+
|
|
9
|
+
**Already works out of the box:**
|
|
10
|
+
```bash
|
|
11
|
+
npx claude-flow@alpha memory store "api-design" "REST with JWT"
|
|
12
|
+
npx claude-flow@alpha memory list
|
|
13
|
+
# ✅ Works perfectly - no setup required!
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**Memory query uses database fallback:**
|
|
17
|
+
```bash
|
|
18
|
+
npx claude-flow@alpha memory query "api"
|
|
19
|
+
# ✅ Works with pattern matching (exact/partial text search)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Optional Enhancement: True Semantic Search
|
|
23
|
+
|
|
24
|
+
Add AI-powered semantic similarity for better query results.
|
|
25
|
+
|
|
26
|
+
### Installation Options
|
|
27
|
+
|
|
28
|
+
**Option 1: Package-level (Recommended for Development)**
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# In agentic-flow repository
|
|
32
|
+
npm install @xenova/transformers --save-optional
|
|
33
|
+
|
|
34
|
+
# Or in claude-flow
|
|
35
|
+
npm install @xenova/transformers --save-optional
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Option 2: User-level (Recommended for Production)**
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Users can enable semantic search with:
|
|
42
|
+
npm install -g @xenova/transformers
|
|
43
|
+
|
|
44
|
+
# Or with npx:
|
|
45
|
+
npx -p @xenova/transformers -p claude-flow@alpha claude-flow memory query "api"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Option 3: Environment Variable Flag**
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Enable semantic search
|
|
52
|
+
export CLAUDE_FLOW_SEMANTIC_SEARCH=true
|
|
53
|
+
|
|
54
|
+
# Run memory commands
|
|
55
|
+
npx claude-flow@alpha memory query "authentication patterns"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Implementation Strategy
|
|
61
|
+
|
|
62
|
+
### 1. Make @xenova/transformers Optional in package.json
|
|
63
|
+
|
|
64
|
+
**File: `agentic-flow/package.json` or `claude-flow/package.json`**
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"dependencies": {
|
|
69
|
+
"agentdb": "^1.4.3",
|
|
70
|
+
"better-sqlite3": "^11.10.0"
|
|
71
|
+
// ... existing deps
|
|
72
|
+
},
|
|
73
|
+
"optionalDependencies": {
|
|
74
|
+
"@xenova/transformers": "^3.2.0"
|
|
75
|
+
},
|
|
76
|
+
"peerDependencies": {
|
|
77
|
+
"@xenova/transformers": "^3.0.0"
|
|
78
|
+
},
|
|
79
|
+
"peerDependenciesMeta": {
|
|
80
|
+
"@xenova/transformers": {
|
|
81
|
+
"optional": true
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 2. Update Embeddings Utility with Graceful Fallback
|
|
88
|
+
|
|
89
|
+
**File: `src/reasoningbank/utils/embeddings.ts`**
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
/**
|
|
93
|
+
* Embedding utilities with optional local model support
|
|
94
|
+
*/
|
|
95
|
+
|
|
96
|
+
let transformersAvailable = false;
|
|
97
|
+
let embeddingPipeline: any = null;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Check if transformers.js is available
|
|
101
|
+
*/
|
|
102
|
+
async function checkTransformersAvailable(): Promise<boolean> {
|
|
103
|
+
try {
|
|
104
|
+
const transformers = await import('@xenova/transformers');
|
|
105
|
+
return true;
|
|
106
|
+
} catch (error) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Initialize embeddings if available
|
|
113
|
+
*/
|
|
114
|
+
async function initializeEmbeddings(): Promise<boolean> {
|
|
115
|
+
if (embeddingPipeline) return true; // Already initialized
|
|
116
|
+
|
|
117
|
+
// Check if feature is enabled
|
|
118
|
+
const semanticSearchEnabled = process.env.CLAUDE_FLOW_SEMANTIC_SEARCH === 'true';
|
|
119
|
+
if (!semanticSearchEnabled) {
|
|
120
|
+
console.log('[Embeddings] Semantic search disabled (set CLAUDE_FLOW_SEMANTIC_SEARCH=true to enable)');
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Check if transformers is available
|
|
125
|
+
transformersAvailable = await checkTransformersAvailable();
|
|
126
|
+
|
|
127
|
+
if (!transformersAvailable) {
|
|
128
|
+
console.log('[Embeddings] @xenova/transformers not installed');
|
|
129
|
+
console.log('');
|
|
130
|
+
console.log('📝 To enable semantic search, run:');
|
|
131
|
+
console.log(' npm install -g @xenova/transformers');
|
|
132
|
+
console.log(' export CLAUDE_FLOW_SEMANTIC_SEARCH=true');
|
|
133
|
+
console.log('');
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
const { pipeline } = await import('@xenova/transformers');
|
|
139
|
+
|
|
140
|
+
console.log('[Embeddings] Loading local model (first time: ~23 MB download)...');
|
|
141
|
+
embeddingPipeline = await pipeline(
|
|
142
|
+
'feature-extraction',
|
|
143
|
+
'Xenova/all-MiniLM-L6-v2'
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
console.log('[Embeddings] ✅ Semantic search enabled (Xenova/all-MiniLM-L6-v2)');
|
|
147
|
+
return true;
|
|
148
|
+
|
|
149
|
+
} catch (error) {
|
|
150
|
+
console.warn('[Embeddings] Failed to initialize:', error.message);
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Compute embedding (returns null if not available)
|
|
157
|
+
*/
|
|
158
|
+
export async function computeEmbedding(text: string): Promise<Float32Array | null> {
|
|
159
|
+
const initialized = await initializeEmbeddings();
|
|
160
|
+
|
|
161
|
+
if (!initialized || !embeddingPipeline) {
|
|
162
|
+
return null; // Feature not available
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
try {
|
|
166
|
+
const output = await embeddingPipeline(text, {
|
|
167
|
+
pooling: 'mean',
|
|
168
|
+
normalize: true
|
|
169
|
+
});
|
|
170
|
+
return new Float32Array(output.data);
|
|
171
|
+
} catch (error) {
|
|
172
|
+
console.error('[Embeddings] Generation failed:', error.message);
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Check if semantic search is available
|
|
179
|
+
*/
|
|
180
|
+
export async function isSemanticSearchAvailable(): Promise<boolean> {
|
|
181
|
+
return await initializeEmbeddings();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Clear embedding cache (no-op if not initialized)
|
|
186
|
+
*/
|
|
187
|
+
export function clearEmbeddingCache(): void {
|
|
188
|
+
// No-op for now
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### 3. Update Retrieval to Handle Optional Embeddings
|
|
193
|
+
|
|
194
|
+
**File: `src/reasoningbank/core/retrieve.ts`**
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
import { computeEmbedding, isSemanticSearchAvailable } from '../utils/embeddings.js';
|
|
198
|
+
import { cosineSimilarity } from '../utils/mmr.js';
|
|
199
|
+
import { fetchMemoryCandidates } from '../db/queries.js';
|
|
200
|
+
|
|
201
|
+
export async function retrieveMemories(
|
|
202
|
+
query: string,
|
|
203
|
+
options: RetrievalOptions
|
|
204
|
+
): Promise<any[]> {
|
|
205
|
+
console.log(`[INFO] Retrieving memories for query: ${query}...`);
|
|
206
|
+
|
|
207
|
+
// Fetch candidates from database
|
|
208
|
+
const candidates = fetchMemoryCandidates(options);
|
|
209
|
+
|
|
210
|
+
if (candidates.length === 0) {
|
|
211
|
+
console.log('[INFO] No memory candidates found');
|
|
212
|
+
return [];
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
console.log(`[INFO] Found ${candidates.length} candidates`);
|
|
216
|
+
|
|
217
|
+
// Check if semantic search is available
|
|
218
|
+
const semanticAvailable = await isSemanticSearchAvailable();
|
|
219
|
+
|
|
220
|
+
if (!semanticAvailable) {
|
|
221
|
+
console.log('[INFO] Using database pattern matching (semantic search not enabled)');
|
|
222
|
+
return candidates.slice(0, options.k);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Try semantic search
|
|
226
|
+
try {
|
|
227
|
+
const queryEmbedding = await computeEmbedding(query);
|
|
228
|
+
|
|
229
|
+
if (!queryEmbedding) {
|
|
230
|
+
console.log('[INFO] Semantic search unavailable, using database fallback');
|
|
231
|
+
return candidates.slice(0, options.k);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
console.log('[INFO] Using semantic search with local embeddings');
|
|
235
|
+
|
|
236
|
+
// Compute similarities
|
|
237
|
+
const scoredCandidates = candidates
|
|
238
|
+
.map(candidate => {
|
|
239
|
+
if (!candidate.embedding || candidate.embedding.length !== queryEmbedding.length) {
|
|
240
|
+
return { ...candidate, similarity: 0 };
|
|
241
|
+
}
|
|
242
|
+
const similarity = cosineSimilarity(queryEmbedding, candidate.embedding);
|
|
243
|
+
return { ...candidate, similarity };
|
|
244
|
+
})
|
|
245
|
+
.sort((a, b) => b.similarity - a.similarity);
|
|
246
|
+
|
|
247
|
+
return scoredCandidates.slice(0, options.k);
|
|
248
|
+
|
|
249
|
+
} catch (error) {
|
|
250
|
+
console.error('[ERROR] Semantic search failed:', error.message);
|
|
251
|
+
console.log('[INFO] Falling back to database pattern matching');
|
|
252
|
+
return candidates.slice(0, options.k);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### 4. Update CLI to Show Status
|
|
258
|
+
|
|
259
|
+
**File: `src/cli/simple-commands/memory.js`**
|
|
260
|
+
|
|
261
|
+
```javascript
|
|
262
|
+
async function handleQueryCommand(query, options) {
|
|
263
|
+
console.log('\nℹ️ 🧠 Using ReasoningBank mode...');
|
|
264
|
+
|
|
265
|
+
// Check semantic search availability
|
|
266
|
+
const { isSemanticSearchAvailable } = await import('../../reasoningbank/utils/embeddings.js');
|
|
267
|
+
const semanticEnabled = await isSemanticSearchAvailable();
|
|
268
|
+
|
|
269
|
+
if (!semanticEnabled) {
|
|
270
|
+
console.log('💡 Tip: Enable semantic search for better results:');
|
|
271
|
+
console.log(' npm install -g @xenova/transformers');
|
|
272
|
+
console.log(' export CLAUDE_FLOW_SEMANTIC_SEARCH=true');
|
|
273
|
+
console.log('');
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// ... rest of query logic
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## User Experience
|
|
283
|
+
|
|
284
|
+
### Default Experience (No Setup)
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
$ npx claude-flow@alpha memory query "api"
|
|
288
|
+
|
|
289
|
+
ℹ️ 🧠 Using ReasoningBank mode...
|
|
290
|
+
[ReasoningBank] Initializing...
|
|
291
|
+
[ReasoningBank] Enabled: true (initializing...)
|
|
292
|
+
[INFO] Retrieving memories for query: api...
|
|
293
|
+
[INFO] Found 5 candidates
|
|
294
|
+
[INFO] Using database pattern matching (semantic search not enabled)
|
|
295
|
+
✅ Found 2 results
|
|
296
|
+
|
|
297
|
+
📌 api-design
|
|
298
|
+
Value: REST with JWT auth
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Enhanced Experience (With Setup)
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
$ npm install -g @xenova/transformers
|
|
305
|
+
$ export CLAUDE_FLOW_SEMANTIC_SEARCH=true
|
|
306
|
+
$ npx claude-flow@alpha memory query "authentication patterns"
|
|
307
|
+
|
|
308
|
+
ℹ️ 🧠 Using ReasoningBank mode...
|
|
309
|
+
[ReasoningBank] Initializing...
|
|
310
|
+
[Embeddings] Loading local model (first time: ~23 MB download)...
|
|
311
|
+
[Embeddings] ✅ Semantic search enabled (Xenova/all-MiniLM-L6-v2)
|
|
312
|
+
[INFO] Using semantic search with local embeddings
|
|
313
|
+
✅ Found 3 results (semantic similarity):
|
|
314
|
+
|
|
315
|
+
📌 api-design
|
|
316
|
+
Value: REST with JWT auth
|
|
317
|
+
Match Score: 89.3% ← Semantic similarity!
|
|
318
|
+
|
|
319
|
+
📌 oauth-config
|
|
320
|
+
Value: OAuth 2.0 with PKCE
|
|
321
|
+
Match Score: 76.2% ← Related concept!
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## Documentation Updates
|
|
327
|
+
|
|
328
|
+
### README.md
|
|
329
|
+
|
|
330
|
+
```markdown
|
|
331
|
+
## Memory System
|
|
332
|
+
|
|
333
|
+
The memory system works out of the box with database pattern matching.
|
|
334
|
+
|
|
335
|
+
### Optional: Semantic Search
|
|
336
|
+
|
|
337
|
+
For AI-powered semantic similarity, install the optional transformer models:
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
# Enable semantic search
|
|
341
|
+
npm install -g @xenova/transformers
|
|
342
|
+
export CLAUDE_FLOW_SEMANTIC_SEARCH=true
|
|
343
|
+
|
|
344
|
+
# Now queries use semantic similarity
|
|
345
|
+
npx claude-flow@alpha memory query "authentication"
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
**Benefits:**
|
|
349
|
+
- Find related concepts (e.g., "auth" matches "JWT", "OAuth")
|
|
350
|
+
- 50-100ms per query
|
|
351
|
+
- Works offline
|
|
352
|
+
- Free (no API costs)
|
|
353
|
+
- ~23 MB one-time download
|
|
354
|
+
|
|
355
|
+
**Without semantic search:**
|
|
356
|
+
- Database pattern matching (exact/partial text)
|
|
357
|
+
- Instant (no model loading)
|
|
358
|
+
- Zero dependencies
|
|
359
|
+
- Always works
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## Package Configuration
|
|
365
|
+
|
|
366
|
+
### package.json Changes
|
|
367
|
+
|
|
368
|
+
```json
|
|
369
|
+
{
|
|
370
|
+
"optionalDependencies": {
|
|
371
|
+
"@xenova/transformers": "^3.2.0"
|
|
372
|
+
},
|
|
373
|
+
"scripts": {
|
|
374
|
+
"postinstall": "node scripts/check-optional-deps.js"
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### scripts/check-optional-deps.js
|
|
380
|
+
|
|
381
|
+
```javascript
|
|
382
|
+
// Check if optional dependencies are available
|
|
383
|
+
const fs = require('fs');
|
|
384
|
+
const path = require('path');
|
|
385
|
+
|
|
386
|
+
const transformersPath = path.join(__dirname, '../node_modules/@xenova/transformers');
|
|
387
|
+
|
|
388
|
+
if (fs.existsSync(transformersPath)) {
|
|
389
|
+
console.log('✅ Optional: Semantic search available (@xenova/transformers installed)');
|
|
390
|
+
} else {
|
|
391
|
+
console.log('');
|
|
392
|
+
console.log('💡 Optional Enhancement Available:');
|
|
393
|
+
console.log(' Install @xenova/transformers for semantic search');
|
|
394
|
+
console.log(' npm install -g @xenova/transformers');
|
|
395
|
+
console.log('');
|
|
396
|
+
}
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
## Benefits of Optional Approach
|
|
402
|
+
|
|
403
|
+
### ✅ Advantages
|
|
404
|
+
|
|
405
|
+
1. **Zero friction for basic use** - Works immediately with npx
|
|
406
|
+
2. **No large downloads required** - Users choose when to download 23 MB model
|
|
407
|
+
3. **Graceful degradation** - Falls back to database search automatically
|
|
408
|
+
4. **User choice** - Install only if semantic search is needed
|
|
409
|
+
5. **Clear communication** - Users know what they're missing and how to get it
|
|
410
|
+
|
|
411
|
+
### ❌ Avoids Problems
|
|
412
|
+
|
|
413
|
+
1. No mandatory 23 MB download for users who don't need semantic search
|
|
414
|
+
2. No install failures due to native dependencies
|
|
415
|
+
3. No confusion about why embeddings aren't working
|
|
416
|
+
4. No breaking changes to existing functionality
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
## Testing Strategy
|
|
421
|
+
|
|
422
|
+
### Test 1: Default (No Semantic Search)
|
|
423
|
+
```bash
|
|
424
|
+
# Fresh install
|
|
425
|
+
npx claude-flow@alpha memory store "test" "value"
|
|
426
|
+
npx claude-flow@alpha memory query "test"
|
|
427
|
+
# ✅ Should work with database pattern matching
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### Test 2: Enhanced (With Semantic Search)
|
|
431
|
+
```bash
|
|
432
|
+
# Install optional dep
|
|
433
|
+
npm install -g @xenova/transformers
|
|
434
|
+
export CLAUDE_FLOW_SEMANTIC_SEARCH=true
|
|
435
|
+
|
|
436
|
+
npx claude-flow@alpha memory query "test"
|
|
437
|
+
# ✅ Should use semantic similarity
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
### Test 3: Graceful Fallback
|
|
441
|
+
```bash
|
|
442
|
+
# Enable flag but don't install package
|
|
443
|
+
export CLAUDE_FLOW_SEMANTIC_SEARCH=true
|
|
444
|
+
unset npm_config_prefix # Ensure transformers not available
|
|
445
|
+
|
|
446
|
+
npx claude-flow@alpha memory query "test"
|
|
447
|
+
# ✅ Should show helpful message and fall back to database search
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
## Summary
|
|
453
|
+
|
|
454
|
+
This approach gives you:
|
|
455
|
+
|
|
456
|
+
✅ **Works out of the box** - No setup required for basic memory system
|
|
457
|
+
✅ **Optional enhancement** - Users install @xenova/transformers only if they want semantic search
|
|
458
|
+
✅ **Graceful fallback** - Always works, even without transformers installed
|
|
459
|
+
✅ **Clear messaging** - Users know what's available and how to enable it
|
|
460
|
+
✅ **Zero breaking changes** - Existing functionality unchanged
|
|
461
|
+
|
|
462
|
+
**Recommendation:** Implement this optional approach for maximum user flexibility and zero friction.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-flow",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.24",
|
|
4
4
|
"description": "Enterprise-grade AI agent orchestration with WASM-powered ReasoningBank memory and AgentDB vector database (always uses latest agentic-flow)",
|
|
5
5
|
"mcpName": "io.github.ruvnet/claude-flow",
|
|
6
6
|
"main": "cli.mjs",
|
|
@@ -120,7 +120,7 @@
|
|
|
120
120
|
"@anthropic-ai/claude-code": "^2.0.1",
|
|
121
121
|
"@anthropic-ai/sdk": "^0.65.0",
|
|
122
122
|
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
123
|
-
"agentic-flow": "^1.8.
|
|
123
|
+
"agentic-flow": "^1.8.7",
|
|
124
124
|
"blessed": "^0.1.81",
|
|
125
125
|
"chalk": "^4.1.2",
|
|
126
126
|
"cli-table3": "^0.6.3",
|
|
@@ -143,6 +143,7 @@
|
|
|
143
143
|
},
|
|
144
144
|
"optionalDependencies": {
|
|
145
145
|
"@types/better-sqlite3": "^7.6.13",
|
|
146
|
+
"@xenova/transformers": "^3.2.0",
|
|
146
147
|
"agentdb": "^1.3.9",
|
|
147
148
|
"better-sqlite3": "^12.2.0",
|
|
148
149
|
"diskusage": "^1.1.3",
|