@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
|
@@ -4574,6 +4574,11 @@ function applyMMR(candidates, k, lambda = 0.5) {
|
|
|
4574
4574
|
return selected;
|
|
4575
4575
|
}
|
|
4576
4576
|
|
|
4577
|
+
// src/lib/memory/recallConstants.ts
|
|
4578
|
+
var RECALL_TOOL_NAME = "recall_memory";
|
|
4579
|
+
var RECALL_MAX_LIMIT = 50;
|
|
4580
|
+
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.";
|
|
4581
|
+
|
|
4577
4582
|
// src/lib/memory/recency.ts
|
|
4578
4583
|
var DAY_MS = 1e3 * 60 * 60 * 24;
|
|
4579
4584
|
var DEFAULT_PER_YEAR_DECAY = 0.2;
|
|
@@ -5556,6 +5561,24 @@ async function eagerEmbedContent(content, embeddingOptions, cache, vaultCtx, mem
|
|
|
5556
5561
|
);
|
|
5557
5562
|
}
|
|
5558
5563
|
}
|
|
5564
|
+
async function embedQueryOrDegrade(query, embeddingOptions, onDegraded) {
|
|
5565
|
+
try {
|
|
5566
|
+
const embedding = await generateEmbedding(query, embeddingOptions);
|
|
5567
|
+
if (embedding.length === 0) {
|
|
5568
|
+
getLogger().warn(
|
|
5569
|
+
"memoryVault: query embedding came back empty \u2014 falling back to BM25-only ranking for this search"
|
|
5570
|
+
);
|
|
5571
|
+
onDegraded?.();
|
|
5572
|
+
}
|
|
5573
|
+
return embedding;
|
|
5574
|
+
} catch (err) {
|
|
5575
|
+
getLogger().warn(
|
|
5576
|
+
"memoryVault: query embedding failed \u2014 falling back to BM25-only ranking for this search: " + (err instanceof Error ? err.message : String(err))
|
|
5577
|
+
);
|
|
5578
|
+
onDegraded?.();
|
|
5579
|
+
return [];
|
|
5580
|
+
}
|
|
5581
|
+
}
|
|
5559
5582
|
function admitVaultProjections(queryEmbedding, vectored, k) {
|
|
5560
5583
|
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);
|
|
5561
5584
|
}
|
|
@@ -5567,23 +5590,36 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
|
|
|
5567
5590
|
const hydrateOpts = queryOpts.includeArchived ? { includeArchived: true } : void 0;
|
|
5568
5591
|
const vaultSize = keys.length;
|
|
5569
5592
|
if (keys.length === 0) {
|
|
5570
|
-
return {
|
|
5593
|
+
return {
|
|
5594
|
+
memories: [],
|
|
5595
|
+
embeddedItems: [],
|
|
5596
|
+
queryEmbedding: [],
|
|
5597
|
+
vaultSize: 0,
|
|
5598
|
+
laneEmbedFailed: false
|
|
5599
|
+
};
|
|
5571
5600
|
}
|
|
5572
|
-
const queryEmbedding = await
|
|
5601
|
+
const queryEmbedding = await embedQueryOrDegrade(
|
|
5602
|
+
query,
|
|
5603
|
+
embeddingOptions,
|
|
5604
|
+
opts.onEmbeddingDegraded
|
|
5605
|
+
);
|
|
5606
|
+
const embeddingsDegraded = queryEmbedding.length === 0;
|
|
5573
5607
|
const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
5574
5608
|
const vectored = [];
|
|
5575
5609
|
const missIds = [];
|
|
5576
5610
|
const noVectorIds = [];
|
|
5577
5611
|
const keyById = new Map(keys.map((k2) => [k2.uniqueId, k2]));
|
|
5578
|
-
|
|
5579
|
-
const
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5612
|
+
if (!embeddingsDegraded) {
|
|
5613
|
+
for (const k2 of keys) {
|
|
5614
|
+
const cached = cache.get(k2.uniqueId);
|
|
5615
|
+
if (cached && cached.length === queryEmbedding.length) {
|
|
5616
|
+
vectored.push({ uniqueId: k2.uniqueId, embedding: cached, updatedAt: k2.updatedAt });
|
|
5617
|
+
continue;
|
|
5618
|
+
}
|
|
5619
|
+
const modelCompatible = (k2.embeddingModel ?? currentModel) === currentModel;
|
|
5620
|
+
if (modelCompatible) missIds.push(k2.uniqueId);
|
|
5621
|
+
else noVectorIds.push(k2.uniqueId);
|
|
5583
5622
|
}
|
|
5584
|
-
const modelCompatible = (k2.embeddingModel ?? currentModel) === currentModel;
|
|
5585
|
-
if (modelCompatible) missIds.push(k2.uniqueId);
|
|
5586
|
-
else noVectorIds.push(k2.uniqueId);
|
|
5587
5623
|
}
|
|
5588
5624
|
if (missIds.length > 0) {
|
|
5589
5625
|
const rows = await getVaultEmbeddingsByIdsOp(vaultCtx, missIds, hydrateOpts);
|
|
@@ -5604,6 +5640,7 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
|
|
|
5604
5640
|
}
|
|
5605
5641
|
for (const id of missIds) if (!gotVector.has(id)) noVectorIds.push(id);
|
|
5606
5642
|
}
|
|
5643
|
+
let laneEmbedFailed = false;
|
|
5607
5644
|
if (noVectorIds.length > 0) {
|
|
5608
5645
|
const laneIds = noVectorIds.slice(0, opts.unembeddedCap);
|
|
5609
5646
|
if (noVectorIds.length > laneIds.length) {
|
|
@@ -5615,26 +5652,44 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
|
|
|
5615
5652
|
(m) => !isEncrypted(m.content)
|
|
5616
5653
|
);
|
|
5617
5654
|
if (laneRows.length > 0) {
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5655
|
+
let laneVecs;
|
|
5656
|
+
try {
|
|
5657
|
+
laneVecs = await generateEmbeddings(
|
|
5658
|
+
laneRows.map((m) => m.content),
|
|
5659
|
+
embeddingOptions
|
|
5660
|
+
);
|
|
5661
|
+
} catch (err) {
|
|
5662
|
+
laneEmbedFailed = true;
|
|
5663
|
+
getLogger().warn(
|
|
5664
|
+
`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))
|
|
5665
|
+
);
|
|
5666
|
+
}
|
|
5667
|
+
if (laneVecs) {
|
|
5668
|
+
const vecs = laneVecs;
|
|
5669
|
+
laneRows.forEach((m, i) => {
|
|
5670
|
+
const vec = Float32Array.from(vecs[i]);
|
|
5671
|
+
cache.set(m.uniqueId, vec);
|
|
5672
|
+
vectored.push({ uniqueId: m.uniqueId, embedding: vec, updatedAt: m.updatedAt });
|
|
5673
|
+
updateVaultMemoryEmbeddingOp(
|
|
5674
|
+
vaultCtx,
|
|
5675
|
+
m.uniqueId,
|
|
5676
|
+
JSON.stringify(vecs[i]),
|
|
5677
|
+
currentModel
|
|
5678
|
+
).catch(() => {
|
|
5679
|
+
});
|
|
5632
5680
|
});
|
|
5633
|
-
}
|
|
5681
|
+
}
|
|
5634
5682
|
}
|
|
5635
5683
|
}
|
|
5636
5684
|
const k = Math.max(opts.limit * opts.admitFactor, opts.admitFloor);
|
|
5637
5685
|
const admittedIds = admitVaultProjections(queryEmbedding, vectored, k);
|
|
5686
|
+
if ((embeddingsDegraded || laneEmbedFailed) && admittedIds.length < k) {
|
|
5687
|
+
const already = new Set(admittedIds);
|
|
5688
|
+
for (const key of [...keys].sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime())) {
|
|
5689
|
+
if (admittedIds.length >= k) break;
|
|
5690
|
+
if (!already.has(key.uniqueId)) admittedIds.push(key.uniqueId);
|
|
5691
|
+
}
|
|
5692
|
+
}
|
|
5638
5693
|
const admissionSet = new Set(admittedIds);
|
|
5639
5694
|
if (opts.forceIncludeIds) {
|
|
5640
5695
|
for (const id of opts.forceIncludeIds) {
|
|
@@ -5662,11 +5717,18 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
|
|
|
5662
5717
|
eventTimeKind: normalizeEventTimeKind(m.eventTimeKind),
|
|
5663
5718
|
factType: m.factType
|
|
5664
5719
|
}));
|
|
5665
|
-
return { memories, embeddedItems, queryEmbedding, vaultSize };
|
|
5720
|
+
return { memories, embeddedItems, queryEmbedding, vaultSize, laneEmbedFailed };
|
|
5666
5721
|
}
|
|
5667
5722
|
async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache, searchOptions) {
|
|
5668
5723
|
if (!query || typeof query !== "string") {
|
|
5669
|
-
return {
|
|
5724
|
+
return {
|
|
5725
|
+
memories: [],
|
|
5726
|
+
embeddedItems: [],
|
|
5727
|
+
queryEmbedding: [],
|
|
5728
|
+
vaultSize: 0,
|
|
5729
|
+
embeddingsUnavailable: false,
|
|
5730
|
+
embeddingFailure: false
|
|
5731
|
+
};
|
|
5670
5732
|
}
|
|
5671
5733
|
const limit = searchOptions?.limit ?? 5;
|
|
5672
5734
|
const scopes = searchOptions?.scopes;
|
|
@@ -5683,6 +5745,12 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
5683
5745
|
let embeddedItems;
|
|
5684
5746
|
let queryEmbedding;
|
|
5685
5747
|
let vaultSize;
|
|
5748
|
+
let embeddingsUnavailable = false;
|
|
5749
|
+
let embeddingFailure = false;
|
|
5750
|
+
const onEmbeddingDegraded = () => {
|
|
5751
|
+
embeddingsUnavailable = true;
|
|
5752
|
+
embeddingFailure = true;
|
|
5753
|
+
};
|
|
5686
5754
|
if (searchOptions?.decryptLast) {
|
|
5687
5755
|
const forceIncludeIds = [
|
|
5688
5756
|
...searchOptions.entityRanking ?? [],
|
|
@@ -5693,14 +5761,30 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
5693
5761
|
admitFactor: ADMIT_FACTOR,
|
|
5694
5762
|
admitFloor: ADMIT_FLOOR,
|
|
5695
5763
|
unembeddedCap: UNEMBEDDED_CAP,
|
|
5696
|
-
...forceIncludeIds.length > 0 && { forceIncludeIds }
|
|
5764
|
+
...forceIncludeIds.length > 0 && { forceIncludeIds },
|
|
5765
|
+
onEmbeddingDegraded
|
|
5697
5766
|
});
|
|
5698
5767
|
if (corpus.vaultSize === 0) {
|
|
5699
|
-
return {
|
|
5768
|
+
return {
|
|
5769
|
+
memories: [],
|
|
5770
|
+
embeddedItems: [],
|
|
5771
|
+
queryEmbedding: [],
|
|
5772
|
+
vaultSize: 0,
|
|
5773
|
+
embeddingsUnavailable: false,
|
|
5774
|
+
embeddingFailure: false
|
|
5775
|
+
};
|
|
5700
5776
|
}
|
|
5701
5777
|
({ memories, embeddedItems, queryEmbedding, vaultSize } = corpus);
|
|
5778
|
+
if (corpus.laneEmbedFailed) embeddingFailure = true;
|
|
5702
5779
|
if (memories.length === 0) {
|
|
5703
|
-
return {
|
|
5780
|
+
return {
|
|
5781
|
+
memories: [],
|
|
5782
|
+
embeddedItems: [],
|
|
5783
|
+
queryEmbedding: [],
|
|
5784
|
+
vaultSize,
|
|
5785
|
+
embeddingsUnavailable,
|
|
5786
|
+
embeddingFailure
|
|
5787
|
+
};
|
|
5704
5788
|
}
|
|
5705
5789
|
} else {
|
|
5706
5790
|
const loaded = await getAllVaultMemoriesOp(
|
|
@@ -5715,14 +5799,21 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
5715
5799
|
);
|
|
5716
5800
|
}
|
|
5717
5801
|
if (memories.length === 0) {
|
|
5718
|
-
return {
|
|
5802
|
+
return {
|
|
5803
|
+
memories: [],
|
|
5804
|
+
embeddedItems: [],
|
|
5805
|
+
queryEmbedding: [],
|
|
5806
|
+
vaultSize: loaded.length,
|
|
5807
|
+
embeddingsUnavailable: false,
|
|
5808
|
+
embeddingFailure: false
|
|
5809
|
+
};
|
|
5719
5810
|
}
|
|
5720
|
-
queryEmbedding = await
|
|
5811
|
+
queryEmbedding = await embedQueryOrDegrade(query, embeddingOptions, onEmbeddingDegraded);
|
|
5721
5812
|
const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
5722
5813
|
const uncachedTexts = [];
|
|
5723
5814
|
const uncachedIndices = [];
|
|
5724
5815
|
let staleReembedCount = 0;
|
|
5725
|
-
for (let i = 0; i < memories.length; i++) {
|
|
5816
|
+
for (let i = 0; queryEmbedding.length > 0 && i < memories.length; i++) {
|
|
5726
5817
|
const content = memories[i].content;
|
|
5727
5818
|
const memoryId = memories[i].uniqueId;
|
|
5728
5819
|
const cached = cache.get(memoryId);
|
|
@@ -5750,20 +5841,30 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
5750
5841
|
);
|
|
5751
5842
|
}
|
|
5752
5843
|
if (uncachedTexts.length > 0) {
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
currentModel
|
|
5761
|
-
).catch(
|
|
5762
|
-
// Silently swallow – SDK must not use console.*; embedding will be retried on next search
|
|
5763
|
-
() => {
|
|
5764
|
-
}
|
|
5844
|
+
let newEmbeddings;
|
|
5845
|
+
try {
|
|
5846
|
+
newEmbeddings = await generateEmbeddings(uncachedTexts, embeddingOptions);
|
|
5847
|
+
} catch (err) {
|
|
5848
|
+
embeddingFailure = true;
|
|
5849
|
+
getLogger().warn(
|
|
5850
|
+
`memoryVault: (re)embedding ${uncachedTexts.length} vault rows failed \u2014 they rank on BM25 alone for this search: ` + (err instanceof Error ? err.message : String(err))
|
|
5765
5851
|
);
|
|
5766
5852
|
}
|
|
5853
|
+
if (newEmbeddings) {
|
|
5854
|
+
for (let j = 0; j < uncachedTexts.length; j++) {
|
|
5855
|
+
cache.set(memories[uncachedIndices[j]].uniqueId, Float32Array.from(newEmbeddings[j]));
|
|
5856
|
+
updateVaultMemoryEmbeddingOp(
|
|
5857
|
+
vaultCtx,
|
|
5858
|
+
memories[uncachedIndices[j]].uniqueId,
|
|
5859
|
+
JSON.stringify(newEmbeddings[j]),
|
|
5860
|
+
currentModel
|
|
5861
|
+
).catch(
|
|
5862
|
+
// Silently swallow – SDK must not use console.*; embedding will be retried on next search
|
|
5863
|
+
() => {
|
|
5864
|
+
}
|
|
5865
|
+
);
|
|
5866
|
+
}
|
|
5867
|
+
}
|
|
5767
5868
|
}
|
|
5768
5869
|
embeddedItems = memories.map((m) => ({
|
|
5769
5870
|
id: m.uniqueId,
|
|
@@ -5780,12 +5881,22 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
5780
5881
|
factType: m.factType
|
|
5781
5882
|
}));
|
|
5782
5883
|
}
|
|
5783
|
-
|
|
5884
|
+
if (!embeddingsUnavailable && !embeddedItems.some((it) => it.embedding.length > 0)) {
|
|
5885
|
+
embeddingsUnavailable = true;
|
|
5886
|
+
}
|
|
5887
|
+
return {
|
|
5888
|
+
memories,
|
|
5889
|
+
embeddedItems,
|
|
5890
|
+
queryEmbedding,
|
|
5891
|
+
vaultSize,
|
|
5892
|
+
embeddingsUnavailable,
|
|
5893
|
+
embeddingFailure
|
|
5894
|
+
};
|
|
5784
5895
|
}
|
|
5785
5896
|
async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, searchOptions) {
|
|
5786
5897
|
const limit = searchOptions?.limit ?? 5;
|
|
5787
5898
|
const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
|
|
5788
|
-
const { memories, embeddedItems, queryEmbedding, vaultSize } = prepared;
|
|
5899
|
+
const { memories, embeddedItems, queryEmbedding, vaultSize, embeddingsUnavailable } = prepared;
|
|
5789
5900
|
if (queryEmbedding.length > 0) {
|
|
5790
5901
|
const mismatched = embeddedItems.filter(
|
|
5791
5902
|
(it) => it.embedding.length > 0 && it.embedding.length !== queryEmbedding.length
|
|
@@ -5822,7 +5933,8 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
5822
5933
|
results: results2,
|
|
5823
5934
|
vaultSize: out.vaultSize,
|
|
5824
5935
|
reranked: out.reranked ?? false,
|
|
5825
|
-
hadV2Head: out.hadV2Head ?? false
|
|
5936
|
+
hadV2Head: out.hadV2Head ?? false,
|
|
5937
|
+
embeddingsUnavailable
|
|
5826
5938
|
};
|
|
5827
5939
|
};
|
|
5828
5940
|
const rerankStats = { applied: false };
|
|
@@ -5845,36 +5957,46 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
5845
5957
|
...searchOptions?.rrfK !== void 0 && { rrfK: searchOptions.rrfK },
|
|
5846
5958
|
...searchOptions?.factTypeWeights && { factTypeWeights: searchOptions.factTypeWeights }
|
|
5847
5959
|
};
|
|
5848
|
-
if (useFusion && searchOptions?.decompose === "llm" && searchOptions.decomposeOptions) {
|
|
5960
|
+
if (useFusion && !embeddingsUnavailable && searchOptions?.decompose === "llm" && searchOptions.decomposeOptions) {
|
|
5849
5961
|
const decomp = await decomposeQuery(query, searchOptions.decomposeOptions);
|
|
5850
5962
|
if (decomp.mode === "composite") {
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5963
|
+
let subEmbeddings;
|
|
5964
|
+
try {
|
|
5965
|
+
subEmbeddings = await generateEmbeddings(decomp.subQueries, embeddingOptions);
|
|
5966
|
+
} catch (err) {
|
|
5967
|
+
getLogger().warn(
|
|
5968
|
+
"memoryVault: sub-query embedding failed \u2014 falling back to single-query ranking: " + (err instanceof Error ? err.message : String(err))
|
|
5969
|
+
);
|
|
5970
|
+
subEmbeddings = [];
|
|
5971
|
+
}
|
|
5972
|
+
if (subEmbeddings.length > 0) {
|
|
5973
|
+
const subQueries = decomp.subQueries.map((sq, i) => ({
|
|
5974
|
+
query: sq,
|
|
5975
|
+
embedding: subEmbeddings[i]
|
|
5976
|
+
}));
|
|
5977
|
+
const v2HeadStats = { hadResults: false };
|
|
5978
|
+
const composite = await rankComposite(query, queryEmbedding, subQueries, embeddedItems, {
|
|
5979
|
+
limit,
|
|
5980
|
+
minSimilarity,
|
|
5981
|
+
rerank: !!searchOptions.rerank,
|
|
5982
|
+
...searchOptions.rerankTopN !== void 0 && {
|
|
5983
|
+
rerankTopN: searchOptions.rerankTopN
|
|
5984
|
+
},
|
|
5985
|
+
...searchOptions.ceWeight !== void 0 && { ceWeight: searchOptions.ceWeight },
|
|
5986
|
+
...searchOptions.mmr !== void 0 && { mmr: searchOptions.mmr },
|
|
5987
|
+
...tuning,
|
|
5988
|
+
...searchOptions.entityRanking && { entityRanking: searchOptions.entityRanking },
|
|
5989
|
+
...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
|
|
5990
|
+
rerankStats,
|
|
5991
|
+
v2HeadStats
|
|
5992
|
+
});
|
|
5993
|
+
return stampTimestamps({
|
|
5994
|
+
results: composite,
|
|
5995
|
+
vaultSize,
|
|
5996
|
+
reranked: rerankStats.applied,
|
|
5997
|
+
hadV2Head: v2HeadStats.hadResults
|
|
5998
|
+
});
|
|
5999
|
+
}
|
|
5878
6000
|
}
|
|
5879
6001
|
}
|
|
5880
6002
|
if (useFusion && searchOptions?.rerank) {
|
|
@@ -5925,7 +6047,14 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
5925
6047
|
}
|
|
5926
6048
|
async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, cache, searchOptions) {
|
|
5927
6049
|
if (!query || typeof query !== "string") {
|
|
5928
|
-
return {
|
|
6050
|
+
return {
|
|
6051
|
+
results: [],
|
|
6052
|
+
vaultSize: 0,
|
|
6053
|
+
reranked: false,
|
|
6054
|
+
hadV2Head: false,
|
|
6055
|
+
embeddingsUnavailable: false,
|
|
6056
|
+
rankedOnCosine: false
|
|
6057
|
+
};
|
|
5929
6058
|
}
|
|
5930
6059
|
const prepared = await prepareVaultCandidates(
|
|
5931
6060
|
query,
|
|
@@ -5935,12 +6064,32 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
5935
6064
|
searchOptions
|
|
5936
6065
|
);
|
|
5937
6066
|
if (prepared.vaultSize === 0) {
|
|
5938
|
-
return {
|
|
6067
|
+
return {
|
|
6068
|
+
results: [],
|
|
6069
|
+
vaultSize: 0,
|
|
6070
|
+
reranked: false,
|
|
6071
|
+
hadV2Head: false,
|
|
6072
|
+
embeddingsUnavailable: prepared.embeddingsUnavailable,
|
|
6073
|
+
rankedOnCosine: false
|
|
6074
|
+
};
|
|
5939
6075
|
}
|
|
5940
6076
|
if (prepared.memories.length === 0) {
|
|
5941
|
-
return {
|
|
6077
|
+
return {
|
|
6078
|
+
results: [],
|
|
6079
|
+
vaultSize: prepared.vaultSize,
|
|
6080
|
+
reranked: false,
|
|
6081
|
+
hadV2Head: false,
|
|
6082
|
+
embeddingsUnavailable: prepared.embeddingsUnavailable,
|
|
6083
|
+
rankedOnCosine: false
|
|
6084
|
+
};
|
|
5942
6085
|
}
|
|
5943
|
-
|
|
6086
|
+
const ranked = await rankPreparedVaultCandidates(
|
|
6087
|
+
query,
|
|
6088
|
+
prepared,
|
|
6089
|
+
embeddingOptions,
|
|
6090
|
+
searchOptions
|
|
6091
|
+
);
|
|
6092
|
+
return { ...ranked, rankedOnCosine: !ranked.embeddingsUnavailable };
|
|
5944
6093
|
}
|
|
5945
6094
|
async function searchVaultMemories(query, vaultCtx, embeddingOptions, cache, searchOptions) {
|
|
5946
6095
|
const { results } = await searchVaultMemoriesWithSize(
|
|
@@ -5952,6 +6101,7 @@ async function searchVaultMemories(query, vaultCtx, embeddingOptions, cache, sea
|
|
|
5952
6101
|
);
|
|
5953
6102
|
return results;
|
|
5954
6103
|
}
|
|
6104
|
+
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.";
|
|
5955
6105
|
function formatVaultHits(hits) {
|
|
5956
6106
|
return hits.map((h, i) => `[${i + 1}] (id: ${h.id}, similarity: ${h.score.toFixed(2)})
|
|
5957
6107
|
${h.content}`).join("\n\n");
|
|
@@ -6014,26 +6164,36 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
6014
6164
|
const budget = searchOptions?.decompose === "llm" && searchOptions.decomposeOptions ? "high" : searchOptions?.rerank ? "mid" : "low";
|
|
6015
6165
|
const folderId = searchOptions?.folderId ?? argFolderId;
|
|
6016
6166
|
if (searchOptions?.useFusion === false) {
|
|
6017
|
-
const legacy = await
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6167
|
+
const { results: legacy, embeddingsUnavailable } = await searchVaultMemoriesWithSize(
|
|
6168
|
+
query,
|
|
6169
|
+
vaultCtx,
|
|
6170
|
+
embeddingOptions,
|
|
6171
|
+
cache,
|
|
6172
|
+
{
|
|
6173
|
+
limit: requestLimit,
|
|
6174
|
+
minSimilarity,
|
|
6175
|
+
useFusion: false,
|
|
6176
|
+
...tuningForward,
|
|
6177
|
+
...folderId !== void 0 && { folderId },
|
|
6178
|
+
...searchOptions?.scopes && { scopes: searchOptions.scopes }
|
|
6179
|
+
}
|
|
6180
|
+
);
|
|
6025
6181
|
if (legacy.length === 0) {
|
|
6026
|
-
return "No relevant memories found in the vault.";
|
|
6182
|
+
return embeddingsUnavailable ? EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL : "No relevant memories found in the vault.";
|
|
6027
6183
|
}
|
|
6028
6184
|
return formatVaultHits(
|
|
6029
6185
|
legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
|
|
6030
6186
|
);
|
|
6031
6187
|
}
|
|
6032
|
-
const { recall: recall2 } = await import("./recall-
|
|
6188
|
+
const { recall: recall2 } = await import("./recall-DOFCEH2I.mjs");
|
|
6189
|
+
let recallDegraded = [];
|
|
6033
6190
|
const result = await recall2(
|
|
6034
6191
|
query,
|
|
6035
6192
|
{ vaultCtx, embeddingOptions, vaultCache: cache },
|
|
6036
6193
|
{
|
|
6194
|
+
onDiagnostics: (d) => {
|
|
6195
|
+
recallDegraded = d.degraded;
|
|
6196
|
+
},
|
|
6037
6197
|
types: ["fact"],
|
|
6038
6198
|
limit: requestLimit,
|
|
6039
6199
|
minScore: minSimilarity,
|
|
@@ -6054,7 +6214,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
6054
6214
|
return "The memory vault is empty. No memories have been saved yet.";
|
|
6055
6215
|
}
|
|
6056
6216
|
if (result.memories.length === 0) {
|
|
6057
|
-
return "No relevant memories found in the vault.";
|
|
6217
|
+
return recallDegraded.includes("embeddings-unavailable") ? EMBEDDINGS_DEGRADED_EMPTY : "No relevant memories found in the vault.";
|
|
6058
6218
|
}
|
|
6059
6219
|
const formatted = formatVaultHits(
|
|
6060
6220
|
result.memories.map((m) => ({
|
|
@@ -6609,6 +6769,9 @@ async function recall(query, ctx, options = {}) {
|
|
|
6609
6769
|
let vaultSize;
|
|
6610
6770
|
let didRerank = false;
|
|
6611
6771
|
let hadV2Head = false;
|
|
6772
|
+
let embeddingsUnavailable = false;
|
|
6773
|
+
let chunkEmbedFailed = false;
|
|
6774
|
+
let factLaneRankedOnCosine = false;
|
|
6612
6775
|
const emitDiagnostics = (candidateCount) => {
|
|
6613
6776
|
const cb = options.onDiagnostics;
|
|
6614
6777
|
if (!cb) return;
|
|
@@ -6617,6 +6780,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
6617
6780
|
degraded.push("rerank-unavailable");
|
|
6618
6781
|
}
|
|
6619
6782
|
if (flags.decompose && !decomposeAvailable) degraded.push("decompose-unavailable");
|
|
6783
|
+
if (embeddingsUnavailable) degraded.push("embeddings-unavailable");
|
|
6620
6784
|
const diagnostics = {
|
|
6621
6785
|
usedBudget,
|
|
6622
6786
|
reranked: didRerank,
|
|
@@ -6647,7 +6811,26 @@ async function recall(query, ctx, options = {}) {
|
|
|
6647
6811
|
const graphRefiner = flags.traverse && options.graphRefine && options.decomposeOptions ? createLlmNeighborRefiner(options.decomposeOptions) : void 0;
|
|
6648
6812
|
const prepStart = nowMs();
|
|
6649
6813
|
const [queryEmbedding, entityRanking, temporalRanking] = await Promise.all([
|
|
6650
|
-
|
|
6814
|
+
// The chunk lane is cosine-only — `searchChunksOp` needs a real vector, and
|
|
6815
|
+
// there is no lexical fallback for it — so an embeddings outage must SKIP the
|
|
6816
|
+
// lane, not reject this shared Promise.all and take the primary fact lane
|
|
6817
|
+
// (which BM25 can still serve) down with it. Mirrors safeLane's posture.
|
|
6818
|
+
needsChunkEmbedding ? generateEmbedding(query, ctx.embeddingOptions).then((vec) => {
|
|
6819
|
+
if (vec.length === 0) {
|
|
6820
|
+
getLogger().warn(
|
|
6821
|
+
"[memory/recall] chunk-lane query embedding came back empty; skipping the chunk lane"
|
|
6822
|
+
);
|
|
6823
|
+
chunkEmbedFailed = true;
|
|
6824
|
+
return void 0;
|
|
6825
|
+
}
|
|
6826
|
+
return vec;
|
|
6827
|
+
}).catch((err) => {
|
|
6828
|
+
getLogger().warn(
|
|
6829
|
+
`[memory/recall] chunk-lane query embedding failed; skipping the chunk lane: ${err instanceof Error ? err.message : String(err)}`
|
|
6830
|
+
);
|
|
6831
|
+
chunkEmbedFailed = true;
|
|
6832
|
+
return void 0;
|
|
6833
|
+
}) : Promise.resolve(void 0),
|
|
6651
6834
|
// The graph + temporal lanes are AUXILIARY (RRF side-signals). A transient
|
|
6652
6835
|
// WatermelonDB throw in either must NOT reject this Promise.all and take
|
|
6653
6836
|
// PRIMARY cosine/BM25 recall down with it — degrade the failing lane to an
|
|
@@ -6672,7 +6855,9 @@ async function recall(query, ctx, options = {}) {
|
|
|
6672
6855
|
results,
|
|
6673
6856
|
vaultSize: size,
|
|
6674
6857
|
reranked,
|
|
6675
|
-
hadV2Head: v2Head
|
|
6858
|
+
hadV2Head: v2Head,
|
|
6859
|
+
embeddingsUnavailable: factEmbeddingsUnavailable,
|
|
6860
|
+
rankedOnCosine: factRankedOnCosine
|
|
6676
6861
|
} = await searchVaultMemoriesWithSize(
|
|
6677
6862
|
query,
|
|
6678
6863
|
ctx.vaultCtx,
|
|
@@ -6729,8 +6914,11 @@ async function recall(query, ctx, options = {}) {
|
|
|
6729
6914
|
vaultSize = size;
|
|
6730
6915
|
didRerank = reranked;
|
|
6731
6916
|
hadV2Head = v2Head;
|
|
6917
|
+
if (factEmbeddingsUnavailable) embeddingsUnavailable = true;
|
|
6918
|
+
factLaneRankedOnCosine = factRankedOnCosine;
|
|
6732
6919
|
factLaneMs = nowMs() - factStart;
|
|
6733
6920
|
}
|
|
6921
|
+
if (chunkEmbedFailed && !factLaneRankedOnCosine) embeddingsUnavailable = true;
|
|
6734
6922
|
if (types.includes("chunk") && ctx.storageCtx && queryEmbedding) {
|
|
6735
6923
|
const chunkStart = nowMs();
|
|
6736
6924
|
const chunkMinScore = options.minScore ?? DEFAULT_CHUNK_MIN_SCORE;
|
|
@@ -7070,6 +7258,9 @@ export {
|
|
|
7070
7258
|
restoreVaultMemoryOp,
|
|
7071
7259
|
hardDeleteDecayedOp,
|
|
7072
7260
|
updateVaultMemoryEmbeddingOp,
|
|
7261
|
+
RECALL_TOOL_NAME,
|
|
7262
|
+
RECALL_MAX_LIMIT,
|
|
7263
|
+
EMBEDDINGS_DEGRADED_EMPTY,
|
|
7073
7264
|
RerankerUnavailableError,
|
|
7074
7265
|
isRerankerAvailable,
|
|
7075
7266
|
DEFAULT_VAULT_CACHE_SIZE,
|