@remnic/core 9.3.594 → 9.3.595

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/dist/index.js CHANGED
@@ -182,7 +182,7 @@ import {
182
182
  saveTaxonomy,
183
183
  validateSlug,
184
184
  validateTaxonomy
185
- } from "./chunk-7WU3FML2.js";
185
+ } from "./chunk-JIBCUYIP.js";
186
186
  import "./chunk-5RIRL3XL.js";
187
187
  import {
188
188
  migrateFromEngram,
@@ -26,7 +26,7 @@ import {
26
26
  sanitizeSessionKeyForFilename,
27
27
  shouldFilterLifecycleRecallCandidate,
28
28
  summarizeGraphShadowComparison
29
- } from "./chunk-7WU3FML2.js";
29
+ } from "./chunk-JIBCUYIP.js";
30
30
  import "./chunk-5RIRL3XL.js";
31
31
  import "./chunk-KVEVLBKC.js";
32
32
  import "./chunk-BFBF3XEF.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remnic/core",
3
- "version": "9.3.594",
3
+ "version": "9.3.595",
4
4
  "description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -134,6 +134,38 @@ test("semantic dedup: ignores non-finite scores", async () => {
134
134
  }
135
135
  });
136
136
 
137
+ test("semantic dedup: ignores malformed hits without a usable memory id", async () => {
138
+ const decision = await decideSemanticDedup(
139
+ "content",
140
+ makeLookup([
141
+ { id: "", score: 0.99 },
142
+ { id: " ", score: 0.98 },
143
+ { id: 42, score: 0.97 } as unknown as SemanticDedupHit,
144
+ { id: "valid-hit", score: 0.93 },
145
+ ]),
146
+ DEFAULT_OPTS,
147
+ );
148
+
149
+ assert.equal(decision.action, "skip");
150
+ if (decision.action === "skip") {
151
+ assert.equal(decision.reason, "near_duplicate");
152
+ assert.equal(decision.topId, "valid-hit");
153
+ assert.equal(decision.topScore, 0.93);
154
+ }
155
+
156
+ const allMalformed = await decideSemanticDedup(
157
+ "content",
158
+ makeLookup([
159
+ { id: "", score: 0.99 },
160
+ { id: 42, score: 0.98 } as unknown as SemanticDedupHit,
161
+ ]),
162
+ DEFAULT_OPTS,
163
+ );
164
+
165
+ assert.equal(allMalformed.action, "keep");
166
+ assert.equal(allMalformed.reason, "no_near_duplicate");
167
+ });
168
+
137
169
  test("semantic dedup: treats lookup throw as fail-open keep", async () => {
138
170
  const decision = await decideSemanticDedup(
139
171
  "content",
@@ -553,6 +585,7 @@ test("embedding fallback ignores persisted indexes from a different provider or
553
585
  localLlmUrl: "http://127.0.0.1:1234",
554
586
  localLlmModel: "local-embed",
555
587
  embeddingFallbackModel: "local-embed",
588
+ openaiApiKey: false,
556
589
  });
557
590
  const fallback = new EmbeddingFallback(config);
558
591
 
@@ -138,7 +138,13 @@ export async function decideSemanticDedup(
138
138
  // Defensive: callers ought to return sorted, but don't trust it.
139
139
  let top: SemanticDedupHit | undefined;
140
140
  for (const hit of hits) {
141
- if (!hit || typeof hit.score !== "number" || !Number.isFinite(hit.score)) {
141
+ if (
142
+ !hit ||
143
+ typeof hit.id !== "string" ||
144
+ hit.id.trim().length === 0 ||
145
+ typeof hit.score !== "number" ||
146
+ !Number.isFinite(hit.score)
147
+ ) {
142
148
  continue;
143
149
  }
144
150
  if (!top || hit.score > top.score) {