@anuma/sdk 2.4.0 → 2.4.2
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/client/index.cjs +8 -0
- package/dist/client/index.d.mts +44 -1
- package/dist/client/index.d.ts +44 -1
- package/dist/client/index.mjs +7 -0
- package/dist/expo/{chunk-SF5AYTXH.mjs → chunk-UOUJUZM4.mjs} +229 -35
- package/dist/expo/index.cjs +256 -38
- package/dist/expo/index.d.mts +146 -1
- package/dist/expo/index.d.ts +146 -1
- package/dist/expo/index.mjs +25 -3
- 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 +252 -37
- package/dist/react/index.d.mts +153 -1
- package/dist/react/index.d.ts +153 -1
- package/dist/react/index.mjs +21 -2
- 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 +245 -36
- package/dist/server/index.d.mts +153 -1
- package/dist/server/index.d.ts +153 -1
- package/dist/server/index.mjs +14 -1
- package/dist/server/{recall-EWMI64SA.mjs → recall-MJHGXMHZ.mjs} +1 -1
- package/package.json +2 -2
|
@@ -1588,7 +1588,13 @@ async function searchMessagesOp(ctx, queryVector, options) {
|
|
|
1588
1588
|
);
|
|
1589
1589
|
}
|
|
1590
1590
|
async function searchChunksOp(ctx, queryVector, options) {
|
|
1591
|
-
const {
|
|
1591
|
+
const {
|
|
1592
|
+
limit = 10,
|
|
1593
|
+
minSimilarity = 0.5,
|
|
1594
|
+
conversationId,
|
|
1595
|
+
embeddingModel,
|
|
1596
|
+
chunkCache
|
|
1597
|
+
} = options || {};
|
|
1592
1598
|
const activeConversations = await ctx.conversationsCollection.query(Q.where("is_deleted", false)).fetch();
|
|
1593
1599
|
const activeConversationIds = new Set(
|
|
1594
1600
|
// Use _getRaw for reliable raw column access
|
|
@@ -1608,23 +1614,54 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
1608
1614
|
continue;
|
|
1609
1615
|
}
|
|
1610
1616
|
}
|
|
1617
|
+
const version = Number(message._getRaw("updated_at")) || 0;
|
|
1618
|
+
const cached = chunkCache?.get(message.id);
|
|
1619
|
+
if (cached && cached.version === version) {
|
|
1620
|
+
if (cached.chunks.length > 0) {
|
|
1621
|
+
for (let ci = 0; ci < cached.chunks.length; ci++) {
|
|
1622
|
+
const vec = cached.chunks[ci];
|
|
1623
|
+
if (vec.length === 0) continue;
|
|
1624
|
+
const similarity = cosineSimilarity(queryVector, vec);
|
|
1625
|
+
if (similarity >= minSimilarity) {
|
|
1626
|
+
candidates.push({
|
|
1627
|
+
message,
|
|
1628
|
+
similarity,
|
|
1629
|
+
chunkTextSource: { kind: "chunk-cached", chunkIndex: ci, version }
|
|
1630
|
+
});
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
} else if (cached.fallback) {
|
|
1634
|
+
const similarity = cosineSimilarity(queryVector, cached.fallback);
|
|
1635
|
+
if (similarity >= minSimilarity) {
|
|
1636
|
+
candidates.push({ message, similarity, chunkTextSource: { kind: "message" } });
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
continue;
|
|
1640
|
+
}
|
|
1611
1641
|
const chunks = await readJsonField(message, "chunks", ctx.walletAddress);
|
|
1612
1642
|
if (chunks && chunks.length > 0) {
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1643
|
+
const vectors = chunks.map(
|
|
1644
|
+
(chunk) => chunk.vector && chunk.vector.length > 0 ? Float32Array.from(chunk.vector) : new Float32Array(0)
|
|
1645
|
+
);
|
|
1646
|
+
chunkCache?.set(message.id, { version, chunks: vectors });
|
|
1647
|
+
for (let ci = 0; ci < chunks.length; ci++) {
|
|
1648
|
+
const vec = vectors[ci];
|
|
1649
|
+
if (vec.length === 0) continue;
|
|
1650
|
+
const similarity = cosineSimilarity(queryVector, vec);
|
|
1616
1651
|
if (similarity >= minSimilarity) {
|
|
1617
1652
|
candidates.push({
|
|
1618
1653
|
message,
|
|
1619
1654
|
similarity,
|
|
1620
|
-
chunkTextSource: { kind: "chunk", text:
|
|
1655
|
+
chunkTextSource: { kind: "chunk", text: chunks[ci].text }
|
|
1621
1656
|
});
|
|
1622
1657
|
}
|
|
1623
1658
|
}
|
|
1624
1659
|
} else {
|
|
1625
1660
|
const messageVector = await readJsonField(message, "vector", ctx.walletAddress);
|
|
1626
1661
|
if (!messageVector || messageVector.length === 0) continue;
|
|
1627
|
-
const
|
|
1662
|
+
const fallback = Float32Array.from(messageVector);
|
|
1663
|
+
chunkCache?.set(message.id, { version, chunks: [], fallback });
|
|
1664
|
+
const similarity = cosineSimilarity(queryVector, fallback);
|
|
1628
1665
|
if (similarity >= minSimilarity) {
|
|
1629
1666
|
candidates.push({ message, similarity, chunkTextSource: { kind: "message" } });
|
|
1630
1667
|
}
|
|
@@ -1651,9 +1688,31 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
1651
1688
|
})
|
|
1652
1689
|
)
|
|
1653
1690
|
);
|
|
1691
|
+
const chunkStateByMsgId = /* @__PURE__ */ new Map();
|
|
1692
|
+
const needsChunkText = /* @__PURE__ */ new Set();
|
|
1693
|
+
for (const c of topK) {
|
|
1694
|
+
if (c.chunkTextSource.kind === "chunk-cached") needsChunkText.add(c.message.id);
|
|
1695
|
+
}
|
|
1696
|
+
await Promise.all(
|
|
1697
|
+
Array.from(needsChunkText, async (id) => {
|
|
1698
|
+
const m = uniqueMessages.get(id);
|
|
1699
|
+
const parsed = await readJsonField(m, "chunks", ctx.walletAddress);
|
|
1700
|
+
const version = Number(m._getRaw("updated_at")) || 0;
|
|
1701
|
+
if (parsed) chunkStateByMsgId.set(id, { version, chunks: parsed });
|
|
1702
|
+
})
|
|
1703
|
+
);
|
|
1654
1704
|
return topK.map(({ message, similarity, chunkTextSource }) => {
|
|
1655
1705
|
const stored = { ...storedById.get(message.id) };
|
|
1656
|
-
|
|
1706
|
+
let chunkText2;
|
|
1707
|
+
if (chunkTextSource.kind === "chunk") {
|
|
1708
|
+
chunkText2 = chunkTextSource.text;
|
|
1709
|
+
} else if (chunkTextSource.kind === "chunk-cached") {
|
|
1710
|
+
const state = chunkStateByMsgId.get(message.id);
|
|
1711
|
+
const chunk = state && state.version === chunkTextSource.version ? state.chunks[chunkTextSource.chunkIndex] : void 0;
|
|
1712
|
+
chunkText2 = chunk?.text ?? stored.content;
|
|
1713
|
+
} else {
|
|
1714
|
+
chunkText2 = stored.content;
|
|
1715
|
+
}
|
|
1657
1716
|
return { chunkText: chunkText2, message: stored, similarity };
|
|
1658
1717
|
});
|
|
1659
1718
|
}
|
|
@@ -4017,9 +4076,9 @@ function recencyMultiplier(updatedAt, opts = {}) {
|
|
|
4017
4076
|
const updatedMs = updatedAt.getTime();
|
|
4018
4077
|
if (!Number.isFinite(updatedMs)) return noDate;
|
|
4019
4078
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
4020
|
-
const
|
|
4021
|
-
if (!Number.isFinite(
|
|
4022
|
-
const ageDays = Math.max(0, (
|
|
4079
|
+
const nowMs2 = now.getTime();
|
|
4080
|
+
if (!Number.isFinite(nowMs2)) return noDate;
|
|
4081
|
+
const ageDays = Math.max(0, (nowMs2 - updatedMs) / DAY_MS);
|
|
4023
4082
|
const perYearDecay = opts.perYearDecay ?? DEFAULT_PER_YEAR_DECAY;
|
|
4024
4083
|
const floor = opts.floor ?? DEFAULT_FLOOR;
|
|
4025
4084
|
const decay = perYearDecay * (ageDays / 365);
|
|
@@ -4028,15 +4087,51 @@ function recencyMultiplier(updatedAt, opts = {}) {
|
|
|
4028
4087
|
|
|
4029
4088
|
// src/lib/memory/reranker.ts
|
|
4030
4089
|
var MODEL_ID = "Xenova/ms-marco-MiniLM-L-6-v2";
|
|
4090
|
+
var RerankerUnavailableError = class extends Error {
|
|
4091
|
+
constructor(reason) {
|
|
4092
|
+
super("cross-encoder reranker unavailable (@huggingface/transformers not installed)");
|
|
4093
|
+
this.name = "RerankerUnavailableError";
|
|
4094
|
+
this.reason = reason;
|
|
4095
|
+
}
|
|
4096
|
+
};
|
|
4097
|
+
var available = void 0;
|
|
4031
4098
|
var modelPromise = null;
|
|
4099
|
+
function isRerankerAvailable() {
|
|
4100
|
+
return available;
|
|
4101
|
+
}
|
|
4102
|
+
function isModuleMissing(err) {
|
|
4103
|
+
let e = err;
|
|
4104
|
+
for (let depth = 0; depth < 5 && e !== null && e !== void 0; depth++) {
|
|
4105
|
+
const code = e.code;
|
|
4106
|
+
if (code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND") return true;
|
|
4107
|
+
if (e instanceof Error && /cannot find (module|package)|failed to resolve|unable to resolve module|requiring unknown module/i.test(
|
|
4108
|
+
e.message
|
|
4109
|
+
)) {
|
|
4110
|
+
return true;
|
|
4111
|
+
}
|
|
4112
|
+
e = e.cause;
|
|
4113
|
+
}
|
|
4114
|
+
return false;
|
|
4115
|
+
}
|
|
4032
4116
|
async function getModel() {
|
|
4117
|
+
if (available === false) throw new RerankerUnavailableError(void 0);
|
|
4033
4118
|
if (!modelPromise) {
|
|
4034
4119
|
const load = (async () => {
|
|
4035
|
-
|
|
4120
|
+
let transformers;
|
|
4121
|
+
try {
|
|
4122
|
+
transformers = await import("@huggingface/transformers");
|
|
4123
|
+
} catch (err) {
|
|
4124
|
+
if (isModuleMissing(err)) {
|
|
4125
|
+
available = false;
|
|
4126
|
+
throw new RerankerUnavailableError(err);
|
|
4127
|
+
}
|
|
4128
|
+
throw err;
|
|
4129
|
+
}
|
|
4036
4130
|
const [tokenizer, model] = await Promise.all([
|
|
4037
4131
|
transformers.AutoTokenizer.from_pretrained(MODEL_ID),
|
|
4038
4132
|
transformers.AutoModelForSequenceClassification.from_pretrained(MODEL_ID)
|
|
4039
4133
|
]);
|
|
4134
|
+
available = true;
|
|
4040
4135
|
return { tokenizer, model };
|
|
4041
4136
|
})();
|
|
4042
4137
|
modelPromise = load;
|
|
@@ -4597,6 +4692,9 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
|
|
|
4597
4692
|
bm25AdmissionDivisor: options?.bm25AdmissionDivisor,
|
|
4598
4693
|
rrfK: options?.rrfK
|
|
4599
4694
|
});
|
|
4695
|
+
if (options?.v2HeadStats) {
|
|
4696
|
+
options.v2HeadStats.hadResults = v2Ranked.length > 0;
|
|
4697
|
+
}
|
|
4600
4698
|
let combined;
|
|
4601
4699
|
let tailSlice = [];
|
|
4602
4700
|
if (options?.rerank) {
|
|
@@ -4617,8 +4715,13 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
|
|
|
4617
4715
|
return { ...r, similarity: v2 * (1 + ceWeight * ce) };
|
|
4618
4716
|
});
|
|
4619
4717
|
combined.sort((a, b) => b.similarity - a.similarity);
|
|
4718
|
+
if (headSlice.length > 0 && options.rerankStats) options.rerankStats.applied = true;
|
|
4620
4719
|
} catch (err) {
|
|
4621
|
-
|
|
4720
|
+
if (err instanceof RerankerUnavailableError) {
|
|
4721
|
+
getLogger().debug("[memory/search] cross-encoder unavailable; using V2 ranking");
|
|
4722
|
+
} else {
|
|
4723
|
+
getLogger().warn("[memory/search] cross-encoder rerank failed; using V2 ranking", err);
|
|
4724
|
+
}
|
|
4622
4725
|
combined = v2Ranked;
|
|
4623
4726
|
}
|
|
4624
4727
|
} else {
|
|
@@ -4752,6 +4855,9 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
|
|
|
4752
4855
|
(r) => r !== null
|
|
4753
4856
|
);
|
|
4754
4857
|
combined.sort((a, b) => b.similarity - a.similarity);
|
|
4858
|
+
if (options?.v2HeadStats) {
|
|
4859
|
+
options.v2HeadStats.hadResults = combined.length > 0;
|
|
4860
|
+
}
|
|
4755
4861
|
if (options?.includeUnrankedTail) {
|
|
4756
4862
|
const fusedIds = new Set(combined.map((r) => r.uniqueId));
|
|
4757
4863
|
for (const item of items) {
|
|
@@ -4787,11 +4893,16 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
|
|
|
4787
4893
|
}));
|
|
4788
4894
|
head.sort((a, b) => b.similarity - a.similarity);
|
|
4789
4895
|
combined = [...head, ...tailSlice];
|
|
4896
|
+
if (headSlice.length > 0 && options.rerankStats) options.rerankStats.applied = true;
|
|
4790
4897
|
} catch (err) {
|
|
4791
|
-
|
|
4792
|
-
"[memory/search]
|
|
4793
|
-
|
|
4794
|
-
|
|
4898
|
+
if (err instanceof RerankerUnavailableError) {
|
|
4899
|
+
getLogger().debug("[memory/search] cross-encoder unavailable; using fused ranking");
|
|
4900
|
+
} else {
|
|
4901
|
+
getLogger().warn(
|
|
4902
|
+
"[memory/search] composite cross-encoder rerank failed; using fused ranking",
|
|
4903
|
+
err
|
|
4904
|
+
);
|
|
4905
|
+
}
|
|
4795
4906
|
}
|
|
4796
4907
|
}
|
|
4797
4908
|
if (options?.mmr) {
|
|
@@ -4883,7 +4994,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
4883
4994
|
const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
|
|
4884
4995
|
const scopes = searchOptions?.scopes;
|
|
4885
4996
|
if (!query || typeof query !== "string") {
|
|
4886
|
-
return { results: [], vaultSize: 0 };
|
|
4997
|
+
return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
|
|
4887
4998
|
}
|
|
4888
4999
|
const folderId = searchOptions?.folderId;
|
|
4889
5000
|
const queryOpts = {};
|
|
@@ -4900,7 +5011,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
4900
5011
|
);
|
|
4901
5012
|
}
|
|
4902
5013
|
if (memories.length === 0) {
|
|
4903
|
-
return { results: [], vaultSize: loaded.length };
|
|
5014
|
+
return { results: [], vaultSize: loaded.length, reranked: false, hadV2Head: false };
|
|
4904
5015
|
}
|
|
4905
5016
|
const queryEmbedding = await generateEmbedding(query, embeddingOptions);
|
|
4906
5017
|
const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
@@ -4976,12 +5087,18 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
4976
5087
|
memories.map((m) => [m.uniqueId, { createdAt: m.createdAt, updatedAt: m.updatedAt }])
|
|
4977
5088
|
);
|
|
4978
5089
|
const stampTimestamps = (out) => {
|
|
4979
|
-
|
|
5090
|
+
const results2 = out.results.map((r) => {
|
|
4980
5091
|
const ts = timestampById.get(r.uniqueId);
|
|
4981
5092
|
return ts ? { ...r, createdAt: ts.createdAt, updatedAt: ts.updatedAt } : r;
|
|
4982
5093
|
});
|
|
4983
|
-
return
|
|
5094
|
+
return {
|
|
5095
|
+
results: results2,
|
|
5096
|
+
vaultSize: out.vaultSize,
|
|
5097
|
+
reranked: out.reranked ?? false,
|
|
5098
|
+
hadV2Head: out.hadV2Head ?? false
|
|
5099
|
+
};
|
|
4984
5100
|
};
|
|
5101
|
+
const rerankStats = { applied: false };
|
|
4985
5102
|
const useFusion = searchOptions?.useFusion ?? true;
|
|
4986
5103
|
const tuning = {
|
|
4987
5104
|
...searchOptions?.recencyAlpha !== void 0 && { recencyAlpha: searchOptions.recencyAlpha },
|
|
@@ -5008,6 +5125,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
5008
5125
|
query: sq,
|
|
5009
5126
|
embedding: subEmbeddings[i]
|
|
5010
5127
|
}));
|
|
5128
|
+
const v2HeadStats = { hadResults: false };
|
|
5011
5129
|
const composite = await rankComposite(query, queryEmbedding, subQueries, embeddedItems, {
|
|
5012
5130
|
limit,
|
|
5013
5131
|
minSimilarity,
|
|
@@ -5019,12 +5137,20 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
5019
5137
|
...searchOptions.mmr !== void 0 && { mmr: searchOptions.mmr },
|
|
5020
5138
|
...tuning,
|
|
5021
5139
|
...searchOptions.entityRanking && { entityRanking: searchOptions.entityRanking },
|
|
5022
|
-
...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking }
|
|
5140
|
+
...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
|
|
5141
|
+
rerankStats,
|
|
5142
|
+
v2HeadStats
|
|
5143
|
+
});
|
|
5144
|
+
return stampTimestamps({
|
|
5145
|
+
results: composite,
|
|
5146
|
+
vaultSize: loaded.length,
|
|
5147
|
+
reranked: rerankStats.applied,
|
|
5148
|
+
hadV2Head: v2HeadStats.hadResults
|
|
5023
5149
|
});
|
|
5024
|
-
return stampTimestamps({ results: composite, vaultSize: loaded.length });
|
|
5025
5150
|
}
|
|
5026
5151
|
}
|
|
5027
5152
|
if (useFusion && searchOptions?.rerank) {
|
|
5153
|
+
const v2HeadStats = { hadResults: false };
|
|
5028
5154
|
const results2 = await rankFusedVaultMemoriesAsync(query, queryEmbedding, embeddedItems, {
|
|
5029
5155
|
limit,
|
|
5030
5156
|
minSimilarity,
|
|
@@ -5036,9 +5162,16 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
5036
5162
|
...searchOptions.mmr !== void 0 && { mmr: searchOptions.mmr },
|
|
5037
5163
|
...tuning,
|
|
5038
5164
|
...searchOptions.entityRanking && { entityRanking: searchOptions.entityRanking },
|
|
5039
|
-
...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking }
|
|
5165
|
+
...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
|
|
5166
|
+
rerankStats,
|
|
5167
|
+
v2HeadStats
|
|
5168
|
+
});
|
|
5169
|
+
return stampTimestamps({
|
|
5170
|
+
results: results2,
|
|
5171
|
+
vaultSize: loaded.length,
|
|
5172
|
+
reranked: rerankStats.applied,
|
|
5173
|
+
hadV2Head: v2HeadStats.hadResults
|
|
5040
5174
|
});
|
|
5041
|
-
return stampTimestamps({ results: results2, vaultSize: loaded.length });
|
|
5042
5175
|
}
|
|
5043
5176
|
if (useFusion) {
|
|
5044
5177
|
const results2 = rankFusedVaultMemories(query, queryEmbedding, embeddedItems, {
|
|
@@ -5048,7 +5181,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
5048
5181
|
...searchOptions?.entityRanking && { entityRanking: searchOptions.entityRanking },
|
|
5049
5182
|
...searchOptions?.temporalRanking && { temporalRanking: searchOptions.temporalRanking }
|
|
5050
5183
|
});
|
|
5051
|
-
return stampTimestamps({ results: results2, vaultSize: loaded.length });
|
|
5184
|
+
return stampTimestamps({ results: results2, vaultSize: loaded.length, hadV2Head: results2.length > 0 });
|
|
5052
5185
|
}
|
|
5053
5186
|
const results = rankVaultMemories(query, queryEmbedding, embeddedItems, {
|
|
5054
5187
|
limit,
|
|
@@ -5060,7 +5193,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
5060
5193
|
supersessionWindow: searchOptions.supersessionWindow
|
|
5061
5194
|
}
|
|
5062
5195
|
});
|
|
5063
|
-
return stampTimestamps({ results, vaultSize: loaded.length });
|
|
5196
|
+
return stampTimestamps({ results, vaultSize: loaded.length, hadV2Head: results.length > 0 });
|
|
5064
5197
|
}
|
|
5065
5198
|
async function searchVaultMemories(query, vaultCtx, embeddingOptions, cache, searchOptions) {
|
|
5066
5199
|
const { results } = await searchVaultMemoriesWithSize(
|
|
@@ -5149,7 +5282,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
5149
5282
|
legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
|
|
5150
5283
|
);
|
|
5151
5284
|
}
|
|
5152
|
-
const { recall: recall2 } = await import("./recall-
|
|
5285
|
+
const { recall: recall2 } = await import("./recall-G3CS444F.mjs");
|
|
5153
5286
|
const result = await recall2(
|
|
5154
5287
|
query,
|
|
5155
5288
|
{ vaultCtx, embeddingOptions, vaultCache: cache },
|
|
@@ -5467,6 +5600,7 @@ function scoreEventTimeOverlap(memoryStart, memoryEnd, memoryKind, window2) {
|
|
|
5467
5600
|
var DEFAULT_LIMIT = 8;
|
|
5468
5601
|
var DEFAULT_BUDGET = "low";
|
|
5469
5602
|
var DEFAULT_FACT_MIN_SCORE = 0.1;
|
|
5603
|
+
var nowMs = () => typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
5470
5604
|
var DEFAULT_CHUNK_MIN_SCORE = 0.5;
|
|
5471
5605
|
function flagsForBudget(budget) {
|
|
5472
5606
|
switch (budget) {
|
|
@@ -5499,22 +5633,67 @@ async function recall(query, ctx, options = {}) {
|
|
|
5499
5633
|
const flags = flagsForBudget(requestedBudget);
|
|
5500
5634
|
const decomposeAvailable = flags.decompose && !!options.decomposeOptions;
|
|
5501
5635
|
const usedBudget = requestedBudget === "high" && !decomposeAvailable ? "mid" : requestedBudget;
|
|
5636
|
+
const t0 = nowMs();
|
|
5637
|
+
let prepMs = 0;
|
|
5638
|
+
let factLaneMs = 0;
|
|
5639
|
+
let chunkLaneMs = 0;
|
|
5640
|
+
let fuseMs = 0;
|
|
5641
|
+
const factResults = [];
|
|
5642
|
+
const chunkResults = [];
|
|
5643
|
+
let vaultSize;
|
|
5644
|
+
let didRerank = false;
|
|
5645
|
+
let hadV2Head = false;
|
|
5646
|
+
const emitDiagnostics = (candidateCount) => {
|
|
5647
|
+
const cb = options.onDiagnostics;
|
|
5648
|
+
if (!cb) return;
|
|
5649
|
+
const degraded = [];
|
|
5650
|
+
if (flags.rerank && factResults.length > 0 && hadV2Head && !didRerank) {
|
|
5651
|
+
degraded.push("rerank-unavailable");
|
|
5652
|
+
}
|
|
5653
|
+
if (flags.decompose && !decomposeAvailable) degraded.push("decompose-unavailable");
|
|
5654
|
+
const diagnostics = {
|
|
5655
|
+
usedBudget,
|
|
5656
|
+
reranked: didRerank,
|
|
5657
|
+
candidateCount,
|
|
5658
|
+
...vaultSize !== void 0 && { vaultSize },
|
|
5659
|
+
factCount: factResults.length,
|
|
5660
|
+
chunkCount: chunkResults.length,
|
|
5661
|
+
timings: {
|
|
5662
|
+
total: nowMs() - t0,
|
|
5663
|
+
prep: prepMs,
|
|
5664
|
+
factLane: factLaneMs,
|
|
5665
|
+
chunkLane: chunkLaneMs,
|
|
5666
|
+
fuse: fuseMs
|
|
5667
|
+
},
|
|
5668
|
+
degraded
|
|
5669
|
+
};
|
|
5670
|
+
try {
|
|
5671
|
+
cb(diagnostics);
|
|
5672
|
+
} catch {
|
|
5673
|
+
}
|
|
5674
|
+
};
|
|
5502
5675
|
if (!query || typeof query !== "string" || query.trim().length === 0) {
|
|
5676
|
+
emitDiagnostics(0);
|
|
5503
5677
|
return { memories: [], usedBudget, reranked: false, candidateCount: 0 };
|
|
5504
5678
|
}
|
|
5505
5679
|
const needsChunkEmbedding = types.includes("chunk") && ctx.storageCtx;
|
|
5506
5680
|
const wantsTemporal = types.includes("fact") && ctx.vaultCtx;
|
|
5681
|
+
const prepStart = nowMs();
|
|
5507
5682
|
const [queryEmbedding, entityRanking, temporalRanking] = await Promise.all([
|
|
5508
5683
|
needsChunkEmbedding ? generateEmbedding(query, ctx.embeddingOptions) : Promise.resolve(void 0),
|
|
5509
5684
|
buildGraphLaneRanking(query, ctx),
|
|
5510
5685
|
wantsTemporal ? buildTemporalLaneRanking(query, ctx.vaultCtx, options.now) : Promise.resolve([])
|
|
5511
5686
|
]);
|
|
5512
|
-
|
|
5513
|
-
const chunkResults = [];
|
|
5514
|
-
let vaultSize;
|
|
5687
|
+
prepMs = nowMs() - prepStart;
|
|
5515
5688
|
if (types.includes("fact") && ctx.vaultCtx && ctx.vaultCache) {
|
|
5689
|
+
const factStart = nowMs();
|
|
5516
5690
|
const vaultMinScore = options.minScore ?? DEFAULT_FACT_MIN_SCORE;
|
|
5517
|
-
const {
|
|
5691
|
+
const {
|
|
5692
|
+
results,
|
|
5693
|
+
vaultSize: size,
|
|
5694
|
+
reranked,
|
|
5695
|
+
hadV2Head: v2Head
|
|
5696
|
+
} = await searchVaultMemoriesWithSize(
|
|
5518
5697
|
query,
|
|
5519
5698
|
ctx.vaultCtx,
|
|
5520
5699
|
ctx.embeddingOptions,
|
|
@@ -5565,14 +5744,19 @@ async function recall(query, ctx, options = {}) {
|
|
|
5565
5744
|
)
|
|
5566
5745
|
);
|
|
5567
5746
|
vaultSize = size;
|
|
5747
|
+
didRerank = reranked;
|
|
5748
|
+
hadV2Head = v2Head;
|
|
5749
|
+
factLaneMs = nowMs() - factStart;
|
|
5568
5750
|
}
|
|
5569
5751
|
if (types.includes("chunk") && ctx.storageCtx && queryEmbedding) {
|
|
5752
|
+
const chunkStart = nowMs();
|
|
5570
5753
|
const chunkMinScore = options.minScore ?? DEFAULT_CHUNK_MIN_SCORE;
|
|
5571
5754
|
const results = await searchChunksOp(ctx.storageCtx, queryEmbedding, {
|
|
5572
5755
|
limit: types.includes("fact") ? Math.max(limit * 2, 16) : limit,
|
|
5573
5756
|
minSimilarity: chunkMinScore,
|
|
5574
5757
|
embeddingModel: ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL,
|
|
5575
|
-
...options.conversationId && { conversationId: options.conversationId }
|
|
5758
|
+
...options.conversationId && { conversationId: options.conversationId },
|
|
5759
|
+
...ctx.chunkCache && { chunkCache: ctx.chunkCache }
|
|
5576
5760
|
});
|
|
5577
5761
|
chunkResults.push(
|
|
5578
5762
|
...dedupeBy(
|
|
@@ -5582,18 +5766,23 @@ async function recall(query, ctx, options = {}) {
|
|
|
5582
5766
|
(r) => r.chunkText.trim()
|
|
5583
5767
|
)
|
|
5584
5768
|
);
|
|
5769
|
+
chunkLaneMs = nowMs() - chunkStart;
|
|
5585
5770
|
}
|
|
5771
|
+
const fuseStart = nowMs();
|
|
5586
5772
|
if (types.length === 1 || factResults.length === 0 || chunkResults.length === 0) {
|
|
5587
5773
|
const memories2 = [
|
|
5588
5774
|
...factResults.map(toFactMemory),
|
|
5589
5775
|
...chunkResults.map(toChunkMemory)
|
|
5590
5776
|
];
|
|
5591
5777
|
memories2.sort((a, b) => b.score - a.score);
|
|
5778
|
+
const candidateCount = factResults.length + chunkResults.length;
|
|
5779
|
+
fuseMs = nowMs() - fuseStart;
|
|
5780
|
+
emitDiagnostics(candidateCount);
|
|
5592
5781
|
return {
|
|
5593
5782
|
memories: memories2.slice(0, limit),
|
|
5594
5783
|
usedBudget,
|
|
5595
|
-
reranked:
|
|
5596
|
-
candidateCount
|
|
5784
|
+
reranked: didRerank,
|
|
5785
|
+
candidateCount,
|
|
5597
5786
|
...vaultSize !== void 0 && { vaultSize }
|
|
5598
5787
|
};
|
|
5599
5788
|
}
|
|
@@ -5642,10 +5831,12 @@ async function recall(query, ctx, options = {}) {
|
|
|
5642
5831
|
suppressed = next;
|
|
5643
5832
|
memories = selectWith(suppressed);
|
|
5644
5833
|
}
|
|
5834
|
+
fuseMs = nowMs() - fuseStart;
|
|
5835
|
+
emitDiagnostics(byId.size);
|
|
5645
5836
|
return {
|
|
5646
5837
|
memories,
|
|
5647
5838
|
usedBudget,
|
|
5648
|
-
reranked:
|
|
5839
|
+
reranked: didRerank,
|
|
5649
5840
|
candidateCount: byId.size,
|
|
5650
5841
|
...vaultSize !== void 0 && { vaultSize }
|
|
5651
5842
|
};
|
|
@@ -5830,7 +6021,10 @@ export {
|
|
|
5830
6021
|
stampTopicsExtractedAtOp,
|
|
5831
6022
|
deleteAllVaultMemoriesForUserOp,
|
|
5832
6023
|
updateVaultMemoryEmbeddingOp,
|
|
6024
|
+
RerankerUnavailableError,
|
|
6025
|
+
isRerankerAvailable,
|
|
5833
6026
|
DEFAULT_VAULT_CACHE_SIZE,
|
|
6027
|
+
LRUCache,
|
|
5834
6028
|
createVaultEmbeddingCache,
|
|
5835
6029
|
recall,
|
|
5836
6030
|
preEmbedVaultMemories,
|