@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.
@@ -2770,7 +2770,13 @@ async function searchMessagesOp(ctx, queryVector, options) {
2770
2770
  );
2771
2771
  }
2772
2772
  async function searchChunksOp(ctx, queryVector, options) {
2773
- const { limit = 10, minSimilarity = 0.5, conversationId, embeddingModel } = options || {};
2773
+ const {
2774
+ limit = 10,
2775
+ minSimilarity = 0.5,
2776
+ conversationId,
2777
+ embeddingModel,
2778
+ chunkCache
2779
+ } = options || {};
2774
2780
  const activeConversations = await ctx.conversationsCollection.query(import_watermelondb.Q.where("is_deleted", false)).fetch();
2775
2781
  const activeConversationIds = new Set(
2776
2782
  // Use _getRaw for reliable raw column access
@@ -2790,23 +2796,54 @@ async function searchChunksOp(ctx, queryVector, options) {
2790
2796
  continue;
2791
2797
  }
2792
2798
  }
2799
+ const version = Number(message._getRaw("updated_at")) || 0;
2800
+ const cached = chunkCache?.get(message.id);
2801
+ if (cached && cached.version === version) {
2802
+ if (cached.chunks.length > 0) {
2803
+ for (let ci = 0; ci < cached.chunks.length; ci++) {
2804
+ const vec = cached.chunks[ci];
2805
+ if (vec.length === 0) continue;
2806
+ const similarity = cosineSimilarity(queryVector, vec);
2807
+ if (similarity >= minSimilarity) {
2808
+ candidates.push({
2809
+ message,
2810
+ similarity,
2811
+ chunkTextSource: { kind: "chunk-cached", chunkIndex: ci, version }
2812
+ });
2813
+ }
2814
+ }
2815
+ } else if (cached.fallback) {
2816
+ const similarity = cosineSimilarity(queryVector, cached.fallback);
2817
+ if (similarity >= minSimilarity) {
2818
+ candidates.push({ message, similarity, chunkTextSource: { kind: "message" } });
2819
+ }
2820
+ }
2821
+ continue;
2822
+ }
2793
2823
  const chunks = await readJsonField(message, "chunks", ctx.walletAddress);
2794
2824
  if (chunks && chunks.length > 0) {
2795
- for (const chunk of chunks) {
2796
- if (!chunk.vector || chunk.vector.length === 0) continue;
2797
- const similarity = cosineSimilarity(queryVector, chunk.vector);
2825
+ const vectors = chunks.map(
2826
+ (chunk) => chunk.vector && chunk.vector.length > 0 ? Float32Array.from(chunk.vector) : new Float32Array(0)
2827
+ );
2828
+ chunkCache?.set(message.id, { version, chunks: vectors });
2829
+ for (let ci = 0; ci < chunks.length; ci++) {
2830
+ const vec = vectors[ci];
2831
+ if (vec.length === 0) continue;
2832
+ const similarity = cosineSimilarity(queryVector, vec);
2798
2833
  if (similarity >= minSimilarity) {
2799
2834
  candidates.push({
2800
2835
  message,
2801
2836
  similarity,
2802
- chunkTextSource: { kind: "chunk", text: chunk.text }
2837
+ chunkTextSource: { kind: "chunk", text: chunks[ci].text }
2803
2838
  });
2804
2839
  }
2805
2840
  }
2806
2841
  } else {
2807
2842
  const messageVector = await readJsonField(message, "vector", ctx.walletAddress);
2808
2843
  if (!messageVector || messageVector.length === 0) continue;
2809
- const similarity = cosineSimilarity(queryVector, messageVector);
2844
+ const fallback = Float32Array.from(messageVector);
2845
+ chunkCache?.set(message.id, { version, chunks: [], fallback });
2846
+ const similarity = cosineSimilarity(queryVector, fallback);
2810
2847
  if (similarity >= minSimilarity) {
2811
2848
  candidates.push({ message, similarity, chunkTextSource: { kind: "message" } });
2812
2849
  }
@@ -2833,9 +2870,31 @@ async function searchChunksOp(ctx, queryVector, options) {
2833
2870
  })
2834
2871
  )
2835
2872
  );
2873
+ const chunkStateByMsgId = /* @__PURE__ */ new Map();
2874
+ const needsChunkText = /* @__PURE__ */ new Set();
2875
+ for (const c of topK) {
2876
+ if (c.chunkTextSource.kind === "chunk-cached") needsChunkText.add(c.message.id);
2877
+ }
2878
+ await Promise.all(
2879
+ Array.from(needsChunkText, async (id) => {
2880
+ const m = uniqueMessages.get(id);
2881
+ const parsed = await readJsonField(m, "chunks", ctx.walletAddress);
2882
+ const version = Number(m._getRaw("updated_at")) || 0;
2883
+ if (parsed) chunkStateByMsgId.set(id, { version, chunks: parsed });
2884
+ })
2885
+ );
2836
2886
  return topK.map(({ message, similarity, chunkTextSource }) => {
2837
2887
  const stored = { ...storedById.get(message.id) };
2838
- const chunkText2 = chunkTextSource.kind === "chunk" ? chunkTextSource.text : stored.content;
2888
+ let chunkText2;
2889
+ if (chunkTextSource.kind === "chunk") {
2890
+ chunkText2 = chunkTextSource.text;
2891
+ } else if (chunkTextSource.kind === "chunk-cached") {
2892
+ const state = chunkStateByMsgId.get(message.id);
2893
+ const chunk = state && state.version === chunkTextSource.version ? state.chunks[chunkTextSource.chunkIndex] : void 0;
2894
+ chunkText2 = chunk?.text ?? stored.content;
2895
+ } else {
2896
+ chunkText2 = stored.content;
2897
+ }
2839
2898
  return { chunkText: chunkText2, message: stored, similarity };
2840
2899
  });
2841
2900
  }
@@ -5172,9 +5231,9 @@ function recencyMultiplier(updatedAt, opts = {}) {
5172
5231
  const updatedMs = updatedAt.getTime();
5173
5232
  if (!Number.isFinite(updatedMs)) return noDate;
5174
5233
  const now = opts.now ?? /* @__PURE__ */ new Date();
5175
- const nowMs = now.getTime();
5176
- if (!Number.isFinite(nowMs)) return noDate;
5177
- const ageDays = Math.max(0, (nowMs - updatedMs) / DAY_MS);
5234
+ const nowMs2 = now.getTime();
5235
+ if (!Number.isFinite(nowMs2)) return noDate;
5236
+ const ageDays = Math.max(0, (nowMs2 - updatedMs) / DAY_MS);
5178
5237
  const perYearDecay = opts.perYearDecay ?? DEFAULT_PER_YEAR_DECAY;
5179
5238
  const floor = opts.floor ?? DEFAULT_FLOOR;
5180
5239
  const decay = perYearDecay * (ageDays / 365);
@@ -5192,14 +5251,42 @@ var init_recency = __esm({
5192
5251
  });
5193
5252
 
5194
5253
  // src/lib/memory/reranker.ts
5254
+ function isRerankerAvailable() {
5255
+ return available;
5256
+ }
5257
+ function isModuleMissing(err) {
5258
+ let e = err;
5259
+ for (let depth = 0; depth < 5 && e !== null && e !== void 0; depth++) {
5260
+ const code = e.code;
5261
+ if (code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND") return true;
5262
+ if (e instanceof Error && /cannot find (module|package)|failed to resolve|unable to resolve module|requiring unknown module/i.test(
5263
+ e.message
5264
+ )) {
5265
+ return true;
5266
+ }
5267
+ e = e.cause;
5268
+ }
5269
+ return false;
5270
+ }
5195
5271
  async function getModel() {
5272
+ if (available === false) throw new RerankerUnavailableError(void 0);
5196
5273
  if (!modelPromise) {
5197
5274
  const load = (async () => {
5198
- const transformers = await import("@huggingface/transformers");
5275
+ let transformers;
5276
+ try {
5277
+ transformers = await import("@huggingface/transformers");
5278
+ } catch (err) {
5279
+ if (isModuleMissing(err)) {
5280
+ available = false;
5281
+ throw new RerankerUnavailableError(err);
5282
+ }
5283
+ throw err;
5284
+ }
5199
5285
  const [tokenizer, model] = await Promise.all([
5200
5286
  transformers.AutoTokenizer.from_pretrained(MODEL_ID),
5201
5287
  transformers.AutoModelForSequenceClassification.from_pretrained(MODEL_ID)
5202
5288
  ]);
5289
+ available = true;
5203
5290
  return { tokenizer, model };
5204
5291
  })();
5205
5292
  modelPromise = load;
@@ -5241,11 +5328,19 @@ async function rerankPairs(query, items) {
5241
5328
  }
5242
5329
  return items.map((item, i) => ({ id: item.id, content: item.content, score: scores[i] })).sort((a, b) => b.score - a.score);
5243
5330
  }
5244
- var MODEL_ID, modelPromise;
5331
+ var MODEL_ID, RerankerUnavailableError, available, modelPromise;
5245
5332
  var init_reranker = __esm({
5246
5333
  "src/lib/memory/reranker.ts"() {
5247
5334
  "use strict";
5248
5335
  MODEL_ID = "Xenova/ms-marco-MiniLM-L-6-v2";
5336
+ RerankerUnavailableError = class extends Error {
5337
+ constructor(reason) {
5338
+ super("cross-encoder reranker unavailable (@huggingface/transformers not installed)");
5339
+ this.name = "RerankerUnavailableError";
5340
+ this.reason = reason;
5341
+ }
5342
+ };
5343
+ available = void 0;
5249
5344
  modelPromise = null;
5250
5345
  }
5251
5346
  });
@@ -5914,22 +6009,67 @@ async function recall(query, ctx, options = {}) {
5914
6009
  const flags = flagsForBudget(requestedBudget);
5915
6010
  const decomposeAvailable = flags.decompose && !!options.decomposeOptions;
5916
6011
  const usedBudget = requestedBudget === "high" && !decomposeAvailable ? "mid" : requestedBudget;
6012
+ const t0 = nowMs();
6013
+ let prepMs = 0;
6014
+ let factLaneMs = 0;
6015
+ let chunkLaneMs = 0;
6016
+ let fuseMs = 0;
6017
+ const factResults = [];
6018
+ const chunkResults = [];
6019
+ let vaultSize;
6020
+ let didRerank = false;
6021
+ let hadV2Head = false;
6022
+ const emitDiagnostics = (candidateCount) => {
6023
+ const cb = options.onDiagnostics;
6024
+ if (!cb) return;
6025
+ const degraded = [];
6026
+ if (flags.rerank && factResults.length > 0 && hadV2Head && !didRerank) {
6027
+ degraded.push("rerank-unavailable");
6028
+ }
6029
+ if (flags.decompose && !decomposeAvailable) degraded.push("decompose-unavailable");
6030
+ const diagnostics = {
6031
+ usedBudget,
6032
+ reranked: didRerank,
6033
+ candidateCount,
6034
+ ...vaultSize !== void 0 && { vaultSize },
6035
+ factCount: factResults.length,
6036
+ chunkCount: chunkResults.length,
6037
+ timings: {
6038
+ total: nowMs() - t0,
6039
+ prep: prepMs,
6040
+ factLane: factLaneMs,
6041
+ chunkLane: chunkLaneMs,
6042
+ fuse: fuseMs
6043
+ },
6044
+ degraded
6045
+ };
6046
+ try {
6047
+ cb(diagnostics);
6048
+ } catch {
6049
+ }
6050
+ };
5917
6051
  if (!query || typeof query !== "string" || query.trim().length === 0) {
6052
+ emitDiagnostics(0);
5918
6053
  return { memories: [], usedBudget, reranked: false, candidateCount: 0 };
5919
6054
  }
5920
6055
  const needsChunkEmbedding = types.includes("chunk") && ctx.storageCtx;
5921
6056
  const wantsTemporal = types.includes("fact") && ctx.vaultCtx;
6057
+ const prepStart = nowMs();
5922
6058
  const [queryEmbedding, entityRanking, temporalRanking] = await Promise.all([
5923
6059
  needsChunkEmbedding ? generateEmbedding(query, ctx.embeddingOptions) : Promise.resolve(void 0),
5924
6060
  buildGraphLaneRanking(query, ctx),
5925
6061
  wantsTemporal ? buildTemporalLaneRanking(query, ctx.vaultCtx, options.now) : Promise.resolve([])
5926
6062
  ]);
5927
- const factResults = [];
5928
- const chunkResults = [];
5929
- let vaultSize;
6063
+ prepMs = nowMs() - prepStart;
5930
6064
  if (types.includes("fact") && ctx.vaultCtx && ctx.vaultCache) {
6065
+ const factStart = nowMs();
5931
6066
  const vaultMinScore = options.minScore ?? DEFAULT_FACT_MIN_SCORE;
5932
- const { results, vaultSize: size } = await searchVaultMemoriesWithSize(
6067
+ const {
6068
+ results,
6069
+ vaultSize: size,
6070
+ reranked,
6071
+ hadV2Head: v2Head
6072
+ } = await searchVaultMemoriesWithSize(
5933
6073
  query,
5934
6074
  ctx.vaultCtx,
5935
6075
  ctx.embeddingOptions,
@@ -5980,14 +6120,19 @@ async function recall(query, ctx, options = {}) {
5980
6120
  )
5981
6121
  );
5982
6122
  vaultSize = size;
6123
+ didRerank = reranked;
6124
+ hadV2Head = v2Head;
6125
+ factLaneMs = nowMs() - factStart;
5983
6126
  }
5984
6127
  if (types.includes("chunk") && ctx.storageCtx && queryEmbedding) {
6128
+ const chunkStart = nowMs();
5985
6129
  const chunkMinScore = options.minScore ?? DEFAULT_CHUNK_MIN_SCORE;
5986
6130
  const results = await searchChunksOp(ctx.storageCtx, queryEmbedding, {
5987
6131
  limit: types.includes("fact") ? Math.max(limit * 2, 16) : limit,
5988
6132
  minSimilarity: chunkMinScore,
5989
6133
  embeddingModel: ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL,
5990
- ...options.conversationId && { conversationId: options.conversationId }
6134
+ ...options.conversationId && { conversationId: options.conversationId },
6135
+ ...ctx.chunkCache && { chunkCache: ctx.chunkCache }
5991
6136
  });
5992
6137
  chunkResults.push(
5993
6138
  ...dedupeBy(
@@ -5997,18 +6142,23 @@ async function recall(query, ctx, options = {}) {
5997
6142
  (r) => r.chunkText.trim()
5998
6143
  )
5999
6144
  );
6145
+ chunkLaneMs = nowMs() - chunkStart;
6000
6146
  }
6147
+ const fuseStart = nowMs();
6001
6148
  if (types.length === 1 || factResults.length === 0 || chunkResults.length === 0) {
6002
6149
  const memories2 = [
6003
6150
  ...factResults.map(toFactMemory),
6004
6151
  ...chunkResults.map(toChunkMemory)
6005
6152
  ];
6006
6153
  memories2.sort((a, b) => b.score - a.score);
6154
+ const candidateCount = factResults.length + chunkResults.length;
6155
+ fuseMs = nowMs() - fuseStart;
6156
+ emitDiagnostics(candidateCount);
6007
6157
  return {
6008
6158
  memories: memories2.slice(0, limit),
6009
6159
  usedBudget,
6010
- reranked: flags.rerank,
6011
- candidateCount: factResults.length + chunkResults.length,
6160
+ reranked: didRerank,
6161
+ candidateCount,
6012
6162
  ...vaultSize !== void 0 && { vaultSize }
6013
6163
  };
6014
6164
  }
@@ -6057,10 +6207,12 @@ async function recall(query, ctx, options = {}) {
6057
6207
  suppressed = next;
6058
6208
  memories = selectWith(suppressed);
6059
6209
  }
6210
+ fuseMs = nowMs() - fuseStart;
6211
+ emitDiagnostics(byId.size);
6060
6212
  return {
6061
6213
  memories,
6062
6214
  usedBudget,
6063
- reranked: flags.rerank,
6215
+ reranked: didRerank,
6064
6216
  candidateCount: byId.size,
6065
6217
  ...vaultSize !== void 0 && { vaultSize }
6066
6218
  };
@@ -6124,7 +6276,7 @@ function toChunkMemory(r) {
6124
6276
  updatedAt: r.message.createdAt
6125
6277
  };
6126
6278
  }
6127
- var DEFAULT_LIMIT, DEFAULT_BUDGET, DEFAULT_FACT_MIN_SCORE, DEFAULT_CHUNK_MIN_SCORE;
6279
+ var DEFAULT_LIMIT, DEFAULT_BUDGET, DEFAULT_FACT_MIN_SCORE, nowMs, DEFAULT_CHUNK_MIN_SCORE;
6128
6280
  var init_recall = __esm({
6129
6281
  "src/lib/memory/recall.ts"() {
6130
6282
  "use strict";
@@ -6140,6 +6292,7 @@ var init_recall = __esm({
6140
6292
  DEFAULT_LIMIT = 8;
6141
6293
  DEFAULT_BUDGET = "low";
6142
6294
  DEFAULT_FACT_MIN_SCORE = 0.1;
6295
+ nowMs = () => typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
6143
6296
  DEFAULT_CHUNK_MIN_SCORE = 0.5;
6144
6297
  }
6145
6298
  });
@@ -6339,6 +6492,9 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
6339
6492
  bm25AdmissionDivisor: options?.bm25AdmissionDivisor,
6340
6493
  rrfK: options?.rrfK
6341
6494
  });
6495
+ if (options?.v2HeadStats) {
6496
+ options.v2HeadStats.hadResults = v2Ranked.length > 0;
6497
+ }
6342
6498
  let combined;
6343
6499
  let tailSlice = [];
6344
6500
  if (options?.rerank) {
@@ -6359,8 +6515,13 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
6359
6515
  return { ...r, similarity: v2 * (1 + ceWeight * ce) };
6360
6516
  });
6361
6517
  combined.sort((a, b) => b.similarity - a.similarity);
6518
+ if (headSlice.length > 0 && options.rerankStats) options.rerankStats.applied = true;
6362
6519
  } catch (err) {
6363
- getLogger().warn("[memory/search] cross-encoder rerank failed; using V2 ranking", err);
6520
+ if (err instanceof RerankerUnavailableError) {
6521
+ getLogger().debug("[memory/search] cross-encoder unavailable; using V2 ranking");
6522
+ } else {
6523
+ getLogger().warn("[memory/search] cross-encoder rerank failed; using V2 ranking", err);
6524
+ }
6364
6525
  combined = v2Ranked;
6365
6526
  }
6366
6527
  } else {
@@ -6494,6 +6655,9 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
6494
6655
  (r) => r !== null
6495
6656
  );
6496
6657
  combined.sort((a, b) => b.similarity - a.similarity);
6658
+ if (options?.v2HeadStats) {
6659
+ options.v2HeadStats.hadResults = combined.length > 0;
6660
+ }
6497
6661
  if (options?.includeUnrankedTail) {
6498
6662
  const fusedIds = new Set(combined.map((r) => r.uniqueId));
6499
6663
  for (const item of items) {
@@ -6529,11 +6693,16 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
6529
6693
  }));
6530
6694
  head.sort((a, b) => b.similarity - a.similarity);
6531
6695
  combined = [...head, ...tailSlice];
6696
+ if (headSlice.length > 0 && options.rerankStats) options.rerankStats.applied = true;
6532
6697
  } catch (err) {
6533
- getLogger().warn(
6534
- "[memory/search] composite cross-encoder rerank failed; using fused ranking",
6535
- err
6536
- );
6698
+ if (err instanceof RerankerUnavailableError) {
6699
+ getLogger().debug("[memory/search] cross-encoder unavailable; using fused ranking");
6700
+ } else {
6701
+ getLogger().warn(
6702
+ "[memory/search] composite cross-encoder rerank failed; using fused ranking",
6703
+ err
6704
+ );
6705
+ }
6537
6706
  }
6538
6707
  }
6539
6708
  if (options?.mmr) {
@@ -6625,7 +6794,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6625
6794
  const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
6626
6795
  const scopes = searchOptions?.scopes;
6627
6796
  if (!query || typeof query !== "string") {
6628
- return { results: [], vaultSize: 0 };
6797
+ return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
6629
6798
  }
6630
6799
  const folderId = searchOptions?.folderId;
6631
6800
  const queryOpts = {};
@@ -6642,7 +6811,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6642
6811
  );
6643
6812
  }
6644
6813
  if (memories.length === 0) {
6645
- return { results: [], vaultSize: loaded.length };
6814
+ return { results: [], vaultSize: loaded.length, reranked: false, hadV2Head: false };
6646
6815
  }
6647
6816
  const queryEmbedding = await generateEmbedding(query, embeddingOptions);
6648
6817
  const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
@@ -6718,12 +6887,18 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6718
6887
  memories.map((m) => [m.uniqueId, { createdAt: m.createdAt, updatedAt: m.updatedAt }])
6719
6888
  );
6720
6889
  const stampTimestamps = (out) => {
6721
- out.results = out.results.map((r) => {
6890
+ const results2 = out.results.map((r) => {
6722
6891
  const ts = timestampById.get(r.uniqueId);
6723
6892
  return ts ? { ...r, createdAt: ts.createdAt, updatedAt: ts.updatedAt } : r;
6724
6893
  });
6725
- return out;
6894
+ return {
6895
+ results: results2,
6896
+ vaultSize: out.vaultSize,
6897
+ reranked: out.reranked ?? false,
6898
+ hadV2Head: out.hadV2Head ?? false
6899
+ };
6726
6900
  };
6901
+ const rerankStats = { applied: false };
6727
6902
  const useFusion = searchOptions?.useFusion ?? true;
6728
6903
  const tuning = {
6729
6904
  ...searchOptions?.recencyAlpha !== void 0 && { recencyAlpha: searchOptions.recencyAlpha },
@@ -6750,6 +6925,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6750
6925
  query: sq,
6751
6926
  embedding: subEmbeddings[i]
6752
6927
  }));
6928
+ const v2HeadStats = { hadResults: false };
6753
6929
  const composite = await rankComposite(query, queryEmbedding, subQueries, embeddedItems, {
6754
6930
  limit,
6755
6931
  minSimilarity,
@@ -6761,12 +6937,20 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6761
6937
  ...searchOptions.mmr !== void 0 && { mmr: searchOptions.mmr },
6762
6938
  ...tuning,
6763
6939
  ...searchOptions.entityRanking && { entityRanking: searchOptions.entityRanking },
6764
- ...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking }
6940
+ ...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
6941
+ rerankStats,
6942
+ v2HeadStats
6943
+ });
6944
+ return stampTimestamps({
6945
+ results: composite,
6946
+ vaultSize: loaded.length,
6947
+ reranked: rerankStats.applied,
6948
+ hadV2Head: v2HeadStats.hadResults
6765
6949
  });
6766
- return stampTimestamps({ results: composite, vaultSize: loaded.length });
6767
6950
  }
6768
6951
  }
6769
6952
  if (useFusion && searchOptions?.rerank) {
6953
+ const v2HeadStats = { hadResults: false };
6770
6954
  const results2 = await rankFusedVaultMemoriesAsync(query, queryEmbedding, embeddedItems, {
6771
6955
  limit,
6772
6956
  minSimilarity,
@@ -6778,9 +6962,16 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6778
6962
  ...searchOptions.mmr !== void 0 && { mmr: searchOptions.mmr },
6779
6963
  ...tuning,
6780
6964
  ...searchOptions.entityRanking && { entityRanking: searchOptions.entityRanking },
6781
- ...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking }
6965
+ ...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
6966
+ rerankStats,
6967
+ v2HeadStats
6968
+ });
6969
+ return stampTimestamps({
6970
+ results: results2,
6971
+ vaultSize: loaded.length,
6972
+ reranked: rerankStats.applied,
6973
+ hadV2Head: v2HeadStats.hadResults
6782
6974
  });
6783
- return stampTimestamps({ results: results2, vaultSize: loaded.length });
6784
6975
  }
6785
6976
  if (useFusion) {
6786
6977
  const results2 = rankFusedVaultMemories(query, queryEmbedding, embeddedItems, {
@@ -6790,7 +6981,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6790
6981
  ...searchOptions?.entityRanking && { entityRanking: searchOptions.entityRanking },
6791
6982
  ...searchOptions?.temporalRanking && { temporalRanking: searchOptions.temporalRanking }
6792
6983
  });
6793
- return stampTimestamps({ results: results2, vaultSize: loaded.length });
6984
+ return stampTimestamps({ results: results2, vaultSize: loaded.length, hadV2Head: results2.length > 0 });
6794
6985
  }
6795
6986
  const results = rankVaultMemories(query, queryEmbedding, embeddedItems, {
6796
6987
  limit,
@@ -6802,7 +6993,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6802
6993
  supersessionWindow: searchOptions.supersessionWindow
6803
6994
  }
6804
6995
  });
6805
- return stampTimestamps({ results, vaultSize: loaded.length });
6996
+ return stampTimestamps({ results, vaultSize: loaded.length, hadV2Head: results.length > 0 });
6806
6997
  }
6807
6998
  async function searchVaultMemories(query, vaultCtx, embeddingOptions, cache, searchOptions) {
6808
6999
  const { results } = await searchVaultMemoriesWithSize(
@@ -7118,6 +7309,7 @@ __export(index_exports, {
7118
7309
  ConversationMemoryModel: () => ConversationMemory,
7119
7310
  DEFAULT_BACKUP_FOLDER: () => DEFAULT_BACKUP_FOLDER,
7120
7311
  DEFAULT_CACHE_EXPIRATION_MS: () => DEFAULT_CACHE_EXPIRATION_MS,
7312
+ DEFAULT_CHUNK_CACHE_SIZE: () => DEFAULT_CHUNK_CACHE_SIZE,
7121
7313
  DEFAULT_CHUNK_OVERLAP: () => DEFAULT_CHUNK_OVERLAP,
7122
7314
  DEFAULT_CHUNK_SIZE: () => DEFAULT_CHUNK_SIZE,
7123
7315
  DEFAULT_DRIVE_CONVERSATIONS_FOLDER: () => DEFAULT_CONVERSATIONS_FOLDER,
@@ -7149,6 +7341,7 @@ __export(index_exports, {
7149
7341
  R2_DEFAULT_TTL_MS: () => R2_DEFAULT_TTL_MS,
7150
7342
  RECALL_MAX_LIMIT: () => RECALL_MAX_LIMIT,
7151
7343
  RECALL_TOOL_NAME: () => RECALL_TOOL_NAME,
7344
+ RerankerUnavailableError: () => RerankerUnavailableError,
7152
7345
  SDK_SCHEMA_VERSION: () => SDK_SCHEMA_VERSION,
7153
7346
  SERVER_TOOL_DEPENDENCY_SETS: () => SERVER_TOOL_DEPENDENCY_SETS,
7154
7347
  SLIDER_CONFIG: () => SLIDER_CONFIG,
@@ -7207,6 +7400,7 @@ __export(index_exports, {
7207
7400
  conversationMemoryToStored: () => conversationMemoryToStored,
7208
7401
  cosineInt8: () => cosineInt8,
7209
7402
  createAutoExtractor: () => createAutoExtractor,
7403
+ createChunkVectorCache: () => createChunkVectorCache,
7210
7404
  createCryptoPricePreProcessor: () => createCryptoPricePreProcessor,
7211
7405
  createGitHubTools: () => createGitHubTools,
7212
7406
  createMediaBatchOp: () => createMediaBatchOp,
@@ -7362,6 +7556,7 @@ __export(index_exports, {
7362
7556
  isNotionCallback: () => isNotionCallback,
7363
7557
  isOPFSSupported: () => isOPFSSupported,
7364
7558
  isR2UrlExpired: () => isR2UrlExpired,
7559
+ isRerankerAvailable: () => isRerankerAvailable,
7365
7560
  isSupportedFile: () => isSupportedFile,
7366
7561
  isSupportedMediaType: () => isSupportedMediaType,
7367
7562
  linkMemoryEntitiesOp: () => linkMemoryEntitiesOp,
@@ -14811,6 +15006,13 @@ function createAutoExtractor(options) {
14811
15006
  };
14812
15007
  }
14813
15008
 
15009
+ // src/lib/memory/chunkVectorCache.ts
15010
+ init_lruCache();
15011
+ var DEFAULT_CHUNK_CACHE_SIZE = 5e3;
15012
+ function createChunkVectorCache(maxSize = DEFAULT_CHUNK_CACHE_SIZE) {
15013
+ return new LRUCache(maxSize);
15014
+ }
15015
+
14814
15016
  // src/lib/memory/index.ts
14815
15017
  init_recall();
14816
15018
 
@@ -15075,6 +15277,9 @@ function parseAnswer(body, base, parseSchema) {
15075
15277
  };
15076
15278
  }
15077
15279
 
15280
+ // src/lib/memory/index.ts
15281
+ init_reranker();
15282
+
15078
15283
  // src/lib/memory/topicExtract.ts
15079
15284
  init_operations2();
15080
15285
  init_operations3();
@@ -18215,6 +18420,7 @@ function useChatStorage(options) {
18215
18420
  [vaultCtx]
18216
18421
  );
18217
18422
  const vaultEmbeddingCacheRef = (0, import_react5.useRef)(createVaultEmbeddingCache());
18423
+ const chunkVectorCacheRef = (0, import_react5.useRef)(createChunkVectorCache());
18218
18424
  const clientToolEmbeddingsCacheRef = (0, import_react5.useRef)(/* @__PURE__ */ new Map());
18219
18425
  (0, import_react5.useEffect)(() => {
18220
18426
  if (!getToken) return;
@@ -18230,7 +18436,10 @@ function useChatStorage(options) {
18230
18436
  })();
18231
18437
  }, [vaultCtx, getToken, vaultEmbeddingOptions]);
18232
18438
  (0, import_react5.useEffect)(() => {
18233
- return onClearAllEncryptionState(() => vaultEmbeddingCacheRef.current.clear());
18439
+ return onClearAllEncryptionState(() => {
18440
+ vaultEmbeddingCacheRef.current.clear();
18441
+ chunkVectorCacheRef.current.clear();
18442
+ });
18234
18443
  }, []);
18235
18444
  const createMemoryVaultSearchTool2 = (0, import_react5.useCallback)(
18236
18445
  (searchOptions) => {
@@ -18258,6 +18467,7 @@ function useChatStorage(options) {
18258
18467
  storageCtx,
18259
18468
  embeddingOptions: vaultEmbeddingOptions,
18260
18469
  vaultCache: vaultEmbeddingCacheRef.current,
18470
+ chunkCache: chunkVectorCacheRef.current,
18261
18471
  // Graph lane fires when entityCtx is present and the query
18262
18472
  // contains extractable entities. Empty memory_entity (e.g.
18263
18473
  // before any auto-extraction linked entities) is a graceful
@@ -18305,6 +18515,7 @@ function useChatStorage(options) {
18305
18515
  // would embed the raw query (often containing the user's PII).
18306
18516
  embeddingOptions: vaultEmbeddingOptions,
18307
18517
  vaultCache: vaultEmbeddingCacheRef.current,
18518
+ chunkCache: chunkVectorCacheRef.current,
18308
18519
  // Graph lane fires only when entityCtx is present and the query
18309
18520
  // has extractable entities; empty memory_entity is a graceful
18310
18521
  // no-op (falls through to fact + chunk lanes). Mirrors createRecallTool.
@@ -29974,6 +30185,7 @@ function renderAnumaJsx(jsx3) {
29974
30185
  ConversationMemoryModel,
29975
30186
  DEFAULT_BACKUP_FOLDER,
29976
30187
  DEFAULT_CACHE_EXPIRATION_MS,
30188
+ DEFAULT_CHUNK_CACHE_SIZE,
29977
30189
  DEFAULT_CHUNK_OVERLAP,
29978
30190
  DEFAULT_CHUNK_SIZE,
29979
30191
  DEFAULT_DRIVE_CONVERSATIONS_FOLDER,
@@ -30005,6 +30217,7 @@ function renderAnumaJsx(jsx3) {
30005
30217
  R2_DEFAULT_TTL_MS,
30006
30218
  RECALL_MAX_LIMIT,
30007
30219
  RECALL_TOOL_NAME,
30220
+ RerankerUnavailableError,
30008
30221
  SDK_SCHEMA_VERSION,
30009
30222
  SERVER_TOOL_DEPENDENCY_SETS,
30010
30223
  SLIDER_CONFIG,
@@ -30063,6 +30276,7 @@ function renderAnumaJsx(jsx3) {
30063
30276
  conversationMemoryToStored,
30064
30277
  cosineInt8,
30065
30278
  createAutoExtractor,
30279
+ createChunkVectorCache,
30066
30280
  createCryptoPricePreProcessor,
30067
30281
  createGitHubTools,
30068
30282
  createMediaBatchOp,
@@ -30218,6 +30432,7 @@ function renderAnumaJsx(jsx3) {
30218
30432
  isNotionCallback,
30219
30433
  isOPFSSupported,
30220
30434
  isR2UrlExpired,
30435
+ isRerankerAvailable,
30221
30436
  isSupportedFile,
30222
30437
  isSupportedMediaType,
30223
30438
  linkMemoryEntitiesOp,