lynkr 8.0.0 → 9.0.1

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 (128) hide show
  1. package/.lynkr/telemetry.db +0 -0
  2. package/.lynkr/telemetry.db-shm +0 -0
  3. package/.lynkr/telemetry.db-wal +0 -0
  4. package/README.md +196 -322
  5. package/lynkr-skill.tar.gz +0 -0
  6. package/package.json +4 -3
  7. package/src/api/openai-router.js +64 -13
  8. package/src/api/providers-handler.js +171 -3
  9. package/src/api/router.js +9 -2
  10. package/src/clients/circuit-breaker.js +10 -247
  11. package/src/clients/codex-process.js +342 -0
  12. package/src/clients/codex-utils.js +143 -0
  13. package/src/clients/databricks.js +210 -63
  14. package/src/clients/resilience.js +540 -0
  15. package/src/clients/retry.js +22 -167
  16. package/src/clients/standard-tools.js +23 -0
  17. package/src/config/index.js +77 -0
  18. package/src/context/compression.js +42 -9
  19. package/src/context/distill.js +492 -0
  20. package/src/orchestrator/index.js +48 -8
  21. package/src/routing/complexity-analyzer.js +258 -5
  22. package/src/routing/index.js +12 -2
  23. package/src/routing/latency-tracker.js +148 -0
  24. package/src/routing/model-tiers.js +2 -0
  25. package/src/routing/quality-scorer.js +113 -0
  26. package/src/routing/telemetry.js +464 -0
  27. package/src/server.js +13 -12
  28. package/src/tools/code-graph.js +538 -0
  29. package/src/tools/code-mode.js +304 -0
  30. package/src/tools/index.js +4 -0
  31. package/src/tools/lazy-loader.js +18 -0
  32. package/src/tools/mcp-remote.js +7 -0
  33. package/src/tools/smart-selection.js +11 -0
  34. package/src/tools/tinyfish.js +358 -0
  35. package/src/tools/truncate.js +1 -0
  36. package/src/utils/payload.js +206 -0
  37. package/src/utils/perf-timer.js +80 -0
  38. package/.github/FUNDING.yml +0 -15
  39. package/.github/workflows/README.md +0 -215
  40. package/.github/workflows/ci.yml +0 -69
  41. package/.github/workflows/index.yml +0 -62
  42. package/.github/workflows/web-tools-tests.yml +0 -56
  43. package/CITATIONS.bib +0 -6
  44. package/DEPLOYMENT.md +0 -1001
  45. package/LYNKR-TUI-PLAN.md +0 -984
  46. package/PERFORMANCE-REPORT.md +0 -866
  47. package/PLAN-per-client-model-routing.md +0 -252
  48. package/docs/42642f749da6234f41b6b425c3bb07c9.txt +0 -1
  49. package/docs/BingSiteAuth.xml +0 -4
  50. package/docs/docs-style.css +0 -478
  51. package/docs/docs.html +0 -198
  52. package/docs/google5be250e608e6da39.html +0 -1
  53. package/docs/index.html +0 -577
  54. package/docs/index.md +0 -584
  55. package/docs/robots.txt +0 -4
  56. package/docs/sitemap.xml +0 -44
  57. package/docs/style.css +0 -1223
  58. package/docs/toon-integration-spec.md +0 -130
  59. package/documentation/README.md +0 -101
  60. package/documentation/api.md +0 -806
  61. package/documentation/claude-code-cli.md +0 -679
  62. package/documentation/codex-cli.md +0 -397
  63. package/documentation/contributing.md +0 -571
  64. package/documentation/cursor-integration.md +0 -734
  65. package/documentation/docker.md +0 -874
  66. package/documentation/embeddings.md +0 -762
  67. package/documentation/faq.md +0 -713
  68. package/documentation/features.md +0 -403
  69. package/documentation/headroom.md +0 -519
  70. package/documentation/installation.md +0 -758
  71. package/documentation/memory-system.md +0 -476
  72. package/documentation/production.md +0 -636
  73. package/documentation/providers.md +0 -1009
  74. package/documentation/routing.md +0 -476
  75. package/documentation/testing.md +0 -629
  76. package/documentation/token-optimization.md +0 -325
  77. package/documentation/tools.md +0 -697
  78. package/documentation/troubleshooting.md +0 -969
  79. package/final-test.js +0 -33
  80. package/headroom-sidecar/config.py +0 -93
  81. package/headroom-sidecar/requirements.txt +0 -14
  82. package/headroom-sidecar/server.py +0 -451
  83. package/monitor-agents.sh +0 -31
  84. package/scripts/audit-log-reader.js +0 -399
  85. package/scripts/compact-dictionary.js +0 -204
  86. package/scripts/test-deduplication.js +0 -448
  87. package/src/db/database.sqlite +0 -0
  88. package/te +0 -11622
  89. package/test/README.md +0 -212
  90. package/test/azure-openai-config.test.js +0 -213
  91. package/test/azure-openai-error-resilience.test.js +0 -238
  92. package/test/azure-openai-format-conversion.test.js +0 -354
  93. package/test/azure-openai-integration.test.js +0 -287
  94. package/test/azure-openai-routing.test.js +0 -175
  95. package/test/azure-openai-streaming.test.js +0 -171
  96. package/test/bedrock-integration.test.js +0 -457
  97. package/test/comprehensive-test-suite.js +0 -928
  98. package/test/config-validation.test.js +0 -207
  99. package/test/cursor-integration.test.js +0 -484
  100. package/test/format-conversion.test.js +0 -578
  101. package/test/hybrid-routing-integration.test.js +0 -269
  102. package/test/hybrid-routing-performance.test.js +0 -428
  103. package/test/llamacpp-integration.test.js +0 -882
  104. package/test/lmstudio-integration.test.js +0 -347
  105. package/test/memory/extractor.test.js +0 -398
  106. package/test/memory/retriever.test.js +0 -613
  107. package/test/memory/retriever.test.js.bak +0 -585
  108. package/test/memory/search.test.js +0 -537
  109. package/test/memory/search.test.js.bak +0 -389
  110. package/test/memory/store.test.js +0 -344
  111. package/test/memory/store.test.js.bak +0 -312
  112. package/test/memory/surprise.test.js +0 -300
  113. package/test/memory-performance.test.js +0 -472
  114. package/test/openai-integration.test.js +0 -683
  115. package/test/openrouter-error-resilience.test.js +0 -418
  116. package/test/passthrough-mode.test.js +0 -385
  117. package/test/performance-benchmark.js +0 -351
  118. package/test/performance-tests.js +0 -528
  119. package/test/routing.test.js +0 -225
  120. package/test/toon-compression.test.js +0 -131
  121. package/test/web-tools.test.js +0 -329
  122. package/test-agents-simple.js +0 -43
  123. package/test-cli-connection.sh +0 -33
  124. package/test-learning-unit.js +0 -126
  125. package/test-learning.js +0 -112
  126. package/test-parallel-agents.sh +0 -124
  127. package/test-parallel-direct.js +0 -155
  128. package/test-subagents.sh +0 -117
@@ -1,399 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * LLM Audit Log Reader
5
- *
6
- * Utility to read and reconstruct audit log entries from deduplicated logs.
7
- * Resolves hash references from the dictionary file and outputs full content.
8
- *
9
- * Usage:
10
- * node scripts/audit-log-reader.js [options]
11
- *
12
- * Options:
13
- * --log-file <path> Path to audit log file (default: logs/llm-audit.log)
14
- * --dict-file <path> Path to dictionary file (default: logs/llm-audit-dictionary.jsonl)
15
- * --full Output full restored entries (resolve all references)
16
- * --filter <type=value> Filter by field (e.g., type=llm_request, provider=anthropic)
17
- * --correlation-id <id> Filter by correlation ID
18
- * --last <n> Show only last N entries
19
- * --stats Show deduplication statistics
20
- * --verify Verify all references can be resolved
21
- * --help Show this help message
22
- *
23
- * Examples:
24
- * # Show all entries with full content
25
- * node scripts/audit-log-reader.js --full
26
- *
27
- * # Show only requests
28
- * node scripts/audit-log-reader.js --filter type=llm_request
29
- *
30
- * # Show last 5 entries
31
- * node scripts/audit-log-reader.js --last 5 --full
32
- *
33
- * # Show deduplication statistics
34
- * node scripts/audit-log-reader.js --stats
35
- *
36
- * # Verify all references resolve
37
- * node scripts/audit-log-reader.js --verify
38
- */
39
-
40
- const fs = require("fs");
41
- const path = require("path");
42
- const readline = require("readline");
43
- const { ContentDeduplicator } = require("../src/logger/deduplicator");
44
-
45
- // Default file paths
46
- const DEFAULT_LOG_FILE = path.join(process.cwd(), "logs", "llm-audit.log");
47
- const DEFAULT_DICT_FILE = path.join(process.cwd(), "logs", "llm-audit-dictionary.jsonl");
48
-
49
- /**
50
- * Parse command line arguments
51
- */
52
- function parseArgs() {
53
- const args = process.argv.slice(2);
54
- const options = {
55
- logFile: DEFAULT_LOG_FILE,
56
- dictFile: DEFAULT_DICT_FILE,
57
- full: false,
58
- filter: null,
59
- correlationId: null,
60
- last: null,
61
- stats: false,
62
- verify: false,
63
- help: false,
64
- };
65
-
66
- for (let i = 0; i < args.length; i++) {
67
- const arg = args[i];
68
- switch (arg) {
69
- case "--log-file":
70
- options.logFile = args[++i];
71
- break;
72
- case "--dict-file":
73
- options.dictFile = args[++i];
74
- break;
75
- case "--full":
76
- options.full = true;
77
- break;
78
- case "--filter":
79
- const filterArg = args[++i];
80
- const [key, value] = filterArg.split("=");
81
- options.filter = { key, value };
82
- break;
83
- case "--correlation-id":
84
- options.correlationId = args[++i];
85
- break;
86
- case "--last":
87
- options.last = Number.parseInt(args[++i], 10);
88
- break;
89
- case "--stats":
90
- options.stats = true;
91
- break;
92
- case "--verify":
93
- options.verify = true;
94
- break;
95
- case "--help":
96
- options.help = true;
97
- break;
98
- default:
99
- console.error(`Unknown option: ${arg}`);
100
- process.exit(1);
101
- }
102
- }
103
-
104
- return options;
105
- }
106
-
107
- /**
108
- * Show help message
109
- */
110
- function showHelp() {
111
- const helpText = `
112
- LLM Audit Log Reader
113
-
114
- Usage: node scripts/audit-log-reader.js [options]
115
-
116
- Options:
117
- --log-file <path> Path to audit log file (default: logs/llm-audit.log)
118
- --dict-file <path> Path to dictionary file (default: logs/llm-audit-dictionary.jsonl)
119
- --full Output full restored entries (resolve all references)
120
- --filter <type=value> Filter by field (e.g., type=llm_request, provider=anthropic)
121
- --correlation-id <id> Filter by correlation ID
122
- --last <n> Show only last N entries
123
- --stats Show deduplication statistics
124
- --verify Verify all references can be resolved
125
- --help Show this help message
126
-
127
- Examples:
128
- # Show all entries with full content
129
- node scripts/audit-log-reader.js --full
130
-
131
- # Show only requests
132
- node scripts/audit-log-reader.js --filter type=llm_request
133
-
134
- # Show last 5 entries
135
- node scripts/audit-log-reader.js --last 5 --full
136
-
137
- # Show deduplication statistics
138
- node scripts/audit-log-reader.js --stats
139
-
140
- # Verify all references resolve
141
- node scripts/audit-log-reader.js --verify
142
- `;
143
- console.log(helpText);
144
- }
145
-
146
- /**
147
- * Read and process log entries
148
- */
149
- async function readLogEntries(options) {
150
- const { logFile, dictFile, full, filter, correlationId, last } = options;
151
-
152
- // Check if log file exists
153
- if (!fs.existsSync(logFile)) {
154
- console.error(`Log file not found: ${logFile}`);
155
- process.exit(1);
156
- }
157
-
158
- // Initialize deduplicator if needed
159
- let deduplicator = null;
160
- if (full && fs.existsSync(dictFile)) {
161
- deduplicator = new ContentDeduplicator(dictFile);
162
- }
163
-
164
- const entries = [];
165
-
166
- // Read log file line by line
167
- const fileStream = fs.createReadStream(logFile);
168
- const rl = readline.createInterface({
169
- input: fileStream,
170
- crlfDelay: Infinity,
171
- });
172
-
173
- for await (const line of rl) {
174
- if (!line.trim()) continue;
175
-
176
- try {
177
- let entry = JSON.parse(line);
178
-
179
- // Apply filters
180
- if (filter && entry[filter.key] !== filter.value) {
181
- continue;
182
- }
183
- if (correlationId && entry.correlationId !== correlationId) {
184
- continue;
185
- }
186
-
187
- // Restore full content if requested
188
- if (full && deduplicator) {
189
- entry = deduplicator.restoreEntry(entry);
190
- }
191
-
192
- entries.push(entry);
193
- } catch (err) {
194
- console.error("Malformed log entry:", err.message);
195
- }
196
- }
197
-
198
- // Apply last N filter
199
- const output = last ? entries.slice(-last) : entries;
200
-
201
- // Output as JSONL
202
- for (const entry of output) {
203
- console.log(JSON.stringify(entry, null, 2));
204
- }
205
-
206
- return entries.length;
207
- }
208
-
209
- /**
210
- * Show deduplication statistics
211
- */
212
- async function showStats(options) {
213
- const { logFile, dictFile } = options;
214
-
215
- if (!fs.existsSync(logFile)) {
216
- console.error(`Log file not found: ${logFile}`);
217
- process.exit(1);
218
- }
219
-
220
- if (!fs.existsSync(dictFile)) {
221
- console.log("No dictionary file found. Deduplication may not be enabled.");
222
- return;
223
- }
224
-
225
- // Get file sizes
226
- const logStats = fs.statSync(logFile);
227
- const dictStats = fs.statSync(dictFile);
228
-
229
- console.log("\n=== LLM Audit Log Deduplication Statistics ===\n");
230
- console.log(`Log file: ${logFile}`);
231
- console.log(` Size: ${formatBytes(logStats.size)}`);
232
- console.log(` Lines: ${await countLines(logFile)}`);
233
- console.log();
234
- console.log(`Dictionary file: ${dictFile}`);
235
- console.log(` Size: ${formatBytes(dictStats.size)}`);
236
- console.log(` Entries: ${await countLines(dictFile)}`);
237
- console.log();
238
- console.log(`Total size: ${formatBytes(logStats.size + dictStats.size)}`);
239
- console.log();
240
-
241
- // Count reference occurrences in log
242
- const refCount = await countReferences(logFile);
243
- console.log(`Reference objects in log: ${refCount}`);
244
- console.log(`Estimated space saved: ~${formatBytes(refCount * 2000)} (assuming ~2KB per deduplicated field)`);
245
- console.log();
246
- }
247
-
248
- /**
249
- * Verify all references can be resolved
250
- */
251
- async function verifyReferences(options) {
252
- const { logFile, dictFile } = options;
253
-
254
- if (!fs.existsSync(logFile)) {
255
- console.error(`Log file not found: ${logFile}`);
256
- process.exit(1);
257
- }
258
-
259
- if (!fs.existsSync(dictFile)) {
260
- console.log("No dictionary file found. Nothing to verify.");
261
- return;
262
- }
263
-
264
- const deduplicator = new ContentDeduplicator(dictFile);
265
- const fileStream = fs.createReadStream(logFile);
266
- const rl = readline.createInterface({
267
- input: fileStream,
268
- crlfDelay: Infinity,
269
- });
270
-
271
- let totalRefs = 0;
272
- let unresolvedRefs = 0;
273
- const unresolvedHashes = new Set();
274
-
275
- console.log("Verifying references...\n");
276
-
277
- for await (const line of rl) {
278
- if (!line.trim()) continue;
279
-
280
- try {
281
- const entry = JSON.parse(line);
282
-
283
- // Check all fields for references
284
- for (const [key, value] of Object.entries(entry)) {
285
- if (typeof value === "object" && value !== null && value.$ref) {
286
- totalRefs++;
287
- const content = deduplicator.getContent(value.$ref);
288
- if (content === null) {
289
- unresolvedRefs++;
290
- unresolvedHashes.add(value.$ref);
291
- console.error(`✗ Unresolved reference: ${value.$ref} in field "${key}"`);
292
- }
293
- }
294
- }
295
- } catch (err) {
296
- console.error("Malformed log entry:", err.message);
297
- }
298
- }
299
-
300
- console.log("\n=== Verification Results ===\n");
301
- console.log(`Total references: ${totalRefs}`);
302
- console.log(`Unresolved references: ${unresolvedRefs}`);
303
- console.log(`Unique unresolved hashes: ${unresolvedHashes.size}`);
304
-
305
- if (unresolvedRefs === 0) {
306
- console.log("\n✓ All references resolved successfully!");
307
- } else {
308
- console.log("\n✗ Some references could not be resolved. Dictionary may be incomplete.");
309
- process.exit(1);
310
- }
311
- }
312
-
313
- /**
314
- * Helper: Format bytes to human-readable string
315
- */
316
- function formatBytes(bytes) {
317
- if (bytes < 1024) return `${bytes} B`;
318
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;
319
- return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
320
- }
321
-
322
- /**
323
- * Helper: Count lines in a file
324
- */
325
- async function countLines(filePath) {
326
- const fileStream = fs.createReadStream(filePath);
327
- const rl = readline.createInterface({
328
- input: fileStream,
329
- crlfDelay: Infinity,
330
- });
331
-
332
- let count = 0;
333
- for await (const line of rl) {
334
- if (line.trim()) count++;
335
- }
336
- return count;
337
- }
338
-
339
- /**
340
- * Helper: Count reference objects in log
341
- */
342
- async function countReferences(filePath) {
343
- const fileStream = fs.createReadStream(filePath);
344
- const rl = readline.createInterface({
345
- input: fileStream,
346
- crlfDelay: Infinity,
347
- });
348
-
349
- let count = 0;
350
- for await (const line of rl) {
351
- if (!line.trim()) continue;
352
- try {
353
- const entry = JSON.parse(line);
354
- for (const value of Object.values(entry)) {
355
- if (typeof value === "object" && value !== null && value.$ref) {
356
- count++;
357
- }
358
- }
359
- } catch {
360
- // Skip malformed lines
361
- }
362
- }
363
- return count;
364
- }
365
-
366
- /**
367
- * Main entry point
368
- */
369
- async function main() {
370
- const options = parseArgs();
371
-
372
- if (options.help) {
373
- showHelp();
374
- return;
375
- }
376
-
377
- if (options.stats) {
378
- await showStats(options);
379
- } else if (options.verify) {
380
- await verifyReferences(options);
381
- } else {
382
- const count = await readLogEntries(options);
383
- console.error(`\n(Processed ${count} entries)`);
384
- }
385
- }
386
-
387
- // Run if called directly
388
- if (require.main === module) {
389
- main().catch((err) => {
390
- console.error("Error:", err.message);
391
- process.exit(1);
392
- });
393
- }
394
-
395
- module.exports = {
396
- readLogEntries,
397
- showStats,
398
- verifyReferences,
399
- };
@@ -1,204 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Compact LLM Audit Dictionary
5
- *
6
- * Removes redundant UPDATE entries from the dictionary file, keeping only:
7
- * - One entry per hash with full content
8
- * - Latest metadata (useCount, lastSeen)
9
- *
10
- * Usage:
11
- * node scripts/compact-dictionary.js [options]
12
- *
13
- * Options:
14
- * --dict-path <path> Path to dictionary file (default: logs/llm-audit-dictionary.jsonl)
15
- * --backup Create backup before compacting (default: true)
16
- * --dry-run Show what would be done without making changes
17
- * --help Show this help message
18
- */
19
-
20
- const fs = require('fs');
21
- const path = require('path');
22
- const readline = require('readline');
23
-
24
- // Parse command line arguments
25
- function parseArgs() {
26
- const args = process.argv.slice(2);
27
- const options = {
28
- dictPath: 'logs/llm-audit-dictionary.jsonl',
29
- backup: true,
30
- dryRun: false,
31
- };
32
-
33
- for (let i = 0; i < args.length; i++) {
34
- const arg = args[i];
35
- switch (arg) {
36
- case '--dict-path':
37
- options.dictPath = args[++i];
38
- break;
39
- case '--backup':
40
- options.backup = true;
41
- break;
42
- case '--no-backup':
43
- options.backup = false;
44
- break;
45
- case '--dry-run':
46
- options.dryRun = true;
47
- break;
48
- case '--help':
49
- console.log(`
50
- Compact LLM Audit Dictionary
51
-
52
- Removes redundant UPDATE entries from the dictionary file.
53
-
54
- Usage:
55
- node scripts/compact-dictionary.js [options]
56
-
57
- Options:
58
- --dict-path <path> Path to dictionary file (default: logs/llm-audit-dictionary.jsonl)
59
- --backup Create backup before compacting (default: true)
60
- --no-backup Skip creating backup
61
- --dry-run Show what would be done without making changes
62
- --help Show this help message
63
-
64
- Example:
65
- node scripts/compact-dictionary.js --dict-path logs/llm-audit-dictionary.jsonl --dry-run
66
- `);
67
- process.exit(0);
68
- default:
69
- if (arg.startsWith('--')) {
70
- console.error(`Unknown option: ${arg}`);
71
- process.exit(1);
72
- }
73
- }
74
- }
75
-
76
- return options;
77
- }
78
-
79
- // Read and compact dictionary
80
- async function compactDictionary(dictPath) {
81
- if (!fs.existsSync(dictPath)) {
82
- throw new Error(`Dictionary file not found: ${dictPath}`);
83
- }
84
-
85
- console.log(`Reading dictionary: ${dictPath}`);
86
-
87
- // Map: hash -> entry object
88
- // For each hash, we'll keep the latest metadata merged with content
89
- const entries = new Map();
90
- let totalLines = 0;
91
- let malformedLines = 0;
92
-
93
- // Read all entries
94
- const fileStream = fs.createReadStream(dictPath);
95
- const rl = readline.createInterface({
96
- input: fileStream,
97
- crlfDelay: Infinity,
98
- });
99
-
100
- for await (const line of rl) {
101
- totalLines++;
102
- if (!line.trim()) continue;
103
-
104
- try {
105
- const entry = JSON.parse(line);
106
- if (!entry.hash) {
107
- malformedLines++;
108
- continue;
109
- }
110
-
111
- const hash = entry.hash;
112
-
113
- // Check if we already have an entry for this hash
114
- if (entries.has(hash)) {
115
- const existing = entries.get(hash);
116
-
117
- // Merge: keep content from entry that has it, use latest metadata
118
- const merged = {
119
- hash,
120
- firstSeen: existing.firstSeen || entry.firstSeen,
121
- useCount: entry.useCount || existing.useCount,
122
- lastSeen: entry.lastSeen || existing.lastSeen,
123
- content: existing.content || entry.content,
124
- };
125
-
126
- entries.set(hash, merged);
127
- } else {
128
- // First time seeing this hash
129
- entries.set(hash, entry);
130
- }
131
- } catch (err) {
132
- malformedLines++;
133
- console.warn(`Skipping malformed line ${totalLines}: ${err.message}`);
134
- }
135
- }
136
-
137
- const compactedCount = entries.size;
138
- const removedCount = totalLines - malformedLines - compactedCount;
139
-
140
- return {
141
- entries,
142
- stats: {
143
- totalLines,
144
- malformedLines,
145
- uniqueHashes: compactedCount,
146
- removedEntries: removedCount,
147
- },
148
- };
149
- }
150
-
151
- // Write compacted dictionary
152
- async function writeCompactedDictionary(dictPath, entries, backup = true) {
153
- // Create backup if requested
154
- if (backup) {
155
- const backupPath = `${dictPath}.backup.${Date.now()}`;
156
- console.log(`Creating backup: ${backupPath}`);
157
- fs.copyFileSync(dictPath, backupPath);
158
- }
159
-
160
- // Write compacted entries
161
- console.log(`Writing compacted dictionary: ${dictPath}`);
162
- const lines = Array.from(entries.values()).map((entry) => JSON.stringify(entry));
163
- fs.writeFileSync(dictPath, lines.join('\n') + '\n');
164
- }
165
-
166
- // Main
167
- async function main() {
168
- try {
169
- const options = parseArgs();
170
- const dictPath = path.resolve(options.dictPath);
171
-
172
- console.log('=== LLM Audit Dictionary Compaction ===\n');
173
-
174
- // Read and compact
175
- const { entries, stats } = await compactDictionary(dictPath);
176
-
177
- // Report statistics
178
- console.log('\nCompaction Statistics:');
179
- console.log(` Total lines in dictionary: ${stats.totalLines}`);
180
- console.log(` Malformed lines skipped: ${stats.malformedLines}`);
181
- console.log(` Unique content hashes: ${stats.uniqueHashes}`);
182
- console.log(` Redundant entries removed: ${stats.removedEntries}`);
183
-
184
- const reductionPercent =
185
- stats.totalLines > 0
186
- ? ((stats.removedEntries / stats.totalLines) * 100).toFixed(1)
187
- : 0;
188
- console.log(` Size reduction: ${reductionPercent}%\n`);
189
-
190
- if (options.dryRun) {
191
- console.log('DRY RUN: No changes made to dictionary file.');
192
- console.log(`Would have written ${stats.uniqueHashes} entries.\n`);
193
- } else {
194
- // Write compacted dictionary
195
- await writeCompactedDictionary(dictPath, entries, options.backup);
196
- console.log('✓ Dictionary compaction complete!\n');
197
- }
198
- } catch (err) {
199
- console.error('Error:', err.message);
200
- process.exit(1);
201
- }
202
- }
203
-
204
- main();