@anuma/sdk 6.19.2 → 6.21.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/dist/expo/{chunk-7HRJOHW4.mjs → chunk-CIMZZ7GQ.mjs} +59 -12
- package/dist/expo/index.cjs +142 -43
- package/dist/expo/index.d.mts +171 -2
- package/dist/expo/index.d.ts +171 -2
- package/dist/expo/index.mjs +85 -33
- package/dist/expo/{recall-SCMH2R24.mjs → recall-FQQGE6A2.mjs} +1 -1
- package/dist/react/{chunk-M53NXLZS.mjs → chunk-JRVAUZHM.mjs} +59 -12
- package/dist/react/index.cjs +142 -43
- package/dist/react/index.d.mts +171 -2
- package/dist/react/index.d.ts +171 -2
- package/dist/react/index.mjs +85 -33
- package/dist/react/{recall-B3M4BWQ2.mjs → recall-7Q3V337H.mjs} +1 -1
- package/dist/server/{chunk-X5EZQFGR.mjs → chunk-4DSDATYG.mjs} +59 -12
- package/dist/server/index.cjs +142 -43
- package/dist/server/index.d.mts +171 -2
- package/dist/server/index.d.ts +171 -2
- package/dist/server/index.mjs +85 -33
- package/dist/server/{recall-M3KBKU74.mjs → recall-HA4UX4BB.mjs} +1 -1
- package/dist/telemetry/index.cjs +20 -0
- package/dist/telemetry/index.d.mts +63 -1
- package/dist/telemetry/index.d.ts +63 -1
- package/dist/telemetry/index.mjs +20 -0
- package/package.json +1 -1
|
@@ -6912,7 +6912,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
6912
6912
|
subQueries = decomp.subQueries;
|
|
6913
6913
|
}
|
|
6914
6914
|
}
|
|
6915
|
-
const { recall: recall2 } = await import("./recall-
|
|
6915
|
+
const { recall: recall2 } = await import("./recall-FQQGE6A2.mjs");
|
|
6916
6916
|
let recallDegraded = [];
|
|
6917
6917
|
const result = await recall2(
|
|
6918
6918
|
query,
|
|
@@ -7503,7 +7503,22 @@ async function recall(query, ctx, options = {}) {
|
|
|
7503
7503
|
let factLaneRankedOnCosine = false;
|
|
7504
7504
|
let decryptLastRan;
|
|
7505
7505
|
let vaultRowsDecrypted;
|
|
7506
|
-
|
|
7506
|
+
let graphLaneCount = 0;
|
|
7507
|
+
let temporalLaneCount = 0;
|
|
7508
|
+
let graphLaneFailed = false;
|
|
7509
|
+
let temporalLaneFailed = false;
|
|
7510
|
+
let hitLimit = false;
|
|
7511
|
+
let factFloor = -1;
|
|
7512
|
+
let chunkFloor = -1;
|
|
7513
|
+
const emptyReasonFor = (admitted, laneRan) => {
|
|
7514
|
+
if (admitted > 0) return "";
|
|
7515
|
+
if (!query || typeof query !== "string" || query.trim().length === 0) return "empty-query";
|
|
7516
|
+
if (!laneRan) return "no-lanes";
|
|
7517
|
+
const chunkLaneCouldAnswer = types.includes("chunk") && !!ctx.storageCtx;
|
|
7518
|
+
if (vaultSize === 0 && !chunkLaneCouldAnswer) return "vault-empty";
|
|
7519
|
+
return "no-candidates";
|
|
7520
|
+
};
|
|
7521
|
+
const emitDiagnostics = (candidateCount, admitted) => {
|
|
7507
7522
|
const cb = options.onDiagnostics;
|
|
7508
7523
|
if (!cb) return;
|
|
7509
7524
|
const degraded = [];
|
|
@@ -7514,6 +7529,11 @@ async function recall(query, ctx, options = {}) {
|
|
|
7514
7529
|
degraded.push("decompose-moved");
|
|
7515
7530
|
}
|
|
7516
7531
|
if (embeddingsUnavailable) degraded.push("embeddings-unavailable");
|
|
7532
|
+
if (graphLaneFailed) degraded.push("graph-lane-failed");
|
|
7533
|
+
if (temporalLaneFailed) degraded.push("temporal-lane-failed");
|
|
7534
|
+
const laneRan = types.includes("fact") && !!ctx.vaultCtx && !!ctx.vaultCache || types.includes("chunk") && !!ctx.storageCtx;
|
|
7535
|
+
const scores = admitted.map((m) => m.score);
|
|
7536
|
+
const minScoreApplied = factResults.length > 0 ? factFloor : chunkResults.length > 0 ? chunkFloor : factFloor >= 0 ? factFloor : chunkFloor;
|
|
7517
7537
|
const diagnostics = {
|
|
7518
7538
|
usedBudget,
|
|
7519
7539
|
reranked: didRerank,
|
|
@@ -7524,6 +7544,14 @@ async function recall(query, ctx, options = {}) {
|
|
|
7524
7544
|
...vaultRowsEmbedded !== void 0 && { vaultRowsEmbedded },
|
|
7525
7545
|
factCount: factResults.length,
|
|
7526
7546
|
chunkCount: chunkResults.length,
|
|
7547
|
+
admittedCount: admitted.length,
|
|
7548
|
+
topScore: scores.length > 0 ? Math.max(...scores) : -1,
|
|
7549
|
+
lowestAdmittedScore: scores.length > 0 ? Math.min(...scores) : -1,
|
|
7550
|
+
minScoreApplied,
|
|
7551
|
+
truncated: hitLimit,
|
|
7552
|
+
graphLaneCount,
|
|
7553
|
+
temporalLaneCount,
|
|
7554
|
+
emptyReason: emptyReasonFor(admitted.length, laneRan),
|
|
7527
7555
|
timings: {
|
|
7528
7556
|
total: nowMs2() - t0,
|
|
7529
7557
|
prep: prepMs,
|
|
@@ -7541,7 +7569,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
7541
7569
|
}
|
|
7542
7570
|
};
|
|
7543
7571
|
if (!query || typeof query !== "string" || query.trim().length === 0) {
|
|
7544
|
-
emitDiagnostics(0);
|
|
7572
|
+
emitDiagnostics(0, []);
|
|
7545
7573
|
return { memories: [], usedBudget, reranked: false, candidateCount: 0 };
|
|
7546
7574
|
}
|
|
7547
7575
|
const needsChunkEmbedding = types.includes("chunk") && ctx.storageCtx;
|
|
@@ -7575,6 +7603,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
7575
7603
|
// empty ranking instead (mirrors safeCountVault's fail-soft posture).
|
|
7576
7604
|
safeLane(
|
|
7577
7605
|
"graph",
|
|
7606
|
+
() => graphLaneFailed = true,
|
|
7578
7607
|
() => buildGraphLaneRanking(query, ctx, flags.traverse, {
|
|
7579
7608
|
...options.maxHops !== void 0 && { maxHops: options.maxHops },
|
|
7580
7609
|
...options.entityFanout !== void 0 && { entityFanout: options.entityFanout },
|
|
@@ -7583,12 +7612,19 @@ async function recall(query, ctx, options = {}) {
|
|
|
7583
7612
|
...graphRefiner && { refineNeighbors: graphRefiner }
|
|
7584
7613
|
})
|
|
7585
7614
|
),
|
|
7586
|
-
wantsTemporal ? safeLane(
|
|
7615
|
+
wantsTemporal ? safeLane(
|
|
7616
|
+
"temporal",
|
|
7617
|
+
() => temporalLaneFailed = true,
|
|
7618
|
+
() => buildTemporalLaneRanking(query, ctx.vaultCtx, options.now)
|
|
7619
|
+
) : Promise.resolve([])
|
|
7587
7620
|
]);
|
|
7588
7621
|
prepMs = nowMs2() - prepStart;
|
|
7622
|
+
graphLaneCount = entityRanking.length;
|
|
7623
|
+
temporalLaneCount = temporalRanking.length;
|
|
7589
7624
|
if (types.includes("fact") && ctx.vaultCtx && ctx.vaultCache) {
|
|
7590
7625
|
const factStart = nowMs2();
|
|
7591
7626
|
const vaultMinScore = options.minScore ?? DEFAULT_FACT_MIN_SCORE;
|
|
7627
|
+
factFloor = vaultMinScore;
|
|
7592
7628
|
const {
|
|
7593
7629
|
results,
|
|
7594
7630
|
vaultSize: size,
|
|
@@ -7668,6 +7704,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
7668
7704
|
if (types.includes("chunk") && ctx.storageCtx && queryEmbedding) {
|
|
7669
7705
|
const chunkStart = nowMs2();
|
|
7670
7706
|
const chunkMinScore = options.minScore ?? DEFAULT_CHUNK_MIN_SCORE;
|
|
7707
|
+
chunkFloor = chunkMinScore;
|
|
7671
7708
|
const results = await searchChunksOp(ctx.storageCtx, queryEmbedding, {
|
|
7672
7709
|
limit: types.includes("fact") ? Math.max(limit * 2, 16) : limit,
|
|
7673
7710
|
minSimilarity: chunkMinScore,
|
|
@@ -7694,9 +7731,11 @@ async function recall(query, ctx, options = {}) {
|
|
|
7694
7731
|
memories2.sort((a, b) => b.score - a.score);
|
|
7695
7732
|
const candidateCount = factResults.length + chunkResults.length;
|
|
7696
7733
|
fuseMs = nowMs2() - fuseStart;
|
|
7697
|
-
|
|
7734
|
+
const admitted = memories2.slice(0, limit);
|
|
7735
|
+
hitLimit = memories2.length > limit;
|
|
7736
|
+
emitDiagnostics(candidateCount, admitted);
|
|
7698
7737
|
return {
|
|
7699
|
-
memories:
|
|
7738
|
+
memories: admitted,
|
|
7700
7739
|
usedBudget,
|
|
7701
7740
|
reranked: didRerank,
|
|
7702
7741
|
candidateCount,
|
|
@@ -7726,12 +7765,16 @@ async function recall(query, ctx, options = {}) {
|
|
|
7726
7765
|
const ordered = [...byId.values()].sort((a, b) => b.score - a.score);
|
|
7727
7766
|
const selectWith = (suppressed2) => {
|
|
7728
7767
|
const out = [];
|
|
7768
|
+
let cut = false;
|
|
7729
7769
|
for (const m of ordered) {
|
|
7730
|
-
if (out.length >= limit) break;
|
|
7731
7770
|
if (m.kind === "chunk" && m.messageId && suppressed2.has(m.messageId)) continue;
|
|
7771
|
+
if (out.length >= limit) {
|
|
7772
|
+
cut = true;
|
|
7773
|
+
break;
|
|
7774
|
+
}
|
|
7732
7775
|
out.push(m);
|
|
7733
7776
|
}
|
|
7734
|
-
return out;
|
|
7777
|
+
return { out, cut };
|
|
7735
7778
|
};
|
|
7736
7779
|
const provenanceOf = (selected) => {
|
|
7737
7780
|
const s = /* @__PURE__ */ new Set();
|
|
@@ -7741,15 +7784,18 @@ async function recall(query, ctx, options = {}) {
|
|
|
7741
7784
|
return s;
|
|
7742
7785
|
};
|
|
7743
7786
|
let suppressed = /* @__PURE__ */ new Set();
|
|
7744
|
-
let
|
|
7787
|
+
let selection = selectWith(suppressed);
|
|
7788
|
+
let memories = selection.out;
|
|
7745
7789
|
for (let i = 0; i < ordered.length; i++) {
|
|
7746
7790
|
const next = provenanceOf(memories);
|
|
7747
7791
|
if (next.size === suppressed.size && [...next].every((id) => suppressed.has(id))) break;
|
|
7748
7792
|
suppressed = next;
|
|
7749
|
-
|
|
7793
|
+
selection = selectWith(suppressed);
|
|
7794
|
+
memories = selection.out;
|
|
7750
7795
|
}
|
|
7796
|
+
hitLimit = selection.cut;
|
|
7751
7797
|
fuseMs = nowMs2() - fuseStart;
|
|
7752
|
-
emitDiagnostics(byId.size);
|
|
7798
|
+
emitDiagnostics(byId.size, memories);
|
|
7753
7799
|
return {
|
|
7754
7800
|
memories,
|
|
7755
7801
|
usedBudget,
|
|
@@ -7833,10 +7879,11 @@ async function safeCountVault(ctx) {
|
|
|
7833
7879
|
return void 0;
|
|
7834
7880
|
}
|
|
7835
7881
|
}
|
|
7836
|
-
async function safeLane(label, run) {
|
|
7882
|
+
async function safeLane(label, onFailure, run) {
|
|
7837
7883
|
try {
|
|
7838
7884
|
return await run();
|
|
7839
7885
|
} catch (err) {
|
|
7886
|
+
onFailure();
|
|
7840
7887
|
getLogger().warn(
|
|
7841
7888
|
`[memory/recall] ${label} lane failed; continuing without it: ${err instanceof Error ? err.message : String(err)}`
|
|
7842
7889
|
);
|
package/dist/expo/index.cjs
CHANGED
|
@@ -7678,7 +7678,22 @@ async function recall(query, ctx, options = {}) {
|
|
|
7678
7678
|
let factLaneRankedOnCosine = false;
|
|
7679
7679
|
let decryptLastRan;
|
|
7680
7680
|
let vaultRowsDecrypted;
|
|
7681
|
-
|
|
7681
|
+
let graphLaneCount = 0;
|
|
7682
|
+
let temporalLaneCount = 0;
|
|
7683
|
+
let graphLaneFailed = false;
|
|
7684
|
+
let temporalLaneFailed = false;
|
|
7685
|
+
let hitLimit = false;
|
|
7686
|
+
let factFloor = -1;
|
|
7687
|
+
let chunkFloor = -1;
|
|
7688
|
+
const emptyReasonFor = (admitted, laneRan) => {
|
|
7689
|
+
if (admitted > 0) return "";
|
|
7690
|
+
if (!query || typeof query !== "string" || query.trim().length === 0) return "empty-query";
|
|
7691
|
+
if (!laneRan) return "no-lanes";
|
|
7692
|
+
const chunkLaneCouldAnswer = types.includes("chunk") && !!ctx.storageCtx;
|
|
7693
|
+
if (vaultSize === 0 && !chunkLaneCouldAnswer) return "vault-empty";
|
|
7694
|
+
return "no-candidates";
|
|
7695
|
+
};
|
|
7696
|
+
const emitDiagnostics = (candidateCount, admitted) => {
|
|
7682
7697
|
const cb = options.onDiagnostics;
|
|
7683
7698
|
if (!cb) return;
|
|
7684
7699
|
const degraded = [];
|
|
@@ -7689,6 +7704,11 @@ async function recall(query, ctx, options = {}) {
|
|
|
7689
7704
|
degraded.push("decompose-moved");
|
|
7690
7705
|
}
|
|
7691
7706
|
if (embeddingsUnavailable) degraded.push("embeddings-unavailable");
|
|
7707
|
+
if (graphLaneFailed) degraded.push("graph-lane-failed");
|
|
7708
|
+
if (temporalLaneFailed) degraded.push("temporal-lane-failed");
|
|
7709
|
+
const laneRan = types.includes("fact") && !!ctx.vaultCtx && !!ctx.vaultCache || types.includes("chunk") && !!ctx.storageCtx;
|
|
7710
|
+
const scores = admitted.map((m) => m.score);
|
|
7711
|
+
const minScoreApplied = factResults.length > 0 ? factFloor : chunkResults.length > 0 ? chunkFloor : factFloor >= 0 ? factFloor : chunkFloor;
|
|
7692
7712
|
const diagnostics = {
|
|
7693
7713
|
usedBudget,
|
|
7694
7714
|
reranked: didRerank,
|
|
@@ -7699,6 +7719,14 @@ async function recall(query, ctx, options = {}) {
|
|
|
7699
7719
|
...vaultRowsEmbedded !== void 0 && { vaultRowsEmbedded },
|
|
7700
7720
|
factCount: factResults.length,
|
|
7701
7721
|
chunkCount: chunkResults.length,
|
|
7722
|
+
admittedCount: admitted.length,
|
|
7723
|
+
topScore: scores.length > 0 ? Math.max(...scores) : -1,
|
|
7724
|
+
lowestAdmittedScore: scores.length > 0 ? Math.min(...scores) : -1,
|
|
7725
|
+
minScoreApplied,
|
|
7726
|
+
truncated: hitLimit,
|
|
7727
|
+
graphLaneCount,
|
|
7728
|
+
temporalLaneCount,
|
|
7729
|
+
emptyReason: emptyReasonFor(admitted.length, laneRan),
|
|
7702
7730
|
timings: {
|
|
7703
7731
|
total: nowMs() - t0,
|
|
7704
7732
|
prep: prepMs,
|
|
@@ -7716,7 +7744,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
7716
7744
|
}
|
|
7717
7745
|
};
|
|
7718
7746
|
if (!query || typeof query !== "string" || query.trim().length === 0) {
|
|
7719
|
-
emitDiagnostics(0);
|
|
7747
|
+
emitDiagnostics(0, []);
|
|
7720
7748
|
return { memories: [], usedBudget, reranked: false, candidateCount: 0 };
|
|
7721
7749
|
}
|
|
7722
7750
|
const needsChunkEmbedding = types.includes("chunk") && ctx.storageCtx;
|
|
@@ -7750,6 +7778,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
7750
7778
|
// empty ranking instead (mirrors safeCountVault's fail-soft posture).
|
|
7751
7779
|
safeLane(
|
|
7752
7780
|
"graph",
|
|
7781
|
+
() => graphLaneFailed = true,
|
|
7753
7782
|
() => buildGraphLaneRanking(query, ctx, flags.traverse, {
|
|
7754
7783
|
...options.maxHops !== void 0 && { maxHops: options.maxHops },
|
|
7755
7784
|
...options.entityFanout !== void 0 && { entityFanout: options.entityFanout },
|
|
@@ -7758,12 +7787,19 @@ async function recall(query, ctx, options = {}) {
|
|
|
7758
7787
|
...graphRefiner && { refineNeighbors: graphRefiner }
|
|
7759
7788
|
})
|
|
7760
7789
|
),
|
|
7761
|
-
wantsTemporal ? safeLane(
|
|
7790
|
+
wantsTemporal ? safeLane(
|
|
7791
|
+
"temporal",
|
|
7792
|
+
() => temporalLaneFailed = true,
|
|
7793
|
+
() => buildTemporalLaneRanking(query, ctx.vaultCtx, options.now)
|
|
7794
|
+
) : Promise.resolve([])
|
|
7762
7795
|
]);
|
|
7763
7796
|
prepMs = nowMs() - prepStart;
|
|
7797
|
+
graphLaneCount = entityRanking.length;
|
|
7798
|
+
temporalLaneCount = temporalRanking.length;
|
|
7764
7799
|
if (types.includes("fact") && ctx.vaultCtx && ctx.vaultCache) {
|
|
7765
7800
|
const factStart = nowMs();
|
|
7766
7801
|
const vaultMinScore = options.minScore ?? DEFAULT_FACT_MIN_SCORE;
|
|
7802
|
+
factFloor = vaultMinScore;
|
|
7767
7803
|
const {
|
|
7768
7804
|
results,
|
|
7769
7805
|
vaultSize: size,
|
|
@@ -7843,6 +7879,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
7843
7879
|
if (types.includes("chunk") && ctx.storageCtx && queryEmbedding) {
|
|
7844
7880
|
const chunkStart = nowMs();
|
|
7845
7881
|
const chunkMinScore = options.minScore ?? DEFAULT_CHUNK_MIN_SCORE;
|
|
7882
|
+
chunkFloor = chunkMinScore;
|
|
7846
7883
|
const results = await searchChunksOp(ctx.storageCtx, queryEmbedding, {
|
|
7847
7884
|
limit: types.includes("fact") ? Math.max(limit * 2, 16) : limit,
|
|
7848
7885
|
minSimilarity: chunkMinScore,
|
|
@@ -7869,9 +7906,11 @@ async function recall(query, ctx, options = {}) {
|
|
|
7869
7906
|
memories2.sort((a, b) => b.score - a.score);
|
|
7870
7907
|
const candidateCount = factResults.length + chunkResults.length;
|
|
7871
7908
|
fuseMs = nowMs() - fuseStart;
|
|
7872
|
-
|
|
7909
|
+
const admitted = memories2.slice(0, limit);
|
|
7910
|
+
hitLimit = memories2.length > limit;
|
|
7911
|
+
emitDiagnostics(candidateCount, admitted);
|
|
7873
7912
|
return {
|
|
7874
|
-
memories:
|
|
7913
|
+
memories: admitted,
|
|
7875
7914
|
usedBudget,
|
|
7876
7915
|
reranked: didRerank,
|
|
7877
7916
|
candidateCount,
|
|
@@ -7901,12 +7940,16 @@ async function recall(query, ctx, options = {}) {
|
|
|
7901
7940
|
const ordered = [...byId.values()].sort((a, b) => b.score - a.score);
|
|
7902
7941
|
const selectWith = (suppressed2) => {
|
|
7903
7942
|
const out = [];
|
|
7943
|
+
let cut = false;
|
|
7904
7944
|
for (const m of ordered) {
|
|
7905
|
-
if (out.length >= limit) break;
|
|
7906
7945
|
if (m.kind === "chunk" && m.messageId && suppressed2.has(m.messageId)) continue;
|
|
7946
|
+
if (out.length >= limit) {
|
|
7947
|
+
cut = true;
|
|
7948
|
+
break;
|
|
7949
|
+
}
|
|
7907
7950
|
out.push(m);
|
|
7908
7951
|
}
|
|
7909
|
-
return out;
|
|
7952
|
+
return { out, cut };
|
|
7910
7953
|
};
|
|
7911
7954
|
const provenanceOf = (selected) => {
|
|
7912
7955
|
const s = /* @__PURE__ */ new Set();
|
|
@@ -7916,15 +7959,18 @@ async function recall(query, ctx, options = {}) {
|
|
|
7916
7959
|
return s;
|
|
7917
7960
|
};
|
|
7918
7961
|
let suppressed = /* @__PURE__ */ new Set();
|
|
7919
|
-
let
|
|
7962
|
+
let selection = selectWith(suppressed);
|
|
7963
|
+
let memories = selection.out;
|
|
7920
7964
|
for (let i = 0; i < ordered.length; i++) {
|
|
7921
7965
|
const next = provenanceOf(memories);
|
|
7922
7966
|
if (next.size === suppressed.size && [...next].every((id) => suppressed.has(id))) break;
|
|
7923
7967
|
suppressed = next;
|
|
7924
|
-
|
|
7968
|
+
selection = selectWith(suppressed);
|
|
7969
|
+
memories = selection.out;
|
|
7925
7970
|
}
|
|
7971
|
+
hitLimit = selection.cut;
|
|
7926
7972
|
fuseMs = nowMs() - fuseStart;
|
|
7927
|
-
emitDiagnostics(byId.size);
|
|
7973
|
+
emitDiagnostics(byId.size, memories);
|
|
7928
7974
|
return {
|
|
7929
7975
|
memories,
|
|
7930
7976
|
usedBudget,
|
|
@@ -8008,10 +8054,11 @@ async function safeCountVault(ctx) {
|
|
|
8008
8054
|
return void 0;
|
|
8009
8055
|
}
|
|
8010
8056
|
}
|
|
8011
|
-
async function safeLane(label, run) {
|
|
8057
|
+
async function safeLane(label, onFailure, run) {
|
|
8012
8058
|
try {
|
|
8013
8059
|
return await run();
|
|
8014
8060
|
} catch (err) {
|
|
8061
|
+
onFailure();
|
|
8015
8062
|
getLogger().warn(
|
|
8016
8063
|
`[memory/recall] ${label} lane failed; continuing without it: ${err instanceof Error ? err.message : String(err)}`
|
|
8017
8064
|
);
|
|
@@ -16385,6 +16432,7 @@ async function retain(content, ctx, options = {}) {
|
|
|
16385
16432
|
const threshold = options.autoMergeThreshold ?? DEFAULT_AUTO_MERGE_THRESHOLD;
|
|
16386
16433
|
const resolvedScope = options.scope ?? DEFAULT_SCOPE;
|
|
16387
16434
|
let supersedeTargetIds = [];
|
|
16435
|
+
let consolidationDecidedCreate = false;
|
|
16388
16436
|
let supersedeContent;
|
|
16389
16437
|
let prepared;
|
|
16390
16438
|
if (enableAutoMerge) {
|
|
@@ -16412,8 +16460,12 @@ async function retain(content, ctx, options = {}) {
|
|
|
16412
16460
|
const outcome = await tryConsolidate(trimmed, ctx, options, prepared);
|
|
16413
16461
|
if (outcome) {
|
|
16414
16462
|
if ("done" in outcome) return outcome.done;
|
|
16415
|
-
|
|
16416
|
-
|
|
16463
|
+
if ("create" in outcome) {
|
|
16464
|
+
consolidationDecidedCreate = true;
|
|
16465
|
+
} else {
|
|
16466
|
+
supersedeTargetIds = outcome.supersede;
|
|
16467
|
+
supersedeContent = outcome.content;
|
|
16468
|
+
}
|
|
16417
16469
|
}
|
|
16418
16470
|
}
|
|
16419
16471
|
if (supersedeTargetIds.length === 0) {
|
|
@@ -16463,7 +16515,14 @@ async function retain(content, ctx, options = {}) {
|
|
|
16463
16515
|
action: "merge",
|
|
16464
16516
|
memoryId: targetId,
|
|
16465
16517
|
targetId,
|
|
16466
|
-
proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1
|
|
16518
|
+
proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1,
|
|
16519
|
+
similarity: matches[0].similarity,
|
|
16520
|
+
// Stage 1 may have run and explicitly said `create`, and Stage 2
|
|
16521
|
+
// then found a strict-cosine match anyway. Reporting the decision
|
|
16522
|
+
// here is what makes that DISAGREEMENT visible — without it the
|
|
16523
|
+
// model's create silently vanished from the distribution whenever
|
|
16524
|
+
// the cosine stage won.
|
|
16525
|
+
...consolidationDecidedCreate && { consolidation: "create" }
|
|
16467
16526
|
};
|
|
16468
16527
|
}
|
|
16469
16528
|
await assertMergeTargetGoneOrThrow(ctx, targetId);
|
|
@@ -16476,12 +16535,18 @@ async function retain(content, ctx, options = {}) {
|
|
|
16476
16535
|
const embedding = reusableQueryEmbedding ?? await generateEmbedding(contentToWrite, ctx.embeddingOptions);
|
|
16477
16536
|
const embeddingModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
16478
16537
|
if (options.respectTombstones) {
|
|
16479
|
-
const
|
|
16538
|
+
const tombstone = await findTombstoneMatch(embedding, embeddingModel, resolvedScope, ctx, {
|
|
16480
16539
|
threshold,
|
|
16481
16540
|
folderId: options.folderId
|
|
16482
16541
|
});
|
|
16483
|
-
if (
|
|
16484
|
-
return {
|
|
16542
|
+
if (tombstone) {
|
|
16543
|
+
return {
|
|
16544
|
+
action: "suppressed",
|
|
16545
|
+
memoryId: tombstone.id,
|
|
16546
|
+
tombstoneId: tombstone.id,
|
|
16547
|
+
proofCount: 0,
|
|
16548
|
+
similarity: tombstone.similarity
|
|
16549
|
+
};
|
|
16485
16550
|
}
|
|
16486
16551
|
}
|
|
16487
16552
|
const createOpts = {
|
|
@@ -16548,7 +16613,8 @@ async function retain(content, ctx, options = {}) {
|
|
|
16548
16613
|
action: "supersede",
|
|
16549
16614
|
memoryId: created2.uniqueId,
|
|
16550
16615
|
targetId: primaryTargetId,
|
|
16551
|
-
proofCount: 1
|
|
16616
|
+
proofCount: 1,
|
|
16617
|
+
consolidation: "supersede"
|
|
16552
16618
|
};
|
|
16553
16619
|
}
|
|
16554
16620
|
notifyConsolidationFallback(
|
|
@@ -16562,7 +16628,8 @@ async function retain(content, ctx, options = {}) {
|
|
|
16562
16628
|
return {
|
|
16563
16629
|
action: "create",
|
|
16564
16630
|
memoryId: created.uniqueId,
|
|
16565
|
-
proofCount: 1
|
|
16631
|
+
proofCount: 1,
|
|
16632
|
+
...consolidationDecidedCreate && { consolidation: "create" }
|
|
16566
16633
|
};
|
|
16567
16634
|
}
|
|
16568
16635
|
function unionStrings(a, b) {
|
|
@@ -16592,7 +16659,7 @@ async function findTombstoneMatch(embedding, embeddingModel, scope, ctx, opts) {
|
|
|
16592
16659
|
bestId = row.uniqueId;
|
|
16593
16660
|
}
|
|
16594
16661
|
}
|
|
16595
|
-
return bestId;
|
|
16662
|
+
return bestId === null ? null : { id: bestId, similarity: bestSim };
|
|
16596
16663
|
}
|
|
16597
16664
|
function pickEventTimeUpdate(existing, incoming) {
|
|
16598
16665
|
if (incoming === void 0 || incoming === null) return void 0;
|
|
@@ -16634,7 +16701,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
16634
16701
|
}));
|
|
16635
16702
|
const { consolidateMemory: doConsolidate } = await Promise.resolve().then(() => (init_consolidate(), consolidate_exports));
|
|
16636
16703
|
const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
|
|
16637
|
-
if (decision.action === "create") return null;
|
|
16704
|
+
if (decision.action === "create") return decision.fallbackReason ? null : { create: true };
|
|
16638
16705
|
if (decision.action === "supersede" && decision.content) {
|
|
16639
16706
|
const requestedIds = decision.targetIds?.length ? decision.targetIds : decision.targetId ? [decision.targetId] : [];
|
|
16640
16707
|
if (requestedIds.length === 0) return null;
|
|
@@ -16693,7 +16760,8 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
16693
16760
|
action: "merge",
|
|
16694
16761
|
memoryId: decision.targetId,
|
|
16695
16762
|
targetId: decision.targetId,
|
|
16696
|
-
proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1
|
|
16763
|
+
proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1,
|
|
16764
|
+
consolidation: "noop"
|
|
16697
16765
|
}
|
|
16698
16766
|
};
|
|
16699
16767
|
}
|
|
@@ -16746,7 +16814,8 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
16746
16814
|
action: "update",
|
|
16747
16815
|
memoryId: decision.targetId,
|
|
16748
16816
|
targetId: decision.targetId,
|
|
16749
|
-
proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1
|
|
16817
|
+
proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1,
|
|
16818
|
+
consolidation: "update"
|
|
16750
16819
|
}
|
|
16751
16820
|
};
|
|
16752
16821
|
}
|
|
@@ -16888,6 +16957,11 @@ Extract durable user facts.`,
|
|
|
16888
16957
|
fallbackSourceId,
|
|
16889
16958
|
options.userIdentity ?? []
|
|
16890
16959
|
);
|
|
16960
|
+
const rawCandidates = parsed.candidates;
|
|
16961
|
+
options.onCandidatesParsed?.({
|
|
16962
|
+
rawCount: Array.isArray(rawCandidates) ? rawCandidates.length : 0,
|
|
16963
|
+
validCount: candidates.length
|
|
16964
|
+
});
|
|
16891
16965
|
if (!redactor) return candidates;
|
|
16892
16966
|
const restored = restoreCandidates(candidates, redactor, options.userIdentity ?? []);
|
|
16893
16967
|
if (candidates.length > 0 && restored.length === 0) {
|
|
@@ -16924,8 +16998,12 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
16924
16998
|
let exhaustedEmpty = false;
|
|
16925
16999
|
let exhaustedFailure;
|
|
16926
17000
|
let droppedAfterRedaction = false;
|
|
17001
|
+
let rawCandidateCount = 0;
|
|
17002
|
+
let validCandidateCount = 0;
|
|
16927
17003
|
const callerOnExhaustedEmpty = options.extract.onExhaustedEmpty;
|
|
16928
17004
|
const callerOnCandidatesDropped = options.extract.onCandidatesDropped;
|
|
17005
|
+
const callerOnCandidatesParsed = options.extract.onCandidatesParsed;
|
|
17006
|
+
const tExtract = Date.now();
|
|
16929
17007
|
const candidates = await extractFacts(messages, {
|
|
16930
17008
|
...options.extract,
|
|
16931
17009
|
onExhaustedEmpty: (failure) => {
|
|
@@ -16936,8 +17014,14 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
16936
17014
|
onCandidatesDropped: () => {
|
|
16937
17015
|
droppedAfterRedaction = true;
|
|
16938
17016
|
callerOnCandidatesDropped?.();
|
|
17017
|
+
},
|
|
17018
|
+
onCandidatesParsed: (stats) => {
|
|
17019
|
+
rawCandidateCount = stats.rawCount;
|
|
17020
|
+
validCandidateCount = stats.validCount;
|
|
17021
|
+
callerOnCandidatesParsed?.(stats);
|
|
16939
17022
|
}
|
|
16940
17023
|
});
|
|
17024
|
+
const extractMs = Date.now() - tExtract;
|
|
16941
17025
|
const filtered = candidates.filter((c) => c.confidence >= minConfidence);
|
|
16942
17026
|
const log = getLogger();
|
|
16943
17027
|
const screened = screenCandidatesForInjection(filtered);
|
|
@@ -16985,6 +17069,7 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
16985
17069
|
const results = [];
|
|
16986
17070
|
const quarantinedInfo = [];
|
|
16987
17071
|
let failedWrites = 0;
|
|
17072
|
+
const tRetain = Date.now();
|
|
16988
17073
|
for (const { candidate, isQuarantined, reason, signature } of toRetain) {
|
|
16989
17074
|
try {
|
|
16990
17075
|
const result = await retain(candidate.content, retainCtx, {
|
|
@@ -17051,6 +17136,21 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
17051
17136
|
failedCount: failedWrites,
|
|
17052
17137
|
outcome,
|
|
17053
17138
|
quarantined: quarantinedInfo,
|
|
17139
|
+
funnel: {
|
|
17140
|
+
rawCandidateCount,
|
|
17141
|
+
validCandidateCount,
|
|
17142
|
+
afterRedactionCount: candidates.length,
|
|
17143
|
+
aboveConfidenceCount: filtered.length,
|
|
17144
|
+
// The PERSISTED quarantines (`quarantinedInfo`), not the screened list: a
|
|
17145
|
+
// screened candidate whose retain() throws is counted in `failedCount`,
|
|
17146
|
+
// and counting it here too would double it and break the identity below.
|
|
17147
|
+
// This also keeps the count equal to `quarantined.length` on the result.
|
|
17148
|
+
quarantinedCount: quarantinedInfo.length,
|
|
17149
|
+
retainedCount: results.length,
|
|
17150
|
+
failedCount: failedWrites
|
|
17151
|
+
},
|
|
17152
|
+
timings: { extractMs, retainMs: Date.now() - tRetain },
|
|
17153
|
+
model: options.extract.model ?? DEFAULT_EXTRACTION_MODEL,
|
|
17054
17154
|
// Only meaningful alongside `outcome: "empty-after-retry"`. Returned as well
|
|
17055
17155
|
// as pushed through the callback so a consumer that only inspects the result
|
|
17056
17156
|
// (rather than wiring a hook) can still report WHY.
|
|
@@ -17306,27 +17406,23 @@ function createAutoExtractor(options) {
|
|
|
17306
17406
|
const t0 = Date.now();
|
|
17307
17407
|
void (async () => {
|
|
17308
17408
|
try {
|
|
17309
|
-
const { candidates, results, failedCount, outcome, failure } = await extractAndRetain(
|
|
17310
|
-
|
|
17311
|
-
|
|
17312
|
-
{
|
|
17313
|
-
|
|
17314
|
-
|
|
17315
|
-
|
|
17316
|
-
|
|
17317
|
-
|
|
17318
|
-
|
|
17319
|
-
|
|
17320
|
-
|
|
17321
|
-
|
|
17322
|
-
|
|
17323
|
-
|
|
17324
|
-
},
|
|
17325
|
-
...options.onMemoryQuarantined && {
|
|
17326
|
-
onQuarantined: (info) => options.onMemoryQuarantined?.({ ...info, conversationId })
|
|
17327
|
-
}
|
|
17409
|
+
const { candidates, results, failedCount, outcome, failure, funnel, timings, model } = await extractAndRetain(window2, retainCtx, {
|
|
17410
|
+
extract,
|
|
17411
|
+
...options.minConfidence !== void 0 && { minConfidence: options.minConfidence },
|
|
17412
|
+
...options.entityCtx !== void 0 && { entityCtx: options.entityCtx },
|
|
17413
|
+
...options.scope !== void 0 && { scope: options.scope },
|
|
17414
|
+
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
17415
|
+
...consolidateOptions !== void 0 && { consolidateOptions },
|
|
17416
|
+
...injectionClassifierOptions !== void 0 && {
|
|
17417
|
+
injectionClassifier: injectionClassifierOptions
|
|
17418
|
+
},
|
|
17419
|
+
...options.onCandidateFailed && {
|
|
17420
|
+
onCandidateFailed: (candidate, error) => options.onCandidateFailed?.({ candidate, error, conversationId })
|
|
17421
|
+
},
|
|
17422
|
+
...options.onMemoryQuarantined && {
|
|
17423
|
+
onQuarantined: (info) => options.onMemoryQuarantined?.({ ...info, conversationId })
|
|
17328
17424
|
}
|
|
17329
|
-
);
|
|
17425
|
+
});
|
|
17330
17426
|
if (outcome !== "empty-after-retry") {
|
|
17331
17427
|
const advancedTo = window2[window2.length - 1].id;
|
|
17332
17428
|
stateFor(conversationId).watermark = advancedTo;
|
|
@@ -17347,6 +17443,9 @@ function createAutoExtractor(options) {
|
|
|
17347
17443
|
durationMs: Date.now() - t0,
|
|
17348
17444
|
conversationId,
|
|
17349
17445
|
outcome,
|
|
17446
|
+
funnel,
|
|
17447
|
+
timings,
|
|
17448
|
+
model,
|
|
17350
17449
|
// Only set alongside `outcome: "empty-after-retry"`. Spread so the key
|
|
17351
17450
|
// is absent rather than explicitly undefined on a healthy turn —
|
|
17352
17451
|
// analytics backends store an explicit undefined as a real value.
|