@graphorin/memory 0.5.0 → 0.6.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 +90 -1
- package/README.md +31 -31
- package/dist/conflict/index.d.ts +3 -1
- package/dist/conflict/index.js +1 -1
- package/dist/conflict/locale-packs/en.d.ts +13 -0
- package/dist/conflict/locale-packs/en.d.ts.map +1 -0
- package/dist/conflict/locale-packs/en.js +1 -1
- package/dist/conflict/locale-packs/en.js.map +1 -1
- package/dist/conflict/pipeline.d.ts +2 -2
- package/dist/conflict/pipeline.js +3 -3
- package/dist/conflict/pipeline.js.map +1 -1
- package/dist/conflict/stages/helpers.js +1 -1
- package/dist/conflict/stages/helpers.js.map +1 -1
- package/dist/conflict/stages/stage1-exact-dedup.js.map +1 -1
- package/dist/conflict/stages/stage2-embedding-three-zone.js.map +1 -1
- package/dist/conflict/stages/stage3-heuristic-regex.js +1 -1
- package/dist/conflict/stages/stage3-heuristic-regex.js.map +1 -1
- package/dist/conflict/stages/stage4-subject-predicate.js.map +1 -1
- package/dist/conflict/stages/stage5-defer-to-deep.js.map +1 -1
- package/dist/conflict/types.d.ts +7 -7
- package/dist/conflict/types.js +1 -1
- package/dist/conflict/types.js.map +1 -1
- package/dist/consolidator/budget.js +16 -3
- package/dist/consolidator/budget.js.map +1 -1
- package/dist/consolidator/decay.d.ts +13 -2
- package/dist/consolidator/decay.js +17 -5
- package/dist/consolidator/decay.js.map +1 -1
- package/dist/consolidator/dlq.js +1 -1
- package/dist/consolidator/dlq.js.map +1 -1
- package/dist/consolidator/errors.js +2 -2
- package/dist/consolidator/errors.js.map +1 -1
- package/dist/consolidator/index.js +8 -6
- package/dist/consolidator/index.js.map +1 -1
- package/dist/consolidator/lock.js +1 -1
- package/dist/consolidator/lock.js.map +1 -1
- package/dist/consolidator/noise-filter.js.map +1 -1
- package/dist/consolidator/phases/deep.js +6 -2
- package/dist/consolidator/phases/deep.js.map +1 -1
- package/dist/consolidator/phases/induce.d.ts +10 -10
- package/dist/consolidator/phases/induce.js +6 -6
- package/dist/consolidator/phases/induce.js.map +1 -1
- package/dist/consolidator/phases/learned-context.js +129 -0
- package/dist/consolidator/phases/learned-context.js.map +1 -0
- package/dist/consolidator/phases/light.js +2 -1
- package/dist/consolidator/phases/light.js.map +1 -1
- package/dist/consolidator/phases/reflect.js +5 -4
- package/dist/consolidator/phases/reflect.js.map +1 -1
- package/dist/consolidator/phases/standard.js +37 -8
- package/dist/consolidator/phases/standard.js.map +1 -1
- package/dist/consolidator/reconcile.js +1 -1
- package/dist/consolidator/reconcile.js.map +1 -1
- package/dist/consolidator/runtime.d.ts +4 -4
- package/dist/consolidator/runtime.d.ts.map +1 -1
- package/dist/consolidator/runtime.js +73 -16
- package/dist/consolidator/runtime.js.map +1 -1
- package/dist/consolidator/scheduler.d.ts +5 -5
- package/dist/consolidator/scheduler.js +1 -1
- package/dist/consolidator/scheduler.js.map +1 -1
- package/dist/consolidator/triggers.js +7 -7
- package/dist/consolidator/triggers.js.map +1 -1
- package/dist/consolidator/types.d.ts +68 -20
- package/dist/consolidator/types.d.ts.map +1 -1
- package/dist/consolidator/types.js +16 -6
- package/dist/consolidator/types.js.map +1 -1
- package/dist/context-engine/annotations.d.ts +9 -9
- package/dist/context-engine/annotations.js +3 -3
- package/dist/context-engine/annotations.js.map +1 -1
- package/dist/context-engine/auto-recall.js.map +1 -1
- package/dist/context-engine/compaction/clear-tool-results.d.ts +18 -3
- package/dist/context-engine/compaction/clear-tool-results.d.ts.map +1 -1
- package/dist/context-engine/compaction/clear-tool-results.js +26 -5
- package/dist/context-engine/compaction/clear-tool-results.js.map +1 -1
- package/dist/context-engine/compaction/compactor.js +19 -6
- package/dist/context-engine/compaction/compactor.js.map +1 -1
- package/dist/context-engine/compaction/hooks/reanchor-persona-block.js +4 -0
- package/dist/context-engine/compaction/hooks/reanchor-persona-block.js.map +1 -1
- package/dist/context-engine/compaction/hooks/reanchor-pinned-facts.js +1 -0
- package/dist/context-engine/compaction/hooks/reanchor-pinned-facts.js.map +1 -1
- package/dist/context-engine/compaction/hooks/reanchor-project-rules.js +2 -1
- package/dist/context-engine/compaction/hooks/reanchor-project-rules.js.map +1 -1
- package/dist/context-engine/compaction/hooks/reanchor-recent-results.d.ts +28 -0
- package/dist/context-engine/compaction/hooks/reanchor-recent-results.d.ts.map +1 -0
- package/dist/context-engine/compaction/hooks/reanchor-recent-results.js +71 -0
- package/dist/context-engine/compaction/hooks/reanchor-recent-results.js.map +1 -0
- package/dist/context-engine/compaction/hooks/types.d.ts +15 -3
- package/dist/context-engine/compaction/hooks/types.d.ts.map +1 -1
- package/dist/context-engine/compaction/index.d.ts +1 -0
- package/dist/context-engine/compaction/index.js +2 -1
- package/dist/context-engine/compaction/templates/summary-9-section.d.ts +10 -3
- package/dist/context-engine/compaction/templates/summary-9-section.d.ts.map +1 -1
- package/dist/context-engine/compaction/templates/summary-9-section.js +42 -5
- package/dist/context-engine/compaction/templates/summary-9-section.js.map +1 -1
- package/dist/context-engine/compaction/thresholds.js.map +1 -1
- package/dist/context-engine/compaction/types.d.ts +47 -7
- package/dist/context-engine/compaction/types.d.ts.map +1 -1
- package/dist/context-engine/engine.d.ts +23 -4
- package/dist/context-engine/engine.d.ts.map +1 -1
- package/dist/context-engine/engine.js +69 -15
- package/dist/context-engine/engine.js.map +1 -1
- package/dist/context-engine/index.d.ts +1 -0
- package/dist/context-engine/index.d.ts.map +1 -1
- package/dist/context-engine/index.js +2 -1
- package/dist/context-engine/locale-packs/en.js +14 -13
- package/dist/context-engine/locale-packs/en.js.map +1 -1
- package/dist/context-engine/locale-packs/types.d.ts +10 -10
- package/dist/context-engine/locale-packs/types.d.ts.map +1 -1
- package/dist/context-engine/locale-packs/types.js.map +1 -1
- package/dist/context-engine/metadata.d.ts +1 -1
- package/dist/context-engine/metadata.js +2 -2
- package/dist/context-engine/metadata.js.map +1 -1
- package/dist/context-engine/preambles/inbound-en.d.ts +1 -1
- package/dist/context-engine/preambles/inbound-en.js +1 -1
- package/dist/context-engine/preambles/inbound-en.js.map +1 -1
- package/dist/context-engine/privacy-filter.d.ts +2 -2
- package/dist/context-engine/privacy-filter.js +1 -1
- package/dist/context-engine/privacy-filter.js.map +1 -1
- package/dist/context-engine/templates/base-en.d.ts +1 -1
- package/dist/context-engine/templates/base-en.js +1 -1
- package/dist/context-engine/templates/base-en.js.map +1 -1
- package/dist/context-engine/templates/composer.d.ts +1 -1
- package/dist/context-engine/templates/composer.js.map +1 -1
- package/dist/context-engine/token-budget.d.ts +1 -1
- package/dist/context-engine/token-budget.js +1 -1
- package/dist/context-engine/token-budget.js.map +1 -1
- package/dist/context-engine/token-counter.d.ts +16 -7
- package/dist/context-engine/token-counter.d.ts.map +1 -1
- package/dist/context-engine/token-counter.js +31 -9
- package/dist/context-engine/token-counter.js.map +1 -1
- package/dist/errors/index.d.ts +2 -2
- package/dist/errors/index.js +4 -4
- package/dist/errors/index.js.map +1 -1
- package/dist/facade.d.ts +44 -15
- package/dist/facade.d.ts.map +1 -1
- package/dist/facade.js +16 -8
- package/dist/facade.js.map +1 -1
- package/dist/graph/entity-resolver.d.ts +2 -2
- package/dist/graph/entity-resolver.js +2 -2
- package/dist/graph/entity-resolver.js.map +1 -1
- package/dist/index.d.ts +9 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -4
- package/dist/index.js.map +1 -1
- package/dist/internal/contextualize.js +2 -2
- package/dist/internal/contextualize.js.map +1 -1
- package/dist/internal/embedder-binding.js +1 -1
- package/dist/internal/embedder-binding.js.map +1 -1
- package/dist/internal/id.js +1 -1
- package/dist/internal/id.js.map +1 -1
- package/dist/internal/injection-heuristics.js +25 -2
- package/dist/internal/injection-heuristics.js.map +1 -1
- package/dist/internal/spans.js +1 -1
- package/dist/internal/spans.js.map +1 -1
- package/dist/internal/storage-adapter.d.ts +71 -22
- package/dist/internal/storage-adapter.d.ts.map +1 -1
- package/dist/migration/embedder-migration.d.ts +7 -7
- package/dist/migration/embedder-migration.js.map +1 -1
- package/dist/search/explain.d.ts +7 -4
- package/dist/search/explain.d.ts.map +1 -1
- package/dist/search/explain.js +1 -1
- package/dist/search/explain.js.map +1 -1
- package/dist/search/fit-weights.d.ts +48 -0
- package/dist/search/fit-weights.d.ts.map +1 -0
- package/dist/search/fit-weights.js +70 -0
- package/dist/search/fit-weights.js.map +1 -0
- package/dist/search/graph-ppr.d.ts +36 -0
- package/dist/search/graph-ppr.d.ts.map +1 -0
- package/dist/search/graph-ppr.js +38 -0
- package/dist/search/graph-ppr.js.map +1 -0
- package/dist/search/index.d.ts +4 -1
- package/dist/search/index.js +4 -1
- package/dist/search/iterative.d.ts +15 -8
- package/dist/search/iterative.d.ts.map +1 -1
- package/dist/search/iterative.js +10 -9
- package/dist/search/iterative.js.map +1 -1
- package/dist/search/query-transform.d.ts +6 -6
- package/dist/search/query-transform.js +6 -6
- package/dist/search/query-transform.js.map +1 -1
- package/dist/search/rrf.d.ts +4 -4
- package/dist/search/rrf.js +4 -4
- package/dist/search/rrf.js.map +1 -1
- package/dist/search/trust.d.ts +30 -0
- package/dist/search/trust.d.ts.map +1 -0
- package/dist/search/trust.js +50 -0
- package/dist/search/trust.js.map +1 -0
- package/dist/search/types.d.ts +1 -1
- package/dist/tiers/episodic-memory.d.ts +6 -4
- package/dist/tiers/episodic-memory.d.ts.map +1 -1
- package/dist/tiers/episodic-memory.js +3 -2
- package/dist/tiers/episodic-memory.js.map +1 -1
- package/dist/tiers/index.d.ts +1 -1
- package/dist/tiers/index.js +1 -1
- package/dist/tiers/insight-memory.d.ts +4 -4
- package/dist/tiers/insight-memory.js +3 -3
- package/dist/tiers/insight-memory.js.map +1 -1
- package/dist/tiers/procedural-memory.d.ts +29 -7
- package/dist/tiers/procedural-memory.d.ts.map +1 -1
- package/dist/tiers/procedural-memory.js +66 -6
- package/dist/tiers/procedural-memory.js.map +1 -1
- package/dist/tiers/semantic-memory.d.ts +111 -30
- package/dist/tiers/semantic-memory.d.ts.map +1 -1
- package/dist/tiers/semantic-memory.js +120 -27
- package/dist/tiers/semantic-memory.js.map +1 -1
- package/dist/tiers/session-memory.d.ts +7 -7
- package/dist/tiers/session-memory.js +7 -7
- package/dist/tiers/session-memory.js.map +1 -1
- package/dist/tiers/shared-memory.d.ts +1 -1
- package/dist/tiers/shared-memory.js +1 -1
- package/dist/tiers/shared-memory.js.map +1 -1
- package/dist/tiers/working-memory.d.ts +3 -3
- package/dist/tiers/working-memory.js +2 -2
- package/dist/tiers/working-memory.js.map +1 -1
- package/dist/tools/block-tools.d.ts +9 -9
- package/dist/tools/block-tools.d.ts.map +1 -1
- package/dist/tools/block-tools.js +3 -3
- package/dist/tools/block-tools.js.map +1 -1
- package/dist/tools/fact-tools.d.ts +48 -31
- package/dist/tools/fact-tools.d.ts.map +1 -1
- package/dist/tools/fact-tools.js +30 -18
- package/dist/tools/fact-tools.js.map +1 -1
- package/dist/tools/index.d.ts +9 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +4 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/recall-tools.d.ts +40 -20
- package/dist/tools/recall-tools.d.ts.map +1 -1
- package/dist/tools/recall-tools.js +29 -10
- package/dist/tools/recall-tools.js.map +1 -1
- package/dist/tools/runbook-tools.d.ts +76 -0
- package/dist/tools/runbook-tools.d.ts.map +1 -0
- package/dist/tools/runbook-tools.js +53 -0
- package/dist/tools/runbook-tools.js.map +1 -0
- package/dist/tools/taint.js +33 -0
- package/dist/tools/taint.js.map +1 -0
- package/dist/tools/types.d.ts +1 -1
- package/package.json +8 -8
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { withMemorySpan } from "../internal/spans.js";
|
|
2
|
+
import { DEFAULT_SALIENCE_WEIGHTS } from "../consolidator/decay.js";
|
|
2
3
|
import { QuarantinePromotionRefusedError } from "../errors/index.js";
|
|
3
4
|
import { contextualize } from "../internal/contextualize.js";
|
|
4
5
|
import { newMemoryId } from "../internal/id.js";
|
|
6
|
+
import { normalizeEntityName } from "../graph/entity-resolver.js";
|
|
5
7
|
import { DEFAULT_MAX_ITERATIONS, runIterativeRetrieval } from "../search/iterative.js";
|
|
6
8
|
import { WeightedRRFReranker, fuseRrf, fuseWeighted } from "../search/rrf.js";
|
|
7
9
|
import { detectMemoryInjection } from "../internal/injection-heuristics.js";
|
|
8
10
|
import { explainRecall } from "../search/explain.js";
|
|
11
|
+
import { pprActivation } from "../search/graph-ppr.js";
|
|
12
|
+
import { trustDiscount } from "../search/trust.js";
|
|
9
13
|
import { md5 } from "@graphorin/core";
|
|
10
14
|
|
|
11
15
|
//#region src/tiers/semantic-memory.ts
|
|
12
16
|
/**
|
|
13
|
-
* `SemanticMemory`
|
|
17
|
+
* `SemanticMemory` - long-term factual store. Hybrid (vector + FTS5)
|
|
14
18
|
* search merges the two ranked lists through the configured
|
|
15
19
|
* {@link ReRanker} (default {@link RRFReranker} with `k = 60`).
|
|
16
20
|
*
|
|
@@ -34,6 +38,7 @@ var SemanticMemory = class {
|
|
|
34
38
|
#grader;
|
|
35
39
|
#iterativeMaxIterations;
|
|
36
40
|
#reranker;
|
|
41
|
+
#trustWeights;
|
|
37
42
|
constructor(args) {
|
|
38
43
|
this.#store = args.store;
|
|
39
44
|
this.#tracer = args.tracer;
|
|
@@ -46,6 +51,7 @@ var SemanticMemory = class {
|
|
|
46
51
|
this.#entityResolver = args.entityResolver ?? null;
|
|
47
52
|
this.#grader = args.grader ?? null;
|
|
48
53
|
this.#iterativeMaxIterations = args.iterativeMaxIterations ?? DEFAULT_MAX_ITERATIONS;
|
|
54
|
+
this.#trustWeights = args.trustWeights ?? DEFAULT_SALIENCE_WEIGHTS;
|
|
49
55
|
}
|
|
50
56
|
/** Replace the active reranker. Returns the previous instance. */
|
|
51
57
|
setReranker(reranker) {
|
|
@@ -104,6 +110,7 @@ var SemanticMemory = class {
|
|
|
104
110
|
...input.supersedes !== void 0 ? { supersedes: input.supersedes } : {},
|
|
105
111
|
...provenance !== void 0 ? { provenance } : {},
|
|
106
112
|
status,
|
|
113
|
+
...input.owner !== void 0 ? { owner: input.owner } : {},
|
|
107
114
|
createdAt: now,
|
|
108
115
|
updatedAt: now
|
|
109
116
|
};
|
|
@@ -212,7 +219,7 @@ var SemanticMemory = class {
|
|
|
212
219
|
* P2-1: resolve the fact's subject / object to canonical entities and
|
|
213
220
|
* link them so one-hop expansion can traverse this fact. A no-op when
|
|
214
221
|
* no resolver is configured (the default) or the fact has no s/p/o, and
|
|
215
|
-
* resilient
|
|
222
|
+
* resilient - a resolution failure never breaks the write that just
|
|
216
223
|
* committed.
|
|
217
224
|
*/
|
|
218
225
|
async #linkEntities(scope, fact, signal) {
|
|
@@ -230,6 +237,8 @@ var SemanticMemory = class {
|
|
|
230
237
|
const weighted = opts.fusion !== void 0 && opts.fusion.strategy === "weighted" ? opts.fusion : null;
|
|
231
238
|
const wFts = weighted?.weights.fts ?? 1;
|
|
232
239
|
const wVector = weighted?.weights.vector ?? 1;
|
|
240
|
+
const wGraph = weighted?.weights.graph ?? 1;
|
|
241
|
+
const wEntity = weighted?.weights.entity ?? 1;
|
|
233
242
|
const queries = await this.#expandQueries(query, opts);
|
|
234
243
|
const lists = [];
|
|
235
244
|
const listWeights = [];
|
|
@@ -244,12 +253,14 @@ var SemanticMemory = class {
|
|
|
244
253
|
...opts.asOf !== void 0 ? { asOf: opts.asOf } : {},
|
|
245
254
|
...opts.tags !== void 0 && opts.tags.length > 0 ? { tags: opts.tags } : {},
|
|
246
255
|
...opts.includeQuarantined === true ? { includeQuarantined: true } : {},
|
|
256
|
+
...opts.includeSuperseded === true ? { includeSuperseded: true } : {},
|
|
257
|
+
...opts.owner !== void 0 ? { owner: opts.owner } : {},
|
|
247
258
|
...opts.signal !== void 0 ? { signal: opts.signal } : {}
|
|
248
259
|
});
|
|
249
260
|
lists.push(ftsHits);
|
|
250
261
|
listWeights.push(wFts);
|
|
251
262
|
listLabels.push(`fts_${queries.indexOf(q)}`);
|
|
252
|
-
const vectorHits = await this.#tryVectorSearch(scope, q, candidateTopK, opts.asOf, opts.includeQuarantined);
|
|
263
|
+
const vectorHits = await this.#tryVectorSearch(scope, q, candidateTopK, opts.asOf, opts.includeQuarantined, opts.includeSuperseded, opts.owner);
|
|
253
264
|
if (vectorHits.length > 0) {
|
|
254
265
|
lists.push(vectorHits);
|
|
255
266
|
listWeights.push(wVector);
|
|
@@ -270,25 +281,34 @@ var SemanticMemory = class {
|
|
|
270
281
|
const graphHits = await this.#tryExpandHops(scope, lists, opts, candidateTopK);
|
|
271
282
|
if (graphHits.length > 0) {
|
|
272
283
|
lists.push(graphHits);
|
|
273
|
-
listWeights.push(
|
|
284
|
+
listWeights.push(wGraph);
|
|
274
285
|
listLabels.push("graph");
|
|
275
286
|
}
|
|
287
|
+
const entityHits = await this.#tryEntityMatch(scope, query, opts, candidateTopK);
|
|
288
|
+
if (entityHits.length > 0) {
|
|
289
|
+
lists.push(entityHits);
|
|
290
|
+
listWeights.push(wEntity);
|
|
291
|
+
listLabels.push("entity");
|
|
292
|
+
}
|
|
276
293
|
const reranker = weighted !== null ? new WeightedRRFReranker({
|
|
277
294
|
weights: listWeights,
|
|
278
295
|
...weighted.k !== void 0 ? { k: weighted.k } : {}
|
|
279
296
|
}) : this.#reranker;
|
|
280
|
-
const fusedTopK = opts.decay !== void 0 ? Math.max(finalTopK, lists.reduce((n, l) => n + l.length, 0)) : finalTopK;
|
|
297
|
+
const fusedTopK = opts.decay !== void 0 || (opts.tags?.length ?? 0) > 0 || opts.owner !== void 0 || (opts.expandHops ?? 0) > 0 || opts.entityMatch === true ? Math.max(finalTopK, lists.reduce((n, l) => n + l.length, 0)) : finalTopK;
|
|
281
298
|
const fused = await reranker.rerank(query, lists, {
|
|
282
299
|
topK: fusedTopK,
|
|
283
300
|
labels: listLabels,
|
|
284
301
|
...opts.signal !== void 0 ? { signal: opts.signal } : {}
|
|
285
302
|
});
|
|
286
303
|
const decayed = await this.#applyDecay(scope, fused, opts.decay);
|
|
287
|
-
const
|
|
304
|
+
const filtered = opts.tags !== void 0 && opts.tags.length > 0 ? decayed.filter((h) => {
|
|
288
305
|
const recordTags = h.record.tags;
|
|
289
306
|
if (recordTags === void 0 || recordTags.length === 0) return false;
|
|
290
307
|
return opts.tags?.some((t) => recordTags.includes(t)) === true;
|
|
291
|
-
}) : decayed
|
|
308
|
+
}) : decayed;
|
|
309
|
+
const wantedOwners = opts.owner === void 0 ? null : typeof opts.owner === "string" ? [opts.owner] : opts.owner;
|
|
310
|
+
const ownerFiltered = wantedOwners !== null ? filtered.filter((h) => wantedOwners.includes(h.record.owner ?? "user")) : filtered;
|
|
311
|
+
const ranked = (opts.trustWeighting === "off" ? ownerFiltered : this.#applyTrustDiscount(ownerFiltered)).slice(0, finalTopK);
|
|
292
312
|
if (ranked.length > 0 && typeof this.#store.semantic.markAccessed === "function") try {
|
|
293
313
|
await this.#store.semantic.markAccessed(ranked.map((h) => h.record.id));
|
|
294
314
|
} catch {}
|
|
@@ -321,8 +341,8 @@ var SemanticMemory = class {
|
|
|
321
341
|
* hard *and* with a grader configured
|
|
322
342
|
* (`createMemory({ iterativeRetrieval })`), the retrieved set is graded
|
|
323
343
|
* for sufficiency and, when weak, the query is reformulated and
|
|
324
|
-
* retrieved again
|
|
325
|
-
* (`expandHops: 1`) on each reformulation pass
|
|
344
|
+
* retrieved again - **widening to one-hop graph expansion**
|
|
345
|
+
* (`expandHops: 1`) on each reformulation pass - up to `maxIterations`
|
|
326
346
|
* (hard-capped at 5). When still insufficient it returns
|
|
327
347
|
* `abstained: true` so the caller can decline to answer instead of
|
|
328
348
|
* confabulating.
|
|
@@ -368,7 +388,7 @@ var SemanticMemory = class {
|
|
|
368
388
|
* zone thresholds are calibrated against them), and it **includes
|
|
369
389
|
* quarantined facts** so prior synthesized memories are visible to
|
|
370
390
|
* reconciliation. Returns `[]` when no embedder / vector adapter is
|
|
371
|
-
* configured
|
|
391
|
+
* configured - the consolidator then treats every candidate as a
|
|
372
392
|
* fresh `add`, degrading gracefully to the pre-reconcile behaviour.
|
|
373
393
|
*
|
|
374
394
|
* @stable
|
|
@@ -390,7 +410,7 @@ var SemanticMemory = class {
|
|
|
390
410
|
* to, oldest → newest, including superseded / soft-deleted rows so
|
|
391
411
|
* callers can answer "how did this fact change over time". Requires
|
|
392
412
|
* a storage adapter that implements
|
|
393
|
-
* `SemanticMemoryStoreExt.historyOf(...)`
|
|
413
|
+
* `SemanticMemoryStoreExt.historyOf(...)` - the default
|
|
394
414
|
* `@graphorin/store-sqlite` adapter wires this through. P0-2.
|
|
395
415
|
*
|
|
396
416
|
* @stable
|
|
@@ -411,12 +431,12 @@ var SemanticMemory = class {
|
|
|
411
431
|
* that admits a synthesized memory into action-driving recall once a
|
|
412
432
|
* human (or trusted non-agent caller) has reviewed it. Writes a
|
|
413
433
|
* `memory_history` audit row. Requires a storage adapter that
|
|
414
|
-
* implements `SemanticMemoryStoreExt.setStatus(...)`
|
|
434
|
+
* implements `SemanticMemoryStoreExt.setStatus(...)` - the default
|
|
415
435
|
* `@graphorin/store-sqlite` adapter wires this through.
|
|
416
436
|
*
|
|
417
437
|
* MRET-3 / MST-1: promotion of a fact whose text still trips the
|
|
418
438
|
* offline injection heuristics is **refused** with
|
|
419
|
-
* {@link QuarantinePromotionRefusedError}
|
|
439
|
+
* {@link QuarantinePromotionRefusedError} - the model-facing
|
|
420
440
|
* `fact_validate` tool calls this with no `force`, so a poisoned
|
|
421
441
|
* memory can never be promoted by the agent itself (the one-turn
|
|
422
442
|
* `fact_remember(poison)` → `fact_validate(id)` chain is closed). An
|
|
@@ -475,7 +495,7 @@ var SemanticMemory = class {
|
|
|
475
495
|
* Hard-delete a fact (GDPR path). Distinct from {@link forget}: the
|
|
476
496
|
* record is removed from storage entirely instead of soft-archived.
|
|
477
497
|
* Requires a storage adapter that implements
|
|
478
|
-
* `SemanticMemoryStoreExt.purge(...)`
|
|
498
|
+
* `SemanticMemoryStoreExt.purge(...)` - the default
|
|
479
499
|
* `@graphorin/store-sqlite` adapter wires this through.
|
|
480
500
|
*/
|
|
481
501
|
async purge(scope, factId, reason) {
|
|
@@ -491,12 +511,12 @@ var SemanticMemory = class {
|
|
|
491
511
|
async fuse(query, lists, options = {}) {
|
|
492
512
|
return this.#reranker.rerank(query, lists, options);
|
|
493
513
|
}
|
|
494
|
-
/** Pure-fusion helper
|
|
514
|
+
/** Pure-fusion helper - exposed for callers that already collected results. */
|
|
495
515
|
static fuseRrf(lists, k = 60) {
|
|
496
516
|
return fuseRrf(lists, k);
|
|
497
517
|
}
|
|
498
518
|
/**
|
|
499
|
-
* Pure weighted-fusion helper (X-2)
|
|
519
|
+
* Pure weighted-fusion helper (X-2) - like {@link SemanticMemory.fuseRrf}
|
|
500
520
|
* but scales each list `i`'s reciprocal-rank contribution by
|
|
501
521
|
* `weights[i]`. A missing / invalid entry defaults to `1`, so equal or
|
|
502
522
|
* absent weights reproduce RRF.
|
|
@@ -507,7 +527,7 @@ var SemanticMemory = class {
|
|
|
507
527
|
/**
|
|
508
528
|
* Multi-query expansion (P2-3). Returns the original query followed by
|
|
509
529
|
* up to `multiQuery - 1` deduped reworded variants. A no-op (`[query]`)
|
|
510
|
-
* when `multiQuery` is unset / `<= 1` or no transformer is configured
|
|
530
|
+
* when `multiQuery` is unset / `<= 1` or no transformer is configured -
|
|
511
531
|
* so the default path makes no provider call. A transformer failure
|
|
512
532
|
* degrades to `[query]` rather than breaking recall.
|
|
513
533
|
*/
|
|
@@ -535,7 +555,7 @@ var SemanticMemory = class {
|
|
|
535
555
|
* HyDE retrieval (P2-3). Generates a hypothetical answer, embeds it,
|
|
536
556
|
* and returns its vector neighbours to fuse into the result. A no-op
|
|
537
557
|
* (`[]`) unless `hyde` is set, a transformer is configured, **and** an
|
|
538
|
-
* embedder + vector surface exist
|
|
558
|
+
* embedder + vector surface exist - the embedder guard is checked
|
|
539
559
|
* *first* so a missing embedder skips the LLM call entirely rather than
|
|
540
560
|
* generating a passage that can never be embedded.
|
|
541
561
|
*/
|
|
@@ -554,7 +574,7 @@ var SemanticMemory = class {
|
|
|
554
574
|
* One-hop graph expansion (P2-1). Seeds on the unique fact ids already
|
|
555
575
|
* gathered into `lists` and fuses in facts sharing a canonical entity,
|
|
556
576
|
* via the adapter's recursive-CTE `graph.expandOneHop`. A no-op (`[]`)
|
|
557
|
-
* unless `expandHops >= 1` and the adapter exposes `graph`
|
|
577
|
+
* unless `expandHops >= 1` and the adapter exposes `graph` - and
|
|
558
578
|
* resilient: a traversal error degrades to no expansion rather than
|
|
559
579
|
* breaking recall. Neighbours carry a `graph` signal so explanations
|
|
560
580
|
* (X-3) can attribute a hit to the hop.
|
|
@@ -570,13 +590,24 @@ var SemanticMemory = class {
|
|
|
570
590
|
seedIds.push(hit.record.id);
|
|
571
591
|
}
|
|
572
592
|
if (seedIds.length === 0) return [];
|
|
593
|
+
const expandOpts = {
|
|
594
|
+
maxHops: hops,
|
|
595
|
+
limit,
|
|
596
|
+
...opts.includeQuarantined === true ? { includeQuarantined: true } : {},
|
|
597
|
+
...opts.includeSuperseded === true ? { includeSuperseded: true } : {},
|
|
598
|
+
...opts.asOf !== void 0 ? { asOf: opts.asOf } : {}
|
|
599
|
+
};
|
|
573
600
|
try {
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
601
|
+
if (opts.graphScoring === "ppr" && typeof graphStore.expandActivation === "function") {
|
|
602
|
+
const graded = await graphStore.expandActivation(scope, seedIds, expandOpts);
|
|
603
|
+
const scores = pprActivation(graded);
|
|
604
|
+
return graded.map((entry, i) => ({
|
|
605
|
+
record: entry.fact,
|
|
606
|
+
score: scores[i] ?? 0,
|
|
607
|
+
signals: Object.freeze({ graph: scores[i] ?? 0 })
|
|
608
|
+
}));
|
|
609
|
+
}
|
|
610
|
+
return (await graphStore.expandOneHop(scope, seedIds, expandOpts)).map((fact) => ({
|
|
580
611
|
record: fact,
|
|
581
612
|
score: 1,
|
|
582
613
|
signals: Object.freeze({ graph: 1 })
|
|
@@ -585,12 +616,74 @@ var SemanticMemory = class {
|
|
|
585
616
|
return [];
|
|
586
617
|
}
|
|
587
618
|
}
|
|
588
|
-
|
|
619
|
+
/**
|
|
620
|
+
* D5 exact entity-match leg. Normalizes the query into candidate
|
|
621
|
+
* entity names and fetches facts linked to a matching canonical
|
|
622
|
+
* entity. A no-op without `entityMatch`, a graph adapter, or the
|
|
623
|
+
* `factsForEntityName` store method.
|
|
624
|
+
*/
|
|
625
|
+
async #tryEntityMatch(scope, query, opts, limit) {
|
|
626
|
+
if (opts.entityMatch !== true) return [];
|
|
627
|
+
const graphStore = this.#store.graph;
|
|
628
|
+
if (graphStore === void 0 || typeof graphStore.factsForEntityName !== "function") return [];
|
|
629
|
+
const normalized = normalizeEntityName(query);
|
|
630
|
+
if (normalized.length === 0) return [];
|
|
631
|
+
const candidates = new Set([normalized]);
|
|
632
|
+
const words = normalized.split(" ").filter((w) => w.length > 2);
|
|
633
|
+
for (const w of words) candidates.add(w);
|
|
634
|
+
const out = [];
|
|
635
|
+
const seen = /* @__PURE__ */ new Set();
|
|
636
|
+
try {
|
|
637
|
+
for (const name of candidates) {
|
|
638
|
+
const facts = await graphStore.factsForEntityName(scope, name, {
|
|
639
|
+
limit,
|
|
640
|
+
...opts.includeQuarantined === true ? { includeQuarantined: true } : {},
|
|
641
|
+
...opts.includeSuperseded === true ? { includeSuperseded: true } : {},
|
|
642
|
+
...opts.asOf !== void 0 ? { asOf: opts.asOf } : {}
|
|
643
|
+
});
|
|
644
|
+
for (const fact of facts) {
|
|
645
|
+
if (seen.has(fact.id)) continue;
|
|
646
|
+
seen.add(fact.id);
|
|
647
|
+
out.push({
|
|
648
|
+
record: fact,
|
|
649
|
+
score: 1,
|
|
650
|
+
signals: Object.freeze({ entity: 1 })
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
} catch {
|
|
655
|
+
return [];
|
|
656
|
+
}
|
|
657
|
+
return out;
|
|
658
|
+
}
|
|
659
|
+
async #tryVectorSearch(scope, query, topK, asOf, includeQuarantined, includeSuperseded, owner) {
|
|
589
660
|
const embedderId = this.#embedderIdProvider();
|
|
590
661
|
if (this.#embedder === null || embedderId === null || typeof this.#store.semantic.searchVector !== "function") return [];
|
|
591
662
|
const [vector] = await this.#embedder.embed([query], { taskType: "query" });
|
|
592
663
|
if (vector === void 0) return [];
|
|
593
|
-
return this.#store.semantic.searchVector(scope, vector, embedderId, topK, asOf, includeQuarantined);
|
|
664
|
+
return this.#store.semantic.searchVector(scope, vector, embedderId, topK, asOf, includeQuarantined, includeSuperseded, owner);
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* C5: multiply each hit's fused score by its trust factor and re-sort.
|
|
668
|
+
* No-ops (returns the same array) when every factor is 1.
|
|
669
|
+
*/
|
|
670
|
+
#applyTrustDiscount(hits) {
|
|
671
|
+
let changed = false;
|
|
672
|
+
const discounted = hits.map((hit) => {
|
|
673
|
+
const factor = trustDiscount(hit.record, this.#trustWeights);
|
|
674
|
+
if (factor >= 1) return hit;
|
|
675
|
+
changed = true;
|
|
676
|
+
return {
|
|
677
|
+
record: hit.record,
|
|
678
|
+
score: hit.score * factor,
|
|
679
|
+
signals: Object.freeze({
|
|
680
|
+
...hit.signals ?? {},
|
|
681
|
+
trust: factor
|
|
682
|
+
})
|
|
683
|
+
};
|
|
684
|
+
});
|
|
685
|
+
if (!changed) return hits;
|
|
686
|
+
return [...discounted].sort((a, b) => b.score - a.score);
|
|
594
687
|
}
|
|
595
688
|
async #applyDecay(scope, hits, decay) {
|
|
596
689
|
if (decay === void 0 || hits.length === 0) return hits;
|