@anuma/sdk 2.4.0 → 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.
@@ -2543,7 +2543,13 @@ async function readJsonField(model, column, walletAddress) {
2543
2543
  }
2544
2544
  }
2545
2545
  async function searchChunksOp(ctx, queryVector, options) {
2546
- const { limit = 10, minSimilarity = 0.5, conversationId, embeddingModel } = options || {};
2546
+ const {
2547
+ limit = 10,
2548
+ minSimilarity = 0.5,
2549
+ conversationId,
2550
+ embeddingModel,
2551
+ chunkCache
2552
+ } = options || {};
2547
2553
  const activeConversations = await ctx.conversationsCollection.query(import_watermelondb.Q.where("is_deleted", false)).fetch();
2548
2554
  const activeConversationIds = new Set(
2549
2555
  // Use _getRaw for reliable raw column access
@@ -2563,23 +2569,54 @@ async function searchChunksOp(ctx, queryVector, options) {
2563
2569
  continue;
2564
2570
  }
2565
2571
  }
2572
+ const version = Number(message._getRaw("updated_at")) || 0;
2573
+ const cached = chunkCache?.get(message.id);
2574
+ if (cached && cached.version === version) {
2575
+ if (cached.chunks.length > 0) {
2576
+ for (let ci = 0; ci < cached.chunks.length; ci++) {
2577
+ const vec = cached.chunks[ci];
2578
+ if (vec.length === 0) continue;
2579
+ const similarity = cosineSimilarity(queryVector, vec);
2580
+ if (similarity >= minSimilarity) {
2581
+ candidates.push({
2582
+ message,
2583
+ similarity,
2584
+ chunkTextSource: { kind: "chunk-cached", chunkIndex: ci, version }
2585
+ });
2586
+ }
2587
+ }
2588
+ } else if (cached.fallback) {
2589
+ const similarity = cosineSimilarity(queryVector, cached.fallback);
2590
+ if (similarity >= minSimilarity) {
2591
+ candidates.push({ message, similarity, chunkTextSource: { kind: "message" } });
2592
+ }
2593
+ }
2594
+ continue;
2595
+ }
2566
2596
  const chunks = await readJsonField(message, "chunks", ctx.walletAddress);
2567
2597
  if (chunks && chunks.length > 0) {
2568
- for (const chunk of chunks) {
2569
- if (!chunk.vector || chunk.vector.length === 0) continue;
2570
- const similarity = cosineSimilarity(queryVector, chunk.vector);
2598
+ const vectors = chunks.map(
2599
+ (chunk) => chunk.vector && chunk.vector.length > 0 ? Float32Array.from(chunk.vector) : new Float32Array(0)
2600
+ );
2601
+ chunkCache?.set(message.id, { version, chunks: vectors });
2602
+ for (let ci = 0; ci < chunks.length; ci++) {
2603
+ const vec = vectors[ci];
2604
+ if (vec.length === 0) continue;
2605
+ const similarity = cosineSimilarity(queryVector, vec);
2571
2606
  if (similarity >= minSimilarity) {
2572
2607
  candidates.push({
2573
2608
  message,
2574
2609
  similarity,
2575
- chunkTextSource: { kind: "chunk", text: chunk.text }
2610
+ chunkTextSource: { kind: "chunk", text: chunks[ci].text }
2576
2611
  });
2577
2612
  }
2578
2613
  }
2579
2614
  } else {
2580
2615
  const messageVector = await readJsonField(message, "vector", ctx.walletAddress);
2581
2616
  if (!messageVector || messageVector.length === 0) continue;
2582
- const similarity = cosineSimilarity(queryVector, messageVector);
2617
+ const fallback = Float32Array.from(messageVector);
2618
+ chunkCache?.set(message.id, { version, chunks: [], fallback });
2619
+ const similarity = cosineSimilarity(queryVector, fallback);
2583
2620
  if (similarity >= minSimilarity) {
2584
2621
  candidates.push({ message, similarity, chunkTextSource: { kind: "message" } });
2585
2622
  }
@@ -2606,9 +2643,31 @@ async function searchChunksOp(ctx, queryVector, options) {
2606
2643
  })
2607
2644
  )
2608
2645
  );
2646
+ const chunkStateByMsgId = /* @__PURE__ */ new Map();
2647
+ const needsChunkText = /* @__PURE__ */ new Set();
2648
+ for (const c of topK) {
2649
+ if (c.chunkTextSource.kind === "chunk-cached") needsChunkText.add(c.message.id);
2650
+ }
2651
+ await Promise.all(
2652
+ Array.from(needsChunkText, async (id) => {
2653
+ const m = uniqueMessages.get(id);
2654
+ const parsed = await readJsonField(m, "chunks", ctx.walletAddress);
2655
+ const version = Number(m._getRaw("updated_at")) || 0;
2656
+ if (parsed) chunkStateByMsgId.set(id, { version, chunks: parsed });
2657
+ })
2658
+ );
2609
2659
  return topK.map(({ message, similarity, chunkTextSource }) => {
2610
2660
  const stored = { ...storedById.get(message.id) };
2611
- const chunkText2 = chunkTextSource.kind === "chunk" ? chunkTextSource.text : stored.content;
2661
+ let chunkText2;
2662
+ if (chunkTextSource.kind === "chunk") {
2663
+ chunkText2 = chunkTextSource.text;
2664
+ } else if (chunkTextSource.kind === "chunk-cached") {
2665
+ const state = chunkStateByMsgId.get(message.id);
2666
+ const chunk = state && state.version === chunkTextSource.version ? state.chunks[chunkTextSource.chunkIndex] : void 0;
2667
+ chunkText2 = chunk?.text ?? stored.content;
2668
+ } else {
2669
+ chunkText2 = stored.content;
2670
+ }
2612
2671
  return { chunkText: chunkText2, message: stored, similarity };
2613
2672
  });
2614
2673
  }
@@ -4840,9 +4899,9 @@ function recencyMultiplier(updatedAt, opts = {}) {
4840
4899
  const updatedMs = updatedAt.getTime();
4841
4900
  if (!Number.isFinite(updatedMs)) return noDate;
4842
4901
  const now = opts.now ?? /* @__PURE__ */ new Date();
4843
- const nowMs = now.getTime();
4844
- if (!Number.isFinite(nowMs)) return noDate;
4845
- const ageDays = Math.max(0, (nowMs - updatedMs) / DAY_MS);
4902
+ const nowMs2 = now.getTime();
4903
+ if (!Number.isFinite(nowMs2)) return noDate;
4904
+ const ageDays = Math.max(0, (nowMs2 - updatedMs) / DAY_MS);
4846
4905
  const perYearDecay = opts.perYearDecay ?? DEFAULT_PER_YEAR_DECAY;
4847
4906
  const floor = opts.floor ?? DEFAULT_FLOOR;
4848
4907
  const decay = perYearDecay * (ageDays / 365);
@@ -4860,14 +4919,42 @@ var init_recency = __esm({
4860
4919
  });
4861
4920
 
4862
4921
  // src/lib/memory/reranker.ts
4922
+ function isRerankerAvailable() {
4923
+ return available;
4924
+ }
4925
+ function isModuleMissing(err) {
4926
+ let e = err;
4927
+ for (let depth = 0; depth < 5 && e !== null && e !== void 0; depth++) {
4928
+ const code = e.code;
4929
+ if (code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND") return true;
4930
+ if (e instanceof Error && /cannot find (module|package)|failed to resolve|unable to resolve module|requiring unknown module/i.test(
4931
+ e.message
4932
+ )) {
4933
+ return true;
4934
+ }
4935
+ e = e.cause;
4936
+ }
4937
+ return false;
4938
+ }
4863
4939
  async function getModel() {
4940
+ if (available === false) throw new RerankerUnavailableError(void 0);
4864
4941
  if (!modelPromise) {
4865
4942
  const load = (async () => {
4866
- const transformers = await import("@huggingface/transformers");
4943
+ let transformers;
4944
+ try {
4945
+ transformers = await import("@huggingface/transformers");
4946
+ } catch (err) {
4947
+ if (isModuleMissing(err)) {
4948
+ available = false;
4949
+ throw new RerankerUnavailableError(err);
4950
+ }
4951
+ throw err;
4952
+ }
4867
4953
  const [tokenizer, model] = await Promise.all([
4868
4954
  transformers.AutoTokenizer.from_pretrained(MODEL_ID),
4869
4955
  transformers.AutoModelForSequenceClassification.from_pretrained(MODEL_ID)
4870
4956
  ]);
4957
+ available = true;
4871
4958
  return { tokenizer, model };
4872
4959
  })();
4873
4960
  modelPromise = load;
@@ -4909,11 +4996,19 @@ async function rerankPairs(query, items) {
4909
4996
  }
4910
4997
  return items.map((item, i) => ({ id: item.id, content: item.content, score: scores[i] })).sort((a, b) => b.score - a.score);
4911
4998
  }
4912
- var MODEL_ID, modelPromise;
4999
+ var MODEL_ID, RerankerUnavailableError, available, modelPromise;
4913
5000
  var init_reranker = __esm({
4914
5001
  "src/lib/memory/reranker.ts"() {
4915
5002
  "use strict";
4916
5003
  MODEL_ID = "Xenova/ms-marco-MiniLM-L-6-v2";
5004
+ RerankerUnavailableError = class extends Error {
5005
+ constructor(reason) {
5006
+ super("cross-encoder reranker unavailable (@huggingface/transformers not installed)");
5007
+ this.name = "RerankerUnavailableError";
5008
+ this.reason = reason;
5009
+ }
5010
+ };
5011
+ available = void 0;
4917
5012
  modelPromise = null;
4918
5013
  }
4919
5014
  });
@@ -5582,22 +5677,67 @@ async function recall(query, ctx, options = {}) {
5582
5677
  const flags = flagsForBudget(requestedBudget);
5583
5678
  const decomposeAvailable = flags.decompose && !!options.decomposeOptions;
5584
5679
  const usedBudget = requestedBudget === "high" && !decomposeAvailable ? "mid" : requestedBudget;
5680
+ const t0 = nowMs();
5681
+ let prepMs = 0;
5682
+ let factLaneMs = 0;
5683
+ let chunkLaneMs = 0;
5684
+ let fuseMs = 0;
5685
+ const factResults = [];
5686
+ const chunkResults = [];
5687
+ let vaultSize;
5688
+ let didRerank = false;
5689
+ let hadV2Head = false;
5690
+ const emitDiagnostics = (candidateCount) => {
5691
+ const cb = options.onDiagnostics;
5692
+ if (!cb) return;
5693
+ const degraded = [];
5694
+ if (flags.rerank && factResults.length > 0 && hadV2Head && !didRerank) {
5695
+ degraded.push("rerank-unavailable");
5696
+ }
5697
+ if (flags.decompose && !decomposeAvailable) degraded.push("decompose-unavailable");
5698
+ const diagnostics = {
5699
+ usedBudget,
5700
+ reranked: didRerank,
5701
+ candidateCount,
5702
+ ...vaultSize !== void 0 && { vaultSize },
5703
+ factCount: factResults.length,
5704
+ chunkCount: chunkResults.length,
5705
+ timings: {
5706
+ total: nowMs() - t0,
5707
+ prep: prepMs,
5708
+ factLane: factLaneMs,
5709
+ chunkLane: chunkLaneMs,
5710
+ fuse: fuseMs
5711
+ },
5712
+ degraded
5713
+ };
5714
+ try {
5715
+ cb(diagnostics);
5716
+ } catch {
5717
+ }
5718
+ };
5585
5719
  if (!query || typeof query !== "string" || query.trim().length === 0) {
5720
+ emitDiagnostics(0);
5586
5721
  return { memories: [], usedBudget, reranked: false, candidateCount: 0 };
5587
5722
  }
5588
5723
  const needsChunkEmbedding = types.includes("chunk") && ctx.storageCtx;
5589
5724
  const wantsTemporal = types.includes("fact") && ctx.vaultCtx;
5725
+ const prepStart = nowMs();
5590
5726
  const [queryEmbedding, entityRanking, temporalRanking] = await Promise.all([
5591
5727
  needsChunkEmbedding ? generateEmbedding(query, ctx.embeddingOptions) : Promise.resolve(void 0),
5592
5728
  buildGraphLaneRanking(query, ctx),
5593
5729
  wantsTemporal ? buildTemporalLaneRanking(query, ctx.vaultCtx, options.now) : Promise.resolve([])
5594
5730
  ]);
5595
- const factResults = [];
5596
- const chunkResults = [];
5597
- let vaultSize;
5731
+ prepMs = nowMs() - prepStart;
5598
5732
  if (types.includes("fact") && ctx.vaultCtx && ctx.vaultCache) {
5733
+ const factStart = nowMs();
5599
5734
  const vaultMinScore = options.minScore ?? DEFAULT_FACT_MIN_SCORE;
5600
- const { results, vaultSize: size } = await searchVaultMemoriesWithSize(
5735
+ const {
5736
+ results,
5737
+ vaultSize: size,
5738
+ reranked,
5739
+ hadV2Head: v2Head
5740
+ } = await searchVaultMemoriesWithSize(
5601
5741
  query,
5602
5742
  ctx.vaultCtx,
5603
5743
  ctx.embeddingOptions,
@@ -5648,14 +5788,19 @@ async function recall(query, ctx, options = {}) {
5648
5788
  )
5649
5789
  );
5650
5790
  vaultSize = size;
5791
+ didRerank = reranked;
5792
+ hadV2Head = v2Head;
5793
+ factLaneMs = nowMs() - factStart;
5651
5794
  }
5652
5795
  if (types.includes("chunk") && ctx.storageCtx && queryEmbedding) {
5796
+ const chunkStart = nowMs();
5653
5797
  const chunkMinScore = options.minScore ?? DEFAULT_CHUNK_MIN_SCORE;
5654
5798
  const results = await searchChunksOp(ctx.storageCtx, queryEmbedding, {
5655
5799
  limit: types.includes("fact") ? Math.max(limit * 2, 16) : limit,
5656
5800
  minSimilarity: chunkMinScore,
5657
5801
  embeddingModel: ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL,
5658
- ...options.conversationId && { conversationId: options.conversationId }
5802
+ ...options.conversationId && { conversationId: options.conversationId },
5803
+ ...ctx.chunkCache && { chunkCache: ctx.chunkCache }
5659
5804
  });
5660
5805
  chunkResults.push(
5661
5806
  ...dedupeBy(
@@ -5665,18 +5810,23 @@ async function recall(query, ctx, options = {}) {
5665
5810
  (r) => r.chunkText.trim()
5666
5811
  )
5667
5812
  );
5813
+ chunkLaneMs = nowMs() - chunkStart;
5668
5814
  }
5815
+ const fuseStart = nowMs();
5669
5816
  if (types.length === 1 || factResults.length === 0 || chunkResults.length === 0) {
5670
5817
  const memories2 = [
5671
5818
  ...factResults.map(toFactMemory),
5672
5819
  ...chunkResults.map(toChunkMemory)
5673
5820
  ];
5674
5821
  memories2.sort((a, b) => b.score - a.score);
5822
+ const candidateCount = factResults.length + chunkResults.length;
5823
+ fuseMs = nowMs() - fuseStart;
5824
+ emitDiagnostics(candidateCount);
5675
5825
  return {
5676
5826
  memories: memories2.slice(0, limit),
5677
5827
  usedBudget,
5678
- reranked: flags.rerank,
5679
- candidateCount: factResults.length + chunkResults.length,
5828
+ reranked: didRerank,
5829
+ candidateCount,
5680
5830
  ...vaultSize !== void 0 && { vaultSize }
5681
5831
  };
5682
5832
  }
@@ -5725,10 +5875,12 @@ async function recall(query, ctx, options = {}) {
5725
5875
  suppressed = next;
5726
5876
  memories = selectWith(suppressed);
5727
5877
  }
5878
+ fuseMs = nowMs() - fuseStart;
5879
+ emitDiagnostics(byId.size);
5728
5880
  return {
5729
5881
  memories,
5730
5882
  usedBudget,
5731
- reranked: flags.rerank,
5883
+ reranked: didRerank,
5732
5884
  candidateCount: byId.size,
5733
5885
  ...vaultSize !== void 0 && { vaultSize }
5734
5886
  };
@@ -5792,7 +5944,7 @@ function toChunkMemory(r) {
5792
5944
  updatedAt: r.message.createdAt
5793
5945
  };
5794
5946
  }
5795
- var DEFAULT_LIMIT, DEFAULT_BUDGET, DEFAULT_FACT_MIN_SCORE, DEFAULT_CHUNK_MIN_SCORE;
5947
+ var DEFAULT_LIMIT, DEFAULT_BUDGET, DEFAULT_FACT_MIN_SCORE, nowMs, DEFAULT_CHUNK_MIN_SCORE;
5796
5948
  var init_recall = __esm({
5797
5949
  "src/lib/memory/recall.ts"() {
5798
5950
  "use strict";
@@ -5808,6 +5960,7 @@ var init_recall = __esm({
5808
5960
  DEFAULT_LIMIT = 8;
5809
5961
  DEFAULT_BUDGET = "low";
5810
5962
  DEFAULT_FACT_MIN_SCORE = 0.1;
5963
+ nowMs = () => typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
5811
5964
  DEFAULT_CHUNK_MIN_SCORE = 0.5;
5812
5965
  }
5813
5966
  });
@@ -6007,6 +6160,9 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
6007
6160
  bm25AdmissionDivisor: options?.bm25AdmissionDivisor,
6008
6161
  rrfK: options?.rrfK
6009
6162
  });
6163
+ if (options?.v2HeadStats) {
6164
+ options.v2HeadStats.hadResults = v2Ranked.length > 0;
6165
+ }
6010
6166
  let combined;
6011
6167
  let tailSlice = [];
6012
6168
  if (options?.rerank) {
@@ -6027,8 +6183,13 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
6027
6183
  return { ...r, similarity: v2 * (1 + ceWeight * ce) };
6028
6184
  });
6029
6185
  combined.sort((a, b) => b.similarity - a.similarity);
6186
+ if (headSlice.length > 0 && options.rerankStats) options.rerankStats.applied = true;
6030
6187
  } catch (err) {
6031
- getLogger().warn("[memory/search] cross-encoder rerank failed; using V2 ranking", err);
6188
+ if (err instanceof RerankerUnavailableError) {
6189
+ getLogger().debug("[memory/search] cross-encoder unavailable; using V2 ranking");
6190
+ } else {
6191
+ getLogger().warn("[memory/search] cross-encoder rerank failed; using V2 ranking", err);
6192
+ }
6032
6193
  combined = v2Ranked;
6033
6194
  }
6034
6195
  } else {
@@ -6162,6 +6323,9 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
6162
6323
  (r) => r !== null
6163
6324
  );
6164
6325
  combined.sort((a, b) => b.similarity - a.similarity);
6326
+ if (options?.v2HeadStats) {
6327
+ options.v2HeadStats.hadResults = combined.length > 0;
6328
+ }
6165
6329
  if (options?.includeUnrankedTail) {
6166
6330
  const fusedIds = new Set(combined.map((r) => r.uniqueId));
6167
6331
  for (const item of items) {
@@ -6197,11 +6361,16 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
6197
6361
  }));
6198
6362
  head.sort((a, b) => b.similarity - a.similarity);
6199
6363
  combined = [...head, ...tailSlice];
6364
+ if (headSlice.length > 0 && options.rerankStats) options.rerankStats.applied = true;
6200
6365
  } catch (err) {
6201
- getLogger().warn(
6202
- "[memory/search] composite cross-encoder rerank failed; using fused ranking",
6203
- err
6204
- );
6366
+ if (err instanceof RerankerUnavailableError) {
6367
+ getLogger().debug("[memory/search] cross-encoder unavailable; using fused ranking");
6368
+ } else {
6369
+ getLogger().warn(
6370
+ "[memory/search] composite cross-encoder rerank failed; using fused ranking",
6371
+ err
6372
+ );
6373
+ }
6205
6374
  }
6206
6375
  }
6207
6376
  if (options?.mmr) {
@@ -6293,7 +6462,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6293
6462
  const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
6294
6463
  const scopes = searchOptions?.scopes;
6295
6464
  if (!query || typeof query !== "string") {
6296
- return { results: [], vaultSize: 0 };
6465
+ return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
6297
6466
  }
6298
6467
  const folderId = searchOptions?.folderId;
6299
6468
  const queryOpts = {};
@@ -6310,7 +6479,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6310
6479
  );
6311
6480
  }
6312
6481
  if (memories.length === 0) {
6313
- return { results: [], vaultSize: loaded.length };
6482
+ return { results: [], vaultSize: loaded.length, reranked: false, hadV2Head: false };
6314
6483
  }
6315
6484
  const queryEmbedding = await generateEmbedding(query, embeddingOptions);
6316
6485
  const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
@@ -6386,12 +6555,18 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6386
6555
  memories.map((m) => [m.uniqueId, { createdAt: m.createdAt, updatedAt: m.updatedAt }])
6387
6556
  );
6388
6557
  const stampTimestamps = (out) => {
6389
- out.results = out.results.map((r) => {
6558
+ const results2 = out.results.map((r) => {
6390
6559
  const ts = timestampById.get(r.uniqueId);
6391
6560
  return ts ? { ...r, createdAt: ts.createdAt, updatedAt: ts.updatedAt } : r;
6392
6561
  });
6393
- return out;
6562
+ return {
6563
+ results: results2,
6564
+ vaultSize: out.vaultSize,
6565
+ reranked: out.reranked ?? false,
6566
+ hadV2Head: out.hadV2Head ?? false
6567
+ };
6394
6568
  };
6569
+ const rerankStats = { applied: false };
6395
6570
  const useFusion = searchOptions?.useFusion ?? true;
6396
6571
  const tuning = {
6397
6572
  ...searchOptions?.recencyAlpha !== void 0 && { recencyAlpha: searchOptions.recencyAlpha },
@@ -6418,6 +6593,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6418
6593
  query: sq,
6419
6594
  embedding: subEmbeddings[i]
6420
6595
  }));
6596
+ const v2HeadStats = { hadResults: false };
6421
6597
  const composite = await rankComposite(query, queryEmbedding, subQueries, embeddedItems, {
6422
6598
  limit,
6423
6599
  minSimilarity,
@@ -6429,12 +6605,20 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6429
6605
  ...searchOptions.mmr !== void 0 && { mmr: searchOptions.mmr },
6430
6606
  ...tuning,
6431
6607
  ...searchOptions.entityRanking && { entityRanking: searchOptions.entityRanking },
6432
- ...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking }
6608
+ ...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
6609
+ rerankStats,
6610
+ v2HeadStats
6611
+ });
6612
+ return stampTimestamps({
6613
+ results: composite,
6614
+ vaultSize: loaded.length,
6615
+ reranked: rerankStats.applied,
6616
+ hadV2Head: v2HeadStats.hadResults
6433
6617
  });
6434
- return stampTimestamps({ results: composite, vaultSize: loaded.length });
6435
6618
  }
6436
6619
  }
6437
6620
  if (useFusion && searchOptions?.rerank) {
6621
+ const v2HeadStats = { hadResults: false };
6438
6622
  const results2 = await rankFusedVaultMemoriesAsync(query, queryEmbedding, embeddedItems, {
6439
6623
  limit,
6440
6624
  minSimilarity,
@@ -6446,9 +6630,16 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6446
6630
  ...searchOptions.mmr !== void 0 && { mmr: searchOptions.mmr },
6447
6631
  ...tuning,
6448
6632
  ...searchOptions.entityRanking && { entityRanking: searchOptions.entityRanking },
6449
- ...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking }
6633
+ ...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
6634
+ rerankStats,
6635
+ v2HeadStats
6636
+ });
6637
+ return stampTimestamps({
6638
+ results: results2,
6639
+ vaultSize: loaded.length,
6640
+ reranked: rerankStats.applied,
6641
+ hadV2Head: v2HeadStats.hadResults
6450
6642
  });
6451
- return stampTimestamps({ results: results2, vaultSize: loaded.length });
6452
6643
  }
6453
6644
  if (useFusion) {
6454
6645
  const results2 = rankFusedVaultMemories(query, queryEmbedding, embeddedItems, {
@@ -6458,7 +6649,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6458
6649
  ...searchOptions?.entityRanking && { entityRanking: searchOptions.entityRanking },
6459
6650
  ...searchOptions?.temporalRanking && { temporalRanking: searchOptions.temporalRanking }
6460
6651
  });
6461
- return stampTimestamps({ results: results2, vaultSize: loaded.length });
6652
+ return stampTimestamps({ results: results2, vaultSize: loaded.length, hadV2Head: results2.length > 0 });
6462
6653
  }
6463
6654
  const results = rankVaultMemories(query, queryEmbedding, embeddedItems, {
6464
6655
  limit,
@@ -6470,7 +6661,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
6470
6661
  supersessionWindow: searchOptions.supersessionWindow
6471
6662
  }
6472
6663
  });
6473
- return stampTimestamps({ results, vaultSize: loaded.length });
6664
+ return stampTimestamps({ results, vaultSize: loaded.length, hadV2Head: results.length > 0 });
6474
6665
  }
6475
6666
  async function searchVaultMemories(query, vaultCtx, embeddingOptions, cache, searchOptions) {
6476
6667
  const { results } = await searchVaultMemoriesWithSize(
@@ -6767,6 +6958,7 @@ __export(index_exports, {
6767
6958
  ChatMessage: () => Message,
6768
6959
  ConversationMemoryModel: () => ConversationMemory,
6769
6960
  DEFAULT_CACHE_EXPIRATION_MS: () => DEFAULT_CACHE_EXPIRATION_MS,
6961
+ DEFAULT_CHUNK_CACHE_SIZE: () => DEFAULT_CHUNK_CACHE_SIZE,
6770
6962
  DEFAULT_CHUNK_OVERLAP: () => DEFAULT_CHUNK_OVERLAP,
6771
6963
  DEFAULT_CHUNK_SIZE: () => DEFAULT_CHUNK_SIZE,
6772
6964
  DEFAULT_MIN_CHUNK_SIZE: () => DEFAULT_MIN_CHUNK_SIZE,
@@ -6780,6 +6972,7 @@ __export(index_exports, {
6780
6972
  QueueManager: () => QueueManager,
6781
6973
  RECALL_MAX_LIMIT: () => RECALL_MAX_LIMIT,
6782
6974
  RECALL_TOOL_NAME: () => RECALL_TOOL_NAME,
6975
+ RerankerUnavailableError: () => RerankerUnavailableError,
6783
6976
  SDK_SCHEMA_VERSION: () => SDK_SCHEMA_VERSION,
6784
6977
  STREAM_RESUMABLE_HEADER: () => STREAM_RESUMABLE_HEADER,
6785
6978
  StoredVaultFolderModel: () => VaultFolder,
@@ -6812,6 +7005,7 @@ __export(index_exports, {
6812
7005
  conversationMemoryToStored: () => conversationMemoryToStored,
6813
7006
  cosineInt8: () => cosineInt8,
6814
7007
  createAutoExtractor: () => createAutoExtractor,
7008
+ createChunkVectorCache: () => createChunkVectorCache,
6815
7009
  createCryptoPricePreProcessor: () => createCryptoPricePreProcessor,
6816
7010
  createMemoryEngineTool: () => createMemoryEngineTool,
6817
7011
  createMemoryVaultSearchTool: () => createMemoryVaultSearchTool,
@@ -6861,6 +7055,7 @@ __export(index_exports, {
6861
7055
  getVaultMemoryOp: () => getVaultMemoryOp,
6862
7056
  hasEncryptionKey: () => hasEncryptionKey,
6863
7057
  isPiiRedactor: () => isPiiRedactor,
7058
+ isRerankerAvailable: () => isRerankerAvailable,
6864
7059
  moveMemoriesToFolderOp: () => moveMemoriesToFolderOp,
6865
7060
  noopLogger: () => noopLogger,
6866
7061
  onKeyAvailable: () => onKeyAvailable,
@@ -13460,6 +13655,13 @@ function createAutoExtractor(options) {
13460
13655
  };
13461
13656
  }
13462
13657
 
13658
+ // src/lib/memory/chunkVectorCache.ts
13659
+ init_lruCache();
13660
+ var DEFAULT_CHUNK_CACHE_SIZE = 5e3;
13661
+ function createChunkVectorCache(maxSize = DEFAULT_CHUNK_CACHE_SIZE) {
13662
+ return new LRUCache(maxSize);
13663
+ }
13664
+
13463
13665
  // src/lib/memory/index.ts
13464
13666
  init_recall();
13465
13667
 
@@ -13724,6 +13926,9 @@ function parseAnswer(body, base, parseSchema) {
13724
13926
  };
13725
13927
  }
13726
13928
 
13929
+ // src/lib/memory/index.ts
13930
+ init_reranker();
13931
+
13727
13932
  // src/lib/memory/topicExtract.ts
13728
13933
  init_operations2();
13729
13934
  init_operations3();
@@ -15105,6 +15310,13 @@ function useChatStorage(options) {
15105
15310
  [vaultCtx]
15106
15311
  );
15107
15312
  const vaultEmbeddingCacheRef = (0, import_react4.useRef)(createVaultEmbeddingCache());
15313
+ const chunkVectorCacheRef = (0, import_react4.useRef)(createChunkVectorCache());
15314
+ (0, import_react4.useEffect)(() => {
15315
+ return onClearAllEncryptionState(() => {
15316
+ vaultEmbeddingCacheRef.current.clear();
15317
+ chunkVectorCacheRef.current.clear();
15318
+ });
15319
+ }, []);
15108
15320
  const createRecallTool2 = (0, import_react4.useCallback)(
15109
15321
  (toolOptions, callbacks) => {
15110
15322
  if (!getToken) {
@@ -15121,7 +15333,8 @@ function useChatStorage(options) {
15121
15333
  model: embeddingModel,
15122
15334
  maskInput: maskEmbeddingInput
15123
15335
  },
15124
- vaultCache: vaultEmbeddingCacheRef.current
15336
+ vaultCache: vaultEmbeddingCacheRef.current,
15337
+ chunkCache: chunkVectorCacheRef.current
15125
15338
  // entityCtx is intentionally omitted on Expo for now — the
15126
15339
  // W5 graph lane is a no-op without it (recall falls through
15127
15340
  // to fact + chunk lanes). Wire it up when the Expo client
@@ -15163,7 +15376,8 @@ function useChatStorage(options) {
15163
15376
  model: embeddingModel,
15164
15377
  maskInput: maskEmbeddingInput
15165
15378
  },
15166
- vaultCache: vaultEmbeddingCacheRef.current
15379
+ vaultCache: vaultEmbeddingCacheRef.current,
15380
+ chunkCache: chunkVectorCacheRef.current
15167
15381
  },
15168
15382
  resolvedOptions
15169
15383
  );
@@ -18490,6 +18704,7 @@ function createNotionTools(getAccessToken, requestNotionAccess) {
18490
18704
  ChatMessage,
18491
18705
  ConversationMemoryModel,
18492
18706
  DEFAULT_CACHE_EXPIRATION_MS,
18707
+ DEFAULT_CHUNK_CACHE_SIZE,
18493
18708
  DEFAULT_CHUNK_OVERLAP,
18494
18709
  DEFAULT_CHUNK_SIZE,
18495
18710
  DEFAULT_MIN_CHUNK_SIZE,
@@ -18503,6 +18718,7 @@ function createNotionTools(getAccessToken, requestNotionAccess) {
18503
18718
  QueueManager,
18504
18719
  RECALL_MAX_LIMIT,
18505
18720
  RECALL_TOOL_NAME,
18721
+ RerankerUnavailableError,
18506
18722
  SDK_SCHEMA_VERSION,
18507
18723
  STREAM_RESUMABLE_HEADER,
18508
18724
  StoredVaultFolderModel,
@@ -18535,6 +18751,7 @@ function createNotionTools(getAccessToken, requestNotionAccess) {
18535
18751
  conversationMemoryToStored,
18536
18752
  cosineInt8,
18537
18753
  createAutoExtractor,
18754
+ createChunkVectorCache,
18538
18755
  createCryptoPricePreProcessor,
18539
18756
  createMemoryEngineTool,
18540
18757
  createMemoryVaultSearchTool,
@@ -18584,6 +18801,7 @@ function createNotionTools(getAccessToken, requestNotionAccess) {
18584
18801
  getVaultMemoryOp,
18585
18802
  hasEncryptionKey,
18586
18803
  isPiiRedactor,
18804
+ isRerankerAvailable,
18587
18805
  moveMemoriesToFolderOp,
18588
18806
  noopLogger,
18589
18807
  onKeyAvailable,