@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
package/dist/expo/index.mjs
CHANGED
|
@@ -133,7 +133,7 @@ import {
|
|
|
133
133
|
upsertMessageOp,
|
|
134
134
|
useEncryption,
|
|
135
135
|
vaultMemoryToStored
|
|
136
|
-
} from "./chunk-
|
|
136
|
+
} from "./chunk-CIMZZ7GQ.mjs";
|
|
137
137
|
import {
|
|
138
138
|
PII_PATTERNS,
|
|
139
139
|
PiiRedactor,
|
|
@@ -6646,6 +6646,7 @@ async function retain(content, ctx, options = {}) {
|
|
|
6646
6646
|
const threshold = options.autoMergeThreshold ?? DEFAULT_AUTO_MERGE_THRESHOLD;
|
|
6647
6647
|
const resolvedScope = options.scope ?? DEFAULT_SCOPE;
|
|
6648
6648
|
let supersedeTargetIds = [];
|
|
6649
|
+
let consolidationDecidedCreate = false;
|
|
6649
6650
|
let supersedeContent;
|
|
6650
6651
|
let prepared;
|
|
6651
6652
|
if (enableAutoMerge) {
|
|
@@ -6673,8 +6674,12 @@ async function retain(content, ctx, options = {}) {
|
|
|
6673
6674
|
const outcome = await tryConsolidate(trimmed, ctx, options, prepared);
|
|
6674
6675
|
if (outcome) {
|
|
6675
6676
|
if ("done" in outcome) return outcome.done;
|
|
6676
|
-
|
|
6677
|
-
|
|
6677
|
+
if ("create" in outcome) {
|
|
6678
|
+
consolidationDecidedCreate = true;
|
|
6679
|
+
} else {
|
|
6680
|
+
supersedeTargetIds = outcome.supersede;
|
|
6681
|
+
supersedeContent = outcome.content;
|
|
6682
|
+
}
|
|
6678
6683
|
}
|
|
6679
6684
|
}
|
|
6680
6685
|
if (supersedeTargetIds.length === 0) {
|
|
@@ -6724,7 +6729,14 @@ async function retain(content, ctx, options = {}) {
|
|
|
6724
6729
|
action: "merge",
|
|
6725
6730
|
memoryId: targetId,
|
|
6726
6731
|
targetId,
|
|
6727
|
-
proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1
|
|
6732
|
+
proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1,
|
|
6733
|
+
similarity: matches[0].similarity,
|
|
6734
|
+
// Stage 1 may have run and explicitly said `create`, and Stage 2
|
|
6735
|
+
// then found a strict-cosine match anyway. Reporting the decision
|
|
6736
|
+
// here is what makes that DISAGREEMENT visible — without it the
|
|
6737
|
+
// model's create silently vanished from the distribution whenever
|
|
6738
|
+
// the cosine stage won.
|
|
6739
|
+
...consolidationDecidedCreate && { consolidation: "create" }
|
|
6728
6740
|
};
|
|
6729
6741
|
}
|
|
6730
6742
|
await assertMergeTargetGoneOrThrow(ctx, targetId);
|
|
@@ -6737,12 +6749,18 @@ async function retain(content, ctx, options = {}) {
|
|
|
6737
6749
|
const embedding = reusableQueryEmbedding ?? await generateEmbedding(contentToWrite, ctx.embeddingOptions);
|
|
6738
6750
|
const embeddingModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
6739
6751
|
if (options.respectTombstones) {
|
|
6740
|
-
const
|
|
6752
|
+
const tombstone = await findTombstoneMatch(embedding, embeddingModel, resolvedScope, ctx, {
|
|
6741
6753
|
threshold,
|
|
6742
6754
|
folderId: options.folderId
|
|
6743
6755
|
});
|
|
6744
|
-
if (
|
|
6745
|
-
return {
|
|
6756
|
+
if (tombstone) {
|
|
6757
|
+
return {
|
|
6758
|
+
action: "suppressed",
|
|
6759
|
+
memoryId: tombstone.id,
|
|
6760
|
+
tombstoneId: tombstone.id,
|
|
6761
|
+
proofCount: 0,
|
|
6762
|
+
similarity: tombstone.similarity
|
|
6763
|
+
};
|
|
6746
6764
|
}
|
|
6747
6765
|
}
|
|
6748
6766
|
const createOpts = {
|
|
@@ -6809,7 +6827,8 @@ async function retain(content, ctx, options = {}) {
|
|
|
6809
6827
|
action: "supersede",
|
|
6810
6828
|
memoryId: created2.uniqueId,
|
|
6811
6829
|
targetId: primaryTargetId,
|
|
6812
|
-
proofCount: 1
|
|
6830
|
+
proofCount: 1,
|
|
6831
|
+
consolidation: "supersede"
|
|
6813
6832
|
};
|
|
6814
6833
|
}
|
|
6815
6834
|
notifyConsolidationFallback(
|
|
@@ -6823,7 +6842,8 @@ async function retain(content, ctx, options = {}) {
|
|
|
6823
6842
|
return {
|
|
6824
6843
|
action: "create",
|
|
6825
6844
|
memoryId: created.uniqueId,
|
|
6826
|
-
proofCount: 1
|
|
6845
|
+
proofCount: 1,
|
|
6846
|
+
...consolidationDecidedCreate && { consolidation: "create" }
|
|
6827
6847
|
};
|
|
6828
6848
|
}
|
|
6829
6849
|
function unionStrings(a, b) {
|
|
@@ -6853,7 +6873,7 @@ async function findTombstoneMatch(embedding, embeddingModel, scope, ctx, opts) {
|
|
|
6853
6873
|
bestId = row.uniqueId;
|
|
6854
6874
|
}
|
|
6855
6875
|
}
|
|
6856
|
-
return bestId;
|
|
6876
|
+
return bestId === null ? null : { id: bestId, similarity: bestSim };
|
|
6857
6877
|
}
|
|
6858
6878
|
function pickEventTimeUpdate(existing, incoming) {
|
|
6859
6879
|
if (incoming === void 0 || incoming === null) return void 0;
|
|
@@ -6895,7 +6915,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
6895
6915
|
}));
|
|
6896
6916
|
const { consolidateMemory: doConsolidate } = await import("./consolidate-XBYKAFKT.mjs");
|
|
6897
6917
|
const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
|
|
6898
|
-
if (decision.action === "create") return null;
|
|
6918
|
+
if (decision.action === "create") return decision.fallbackReason ? null : { create: true };
|
|
6899
6919
|
if (decision.action === "supersede" && decision.content) {
|
|
6900
6920
|
const requestedIds = decision.targetIds?.length ? decision.targetIds : decision.targetId ? [decision.targetId] : [];
|
|
6901
6921
|
if (requestedIds.length === 0) return null;
|
|
@@ -6954,7 +6974,8 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
6954
6974
|
action: "merge",
|
|
6955
6975
|
memoryId: decision.targetId,
|
|
6956
6976
|
targetId: decision.targetId,
|
|
6957
|
-
proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1
|
|
6977
|
+
proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1,
|
|
6978
|
+
consolidation: "noop"
|
|
6958
6979
|
}
|
|
6959
6980
|
};
|
|
6960
6981
|
}
|
|
@@ -7007,7 +7028,8 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
7007
7028
|
action: "update",
|
|
7008
7029
|
memoryId: decision.targetId,
|
|
7009
7030
|
targetId: decision.targetId,
|
|
7010
|
-
proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1
|
|
7031
|
+
proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1,
|
|
7032
|
+
consolidation: "update"
|
|
7011
7033
|
}
|
|
7012
7034
|
};
|
|
7013
7035
|
}
|
|
@@ -7149,6 +7171,11 @@ Extract durable user facts.`,
|
|
|
7149
7171
|
fallbackSourceId,
|
|
7150
7172
|
options.userIdentity ?? []
|
|
7151
7173
|
);
|
|
7174
|
+
const rawCandidates = parsed.candidates;
|
|
7175
|
+
options.onCandidatesParsed?.({
|
|
7176
|
+
rawCount: Array.isArray(rawCandidates) ? rawCandidates.length : 0,
|
|
7177
|
+
validCount: candidates.length
|
|
7178
|
+
});
|
|
7152
7179
|
if (!redactor) return candidates;
|
|
7153
7180
|
const restored = restoreCandidates(candidates, redactor, options.userIdentity ?? []);
|
|
7154
7181
|
if (candidates.length > 0 && restored.length === 0) {
|
|
@@ -7185,8 +7212,12 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
7185
7212
|
let exhaustedEmpty = false;
|
|
7186
7213
|
let exhaustedFailure;
|
|
7187
7214
|
let droppedAfterRedaction = false;
|
|
7215
|
+
let rawCandidateCount = 0;
|
|
7216
|
+
let validCandidateCount = 0;
|
|
7188
7217
|
const callerOnExhaustedEmpty = options.extract.onExhaustedEmpty;
|
|
7189
7218
|
const callerOnCandidatesDropped = options.extract.onCandidatesDropped;
|
|
7219
|
+
const callerOnCandidatesParsed = options.extract.onCandidatesParsed;
|
|
7220
|
+
const tExtract = Date.now();
|
|
7190
7221
|
const candidates = await extractFacts(messages, {
|
|
7191
7222
|
...options.extract,
|
|
7192
7223
|
onExhaustedEmpty: (failure) => {
|
|
@@ -7197,8 +7228,14 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
7197
7228
|
onCandidatesDropped: () => {
|
|
7198
7229
|
droppedAfterRedaction = true;
|
|
7199
7230
|
callerOnCandidatesDropped?.();
|
|
7231
|
+
},
|
|
7232
|
+
onCandidatesParsed: (stats) => {
|
|
7233
|
+
rawCandidateCount = stats.rawCount;
|
|
7234
|
+
validCandidateCount = stats.validCount;
|
|
7235
|
+
callerOnCandidatesParsed?.(stats);
|
|
7200
7236
|
}
|
|
7201
7237
|
});
|
|
7238
|
+
const extractMs = Date.now() - tExtract;
|
|
7202
7239
|
const filtered = candidates.filter((c) => c.confidence >= minConfidence);
|
|
7203
7240
|
const log = getLogger();
|
|
7204
7241
|
const screened = screenCandidatesForInjection(filtered);
|
|
@@ -7246,6 +7283,7 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
7246
7283
|
const results = [];
|
|
7247
7284
|
const quarantinedInfo = [];
|
|
7248
7285
|
let failedWrites = 0;
|
|
7286
|
+
const tRetain = Date.now();
|
|
7249
7287
|
for (const { candidate, isQuarantined, reason, signature } of toRetain) {
|
|
7250
7288
|
try {
|
|
7251
7289
|
const result = await retain(candidate.content, retainCtx, {
|
|
@@ -7312,6 +7350,21 @@ async function extractAndRetain(messages, retainCtx, options) {
|
|
|
7312
7350
|
failedCount: failedWrites,
|
|
7313
7351
|
outcome,
|
|
7314
7352
|
quarantined: quarantinedInfo,
|
|
7353
|
+
funnel: {
|
|
7354
|
+
rawCandidateCount,
|
|
7355
|
+
validCandidateCount,
|
|
7356
|
+
afterRedactionCount: candidates.length,
|
|
7357
|
+
aboveConfidenceCount: filtered.length,
|
|
7358
|
+
// The PERSISTED quarantines (`quarantinedInfo`), not the screened list: a
|
|
7359
|
+
// screened candidate whose retain() throws is counted in `failedCount`,
|
|
7360
|
+
// and counting it here too would double it and break the identity below.
|
|
7361
|
+
// This also keeps the count equal to `quarantined.length` on the result.
|
|
7362
|
+
quarantinedCount: quarantinedInfo.length,
|
|
7363
|
+
retainedCount: results.length,
|
|
7364
|
+
failedCount: failedWrites
|
|
7365
|
+
},
|
|
7366
|
+
timings: { extractMs, retainMs: Date.now() - tRetain },
|
|
7367
|
+
model: options.extract.model ?? DEFAULT_EXTRACTION_MODEL,
|
|
7315
7368
|
// Only meaningful alongside `outcome: "empty-after-retry"`. Returned as well
|
|
7316
7369
|
// as pushed through the callback so a consumer that only inspects the result
|
|
7317
7370
|
// (rather than wiring a hook) can still report WHY.
|
|
@@ -7565,27 +7618,23 @@ function createAutoExtractor(options) {
|
|
|
7565
7618
|
const t0 = Date.now();
|
|
7566
7619
|
void (async () => {
|
|
7567
7620
|
try {
|
|
7568
|
-
const { candidates, results, failedCount, outcome, failure } = await extractAndRetain(
|
|
7569
|
-
|
|
7570
|
-
|
|
7571
|
-
{
|
|
7572
|
-
|
|
7573
|
-
|
|
7574
|
-
|
|
7575
|
-
|
|
7576
|
-
|
|
7577
|
-
|
|
7578
|
-
|
|
7579
|
-
|
|
7580
|
-
|
|
7581
|
-
|
|
7582
|
-
|
|
7583
|
-
},
|
|
7584
|
-
...options.onMemoryQuarantined && {
|
|
7585
|
-
onQuarantined: (info) => options.onMemoryQuarantined?.({ ...info, conversationId })
|
|
7586
|
-
}
|
|
7621
|
+
const { candidates, results, failedCount, outcome, failure, funnel, timings, model } = await extractAndRetain(window, retainCtx, {
|
|
7622
|
+
extract,
|
|
7623
|
+
...options.minConfidence !== void 0 && { minConfidence: options.minConfidence },
|
|
7624
|
+
...options.entityCtx !== void 0 && { entityCtx: options.entityCtx },
|
|
7625
|
+
...options.scope !== void 0 && { scope: options.scope },
|
|
7626
|
+
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
7627
|
+
...consolidateOptions !== void 0 && { consolidateOptions },
|
|
7628
|
+
...injectionClassifierOptions !== void 0 && {
|
|
7629
|
+
injectionClassifier: injectionClassifierOptions
|
|
7630
|
+
},
|
|
7631
|
+
...options.onCandidateFailed && {
|
|
7632
|
+
onCandidateFailed: (candidate, error) => options.onCandidateFailed?.({ candidate, error, conversationId })
|
|
7633
|
+
},
|
|
7634
|
+
...options.onMemoryQuarantined && {
|
|
7635
|
+
onQuarantined: (info) => options.onMemoryQuarantined?.({ ...info, conversationId })
|
|
7587
7636
|
}
|
|
7588
|
-
);
|
|
7637
|
+
});
|
|
7589
7638
|
if (outcome !== "empty-after-retry") {
|
|
7590
7639
|
const advancedTo = window[window.length - 1].id;
|
|
7591
7640
|
stateFor(conversationId).watermark = advancedTo;
|
|
@@ -7606,6 +7655,9 @@ function createAutoExtractor(options) {
|
|
|
7606
7655
|
durationMs: Date.now() - t0,
|
|
7607
7656
|
conversationId,
|
|
7608
7657
|
outcome,
|
|
7658
|
+
funnel,
|
|
7659
|
+
timings,
|
|
7660
|
+
model,
|
|
7609
7661
|
// Only set alongside `outcome: "empty-after-retry"`. Spread so the key
|
|
7610
7662
|
// is absent rather than explicitly undefined on a healthy turn —
|
|
7611
7663
|
// analytics backends store an explicit undefined as a real value.
|
|
@@ -7196,7 +7196,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
7196
7196
|
subQueries = decomp.subQueries;
|
|
7197
7197
|
}
|
|
7198
7198
|
}
|
|
7199
|
-
const { recall: recall2 } = await import("./recall-
|
|
7199
|
+
const { recall: recall2 } = await import("./recall-7Q3V337H.mjs");
|
|
7200
7200
|
let recallDegraded = [];
|
|
7201
7201
|
const result = await recall2(
|
|
7202
7202
|
query,
|
|
@@ -7787,7 +7787,22 @@ async function recall(query, ctx, options = {}) {
|
|
|
7787
7787
|
let factLaneRankedOnCosine = false;
|
|
7788
7788
|
let decryptLastRan;
|
|
7789
7789
|
let vaultRowsDecrypted;
|
|
7790
|
-
|
|
7790
|
+
let graphLaneCount = 0;
|
|
7791
|
+
let temporalLaneCount = 0;
|
|
7792
|
+
let graphLaneFailed = false;
|
|
7793
|
+
let temporalLaneFailed = false;
|
|
7794
|
+
let hitLimit = false;
|
|
7795
|
+
let factFloor = -1;
|
|
7796
|
+
let chunkFloor = -1;
|
|
7797
|
+
const emptyReasonFor = (admitted, laneRan) => {
|
|
7798
|
+
if (admitted > 0) return "";
|
|
7799
|
+
if (!query || typeof query !== "string" || query.trim().length === 0) return "empty-query";
|
|
7800
|
+
if (!laneRan) return "no-lanes";
|
|
7801
|
+
const chunkLaneCouldAnswer = types.includes("chunk") && !!ctx.storageCtx;
|
|
7802
|
+
if (vaultSize === 0 && !chunkLaneCouldAnswer) return "vault-empty";
|
|
7803
|
+
return "no-candidates";
|
|
7804
|
+
};
|
|
7805
|
+
const emitDiagnostics = (candidateCount, admitted) => {
|
|
7791
7806
|
const cb = options.onDiagnostics;
|
|
7792
7807
|
if (!cb) return;
|
|
7793
7808
|
const degraded = [];
|
|
@@ -7798,6 +7813,11 @@ async function recall(query, ctx, options = {}) {
|
|
|
7798
7813
|
degraded.push("decompose-moved");
|
|
7799
7814
|
}
|
|
7800
7815
|
if (embeddingsUnavailable) degraded.push("embeddings-unavailable");
|
|
7816
|
+
if (graphLaneFailed) degraded.push("graph-lane-failed");
|
|
7817
|
+
if (temporalLaneFailed) degraded.push("temporal-lane-failed");
|
|
7818
|
+
const laneRan = types.includes("fact") && !!ctx.vaultCtx && !!ctx.vaultCache || types.includes("chunk") && !!ctx.storageCtx;
|
|
7819
|
+
const scores = admitted.map((m) => m.score);
|
|
7820
|
+
const minScoreApplied = factResults.length > 0 ? factFloor : chunkResults.length > 0 ? chunkFloor : factFloor >= 0 ? factFloor : chunkFloor;
|
|
7801
7821
|
const diagnostics = {
|
|
7802
7822
|
usedBudget,
|
|
7803
7823
|
reranked: didRerank,
|
|
@@ -7808,6 +7828,14 @@ async function recall(query, ctx, options = {}) {
|
|
|
7808
7828
|
...vaultRowsEmbedded !== void 0 && { vaultRowsEmbedded },
|
|
7809
7829
|
factCount: factResults.length,
|
|
7810
7830
|
chunkCount: chunkResults.length,
|
|
7831
|
+
admittedCount: admitted.length,
|
|
7832
|
+
topScore: scores.length > 0 ? Math.max(...scores) : -1,
|
|
7833
|
+
lowestAdmittedScore: scores.length > 0 ? Math.min(...scores) : -1,
|
|
7834
|
+
minScoreApplied,
|
|
7835
|
+
truncated: hitLimit,
|
|
7836
|
+
graphLaneCount,
|
|
7837
|
+
temporalLaneCount,
|
|
7838
|
+
emptyReason: emptyReasonFor(admitted.length, laneRan),
|
|
7811
7839
|
timings: {
|
|
7812
7840
|
total: nowMs2() - t0,
|
|
7813
7841
|
prep: prepMs,
|
|
@@ -7825,7 +7853,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
7825
7853
|
}
|
|
7826
7854
|
};
|
|
7827
7855
|
if (!query || typeof query !== "string" || query.trim().length === 0) {
|
|
7828
|
-
emitDiagnostics(0);
|
|
7856
|
+
emitDiagnostics(0, []);
|
|
7829
7857
|
return { memories: [], usedBudget, reranked: false, candidateCount: 0 };
|
|
7830
7858
|
}
|
|
7831
7859
|
const needsChunkEmbedding = types.includes("chunk") && ctx.storageCtx;
|
|
@@ -7859,6 +7887,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
7859
7887
|
// empty ranking instead (mirrors safeCountVault's fail-soft posture).
|
|
7860
7888
|
safeLane(
|
|
7861
7889
|
"graph",
|
|
7890
|
+
() => graphLaneFailed = true,
|
|
7862
7891
|
() => buildGraphLaneRanking(query, ctx, flags.traverse, {
|
|
7863
7892
|
...options.maxHops !== void 0 && { maxHops: options.maxHops },
|
|
7864
7893
|
...options.entityFanout !== void 0 && { entityFanout: options.entityFanout },
|
|
@@ -7867,12 +7896,19 @@ async function recall(query, ctx, options = {}) {
|
|
|
7867
7896
|
...graphRefiner && { refineNeighbors: graphRefiner }
|
|
7868
7897
|
})
|
|
7869
7898
|
),
|
|
7870
|
-
wantsTemporal ? safeLane(
|
|
7899
|
+
wantsTemporal ? safeLane(
|
|
7900
|
+
"temporal",
|
|
7901
|
+
() => temporalLaneFailed = true,
|
|
7902
|
+
() => buildTemporalLaneRanking(query, ctx.vaultCtx, options.now)
|
|
7903
|
+
) : Promise.resolve([])
|
|
7871
7904
|
]);
|
|
7872
7905
|
prepMs = nowMs2() - prepStart;
|
|
7906
|
+
graphLaneCount = entityRanking.length;
|
|
7907
|
+
temporalLaneCount = temporalRanking.length;
|
|
7873
7908
|
if (types.includes("fact") && ctx.vaultCtx && ctx.vaultCache) {
|
|
7874
7909
|
const factStart = nowMs2();
|
|
7875
7910
|
const vaultMinScore = options.minScore ?? DEFAULT_FACT_MIN_SCORE;
|
|
7911
|
+
factFloor = vaultMinScore;
|
|
7876
7912
|
const {
|
|
7877
7913
|
results,
|
|
7878
7914
|
vaultSize: size,
|
|
@@ -7952,6 +7988,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
7952
7988
|
if (types.includes("chunk") && ctx.storageCtx && queryEmbedding) {
|
|
7953
7989
|
const chunkStart = nowMs2();
|
|
7954
7990
|
const chunkMinScore = options.minScore ?? DEFAULT_CHUNK_MIN_SCORE;
|
|
7991
|
+
chunkFloor = chunkMinScore;
|
|
7955
7992
|
const results = await searchChunksOp(ctx.storageCtx, queryEmbedding, {
|
|
7956
7993
|
limit: types.includes("fact") ? Math.max(limit * 2, 16) : limit,
|
|
7957
7994
|
minSimilarity: chunkMinScore,
|
|
@@ -7978,9 +8015,11 @@ async function recall(query, ctx, options = {}) {
|
|
|
7978
8015
|
memories2.sort((a, b) => b.score - a.score);
|
|
7979
8016
|
const candidateCount = factResults.length + chunkResults.length;
|
|
7980
8017
|
fuseMs = nowMs2() - fuseStart;
|
|
7981
|
-
|
|
8018
|
+
const admitted = memories2.slice(0, limit);
|
|
8019
|
+
hitLimit = memories2.length > limit;
|
|
8020
|
+
emitDiagnostics(candidateCount, admitted);
|
|
7982
8021
|
return {
|
|
7983
|
-
memories:
|
|
8022
|
+
memories: admitted,
|
|
7984
8023
|
usedBudget,
|
|
7985
8024
|
reranked: didRerank,
|
|
7986
8025
|
candidateCount,
|
|
@@ -8010,12 +8049,16 @@ async function recall(query, ctx, options = {}) {
|
|
|
8010
8049
|
const ordered = [...byId.values()].sort((a, b) => b.score - a.score);
|
|
8011
8050
|
const selectWith = (suppressed2) => {
|
|
8012
8051
|
const out = [];
|
|
8052
|
+
let cut = false;
|
|
8013
8053
|
for (const m of ordered) {
|
|
8014
|
-
if (out.length >= limit) break;
|
|
8015
8054
|
if (m.kind === "chunk" && m.messageId && suppressed2.has(m.messageId)) continue;
|
|
8055
|
+
if (out.length >= limit) {
|
|
8056
|
+
cut = true;
|
|
8057
|
+
break;
|
|
8058
|
+
}
|
|
8016
8059
|
out.push(m);
|
|
8017
8060
|
}
|
|
8018
|
-
return out;
|
|
8061
|
+
return { out, cut };
|
|
8019
8062
|
};
|
|
8020
8063
|
const provenanceOf = (selected) => {
|
|
8021
8064
|
const s = /* @__PURE__ */ new Set();
|
|
@@ -8025,15 +8068,18 @@ async function recall(query, ctx, options = {}) {
|
|
|
8025
8068
|
return s;
|
|
8026
8069
|
};
|
|
8027
8070
|
let suppressed = /* @__PURE__ */ new Set();
|
|
8028
|
-
let
|
|
8071
|
+
let selection = selectWith(suppressed);
|
|
8072
|
+
let memories = selection.out;
|
|
8029
8073
|
for (let i = 0; i < ordered.length; i++) {
|
|
8030
8074
|
const next = provenanceOf(memories);
|
|
8031
8075
|
if (next.size === suppressed.size && [...next].every((id) => suppressed.has(id))) break;
|
|
8032
8076
|
suppressed = next;
|
|
8033
|
-
|
|
8077
|
+
selection = selectWith(suppressed);
|
|
8078
|
+
memories = selection.out;
|
|
8034
8079
|
}
|
|
8080
|
+
hitLimit = selection.cut;
|
|
8035
8081
|
fuseMs = nowMs2() - fuseStart;
|
|
8036
|
-
emitDiagnostics(byId.size);
|
|
8082
|
+
emitDiagnostics(byId.size, memories);
|
|
8037
8083
|
return {
|
|
8038
8084
|
memories,
|
|
8039
8085
|
usedBudget,
|
|
@@ -8117,10 +8163,11 @@ async function safeCountVault(ctx) {
|
|
|
8117
8163
|
return void 0;
|
|
8118
8164
|
}
|
|
8119
8165
|
}
|
|
8120
|
-
async function safeLane(label, run) {
|
|
8166
|
+
async function safeLane(label, onFailure, run) {
|
|
8121
8167
|
try {
|
|
8122
8168
|
return await run();
|
|
8123
8169
|
} catch (err) {
|
|
8170
|
+
onFailure();
|
|
8124
8171
|
getLogger().warn(
|
|
8125
8172
|
`[memory/recall] ${label} lane failed; continuing without it: ${err instanceof Error ? err.message : String(err)}`
|
|
8126
8173
|
);
|