@anuma/sdk 3.11.2 → 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 +303 -99
- package/dist/expo/index.d.mts +14 -1
- package/dist/expo/index.d.ts +14 -1
- package/dist/expo/index.mjs +16 -5
- 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 +303 -99
- package/dist/react/index.d.mts +14 -1
- package/dist/react/index.d.ts +14 -1
- package/dist/react/index.mjs +16 -5
- 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 +302 -99
- package/dist/server/index.d.mts +14 -1
- package/dist/server/index.d.ts +14 -1
- package/dist/server/index.mjs +16 -5
- package/dist/server/{recall-AN7HBEFS.mjs → recall-QH3YX6T4.mjs} +1 -1
- package/package.json +1 -1
|
@@ -4273,6 +4273,11 @@ function applyMMR(candidates, k, lambda = 0.5) {
|
|
|
4273
4273
|
return selected;
|
|
4274
4274
|
}
|
|
4275
4275
|
|
|
4276
|
+
// src/lib/memory/recallConstants.ts
|
|
4277
|
+
var RECALL_TOOL_NAME = "recall_memory";
|
|
4278
|
+
var RECALL_MAX_LIMIT = 50;
|
|
4279
|
+
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.";
|
|
4280
|
+
|
|
4276
4281
|
// src/lib/memory/recency.ts
|
|
4277
4282
|
var DAY_MS = 1e3 * 60 * 60 * 24;
|
|
4278
4283
|
var DEFAULT_PER_YEAR_DECAY = 0.2;
|
|
@@ -5255,6 +5260,24 @@ async function eagerEmbedContent(content, embeddingOptions, cache, vaultCtx, mem
|
|
|
5255
5260
|
);
|
|
5256
5261
|
}
|
|
5257
5262
|
}
|
|
5263
|
+
async function embedQueryOrDegrade(query, embeddingOptions, onDegraded) {
|
|
5264
|
+
try {
|
|
5265
|
+
const embedding = await generateEmbedding(query, embeddingOptions);
|
|
5266
|
+
if (embedding.length === 0) {
|
|
5267
|
+
getLogger().warn(
|
|
5268
|
+
"memoryVault: query embedding came back empty \u2014 falling back to BM25-only ranking for this search"
|
|
5269
|
+
);
|
|
5270
|
+
onDegraded?.();
|
|
5271
|
+
}
|
|
5272
|
+
return embedding;
|
|
5273
|
+
} catch (err) {
|
|
5274
|
+
getLogger().warn(
|
|
5275
|
+
"memoryVault: query embedding failed \u2014 falling back to BM25-only ranking for this search: " + (err instanceof Error ? err.message : String(err))
|
|
5276
|
+
);
|
|
5277
|
+
onDegraded?.();
|
|
5278
|
+
return [];
|
|
5279
|
+
}
|
|
5280
|
+
}
|
|
5258
5281
|
function admitVaultProjections(queryEmbedding, vectored, k) {
|
|
5259
5282
|
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);
|
|
5260
5283
|
}
|
|
@@ -5266,23 +5289,36 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
|
|
|
5266
5289
|
const hydrateOpts = queryOpts.includeArchived ? { includeArchived: true } : void 0;
|
|
5267
5290
|
const vaultSize = keys.length;
|
|
5268
5291
|
if (keys.length === 0) {
|
|
5269
|
-
return {
|
|
5292
|
+
return {
|
|
5293
|
+
memories: [],
|
|
5294
|
+
embeddedItems: [],
|
|
5295
|
+
queryEmbedding: [],
|
|
5296
|
+
vaultSize: 0,
|
|
5297
|
+
laneEmbedFailed: false
|
|
5298
|
+
};
|
|
5270
5299
|
}
|
|
5271
|
-
const queryEmbedding = await
|
|
5300
|
+
const queryEmbedding = await embedQueryOrDegrade(
|
|
5301
|
+
query,
|
|
5302
|
+
embeddingOptions,
|
|
5303
|
+
opts.onEmbeddingDegraded
|
|
5304
|
+
);
|
|
5305
|
+
const embeddingsDegraded = queryEmbedding.length === 0;
|
|
5272
5306
|
const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
5273
5307
|
const vectored = [];
|
|
5274
5308
|
const missIds = [];
|
|
5275
5309
|
const noVectorIds = [];
|
|
5276
5310
|
const keyById = new Map(keys.map((k2) => [k2.uniqueId, k2]));
|
|
5277
|
-
|
|
5278
|
-
const
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5311
|
+
if (!embeddingsDegraded) {
|
|
5312
|
+
for (const k2 of keys) {
|
|
5313
|
+
const cached = cache.get(k2.uniqueId);
|
|
5314
|
+
if (cached && cached.length === queryEmbedding.length) {
|
|
5315
|
+
vectored.push({ uniqueId: k2.uniqueId, embedding: cached, updatedAt: k2.updatedAt });
|
|
5316
|
+
continue;
|
|
5317
|
+
}
|
|
5318
|
+
const modelCompatible = (k2.embeddingModel ?? currentModel) === currentModel;
|
|
5319
|
+
if (modelCompatible) missIds.push(k2.uniqueId);
|
|
5320
|
+
else noVectorIds.push(k2.uniqueId);
|
|
5282
5321
|
}
|
|
5283
|
-
const modelCompatible = (k2.embeddingModel ?? currentModel) === currentModel;
|
|
5284
|
-
if (modelCompatible) missIds.push(k2.uniqueId);
|
|
5285
|
-
else noVectorIds.push(k2.uniqueId);
|
|
5286
5322
|
}
|
|
5287
5323
|
if (missIds.length > 0) {
|
|
5288
5324
|
const rows = await getVaultEmbeddingsByIdsOp(vaultCtx, missIds, hydrateOpts);
|
|
@@ -5303,6 +5339,7 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
|
|
|
5303
5339
|
}
|
|
5304
5340
|
for (const id of missIds) if (!gotVector.has(id)) noVectorIds.push(id);
|
|
5305
5341
|
}
|
|
5342
|
+
let laneEmbedFailed = false;
|
|
5306
5343
|
if (noVectorIds.length > 0) {
|
|
5307
5344
|
const laneIds = noVectorIds.slice(0, opts.unembeddedCap);
|
|
5308
5345
|
if (noVectorIds.length > laneIds.length) {
|
|
@@ -5314,26 +5351,44 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
|
|
|
5314
5351
|
(m) => !isEncrypted(m.content)
|
|
5315
5352
|
);
|
|
5316
5353
|
if (laneRows.length > 0) {
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5354
|
+
let laneVecs;
|
|
5355
|
+
try {
|
|
5356
|
+
laneVecs = await generateEmbeddings(
|
|
5357
|
+
laneRows.map((m) => m.content),
|
|
5358
|
+
embeddingOptions
|
|
5359
|
+
);
|
|
5360
|
+
} catch (err) {
|
|
5361
|
+
laneEmbedFailed = true;
|
|
5362
|
+
getLogger().warn(
|
|
5363
|
+
`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))
|
|
5364
|
+
);
|
|
5365
|
+
}
|
|
5366
|
+
if (laneVecs) {
|
|
5367
|
+
const vecs = laneVecs;
|
|
5368
|
+
laneRows.forEach((m, i) => {
|
|
5369
|
+
const vec = Float32Array.from(vecs[i]);
|
|
5370
|
+
cache.set(m.uniqueId, vec);
|
|
5371
|
+
vectored.push({ uniqueId: m.uniqueId, embedding: vec, updatedAt: m.updatedAt });
|
|
5372
|
+
updateVaultMemoryEmbeddingOp(
|
|
5373
|
+
vaultCtx,
|
|
5374
|
+
m.uniqueId,
|
|
5375
|
+
JSON.stringify(vecs[i]),
|
|
5376
|
+
currentModel
|
|
5377
|
+
).catch(() => {
|
|
5378
|
+
});
|
|
5331
5379
|
});
|
|
5332
|
-
}
|
|
5380
|
+
}
|
|
5333
5381
|
}
|
|
5334
5382
|
}
|
|
5335
5383
|
const k = Math.max(opts.limit * opts.admitFactor, opts.admitFloor);
|
|
5336
5384
|
const admittedIds = admitVaultProjections(queryEmbedding, vectored, k);
|
|
5385
|
+
if ((embeddingsDegraded || laneEmbedFailed) && admittedIds.length < k) {
|
|
5386
|
+
const already = new Set(admittedIds);
|
|
5387
|
+
for (const key of [...keys].sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime())) {
|
|
5388
|
+
if (admittedIds.length >= k) break;
|
|
5389
|
+
if (!already.has(key.uniqueId)) admittedIds.push(key.uniqueId);
|
|
5390
|
+
}
|
|
5391
|
+
}
|
|
5337
5392
|
const admissionSet = new Set(admittedIds);
|
|
5338
5393
|
if (opts.forceIncludeIds) {
|
|
5339
5394
|
for (const id of opts.forceIncludeIds) {
|
|
@@ -5361,11 +5416,18 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
|
|
|
5361
5416
|
eventTimeKind: normalizeEventTimeKind(m.eventTimeKind),
|
|
5362
5417
|
factType: m.factType
|
|
5363
5418
|
}));
|
|
5364
|
-
return { memories, embeddedItems, queryEmbedding, vaultSize };
|
|
5419
|
+
return { memories, embeddedItems, queryEmbedding, vaultSize, laneEmbedFailed };
|
|
5365
5420
|
}
|
|
5366
5421
|
async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache, searchOptions) {
|
|
5367
5422
|
if (!query || typeof query !== "string") {
|
|
5368
|
-
return {
|
|
5423
|
+
return {
|
|
5424
|
+
memories: [],
|
|
5425
|
+
embeddedItems: [],
|
|
5426
|
+
queryEmbedding: [],
|
|
5427
|
+
vaultSize: 0,
|
|
5428
|
+
embeddingsUnavailable: false,
|
|
5429
|
+
embeddingFailure: false
|
|
5430
|
+
};
|
|
5369
5431
|
}
|
|
5370
5432
|
const limit = searchOptions?.limit ?? 5;
|
|
5371
5433
|
const scopes = searchOptions?.scopes;
|
|
@@ -5382,6 +5444,12 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
5382
5444
|
let embeddedItems;
|
|
5383
5445
|
let queryEmbedding;
|
|
5384
5446
|
let vaultSize;
|
|
5447
|
+
let embeddingsUnavailable = false;
|
|
5448
|
+
let embeddingFailure = false;
|
|
5449
|
+
const onEmbeddingDegraded = () => {
|
|
5450
|
+
embeddingsUnavailable = true;
|
|
5451
|
+
embeddingFailure = true;
|
|
5452
|
+
};
|
|
5385
5453
|
if (searchOptions?.decryptLast) {
|
|
5386
5454
|
const forceIncludeIds = [
|
|
5387
5455
|
...searchOptions.entityRanking ?? [],
|
|
@@ -5392,14 +5460,30 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
5392
5460
|
admitFactor: ADMIT_FACTOR,
|
|
5393
5461
|
admitFloor: ADMIT_FLOOR,
|
|
5394
5462
|
unembeddedCap: UNEMBEDDED_CAP,
|
|
5395
|
-
...forceIncludeIds.length > 0 && { forceIncludeIds }
|
|
5463
|
+
...forceIncludeIds.length > 0 && { forceIncludeIds },
|
|
5464
|
+
onEmbeddingDegraded
|
|
5396
5465
|
});
|
|
5397
5466
|
if (corpus.vaultSize === 0) {
|
|
5398
|
-
return {
|
|
5467
|
+
return {
|
|
5468
|
+
memories: [],
|
|
5469
|
+
embeddedItems: [],
|
|
5470
|
+
queryEmbedding: [],
|
|
5471
|
+
vaultSize: 0,
|
|
5472
|
+
embeddingsUnavailable: false,
|
|
5473
|
+
embeddingFailure: false
|
|
5474
|
+
};
|
|
5399
5475
|
}
|
|
5400
5476
|
({ memories, embeddedItems, queryEmbedding, vaultSize } = corpus);
|
|
5477
|
+
if (corpus.laneEmbedFailed) embeddingFailure = true;
|
|
5401
5478
|
if (memories.length === 0) {
|
|
5402
|
-
return {
|
|
5479
|
+
return {
|
|
5480
|
+
memories: [],
|
|
5481
|
+
embeddedItems: [],
|
|
5482
|
+
queryEmbedding: [],
|
|
5483
|
+
vaultSize,
|
|
5484
|
+
embeddingsUnavailable,
|
|
5485
|
+
embeddingFailure
|
|
5486
|
+
};
|
|
5403
5487
|
}
|
|
5404
5488
|
} else {
|
|
5405
5489
|
const loaded = await getAllVaultMemoriesOp(
|
|
@@ -5414,14 +5498,21 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
5414
5498
|
);
|
|
5415
5499
|
}
|
|
5416
5500
|
if (memories.length === 0) {
|
|
5417
|
-
return {
|
|
5501
|
+
return {
|
|
5502
|
+
memories: [],
|
|
5503
|
+
embeddedItems: [],
|
|
5504
|
+
queryEmbedding: [],
|
|
5505
|
+
vaultSize: loaded.length,
|
|
5506
|
+
embeddingsUnavailable: false,
|
|
5507
|
+
embeddingFailure: false
|
|
5508
|
+
};
|
|
5418
5509
|
}
|
|
5419
|
-
queryEmbedding = await
|
|
5510
|
+
queryEmbedding = await embedQueryOrDegrade(query, embeddingOptions, onEmbeddingDegraded);
|
|
5420
5511
|
const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
5421
5512
|
const uncachedTexts = [];
|
|
5422
5513
|
const uncachedIndices = [];
|
|
5423
5514
|
let staleReembedCount = 0;
|
|
5424
|
-
for (let i = 0; i < memories.length; i++) {
|
|
5515
|
+
for (let i = 0; queryEmbedding.length > 0 && i < memories.length; i++) {
|
|
5425
5516
|
const content = memories[i].content;
|
|
5426
5517
|
const memoryId = memories[i].uniqueId;
|
|
5427
5518
|
const cached = cache.get(memoryId);
|
|
@@ -5449,20 +5540,30 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
5449
5540
|
);
|
|
5450
5541
|
}
|
|
5451
5542
|
if (uncachedTexts.length > 0) {
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
currentModel
|
|
5460
|
-
).catch(
|
|
5461
|
-
// Silently swallow – SDK must not use console.*; embedding will be retried on next search
|
|
5462
|
-
() => {
|
|
5463
|
-
}
|
|
5543
|
+
let newEmbeddings;
|
|
5544
|
+
try {
|
|
5545
|
+
newEmbeddings = await generateEmbeddings(uncachedTexts, embeddingOptions);
|
|
5546
|
+
} catch (err) {
|
|
5547
|
+
embeddingFailure = true;
|
|
5548
|
+
getLogger().warn(
|
|
5549
|
+
`memoryVault: (re)embedding ${uncachedTexts.length} vault rows failed \u2014 they rank on BM25 alone for this search: ` + (err instanceof Error ? err.message : String(err))
|
|
5464
5550
|
);
|
|
5465
5551
|
}
|
|
5552
|
+
if (newEmbeddings) {
|
|
5553
|
+
for (let j = 0; j < uncachedTexts.length; j++) {
|
|
5554
|
+
cache.set(memories[uncachedIndices[j]].uniqueId, Float32Array.from(newEmbeddings[j]));
|
|
5555
|
+
updateVaultMemoryEmbeddingOp(
|
|
5556
|
+
vaultCtx,
|
|
5557
|
+
memories[uncachedIndices[j]].uniqueId,
|
|
5558
|
+
JSON.stringify(newEmbeddings[j]),
|
|
5559
|
+
currentModel
|
|
5560
|
+
).catch(
|
|
5561
|
+
// Silently swallow – SDK must not use console.*; embedding will be retried on next search
|
|
5562
|
+
() => {
|
|
5563
|
+
}
|
|
5564
|
+
);
|
|
5565
|
+
}
|
|
5566
|
+
}
|
|
5466
5567
|
}
|
|
5467
5568
|
embeddedItems = memories.map((m) => ({
|
|
5468
5569
|
id: m.uniqueId,
|
|
@@ -5479,12 +5580,22 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
5479
5580
|
factType: m.factType
|
|
5480
5581
|
}));
|
|
5481
5582
|
}
|
|
5482
|
-
|
|
5583
|
+
if (!embeddingsUnavailable && !embeddedItems.some((it) => it.embedding.length > 0)) {
|
|
5584
|
+
embeddingsUnavailable = true;
|
|
5585
|
+
}
|
|
5586
|
+
return {
|
|
5587
|
+
memories,
|
|
5588
|
+
embeddedItems,
|
|
5589
|
+
queryEmbedding,
|
|
5590
|
+
vaultSize,
|
|
5591
|
+
embeddingsUnavailable,
|
|
5592
|
+
embeddingFailure
|
|
5593
|
+
};
|
|
5483
5594
|
}
|
|
5484
5595
|
async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, searchOptions) {
|
|
5485
5596
|
const limit = searchOptions?.limit ?? 5;
|
|
5486
5597
|
const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
|
|
5487
|
-
const { memories, embeddedItems, queryEmbedding, vaultSize } = prepared;
|
|
5598
|
+
const { memories, embeddedItems, queryEmbedding, vaultSize, embeddingsUnavailable } = prepared;
|
|
5488
5599
|
if (queryEmbedding.length > 0) {
|
|
5489
5600
|
const mismatched = embeddedItems.filter(
|
|
5490
5601
|
(it) => it.embedding.length > 0 && it.embedding.length !== queryEmbedding.length
|
|
@@ -5521,7 +5632,8 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
5521
5632
|
results: results2,
|
|
5522
5633
|
vaultSize: out.vaultSize,
|
|
5523
5634
|
reranked: out.reranked ?? false,
|
|
5524
|
-
hadV2Head: out.hadV2Head ?? false
|
|
5635
|
+
hadV2Head: out.hadV2Head ?? false,
|
|
5636
|
+
embeddingsUnavailable
|
|
5525
5637
|
};
|
|
5526
5638
|
};
|
|
5527
5639
|
const rerankStats = { applied: false };
|
|
@@ -5544,36 +5656,46 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
5544
5656
|
...searchOptions?.rrfK !== void 0 && { rrfK: searchOptions.rrfK },
|
|
5545
5657
|
...searchOptions?.factTypeWeights && { factTypeWeights: searchOptions.factTypeWeights }
|
|
5546
5658
|
};
|
|
5547
|
-
if (useFusion && searchOptions?.decompose === "llm" && searchOptions.decomposeOptions) {
|
|
5659
|
+
if (useFusion && !embeddingsUnavailable && searchOptions?.decompose === "llm" && searchOptions.decomposeOptions) {
|
|
5548
5660
|
const decomp = await decomposeQuery(query, searchOptions.decomposeOptions);
|
|
5549
5661
|
if (decomp.mode === "composite") {
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5662
|
+
let subEmbeddings;
|
|
5663
|
+
try {
|
|
5664
|
+
subEmbeddings = await generateEmbeddings(decomp.subQueries, embeddingOptions);
|
|
5665
|
+
} catch (err) {
|
|
5666
|
+
getLogger().warn(
|
|
5667
|
+
"memoryVault: sub-query embedding failed \u2014 falling back to single-query ranking: " + (err instanceof Error ? err.message : String(err))
|
|
5668
|
+
);
|
|
5669
|
+
subEmbeddings = [];
|
|
5670
|
+
}
|
|
5671
|
+
if (subEmbeddings.length > 0) {
|
|
5672
|
+
const subQueries = decomp.subQueries.map((sq, i) => ({
|
|
5673
|
+
query: sq,
|
|
5674
|
+
embedding: subEmbeddings[i]
|
|
5675
|
+
}));
|
|
5676
|
+
const v2HeadStats = { hadResults: false };
|
|
5677
|
+
const composite = await rankComposite(query, queryEmbedding, subQueries, embeddedItems, {
|
|
5678
|
+
limit,
|
|
5679
|
+
minSimilarity,
|
|
5680
|
+
rerank: !!searchOptions.rerank,
|
|
5681
|
+
...searchOptions.rerankTopN !== void 0 && {
|
|
5682
|
+
rerankTopN: searchOptions.rerankTopN
|
|
5683
|
+
},
|
|
5684
|
+
...searchOptions.ceWeight !== void 0 && { ceWeight: searchOptions.ceWeight },
|
|
5685
|
+
...searchOptions.mmr !== void 0 && { mmr: searchOptions.mmr },
|
|
5686
|
+
...tuning,
|
|
5687
|
+
...searchOptions.entityRanking && { entityRanking: searchOptions.entityRanking },
|
|
5688
|
+
...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
|
|
5689
|
+
rerankStats,
|
|
5690
|
+
v2HeadStats
|
|
5691
|
+
});
|
|
5692
|
+
return stampTimestamps({
|
|
5693
|
+
results: composite,
|
|
5694
|
+
vaultSize,
|
|
5695
|
+
reranked: rerankStats.applied,
|
|
5696
|
+
hadV2Head: v2HeadStats.hadResults
|
|
5697
|
+
});
|
|
5698
|
+
}
|
|
5577
5699
|
}
|
|
5578
5700
|
}
|
|
5579
5701
|
if (useFusion && searchOptions?.rerank) {
|
|
@@ -5624,7 +5746,14 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
5624
5746
|
}
|
|
5625
5747
|
async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, cache, searchOptions) {
|
|
5626
5748
|
if (!query || typeof query !== "string") {
|
|
5627
|
-
return {
|
|
5749
|
+
return {
|
|
5750
|
+
results: [],
|
|
5751
|
+
vaultSize: 0,
|
|
5752
|
+
reranked: false,
|
|
5753
|
+
hadV2Head: false,
|
|
5754
|
+
embeddingsUnavailable: false,
|
|
5755
|
+
rankedOnCosine: false
|
|
5756
|
+
};
|
|
5628
5757
|
}
|
|
5629
5758
|
const prepared = await prepareVaultCandidates(
|
|
5630
5759
|
query,
|
|
@@ -5634,12 +5763,32 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
5634
5763
|
searchOptions
|
|
5635
5764
|
);
|
|
5636
5765
|
if (prepared.vaultSize === 0) {
|
|
5637
|
-
return {
|
|
5766
|
+
return {
|
|
5767
|
+
results: [],
|
|
5768
|
+
vaultSize: 0,
|
|
5769
|
+
reranked: false,
|
|
5770
|
+
hadV2Head: false,
|
|
5771
|
+
embeddingsUnavailable: prepared.embeddingsUnavailable,
|
|
5772
|
+
rankedOnCosine: false
|
|
5773
|
+
};
|
|
5638
5774
|
}
|
|
5639
5775
|
if (prepared.memories.length === 0) {
|
|
5640
|
-
return {
|
|
5776
|
+
return {
|
|
5777
|
+
results: [],
|
|
5778
|
+
vaultSize: prepared.vaultSize,
|
|
5779
|
+
reranked: false,
|
|
5780
|
+
hadV2Head: false,
|
|
5781
|
+
embeddingsUnavailable: prepared.embeddingsUnavailable,
|
|
5782
|
+
rankedOnCosine: false
|
|
5783
|
+
};
|
|
5641
5784
|
}
|
|
5642
|
-
|
|
5785
|
+
const ranked = await rankPreparedVaultCandidates(
|
|
5786
|
+
query,
|
|
5787
|
+
prepared,
|
|
5788
|
+
embeddingOptions,
|
|
5789
|
+
searchOptions
|
|
5790
|
+
);
|
|
5791
|
+
return { ...ranked, rankedOnCosine: !ranked.embeddingsUnavailable };
|
|
5643
5792
|
}
|
|
5644
5793
|
async function searchVaultMemories(query, vaultCtx, embeddingOptions, cache, searchOptions) {
|
|
5645
5794
|
const { results } = await searchVaultMemoriesWithSize(
|
|
@@ -5651,6 +5800,7 @@ async function searchVaultMemories(query, vaultCtx, embeddingOptions, cache, sea
|
|
|
5651
5800
|
);
|
|
5652
5801
|
return results;
|
|
5653
5802
|
}
|
|
5803
|
+
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.";
|
|
5654
5804
|
function formatVaultHits(hits) {
|
|
5655
5805
|
return hits.map((h, i) => `[${i + 1}] (id: ${h.id}, similarity: ${h.score.toFixed(2)})
|
|
5656
5806
|
${h.content}`).join("\n\n");
|
|
@@ -5713,26 +5863,36 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
5713
5863
|
const budget = searchOptions?.decompose === "llm" && searchOptions.decomposeOptions ? "high" : searchOptions?.rerank ? "mid" : "low";
|
|
5714
5864
|
const folderId = searchOptions?.folderId ?? argFolderId;
|
|
5715
5865
|
if (searchOptions?.useFusion === false) {
|
|
5716
|
-
const legacy = await
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5866
|
+
const { results: legacy, embeddingsUnavailable } = await searchVaultMemoriesWithSize(
|
|
5867
|
+
query,
|
|
5868
|
+
vaultCtx,
|
|
5869
|
+
embeddingOptions,
|
|
5870
|
+
cache,
|
|
5871
|
+
{
|
|
5872
|
+
limit: requestLimit,
|
|
5873
|
+
minSimilarity,
|
|
5874
|
+
useFusion: false,
|
|
5875
|
+
...tuningForward,
|
|
5876
|
+
...folderId !== void 0 && { folderId },
|
|
5877
|
+
...searchOptions?.scopes && { scopes: searchOptions.scopes }
|
|
5878
|
+
}
|
|
5879
|
+
);
|
|
5724
5880
|
if (legacy.length === 0) {
|
|
5725
|
-
return "No relevant memories found in the vault.";
|
|
5881
|
+
return embeddingsUnavailable ? EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL : "No relevant memories found in the vault.";
|
|
5726
5882
|
}
|
|
5727
5883
|
return formatVaultHits(
|
|
5728
5884
|
legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
|
|
5729
5885
|
);
|
|
5730
5886
|
}
|
|
5731
|
-
const { recall: recall2 } = await import("./recall-
|
|
5887
|
+
const { recall: recall2 } = await import("./recall-JWQ4IJX6.mjs");
|
|
5888
|
+
let recallDegraded = [];
|
|
5732
5889
|
const result = await recall2(
|
|
5733
5890
|
query,
|
|
5734
5891
|
{ vaultCtx, embeddingOptions, vaultCache: cache },
|
|
5735
5892
|
{
|
|
5893
|
+
onDiagnostics: (d) => {
|
|
5894
|
+
recallDegraded = d.degraded;
|
|
5895
|
+
},
|
|
5736
5896
|
types: ["fact"],
|
|
5737
5897
|
limit: requestLimit,
|
|
5738
5898
|
minScore: minSimilarity,
|
|
@@ -5753,7 +5913,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
5753
5913
|
return "The memory vault is empty. No memories have been saved yet.";
|
|
5754
5914
|
}
|
|
5755
5915
|
if (result.memories.length === 0) {
|
|
5756
|
-
return "No relevant memories found in the vault.";
|
|
5916
|
+
return recallDegraded.includes("embeddings-unavailable") ? EMBEDDINGS_DEGRADED_EMPTY : "No relevant memories found in the vault.";
|
|
5757
5917
|
}
|
|
5758
5918
|
const formatted = formatVaultHits(
|
|
5759
5919
|
result.memories.map((m) => ({
|
|
@@ -6308,6 +6468,9 @@ async function recall(query, ctx, options = {}) {
|
|
|
6308
6468
|
let vaultSize;
|
|
6309
6469
|
let didRerank = false;
|
|
6310
6470
|
let hadV2Head = false;
|
|
6471
|
+
let embeddingsUnavailable = false;
|
|
6472
|
+
let chunkEmbedFailed = false;
|
|
6473
|
+
let factLaneRankedOnCosine = false;
|
|
6311
6474
|
const emitDiagnostics = (candidateCount) => {
|
|
6312
6475
|
const cb = options.onDiagnostics;
|
|
6313
6476
|
if (!cb) return;
|
|
@@ -6316,6 +6479,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
6316
6479
|
degraded.push("rerank-unavailable");
|
|
6317
6480
|
}
|
|
6318
6481
|
if (flags.decompose && !decomposeAvailable) degraded.push("decompose-unavailable");
|
|
6482
|
+
if (embeddingsUnavailable) degraded.push("embeddings-unavailable");
|
|
6319
6483
|
const diagnostics = {
|
|
6320
6484
|
usedBudget,
|
|
6321
6485
|
reranked: didRerank,
|
|
@@ -6346,7 +6510,26 @@ async function recall(query, ctx, options = {}) {
|
|
|
6346
6510
|
const graphRefiner = flags.traverse && options.graphRefine && options.decomposeOptions ? createLlmNeighborRefiner(options.decomposeOptions) : void 0;
|
|
6347
6511
|
const prepStart = nowMs();
|
|
6348
6512
|
const [queryEmbedding, entityRanking, temporalRanking] = await Promise.all([
|
|
6349
|
-
|
|
6513
|
+
// The chunk lane is cosine-only — `searchChunksOp` needs a real vector, and
|
|
6514
|
+
// there is no lexical fallback for it — so an embeddings outage must SKIP the
|
|
6515
|
+
// lane, not reject this shared Promise.all and take the primary fact lane
|
|
6516
|
+
// (which BM25 can still serve) down with it. Mirrors safeLane's posture.
|
|
6517
|
+
needsChunkEmbedding ? generateEmbedding(query, ctx.embeddingOptions).then((vec) => {
|
|
6518
|
+
if (vec.length === 0) {
|
|
6519
|
+
getLogger().warn(
|
|
6520
|
+
"[memory/recall] chunk-lane query embedding came back empty; skipping the chunk lane"
|
|
6521
|
+
);
|
|
6522
|
+
chunkEmbedFailed = true;
|
|
6523
|
+
return void 0;
|
|
6524
|
+
}
|
|
6525
|
+
return vec;
|
|
6526
|
+
}).catch((err) => {
|
|
6527
|
+
getLogger().warn(
|
|
6528
|
+
`[memory/recall] chunk-lane query embedding failed; skipping the chunk lane: ${err instanceof Error ? err.message : String(err)}`
|
|
6529
|
+
);
|
|
6530
|
+
chunkEmbedFailed = true;
|
|
6531
|
+
return void 0;
|
|
6532
|
+
}) : Promise.resolve(void 0),
|
|
6350
6533
|
// The graph + temporal lanes are AUXILIARY (RRF side-signals). A transient
|
|
6351
6534
|
// WatermelonDB throw in either must NOT reject this Promise.all and take
|
|
6352
6535
|
// PRIMARY cosine/BM25 recall down with it — degrade the failing lane to an
|
|
@@ -6371,7 +6554,9 @@ async function recall(query, ctx, options = {}) {
|
|
|
6371
6554
|
results,
|
|
6372
6555
|
vaultSize: size,
|
|
6373
6556
|
reranked,
|
|
6374
|
-
hadV2Head: v2Head
|
|
6557
|
+
hadV2Head: v2Head,
|
|
6558
|
+
embeddingsUnavailable: factEmbeddingsUnavailable,
|
|
6559
|
+
rankedOnCosine: factRankedOnCosine
|
|
6375
6560
|
} = await searchVaultMemoriesWithSize(
|
|
6376
6561
|
query,
|
|
6377
6562
|
ctx.vaultCtx,
|
|
@@ -6428,8 +6613,11 @@ async function recall(query, ctx, options = {}) {
|
|
|
6428
6613
|
vaultSize = size;
|
|
6429
6614
|
didRerank = reranked;
|
|
6430
6615
|
hadV2Head = v2Head;
|
|
6616
|
+
if (factEmbeddingsUnavailable) embeddingsUnavailable = true;
|
|
6617
|
+
factLaneRankedOnCosine = factRankedOnCosine;
|
|
6431
6618
|
factLaneMs = nowMs() - factStart;
|
|
6432
6619
|
}
|
|
6620
|
+
if (chunkEmbedFailed && !factLaneRankedOnCosine) embeddingsUnavailable = true;
|
|
6433
6621
|
if (types.includes("chunk") && ctx.storageCtx && queryEmbedding) {
|
|
6434
6622
|
const chunkStart = nowMs();
|
|
6435
6623
|
const chunkMinScore = options.minScore ?? DEFAULT_CHUNK_MIN_SCORE;
|
|
@@ -6724,6 +6912,9 @@ export {
|
|
|
6724
6912
|
restoreVaultMemoryOp,
|
|
6725
6913
|
hardDeleteDecayedOp,
|
|
6726
6914
|
updateVaultMemoryEmbeddingOp,
|
|
6915
|
+
RECALL_TOOL_NAME,
|
|
6916
|
+
RECALL_MAX_LIMIT,
|
|
6917
|
+
EMBEDDINGS_DEGRADED_EMPTY,
|
|
6727
6918
|
RerankerUnavailableError,
|
|
6728
6919
|
isRerankerAvailable,
|
|
6729
6920
|
DEFAULT_VAULT_CACHE_SIZE,
|