lynkr 9.7.2 → 9.9.0

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 (80) hide show
  1. package/README.md +29 -19
  2. package/bin/cli.js +11 -0
  3. package/bin/lynkr-init.js +14 -1
  4. package/bin/lynkr-usage.js +78 -0
  5. package/bin/wrap.js +60 -35
  6. package/config/difficulty-anchors.json +22 -0
  7. package/package.json +24 -3
  8. package/scripts/audit-log-reader.js +399 -0
  9. package/scripts/calibrate-thresholds.js +38 -157
  10. package/scripts/compact-dictionary.js +204 -0
  11. package/scripts/test-deduplication.js +448 -0
  12. package/scripts/ws7-anchor-replay.js +108 -0
  13. package/skills/lynkr/SKILL.md +195 -0
  14. package/src/agents/context-manager.js +18 -2
  15. package/src/agents/definitions/loader.js +90 -0
  16. package/src/agents/executor.js +24 -2
  17. package/src/agents/index.js +9 -1
  18. package/src/agents/parallel-coordinator.js +2 -2
  19. package/src/agents/reflector.js +11 -1
  20. package/src/api/middleware/loop-guard.js +87 -0
  21. package/src/api/middleware/request-logging.js +5 -64
  22. package/src/api/middleware/session.js +0 -0
  23. package/src/api/openai-router.js +120 -101
  24. package/src/api/providers-handler.js +27 -2
  25. package/src/api/router.js +450 -125
  26. package/src/budget/index.js +2 -19
  27. package/src/cache/semantic.js +9 -0
  28. package/src/clients/databricks.js +459 -146
  29. package/src/clients/gpt-utils.js +11 -105
  30. package/src/clients/openai-format.js +10 -3
  31. package/src/clients/openrouter-utils.js +49 -24
  32. package/src/clients/prompt-cache-injection.js +1 -0
  33. package/src/clients/provider-capabilities.js +1 -1
  34. package/src/clients/responses-format.js +34 -3
  35. package/src/clients/routing.js +15 -0
  36. package/src/config/index.js +36 -2
  37. package/src/context/gcf.js +275 -0
  38. package/src/context/tool-result-compressor.js +51 -9
  39. package/src/dashboard/api.js +1 -0
  40. package/src/logger/index.js +14 -1
  41. package/src/memory/search.js +12 -40
  42. package/src/memory/tools.js +3 -24
  43. package/src/orchestrator/bypass.js +4 -2
  44. package/src/orchestrator/index.js +144 -88
  45. package/src/routing/affinity-store.js +194 -0
  46. package/src/routing/agentic-detector.js +36 -6
  47. package/src/routing/bandit.js +25 -6
  48. package/src/routing/calibration.js +212 -0
  49. package/src/routing/client-profiles.js +292 -0
  50. package/src/routing/complexity-analyzer.js +48 -11
  51. package/src/routing/deescalator.js +148 -0
  52. package/src/routing/degradation.js +109 -0
  53. package/src/routing/feedback.js +157 -0
  54. package/src/routing/index.js +897 -87
  55. package/src/routing/intent-score.js +339 -0
  56. package/src/routing/interaction.js +3 -0
  57. package/src/routing/knn-router.js +70 -21
  58. package/src/routing/model-registry.js +28 -7
  59. package/src/routing/model-tiers.js +25 -2
  60. package/src/routing/reward-pipeline.js +68 -2
  61. package/src/routing/risk-analyzer.js +30 -1
  62. package/src/routing/risk-classifier.js +6 -2
  63. package/src/routing/session-affinity.js +162 -34
  64. package/src/routing/telemetry.js +298 -10
  65. package/src/routing/verifier.js +267 -0
  66. package/src/server.js +66 -21
  67. package/src/sessions/cleanup.js +17 -0
  68. package/src/tools/index.js +1 -15
  69. package/src/tools/smart-selection.js +10 -0
  70. package/src/tools/web-client.js +3 -3
  71. package/.eslintrc.cjs +0 -12
  72. package/benchmark-configs/litellm_config.yaml +0 -86
  73. package/benchmark-configs/lynkr.env +0 -48
  74. package/benchmark-configs/portkey-config.json +0 -60
  75. package/benchmark-configs/portkey-docker.sh +0 -23
  76. package/benchmark-tier-routing.js +0 -449
  77. package/funding.json +0 -110
  78. package/src/api/middleware/validation.js +0 -261
  79. package/src/routing/drift-monitor.js +0 -113
  80. package/src/workers/helpers.js +0 -185
@@ -77,7 +77,6 @@ class BudgetManager {
77
77
  );
78
78
  `);
79
79
 
80
- // Prepared statements
81
80
  this.stmts = {
82
81
  getBudget: this.db.prepare('SELECT * FROM user_budgets WHERE user_id = ?'),
83
82
  createBudget: this.db.prepare(`
@@ -115,7 +114,6 @@ class BudgetManager {
115
114
  };
116
115
  }
117
116
 
118
- // Check if user is within rate limits
119
117
  checkRateLimit(userId) {
120
118
  if (!this.enabled) return { allowed: true };
121
119
 
@@ -130,24 +128,21 @@ class BudgetManager {
130
128
  return { allowed: true };
131
129
  }
132
130
 
133
- const minuteWindow = 60 * 1000; // 1 minute
134
- const hourWindow = 60 * 60 * 1000; // 1 hour
131
+ const minuteWindow = 60 * 1000;
132
+ const hourWindow = 60 * 60 * 1000;
135
133
 
136
134
  let { request_count_minute, request_count_hour, minute_window_start, hour_window_start } = rateLimit;
137
135
 
138
- // Reset minute window if needed
139
136
  if (now - minute_window_start >= minuteWindow) {
140
137
  request_count_minute = 0;
141
138
  minute_window_start = now;
142
139
  }
143
140
 
144
- // Reset hour window if needed
145
141
  if (now - hour_window_start >= hourWindow) {
146
142
  request_count_hour = 0;
147
143
  hour_window_start = now;
148
144
  }
149
145
 
150
- // Check limits
151
146
  if (request_count_minute >= rateLimit.requests_per_minute) {
152
147
  const resetIn = minuteWindow - (now - minute_window_start);
153
148
  return {
@@ -170,7 +165,6 @@ class BudgetManager {
170
165
  };
171
166
  }
172
167
 
173
- // Increment counters
174
168
  request_count_minute++;
175
169
  request_count_hour++;
176
170
 
@@ -188,7 +182,6 @@ class BudgetManager {
188
182
  return { allowed: true };
189
183
  }
190
184
 
191
- // Check if user is within budget
192
185
  checkBudget(userId) {
193
186
  if (!this.enabled) return { allowed: true };
194
187
 
@@ -199,7 +192,6 @@ class BudgetManager {
199
192
  return { allowed: true, warning: 'No budget configured' };
200
193
  }
201
194
 
202
- // Get current month usage
203
195
  const monthStart = new Date();
204
196
  monthStart.setDate(1);
205
197
  monthStart.setHours(0, 0, 0, 0);
@@ -207,7 +199,6 @@ class BudgetManager {
207
199
 
208
200
  const usage = this.stmts.getMonthlyUsage.get(userId, monthStartMs);
209
201
 
210
- // Check token limit
211
202
  if (usage.total_tokens >= budget.monthly_token_limit) {
212
203
  return {
213
204
  allowed: false,
@@ -217,7 +208,6 @@ class BudgetManager {
217
208
  };
218
209
  }
219
210
 
220
- // Check request limit
221
211
  if (usage.request_count >= budget.monthly_request_limit) {
222
212
  return {
223
213
  allowed: false,
@@ -227,7 +217,6 @@ class BudgetManager {
227
217
  };
228
218
  }
229
219
 
230
- // Check cost limit
231
220
  if (usage.total_cost >= budget.monthly_cost_limit) {
232
221
  return {
233
222
  allowed: false,
@@ -237,7 +226,6 @@ class BudgetManager {
237
226
  };
238
227
  }
239
228
 
240
- // Check if approaching limits (alert threshold)
241
229
  const warnings = [];
242
230
  if (usage.total_tokens / budget.monthly_token_limit >= budget.alert_threshold) {
243
231
  warnings.push({
@@ -274,7 +262,6 @@ class BudgetManager {
274
262
  };
275
263
  }
276
264
 
277
- // Record usage for a request
278
265
  recordUsage(userId, sessionId, usage) {
279
266
  if (!this.enabled) return;
280
267
 
@@ -302,7 +289,6 @@ class BudgetManager {
302
289
  }
303
290
  }
304
291
 
305
- // Set budget for a user
306
292
  setBudget(userId, budget) {
307
293
  if (!this.enabled) return;
308
294
 
@@ -333,7 +319,6 @@ class BudgetManager {
333
319
  logger.info({ userId, budget }, 'Budget updated');
334
320
  }
335
321
 
336
- // Get usage summary for a user
337
322
  getUsageSummary(userId, days = 30) {
338
323
  if (!this.enabled) return null;
339
324
 
@@ -366,7 +351,6 @@ class BudgetManager {
366
351
  }
367
352
  }
368
353
 
369
- // Singleton instance
370
354
  let budgetManager = null;
371
355
 
372
356
  function getBudgetManager() {
@@ -379,7 +363,6 @@ function getBudgetManager() {
379
363
  return budgetManager;
380
364
  }
381
365
 
382
- // Cleanup on exit
383
366
  process.on('exit', () => {
384
367
  if (budgetManager) {
385
368
  budgetManager.close();
@@ -444,6 +444,15 @@ class SemanticCache {
444
444
  cacheHits: match.entry.hits,
445
445
  }, '[SemanticCache] Cache hit');
446
446
 
447
+ // Tokens avoided ≈ prompt + stored response (no model call was made)
448
+ try {
449
+ const respLen = JSON.stringify(match.entry.response ?? '').length;
450
+ require('../routing/telemetry').recordSavings(
451
+ 'cache_hit',
452
+ Math.ceil((prompt.length + respLen) / 4)
453
+ );
454
+ } catch { /* telemetry is best-effort */ }
455
+
447
456
  return {
448
457
  hit: true,
449
458
  response: match.entry.response,