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.
- package/README.md +3 -3
- package/config/model-tiers.json +89 -0
- package/install.sh +6 -1
- package/package.json +4 -2
- package/scripts/setup.js +0 -1
- package/src/agents/executor.js +14 -6
- package/src/api/middleware/session.js +15 -2
- package/src/api/openai-router.js +162 -37
- package/src/api/providers-handler.js +15 -1
- package/src/api/router.js +107 -2
- package/src/budget/index.js +4 -3
- package/src/clients/databricks.js +431 -234
- package/src/clients/gpt-utils.js +181 -0
- package/src/clients/ollama-utils.js +66 -140
- package/src/clients/routing.js +0 -1
- package/src/clients/standard-tools.js +99 -3
- package/src/config/index.js +133 -35
- package/src/context/toon.js +173 -0
- package/src/logger/index.js +23 -0
- package/src/orchestrator/index.js +688 -213
- package/src/routing/agentic-detector.js +320 -0
- package/src/routing/complexity-analyzer.js +202 -2
- package/src/routing/cost-optimizer.js +305 -0
- package/src/routing/index.js +168 -159
- package/src/routing/model-tiers.js +365 -0
- package/src/server.js +4 -14
- package/src/sessions/cleanup.js +3 -3
- package/src/sessions/record.js +10 -1
- package/src/sessions/store.js +7 -2
- package/src/tools/agent-task.js +48 -1
- package/src/tools/index.js +19 -2
- package/src/tools/lazy-loader.js +7 -0
- package/src/tools/tinyfish.js +358 -0
- package/src/tools/truncate.js +1 -0
- package/.github/FUNDING.yml +0 -15
- package/.github/workflows/README.md +0 -215
- package/.github/workflows/ci.yml +0 -69
- package/.github/workflows/index.yml +0 -62
- package/.github/workflows/web-tools-tests.yml +0 -56
- package/CITATIONS.bib +0 -6
- package/CLAWROUTER_ROUTING_PLAN.md +0 -910
- package/DEPLOYMENT.md +0 -1001
- package/LYNKR-TUI-PLAN.md +0 -984
- package/PERFORMANCE-REPORT.md +0 -866
- package/PLAN-per-client-model-routing.md +0 -252
- package/ROUTER_COMPARISON.md +0 -173
- package/TIER_ROUTING_PLAN.md +0 -771
- package/docs/42642f749da6234f41b6b425c3bb07c9.txt +0 -1
- package/docs/BingSiteAuth.xml +0 -4
- package/docs/docs-style.css +0 -478
- package/docs/docs.html +0 -197
- package/docs/google5be250e608e6da39.html +0 -1
- package/docs/index.html +0 -577
- package/docs/index.md +0 -577
- package/docs/robots.txt +0 -4
- package/docs/sitemap.xml +0 -44
- package/docs/style.css +0 -1223
- package/documentation/README.md +0 -100
- package/documentation/api.md +0 -806
- package/documentation/claude-code-cli.md +0 -672
- package/documentation/codex-cli.md +0 -397
- package/documentation/contributing.md +0 -571
- package/documentation/cursor-integration.md +0 -731
- package/documentation/docker.md +0 -867
- package/documentation/embeddings.md +0 -760
- package/documentation/faq.md +0 -659
- package/documentation/features.md +0 -396
- package/documentation/headroom.md +0 -519
- package/documentation/installation.md +0 -706
- package/documentation/memory-system.md +0 -476
- package/documentation/production.md +0 -601
- package/documentation/providers.md +0 -906
- package/documentation/testing.md +0 -629
- package/documentation/token-optimization.md +0 -323
- package/documentation/tools.md +0 -697
- package/documentation/troubleshooting.md +0 -893
- package/final-test.js +0 -33
- package/headroom-sidecar/config.py +0 -93
- package/headroom-sidecar/requirements.txt +0 -14
- package/headroom-sidecar/server.py +0 -451
- package/monitor-agents.sh +0 -31
- package/scripts/audit-log-reader.js +0 -399
- package/scripts/compact-dictionary.js +0 -204
- package/scripts/test-deduplication.js +0 -448
- package/src/db/database.sqlite +0 -0
- package/test/README.md +0 -212
- package/test/azure-openai-config.test.js +0 -204
- package/test/azure-openai-error-resilience.test.js +0 -238
- package/test/azure-openai-format-conversion.test.js +0 -354
- package/test/azure-openai-integration.test.js +0 -281
- package/test/azure-openai-routing.test.js +0 -177
- package/test/azure-openai-streaming.test.js +0 -171
- package/test/bedrock-integration.test.js +0 -471
- package/test/comprehensive-test-suite.js +0 -928
- package/test/config-validation.test.js +0 -207
- package/test/cursor-integration.test.js +0 -484
- package/test/format-conversion.test.js +0 -578
- package/test/hybrid-routing-integration.test.js +0 -254
- package/test/hybrid-routing-performance.test.js +0 -418
- package/test/llamacpp-integration.test.js +0 -863
- package/test/lmstudio-integration.test.js +0 -335
- package/test/memory/extractor.test.js +0 -398
- package/test/memory/retriever.test.js +0 -613
- package/test/memory/retriever.test.js.bak +0 -585
- package/test/memory/search.test.js +0 -537
- package/test/memory/search.test.js.bak +0 -389
- package/test/memory/store.test.js +0 -344
- package/test/memory/store.test.js.bak +0 -312
- package/test/memory/surprise.test.js +0 -300
- package/test/memory-performance.test.js +0 -472
- package/test/openai-integration.test.js +0 -686
- package/test/openrouter-error-resilience.test.js +0 -418
- package/test/passthrough-mode.test.js +0 -385
- package/test/performance-benchmark.js +0 -351
- package/test/performance-tests.js +0 -528
- package/test/routing.test.js +0 -219
- package/test/web-tools.test.js +0 -329
- package/test-agents-simple.js +0 -43
- package/test-cli-connection.sh +0 -33
- package/test-learning-unit.js +0 -126
- package/test-learning.js +0 -112
- package/test-parallel-agents.sh +0 -124
- package/test-parallel-direct.js +0 -155
- package/test-subagents.sh +0 -117
|
@@ -1,300 +0,0 @@
|
|
|
1
|
-
const assert = require("assert");
|
|
2
|
-
const { describe, it, beforeEach } = require("node:test");
|
|
3
|
-
|
|
4
|
-
describe("Surprise Detection", () => {
|
|
5
|
-
let surprise;
|
|
6
|
-
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
// Clear module cache
|
|
9
|
-
delete require.cache[require.resolve("../../src/memory/surprise")];
|
|
10
|
-
surprise = require("../../src/memory/surprise");
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
describe("calculateSurprise()", () => {
|
|
14
|
-
it("should return high surprise for novel entities", () => {
|
|
15
|
-
const newMemory = {
|
|
16
|
-
content: "This project uses TensorFlow and PyTorch for ML models",
|
|
17
|
-
type: "fact",
|
|
18
|
-
category: "project"
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const existingMemories = [
|
|
22
|
-
{ content: "This project uses Express.js and React", type: "fact" },
|
|
23
|
-
{ content: "Database is PostgreSQL", type: "fact" }
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
const score = surprise.calculateSurprise(newMemory, existingMemories);
|
|
27
|
-
assert.ok(score > 0.25, `Expected surprise > 0.25, got ${score}`);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("should return low surprise for repeated information", () => {
|
|
31
|
-
const newMemory = {
|
|
32
|
-
content: "User prefers Python",
|
|
33
|
-
type: "preference"
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const existingMemories = [
|
|
37
|
-
{ content: "User prefers Python for scripting", type: "preference" },
|
|
38
|
-
{ content: "User always uses Python", type: "preference" }
|
|
39
|
-
];
|
|
40
|
-
|
|
41
|
-
const score = surprise.calculateSurprise(newMemory, existingMemories);
|
|
42
|
-
assert.ok(score < 0.3, `Expected surprise < 0.3, got ${score}`);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it("should detect contradictions and return high surprise", () => {
|
|
46
|
-
const newMemory = {
|
|
47
|
-
content: "User prefers TypeScript over JavaScript",
|
|
48
|
-
type: "preference"
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
const existingMemories = [
|
|
52
|
-
{ content: "User prefers JavaScript for all projects", type: "preference" }
|
|
53
|
-
];
|
|
54
|
-
|
|
55
|
-
const score = surprise.calculateSurprise(newMemory, existingMemories, {
|
|
56
|
-
userContent: "Actually, I prefer TypeScript"
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
assert.ok(score > 0.4, `Expected high contradiction surprise > 0.4, got ${score}`);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it("should give higher scores to specific details", () => {
|
|
63
|
-
const specificMemory = {
|
|
64
|
-
content: "The authentication module uses JWT tokens with RS256 algorithm and 1-hour expiration",
|
|
65
|
-
type: "fact"
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
const vagueMemory = {
|
|
69
|
-
content: "Uses JWT",
|
|
70
|
-
type: "fact"
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const specificScore = surprise.calculateSurprise(specificMemory, []);
|
|
74
|
-
const vagueScore = surprise.calculateSurprise(vagueMemory, []);
|
|
75
|
-
|
|
76
|
-
assert.ok(specificScore > vagueScore,
|
|
77
|
-
`Expected specific (${specificScore}) > vague (${vagueScore})`);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it("should detect user emphasis and increase surprise", () => {
|
|
81
|
-
const memory = {
|
|
82
|
-
content: "Always use async/await for database operations",
|
|
83
|
-
type: "preference"
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const withEmphasis = surprise.calculateSurprise(memory, [], {
|
|
87
|
-
userContent: "IMPORTANT: Always use async/await!"
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
const withoutEmphasis = surprise.calculateSurprise(memory, []);
|
|
91
|
-
|
|
92
|
-
assert.ok(withEmphasis > withoutEmphasis,
|
|
93
|
-
`Expected emphasis (${withEmphasis}) > no emphasis (${withoutEmphasis})`);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it("should detect context switches", () => {
|
|
97
|
-
const newMemory = {
|
|
98
|
-
content: "User's favorite color is blue",
|
|
99
|
-
type: "preference",
|
|
100
|
-
category: "user"
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
const existingMemories = [
|
|
104
|
-
{ content: "Database uses connection pooling", type: "fact", category: "code" },
|
|
105
|
-
{ content: "API endpoint uses rate limiting", type: "fact", category: "code" }
|
|
106
|
-
];
|
|
107
|
-
|
|
108
|
-
const score = surprise.calculateSurprise(newMemory, existingMemories);
|
|
109
|
-
// Should have some surprise from context switch (5% weight)
|
|
110
|
-
assert.ok(score > 0, `Expected some surprise from context switch, got ${score}`);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it("should return 0 for empty existing memories", () => {
|
|
114
|
-
const memory = { content: "Test memory", type: "fact" };
|
|
115
|
-
const score = surprise.calculateSurprise(memory, []);
|
|
116
|
-
assert.ok(score >= 0 && score <= 1, `Score should be in [0,1], got ${score}`);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it("should bound surprise score between 0 and 1", () => {
|
|
120
|
-
const memory = {
|
|
121
|
-
content: "CRITICAL IMPORTANT: This is completely new revolutionary groundbreaking paradigm shift",
|
|
122
|
-
type: "fact"
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
const score = surprise.calculateSurprise(memory, []);
|
|
126
|
-
assert.ok(score >= 0 && score <= 1, `Score should be in [0,1], got ${score}`);
|
|
127
|
-
});
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
describe("calculateNovelty()", () => {
|
|
131
|
-
it("should return high novelty for unique content", () => {
|
|
132
|
-
const memory = { content: "GraphQL and Apollo Server", type: "fact" };
|
|
133
|
-
const existing = [
|
|
134
|
-
{ content: "REST API with Express", type: "fact" }
|
|
135
|
-
];
|
|
136
|
-
|
|
137
|
-
const novelty = surprise.calculateNovelty(memory, existing);
|
|
138
|
-
assert.ok(novelty > 0.5, `Expected high novelty > 0.5, got ${novelty}`);
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
it("should return low novelty for similar content", () => {
|
|
142
|
-
const memory = { content: "Uses Express for API", type: "fact" };
|
|
143
|
-
const existing = [
|
|
144
|
-
{ content: "Using Express.js for REST API", type: "fact" }
|
|
145
|
-
];
|
|
146
|
-
|
|
147
|
-
const novelty = surprise.calculateNovelty(memory, existing);
|
|
148
|
-
assert.ok(novelty < 0.5, `Expected low novelty < 0.5, got ${novelty}`);
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
describe("detectContradiction()", () => {
|
|
153
|
-
it("should detect contradictions with negation words", () => {
|
|
154
|
-
const memory = { content: "User doesn't like Python", type: "preference" };
|
|
155
|
-
const existing = [
|
|
156
|
-
{ content: "User prefers Python", type: "preference" }
|
|
157
|
-
];
|
|
158
|
-
|
|
159
|
-
const contradiction = surprise.detectContradiction(memory, existing);
|
|
160
|
-
assert.ok(contradiction > 0.5, `Expected contradiction > 0.5, got ${contradiction}`);
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it("should detect contradictions with opposing preferences", () => {
|
|
164
|
-
const memory = { content: "User prefers dark mode", type: "preference" };
|
|
165
|
-
const existing = [
|
|
166
|
-
{ content: "User prefers light mode", type: "preference" }
|
|
167
|
-
];
|
|
168
|
-
|
|
169
|
-
const contradiction = surprise.detectContradiction(memory, existing);
|
|
170
|
-
assert.ok(contradiction > 0, `Expected some contradiction, got ${contradiction}`);
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
it("should return 0 for no contradictions", () => {
|
|
174
|
-
const memory = { content: "User likes TypeScript", type: "preference" };
|
|
175
|
-
const existing = [
|
|
176
|
-
{ content: "User likes JavaScript", type: "preference" }
|
|
177
|
-
];
|
|
178
|
-
|
|
179
|
-
const contradiction = surprise.detectContradiction(memory, existing);
|
|
180
|
-
// These are compatible preferences
|
|
181
|
-
assert.ok(contradiction >= 0, `Expected non-negative, got ${contradiction}`);
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
describe("measureSpecificity()", () => {
|
|
186
|
-
it("should return high score for detailed content", () => {
|
|
187
|
-
const detailed = "The authentication system uses JWT tokens with RS256 signing, 1-hour access tokens, 7-day refresh tokens, and Redis for token storage";
|
|
188
|
-
const specific = surprise.measureSpecificity(detailed);
|
|
189
|
-
assert.ok(specific >= 0.5, `Expected high specificity >= 0.5, got ${specific}`);
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it("should return low score for vague content", () => {
|
|
193
|
-
const vague = "Uses auth";
|
|
194
|
-
const specific = surprise.measureSpecificity(vague);
|
|
195
|
-
assert.ok(specific < 0.3, `Expected low specificity < 0.3, got ${specific}`);
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
it("should give higher scores to content with numbers and technical terms", () => {
|
|
199
|
-
const withDetails = "Server runs on port 3000 with 50 concurrent connections";
|
|
200
|
-
const withoutDetails = "Server runs";
|
|
201
|
-
|
|
202
|
-
const scoreWith = surprise.measureSpecificity(withDetails);
|
|
203
|
-
const scoreWithout = surprise.measureSpecificity(withoutDetails);
|
|
204
|
-
|
|
205
|
-
assert.ok(scoreWith > scoreWithout,
|
|
206
|
-
`Expected detailed (${scoreWith}) > simple (${scoreWithout})`);
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
describe("detectEmphasis()", () => {
|
|
211
|
-
it("should detect all-caps words", () => {
|
|
212
|
-
const emphasized = "IMPORTANT: This is critical";
|
|
213
|
-
const score = surprise.detectEmphasis(emphasized);
|
|
214
|
-
assert.ok(score >= 0.5, `Expected high emphasis >= 0.5, got ${score}`);
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
it("should detect emphasis keywords", () => {
|
|
218
|
-
const keywords = [
|
|
219
|
-
"CRITICAL: Remember this",
|
|
220
|
-
"IMPORTANT: Don't forget",
|
|
221
|
-
"NOTE: This is key",
|
|
222
|
-
"ALWAYS use this approach",
|
|
223
|
-
"NEVER do this"
|
|
224
|
-
];
|
|
225
|
-
|
|
226
|
-
keywords.forEach(text => {
|
|
227
|
-
const score = surprise.detectEmphasis(text);
|
|
228
|
-
assert.ok(score > 0, `Expected emphasis for "${text}", got ${score}`);
|
|
229
|
-
});
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
it("should detect exclamation marks", () => {
|
|
233
|
-
const excited = "This is really important!!!";
|
|
234
|
-
const score = surprise.detectEmphasis(excited);
|
|
235
|
-
assert.ok(score > 0.3, `Expected some emphasis > 0.3, got ${score}`);
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
it("should return 0 for neutral text", () => {
|
|
239
|
-
const neutral = "This is a regular statement.";
|
|
240
|
-
const score = surprise.detectEmphasis(neutral);
|
|
241
|
-
assert.strictEqual(score, 0);
|
|
242
|
-
});
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
describe("measureContextSwitch()", () => {
|
|
246
|
-
it("should detect category changes", () => {
|
|
247
|
-
const newMemory = { content: "User's birthday is January 1st", type: "fact", category: "user" };
|
|
248
|
-
const existing = [
|
|
249
|
-
{ content: "Uses Express.js", type: "fact", category: "code" },
|
|
250
|
-
{ content: "Database is SQLite", type: "fact", category: "code" }
|
|
251
|
-
];
|
|
252
|
-
|
|
253
|
-
const score = surprise.measureContextSwitch(newMemory, existing);
|
|
254
|
-
assert.ok(score > 0, `Expected context switch score > 0, got ${score}`);
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
it("should detect type changes", () => {
|
|
258
|
-
const newMemory = { content: "User prefers Python", type: "preference" };
|
|
259
|
-
const existing = [
|
|
260
|
-
{ content: "Project uses JavaScript", type: "fact" },
|
|
261
|
-
{ content: "API uses REST", type: "fact" }
|
|
262
|
-
];
|
|
263
|
-
|
|
264
|
-
const score = surprise.measureContextSwitch(newMemory, existing);
|
|
265
|
-
assert.ok(score > 0, `Expected type switch score > 0, got ${score}`);
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
it("should return low score for similar context", () => {
|
|
269
|
-
const newMemory = { content: "Code fact about functions", type: "fact", category: "code" };
|
|
270
|
-
const existing = [
|
|
271
|
-
{ content: "Code fact about functions and classes", type: "fact", category: "code" }
|
|
272
|
-
];
|
|
273
|
-
|
|
274
|
-
const score = surprise.measureContextSwitch(newMemory, existing);
|
|
275
|
-
// Should have low context switch due to keyword overlap
|
|
276
|
-
assert.ok(score < 0.5, `Expected low context switch < 0.5, got ${score}`);
|
|
277
|
-
});
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
describe("Edge Cases", () => {
|
|
281
|
-
it("should handle empty content", () => {
|
|
282
|
-
const memory = { content: "", type: "fact" };
|
|
283
|
-
const score = surprise.calculateSurprise(memory, []);
|
|
284
|
-
assert.ok(score >= 0 && score <= 1);
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
it("should handle very long content", () => {
|
|
288
|
-
const longContent = "word ".repeat(1000);
|
|
289
|
-
const memory = { content: longContent, type: "fact" };
|
|
290
|
-
const score = surprise.calculateSurprise(memory, []);
|
|
291
|
-
assert.ok(score >= 0 && score <= 1);
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
it("should handle special characters", () => {
|
|
295
|
-
const memory = { content: "Uses @angular/core ^16.0.0 with RxJS ~7.8", type: "fact" };
|
|
296
|
-
const score = surprise.calculateSurprise(memory, []);
|
|
297
|
-
assert.ok(score >= 0 && score <= 1);
|
|
298
|
-
});
|
|
299
|
-
});
|
|
300
|
-
});
|