@anuma/sdk 2.3.1 → 2.4.1
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-SF5AYTXH.mjs → chunk-UOUJUZM4.mjs} +229 -35
- package/dist/expo/index.cjs +310 -44
- package/dist/expo/index.d.mts +212 -10
- package/dist/expo/index.d.ts +212 -10
- package/dist/expo/index.mjs +78 -9
- package/dist/expo/{recall-PCKDVF3U.mjs → recall-HI7VO3VM.mjs} +1 -1
- package/dist/react/{chunk-JUDJVX66.mjs → chunk-IYDQBFS2.mjs} +229 -35
- package/dist/react/index.cjs +306 -43
- package/dist/react/index.d.mts +219 -10
- package/dist/react/index.d.ts +219 -10
- package/dist/react/index.mjs +74 -8
- package/dist/react/{recall-DSJSBDR4.mjs → recall-G3CS444F.mjs} +1 -1
- package/dist/server/{chunk-3AWYZRTS.mjs → chunk-3MLG7SUH.mjs} +229 -35
- package/dist/server/index.cjs +299 -42
- package/dist/server/index.d.mts +219 -10
- package/dist/server/index.d.ts +219 -10
- package/dist/server/index.mjs +67 -7
- package/dist/server/{recall-EWMI64SA.mjs → recall-MJHGXMHZ.mjs} +1 -1
- package/package.json +1 -1
|
@@ -1483,7 +1483,13 @@ async function readJsonField(model, column, walletAddress) {
|
|
|
1483
1483
|
}
|
|
1484
1484
|
}
|
|
1485
1485
|
async function searchChunksOp(ctx, queryVector, options) {
|
|
1486
|
-
const {
|
|
1486
|
+
const {
|
|
1487
|
+
limit = 10,
|
|
1488
|
+
minSimilarity = 0.5,
|
|
1489
|
+
conversationId,
|
|
1490
|
+
embeddingModel,
|
|
1491
|
+
chunkCache
|
|
1492
|
+
} = options || {};
|
|
1487
1493
|
const activeConversations = await ctx.conversationsCollection.query(Q.where("is_deleted", false)).fetch();
|
|
1488
1494
|
const activeConversationIds = new Set(
|
|
1489
1495
|
// Use _getRaw for reliable raw column access
|
|
@@ -1503,23 +1509,54 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
1503
1509
|
continue;
|
|
1504
1510
|
}
|
|
1505
1511
|
}
|
|
1512
|
+
const version = Number(message._getRaw("updated_at")) || 0;
|
|
1513
|
+
const cached = chunkCache?.get(message.id);
|
|
1514
|
+
if (cached && cached.version === version) {
|
|
1515
|
+
if (cached.chunks.length > 0) {
|
|
1516
|
+
for (let ci = 0; ci < cached.chunks.length; ci++) {
|
|
1517
|
+
const vec = cached.chunks[ci];
|
|
1518
|
+
if (vec.length === 0) continue;
|
|
1519
|
+
const similarity = cosineSimilarity(queryVector, vec);
|
|
1520
|
+
if (similarity >= minSimilarity) {
|
|
1521
|
+
candidates.push({
|
|
1522
|
+
message,
|
|
1523
|
+
similarity,
|
|
1524
|
+
chunkTextSource: { kind: "chunk-cached", chunkIndex: ci, version }
|
|
1525
|
+
});
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
} else if (cached.fallback) {
|
|
1529
|
+
const similarity = cosineSimilarity(queryVector, cached.fallback);
|
|
1530
|
+
if (similarity >= minSimilarity) {
|
|
1531
|
+
candidates.push({ message, similarity, chunkTextSource: { kind: "message" } });
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
continue;
|
|
1535
|
+
}
|
|
1506
1536
|
const chunks = await readJsonField(message, "chunks", ctx.walletAddress);
|
|
1507
1537
|
if (chunks && chunks.length > 0) {
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1538
|
+
const vectors = chunks.map(
|
|
1539
|
+
(chunk) => chunk.vector && chunk.vector.length > 0 ? Float32Array.from(chunk.vector) : new Float32Array(0)
|
|
1540
|
+
);
|
|
1541
|
+
chunkCache?.set(message.id, { version, chunks: vectors });
|
|
1542
|
+
for (let ci = 0; ci < chunks.length; ci++) {
|
|
1543
|
+
const vec = vectors[ci];
|
|
1544
|
+
if (vec.length === 0) continue;
|
|
1545
|
+
const similarity = cosineSimilarity(queryVector, vec);
|
|
1511
1546
|
if (similarity >= minSimilarity) {
|
|
1512
1547
|
candidates.push({
|
|
1513
1548
|
message,
|
|
1514
1549
|
similarity,
|
|
1515
|
-
chunkTextSource: { kind: "chunk", text:
|
|
1550
|
+
chunkTextSource: { kind: "chunk", text: chunks[ci].text }
|
|
1516
1551
|
});
|
|
1517
1552
|
}
|
|
1518
1553
|
}
|
|
1519
1554
|
} else {
|
|
1520
1555
|
const messageVector = await readJsonField(message, "vector", ctx.walletAddress);
|
|
1521
1556
|
if (!messageVector || messageVector.length === 0) continue;
|
|
1522
|
-
const
|
|
1557
|
+
const fallback = Float32Array.from(messageVector);
|
|
1558
|
+
chunkCache?.set(message.id, { version, chunks: [], fallback });
|
|
1559
|
+
const similarity = cosineSimilarity(queryVector, fallback);
|
|
1523
1560
|
if (similarity >= minSimilarity) {
|
|
1524
1561
|
candidates.push({ message, similarity, chunkTextSource: { kind: "message" } });
|
|
1525
1562
|
}
|
|
@@ -1546,9 +1583,31 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
1546
1583
|
})
|
|
1547
1584
|
)
|
|
1548
1585
|
);
|
|
1586
|
+
const chunkStateByMsgId = /* @__PURE__ */ new Map();
|
|
1587
|
+
const needsChunkText = /* @__PURE__ */ new Set();
|
|
1588
|
+
for (const c of topK) {
|
|
1589
|
+
if (c.chunkTextSource.kind === "chunk-cached") needsChunkText.add(c.message.id);
|
|
1590
|
+
}
|
|
1591
|
+
await Promise.all(
|
|
1592
|
+
Array.from(needsChunkText, async (id) => {
|
|
1593
|
+
const m = uniqueMessages.get(id);
|
|
1594
|
+
const parsed = await readJsonField(m, "chunks", ctx.walletAddress);
|
|
1595
|
+
const version = Number(m._getRaw("updated_at")) || 0;
|
|
1596
|
+
if (parsed) chunkStateByMsgId.set(id, { version, chunks: parsed });
|
|
1597
|
+
})
|
|
1598
|
+
);
|
|
1549
1599
|
return topK.map(({ message, similarity, chunkTextSource }) => {
|
|
1550
1600
|
const stored = { ...storedById.get(message.id) };
|
|
1551
|
-
|
|
1601
|
+
let chunkText2;
|
|
1602
|
+
if (chunkTextSource.kind === "chunk") {
|
|
1603
|
+
chunkText2 = chunkTextSource.text;
|
|
1604
|
+
} else if (chunkTextSource.kind === "chunk-cached") {
|
|
1605
|
+
const state = chunkStateByMsgId.get(message.id);
|
|
1606
|
+
const chunk = state && state.version === chunkTextSource.version ? state.chunks[chunkTextSource.chunkIndex] : void 0;
|
|
1607
|
+
chunkText2 = chunk?.text ?? stored.content;
|
|
1608
|
+
} else {
|
|
1609
|
+
chunkText2 = stored.content;
|
|
1610
|
+
}
|
|
1552
1611
|
return { chunkText: chunkText2, message: stored, similarity };
|
|
1553
1612
|
});
|
|
1554
1613
|
}
|
|
@@ -3685,9 +3744,9 @@ function recencyMultiplier(updatedAt, opts = {}) {
|
|
|
3685
3744
|
const updatedMs = updatedAt.getTime();
|
|
3686
3745
|
if (!Number.isFinite(updatedMs)) return noDate;
|
|
3687
3746
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
3688
|
-
const
|
|
3689
|
-
if (!Number.isFinite(
|
|
3690
|
-
const ageDays = Math.max(0, (
|
|
3747
|
+
const nowMs2 = now.getTime();
|
|
3748
|
+
if (!Number.isFinite(nowMs2)) return noDate;
|
|
3749
|
+
const ageDays = Math.max(0, (nowMs2 - updatedMs) / DAY_MS);
|
|
3691
3750
|
const perYearDecay = opts.perYearDecay ?? DEFAULT_PER_YEAR_DECAY;
|
|
3692
3751
|
const floor = opts.floor ?? DEFAULT_FLOOR;
|
|
3693
3752
|
const decay = perYearDecay * (ageDays / 365);
|
|
@@ -3696,15 +3755,51 @@ function recencyMultiplier(updatedAt, opts = {}) {
|
|
|
3696
3755
|
|
|
3697
3756
|
// src/lib/memory/reranker.ts
|
|
3698
3757
|
var MODEL_ID = "Xenova/ms-marco-MiniLM-L-6-v2";
|
|
3758
|
+
var RerankerUnavailableError = class extends Error {
|
|
3759
|
+
constructor(reason) {
|
|
3760
|
+
super("cross-encoder reranker unavailable (@huggingface/transformers not installed)");
|
|
3761
|
+
this.name = "RerankerUnavailableError";
|
|
3762
|
+
this.reason = reason;
|
|
3763
|
+
}
|
|
3764
|
+
};
|
|
3765
|
+
var available = void 0;
|
|
3699
3766
|
var modelPromise = null;
|
|
3767
|
+
function isRerankerAvailable() {
|
|
3768
|
+
return available;
|
|
3769
|
+
}
|
|
3770
|
+
function isModuleMissing(err) {
|
|
3771
|
+
let e = err;
|
|
3772
|
+
for (let depth = 0; depth < 5 && e !== null && e !== void 0; depth++) {
|
|
3773
|
+
const code = e.code;
|
|
3774
|
+
if (code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND") return true;
|
|
3775
|
+
if (e instanceof Error && /cannot find (module|package)|failed to resolve|unable to resolve module|requiring unknown module/i.test(
|
|
3776
|
+
e.message
|
|
3777
|
+
)) {
|
|
3778
|
+
return true;
|
|
3779
|
+
}
|
|
3780
|
+
e = e.cause;
|
|
3781
|
+
}
|
|
3782
|
+
return false;
|
|
3783
|
+
}
|
|
3700
3784
|
async function getModel() {
|
|
3785
|
+
if (available === false) throw new RerankerUnavailableError(void 0);
|
|
3701
3786
|
if (!modelPromise) {
|
|
3702
3787
|
const load = (async () => {
|
|
3703
|
-
|
|
3788
|
+
let transformers;
|
|
3789
|
+
try {
|
|
3790
|
+
transformers = await import("@huggingface/transformers");
|
|
3791
|
+
} catch (err) {
|
|
3792
|
+
if (isModuleMissing(err)) {
|
|
3793
|
+
available = false;
|
|
3794
|
+
throw new RerankerUnavailableError(err);
|
|
3795
|
+
}
|
|
3796
|
+
throw err;
|
|
3797
|
+
}
|
|
3704
3798
|
const [tokenizer, model] = await Promise.all([
|
|
3705
3799
|
transformers.AutoTokenizer.from_pretrained(MODEL_ID),
|
|
3706
3800
|
transformers.AutoModelForSequenceClassification.from_pretrained(MODEL_ID)
|
|
3707
3801
|
]);
|
|
3802
|
+
available = true;
|
|
3708
3803
|
return { tokenizer, model };
|
|
3709
3804
|
})();
|
|
3710
3805
|
modelPromise = load;
|
|
@@ -4265,6 +4360,9 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
|
|
|
4265
4360
|
bm25AdmissionDivisor: options?.bm25AdmissionDivisor,
|
|
4266
4361
|
rrfK: options?.rrfK
|
|
4267
4362
|
});
|
|
4363
|
+
if (options?.v2HeadStats) {
|
|
4364
|
+
options.v2HeadStats.hadResults = v2Ranked.length > 0;
|
|
4365
|
+
}
|
|
4268
4366
|
let combined;
|
|
4269
4367
|
let tailSlice = [];
|
|
4270
4368
|
if (options?.rerank) {
|
|
@@ -4285,8 +4383,13 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
|
|
|
4285
4383
|
return { ...r, similarity: v2 * (1 + ceWeight * ce) };
|
|
4286
4384
|
});
|
|
4287
4385
|
combined.sort((a, b) => b.similarity - a.similarity);
|
|
4386
|
+
if (headSlice.length > 0 && options.rerankStats) options.rerankStats.applied = true;
|
|
4288
4387
|
} catch (err) {
|
|
4289
|
-
|
|
4388
|
+
if (err instanceof RerankerUnavailableError) {
|
|
4389
|
+
getLogger().debug("[memory/search] cross-encoder unavailable; using V2 ranking");
|
|
4390
|
+
} else {
|
|
4391
|
+
getLogger().warn("[memory/search] cross-encoder rerank failed; using V2 ranking", err);
|
|
4392
|
+
}
|
|
4290
4393
|
combined = v2Ranked;
|
|
4291
4394
|
}
|
|
4292
4395
|
} else {
|
|
@@ -4420,6 +4523,9 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
|
|
|
4420
4523
|
(r) => r !== null
|
|
4421
4524
|
);
|
|
4422
4525
|
combined.sort((a, b) => b.similarity - a.similarity);
|
|
4526
|
+
if (options?.v2HeadStats) {
|
|
4527
|
+
options.v2HeadStats.hadResults = combined.length > 0;
|
|
4528
|
+
}
|
|
4423
4529
|
if (options?.includeUnrankedTail) {
|
|
4424
4530
|
const fusedIds = new Set(combined.map((r) => r.uniqueId));
|
|
4425
4531
|
for (const item of items) {
|
|
@@ -4455,11 +4561,16 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
|
|
|
4455
4561
|
}));
|
|
4456
4562
|
head.sort((a, b) => b.similarity - a.similarity);
|
|
4457
4563
|
combined = [...head, ...tailSlice];
|
|
4564
|
+
if (headSlice.length > 0 && options.rerankStats) options.rerankStats.applied = true;
|
|
4458
4565
|
} catch (err) {
|
|
4459
|
-
|
|
4460
|
-
"[memory/search]
|
|
4461
|
-
|
|
4462
|
-
|
|
4566
|
+
if (err instanceof RerankerUnavailableError) {
|
|
4567
|
+
getLogger().debug("[memory/search] cross-encoder unavailable; using fused ranking");
|
|
4568
|
+
} else {
|
|
4569
|
+
getLogger().warn(
|
|
4570
|
+
"[memory/search] composite cross-encoder rerank failed; using fused ranking",
|
|
4571
|
+
err
|
|
4572
|
+
);
|
|
4573
|
+
}
|
|
4463
4574
|
}
|
|
4464
4575
|
}
|
|
4465
4576
|
if (options?.mmr) {
|
|
@@ -4551,7 +4662,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
4551
4662
|
const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
|
|
4552
4663
|
const scopes = searchOptions?.scopes;
|
|
4553
4664
|
if (!query || typeof query !== "string") {
|
|
4554
|
-
return { results: [], vaultSize: 0 };
|
|
4665
|
+
return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
|
|
4555
4666
|
}
|
|
4556
4667
|
const folderId = searchOptions?.folderId;
|
|
4557
4668
|
const queryOpts = {};
|
|
@@ -4568,7 +4679,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
4568
4679
|
);
|
|
4569
4680
|
}
|
|
4570
4681
|
if (memories.length === 0) {
|
|
4571
|
-
return { results: [], vaultSize: loaded.length };
|
|
4682
|
+
return { results: [], vaultSize: loaded.length, reranked: false, hadV2Head: false };
|
|
4572
4683
|
}
|
|
4573
4684
|
const queryEmbedding = await generateEmbedding(query, embeddingOptions);
|
|
4574
4685
|
const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
@@ -4644,12 +4755,18 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
4644
4755
|
memories.map((m) => [m.uniqueId, { createdAt: m.createdAt, updatedAt: m.updatedAt }])
|
|
4645
4756
|
);
|
|
4646
4757
|
const stampTimestamps = (out) => {
|
|
4647
|
-
|
|
4758
|
+
const results2 = out.results.map((r) => {
|
|
4648
4759
|
const ts = timestampById.get(r.uniqueId);
|
|
4649
4760
|
return ts ? { ...r, createdAt: ts.createdAt, updatedAt: ts.updatedAt } : r;
|
|
4650
4761
|
});
|
|
4651
|
-
return
|
|
4762
|
+
return {
|
|
4763
|
+
results: results2,
|
|
4764
|
+
vaultSize: out.vaultSize,
|
|
4765
|
+
reranked: out.reranked ?? false,
|
|
4766
|
+
hadV2Head: out.hadV2Head ?? false
|
|
4767
|
+
};
|
|
4652
4768
|
};
|
|
4769
|
+
const rerankStats = { applied: false };
|
|
4653
4770
|
const useFusion = searchOptions?.useFusion ?? true;
|
|
4654
4771
|
const tuning = {
|
|
4655
4772
|
...searchOptions?.recencyAlpha !== void 0 && { recencyAlpha: searchOptions.recencyAlpha },
|
|
@@ -4676,6 +4793,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
4676
4793
|
query: sq,
|
|
4677
4794
|
embedding: subEmbeddings[i]
|
|
4678
4795
|
}));
|
|
4796
|
+
const v2HeadStats = { hadResults: false };
|
|
4679
4797
|
const composite = await rankComposite(query, queryEmbedding, subQueries, embeddedItems, {
|
|
4680
4798
|
limit,
|
|
4681
4799
|
minSimilarity,
|
|
@@ -4687,12 +4805,20 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
4687
4805
|
...searchOptions.mmr !== void 0 && { mmr: searchOptions.mmr },
|
|
4688
4806
|
...tuning,
|
|
4689
4807
|
...searchOptions.entityRanking && { entityRanking: searchOptions.entityRanking },
|
|
4690
|
-
...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking }
|
|
4808
|
+
...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
|
|
4809
|
+
rerankStats,
|
|
4810
|
+
v2HeadStats
|
|
4811
|
+
});
|
|
4812
|
+
return stampTimestamps({
|
|
4813
|
+
results: composite,
|
|
4814
|
+
vaultSize: loaded.length,
|
|
4815
|
+
reranked: rerankStats.applied,
|
|
4816
|
+
hadV2Head: v2HeadStats.hadResults
|
|
4691
4817
|
});
|
|
4692
|
-
return stampTimestamps({ results: composite, vaultSize: loaded.length });
|
|
4693
4818
|
}
|
|
4694
4819
|
}
|
|
4695
4820
|
if (useFusion && searchOptions?.rerank) {
|
|
4821
|
+
const v2HeadStats = { hadResults: false };
|
|
4696
4822
|
const results2 = await rankFusedVaultMemoriesAsync(query, queryEmbedding, embeddedItems, {
|
|
4697
4823
|
limit,
|
|
4698
4824
|
minSimilarity,
|
|
@@ -4704,9 +4830,16 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
4704
4830
|
...searchOptions.mmr !== void 0 && { mmr: searchOptions.mmr },
|
|
4705
4831
|
...tuning,
|
|
4706
4832
|
...searchOptions.entityRanking && { entityRanking: searchOptions.entityRanking },
|
|
4707
|
-
...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking }
|
|
4833
|
+
...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
|
|
4834
|
+
rerankStats,
|
|
4835
|
+
v2HeadStats
|
|
4836
|
+
});
|
|
4837
|
+
return stampTimestamps({
|
|
4838
|
+
results: results2,
|
|
4839
|
+
vaultSize: loaded.length,
|
|
4840
|
+
reranked: rerankStats.applied,
|
|
4841
|
+
hadV2Head: v2HeadStats.hadResults
|
|
4708
4842
|
});
|
|
4709
|
-
return stampTimestamps({ results: results2, vaultSize: loaded.length });
|
|
4710
4843
|
}
|
|
4711
4844
|
if (useFusion) {
|
|
4712
4845
|
const results2 = rankFusedVaultMemories(query, queryEmbedding, embeddedItems, {
|
|
@@ -4716,7 +4849,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
4716
4849
|
...searchOptions?.entityRanking && { entityRanking: searchOptions.entityRanking },
|
|
4717
4850
|
...searchOptions?.temporalRanking && { temporalRanking: searchOptions.temporalRanking }
|
|
4718
4851
|
});
|
|
4719
|
-
return stampTimestamps({ results: results2, vaultSize: loaded.length });
|
|
4852
|
+
return stampTimestamps({ results: results2, vaultSize: loaded.length, hadV2Head: results2.length > 0 });
|
|
4720
4853
|
}
|
|
4721
4854
|
const results = rankVaultMemories(query, queryEmbedding, embeddedItems, {
|
|
4722
4855
|
limit,
|
|
@@ -4728,7 +4861,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
4728
4861
|
supersessionWindow: searchOptions.supersessionWindow
|
|
4729
4862
|
}
|
|
4730
4863
|
});
|
|
4731
|
-
return stampTimestamps({ results, vaultSize: loaded.length });
|
|
4864
|
+
return stampTimestamps({ results, vaultSize: loaded.length, hadV2Head: results.length > 0 });
|
|
4732
4865
|
}
|
|
4733
4866
|
async function searchVaultMemories(query, vaultCtx, embeddingOptions, cache, searchOptions) {
|
|
4734
4867
|
const { results } = await searchVaultMemoriesWithSize(
|
|
@@ -4817,7 +4950,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
4817
4950
|
legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
|
|
4818
4951
|
);
|
|
4819
4952
|
}
|
|
4820
|
-
const { recall: recall2 } = await import("./recall-
|
|
4953
|
+
const { recall: recall2 } = await import("./recall-HI7VO3VM.mjs");
|
|
4821
4954
|
const result = await recall2(
|
|
4822
4955
|
query,
|
|
4823
4956
|
{ vaultCtx, embeddingOptions, vaultCache: cache },
|
|
@@ -5135,6 +5268,7 @@ function scoreEventTimeOverlap(memoryStart, memoryEnd, memoryKind, window2) {
|
|
|
5135
5268
|
var DEFAULT_LIMIT = 8;
|
|
5136
5269
|
var DEFAULT_BUDGET = "low";
|
|
5137
5270
|
var DEFAULT_FACT_MIN_SCORE = 0.1;
|
|
5271
|
+
var nowMs = () => typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
5138
5272
|
var DEFAULT_CHUNK_MIN_SCORE = 0.5;
|
|
5139
5273
|
function flagsForBudget(budget) {
|
|
5140
5274
|
switch (budget) {
|
|
@@ -5167,22 +5301,67 @@ async function recall(query, ctx, options = {}) {
|
|
|
5167
5301
|
const flags = flagsForBudget(requestedBudget);
|
|
5168
5302
|
const decomposeAvailable = flags.decompose && !!options.decomposeOptions;
|
|
5169
5303
|
const usedBudget = requestedBudget === "high" && !decomposeAvailable ? "mid" : requestedBudget;
|
|
5304
|
+
const t0 = nowMs();
|
|
5305
|
+
let prepMs = 0;
|
|
5306
|
+
let factLaneMs = 0;
|
|
5307
|
+
let chunkLaneMs = 0;
|
|
5308
|
+
let fuseMs = 0;
|
|
5309
|
+
const factResults = [];
|
|
5310
|
+
const chunkResults = [];
|
|
5311
|
+
let vaultSize;
|
|
5312
|
+
let didRerank = false;
|
|
5313
|
+
let hadV2Head = false;
|
|
5314
|
+
const emitDiagnostics = (candidateCount) => {
|
|
5315
|
+
const cb = options.onDiagnostics;
|
|
5316
|
+
if (!cb) return;
|
|
5317
|
+
const degraded = [];
|
|
5318
|
+
if (flags.rerank && factResults.length > 0 && hadV2Head && !didRerank) {
|
|
5319
|
+
degraded.push("rerank-unavailable");
|
|
5320
|
+
}
|
|
5321
|
+
if (flags.decompose && !decomposeAvailable) degraded.push("decompose-unavailable");
|
|
5322
|
+
const diagnostics = {
|
|
5323
|
+
usedBudget,
|
|
5324
|
+
reranked: didRerank,
|
|
5325
|
+
candidateCount,
|
|
5326
|
+
...vaultSize !== void 0 && { vaultSize },
|
|
5327
|
+
factCount: factResults.length,
|
|
5328
|
+
chunkCount: chunkResults.length,
|
|
5329
|
+
timings: {
|
|
5330
|
+
total: nowMs() - t0,
|
|
5331
|
+
prep: prepMs,
|
|
5332
|
+
factLane: factLaneMs,
|
|
5333
|
+
chunkLane: chunkLaneMs,
|
|
5334
|
+
fuse: fuseMs
|
|
5335
|
+
},
|
|
5336
|
+
degraded
|
|
5337
|
+
};
|
|
5338
|
+
try {
|
|
5339
|
+
cb(diagnostics);
|
|
5340
|
+
} catch {
|
|
5341
|
+
}
|
|
5342
|
+
};
|
|
5170
5343
|
if (!query || typeof query !== "string" || query.trim().length === 0) {
|
|
5344
|
+
emitDiagnostics(0);
|
|
5171
5345
|
return { memories: [], usedBudget, reranked: false, candidateCount: 0 };
|
|
5172
5346
|
}
|
|
5173
5347
|
const needsChunkEmbedding = types.includes("chunk") && ctx.storageCtx;
|
|
5174
5348
|
const wantsTemporal = types.includes("fact") && ctx.vaultCtx;
|
|
5349
|
+
const prepStart = nowMs();
|
|
5175
5350
|
const [queryEmbedding, entityRanking, temporalRanking] = await Promise.all([
|
|
5176
5351
|
needsChunkEmbedding ? generateEmbedding(query, ctx.embeddingOptions) : Promise.resolve(void 0),
|
|
5177
5352
|
buildGraphLaneRanking(query, ctx),
|
|
5178
5353
|
wantsTemporal ? buildTemporalLaneRanking(query, ctx.vaultCtx, options.now) : Promise.resolve([])
|
|
5179
5354
|
]);
|
|
5180
|
-
|
|
5181
|
-
const chunkResults = [];
|
|
5182
|
-
let vaultSize;
|
|
5355
|
+
prepMs = nowMs() - prepStart;
|
|
5183
5356
|
if (types.includes("fact") && ctx.vaultCtx && ctx.vaultCache) {
|
|
5357
|
+
const factStart = nowMs();
|
|
5184
5358
|
const vaultMinScore = options.minScore ?? DEFAULT_FACT_MIN_SCORE;
|
|
5185
|
-
const {
|
|
5359
|
+
const {
|
|
5360
|
+
results,
|
|
5361
|
+
vaultSize: size,
|
|
5362
|
+
reranked,
|
|
5363
|
+
hadV2Head: v2Head
|
|
5364
|
+
} = await searchVaultMemoriesWithSize(
|
|
5186
5365
|
query,
|
|
5187
5366
|
ctx.vaultCtx,
|
|
5188
5367
|
ctx.embeddingOptions,
|
|
@@ -5233,14 +5412,19 @@ async function recall(query, ctx, options = {}) {
|
|
|
5233
5412
|
)
|
|
5234
5413
|
);
|
|
5235
5414
|
vaultSize = size;
|
|
5415
|
+
didRerank = reranked;
|
|
5416
|
+
hadV2Head = v2Head;
|
|
5417
|
+
factLaneMs = nowMs() - factStart;
|
|
5236
5418
|
}
|
|
5237
5419
|
if (types.includes("chunk") && ctx.storageCtx && queryEmbedding) {
|
|
5420
|
+
const chunkStart = nowMs();
|
|
5238
5421
|
const chunkMinScore = options.minScore ?? DEFAULT_CHUNK_MIN_SCORE;
|
|
5239
5422
|
const results = await searchChunksOp(ctx.storageCtx, queryEmbedding, {
|
|
5240
5423
|
limit: types.includes("fact") ? Math.max(limit * 2, 16) : limit,
|
|
5241
5424
|
minSimilarity: chunkMinScore,
|
|
5242
5425
|
embeddingModel: ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL,
|
|
5243
|
-
...options.conversationId && { conversationId: options.conversationId }
|
|
5426
|
+
...options.conversationId && { conversationId: options.conversationId },
|
|
5427
|
+
...ctx.chunkCache && { chunkCache: ctx.chunkCache }
|
|
5244
5428
|
});
|
|
5245
5429
|
chunkResults.push(
|
|
5246
5430
|
...dedupeBy(
|
|
@@ -5250,18 +5434,23 @@ async function recall(query, ctx, options = {}) {
|
|
|
5250
5434
|
(r) => r.chunkText.trim()
|
|
5251
5435
|
)
|
|
5252
5436
|
);
|
|
5437
|
+
chunkLaneMs = nowMs() - chunkStart;
|
|
5253
5438
|
}
|
|
5439
|
+
const fuseStart = nowMs();
|
|
5254
5440
|
if (types.length === 1 || factResults.length === 0 || chunkResults.length === 0) {
|
|
5255
5441
|
const memories2 = [
|
|
5256
5442
|
...factResults.map(toFactMemory),
|
|
5257
5443
|
...chunkResults.map(toChunkMemory)
|
|
5258
5444
|
];
|
|
5259
5445
|
memories2.sort((a, b) => b.score - a.score);
|
|
5446
|
+
const candidateCount = factResults.length + chunkResults.length;
|
|
5447
|
+
fuseMs = nowMs() - fuseStart;
|
|
5448
|
+
emitDiagnostics(candidateCount);
|
|
5260
5449
|
return {
|
|
5261
5450
|
memories: memories2.slice(0, limit),
|
|
5262
5451
|
usedBudget,
|
|
5263
|
-
reranked:
|
|
5264
|
-
candidateCount
|
|
5452
|
+
reranked: didRerank,
|
|
5453
|
+
candidateCount,
|
|
5265
5454
|
...vaultSize !== void 0 && { vaultSize }
|
|
5266
5455
|
};
|
|
5267
5456
|
}
|
|
@@ -5310,10 +5499,12 @@ async function recall(query, ctx, options = {}) {
|
|
|
5310
5499
|
suppressed = next;
|
|
5311
5500
|
memories = selectWith(suppressed);
|
|
5312
5501
|
}
|
|
5502
|
+
fuseMs = nowMs() - fuseStart;
|
|
5503
|
+
emitDiagnostics(byId.size);
|
|
5313
5504
|
return {
|
|
5314
5505
|
memories,
|
|
5315
5506
|
usedBudget,
|
|
5316
|
-
reranked:
|
|
5507
|
+
reranked: didRerank,
|
|
5317
5508
|
candidateCount: byId.size,
|
|
5318
5509
|
...vaultSize !== void 0 && { vaultSize }
|
|
5319
5510
|
};
|
|
@@ -5456,7 +5647,10 @@ export {
|
|
|
5456
5647
|
stampTopicsExtractedAtOp,
|
|
5457
5648
|
deleteAllVaultMemoriesForUserOp,
|
|
5458
5649
|
updateVaultMemoryEmbeddingOp,
|
|
5650
|
+
RerankerUnavailableError,
|
|
5651
|
+
isRerankerAvailable,
|
|
5459
5652
|
DEFAULT_VAULT_CACHE_SIZE,
|
|
5653
|
+
LRUCache,
|
|
5460
5654
|
createVaultEmbeddingCache,
|
|
5461
5655
|
recall,
|
|
5462
5656
|
preEmbedVaultMemories,
|