@seanhogg/builderforce-memory 2026.10.28 → 2026.10.29

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 (253) hide show
  1. package/dist/ingest/IngestionPipeline.d.ts +1 -8
  2. package/dist/ingest/IngestionPipeline.d.ts.map +1 -1
  3. package/dist/ingest/IngestionPipeline.js +3 -15
  4. package/dist/ingest/IngestionPipeline.js.map +1 -1
  5. package/dist/ingest/docsExtract.d.ts +30 -0
  6. package/dist/ingest/docsExtract.d.ts.map +1 -0
  7. package/dist/ingest/docsExtract.js +221 -0
  8. package/dist/ingest/docsExtract.js.map +1 -0
  9. package/dist/ingest/hash.d.ts +15 -0
  10. package/dist/ingest/hash.d.ts.map +1 -0
  11. package/dist/ingest/hash.js +22 -0
  12. package/dist/ingest/hash.js.map +1 -0
  13. package/dist/ingest/parsers.d.ts.map +1 -1
  14. package/dist/ingest/parsers.js +4 -0
  15. package/dist/ingest/parsers.js.map +1 -1
  16. package/dist/ingest/types.d.ts +7 -0
  17. package/dist/ingest/types.d.ts.map +1 -1
  18. package/dist/ingest/types.js.map +1 -1
  19. package/dist/knowledge/build.d.ts +24 -0
  20. package/dist/knowledge/build.d.ts.map +1 -0
  21. package/dist/knowledge/build.js +263 -0
  22. package/dist/knowledge/build.js.map +1 -0
  23. package/dist/knowledge/cards.d.ts +17 -0
  24. package/dist/knowledge/cards.d.ts.map +1 -0
  25. package/dist/knowledge/cards.js +118 -0
  26. package/dist/knowledge/cards.js.map +1 -0
  27. package/dist/knowledge/findings.d.ts +24 -0
  28. package/dist/knowledge/findings.d.ts.map +1 -0
  29. package/dist/knowledge/findings.js +152 -0
  30. package/dist/knowledge/findings.js.map +1 -0
  31. package/dist/knowledge/importance.d.ts +21 -0
  32. package/dist/knowledge/importance.d.ts.map +1 -0
  33. package/dist/knowledge/importance.js +70 -0
  34. package/dist/knowledge/importance.js.map +1 -0
  35. package/dist/knowledge/index.d.ts +31 -0
  36. package/dist/knowledge/index.d.ts.map +1 -0
  37. package/dist/knowledge/index.js +26 -0
  38. package/dist/knowledge/index.js.map +1 -0
  39. package/dist/knowledge/judge.d.ts +86 -0
  40. package/dist/knowledge/judge.d.ts.map +1 -0
  41. package/dist/knowledge/judge.js +213 -0
  42. package/dist/knowledge/judge.js.map +1 -0
  43. package/dist/knowledge/model.d.ts +333 -0
  44. package/dist/knowledge/model.d.ts.map +1 -0
  45. package/dist/knowledge/model.js +13 -0
  46. package/dist/knowledge/model.js.map +1 -0
  47. package/dist/knowledge/packs/docs.d.ts +17 -0
  48. package/dist/knowledge/packs/docs.d.ts.map +1 -0
  49. package/dist/knowledge/packs/docs.js +89 -0
  50. package/dist/knowledge/packs/docs.js.map +1 -0
  51. package/dist/knowledge/partitions.d.ts +31 -0
  52. package/dist/knowledge/partitions.d.ts.map +1 -0
  53. package/dist/knowledge/partitions.js +135 -0
  54. package/dist/knowledge/partitions.js.map +1 -0
  55. package/dist/knowledge/plan.d.ts +33 -0
  56. package/dist/knowledge/plan.d.ts.map +1 -0
  57. package/dist/knowledge/plan.js +89 -0
  58. package/dist/knowledge/plan.js.map +1 -0
  59. package/dist/knowledge/refs.d.ts +40 -0
  60. package/dist/knowledge/refs.d.ts.map +1 -0
  61. package/dist/knowledge/refs.js +102 -0
  62. package/dist/knowledge/refs.js.map +1 -0
  63. package/dist/knowledge/resolve.d.ts +35 -0
  64. package/dist/knowledge/resolve.d.ts.map +1 -0
  65. package/dist/knowledge/resolve.js +67 -0
  66. package/dist/knowledge/resolve.js.map +1 -0
  67. package/dist/knowledge/review.d.ts +23 -0
  68. package/dist/knowledge/review.d.ts.map +1 -0
  69. package/dist/knowledge/review.js +233 -0
  70. package/dist/knowledge/review.js.map +1 -0
  71. package/dist/knowledge/sources.d.ts +47 -0
  72. package/dist/knowledge/sources.d.ts.map +1 -0
  73. package/dist/knowledge/sources.js +136 -0
  74. package/dist/knowledge/sources.js.map +1 -0
  75. package/dist/knowledge/stores/localSnapshotStore.d.ts +50 -0
  76. package/dist/knowledge/stores/localSnapshotStore.d.ts.map +1 -0
  77. package/dist/knowledge/stores/localSnapshotStore.js +125 -0
  78. package/dist/knowledge/stores/localSnapshotStore.js.map +1 -0
  79. package/dist/knowledge/trace.d.ts +32 -0
  80. package/dist/knowledge/trace.d.ts.map +1 -0
  81. package/dist/knowledge/trace.js +102 -0
  82. package/dist/knowledge/trace.js.map +1 -0
  83. package/dist/knowledge/truncate.d.ts +24 -0
  84. package/dist/knowledge/truncate.d.ts.map +1 -0
  85. package/dist/knowledge/truncate.js +128 -0
  86. package/dist/knowledge/truncate.js.map +1 -0
  87. package/dist/memory/SemanticRecall.d.ts.map +1 -1
  88. package/dist/memory/SemanticRecall.js +3 -1
  89. package/dist/memory/SemanticRecall.js.map +1 -1
  90. package/dist/retrieval/HybridRetriever.d.ts.map +1 -1
  91. package/dist/retrieval/HybridRetriever.js +3 -1
  92. package/dist/retrieval/HybridRetriever.js.map +1 -1
  93. package/dist/retrieval/bm25.d.ts +3 -2
  94. package/dist/retrieval/bm25.d.ts.map +1 -1
  95. package/dist/retrieval/bm25.js +5 -3
  96. package/dist/retrieval/bm25.js.map +1 -1
  97. package/dist/retrieval/fusion.d.ts +2 -1
  98. package/dist/retrieval/fusion.d.ts.map +1 -1
  99. package/dist/retrieval/fusion.js +4 -2
  100. package/dist/retrieval/fusion.js.map +1 -1
  101. package/dist/retrieval/hnsw.d.ts +49 -11
  102. package/dist/retrieval/hnsw.d.ts.map +1 -1
  103. package/dist/retrieval/hnsw.js +57 -29
  104. package/dist/retrieval/hnsw.js.map +1 -1
  105. package/dist/retrieval/index.d.ts +7 -3
  106. package/dist/retrieval/index.d.ts.map +1 -1
  107. package/dist/retrieval/index.js +5 -2
  108. package/dist/retrieval/index.js.map +1 -1
  109. package/dist/retrieval/knowledge-index/bytes.d.ts +43 -0
  110. package/dist/retrieval/knowledge-index/bytes.d.ts.map +1 -0
  111. package/dist/retrieval/knowledge-index/bytes.js +151 -0
  112. package/dist/retrieval/knowledge-index/bytes.js.map +1 -0
  113. package/dist/retrieval/knowledge-index/cascade.d.ts +37 -0
  114. package/dist/retrieval/knowledge-index/cascade.d.ts.map +1 -0
  115. package/dist/retrieval/knowledge-index/cascade.js +111 -0
  116. package/dist/retrieval/knowledge-index/cascade.js.map +1 -0
  117. package/dist/retrieval/knowledge-index/compact.d.ts +18 -0
  118. package/dist/retrieval/knowledge-index/compact.d.ts.map +1 -0
  119. package/dist/retrieval/knowledge-index/compact.js +64 -0
  120. package/dist/retrieval/knowledge-index/compact.js.map +1 -0
  121. package/dist/retrieval/knowledge-index/csr.d.ts +41 -0
  122. package/dist/retrieval/knowledge-index/csr.d.ts.map +1 -0
  123. package/dist/retrieval/knowledge-index/csr.js +76 -0
  124. package/dist/retrieval/knowledge-index/csr.js.map +1 -0
  125. package/dist/retrieval/knowledge-index/digest.d.ts +21 -0
  126. package/dist/retrieval/knowledge-index/digest.d.ts.map +1 -0
  127. package/dist/retrieval/knowledge-index/digest.js +50 -0
  128. package/dist/retrieval/knowledge-index/digest.js.map +1 -0
  129. package/dist/retrieval/knowledge-index/embeddings.d.ts +32 -0
  130. package/dist/retrieval/knowledge-index/embeddings.d.ts.map +1 -0
  131. package/dist/retrieval/knowledge-index/embeddings.js +78 -0
  132. package/dist/retrieval/knowledge-index/embeddings.js.map +1 -0
  133. package/dist/retrieval/knowledge-index/expand.d.ts +19 -0
  134. package/dist/retrieval/knowledge-index/expand.d.ts.map +1 -0
  135. package/dist/retrieval/knowledge-index/expand.js +49 -0
  136. package/dist/retrieval/knowledge-index/expand.js.map +1 -0
  137. package/dist/retrieval/knowledge-index/index.d.ts +40 -0
  138. package/dist/retrieval/knowledge-index/index.d.ts.map +1 -0
  139. package/dist/retrieval/knowledge-index/index.js +134 -0
  140. package/dist/retrieval/knowledge-index/index.js.map +1 -0
  141. package/dist/retrieval/knowledge-index/lexical.d.ts +26 -0
  142. package/dist/retrieval/knowledge-index/lexical.d.ts.map +1 -0
  143. package/dist/retrieval/knowledge-index/lexical.js +76 -0
  144. package/dist/retrieval/knowledge-index/lexical.js.map +1 -0
  145. package/dist/retrieval/knowledge-index/pairs.d.ts +22 -0
  146. package/dist/retrieval/knowledge-index/pairs.d.ts.map +1 -0
  147. package/dist/retrieval/knowledge-index/pairs.js +51 -0
  148. package/dist/retrieval/knowledge-index/pairs.js.map +1 -0
  149. package/dist/retrieval/knowledge-index/prune.d.ts +21 -0
  150. package/dist/retrieval/knowledge-index/prune.d.ts.map +1 -0
  151. package/dist/retrieval/knowledge-index/prune.js +43 -0
  152. package/dist/retrieval/knowledge-index/prune.js.map +1 -0
  153. package/dist/retrieval/knowledge-index/quantize.d.ts +37 -0
  154. package/dist/retrieval/knowledge-index/quantize.d.ts.map +1 -0
  155. package/dist/retrieval/knowledge-index/quantize.js +77 -0
  156. package/dist/retrieval/knowledge-index/quantize.js.map +1 -0
  157. package/dist/retrieval/knowledge-index/serialize.d.ts +18 -0
  158. package/dist/retrieval/knowledge-index/serialize.d.ts.map +1 -0
  159. package/dist/retrieval/knowledge-index/serialize.js +123 -0
  160. package/dist/retrieval/knowledge-index/serialize.js.map +1 -0
  161. package/dist/retrieval/knowledge-index/sha256.d.ts +30 -0
  162. package/dist/retrieval/knowledge-index/sha256.d.ts.map +1 -0
  163. package/dist/retrieval/knowledge-index/sha256.js +130 -0
  164. package/dist/retrieval/knowledge-index/sha256.js.map +1 -0
  165. package/dist/retrieval/knowledge-index/state.d.ts +55 -0
  166. package/dist/retrieval/knowledge-index/state.d.ts.map +1 -0
  167. package/dist/retrieval/knowledge-index/state.js +67 -0
  168. package/dist/retrieval/knowledge-index/state.js.map +1 -0
  169. package/dist/retrieval/knowledge-index/tokenize.d.ts +20 -0
  170. package/dist/retrieval/knowledge-index/tokenize.d.ts.map +1 -0
  171. package/dist/retrieval/knowledge-index/tokenize.js +42 -0
  172. package/dist/retrieval/knowledge-index/tokenize.js.map +1 -0
  173. package/dist/retrieval/knowledge-index/traverse.d.ts +26 -0
  174. package/dist/retrieval/knowledge-index/traverse.d.ts.map +1 -0
  175. package/dist/retrieval/knowledge-index/traverse.js +90 -0
  176. package/dist/retrieval/knowledge-index/traverse.js.map +1 -0
  177. package/dist/retrieval/knowledge-index/types.d.ts +85 -0
  178. package/dist/retrieval/knowledge-index/types.d.ts.map +1 -0
  179. package/dist/retrieval/knowledge-index/types.js +9 -0
  180. package/dist/retrieval/knowledge-index/types.js.map +1 -0
  181. package/dist/retrieval/mmr.d.ts +11 -4
  182. package/dist/retrieval/mmr.d.ts.map +1 -1
  183. package/dist/retrieval/mmr.js +28 -8
  184. package/dist/retrieval/mmr.js.map +1 -1
  185. package/dist/retrieval/order.d.ts +41 -0
  186. package/dist/retrieval/order.d.ts.map +1 -0
  187. package/dist/retrieval/order.js +54 -0
  188. package/dist/retrieval/order.js.map +1 -0
  189. package/dist/retrieval/weightedFusion.d.ts +2 -1
  190. package/dist/retrieval/weightedFusion.d.ts.map +1 -1
  191. package/dist/retrieval/weightedFusion.js +7 -5
  192. package/dist/retrieval/weightedFusion.js.map +1 -1
  193. package/dist/vectorstore/MemoryVectorStore.d.ts.map +1 -1
  194. package/dist/vectorstore/MemoryVectorStore.js +2 -1
  195. package/dist/vectorstore/MemoryVectorStore.js.map +1 -1
  196. package/package.json +8 -3
  197. package/src/ingest/IngestionPipeline.ts +3 -15
  198. package/src/ingest/docsExtract.ts +219 -0
  199. package/src/ingest/hash.ts +22 -0
  200. package/src/ingest/parsers.ts +4 -0
  201. package/src/ingest/types.ts +7 -0
  202. package/src/knowledge/build.test.ts +150 -0
  203. package/src/knowledge/build.ts +266 -0
  204. package/src/knowledge/cards.ts +130 -0
  205. package/src/knowledge/docs.test.ts +118 -0
  206. package/src/knowledge/findings.ts +159 -0
  207. package/src/knowledge/importance.ts +72 -0
  208. package/src/knowledge/index.ts +53 -0
  209. package/src/knowledge/judge.ts +231 -0
  210. package/src/knowledge/model.ts +312 -0
  211. package/src/knowledge/packs/docs.ts +91 -0
  212. package/src/knowledge/partitions.test.ts +98 -0
  213. package/src/knowledge/partitions.ts +119 -0
  214. package/src/knowledge/plan.ts +115 -0
  215. package/src/knowledge/refs.ts +108 -0
  216. package/src/knowledge/resolve.ts +78 -0
  217. package/src/knowledge/review.test.ts +180 -0
  218. package/src/knowledge/review.ts +235 -0
  219. package/src/knowledge/sources.ts +146 -0
  220. package/src/knowledge/stores/localSnapshotStore.test.ts +82 -0
  221. package/src/knowledge/stores/localSnapshotStore.ts +159 -0
  222. package/src/knowledge/testkit.test-util.ts +92 -0
  223. package/src/knowledge/trace.test.ts +91 -0
  224. package/src/knowledge/trace.ts +111 -0
  225. package/src/knowledge/truncate.ts +118 -0
  226. package/src/memory/SemanticRecall.ts +3 -1
  227. package/src/retrieval/HybridRetriever.ts +3 -1
  228. package/src/retrieval/bm25.ts +5 -3
  229. package/src/retrieval/fusion.ts +5 -2
  230. package/src/retrieval/hnsw.ts +82 -35
  231. package/src/retrieval/index.ts +17 -3
  232. package/src/retrieval/knowledge-index/bytes.ts +166 -0
  233. package/src/retrieval/knowledge-index/cascade.ts +125 -0
  234. package/src/retrieval/knowledge-index/compact.ts +68 -0
  235. package/src/retrieval/knowledge-index/csr.ts +102 -0
  236. package/src/retrieval/knowledge-index/digest.ts +54 -0
  237. package/src/retrieval/knowledge-index/embeddings.ts +85 -0
  238. package/src/retrieval/knowledge-index/expand.ts +55 -0
  239. package/src/retrieval/knowledge-index/index.ts +162 -0
  240. package/src/retrieval/knowledge-index/lexical.ts +78 -0
  241. package/src/retrieval/knowledge-index/pairs.ts +57 -0
  242. package/src/retrieval/knowledge-index/prune.ts +48 -0
  243. package/src/retrieval/knowledge-index/quantize.ts +78 -0
  244. package/src/retrieval/knowledge-index/serialize.ts +124 -0
  245. package/src/retrieval/knowledge-index/sha256.ts +122 -0
  246. package/src/retrieval/knowledge-index/state.ts +108 -0
  247. package/src/retrieval/knowledge-index/tokenize.ts +41 -0
  248. package/src/retrieval/knowledge-index/traverse.ts +95 -0
  249. package/src/retrieval/knowledge-index/types.ts +78 -0
  250. package/src/retrieval/mmr.ts +35 -10
  251. package/src/retrieval/order.ts +68 -0
  252. package/src/retrieval/weightedFusion.ts +8 -5
  253. package/src/vectorstore/MemoryVectorStore.ts +2 -1
@@ -0,0 +1,111 @@
1
+ /**
2
+ * cascade.ts — the knowledge index's search: cheapest tier first.
3
+ *
4
+ * 1. exact — the folded `keys` map; a hit scores 1.0, and when the exact hits
5
+ * fill `k` nothing else runs;
6
+ * 2. lexical — BM25 over card text with the code-aware tokenizer;
7
+ * 3. dense — int8 graph search for `k × rerankFactor` candidates (plus the
8
+ * cards not yet compacted), then a float rerank over vectors
9
+ * recomputed through the hash-keyed LRU;
10
+ * 4. fuse — RRF over the lexical and dense lists; exact hits stay on top at
11
+ * 1.0; everything in {@link compareHits} order.
12
+ *
13
+ * Dense runs only with an embedder of the stored fingerprint — otherwise the tier
14
+ * is absent, never silently replaced.
15
+ */
16
+ import { reciprocalRankFusion } from '../fusion.js';
17
+ import { compareDenseHits, compareHits } from '../order.js';
18
+ import { cosineSimilarity } from '../../similarity/index.js';
19
+ import { availableTiers, graphNode } from './state.js';
20
+ import { dotInt8, quantize } from './quantize.js';
21
+ import { searchGraph } from './traverse.js';
22
+ import { foldKey } from './tokenize.js';
23
+ /** Exact-tier ids for `q`, ascending. */
24
+ function exactIds(state, q) {
25
+ const ids = state.keys.get(foldKey(q));
26
+ return ids ? [...ids].sort() : [];
27
+ }
28
+ /**
29
+ * Dense candidates before the float rerank: the best `n` live graph nodes by
30
+ * integer dot product, plus the best `n` cards not yet in the graph. Ids, unordered
31
+ * between the two sources (the rerank orders them).
32
+ */
33
+ export async function denseCandidates(ctx, qv, n) {
34
+ const { state, cache } = ctx;
35
+ const out = new Set();
36
+ const c = state.compacted;
37
+ if (c && state.scale > 0) {
38
+ const qc = quantize(qv, state.scale);
39
+ const recomputed = new Map();
40
+ const codeOf = (node) => c.codes[node] ?? recomputed.get(node);
41
+ const found = await searchGraph(c.graph, {
42
+ score: (node) => {
43
+ const code = codeOf(node);
44
+ return code ? dotInt8(qc, code) : -Infinity;
45
+ },
46
+ ensure: cache && state.params.lean ? (nodes) => {
47
+ const live = nodes.filter((node) => !codeOf(node) && graphNode(state, c.ids[node]) === node);
48
+ if (live.length === 0)
49
+ return undefined;
50
+ return cache.vectors(live.map((node) => state.docs.get(c.ids[node]))).then((vecs) => {
51
+ live.forEach((node, i) => recomputed.set(node, quantize(vecs[i], state.scale)));
52
+ });
53
+ } : undefined,
54
+ }, Math.max(state.params.efSearch, n));
55
+ for (const hit of found) {
56
+ if (out.size >= n)
57
+ break;
58
+ if (hit.score !== -Infinity && graphNode(state, c.ids[hit.node]) === hit.node)
59
+ out.add(c.ids[hit.node]);
60
+ }
61
+ }
62
+ const pending = [];
63
+ for (const doc of state.docs.values()) {
64
+ if (doc.vec && graphNode(state, doc.id) < 0)
65
+ pending.push({ id: doc.id, score: cosineSimilarity(qv, doc.vec) });
66
+ }
67
+ for (const hit of pending.sort(compareDenseHits).slice(0, n))
68
+ out.add(hit.id);
69
+ return [...out];
70
+ }
71
+ /** The dense tier: candidates, then float recompute + rerank, best first. */
72
+ async function denseRank(ctx, q, n) {
73
+ const cache = ctx.cache;
74
+ const qv = await cache.query(q);
75
+ const ids = await denseCandidates(ctx, qv, n);
76
+ const docs = ids.map((id) => ctx.state.docs.get(id));
77
+ const needVec = docs.filter((d) => !d.vec);
78
+ const fresh = await cache.vectors(needVec);
79
+ const vecOf = new Map(needVec.map((d, i) => [d, fresh[i]]));
80
+ return docs
81
+ .map((d) => ({ id: d.id, score: cosineSimilarity(qv, d.vec ?? vecOf.get(d)) }))
82
+ .sort(compareDenseHits)
83
+ .slice(0, n);
84
+ }
85
+ /** Runs the cascade. A pure function of the state (its digest), `q` and `opts`. */
86
+ export async function cascadeSearch(ctx, q, opts = {}) {
87
+ const { state } = ctx;
88
+ const k = Math.max(0, opts.k ?? 10);
89
+ if (k === 0 || state.docs.size === 0)
90
+ return [];
91
+ const available = availableTiers(state, ctx.embedder);
92
+ const run = new Set((opts.tiers ?? available).filter((t) => available.includes(t)));
93
+ const exact = run.has('exact')
94
+ ? exactIds(state, q).map((id) => ({ id, score: 1, tier: 'exact' }))
95
+ : [];
96
+ if (exact.length >= k)
97
+ return exact.slice(0, k);
98
+ const exactSet = new Set(exact.map((h) => h.id));
99
+ const n = Math.max(k, k * state.params.rerankFactor);
100
+ const lexical = run.has('lexical')
101
+ ? state.lexical.search(q, n + exact.length).filter((h) => !exactSet.has(h.id)).map((h) => h.id)
102
+ : [];
103
+ const dense = run.has('dense')
104
+ ? (await denseRank(ctx, q, n + exact.length)).filter((h) => !exactSet.has(h.id)).map((h) => h.id)
105
+ : [];
106
+ const lexicalSet = new Set(lexical);
107
+ const fused = reciprocalRankFusion([{ ids: lexical }, { ids: dense }].filter((l) => l.ids.length > 0), state.params.rrfK)
108
+ .map((h) => ({ id: h.id, score: h.score, tier: lexicalSet.has(h.id) ? 'lexical' : 'dense' }));
109
+ return [...exact, ...fused].sort(compareHits).slice(0, k);
110
+ }
111
+ //# sourceMappingURL=cascade.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cascade.js","sourceRoot":"","sources":["../../../src/retrieval/knowledge-index/cascade.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * compact.ts — the canonical rebuild.
3
+ *
4
+ * Every live card, in id order, is coded (an unchanged node keeps its code; a new
5
+ * or changed card is quantized from its float vector) and the graph is rebuilt
6
+ * from those codes. Since levels come from id hashes, inserts are id-ordered and
7
+ * every tie breaks on id, the same card set and fingerprint give the same bytes
8
+ * whatever order the upserts arrived in.
9
+ *
10
+ * The int8 scale is fitted at the first compaction and fixed after it. An embedder
11
+ * whose fingerprint differs from the stored one is never mixed in: compaction
12
+ * drops every stored vector and code and re-embeds all cards under it.
13
+ */
14
+ import type { EmbedderPort } from './types.js';
15
+ import { type IndexState } from './state.js';
16
+ import type { EmbeddingCache } from './embeddings.js';
17
+ export declare function compactState(state: IndexState, embedder: EmbedderPort | undefined, cache: EmbeddingCache | undefined): Promise<void>;
18
+ //# sourceMappingURL=compact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compact.d.ts","sourceRoot":"","sources":["../../../src/retrieval/knowledge-index/compact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAA4B,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAUtD,wBAAsB,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,GAAG,SAAS,EAAE,KAAK,EAAE,cAAc,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAwC1I"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * compact.ts — the canonical rebuild.
3
+ *
4
+ * Every live card, in id order, is coded (an unchanged node keeps its code; a new
5
+ * or changed card is quantized from its float vector) and the graph is rebuilt
6
+ * from those codes. Since levels come from id hashes, inserts are id-ordered and
7
+ * every tie breaks on id, the same card set and fingerprint give the same bytes
8
+ * whatever order the upserts arrived in.
9
+ *
10
+ * The int8 scale is fitted at the first compaction and fixed after it. An embedder
11
+ * whose fingerprint differs from the stored one is never mixed in: compaction
12
+ * drops every stored vector and code and re-embeds all cards under it.
13
+ */
14
+ import { compareIds } from '../order.js';
15
+ import { graphNode } from './state.js';
16
+ import { fitScale, quantize } from './quantize.js';
17
+ import { buildGraph } from './csr.js';
18
+ /** Float vectors for the docs that have neither a reusable code nor a pending vector. */
19
+ async function vectorsFor(cache, docs) {
20
+ const vecs = await cache.vectors(docs);
21
+ return new Map(docs.map((d, i) => [d.id, vecs[i]]));
22
+ }
23
+ export async function compactState(state, embedder, cache) {
24
+ // Nothing to code with: exact and lexical need no compaction, and a stored
25
+ // graph of another fingerprint is kept for an embedder that matches it.
26
+ if (!embedder || !cache)
27
+ return;
28
+ if (embedder.fingerprint !== state.fingerprint || embedder.dims !== state.dims) {
29
+ state.fingerprint = embedder.fingerprint;
30
+ state.dims = embedder.dims;
31
+ state.scale = 0;
32
+ state.compacted = null;
33
+ for (const doc of state.docs.values())
34
+ doc.vec = undefined;
35
+ }
36
+ const ids = [...state.docs.keys()].sort(compareIds);
37
+ const docs = ids.map((id) => state.docs.get(id));
38
+ if (docs.length === 0) {
39
+ state.compacted = null;
40
+ return;
41
+ }
42
+ const old = state.compacted;
43
+ const reused = docs.map((d) => {
44
+ const node = graphNode(state, d.id);
45
+ return node >= 0 && state.scale > 0 ? old.codes[node] : undefined;
46
+ });
47
+ const missing = await vectorsFor(cache, docs.filter((d, i) => !reused[i] && !d.vec));
48
+ const floatOf = (d) => d.vec ?? missing.get(d.id);
49
+ if (state.scale === 0)
50
+ state.scale = fitScale(docs.map(floatOf));
51
+ const codes = docs.map((d, i) => reused[i] ?? quantize(floatOf(d), state.scale));
52
+ const { graph, hubs } = buildGraph(ids, codes, state.params);
53
+ state.compacted = {
54
+ ids,
55
+ hashes: docs.map((d) => d.hash),
56
+ codes: state.params.lean ? codes.map((code, i) => (hubs[i] ? code : undefined)) : codes,
57
+ hubs,
58
+ graph,
59
+ nodeOf: new Map(ids.map((id, i) => [id, i])),
60
+ };
61
+ for (const doc of docs)
62
+ doc.vec = undefined;
63
+ }
64
+ //# sourceMappingURL=compact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compact.js","sourceRoot":"","sources":["../../../src/retrieval/knowledge-index/compact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * csr.ts — the knowledge index's graph, stored as CSR (compressed sparse rows).
3
+ *
4
+ * The graph is built by the package's HNSW over int8 codes (canonical, id-ordered
5
+ * inserts, hash-derived levels), its base layer is pruned (`prune.ts`), and every
6
+ * layer is flattened into a `Uint32Array` of offsets plus a `Uint32Array` of
7
+ * neighbours: no per-node arrays, a fixed byte layout to serialize and hash.
8
+ *
9
+ * Layer 0 holds every node and is indexed by node directly. An upper layer holds
10
+ * only the nodes that reach it, listed ascending in `nodes`.
11
+ */
12
+ import type { IndexParams } from './types.js';
13
+ export interface CsrLayer {
14
+ /** Upper layers: the node indices present, ascending. Absent on layer 0 (every node). */
15
+ nodes?: Uint32Array;
16
+ /** Row `r`'s neighbours are `neighbours[offsets[r] .. offsets[r + 1])`. */
17
+ offsets: Uint32Array;
18
+ neighbours: Uint32Array;
19
+ }
20
+ export interface CsrGraph {
21
+ /** Entry node for search; -1 for an empty graph. */
22
+ entry: number;
23
+ /** layers[0] is the base layer; layers.length - 1 is the top layer. */
24
+ layers: CsrLayer[];
25
+ }
26
+ export declare const EMPTY_GRAPH: CsrGraph;
27
+ /** Flattens per-row neighbour lists into one CSR layer. */
28
+ export declare function toCsrLayer(rows: ReadonlyArray<readonly number[]>, nodes?: Uint32Array): CsrLayer;
29
+ /** Neighbours of `node` on `layer` (empty when the node is not on it). */
30
+ export declare function neighboursOf(layer: CsrLayer, node: number): Uint32Array;
31
+ /**
32
+ * Builds the pruned CSR graph over `codes`, whose order is the id order of `ids`
33
+ * (already sorted and unique). Distances are cosine over the int8 codes, which is
34
+ * exact integer arithmetic plus correctly-rounded sqrt/division — so the same codes
35
+ * give the same graph on every platform.
36
+ */
37
+ export declare function buildGraph(ids: readonly string[], codes: readonly Int8Array[], params: IndexParams): {
38
+ graph: CsrGraph;
39
+ hubs: Uint8Array;
40
+ };
41
+ //# sourceMappingURL=csr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csr.d.ts","sourceRoot":"","sources":["../../../src/retrieval/knowledge-index/csr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAI9C,MAAM,WAAW,QAAQ;IACrB,yFAAyF;IACzF,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,2EAA2E;IAC3E,OAAO,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,WAAW,CAAC;CAC3B;AAED,MAAM,WAAW,QAAQ;IACrB,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,MAAM,EAAE,QAAQ,EAAE,CAAC;CACtB;AAED,eAAO,MAAM,WAAW,EAAE,QAA+D,CAAC;AAE1F,2DAA2D;AAC3D,wBAAgB,UAAU,CAAC,IAAI,EAAE,aAAa,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,QAAQ,CAUhG;AAiBD,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAIvE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CACtB,GAAG,EAAE,SAAS,MAAM,EAAE,EACtB,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,MAAM,EAAE,WAAW,GACpB;IAAE,KAAK,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAsBvC"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * csr.ts — the knowledge index's graph, stored as CSR (compressed sparse rows).
3
+ *
4
+ * The graph is built by the package's HNSW over int8 codes (canonical, id-ordered
5
+ * inserts, hash-derived levels), its base layer is pruned (`prune.ts`), and every
6
+ * layer is flattened into a `Uint32Array` of offsets plus a `Uint32Array` of
7
+ * neighbours: no per-node arrays, a fixed byte layout to serialize and hash.
8
+ *
9
+ * Layer 0 holds every node and is indexed by node directly. An upper layer holds
10
+ * only the nodes that reach it, listed ascending in `nodes`.
11
+ */
12
+ import { HnswIndex } from '../hnsw.js';
13
+ import { pruneBaseLayer } from './prune.js';
14
+ import { cosineInt8 } from './quantize.js';
15
+ export const EMPTY_GRAPH = Object.freeze({ entry: -1, layers: [] });
16
+ /** Flattens per-row neighbour lists into one CSR layer. */
17
+ export function toCsrLayer(rows, nodes) {
18
+ const offsets = new Uint32Array(rows.length + 1);
19
+ let total = 0;
20
+ rows.forEach((row, r) => {
21
+ total += row.length;
22
+ offsets[r + 1] = total;
23
+ });
24
+ const neighbours = new Uint32Array(total);
25
+ rows.forEach((row, r) => neighbours.set(row, offsets[r]));
26
+ return nodes ? { nodes, offsets, neighbours } : { offsets, neighbours };
27
+ }
28
+ /** The row of `node` in `layer`, or -1 when the node is not on it. */
29
+ function rowOf(layer, node) {
30
+ if (!layer.nodes)
31
+ return node < layer.offsets.length - 1 ? node : -1;
32
+ let lo = 0;
33
+ let hi = layer.nodes.length - 1;
34
+ while (lo <= hi) {
35
+ const mid = (lo + hi) >>> 1;
36
+ const v = layer.nodes[mid];
37
+ if (v === node)
38
+ return mid;
39
+ if (v < node)
40
+ lo = mid + 1;
41
+ else
42
+ hi = mid - 1;
43
+ }
44
+ return -1;
45
+ }
46
+ /** Neighbours of `node` on `layer` (empty when the node is not on it). */
47
+ export function neighboursOf(layer, node) {
48
+ const r = rowOf(layer, node);
49
+ if (r < 0)
50
+ return layer.neighbours.subarray(0, 0);
51
+ return layer.neighbours.subarray(layer.offsets[r], layer.offsets[r + 1]);
52
+ }
53
+ /**
54
+ * Builds the pruned CSR graph over `codes`, whose order is the id order of `ids`
55
+ * (already sorted and unique). Distances are cosine over the int8 codes, which is
56
+ * exact integer arithmetic plus correctly-rounded sqrt/division — so the same codes
57
+ * give the same graph on every platform.
58
+ */
59
+ export function buildGraph(ids, codes, params) {
60
+ if (ids.length === 0)
61
+ return { graph: EMPTY_GRAPH, hubs: new Uint8Array(0) };
62
+ const hnsw = HnswIndex.canonicalBuild(ids.map((id, i) => ({ id, vector: codes[i] })), { M: params.m, efConstruction: params.efConstruction, efSearch: params.efSearch });
63
+ const view = hnsw.graph();
64
+ const { rows, hubs } = pruneBaseLayer(view.neighbours.map((layers) => layers[0] ?? []), params.m, params.hubShare, (a, b) => cosineInt8(codes[a], codes[b]));
65
+ const layers = [toCsrLayer(rows)];
66
+ for (let l = 1; l <= view.maxLayer; l++) {
67
+ const present = [];
68
+ view.neighbours.forEach((layersOfNode, node) => {
69
+ if (layersOfNode.length > l)
70
+ present.push(node);
71
+ });
72
+ layers.push(toCsrLayer(present.map((node) => view.neighbours[node][l]), Uint32Array.from(present)));
73
+ }
74
+ return { graph: { entry: view.entry, layers }, hubs };
75
+ }
76
+ //# sourceMappingURL=csr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csr.js","sourceRoot":"","sources":["../../../src/retrieval/knowledge-index/csr.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * digest.ts — the name of an index state.
3
+ *
4
+ * sha-256 over the canonical encoding of everything a result depends on: the
5
+ * fingerprint, dims, params and int8 scale; every live card's (id, hash, keys) in
6
+ * id order; and the compacted snapshot (node ids and hashes, hubs, the CSR graph).
7
+ * Every search result is a pure function of `(digest, query, opts)`, which is what
8
+ * lets a logged digest replay a disputed answer.
9
+ */
10
+ import type { IndexParams } from './types.js';
11
+ import type { IndexState } from './state.js';
12
+ import type { CsrGraph } from './csr.js';
13
+ import { ByteWriter } from './bytes.js';
14
+ /** The default content hash of a card's text. */
15
+ export declare function hashDocText(text: string): string;
16
+ /** Params in a fixed field order, for the digest and the serialized header. */
17
+ export declare function writeParams(w: ByteWriter, p: IndexParams): void;
18
+ /** The graph's layers: entry, then per layer its node list, offsets and neighbours. */
19
+ export declare function writeGraph(w: ByteWriter, g: CsrGraph): void;
20
+ export declare function stateDigest(state: IndexState): string;
21
+ //# sourceMappingURL=digest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["../../../src/retrieval/knowledge-index/digest.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGxC,iDAAiD;AACjD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,WAAW,GAAG,IAAI,CAE/D;AAED,uFAAuF;AACvF,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,CAG3D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAoBrD"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * digest.ts — the name of an index state.
3
+ *
4
+ * sha-256 over the canonical encoding of everything a result depends on: the
5
+ * fingerprint, dims, params and int8 scale; every live card's (id, hash, keys) in
6
+ * id order; and the compacted snapshot (node ids and hashes, hubs, the CSR graph).
7
+ * Every search result is a pure function of `(digest, query, opts)`, which is what
8
+ * lets a logged digest replay a disputed answer.
9
+ */
10
+ import { compareIds } from '../order.js';
11
+ import { ByteWriter } from './bytes.js';
12
+ import { sha256Hex } from './sha256.js';
13
+ /** The default content hash of a card's text. */
14
+ export function hashDocText(text) {
15
+ return sha256Hex(text);
16
+ }
17
+ /** Params in a fixed field order, for the digest and the serialized header. */
18
+ export function writeParams(w, p) {
19
+ w.u32(p.m).u32(p.efConstruction).u32(p.efSearch).f64(p.hubShare).u32(p.rerankFactor).u8(p.lean ? 1 : 0).u32(p.rrfK);
20
+ }
21
+ /** The graph's layers: entry, then per layer its node list, offsets and neighbours. */
22
+ export function writeGraph(w, g) {
23
+ w.i32(g.entry).u32(g.layers.length);
24
+ for (const layer of g.layers)
25
+ w.u32s(layer.nodes ?? []).u32s(layer.offsets).u32s(layer.neighbours);
26
+ }
27
+ export function stateDigest(state) {
28
+ const w = new ByteWriter();
29
+ w.str('bf-knowledge-index/digest/1').str(state.fingerprint).u32(state.dims).f64(state.scale);
30
+ writeParams(w, state.params);
31
+ const ids = [...state.docs.keys()].sort(compareIds);
32
+ w.u32(ids.length);
33
+ for (const id of ids) {
34
+ const doc = state.docs.get(id);
35
+ w.str(id).str(doc.hash).u32(doc.keys.length);
36
+ for (const key of doc.keys)
37
+ w.str(key);
38
+ }
39
+ const c = state.compacted;
40
+ w.u8(c ? 1 : 0);
41
+ if (c) {
42
+ w.u32(c.ids.length);
43
+ for (let i = 0; i < c.ids.length; i++)
44
+ w.str(c.ids[i]).str(c.hashes[i]);
45
+ w.bytes(c.hubs);
46
+ writeGraph(w, c.graph);
47
+ }
48
+ return sha256Hex(w.finish());
49
+ }
50
+ //# sourceMappingURL=digest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"digest.js","sourceRoot":"","sources":["../../../src/retrieval/knowledge-index/digest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * embeddings.ts — the index's recompute path: card text → unit float vector,
3
+ * through a bounded LRU keyed by the card's content hash.
4
+ *
5
+ * LEANN's point is that most vectors need not be stored: the dense tier
6
+ * recomputes float vectors only for the handful of candidates it reranks, and
7
+ * lean mode recomputes the codes it dropped. Keying by hash means an unchanged
8
+ * card is never re-embedded while it stays warm, and a changed one never serves
9
+ * a stale vector.
10
+ */
11
+ import type { EmbedderPort } from './types.js';
12
+ /** Default number of vectors held. */
13
+ export declare const EMBEDDING_CACHE_MAX = 8192;
14
+ /** Texts per `embed` call. */
15
+ export declare const EMBED_BATCH = 256;
16
+ export interface Embeddable {
17
+ hash: string;
18
+ text: string;
19
+ }
20
+ export declare class EmbeddingCache {
21
+ private readonly _embedder;
22
+ private readonly _max;
23
+ private readonly _lru;
24
+ constructor(_embedder: EmbedderPort, _max?: number);
25
+ /** Unit vectors for `items`, in order. Misses are embedded in batches of {@link EMBED_BATCH}. */
26
+ vectors(items: readonly Embeddable[]): Promise<Float32Array[]>;
27
+ /** A query (not a card) vector: not cached, the query space is unbounded. */
28
+ query(text: string): Promise<Float32Array>;
29
+ private _touch;
30
+ private _put;
31
+ }
32
+ //# sourceMappingURL=embeddings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../../../src/retrieval/knowledge-index/embeddings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,sCAAsC;AACtC,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,8BAA8B;AAC9B,eAAO,MAAM,WAAW,MAAM,CAAC;AAE/B,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,cAAc;IAInB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJzB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmC;gBAGnC,SAAS,EAAE,YAAY,EACvB,IAAI,GAAE,MAA4B;IAGvD,iGAAiG;IAC3F,OAAO,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IA2BpE,6EAA6E;IACvE,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAMhD,OAAO,CAAC,MAAM;IASd,OAAO,CAAC,IAAI;CAQf"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * embeddings.ts — the index's recompute path: card text → unit float vector,
3
+ * through a bounded LRU keyed by the card's content hash.
4
+ *
5
+ * LEANN's point is that most vectors need not be stored: the dense tier
6
+ * recomputes float vectors only for the handful of candidates it reranks, and
7
+ * lean mode recomputes the codes it dropped. Keying by hash means an unchanged
8
+ * card is never re-embedded while it stays warm, and a changed one never serves
9
+ * a stale vector.
10
+ */
11
+ import { toUnit } from './quantize.js';
12
+ /** Default number of vectors held. */
13
+ export const EMBEDDING_CACHE_MAX = 8192;
14
+ /** Texts per `embed` call. */
15
+ export const EMBED_BATCH = 256;
16
+ export class EmbeddingCache {
17
+ _embedder;
18
+ _max;
19
+ _lru = new Map();
20
+ constructor(_embedder, _max = EMBEDDING_CACHE_MAX) {
21
+ this._embedder = _embedder;
22
+ this._max = _max;
23
+ }
24
+ /** Unit vectors for `items`, in order. Misses are embedded in batches of {@link EMBED_BATCH}. */
25
+ async vectors(items) {
26
+ const out = items.map((it) => this._touch(it.hash));
27
+ const missing = [];
28
+ const seen = new Map();
29
+ items.forEach((it, i) => {
30
+ if (out[i] || seen.has(it.hash))
31
+ return;
32
+ seen.set(it.hash, missing.length);
33
+ missing.push(i);
34
+ });
35
+ if (missing.length > 0) {
36
+ const raw = [];
37
+ for (let start = 0; start < missing.length; start += EMBED_BATCH) {
38
+ const batch = missing.slice(start, start + EMBED_BATCH).map((i) => items[i].text);
39
+ raw.push(...(await this._embedder.embed(batch)));
40
+ }
41
+ missing.forEach((i, j) => {
42
+ const vec = raw[j];
43
+ if (!vec)
44
+ throw new Error('knowledge-index: embedder returned fewer vectors than texts');
45
+ this._put(items[i].hash, toUnit(vec));
46
+ });
47
+ items.forEach((it, i) => {
48
+ if (!out[i])
49
+ out[i] = this._touch(it.hash) ?? toUnit(raw[seen.get(it.hash)]);
50
+ });
51
+ }
52
+ return out;
53
+ }
54
+ /** A query (not a card) vector: not cached, the query space is unbounded. */
55
+ async query(text) {
56
+ const [vec] = await this._embedder.embed([text]);
57
+ if (!vec)
58
+ throw new Error('knowledge-index: embedder returned no vector for the query');
59
+ return toUnit(vec);
60
+ }
61
+ _touch(hash) {
62
+ const hit = this._lru.get(hash);
63
+ if (hit) {
64
+ this._lru.delete(hash);
65
+ this._lru.set(hash, hit);
66
+ }
67
+ return hit;
68
+ }
69
+ _put(hash, vec) {
70
+ this._lru.delete(hash);
71
+ this._lru.set(hash, vec);
72
+ while (this._lru.size > this._max) {
73
+ const oldest = this._lru.keys().next().value;
74
+ this._lru.delete(oldest);
75
+ }
76
+ }
77
+ }
78
+ //# sourceMappingURL=embeddings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../../../src/retrieval/knowledge-index/embeddings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * expand.ts — recall expansion over the knowledge graph's edges.
3
+ *
4
+ * A hit alone is an isolated fact; its neighbours make it knowledge (a claim's
5
+ * source section, the claims contradicting it, the entity it is about). Each hop
6
+ * scores `parent score × edge weight × 0.5`; a node reached more than one way keeps
7
+ * its best score; the original hits keep theirs. The result is re-ordered by
8
+ * {@link compareHits}, so it is deterministic whatever order the graph lists
9
+ * neighbours in.
10
+ */
11
+ import type { GraphNeighbours, IndexHit } from './types.js';
12
+ /** The per-hop decay. */
13
+ export declare const EXPAND_HOP_DECAY = 0.5;
14
+ export interface ExpandOptions {
15
+ hops?: 1 | 2;
16
+ edgeKinds?: string[];
17
+ }
18
+ export declare function expandHits(hits: readonly IndexHit[], graph: GraphNeighbours, opts?: ExpandOptions): IndexHit[];
19
+ //# sourceMappingURL=expand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expand.d.ts","sourceRoot":"","sources":["../../../src/retrieval/knowledge-index/expand.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE5D,yBAAyB;AACzB,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC,MAAM,WAAW,aAAa;IAC1B,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,QAAQ,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,GAAE,aAAkB,GAAG,QAAQ,EAAE,CAgClH"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * expand.ts — recall expansion over the knowledge graph's edges.
3
+ *
4
+ * A hit alone is an isolated fact; its neighbours make it knowledge (a claim's
5
+ * source section, the claims contradicting it, the entity it is about). Each hop
6
+ * scores `parent score × edge weight × 0.5`; a node reached more than one way keeps
7
+ * its best score; the original hits keep theirs. The result is re-ordered by
8
+ * {@link compareHits}, so it is deterministic whatever order the graph lists
9
+ * neighbours in.
10
+ */
11
+ import { compareHits } from '../order.js';
12
+ /** The per-hop decay. */
13
+ export const EXPAND_HOP_DECAY = 0.5;
14
+ export function expandHits(hits, graph, opts = {}) {
15
+ const hops = opts.hops ?? 1;
16
+ const best = new Map();
17
+ for (const hit of [...hits].sort(compareHits)) {
18
+ const prev = best.get(hit.id);
19
+ if (!prev || hit.score > prev.score)
20
+ best.set(hit.id, { ...hit });
21
+ }
22
+ const original = new Set(best.keys());
23
+ let frontier = [...best.values()];
24
+ for (let hop = 0; hop < hops; hop++) {
25
+ const reached = new Map();
26
+ // Parents in total order, and a strict `>` to replace: equal-score ties keep
27
+ // the first parent in that order, independent of the graph's listing order.
28
+ for (const parent of frontier.sort(compareHits)) {
29
+ for (const edge of graph.neighbours(parent.id, opts.edgeKinds)) {
30
+ if (original.has(edge.id))
31
+ continue;
32
+ const score = parent.score * edge.weight * EXPAND_HOP_DECAY;
33
+ const prev = reached.get(edge.id);
34
+ if (!prev || score > prev.score)
35
+ reached.set(edge.id, { id: edge.id, score, tier: parent.tier });
36
+ }
37
+ }
38
+ frontier = [];
39
+ for (const [id, hit] of reached) {
40
+ const prev = best.get(id);
41
+ if (!prev || hit.score > prev.score) {
42
+ best.set(id, hit);
43
+ frontier.push(hit);
44
+ }
45
+ }
46
+ }
47
+ return [...best.values()].sort(compareHits);
48
+ }
49
+ //# sourceMappingURL=expand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expand.js","sourceRoot":"","sources":["../../../src/retrieval/knowledge-index/expand.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,yBAAyB;AACzB,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAOpC,MAAM,UAAU,UAAU,CAAC,IAAyB,EAAE,KAAsB,EAAE,OAAsB,EAAE;IAClG,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;IAC5B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAoB,CAAC;IACzC,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAEtC,IAAI,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAClC,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAoB,CAAC;QAC5C,6EAA6E;QAC7E,4EAA4E;QAC5E,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YAC9C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC7D,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBAAE,SAAS;gBACpC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,GAAG,gBAAgB,CAAC;gBAC5D,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAClC,IAAI,CAAC,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK;oBAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YACrG,CAAC;QACL,CAAC;QACD,QAAQ,GAAG,EAAE,CAAC;QACd,KAAK,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,OAAO,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC1B,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;gBAClC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;gBAClB,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACvB,CAAC;QACL,CAAC;IACL,CAAC;IACD,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AAChD,CAAC"}