lynkr 8.0.0 → 8.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 (102) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/src/api/openai-router.js +34 -2
  4. package/src/clients/standard-tools.js +23 -0
  5. package/src/config/index.js +20 -0
  6. package/src/orchestrator/index.js +2 -2
  7. package/src/server.js +2 -12
  8. package/src/tools/index.js +4 -0
  9. package/src/tools/lazy-loader.js +7 -0
  10. package/src/tools/tinyfish.js +358 -0
  11. package/src/tools/truncate.js +1 -0
  12. package/.github/FUNDING.yml +0 -15
  13. package/.github/workflows/README.md +0 -215
  14. package/.github/workflows/ci.yml +0 -69
  15. package/.github/workflows/index.yml +0 -62
  16. package/.github/workflows/web-tools-tests.yml +0 -56
  17. package/CITATIONS.bib +0 -6
  18. package/DEPLOYMENT.md +0 -1001
  19. package/LYNKR-TUI-PLAN.md +0 -984
  20. package/PERFORMANCE-REPORT.md +0 -866
  21. package/PLAN-per-client-model-routing.md +0 -252
  22. package/docs/42642f749da6234f41b6b425c3bb07c9.txt +0 -1
  23. package/docs/BingSiteAuth.xml +0 -4
  24. package/docs/docs-style.css +0 -478
  25. package/docs/docs.html +0 -198
  26. package/docs/google5be250e608e6da39.html +0 -1
  27. package/docs/index.html +0 -577
  28. package/docs/index.md +0 -584
  29. package/docs/robots.txt +0 -4
  30. package/docs/sitemap.xml +0 -44
  31. package/docs/style.css +0 -1223
  32. package/docs/toon-integration-spec.md +0 -130
  33. package/documentation/README.md +0 -101
  34. package/documentation/api.md +0 -806
  35. package/documentation/claude-code-cli.md +0 -679
  36. package/documentation/codex-cli.md +0 -397
  37. package/documentation/contributing.md +0 -571
  38. package/documentation/cursor-integration.md +0 -734
  39. package/documentation/docker.md +0 -874
  40. package/documentation/embeddings.md +0 -762
  41. package/documentation/faq.md +0 -713
  42. package/documentation/features.md +0 -403
  43. package/documentation/headroom.md +0 -519
  44. package/documentation/installation.md +0 -758
  45. package/documentation/memory-system.md +0 -476
  46. package/documentation/production.md +0 -636
  47. package/documentation/providers.md +0 -1009
  48. package/documentation/routing.md +0 -476
  49. package/documentation/testing.md +0 -629
  50. package/documentation/token-optimization.md +0 -325
  51. package/documentation/tools.md +0 -697
  52. package/documentation/troubleshooting.md +0 -969
  53. package/final-test.js +0 -33
  54. package/headroom-sidecar/config.py +0 -93
  55. package/headroom-sidecar/requirements.txt +0 -14
  56. package/headroom-sidecar/server.py +0 -451
  57. package/monitor-agents.sh +0 -31
  58. package/scripts/audit-log-reader.js +0 -399
  59. package/scripts/compact-dictionary.js +0 -204
  60. package/scripts/test-deduplication.js +0 -448
  61. package/src/db/database.sqlite +0 -0
  62. package/te +0 -11622
  63. package/test/README.md +0 -212
  64. package/test/azure-openai-config.test.js +0 -213
  65. package/test/azure-openai-error-resilience.test.js +0 -238
  66. package/test/azure-openai-format-conversion.test.js +0 -354
  67. package/test/azure-openai-integration.test.js +0 -287
  68. package/test/azure-openai-routing.test.js +0 -175
  69. package/test/azure-openai-streaming.test.js +0 -171
  70. package/test/bedrock-integration.test.js +0 -457
  71. package/test/comprehensive-test-suite.js +0 -928
  72. package/test/config-validation.test.js +0 -207
  73. package/test/cursor-integration.test.js +0 -484
  74. package/test/format-conversion.test.js +0 -578
  75. package/test/hybrid-routing-integration.test.js +0 -269
  76. package/test/hybrid-routing-performance.test.js +0 -428
  77. package/test/llamacpp-integration.test.js +0 -882
  78. package/test/lmstudio-integration.test.js +0 -347
  79. package/test/memory/extractor.test.js +0 -398
  80. package/test/memory/retriever.test.js +0 -613
  81. package/test/memory/retriever.test.js.bak +0 -585
  82. package/test/memory/search.test.js +0 -537
  83. package/test/memory/search.test.js.bak +0 -389
  84. package/test/memory/store.test.js +0 -344
  85. package/test/memory/store.test.js.bak +0 -312
  86. package/test/memory/surprise.test.js +0 -300
  87. package/test/memory-performance.test.js +0 -472
  88. package/test/openai-integration.test.js +0 -683
  89. package/test/openrouter-error-resilience.test.js +0 -418
  90. package/test/passthrough-mode.test.js +0 -385
  91. package/test/performance-benchmark.js +0 -351
  92. package/test/performance-tests.js +0 -528
  93. package/test/routing.test.js +0 -225
  94. package/test/toon-compression.test.js +0 -131
  95. package/test/web-tools.test.js +0 -329
  96. package/test-agents-simple.js +0 -43
  97. package/test-cli-connection.sh +0 -33
  98. package/test-learning-unit.js +0 -126
  99. package/test-learning.js +0 -112
  100. package/test-parallel-agents.sh +0 -124
  101. package/test-parallel-direct.js +0 -155
  102. 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();