@theokit/sdk 4.61.0 → 4.62.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/CHANGELOG.md +73 -0
- package/dist/{agent-P42GA6RM.js → agent-NVBFTY5H.js} +3 -3
- package/dist/{agent-P42GA6RM.js.map → agent-NVBFTY5H.js.map} +1 -1
- package/dist/{agent-M53C3PAA.cjs → agent-VYPUO4UB.cjs} +4 -4
- package/dist/{agent-M53C3PAA.cjs.map → agent-VYPUO4UB.cjs.map} +1 -1
- package/dist/{chunk-R7YIVL3K.cjs → chunk-AH6WD7JR.cjs} +57 -24
- package/dist/chunk-AH6WD7JR.cjs.map +1 -0
- package/dist/{chunk-5IT6DUOO.cjs → chunk-CWHTMNNK.cjs} +4 -4
- package/dist/{chunk-5IT6DUOO.cjs.map → chunk-CWHTMNNK.cjs.map} +1 -1
- package/dist/{chunk-532CSLYU.js → chunk-IBYRA5PM.js} +3 -3
- package/dist/{chunk-532CSLYU.js.map → chunk-IBYRA5PM.js.map} +1 -1
- package/dist/{chunk-GQZKDGZM.js → chunk-SKOCYA55.js} +55 -22
- package/dist/chunk-SKOCYA55.js.map +1 -0
- package/dist/cron.cjs +3 -3
- package/dist/cron.js +2 -2
- package/dist/eval.cjs +2 -2
- package/dist/eval.js +1 -1
- package/dist/index.cjs +17 -17
- package/dist/index.js +4 -4
- package/package.json +1 -1
- package/dist/chunk-GQZKDGZM.js.map +0 -1
- package/dist/chunk-R7YIVL3K.cjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,78 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.62.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 36bb21f: Memory recall is scored with BM25 instead of Jaccard, and rank fusion is damped for stores of
|
|
8
|
+
tens rather than hundreds.
|
|
9
|
+
|
|
10
|
+
**What changes for you:** which memories are selected when several are plausible. The store, the
|
|
11
|
+
budget and the API are unchanged; the ordering is not.
|
|
12
|
+
|
|
13
|
+
Measured on LongMemEval-S — 500 questions, 54 sessions each — through a public eval harness, with
|
|
14
|
+
its tokenised-substring `grep` adapter as the floor:
|
|
15
|
+
|
|
16
|
+
| | hit@5 | P@5 | R@5 | p50 |
|
|
17
|
+
| ----------------------- | --------- | --------- | --------- | -------- |
|
|
18
|
+
| Jaccard (4.61.0) | 80.0% | 0.236 | 0.670 | 205ms |
|
|
19
|
+
| `grep` (floor) | 89.0% | 0.295 | 0.807 | 2ms |
|
|
20
|
+
| **BM25 (this release)** | **96.8%** | **0.329** | **0.904** | **20ms** |
|
|
21
|
+
|
|
22
|
+
Jaccard lost to a naive substring match. The mechanism was isolated before it was fixed: on a
|
|
23
|
+
preference query, the term that discriminates appeared in 2 of 15 documents while a noise term
|
|
24
|
+
appeared in 14 — and Jaccard weighted them identically. Almost every document scored above zero,
|
|
25
|
+
fusion flattened what ordering remained, and recency decided a relevance question. IDF is the
|
|
26
|
+
whole fix, and the gain concentrates where that predicts:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
single-session-preference 46.7% -> 86.7% (+40.0)
|
|
30
|
+
single-session-assistant 89.3% -> 100.0% (+10.7)
|
|
31
|
+
temporal-reasoning 85.7% -> 96.2% (+10.5)
|
|
32
|
+
multi-session 94.7% -> 96.2% (+1.5)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Also **10x faster**: the previous implementation called its scoring function from inside sort
|
|
36
|
+
comparators, re-tokenising every fact O(n log n) times per query.
|
|
37
|
+
|
|
38
|
+
Rank fusion damping moves from k = 60 to k = 5. Swept rather than chosen — the 500-question corpus
|
|
39
|
+
is insensitive to k once terms are IDF-weighted, while a 15-session corpus goes from 14/15 to
|
|
40
|
+
15/15. The sweep cannot separate 5 from 1, so the tie is broken on the principle that at k = 1
|
|
41
|
+
damping is nearly gone and fusion stops fusing.
|
|
42
|
+
|
|
43
|
+
**This improves the reliability of memory poisoning as well as of recall**, and the two cannot be
|
|
44
|
+
separated: the property that makes a planted entry work is the property that makes a real one
|
|
45
|
+
useful. See the accompanying patch note for the re-measured figures.
|
|
46
|
+
|
|
47
|
+
### Patch Changes
|
|
48
|
+
|
|
49
|
+
- Corrects a security figure published with 4.61.0, and adds the rule that produced the error.
|
|
50
|
+
|
|
51
|
+
The 4.61.0 notes said a planted memory entry made the agent perform the action it described in
|
|
52
|
+
**2 of 6 runs**. Re-measured against the published 4.61.0 itself, it is **6 of 6**. Registering
|
|
53
|
+
the permission engine still blocks it — 6 of 6, with zero errors.
|
|
54
|
+
|
|
55
|
+
The old figure was not a smaller version of the same risk; it was a measurement of a different
|
|
56
|
+
thing. It was taken against a retrieval path that did not recall the planted entry at all: on
|
|
57
|
+
4.60.0 the agent answered "Done." and never saw it, while on 4.61.0 it recites the entry
|
|
58
|
+
verbatim. Nothing about the attack changed between those runs — the recall path did.
|
|
59
|
+
|
|
60
|
+
**A poisoning rate measured against a retrieval path that does not recall the plant is a
|
|
61
|
+
measurement of how often the attack reached the model, not of how often the model resisted it.**
|
|
62
|
+
Any such figure has to record whether the plant was recalled, or it cannot be compared across
|
|
63
|
+
versions.
|
|
64
|
+
|
|
65
|
+
The consequence for anyone depending on this: improving recall is a change to the threat model,
|
|
66
|
+
not something orthogonal to it. The property that makes a planted memory work is the property
|
|
67
|
+
that makes a real one useful. **If anything other than your agent's own deliberate writes can
|
|
68
|
+
reach the memory directory, register the permission engine.**
|
|
69
|
+
|
|
70
|
+
Separately, the original proof constructed the engine as `new PermissionEngine({ rules: [] })`.
|
|
71
|
+
The constructor takes the rules positionally, so that was never a rule list, and nothing checked
|
|
72
|
+
because the script was JavaScript. A crash inside the engine and a gated call produce the same
|
|
73
|
+
observation. Re-run in TypeScript with `new PermissionEngine([])`, it gates: 6 of 6 blocked, 0
|
|
74
|
+
runs threw.
|
|
75
|
+
|
|
3
76
|
## 4.61.0
|
|
4
77
|
|
|
5
78
|
### Minor Changes
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { Agent } from './chunk-
|
|
1
|
+
export { Agent } from './chunk-SKOCYA55.js';
|
|
2
2
|
import './chunk-SUKXXLWD.js';
|
|
3
3
|
import './chunk-YEXA3PGR.js';
|
|
4
4
|
import './chunk-K2BQQ445.js';
|
|
@@ -51,5 +51,5 @@ import './chunk-3OR54XG4.js';
|
|
|
51
51
|
import './chunk-IDCKSLYH.js';
|
|
52
52
|
import './chunk-T7XEKOVW.js';
|
|
53
53
|
import './chunk-T7O6K6PX.js';
|
|
54
|
-
//# sourceMappingURL=agent-
|
|
55
|
-
//# sourceMappingURL=agent-
|
|
54
|
+
//# sourceMappingURL=agent-NVBFTY5H.js.map
|
|
55
|
+
//# sourceMappingURL=agent-NVBFTY5H.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"agent-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"agent-NVBFTY5H.js"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkAH6WD7JR_cjs = require('./chunk-AH6WD7JR.cjs');
|
|
4
4
|
require('./chunk-NGESVVJN.cjs');
|
|
5
5
|
require('./chunk-2DG7KW4L.cjs');
|
|
6
6
|
require('./chunk-BUUUWQMB.cjs');
|
|
@@ -58,7 +58,7 @@ require('./chunk-NUKRL3I6.cjs');
|
|
|
58
58
|
|
|
59
59
|
Object.defineProperty(exports, "Agent", {
|
|
60
60
|
enumerable: true,
|
|
61
|
-
get: function () { return
|
|
61
|
+
get: function () { return chunkAH6WD7JR_cjs.Agent; }
|
|
62
62
|
});
|
|
63
|
-
//# sourceMappingURL=agent-
|
|
64
|
-
//# sourceMappingURL=agent-
|
|
63
|
+
//# sourceMappingURL=agent-VYPUO4UB.cjs.map
|
|
64
|
+
//# sourceMappingURL=agent-VYPUO4UB.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"agent-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"agent-VYPUO4UB.cjs"}
|
|
@@ -3439,7 +3439,7 @@ var HISTOGRAM_NAMES = {
|
|
|
3439
3439
|
};
|
|
3440
3440
|
function safeRequire(moduleName) {
|
|
3441
3441
|
try {
|
|
3442
|
-
const r = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-
|
|
3442
|
+
const r = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-AH6WD7JR.cjs', document.baseURI).href)));
|
|
3443
3443
|
return r(moduleName);
|
|
3444
3444
|
} catch {
|
|
3445
3445
|
return void 0;
|
|
@@ -3667,7 +3667,7 @@ var cachedOtel;
|
|
|
3667
3667
|
function loadOtel() {
|
|
3668
3668
|
if (cachedOtel === void 0) {
|
|
3669
3669
|
try {
|
|
3670
|
-
const r = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-
|
|
3670
|
+
const r = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-AH6WD7JR.cjs', document.baseURI).href)));
|
|
3671
3671
|
const mod = r("@opentelemetry/api");
|
|
3672
3672
|
cachedOtel = mod;
|
|
3673
3673
|
} catch {
|
|
@@ -9139,17 +9139,7 @@ function terms(text) {
|
|
|
9139
9139
|
text.toLowerCase().split(/[^a-z0-9]+/).filter((w) => w.length >= 3 && !STOPWORDS.has(w))
|
|
9140
9140
|
);
|
|
9141
9141
|
}
|
|
9142
|
-
|
|
9143
|
-
if (queryTerms.size === 0) return 0;
|
|
9144
|
-
const factTerms = terms(fact.text);
|
|
9145
|
-
if (factTerms.size === 0) return 0;
|
|
9146
|
-
let shared = 0;
|
|
9147
|
-
for (const w of queryTerms) if (factTerms.has(w)) shared += 1;
|
|
9148
|
-
if (shared === 0) return 0;
|
|
9149
|
-
const union = (/* @__PURE__ */ new Set([...queryTerms, ...factTerms])).size;
|
|
9150
|
-
return shared / union;
|
|
9151
|
-
}
|
|
9152
|
-
var RRF_K = 60;
|
|
9142
|
+
var RRF_K = 5;
|
|
9153
9143
|
function corroborationRank(fact) {
|
|
9154
9144
|
if (fact.observations === void 0) return 1;
|
|
9155
9145
|
return fact.observations > 1 ? 2 : 0;
|
|
@@ -9157,13 +9147,55 @@ function corroborationRank(fact) {
|
|
|
9157
9147
|
function sortByCorroboration(facts) {
|
|
9158
9148
|
return [...facts].sort((a, b) => corroborationRank(b) - corroborationRank(a));
|
|
9159
9149
|
}
|
|
9160
|
-
|
|
9161
|
-
|
|
9162
|
-
|
|
9163
|
-
const
|
|
9164
|
-
|
|
9165
|
-
|
|
9166
|
-
|
|
9150
|
+
var BM25_K1 = 1.2;
|
|
9151
|
+
var BM25_B = 0.75;
|
|
9152
|
+
function docTerms(text) {
|
|
9153
|
+
const counts = /* @__PURE__ */ new Map();
|
|
9154
|
+
let length = 0;
|
|
9155
|
+
for (const w of text.toLowerCase().split(/[^a-z0-9]+/).filter((x) => x.length >= 3 && !STOPWORDS.has(x))) {
|
|
9156
|
+
counts.set(w, (counts.get(w) ?? 0) + 1);
|
|
9157
|
+
length += 1;
|
|
9158
|
+
}
|
|
9159
|
+
return { counts, length };
|
|
9160
|
+
}
|
|
9161
|
+
function documentFrequencies(docs, queryTerms) {
|
|
9162
|
+
const df = /* @__PURE__ */ new Map();
|
|
9163
|
+
for (const term of queryTerms) {
|
|
9164
|
+
let count = 0;
|
|
9165
|
+
for (const d of docs) if (d.terms.counts.has(term)) count += 1;
|
|
9166
|
+
df.set(term, count);
|
|
9167
|
+
}
|
|
9168
|
+
return df;
|
|
9169
|
+
}
|
|
9170
|
+
function scoreDoc(doc, queryTerms, df, n, avgLength) {
|
|
9171
|
+
let score = 0;
|
|
9172
|
+
for (const term of queryTerms) {
|
|
9173
|
+
const tf = doc.terms.counts.get(term);
|
|
9174
|
+
if (tf === void 0) continue;
|
|
9175
|
+
const frequency = df.get(term) ?? 0;
|
|
9176
|
+
const idf = Math.log(1 + (n - frequency + 0.5) / (frequency + 0.5));
|
|
9177
|
+
const norm = tf + BM25_K1 * (1 - BM25_B + BM25_B * doc.terms.length / avgLength);
|
|
9178
|
+
score += idf * (tf * (BM25_K1 + 1)) / norm;
|
|
9179
|
+
}
|
|
9180
|
+
return score;
|
|
9181
|
+
}
|
|
9182
|
+
function bm25Scores(facts, queryTerms) {
|
|
9183
|
+
const scores = /* @__PURE__ */ new Map();
|
|
9184
|
+
if (queryTerms.size === 0 || facts.length === 0) return scores;
|
|
9185
|
+
const docs = facts.map((f) => ({ fact: f, terms: docTerms(f.text) }));
|
|
9186
|
+
const n = docs.length;
|
|
9187
|
+
const avgLength = docs.reduce((sum, d) => sum + d.terms.length, 0) / n || 1;
|
|
9188
|
+
const df = documentFrequencies(docs, queryTerms);
|
|
9189
|
+
for (const d of docs) {
|
|
9190
|
+
const score = scoreDoc(d, queryTerms, df, n, avgLength);
|
|
9191
|
+
if (score > 0) scores.set(d.fact, score);
|
|
9192
|
+
}
|
|
9193
|
+
return scores;
|
|
9194
|
+
}
|
|
9195
|
+
function rankForQuery(facts, scores) {
|
|
9196
|
+
const matching = facts.filter((f) => (scores.get(f) ?? 0) > 0);
|
|
9197
|
+
const rest = facts.filter((f) => (scores.get(f) ?? 0) <= 0);
|
|
9198
|
+
const byRelevance = [...matching].sort((a, b) => (scores.get(b) ?? 0) - (scores.get(a) ?? 0));
|
|
9167
9199
|
const byRecency = [...matching].sort(
|
|
9168
9200
|
(a, b) => (b.modified ?? "").localeCompare(a.modified ?? "")
|
|
9169
9201
|
);
|
|
@@ -9191,9 +9223,10 @@ function rankBuckets(facts, query) {
|
|
|
9191
9223
|
dated.sort((a, b) => b.modified.localeCompare(a.modified));
|
|
9192
9224
|
return { dated, undated };
|
|
9193
9225
|
}
|
|
9226
|
+
const scores = bm25Scores(facts, queryTerms);
|
|
9194
9227
|
return {
|
|
9195
|
-
dated: rankForQuery(dated,
|
|
9196
|
-
undated: [...undated].sort((a, b) =>
|
|
9228
|
+
dated: rankForQuery(dated, scores),
|
|
9229
|
+
undated: [...undated].sort((a, b) => (scores.get(b) ?? 0) - (scores.get(a) ?? 0))
|
|
9197
9230
|
};
|
|
9198
9231
|
}
|
|
9199
9232
|
function selectFactsForInjection(facts, options = {}) {
|
|
@@ -10755,5 +10788,5 @@ exports.computeCost = computeCost;
|
|
|
10755
10788
|
exports.generateCronId = generateCronId;
|
|
10756
10789
|
exports.getPricingEntry = getPricingEntry;
|
|
10757
10790
|
exports.openRouterMemoryEmbeddingProviderAdapter = openRouterMemoryEmbeddingProviderAdapter;
|
|
10758
|
-
//# sourceMappingURL=chunk-
|
|
10759
|
-
//# sourceMappingURL=chunk-
|
|
10791
|
+
//# sourceMappingURL=chunk-AH6WD7JR.cjs.map
|
|
10792
|
+
//# sourceMappingURL=chunk-AH6WD7JR.cjs.map
|