lynkr 9.7.3 → 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.
- package/README.md +29 -19
- package/bin/cli.js +11 -0
- package/bin/lynkr-init.js +14 -1
- package/bin/lynkr-usage.js +78 -0
- package/bin/wrap.js +60 -35
- package/config/difficulty-anchors.json +22 -0
- package/package.json +24 -3
- package/scripts/audit-log-reader.js +399 -0
- package/scripts/calibrate-thresholds.js +38 -157
- package/scripts/compact-dictionary.js +204 -0
- package/scripts/test-deduplication.js +448 -0
- package/scripts/ws7-anchor-replay.js +108 -0
- package/skills/lynkr/SKILL.md +195 -0
- package/src/api/middleware/loop-guard.js +87 -0
- package/src/api/middleware/request-logging.js +5 -64
- package/src/api/middleware/session.js +0 -0
- package/src/api/openai-router.js +120 -101
- package/src/api/providers-handler.js +27 -2
- package/src/api/router.js +450 -125
- package/src/budget/index.js +2 -19
- package/src/cache/semantic.js +9 -0
- package/src/clients/databricks.js +455 -142
- package/src/clients/gpt-utils.js +11 -105
- package/src/clients/openai-format.js +10 -3
- package/src/clients/openrouter-utils.js +49 -24
- package/src/clients/prompt-cache-injection.js +1 -0
- package/src/clients/provider-capabilities.js +1 -1
- package/src/clients/responses-format.js +34 -3
- package/src/clients/routing.js +15 -0
- package/src/config/index.js +36 -2
- package/src/context/gcf.js +275 -0
- package/src/context/tool-result-compressor.js +51 -9
- package/src/dashboard/api.js +1 -0
- package/src/logger/index.js +14 -1
- package/src/memory/search.js +12 -40
- package/src/memory/tools.js +3 -24
- package/src/orchestrator/bypass.js +4 -2
- package/src/orchestrator/index.js +120 -85
- package/src/routing/affinity-store.js +194 -0
- package/src/routing/agentic-detector.js +36 -6
- package/src/routing/bandit.js +25 -6
- package/src/routing/calibration.js +212 -0
- package/src/routing/client-profiles.js +292 -0
- package/src/routing/complexity-analyzer.js +48 -11
- package/src/routing/deescalator.js +148 -0
- package/src/routing/degradation.js +109 -0
- package/src/routing/feedback.js +157 -0
- package/src/routing/index.js +897 -87
- package/src/routing/intent-score.js +339 -0
- package/src/routing/interaction.js +3 -0
- package/src/routing/knn-router.js +70 -21
- package/src/routing/model-registry.js +28 -7
- package/src/routing/model-tiers.js +25 -2
- package/src/routing/reward-pipeline.js +68 -2
- package/src/routing/risk-analyzer.js +30 -1
- package/src/routing/risk-classifier.js +6 -2
- package/src/routing/session-affinity.js +162 -34
- package/src/routing/telemetry.js +286 -13
- package/src/routing/verifier.js +267 -0
- package/src/server.js +66 -21
- package/src/sessions/cleanup.js +17 -0
- package/src/tools/index.js +1 -15
- package/src/tools/smart-selection.js +10 -0
- package/src/tools/web-client.js +3 -3
- package/.eslintrc.cjs +0 -12
- package/benchmark-configs/litellm_config.yaml +0 -86
- package/benchmark-configs/lynkr.env +0 -48
- package/benchmark-configs/portkey-config.json +0 -60
- package/benchmark-configs/portkey-docker.sh +0 -23
- package/benchmark-tier-routing.js +0 -449
- package/funding.json +0 -110
- package/src/api/middleware/validation.js +0 -261
- package/src/routing/drift-monitor.js +0 -113
- package/src/workers/helpers.js +0 -185
package/src/budget/index.js
CHANGED
|
@@ -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;
|
|
134
|
-
const hourWindow = 60 * 60 * 1000;
|
|
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();
|
package/src/cache/semantic.js
CHANGED
|
@@ -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,
|