@anuma/sdk 3.11.1 → 3.11.3
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-7CTI3XR6.mjs → chunk-7AW2VD5W.mjs} +284 -93
- package/dist/expo/index.cjs +333 -101
- package/dist/expo/index.d.mts +14 -1
- package/dist/expo/index.d.ts +14 -1
- package/dist/expo/index.mjs +46 -7
- package/dist/expo/{recall-IBGUFY4P.mjs → recall-JWQ4IJX6.mjs} +1 -1
- package/dist/react/{chunk-LAFUCS4U.mjs → chunk-L2QRTJII.mjs} +284 -93
- package/dist/react/index.cjs +333 -101
- package/dist/react/index.d.mts +14 -1
- package/dist/react/index.d.ts +14 -1
- package/dist/react/index.mjs +46 -7
- package/dist/react/{recall-Q5V5DN4L.mjs → recall-DOFCEH2I.mjs} +1 -1
- package/dist/server/{chunk-NCKDSZPQ.mjs → chunk-FZZCEZL2.mjs} +284 -93
- package/dist/server/index.cjs +332 -101
- package/dist/server/index.d.mts +14 -1
- package/dist/server/index.d.ts +14 -1
- package/dist/server/index.mjs +46 -7
- package/dist/server/{recall-AN7HBEFS.mjs → recall-QH3YX6T4.mjs} +1 -1
- package/dist/tools/index.cjs +14 -0
- package/dist/tools/index.mjs +14 -0
- package/package.json +1 -1
|
@@ -18464,6 +18464,11 @@ function applyMMR(candidates, k, lambda = 0.5) {
|
|
|
18464
18464
|
return selected;
|
|
18465
18465
|
}
|
|
18466
18466
|
|
|
18467
|
+
// src/lib/memory/recallConstants.ts
|
|
18468
|
+
var RECALL_TOOL_NAME = "recall_memory";
|
|
18469
|
+
var RECALL_MAX_LIMIT = 50;
|
|
18470
|
+
var EMBEDDINGS_DEGRADED_EMPTY = "Semantic memory search is temporarily unavailable, so only keyword matching ran and it found no matches. Do not conclude the user has no such memory \u2014 say the memory lookup was degraded, or retry with different keywords.";
|
|
18471
|
+
|
|
18467
18472
|
// src/lib/memory/recency.ts
|
|
18468
18473
|
var DAY_MS = 1e3 * 60 * 60 * 24;
|
|
18469
18474
|
var DEFAULT_PER_YEAR_DECAY = 0.2;
|
|
@@ -19446,6 +19451,24 @@ async function eagerEmbedContent(content, embeddingOptions, cache, vaultCtx, mem
|
|
|
19446
19451
|
);
|
|
19447
19452
|
}
|
|
19448
19453
|
}
|
|
19454
|
+
async function embedQueryOrDegrade(query, embeddingOptions, onDegraded) {
|
|
19455
|
+
try {
|
|
19456
|
+
const embedding = await generateEmbedding(query, embeddingOptions);
|
|
19457
|
+
if (embedding.length === 0) {
|
|
19458
|
+
getLogger().warn(
|
|
19459
|
+
"memoryVault: query embedding came back empty \u2014 falling back to BM25-only ranking for this search"
|
|
19460
|
+
);
|
|
19461
|
+
onDegraded?.();
|
|
19462
|
+
}
|
|
19463
|
+
return embedding;
|
|
19464
|
+
} catch (err) {
|
|
19465
|
+
getLogger().warn(
|
|
19466
|
+
"memoryVault: query embedding failed \u2014 falling back to BM25-only ranking for this search: " + (err instanceof Error ? err.message : String(err))
|
|
19467
|
+
);
|
|
19468
|
+
onDegraded?.();
|
|
19469
|
+
return [];
|
|
19470
|
+
}
|
|
19471
|
+
}
|
|
19449
19472
|
function admitVaultProjections(queryEmbedding, vectored, k) {
|
|
19450
19473
|
return vectored.map((it) => ({ it, score: cosineSimilarity(queryEmbedding, it.embedding) })).sort((a, b) => b.score - a.score || b.it.updatedAt.getTime() - a.it.updatedAt.getTime()).slice(0, k).map((s) => s.it.uniqueId);
|
|
19451
19474
|
}
|
|
@@ -19457,23 +19480,36 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
|
|
|
19457
19480
|
const hydrateOpts = queryOpts.includeArchived ? { includeArchived: true } : void 0;
|
|
19458
19481
|
const vaultSize = keys.length;
|
|
19459
19482
|
if (keys.length === 0) {
|
|
19460
|
-
return {
|
|
19483
|
+
return {
|
|
19484
|
+
memories: [],
|
|
19485
|
+
embeddedItems: [],
|
|
19486
|
+
queryEmbedding: [],
|
|
19487
|
+
vaultSize: 0,
|
|
19488
|
+
laneEmbedFailed: false
|
|
19489
|
+
};
|
|
19461
19490
|
}
|
|
19462
|
-
const queryEmbedding = await
|
|
19491
|
+
const queryEmbedding = await embedQueryOrDegrade(
|
|
19492
|
+
query,
|
|
19493
|
+
embeddingOptions,
|
|
19494
|
+
opts.onEmbeddingDegraded
|
|
19495
|
+
);
|
|
19496
|
+
const embeddingsDegraded = queryEmbedding.length === 0;
|
|
19463
19497
|
const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
19464
19498
|
const vectored = [];
|
|
19465
19499
|
const missIds = [];
|
|
19466
19500
|
const noVectorIds = [];
|
|
19467
19501
|
const keyById = new Map(keys.map((k2) => [k2.uniqueId, k2]));
|
|
19468
|
-
|
|
19469
|
-
const
|
|
19470
|
-
|
|
19471
|
-
|
|
19472
|
-
|
|
19502
|
+
if (!embeddingsDegraded) {
|
|
19503
|
+
for (const k2 of keys) {
|
|
19504
|
+
const cached = cache.get(k2.uniqueId);
|
|
19505
|
+
if (cached && cached.length === queryEmbedding.length) {
|
|
19506
|
+
vectored.push({ uniqueId: k2.uniqueId, embedding: cached, updatedAt: k2.updatedAt });
|
|
19507
|
+
continue;
|
|
19508
|
+
}
|
|
19509
|
+
const modelCompatible = (k2.embeddingModel ?? currentModel) === currentModel;
|
|
19510
|
+
if (modelCompatible) missIds.push(k2.uniqueId);
|
|
19511
|
+
else noVectorIds.push(k2.uniqueId);
|
|
19473
19512
|
}
|
|
19474
|
-
const modelCompatible = (k2.embeddingModel ?? currentModel) === currentModel;
|
|
19475
|
-
if (modelCompatible) missIds.push(k2.uniqueId);
|
|
19476
|
-
else noVectorIds.push(k2.uniqueId);
|
|
19477
19513
|
}
|
|
19478
19514
|
if (missIds.length > 0) {
|
|
19479
19515
|
const rows = await getVaultEmbeddingsByIdsOp(vaultCtx, missIds, hydrateOpts);
|
|
@@ -19494,6 +19530,7 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
|
|
|
19494
19530
|
}
|
|
19495
19531
|
for (const id of missIds) if (!gotVector.has(id)) noVectorIds.push(id);
|
|
19496
19532
|
}
|
|
19533
|
+
let laneEmbedFailed = false;
|
|
19497
19534
|
if (noVectorIds.length > 0) {
|
|
19498
19535
|
const laneIds = noVectorIds.slice(0, opts.unembeddedCap);
|
|
19499
19536
|
if (noVectorIds.length > laneIds.length) {
|
|
@@ -19505,26 +19542,44 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
|
|
|
19505
19542
|
(m) => !isEncrypted(m.content)
|
|
19506
19543
|
);
|
|
19507
19544
|
if (laneRows.length > 0) {
|
|
19508
|
-
|
|
19509
|
-
|
|
19510
|
-
|
|
19511
|
-
|
|
19512
|
-
|
|
19513
|
-
|
|
19514
|
-
|
|
19515
|
-
|
|
19516
|
-
|
|
19517
|
-
|
|
19518
|
-
|
|
19519
|
-
|
|
19520
|
-
|
|
19521
|
-
|
|
19545
|
+
let laneVecs;
|
|
19546
|
+
try {
|
|
19547
|
+
laneVecs = await generateEmbeddings(
|
|
19548
|
+
laneRows.map((m) => m.content),
|
|
19549
|
+
embeddingOptions
|
|
19550
|
+
);
|
|
19551
|
+
} catch (err) {
|
|
19552
|
+
laneEmbedFailed = true;
|
|
19553
|
+
getLogger().warn(
|
|
19554
|
+
`memoryVault: un-embedded lane embedding failed for ${laneRows.length} rows \u2014 they rank on BM25 alone for this search: ` + (err instanceof Error ? err.message : String(err))
|
|
19555
|
+
);
|
|
19556
|
+
}
|
|
19557
|
+
if (laneVecs) {
|
|
19558
|
+
const vecs = laneVecs;
|
|
19559
|
+
laneRows.forEach((m, i) => {
|
|
19560
|
+
const vec = Float32Array.from(vecs[i]);
|
|
19561
|
+
cache.set(m.uniqueId, vec);
|
|
19562
|
+
vectored.push({ uniqueId: m.uniqueId, embedding: vec, updatedAt: m.updatedAt });
|
|
19563
|
+
updateVaultMemoryEmbeddingOp(
|
|
19564
|
+
vaultCtx,
|
|
19565
|
+
m.uniqueId,
|
|
19566
|
+
JSON.stringify(vecs[i]),
|
|
19567
|
+
currentModel
|
|
19568
|
+
).catch(() => {
|
|
19569
|
+
});
|
|
19522
19570
|
});
|
|
19523
|
-
}
|
|
19571
|
+
}
|
|
19524
19572
|
}
|
|
19525
19573
|
}
|
|
19526
19574
|
const k = Math.max(opts.limit * opts.admitFactor, opts.admitFloor);
|
|
19527
19575
|
const admittedIds = admitVaultProjections(queryEmbedding, vectored, k);
|
|
19576
|
+
if ((embeddingsDegraded || laneEmbedFailed) && admittedIds.length < k) {
|
|
19577
|
+
const already = new Set(admittedIds);
|
|
19578
|
+
for (const key of [...keys].sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime())) {
|
|
19579
|
+
if (admittedIds.length >= k) break;
|
|
19580
|
+
if (!already.has(key.uniqueId)) admittedIds.push(key.uniqueId);
|
|
19581
|
+
}
|
|
19582
|
+
}
|
|
19528
19583
|
const admissionSet = new Set(admittedIds);
|
|
19529
19584
|
if (opts.forceIncludeIds) {
|
|
19530
19585
|
for (const id of opts.forceIncludeIds) {
|
|
@@ -19552,11 +19607,18 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
|
|
|
19552
19607
|
eventTimeKind: normalizeEventTimeKind(m.eventTimeKind),
|
|
19553
19608
|
factType: m.factType
|
|
19554
19609
|
}));
|
|
19555
|
-
return { memories, embeddedItems, queryEmbedding, vaultSize };
|
|
19610
|
+
return { memories, embeddedItems, queryEmbedding, vaultSize, laneEmbedFailed };
|
|
19556
19611
|
}
|
|
19557
19612
|
async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache, searchOptions) {
|
|
19558
19613
|
if (!query || typeof query !== "string") {
|
|
19559
|
-
return {
|
|
19614
|
+
return {
|
|
19615
|
+
memories: [],
|
|
19616
|
+
embeddedItems: [],
|
|
19617
|
+
queryEmbedding: [],
|
|
19618
|
+
vaultSize: 0,
|
|
19619
|
+
embeddingsUnavailable: false,
|
|
19620
|
+
embeddingFailure: false
|
|
19621
|
+
};
|
|
19560
19622
|
}
|
|
19561
19623
|
const limit = searchOptions?.limit ?? 5;
|
|
19562
19624
|
const scopes = searchOptions?.scopes;
|
|
@@ -19573,6 +19635,12 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
19573
19635
|
let embeddedItems;
|
|
19574
19636
|
let queryEmbedding;
|
|
19575
19637
|
let vaultSize;
|
|
19638
|
+
let embeddingsUnavailable = false;
|
|
19639
|
+
let embeddingFailure = false;
|
|
19640
|
+
const onEmbeddingDegraded = () => {
|
|
19641
|
+
embeddingsUnavailable = true;
|
|
19642
|
+
embeddingFailure = true;
|
|
19643
|
+
};
|
|
19576
19644
|
if (searchOptions?.decryptLast) {
|
|
19577
19645
|
const forceIncludeIds = [
|
|
19578
19646
|
...searchOptions.entityRanking ?? [],
|
|
@@ -19583,14 +19651,30 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
19583
19651
|
admitFactor: ADMIT_FACTOR,
|
|
19584
19652
|
admitFloor: ADMIT_FLOOR,
|
|
19585
19653
|
unembeddedCap: UNEMBEDDED_CAP,
|
|
19586
|
-
...forceIncludeIds.length > 0 && { forceIncludeIds }
|
|
19654
|
+
...forceIncludeIds.length > 0 && { forceIncludeIds },
|
|
19655
|
+
onEmbeddingDegraded
|
|
19587
19656
|
});
|
|
19588
19657
|
if (corpus.vaultSize === 0) {
|
|
19589
|
-
return {
|
|
19658
|
+
return {
|
|
19659
|
+
memories: [],
|
|
19660
|
+
embeddedItems: [],
|
|
19661
|
+
queryEmbedding: [],
|
|
19662
|
+
vaultSize: 0,
|
|
19663
|
+
embeddingsUnavailable: false,
|
|
19664
|
+
embeddingFailure: false
|
|
19665
|
+
};
|
|
19590
19666
|
}
|
|
19591
19667
|
({ memories, embeddedItems, queryEmbedding, vaultSize } = corpus);
|
|
19668
|
+
if (corpus.laneEmbedFailed) embeddingFailure = true;
|
|
19592
19669
|
if (memories.length === 0) {
|
|
19593
|
-
return {
|
|
19670
|
+
return {
|
|
19671
|
+
memories: [],
|
|
19672
|
+
embeddedItems: [],
|
|
19673
|
+
queryEmbedding: [],
|
|
19674
|
+
vaultSize,
|
|
19675
|
+
embeddingsUnavailable,
|
|
19676
|
+
embeddingFailure
|
|
19677
|
+
};
|
|
19594
19678
|
}
|
|
19595
19679
|
} else {
|
|
19596
19680
|
const loaded = await getAllVaultMemoriesOp(
|
|
@@ -19605,14 +19689,21 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
19605
19689
|
);
|
|
19606
19690
|
}
|
|
19607
19691
|
if (memories.length === 0) {
|
|
19608
|
-
return {
|
|
19692
|
+
return {
|
|
19693
|
+
memories: [],
|
|
19694
|
+
embeddedItems: [],
|
|
19695
|
+
queryEmbedding: [],
|
|
19696
|
+
vaultSize: loaded.length,
|
|
19697
|
+
embeddingsUnavailable: false,
|
|
19698
|
+
embeddingFailure: false
|
|
19699
|
+
};
|
|
19609
19700
|
}
|
|
19610
|
-
queryEmbedding = await
|
|
19701
|
+
queryEmbedding = await embedQueryOrDegrade(query, embeddingOptions, onEmbeddingDegraded);
|
|
19611
19702
|
const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
19612
19703
|
const uncachedTexts = [];
|
|
19613
19704
|
const uncachedIndices = [];
|
|
19614
19705
|
let staleReembedCount = 0;
|
|
19615
|
-
for (let i = 0; i < memories.length; i++) {
|
|
19706
|
+
for (let i = 0; queryEmbedding.length > 0 && i < memories.length; i++) {
|
|
19616
19707
|
const content = memories[i].content;
|
|
19617
19708
|
const memoryId = memories[i].uniqueId;
|
|
19618
19709
|
const cached = cache.get(memoryId);
|
|
@@ -19640,20 +19731,30 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
19640
19731
|
);
|
|
19641
19732
|
}
|
|
19642
19733
|
if (uncachedTexts.length > 0) {
|
|
19643
|
-
|
|
19644
|
-
|
|
19645
|
-
|
|
19646
|
-
|
|
19647
|
-
|
|
19648
|
-
|
|
19649
|
-
|
|
19650
|
-
currentModel
|
|
19651
|
-
).catch(
|
|
19652
|
-
// Silently swallow – SDK must not use console.*; embedding will be retried on next search
|
|
19653
|
-
() => {
|
|
19654
|
-
}
|
|
19734
|
+
let newEmbeddings;
|
|
19735
|
+
try {
|
|
19736
|
+
newEmbeddings = await generateEmbeddings(uncachedTexts, embeddingOptions);
|
|
19737
|
+
} catch (err) {
|
|
19738
|
+
embeddingFailure = true;
|
|
19739
|
+
getLogger().warn(
|
|
19740
|
+
`memoryVault: (re)embedding ${uncachedTexts.length} vault rows failed \u2014 they rank on BM25 alone for this search: ` + (err instanceof Error ? err.message : String(err))
|
|
19655
19741
|
);
|
|
19656
19742
|
}
|
|
19743
|
+
if (newEmbeddings) {
|
|
19744
|
+
for (let j = 0; j < uncachedTexts.length; j++) {
|
|
19745
|
+
cache.set(memories[uncachedIndices[j]].uniqueId, Float32Array.from(newEmbeddings[j]));
|
|
19746
|
+
updateVaultMemoryEmbeddingOp(
|
|
19747
|
+
vaultCtx,
|
|
19748
|
+
memories[uncachedIndices[j]].uniqueId,
|
|
19749
|
+
JSON.stringify(newEmbeddings[j]),
|
|
19750
|
+
currentModel
|
|
19751
|
+
).catch(
|
|
19752
|
+
// Silently swallow – SDK must not use console.*; embedding will be retried on next search
|
|
19753
|
+
() => {
|
|
19754
|
+
}
|
|
19755
|
+
);
|
|
19756
|
+
}
|
|
19757
|
+
}
|
|
19657
19758
|
}
|
|
19658
19759
|
embeddedItems = memories.map((m) => ({
|
|
19659
19760
|
id: m.uniqueId,
|
|
@@ -19670,12 +19771,22 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
19670
19771
|
factType: m.factType
|
|
19671
19772
|
}));
|
|
19672
19773
|
}
|
|
19673
|
-
|
|
19774
|
+
if (!embeddingsUnavailable && !embeddedItems.some((it) => it.embedding.length > 0)) {
|
|
19775
|
+
embeddingsUnavailable = true;
|
|
19776
|
+
}
|
|
19777
|
+
return {
|
|
19778
|
+
memories,
|
|
19779
|
+
embeddedItems,
|
|
19780
|
+
queryEmbedding,
|
|
19781
|
+
vaultSize,
|
|
19782
|
+
embeddingsUnavailable,
|
|
19783
|
+
embeddingFailure
|
|
19784
|
+
};
|
|
19674
19785
|
}
|
|
19675
19786
|
async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, searchOptions) {
|
|
19676
19787
|
const limit = searchOptions?.limit ?? 5;
|
|
19677
19788
|
const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
|
|
19678
|
-
const { memories, embeddedItems, queryEmbedding, vaultSize } = prepared;
|
|
19789
|
+
const { memories, embeddedItems, queryEmbedding, vaultSize, embeddingsUnavailable } = prepared;
|
|
19679
19790
|
if (queryEmbedding.length > 0) {
|
|
19680
19791
|
const mismatched = embeddedItems.filter(
|
|
19681
19792
|
(it) => it.embedding.length > 0 && it.embedding.length !== queryEmbedding.length
|
|
@@ -19712,7 +19823,8 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
19712
19823
|
results: results2,
|
|
19713
19824
|
vaultSize: out.vaultSize,
|
|
19714
19825
|
reranked: out.reranked ?? false,
|
|
19715
|
-
hadV2Head: out.hadV2Head ?? false
|
|
19826
|
+
hadV2Head: out.hadV2Head ?? false,
|
|
19827
|
+
embeddingsUnavailable
|
|
19716
19828
|
};
|
|
19717
19829
|
};
|
|
19718
19830
|
const rerankStats = { applied: false };
|
|
@@ -19735,36 +19847,46 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
19735
19847
|
...searchOptions?.rrfK !== void 0 && { rrfK: searchOptions.rrfK },
|
|
19736
19848
|
...searchOptions?.factTypeWeights && { factTypeWeights: searchOptions.factTypeWeights }
|
|
19737
19849
|
};
|
|
19738
|
-
if (useFusion && searchOptions?.decompose === "llm" && searchOptions.decomposeOptions) {
|
|
19850
|
+
if (useFusion && !embeddingsUnavailable && searchOptions?.decompose === "llm" && searchOptions.decomposeOptions) {
|
|
19739
19851
|
const decomp = await decomposeQuery(query, searchOptions.decomposeOptions);
|
|
19740
19852
|
if (decomp.mode === "composite") {
|
|
19741
|
-
|
|
19742
|
-
|
|
19743
|
-
|
|
19744
|
-
|
|
19745
|
-
|
|
19746
|
-
|
|
19747
|
-
|
|
19748
|
-
|
|
19749
|
-
|
|
19750
|
-
|
|
19751
|
-
|
|
19752
|
-
|
|
19753
|
-
|
|
19754
|
-
|
|
19755
|
-
|
|
19756
|
-
|
|
19757
|
-
|
|
19758
|
-
|
|
19759
|
-
|
|
19760
|
-
|
|
19761
|
-
|
|
19762
|
-
|
|
19763
|
-
|
|
19764
|
-
|
|
19765
|
-
|
|
19766
|
-
|
|
19767
|
-
|
|
19853
|
+
let subEmbeddings;
|
|
19854
|
+
try {
|
|
19855
|
+
subEmbeddings = await generateEmbeddings(decomp.subQueries, embeddingOptions);
|
|
19856
|
+
} catch (err) {
|
|
19857
|
+
getLogger().warn(
|
|
19858
|
+
"memoryVault: sub-query embedding failed \u2014 falling back to single-query ranking: " + (err instanceof Error ? err.message : String(err))
|
|
19859
|
+
);
|
|
19860
|
+
subEmbeddings = [];
|
|
19861
|
+
}
|
|
19862
|
+
if (subEmbeddings.length > 0) {
|
|
19863
|
+
const subQueries = decomp.subQueries.map((sq, i) => ({
|
|
19864
|
+
query: sq,
|
|
19865
|
+
embedding: subEmbeddings[i]
|
|
19866
|
+
}));
|
|
19867
|
+
const v2HeadStats = { hadResults: false };
|
|
19868
|
+
const composite = await rankComposite(query, queryEmbedding, subQueries, embeddedItems, {
|
|
19869
|
+
limit,
|
|
19870
|
+
minSimilarity,
|
|
19871
|
+
rerank: !!searchOptions.rerank,
|
|
19872
|
+
...searchOptions.rerankTopN !== void 0 && {
|
|
19873
|
+
rerankTopN: searchOptions.rerankTopN
|
|
19874
|
+
},
|
|
19875
|
+
...searchOptions.ceWeight !== void 0 && { ceWeight: searchOptions.ceWeight },
|
|
19876
|
+
...searchOptions.mmr !== void 0 && { mmr: searchOptions.mmr },
|
|
19877
|
+
...tuning,
|
|
19878
|
+
...searchOptions.entityRanking && { entityRanking: searchOptions.entityRanking },
|
|
19879
|
+
...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
|
|
19880
|
+
rerankStats,
|
|
19881
|
+
v2HeadStats
|
|
19882
|
+
});
|
|
19883
|
+
return stampTimestamps({
|
|
19884
|
+
results: composite,
|
|
19885
|
+
vaultSize,
|
|
19886
|
+
reranked: rerankStats.applied,
|
|
19887
|
+
hadV2Head: v2HeadStats.hadResults
|
|
19888
|
+
});
|
|
19889
|
+
}
|
|
19768
19890
|
}
|
|
19769
19891
|
}
|
|
19770
19892
|
if (useFusion && searchOptions?.rerank) {
|
|
@@ -19815,7 +19937,14 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
19815
19937
|
}
|
|
19816
19938
|
async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, cache, searchOptions) {
|
|
19817
19939
|
if (!query || typeof query !== "string") {
|
|
19818
|
-
return {
|
|
19940
|
+
return {
|
|
19941
|
+
results: [],
|
|
19942
|
+
vaultSize: 0,
|
|
19943
|
+
reranked: false,
|
|
19944
|
+
hadV2Head: false,
|
|
19945
|
+
embeddingsUnavailable: false,
|
|
19946
|
+
rankedOnCosine: false
|
|
19947
|
+
};
|
|
19819
19948
|
}
|
|
19820
19949
|
const prepared = await prepareVaultCandidates(
|
|
19821
19950
|
query,
|
|
@@ -19825,12 +19954,32 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
19825
19954
|
searchOptions
|
|
19826
19955
|
);
|
|
19827
19956
|
if (prepared.vaultSize === 0) {
|
|
19828
|
-
return {
|
|
19957
|
+
return {
|
|
19958
|
+
results: [],
|
|
19959
|
+
vaultSize: 0,
|
|
19960
|
+
reranked: false,
|
|
19961
|
+
hadV2Head: false,
|
|
19962
|
+
embeddingsUnavailable: prepared.embeddingsUnavailable,
|
|
19963
|
+
rankedOnCosine: false
|
|
19964
|
+
};
|
|
19829
19965
|
}
|
|
19830
19966
|
if (prepared.memories.length === 0) {
|
|
19831
|
-
return {
|
|
19967
|
+
return {
|
|
19968
|
+
results: [],
|
|
19969
|
+
vaultSize: prepared.vaultSize,
|
|
19970
|
+
reranked: false,
|
|
19971
|
+
hadV2Head: false,
|
|
19972
|
+
embeddingsUnavailable: prepared.embeddingsUnavailable,
|
|
19973
|
+
rankedOnCosine: false
|
|
19974
|
+
};
|
|
19832
19975
|
}
|
|
19833
|
-
|
|
19976
|
+
const ranked = await rankPreparedVaultCandidates(
|
|
19977
|
+
query,
|
|
19978
|
+
prepared,
|
|
19979
|
+
embeddingOptions,
|
|
19980
|
+
searchOptions
|
|
19981
|
+
);
|
|
19982
|
+
return { ...ranked, rankedOnCosine: !ranked.embeddingsUnavailable };
|
|
19834
19983
|
}
|
|
19835
19984
|
async function searchVaultMemories(query, vaultCtx, embeddingOptions, cache, searchOptions) {
|
|
19836
19985
|
const { results } = await searchVaultMemoriesWithSize(
|
|
@@ -19842,6 +19991,7 @@ async function searchVaultMemories(query, vaultCtx, embeddingOptions, cache, sea
|
|
|
19842
19991
|
);
|
|
19843
19992
|
return results;
|
|
19844
19993
|
}
|
|
19994
|
+
var EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL = "Memory search is temporarily unavailable \u2014 the semantic lookup failed and this search mode has no keyword fallback, so no memory search ran at all. Do not conclude the user has no such memory; say the memory lookup was unavailable.";
|
|
19845
19995
|
function formatVaultHits(hits) {
|
|
19846
19996
|
return hits.map((h, i) => `[${i + 1}] (id: ${h.id}, similarity: ${h.score.toFixed(2)})
|
|
19847
19997
|
${h.content}`).join("\n\n");
|
|
@@ -19904,26 +20054,36 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
19904
20054
|
const budget = searchOptions?.decompose === "llm" && searchOptions.decomposeOptions ? "high" : searchOptions?.rerank ? "mid" : "low";
|
|
19905
20055
|
const folderId = searchOptions?.folderId ?? argFolderId;
|
|
19906
20056
|
if (searchOptions?.useFusion === false) {
|
|
19907
|
-
const legacy = await
|
|
19908
|
-
|
|
19909
|
-
|
|
19910
|
-
|
|
19911
|
-
|
|
19912
|
-
|
|
19913
|
-
|
|
19914
|
-
|
|
20057
|
+
const { results: legacy, embeddingsUnavailable } = await searchVaultMemoriesWithSize(
|
|
20058
|
+
query,
|
|
20059
|
+
vaultCtx,
|
|
20060
|
+
embeddingOptions,
|
|
20061
|
+
cache,
|
|
20062
|
+
{
|
|
20063
|
+
limit: requestLimit,
|
|
20064
|
+
minSimilarity,
|
|
20065
|
+
useFusion: false,
|
|
20066
|
+
...tuningForward,
|
|
20067
|
+
...folderId !== void 0 && { folderId },
|
|
20068
|
+
...searchOptions?.scopes && { scopes: searchOptions.scopes }
|
|
20069
|
+
}
|
|
20070
|
+
);
|
|
19915
20071
|
if (legacy.length === 0) {
|
|
19916
|
-
return "No relevant memories found in the vault.";
|
|
20072
|
+
return embeddingsUnavailable ? EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL : "No relevant memories found in the vault.";
|
|
19917
20073
|
}
|
|
19918
20074
|
return formatVaultHits(
|
|
19919
20075
|
legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
|
|
19920
20076
|
);
|
|
19921
20077
|
}
|
|
19922
|
-
const { recall: recall2 } = await import("./recall-
|
|
20078
|
+
const { recall: recall2 } = await import("./recall-QH3YX6T4.mjs");
|
|
20079
|
+
let recallDegraded = [];
|
|
19923
20080
|
const result = await recall2(
|
|
19924
20081
|
query,
|
|
19925
20082
|
{ vaultCtx, embeddingOptions, vaultCache: cache },
|
|
19926
20083
|
{
|
|
20084
|
+
onDiagnostics: (d) => {
|
|
20085
|
+
recallDegraded = d.degraded;
|
|
20086
|
+
},
|
|
19927
20087
|
types: ["fact"],
|
|
19928
20088
|
limit: requestLimit,
|
|
19929
20089
|
minScore: minSimilarity,
|
|
@@ -19944,7 +20104,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
19944
20104
|
return "The memory vault is empty. No memories have been saved yet.";
|
|
19945
20105
|
}
|
|
19946
20106
|
if (result.memories.length === 0) {
|
|
19947
|
-
return "No relevant memories found in the vault.";
|
|
20107
|
+
return recallDegraded.includes("embeddings-unavailable") ? EMBEDDINGS_DEGRADED_EMPTY : "No relevant memories found in the vault.";
|
|
19948
20108
|
}
|
|
19949
20109
|
const formatted = formatVaultHits(
|
|
19950
20110
|
result.memories.map((m) => ({
|
|
@@ -20499,6 +20659,9 @@ async function recall(query, ctx, options = {}) {
|
|
|
20499
20659
|
let vaultSize;
|
|
20500
20660
|
let didRerank = false;
|
|
20501
20661
|
let hadV2Head = false;
|
|
20662
|
+
let embeddingsUnavailable = false;
|
|
20663
|
+
let chunkEmbedFailed = false;
|
|
20664
|
+
let factLaneRankedOnCosine = false;
|
|
20502
20665
|
const emitDiagnostics = (candidateCount) => {
|
|
20503
20666
|
const cb = options.onDiagnostics;
|
|
20504
20667
|
if (!cb) return;
|
|
@@ -20507,6 +20670,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
20507
20670
|
degraded.push("rerank-unavailable");
|
|
20508
20671
|
}
|
|
20509
20672
|
if (flags.decompose && !decomposeAvailable) degraded.push("decompose-unavailable");
|
|
20673
|
+
if (embeddingsUnavailable) degraded.push("embeddings-unavailable");
|
|
20510
20674
|
const diagnostics = {
|
|
20511
20675
|
usedBudget,
|
|
20512
20676
|
reranked: didRerank,
|
|
@@ -20537,7 +20701,26 @@ async function recall(query, ctx, options = {}) {
|
|
|
20537
20701
|
const graphRefiner = flags.traverse && options.graphRefine && options.decomposeOptions ? createLlmNeighborRefiner(options.decomposeOptions) : void 0;
|
|
20538
20702
|
const prepStart = nowMs();
|
|
20539
20703
|
const [queryEmbedding, entityRanking, temporalRanking] = await Promise.all([
|
|
20540
|
-
|
|
20704
|
+
// The chunk lane is cosine-only — `searchChunksOp` needs a real vector, and
|
|
20705
|
+
// there is no lexical fallback for it — so an embeddings outage must SKIP the
|
|
20706
|
+
// lane, not reject this shared Promise.all and take the primary fact lane
|
|
20707
|
+
// (which BM25 can still serve) down with it. Mirrors safeLane's posture.
|
|
20708
|
+
needsChunkEmbedding ? generateEmbedding(query, ctx.embeddingOptions).then((vec) => {
|
|
20709
|
+
if (vec.length === 0) {
|
|
20710
|
+
getLogger().warn(
|
|
20711
|
+
"[memory/recall] chunk-lane query embedding came back empty; skipping the chunk lane"
|
|
20712
|
+
);
|
|
20713
|
+
chunkEmbedFailed = true;
|
|
20714
|
+
return void 0;
|
|
20715
|
+
}
|
|
20716
|
+
return vec;
|
|
20717
|
+
}).catch((err) => {
|
|
20718
|
+
getLogger().warn(
|
|
20719
|
+
`[memory/recall] chunk-lane query embedding failed; skipping the chunk lane: ${err instanceof Error ? err.message : String(err)}`
|
|
20720
|
+
);
|
|
20721
|
+
chunkEmbedFailed = true;
|
|
20722
|
+
return void 0;
|
|
20723
|
+
}) : Promise.resolve(void 0),
|
|
20541
20724
|
// The graph + temporal lanes are AUXILIARY (RRF side-signals). A transient
|
|
20542
20725
|
// WatermelonDB throw in either must NOT reject this Promise.all and take
|
|
20543
20726
|
// PRIMARY cosine/BM25 recall down with it — degrade the failing lane to an
|
|
@@ -20562,7 +20745,9 @@ async function recall(query, ctx, options = {}) {
|
|
|
20562
20745
|
results,
|
|
20563
20746
|
vaultSize: size,
|
|
20564
20747
|
reranked,
|
|
20565
|
-
hadV2Head: v2Head
|
|
20748
|
+
hadV2Head: v2Head,
|
|
20749
|
+
embeddingsUnavailable: factEmbeddingsUnavailable,
|
|
20750
|
+
rankedOnCosine: factRankedOnCosine
|
|
20566
20751
|
} = await searchVaultMemoriesWithSize(
|
|
20567
20752
|
query,
|
|
20568
20753
|
ctx.vaultCtx,
|
|
@@ -20619,8 +20804,11 @@ async function recall(query, ctx, options = {}) {
|
|
|
20619
20804
|
vaultSize = size;
|
|
20620
20805
|
didRerank = reranked;
|
|
20621
20806
|
hadV2Head = v2Head;
|
|
20807
|
+
if (factEmbeddingsUnavailable) embeddingsUnavailable = true;
|
|
20808
|
+
factLaneRankedOnCosine = factRankedOnCosine;
|
|
20622
20809
|
factLaneMs = nowMs() - factStart;
|
|
20623
20810
|
}
|
|
20811
|
+
if (chunkEmbedFailed && !factLaneRankedOnCosine) embeddingsUnavailable = true;
|
|
20624
20812
|
if (types.includes("chunk") && ctx.storageCtx && queryEmbedding) {
|
|
20625
20813
|
const chunkStart = nowMs();
|
|
20626
20814
|
const chunkMinScore = options.minScore ?? DEFAULT_CHUNK_MIN_SCORE;
|
|
@@ -20932,6 +21120,9 @@ export {
|
|
|
20932
21120
|
embedAllMessages,
|
|
20933
21121
|
chunkAndEmbedMessage,
|
|
20934
21122
|
chunkAndEmbedAllMessages,
|
|
21123
|
+
RECALL_TOOL_NAME,
|
|
21124
|
+
RECALL_MAX_LIMIT,
|
|
21125
|
+
EMBEDDINGS_DEGRADED_EMPTY,
|
|
20935
21126
|
RerankerUnavailableError,
|
|
20936
21127
|
isRerankerAvailable,
|
|
20937
21128
|
DEFAULT_VAULT_CACHE_SIZE,
|