@wrongstack/vector-memory 1.0.0 → 1.0.2

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 (2) hide show
  1. package/dist/index.js +19 -14
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -565,7 +565,7 @@ var VectorMemoryStore = class _VectorMemoryStore {
565
565
  const vec = decodeVector(row.vec_blob);
566
566
  const raw = cosineSimilarity(queryVec, vec);
567
567
  const score = Math.max(0, Math.min(1, raw));
568
- if (score < threshold) continue;
568
+ if (!Number.isFinite(score) || score < threshold) continue;
569
569
  if (top.length >= limit && score <= (top[top.length - 1]?.score ?? 0)) continue;
570
570
  let at = top.length;
571
571
  while (at > 0 && (top[at - 1]?.score ?? 0) < score) at--;
@@ -1231,12 +1231,14 @@ async function fuseWithVectorMemory(query, lexical, options = {}) {
1231
1231
  lexicalScore: lexicalRankScore(index, lexical.length)
1232
1232
  }));
1233
1233
  const vectorRanked = [];
1234
+ const seenVectorSageIds = /* @__PURE__ */ new Set();
1234
1235
  for (let i = 0; i < vectorHits.length; i++) {
1235
1236
  const hit = vectorHits[i];
1236
1237
  const sageId = hit.entry.metadata?.["sageId"];
1237
- if (typeof sageId !== "string") continue;
1238
+ if (typeof sageId !== "string" || seenVectorSageIds.has(sageId)) continue;
1238
1239
  const memory = sageById.get(sageId);
1239
1240
  if (!memory) continue;
1241
+ seenVectorSageIds.add(sageId);
1240
1242
  vectorRanked.push({ memory, vectorScore: hit.score });
1241
1243
  }
1242
1244
  const fused = /* @__PURE__ */ new Map();
@@ -1586,12 +1588,16 @@ async function runSearchRace(query, lexical, vectorStore, options = {}) {
1586
1588
  preview: previewText(mem.text, 140)
1587
1589
  });
1588
1590
  }
1591
+ const overlapById = /* @__PURE__ */ new Map();
1592
+ for (const row of overlap) overlapById.set(row.id, row);
1589
1593
  for (const hit of vectorHits) {
1590
1594
  const sageId = hit.entry.metadata?.["sageId"];
1591
1595
  if (typeof sageId !== "string") continue;
1592
- const existing = overlap.find((row) => row.id === sageId);
1596
+ const existing = overlapById.get(sageId);
1593
1597
  if (existing) {
1594
- existing.vectorScore = hit.score;
1598
+ if (existing.vectorScore === null) {
1599
+ existing.vectorScore = hit.score;
1600
+ }
1595
1601
  continue;
1596
1602
  }
1597
1603
  if (seenIds.has(sageId)) continue;
@@ -1603,8 +1609,8 @@ async function runSearchRace(query, lexical, vectorStore, options = {}) {
1603
1609
  preview: previewText(hit.entry.text, 140)
1604
1610
  });
1605
1611
  }
1606
- for (let i = overlap.length - 1; i >= 0; i--) {
1607
- const row = overlap[i];
1612
+ const finalOverlap = [];
1613
+ for (const row of overlap) {
1608
1614
  if (row.vectorScore === null) {
1609
1615
  lexicalOnly.push({
1610
1616
  id: row.id,
@@ -1612,26 +1618,25 @@ async function runSearchRace(query, lexical, vectorStore, options = {}) {
1612
1618
  vectorScore: null,
1613
1619
  preview: row.preview
1614
1620
  });
1615
- overlap.splice(i, 1);
1621
+ } else {
1622
+ finalOverlap.push(row);
1616
1623
  }
1617
1624
  }
1618
- const lexicalCount = lexicalOnly.length + overlap.length;
1619
- const vectorCount = vectorOnly.length + overlap.length;
1625
+ const lexicalCount = lexicalOnly.length + finalOverlap.length;
1626
+ const vectorCount = vectorOnly.length + finalOverlap.length;
1620
1627
  const denom = Math.max(lexicalCount, vectorCount, 1);
1621
1628
  return {
1622
1629
  query,
1623
1630
  lexicalOnly,
1624
1631
  vectorOnly,
1625
- // The sweep above removed every row still carrying a null vectorScore,
1626
- // so every remaining row holds a real number here.
1627
- overlap,
1632
+ overlap: finalOverlap,
1628
1633
  metrics: {
1629
1634
  lexicalCount,
1630
1635
  vectorCount,
1631
- overlapCount: overlap.length,
1636
+ overlapCount: finalOverlap.length,
1632
1637
  lexicalOnlyRatio: lexicalCount === 0 ? 0 : lexicalOnly.length / lexicalCount,
1633
1638
  vectorOnlyRatio: vectorCount === 0 ? 0 : vectorOnly.length / vectorCount,
1634
- agreementRatio: overlap.length / denom
1639
+ agreementRatio: finalOverlap.length / denom
1635
1640
  }
1636
1641
  };
1637
1642
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/vector-memory",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "license": "MIT",
5
5
  "description": "WrongStack Vector Memory — an additional vector-search memory store powered by @huggingface/transformers (local ONNX embeddings), alongside the SAGE lexical memory system.",
6
6
  "repository": {
@@ -27,9 +27,9 @@
27
27
  "README.md"
28
28
  ],
29
29
  "dependencies": {
30
- "@wrongstack/core": "1.0.0",
31
- "@wrongstack/persistence": "1.0.0",
32
- "@wrongstack/sage": "1.0.0"
30
+ "@wrongstack/core": "1.0.2",
31
+ "@wrongstack/persistence": "1.0.2",
32
+ "@wrongstack/sage": "1.0.2"
33
33
  },
34
34
  "optionalDependencies": {
35
35
  "@huggingface/transformers": "^4.2.0"