lynkr 7.2.5 → 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 (124) hide show
  1. package/README.md +3 -3
  2. package/config/model-tiers.json +89 -0
  3. package/install.sh +6 -1
  4. package/package.json +4 -2
  5. package/scripts/setup.js +0 -1
  6. package/src/agents/executor.js +14 -6
  7. package/src/api/middleware/session.js +15 -2
  8. package/src/api/openai-router.js +162 -37
  9. package/src/api/providers-handler.js +15 -1
  10. package/src/api/router.js +107 -2
  11. package/src/budget/index.js +4 -3
  12. package/src/clients/databricks.js +431 -234
  13. package/src/clients/gpt-utils.js +181 -0
  14. package/src/clients/ollama-utils.js +66 -140
  15. package/src/clients/routing.js +0 -1
  16. package/src/clients/standard-tools.js +99 -3
  17. package/src/config/index.js +133 -35
  18. package/src/context/toon.js +173 -0
  19. package/src/logger/index.js +23 -0
  20. package/src/orchestrator/index.js +688 -213
  21. package/src/routing/agentic-detector.js +320 -0
  22. package/src/routing/complexity-analyzer.js +202 -2
  23. package/src/routing/cost-optimizer.js +305 -0
  24. package/src/routing/index.js +168 -159
  25. package/src/routing/model-tiers.js +365 -0
  26. package/src/server.js +4 -14
  27. package/src/sessions/cleanup.js +3 -3
  28. package/src/sessions/record.js +10 -1
  29. package/src/sessions/store.js +7 -2
  30. package/src/tools/agent-task.js +48 -1
  31. package/src/tools/index.js +19 -2
  32. package/src/tools/lazy-loader.js +7 -0
  33. package/src/tools/tinyfish.js +358 -0
  34. package/src/tools/truncate.js +1 -0
  35. package/.github/FUNDING.yml +0 -15
  36. package/.github/workflows/README.md +0 -215
  37. package/.github/workflows/ci.yml +0 -69
  38. package/.github/workflows/index.yml +0 -62
  39. package/.github/workflows/web-tools-tests.yml +0 -56
  40. package/CITATIONS.bib +0 -6
  41. package/CLAWROUTER_ROUTING_PLAN.md +0 -910
  42. package/DEPLOYMENT.md +0 -1001
  43. package/LYNKR-TUI-PLAN.md +0 -984
  44. package/PERFORMANCE-REPORT.md +0 -866
  45. package/PLAN-per-client-model-routing.md +0 -252
  46. package/ROUTER_COMPARISON.md +0 -173
  47. package/TIER_ROUTING_PLAN.md +0 -771
  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 -197
  52. package/docs/google5be250e608e6da39.html +0 -1
  53. package/docs/index.html +0 -577
  54. package/docs/index.md +0 -577
  55. package/docs/robots.txt +0 -4
  56. package/docs/sitemap.xml +0 -44
  57. package/docs/style.css +0 -1223
  58. package/documentation/README.md +0 -100
  59. package/documentation/api.md +0 -806
  60. package/documentation/claude-code-cli.md +0 -672
  61. package/documentation/codex-cli.md +0 -397
  62. package/documentation/contributing.md +0 -571
  63. package/documentation/cursor-integration.md +0 -731
  64. package/documentation/docker.md +0 -867
  65. package/documentation/embeddings.md +0 -760
  66. package/documentation/faq.md +0 -659
  67. package/documentation/features.md +0 -396
  68. package/documentation/headroom.md +0 -519
  69. package/documentation/installation.md +0 -706
  70. package/documentation/memory-system.md +0 -476
  71. package/documentation/production.md +0 -601
  72. package/documentation/providers.md +0 -906
  73. package/documentation/testing.md +0 -629
  74. package/documentation/token-optimization.md +0 -323
  75. package/documentation/tools.md +0 -697
  76. package/documentation/troubleshooting.md +0 -893
  77. package/final-test.js +0 -33
  78. package/headroom-sidecar/config.py +0 -93
  79. package/headroom-sidecar/requirements.txt +0 -14
  80. package/headroom-sidecar/server.py +0 -451
  81. package/monitor-agents.sh +0 -31
  82. package/scripts/audit-log-reader.js +0 -399
  83. package/scripts/compact-dictionary.js +0 -204
  84. package/scripts/test-deduplication.js +0 -448
  85. package/src/db/database.sqlite +0 -0
  86. package/test/README.md +0 -212
  87. package/test/azure-openai-config.test.js +0 -204
  88. package/test/azure-openai-error-resilience.test.js +0 -238
  89. package/test/azure-openai-format-conversion.test.js +0 -354
  90. package/test/azure-openai-integration.test.js +0 -281
  91. package/test/azure-openai-routing.test.js +0 -177
  92. package/test/azure-openai-streaming.test.js +0 -171
  93. package/test/bedrock-integration.test.js +0 -471
  94. package/test/comprehensive-test-suite.js +0 -928
  95. package/test/config-validation.test.js +0 -207
  96. package/test/cursor-integration.test.js +0 -484
  97. package/test/format-conversion.test.js +0 -578
  98. package/test/hybrid-routing-integration.test.js +0 -254
  99. package/test/hybrid-routing-performance.test.js +0 -418
  100. package/test/llamacpp-integration.test.js +0 -863
  101. package/test/lmstudio-integration.test.js +0 -335
  102. package/test/memory/extractor.test.js +0 -398
  103. package/test/memory/retriever.test.js +0 -613
  104. package/test/memory/retriever.test.js.bak +0 -585
  105. package/test/memory/search.test.js +0 -537
  106. package/test/memory/search.test.js.bak +0 -389
  107. package/test/memory/store.test.js +0 -344
  108. package/test/memory/store.test.js.bak +0 -312
  109. package/test/memory/surprise.test.js +0 -300
  110. package/test/memory-performance.test.js +0 -472
  111. package/test/openai-integration.test.js +0 -686
  112. package/test/openrouter-error-resilience.test.js +0 -418
  113. package/test/passthrough-mode.test.js +0 -385
  114. package/test/performance-benchmark.js +0 -351
  115. package/test/performance-tests.js +0 -528
  116. package/test/routing.test.js +0 -219
  117. package/test/web-tools.test.js +0 -329
  118. package/test-agents-simple.js +0 -43
  119. package/test-cli-connection.sh +0 -33
  120. package/test-learning-unit.js +0 -126
  121. package/test-learning.js +0 -112
  122. package/test-parallel-agents.sh +0 -124
  123. package/test-parallel-direct.js +0 -155
  124. package/test-subagents.sh +0 -117
@@ -1,472 +0,0 @@
1
- /**
2
- * Performance Tests for Titans-Inspired Long-Term Memory System
3
- *
4
- * Performance Targets:
5
- * - Retrieval latency: <50ms for top 10 memories
6
- * - Extraction latency: <100ms (async, non-blocking)
7
- * - Memory overhead: <50MB for 10K memories
8
- * - Database size: ~100 bytes per memory
9
- */
10
-
11
- const assert = require("assert");
12
- const fs = require("fs");
13
- const path = require("path");
14
-
15
- // Test configuration
16
- const PERFORMANCE_TARGETS = {
17
- retrievalLatencyMs: 50,
18
- extractionLatencyMs: 100,
19
- storageLatencyMs: 10,
20
- searchLatencyMs: 50,
21
- memoryOverheadMb: 50,
22
- bytesPerMemory: 200, // Conservative estimate
23
- };
24
-
25
- const TEST_SIZES = {
26
- small: 100,
27
- medium: 1000,
28
- large: 10000,
29
- };
30
-
31
- console.log("=".repeat(80));
32
- console.log("Memory System Performance Tests");
33
- console.log("=".repeat(80));
34
- console.log();
35
-
36
- // Setup test environment
37
- const testDbPath = path.join(__dirname, `../data/perf-test-${Date.now()}.db`);
38
- process.env.DB_PATH = testDbPath;
39
- process.env.MEMORY_ENABLED = "true";
40
- process.env.MEMORY_SURPRISE_THRESHOLD = "0.3";
41
-
42
- // Clear module cache
43
- Object.keys(require.cache).forEach(key => {
44
- if (key.includes('/src/')) {
45
- delete require.cache[key];
46
- }
47
- });
48
-
49
- // Initialize modules
50
- const db = require("../src/db");
51
- const store = require("../src/memory/store");
52
- const search = require("../src/memory/search");
53
- const retriever = require("../src/memory/retriever");
54
- const surprise = require("../src/memory/surprise");
55
- const extractor = require("../src/memory/extractor");
56
-
57
- /**
58
- * Measure execution time
59
- */
60
- function measureTime(fn) {
61
- const start = process.hrtime.bigint();
62
- const result = fn();
63
- const end = process.hrtime.bigint();
64
- const durationMs = Number(end - start) / 1_000_000;
65
- return { result, durationMs };
66
- }
67
-
68
- /**
69
- * Measure async execution time
70
- */
71
- async function measureTimeAsync(fn) {
72
- const start = process.hrtime.bigint();
73
- const result = await fn();
74
- const end = process.hrtime.bigint();
75
- const durationMs = Number(end - start) / 1_000_000;
76
- return { result, durationMs };
77
- }
78
-
79
- /**
80
- * Create test memories
81
- */
82
- function createTestMemories(count) {
83
- const memories = [];
84
- const types = ['preference', 'decision', 'fact', 'entity', 'relationship'];
85
- const categories = ['user', 'code', 'project', 'general'];
86
-
87
- console.log(`Creating ${count} test memories...`);
88
- const start = Date.now();
89
-
90
- for (let i = 0; i < count; i++) {
91
- const type = types[i % types.length];
92
- const category = categories[i % categories.length];
93
-
94
- const memory = store.createMemory({
95
- content: `Test memory ${i}: This is about ${type} in ${category} with various keywords like Python JavaScript TypeScript React Express`,
96
- type,
97
- category,
98
- importance: Math.random(),
99
- surpriseScore: Math.random(),
100
- sessionId: null,
101
- });
102
-
103
- memories.push(memory);
104
-
105
- if ((i + 1) % 1000 === 0) {
106
- process.stdout.write(` Created ${i + 1}/${count}...\r`);
107
- }
108
- }
109
-
110
- const duration = Date.now() - start;
111
- console.log(` Created ${count} memories in ${duration}ms (${(duration/count).toFixed(2)}ms per memory)`);
112
- console.log();
113
-
114
- return memories;
115
- }
116
-
117
- /**
118
- * Test 1: Memory Creation Performance
119
- */
120
- function testCreationPerformance() {
121
- console.log("Test 1: Memory Creation Performance");
122
- console.log("-".repeat(60));
123
-
124
- const { durationMs } = measureTime(() => {
125
- return store.createMemory({
126
- content: "User prefers Python for data processing with pandas and numpy libraries",
127
- type: "preference",
128
- category: "user",
129
- importance: 0.8,
130
- surpriseScore: 0.6,
131
- });
132
- });
133
-
134
- console.log(` Single memory creation: ${durationMs.toFixed(2)}ms`);
135
-
136
- if (durationMs < PERFORMANCE_TARGETS.storageLatencyMs) {
137
- console.log(` ✓ PASS: Under ${PERFORMANCE_TARGETS.storageLatencyMs}ms target`);
138
- } else {
139
- console.log(` ✗ FAIL: Exceeds ${PERFORMANCE_TARGETS.storageLatencyMs}ms target`);
140
- }
141
-
142
- console.log();
143
- return durationMs < PERFORMANCE_TARGETS.storageLatencyMs;
144
- }
145
-
146
- /**
147
- * Test 2: Retrieval Performance at Scale
148
- */
149
- function testRetrievalPerformance(memoryCount) {
150
- console.log(`Test 2: Retrieval Performance (${memoryCount} memories)`);
151
- console.log("-".repeat(60));
152
-
153
- createTestMemories(memoryCount);
154
-
155
- // Test retrieval
156
- const queries = [
157
- "Python programming",
158
- "JavaScript framework",
159
- "database connection",
160
- "user authentication",
161
- "API endpoint",
162
- ];
163
-
164
- const results = [];
165
-
166
- for (const query of queries) {
167
- const { result, durationMs } = measureTime(() => {
168
- return retriever.retrieveRelevantMemories(query, { limit: 10 });
169
- });
170
-
171
- results.push({ query, durationMs, count: result.length });
172
- console.log(` "${query}": ${durationMs.toFixed(2)}ms (${result.length} results)`);
173
- }
174
-
175
- const avgDuration = results.reduce((sum, r) => sum + r.durationMs, 0) / results.length;
176
- console.log(` Average retrieval time: ${avgDuration.toFixed(2)}ms`);
177
-
178
- if (avgDuration < PERFORMANCE_TARGETS.retrievalLatencyMs) {
179
- console.log(` ✓ PASS: Under ${PERFORMANCE_TARGETS.retrievalLatencyMs}ms target`);
180
- } else {
181
- console.log(` ✗ FAIL: Exceeds ${PERFORMANCE_TARGETS.retrievalLatencyMs}ms target`);
182
- }
183
-
184
- console.log();
185
- return avgDuration < PERFORMANCE_TARGETS.retrievalLatencyMs;
186
- }
187
-
188
- /**
189
- * Test 3: FTS5 Search Performance
190
- */
191
- function testSearchPerformance(memoryCount) {
192
- console.log(`Test 3: FTS5 Search Performance (${memoryCount} memories)`);
193
- console.log("-".repeat(60));
194
-
195
- const queries = [
196
- "Python",
197
- "framework AND JavaScript",
198
- "database OR connection",
199
- "user authentication security",
200
- ];
201
-
202
- const results = [];
203
-
204
- for (const query of queries) {
205
- const { result, durationMs } = measureTime(() => {
206
- return search.searchMemories({ query, limit: 20 });
207
- });
208
-
209
- results.push({ query, durationMs, count: result.length });
210
- console.log(` "${query}": ${durationMs.toFixed(2)}ms (${result.length} results)`);
211
- }
212
-
213
- const avgDuration = results.reduce((sum, r) => sum + r.durationMs, 0) / results.length;
214
- console.log(` Average search time: ${avgDuration.toFixed(2)}ms`);
215
-
216
- if (avgDuration < PERFORMANCE_TARGETS.searchLatencyMs) {
217
- console.log(` ✓ PASS: Under ${PERFORMANCE_TARGETS.searchLatencyMs}ms target`);
218
- } else {
219
- console.log(` ✗ FAIL: Exceeds ${PERFORMANCE_TARGETS.searchLatencyMs}ms target`);
220
- }
221
-
222
- console.log();
223
- return avgDuration < PERFORMANCE_TARGETS.searchLatencyMs;
224
- }
225
-
226
- /**
227
- * Test 4: Surprise Calculation Performance
228
- */
229
- function testSurprisePerformance() {
230
- console.log("Test 4: Surprise Calculation Performance");
231
- console.log("-".repeat(60));
232
-
233
- const existingMemories = store.getRecentMemories({ limit: 100 });
234
-
235
- const testCases = [
236
- "User prefers Rust for systems programming with zero-cost abstractions",
237
- "This project uses GraphQL with Apollo Server and PostgreSQL database",
238
- "IMPORTANT: Always validate input to prevent SQL injection attacks",
239
- ];
240
-
241
- const results = [];
242
-
243
- for (const content of testCases) {
244
- const { result, durationMs } = measureTime(() => {
245
- return surprise.calculateSurprise(
246
- { content, type: "fact", category: "code" },
247
- existingMemories,
248
- { userContent: content }
249
- );
250
- });
251
-
252
- results.push({ durationMs, score: result });
253
- console.log(` Surprise calculation: ${durationMs.toFixed(2)}ms (score: ${result.toFixed(3)})`);
254
- }
255
-
256
- const avgDuration = results.reduce((sum, r) => sum + r.durationMs, 0) / results.length;
257
- console.log(` Average surprise calculation: ${avgDuration.toFixed(2)}ms`);
258
-
259
- // Surprise calculation should be fast (<10ms)
260
- const passThreshold = 10;
261
- if (avgDuration < passThreshold) {
262
- console.log(` ✓ PASS: Under ${passThreshold}ms target`);
263
- } else {
264
- console.log(` ✗ FAIL: Exceeds ${passThreshold}ms target`);
265
- }
266
-
267
- console.log();
268
- return avgDuration < passThreshold;
269
- }
270
-
271
- /**
272
- * Test 5: Memory Extraction Performance
273
- */
274
- async function testExtractionPerformance() {
275
- console.log("Test 5: Memory Extraction Performance");
276
- console.log("-".repeat(60));
277
-
278
- const testResponses = [
279
- {
280
- role: "assistant",
281
- content: "I understand that you prefer Python for data processing and always use pandas for DataFrame operations. We decided to implement the API using FastAPI framework with async/await patterns."
282
- },
283
- {
284
- role: "assistant",
285
- content: "This project uses TypeScript with strict mode, ESLint for linting, and Jest for testing. The database connection uses connection pooling with max 20 connections."
286
- },
287
- {
288
- role: "assistant",
289
- content: "IMPORTANT: User wants detailed error messages in development but minimal info in production. The authentication system must use JWT tokens with 1-hour expiration."
290
- },
291
- ];
292
-
293
- const results = [];
294
-
295
- for (const response of testResponses) {
296
- const { result, durationMs } = await measureTimeAsync(async () => {
297
- return await extractor.extractMemories(response, [], { sessionId: null });
298
- });
299
-
300
- results.push({ durationMs, count: result.length });
301
- console.log(` Extraction: ${durationMs.toFixed(2)}ms (${result.length} memories extracted)`);
302
- }
303
-
304
- const avgDuration = results.reduce((sum, r) => sum + r.durationMs, 0) / results.length;
305
- console.log(` Average extraction time: ${avgDuration.toFixed(2)}ms`);
306
-
307
- if (avgDuration < PERFORMANCE_TARGETS.extractionLatencyMs) {
308
- console.log(` ✓ PASS: Under ${PERFORMANCE_TARGETS.extractionLatencyMs}ms target`);
309
- } else {
310
- console.log(` ✗ FAIL: Exceeds ${PERFORMANCE_TARGETS.extractionLatencyMs}ms target`);
311
- }
312
-
313
- console.log();
314
- return avgDuration < PERFORMANCE_TARGETS.extractionLatencyMs;
315
- }
316
-
317
- /**
318
- * Test 6: Database Size and Memory Overhead
319
- */
320
- function testStorageEfficiency(memoryCount) {
321
- console.log(`Test 6: Storage Efficiency (${memoryCount} memories)`);
322
- console.log("-".repeat(60));
323
-
324
- // Get the actual database path used
325
- const actualDbPath = require("../src/config").dbPath;
326
-
327
- if (!fs.existsSync(actualDbPath)) {
328
- console.log(` ⚠ SKIP: Database file not found at ${actualDbPath}`);
329
- console.log();
330
- return true; // Skip, don't fail
331
- }
332
-
333
- const stats = fs.statSync(actualDbPath);
334
- const sizeMb = stats.size / (1024 * 1024);
335
- const bytesPerMemory = memoryCount > 0 ? stats.size / memoryCount : 0;
336
-
337
- console.log(` Database size: ${sizeMb.toFixed(2)} MB`);
338
- console.log(` Bytes per memory: ${bytesPerMemory.toFixed(0)} bytes`);
339
- console.log(` Total memories: ${memoryCount}`);
340
-
341
- if (bytesPerMemory < PERFORMANCE_TARGETS.bytesPerMemory) {
342
- console.log(` ✓ PASS: Under ${PERFORMANCE_TARGETS.bytesPerMemory} bytes per memory target`);
343
- } else {
344
- console.log(` ✗ FAIL: Exceeds ${PERFORMANCE_TARGETS.bytesPerMemory} bytes per memory target`);
345
- }
346
-
347
- console.log();
348
- return bytesPerMemory < PERFORMANCE_TARGETS.bytesPerMemory;
349
- }
350
-
351
- /**
352
- * Test 7: Concurrent Access Performance
353
- */
354
- function testConcurrentAccess() {
355
- console.log("Test 7: Concurrent Access Performance");
356
- console.log("-".repeat(60));
357
-
358
- const queries = Array.from({ length: 10 }, (_, i) => `query${i}`);
359
-
360
- const start = process.hrtime.bigint();
361
-
362
- const results = queries.map(query => {
363
- return retriever.retrieveRelevantMemories(query, { limit: 5 });
364
- });
365
-
366
- const end = process.hrtime.bigint();
367
- const durationMs = Number(end - start) / 1_000_000;
368
-
369
- console.log(` 10 concurrent retrievals: ${durationMs.toFixed(2)}ms`);
370
- console.log(` Average per retrieval: ${(durationMs / 10).toFixed(2)}ms`);
371
-
372
- const passThreshold = 100;
373
- if (durationMs < passThreshold) {
374
- console.log(` ✓ PASS: Under ${passThreshold}ms for 10 concurrent queries`);
375
- } else {
376
- console.log(` ✗ FAIL: Exceeds ${passThreshold}ms for 10 concurrent queries`);
377
- }
378
-
379
- console.log();
380
- return durationMs < passThreshold;
381
- }
382
-
383
- /**
384
- * Run all performance tests
385
- */
386
- async function runPerformanceTests() {
387
- console.log(`Starting at: ${new Date().toISOString()}`);
388
- console.log();
389
-
390
- const results = {
391
- creation: false,
392
- retrieval: false,
393
- search: false,
394
- surprise: false,
395
- extraction: false,
396
- storage: false,
397
- concurrent: false,
398
- };
399
-
400
- try {
401
- // Test 1: Creation
402
- results.creation = testCreationPerformance();
403
-
404
- // Test 2: Retrieval (with 1000 memories)
405
- results.retrieval = testRetrievalPerformance(TEST_SIZES.medium);
406
-
407
- // Test 3: Search
408
- results.search = testSearchPerformance(TEST_SIZES.medium);
409
-
410
- // Test 4: Surprise
411
- results.surprise = testSurprisePerformance();
412
-
413
- // Test 5: Extraction
414
- results.extraction = await testExtractionPerformance();
415
-
416
- // Test 6: Storage efficiency
417
- const totalMemories = store.countMemories();
418
- results.storage = testStorageEfficiency(totalMemories);
419
-
420
- // Test 7: Concurrent access
421
- results.concurrent = testConcurrentAccess();
422
-
423
- // Summary
424
- console.log("=".repeat(80));
425
- console.log("Performance Test Summary");
426
- console.log("=".repeat(80));
427
- console.log();
428
-
429
- const passCount = Object.values(results).filter(Boolean).length;
430
- const totalTests = Object.keys(results).length;
431
-
432
- Object.entries(results).forEach(([test, passed]) => {
433
- console.log(` ${passed ? '✓' : '✗'} ${test.padEnd(20)} ${passed ? 'PASS' : 'FAIL'}`);
434
- });
435
-
436
- console.log();
437
- console.log(`Total: ${passCount}/${totalTests} tests passed`);
438
- console.log();
439
-
440
- if (passCount === totalTests) {
441
- console.log("✓ All performance tests PASSED");
442
- return 0;
443
- } else {
444
- console.log(`✗ ${totalTests - passCount} performance tests FAILED`);
445
- return 1;
446
- }
447
-
448
- } catch (err) {
449
- console.error("Performance test error:", err);
450
- return 1;
451
- } finally {
452
- // Cleanup
453
- try {
454
- if (fs.existsSync(testDbPath)) {
455
- fs.unlinkSync(testDbPath);
456
- console.log(`Cleaned up test database: ${testDbPath}`);
457
- }
458
- } catch (err) {
459
- console.error("Cleanup error:", err);
460
- }
461
- }
462
- }
463
-
464
- // Run tests
465
- runPerformanceTests()
466
- .then(exitCode => {
467
- process.exit(exitCode);
468
- })
469
- .catch(err => {
470
- console.error("Fatal error:", err);
471
- process.exit(1);
472
- });