@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.
@@ -15640,7 +15640,13 @@ async function searchMessagesOp(ctx, queryVector, options) {
15640
15640
  );
15641
15641
  }
15642
15642
  async function searchChunksOp(ctx, queryVector, options) {
15643
- const { limit = 10, minSimilarity = 0.5, conversationId, embeddingModel } = options || {};
15643
+ const {
15644
+ limit = 10,
15645
+ minSimilarity = 0.5,
15646
+ conversationId,
15647
+ embeddingModel,
15648
+ chunkCache
15649
+ } = options || {};
15644
15650
  const activeConversations = await ctx.conversationsCollection.query(import_watermelondb.Q.where("is_deleted", false)).fetch();
15645
15651
  const activeConversationIds = new Set(
15646
15652
  // Use _getRaw for reliable raw column access
@@ -15660,23 +15666,54 @@ async function searchChunksOp(ctx, queryVector, options) {
15660
15666
  continue;
15661
15667
  }
15662
15668
  }
15669
+ const version = Number(message._getRaw("updated_at")) || 0;
15670
+ const cached = chunkCache?.get(message.id);
15671
+ if (cached && cached.version === version) {
15672
+ if (cached.chunks.length > 0) {
15673
+ for (let ci = 0; ci < cached.chunks.length; ci++) {
15674
+ const vec = cached.chunks[ci];
15675
+ if (vec.length === 0) continue;
15676
+ const similarity = cosineSimilarity(queryVector, vec);
15677
+ if (similarity >= minSimilarity) {
15678
+ candidates.push({
15679
+ message,
15680
+ similarity,
15681
+ chunkTextSource: { kind: "chunk-cached", chunkIndex: ci, version }
15682
+ });
15683
+ }
15684
+ }
15685
+ } else if (cached.fallback) {
15686
+ const similarity = cosineSimilarity(queryVector, cached.fallback);
15687
+ if (similarity >= minSimilarity) {
15688
+ candidates.push({ message, similarity, chunkTextSource: { kind: "message" } });
15689
+ }
15690
+ }
15691
+ continue;
15692
+ }
15663
15693
  const chunks = await readJsonField(message, "chunks", ctx.walletAddress);
15664
15694
  if (chunks && chunks.length > 0) {
15665
- for (const chunk of chunks) {
15666
- if (!chunk.vector || chunk.vector.length === 0) continue;
15667
- const similarity = cosineSimilarity(queryVector, chunk.vector);
15695
+ const vectors = chunks.map(
15696
+ (chunk) => chunk.vector && chunk.vector.length > 0 ? Float32Array.from(chunk.vector) : new Float32Array(0)
15697
+ );
15698
+ chunkCache?.set(message.id, { version, chunks: vectors });
15699
+ for (let ci = 0; ci < chunks.length; ci++) {
15700
+ const vec = vectors[ci];
15701
+ if (vec.length === 0) continue;
15702
+ const similarity = cosineSimilarity(queryVector, vec);
15668
15703
  if (similarity >= minSimilarity) {
15669
15704
  candidates.push({
15670
15705
  message,
15671
15706
  similarity,
15672
- chunkTextSource: { kind: "chunk", text: chunk.text }
15707
+ chunkTextSource: { kind: "chunk", text: chunks[ci].text }
15673
15708
  });
15674
15709
  }
15675
15710
  }
15676
15711
  } else {
15677
15712
  const messageVector = await readJsonField(message, "vector", ctx.walletAddress);
15678
15713
  if (!messageVector || messageVector.length === 0) continue;
15679
- const similarity = cosineSimilarity(queryVector, messageVector);
15714
+ const fallback = Float32Array.from(messageVector);
15715
+ chunkCache?.set(message.id, { version, chunks: [], fallback });
15716
+ const similarity = cosineSimilarity(queryVector, fallback);
15680
15717
  if (similarity >= minSimilarity) {
15681
15718
  candidates.push({ message, similarity, chunkTextSource: { kind: "message" } });
15682
15719
  }
@@ -15703,9 +15740,31 @@ async function searchChunksOp(ctx, queryVector, options) {
15703
15740
  })
15704
15741
  )
15705
15742
  );
15743
+ const chunkStateByMsgId = /* @__PURE__ */ new Map();
15744
+ const needsChunkText = /* @__PURE__ */ new Set();
15745
+ for (const c of topK) {
15746
+ if (c.chunkTextSource.kind === "chunk-cached") needsChunkText.add(c.message.id);
15747
+ }
15748
+ await Promise.all(
15749
+ Array.from(needsChunkText, async (id) => {
15750
+ const m = uniqueMessages.get(id);
15751
+ const parsed = await readJsonField(m, "chunks", ctx.walletAddress);
15752
+ const version = Number(m._getRaw("updated_at")) || 0;
15753
+ if (parsed) chunkStateByMsgId.set(id, { version, chunks: parsed });
15754
+ })
15755
+ );
15706
15756
  return topK.map(({ message, similarity, chunkTextSource }) => {
15707
15757
  const stored = { ...storedById.get(message.id) };
15708
- const chunkText2 = chunkTextSource.kind === "chunk" ? chunkTextSource.text : stored.content;
15758
+ let chunkText2;
15759
+ if (chunkTextSource.kind === "chunk") {
15760
+ chunkText2 = chunkTextSource.text;
15761
+ } else if (chunkTextSource.kind === "chunk-cached") {
15762
+ const state = chunkStateByMsgId.get(message.id);
15763
+ const chunk = state && state.version === chunkTextSource.version ? state.chunks[chunkTextSource.chunkIndex] : void 0;
15764
+ chunkText2 = chunk?.text ?? stored.content;
15765
+ } else {
15766
+ chunkText2 = stored.content;
15767
+ }
15709
15768
  return { chunkText: chunkText2, message: stored, similarity };
15710
15769
  });
15711
15770
  }
@@ -17843,9 +17902,9 @@ function recencyMultiplier(updatedAt, opts = {}) {
17843
17902
  const updatedMs = updatedAt.getTime();
17844
17903
  if (!Number.isFinite(updatedMs)) return noDate;
17845
17904
  const now = opts.now ?? /* @__PURE__ */ new Date();
17846
- const nowMs = now.getTime();
17847
- if (!Number.isFinite(nowMs)) return noDate;
17848
- const ageDays = Math.max(0, (nowMs - updatedMs) / DAY_MS);
17905
+ const nowMs2 = now.getTime();
17906
+ if (!Number.isFinite(nowMs2)) return noDate;
17907
+ const ageDays = Math.max(0, (nowMs2 - updatedMs) / DAY_MS);
17849
17908
  const perYearDecay = opts.perYearDecay ?? DEFAULT_PER_YEAR_DECAY;
17850
17909
  const floor = opts.floor ?? DEFAULT_FLOOR;
17851
17910
  const decay = perYearDecay * (ageDays / 365);
@@ -17854,15 +17913,51 @@ function recencyMultiplier(updatedAt, opts = {}) {
17854
17913
 
17855
17914
  // src/lib/memory/reranker.ts
17856
17915
  var MODEL_ID = "Xenova/ms-marco-MiniLM-L-6-v2";
17916
+ var RerankerUnavailableError = class extends Error {
17917
+ constructor(reason) {
17918
+ super("cross-encoder reranker unavailable (@huggingface/transformers not installed)");
17919
+ this.name = "RerankerUnavailableError";
17920
+ this.reason = reason;
17921
+ }
17922
+ };
17923
+ var available = void 0;
17857
17924
  var modelPromise = null;
17925
+ function isRerankerAvailable() {
17926
+ return available;
17927
+ }
17928
+ function isModuleMissing(err) {
17929
+ let e = err;
17930
+ for (let depth = 0; depth < 5 && e !== null && e !== void 0; depth++) {
17931
+ const code = e.code;
17932
+ if (code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND") return true;
17933
+ if (e instanceof Error && /cannot find (module|package)|failed to resolve|unable to resolve module|requiring unknown module/i.test(
17934
+ e.message
17935
+ )) {
17936
+ return true;
17937
+ }
17938
+ e = e.cause;
17939
+ }
17940
+ return false;
17941
+ }
17858
17942
  async function getModel() {
17943
+ if (available === false) throw new RerankerUnavailableError(void 0);
17859
17944
  if (!modelPromise) {
17860
17945
  const load = (async () => {
17861
- const transformers = await import("@huggingface/transformers");
17946
+ let transformers;
17947
+ try {
17948
+ transformers = await import("@huggingface/transformers");
17949
+ } catch (err) {
17950
+ if (isModuleMissing(err)) {
17951
+ available = false;
17952
+ throw new RerankerUnavailableError(err);
17953
+ }
17954
+ throw err;
17955
+ }
17862
17956
  const [tokenizer, model] = await Promise.all([
17863
17957
  transformers.AutoTokenizer.from_pretrained(MODEL_ID),
17864
17958
  transformers.AutoModelForSequenceClassification.from_pretrained(MODEL_ID)
17865
17959
  ]);
17960
+ available = true;
17866
17961
  return { tokenizer, model };
17867
17962
  })();
17868
17963
  modelPromise = load;
@@ -18423,6 +18518,9 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
18423
18518
  bm25AdmissionDivisor: options?.bm25AdmissionDivisor,
18424
18519
  rrfK: options?.rrfK
18425
18520
  });
18521
+ if (options?.v2HeadStats) {
18522
+ options.v2HeadStats.hadResults = v2Ranked.length > 0;
18523
+ }
18426
18524
  let combined;
18427
18525
  let tailSlice = [];
18428
18526
  if (options?.rerank) {
@@ -18443,8 +18541,13 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
18443
18541
  return { ...r, similarity: v2 * (1 + ceWeight * ce) };
18444
18542
  });
18445
18543
  combined.sort((a, b) => b.similarity - a.similarity);
18544
+ if (headSlice.length > 0 && options.rerankStats) options.rerankStats.applied = true;
18446
18545
  } catch (err) {
18447
- getLogger().warn("[memory/search] cross-encoder rerank failed; using V2 ranking", err);
18546
+ if (err instanceof RerankerUnavailableError) {
18547
+ getLogger().debug("[memory/search] cross-encoder unavailable; using V2 ranking");
18548
+ } else {
18549
+ getLogger().warn("[memory/search] cross-encoder rerank failed; using V2 ranking", err);
18550
+ }
18448
18551
  combined = v2Ranked;
18449
18552
  }
18450
18553
  } else {
@@ -18578,6 +18681,9 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
18578
18681
  (r) => r !== null
18579
18682
  );
18580
18683
  combined.sort((a, b) => b.similarity - a.similarity);
18684
+ if (options?.v2HeadStats) {
18685
+ options.v2HeadStats.hadResults = combined.length > 0;
18686
+ }
18581
18687
  if (options?.includeUnrankedTail) {
18582
18688
  const fusedIds = new Set(combined.map((r) => r.uniqueId));
18583
18689
  for (const item of items) {
@@ -18613,11 +18719,16 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
18613
18719
  }));
18614
18720
  head.sort((a, b) => b.similarity - a.similarity);
18615
18721
  combined = [...head, ...tailSlice];
18722
+ if (headSlice.length > 0 && options.rerankStats) options.rerankStats.applied = true;
18616
18723
  } catch (err) {
18617
- getLogger().warn(
18618
- "[memory/search] composite cross-encoder rerank failed; using fused ranking",
18619
- err
18620
- );
18724
+ if (err instanceof RerankerUnavailableError) {
18725
+ getLogger().debug("[memory/search] cross-encoder unavailable; using fused ranking");
18726
+ } else {
18727
+ getLogger().warn(
18728
+ "[memory/search] composite cross-encoder rerank failed; using fused ranking",
18729
+ err
18730
+ );
18731
+ }
18621
18732
  }
18622
18733
  }
18623
18734
  if (options?.mmr) {
@@ -18709,7 +18820,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
18709
18820
  const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
18710
18821
  const scopes = searchOptions?.scopes;
18711
18822
  if (!query || typeof query !== "string") {
18712
- return { results: [], vaultSize: 0 };
18823
+ return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
18713
18824
  }
18714
18825
  const folderId = searchOptions?.folderId;
18715
18826
  const queryOpts = {};
@@ -18726,7 +18837,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
18726
18837
  );
18727
18838
  }
18728
18839
  if (memories.length === 0) {
18729
- return { results: [], vaultSize: loaded.length };
18840
+ return { results: [], vaultSize: loaded.length, reranked: false, hadV2Head: false };
18730
18841
  }
18731
18842
  const queryEmbedding = await generateEmbedding(query, embeddingOptions);
18732
18843
  const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
@@ -18802,12 +18913,18 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
18802
18913
  memories.map((m) => [m.uniqueId, { createdAt: m.createdAt, updatedAt: m.updatedAt }])
18803
18914
  );
18804
18915
  const stampTimestamps = (out) => {
18805
- out.results = out.results.map((r) => {
18916
+ const results2 = out.results.map((r) => {
18806
18917
  const ts = timestampById.get(r.uniqueId);
18807
18918
  return ts ? { ...r, createdAt: ts.createdAt, updatedAt: ts.updatedAt } : r;
18808
18919
  });
18809
- return out;
18920
+ return {
18921
+ results: results2,
18922
+ vaultSize: out.vaultSize,
18923
+ reranked: out.reranked ?? false,
18924
+ hadV2Head: out.hadV2Head ?? false
18925
+ };
18810
18926
  };
18927
+ const rerankStats = { applied: false };
18811
18928
  const useFusion = searchOptions?.useFusion ?? true;
18812
18929
  const tuning = {
18813
18930
  ...searchOptions?.recencyAlpha !== void 0 && { recencyAlpha: searchOptions.recencyAlpha },
@@ -18834,6 +18951,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
18834
18951
  query: sq,
18835
18952
  embedding: subEmbeddings[i]
18836
18953
  }));
18954
+ const v2HeadStats = { hadResults: false };
18837
18955
  const composite = await rankComposite(query, queryEmbedding, subQueries, embeddedItems, {
18838
18956
  limit,
18839
18957
  minSimilarity,
@@ -18845,12 +18963,20 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
18845
18963
  ...searchOptions.mmr !== void 0 && { mmr: searchOptions.mmr },
18846
18964
  ...tuning,
18847
18965
  ...searchOptions.entityRanking && { entityRanking: searchOptions.entityRanking },
18848
- ...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking }
18966
+ ...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
18967
+ rerankStats,
18968
+ v2HeadStats
18969
+ });
18970
+ return stampTimestamps({
18971
+ results: composite,
18972
+ vaultSize: loaded.length,
18973
+ reranked: rerankStats.applied,
18974
+ hadV2Head: v2HeadStats.hadResults
18849
18975
  });
18850
- return stampTimestamps({ results: composite, vaultSize: loaded.length });
18851
18976
  }
18852
18977
  }
18853
18978
  if (useFusion && searchOptions?.rerank) {
18979
+ const v2HeadStats = { hadResults: false };
18854
18980
  const results2 = await rankFusedVaultMemoriesAsync(query, queryEmbedding, embeddedItems, {
18855
18981
  limit,
18856
18982
  minSimilarity,
@@ -18862,9 +18988,16 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
18862
18988
  ...searchOptions.mmr !== void 0 && { mmr: searchOptions.mmr },
18863
18989
  ...tuning,
18864
18990
  ...searchOptions.entityRanking && { entityRanking: searchOptions.entityRanking },
18865
- ...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking }
18991
+ ...searchOptions.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
18992
+ rerankStats,
18993
+ v2HeadStats
18994
+ });
18995
+ return stampTimestamps({
18996
+ results: results2,
18997
+ vaultSize: loaded.length,
18998
+ reranked: rerankStats.applied,
18999
+ hadV2Head: v2HeadStats.hadResults
18866
19000
  });
18867
- return stampTimestamps({ results: results2, vaultSize: loaded.length });
18868
19001
  }
18869
19002
  if (useFusion) {
18870
19003
  const results2 = rankFusedVaultMemories(query, queryEmbedding, embeddedItems, {
@@ -18874,7 +19007,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
18874
19007
  ...searchOptions?.entityRanking && { entityRanking: searchOptions.entityRanking },
18875
19008
  ...searchOptions?.temporalRanking && { temporalRanking: searchOptions.temporalRanking }
18876
19009
  });
18877
- return stampTimestamps({ results: results2, vaultSize: loaded.length });
19010
+ return stampTimestamps({ results: results2, vaultSize: loaded.length, hadV2Head: results2.length > 0 });
18878
19011
  }
18879
19012
  const results = rankVaultMemories(query, queryEmbedding, embeddedItems, {
18880
19013
  limit,
@@ -18886,7 +19019,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
18886
19019
  supersessionWindow: searchOptions.supersessionWindow
18887
19020
  }
18888
19021
  });
18889
- return stampTimestamps({ results, vaultSize: loaded.length });
19022
+ return stampTimestamps({ results, vaultSize: loaded.length, hadV2Head: results.length > 0 });
18890
19023
  }
18891
19024
  async function searchVaultMemories(query, vaultCtx, embeddingOptions, cache, searchOptions) {
18892
19025
  const { results } = await searchVaultMemoriesWithSize(
@@ -18975,7 +19108,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
18975
19108
  legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
18976
19109
  );
18977
19110
  }
18978
- const { recall: recall2 } = await import("./recall-EWMI64SA.mjs");
19111
+ const { recall: recall2 } = await import("./recall-MJHGXMHZ.mjs");
18979
19112
  const result = await recall2(
18980
19113
  query,
18981
19114
  { vaultCtx, embeddingOptions, vaultCache: cache },
@@ -19293,6 +19426,7 @@ function scoreEventTimeOverlap(memoryStart, memoryEnd, memoryKind, window2) {
19293
19426
  var DEFAULT_LIMIT = 8;
19294
19427
  var DEFAULT_BUDGET = "low";
19295
19428
  var DEFAULT_FACT_MIN_SCORE = 0.1;
19429
+ var nowMs = () => typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
19296
19430
  var DEFAULT_CHUNK_MIN_SCORE = 0.5;
19297
19431
  function flagsForBudget(budget) {
19298
19432
  switch (budget) {
@@ -19325,22 +19459,67 @@ async function recall(query, ctx, options = {}) {
19325
19459
  const flags = flagsForBudget(requestedBudget);
19326
19460
  const decomposeAvailable = flags.decompose && !!options.decomposeOptions;
19327
19461
  const usedBudget = requestedBudget === "high" && !decomposeAvailable ? "mid" : requestedBudget;
19462
+ const t0 = nowMs();
19463
+ let prepMs = 0;
19464
+ let factLaneMs = 0;
19465
+ let chunkLaneMs = 0;
19466
+ let fuseMs = 0;
19467
+ const factResults = [];
19468
+ const chunkResults = [];
19469
+ let vaultSize;
19470
+ let didRerank = false;
19471
+ let hadV2Head = false;
19472
+ const emitDiagnostics = (candidateCount) => {
19473
+ const cb = options.onDiagnostics;
19474
+ if (!cb) return;
19475
+ const degraded = [];
19476
+ if (flags.rerank && factResults.length > 0 && hadV2Head && !didRerank) {
19477
+ degraded.push("rerank-unavailable");
19478
+ }
19479
+ if (flags.decompose && !decomposeAvailable) degraded.push("decompose-unavailable");
19480
+ const diagnostics = {
19481
+ usedBudget,
19482
+ reranked: didRerank,
19483
+ candidateCount,
19484
+ ...vaultSize !== void 0 && { vaultSize },
19485
+ factCount: factResults.length,
19486
+ chunkCount: chunkResults.length,
19487
+ timings: {
19488
+ total: nowMs() - t0,
19489
+ prep: prepMs,
19490
+ factLane: factLaneMs,
19491
+ chunkLane: chunkLaneMs,
19492
+ fuse: fuseMs
19493
+ },
19494
+ degraded
19495
+ };
19496
+ try {
19497
+ cb(diagnostics);
19498
+ } catch {
19499
+ }
19500
+ };
19328
19501
  if (!query || typeof query !== "string" || query.trim().length === 0) {
19502
+ emitDiagnostics(0);
19329
19503
  return { memories: [], usedBudget, reranked: false, candidateCount: 0 };
19330
19504
  }
19331
19505
  const needsChunkEmbedding = types.includes("chunk") && ctx.storageCtx;
19332
19506
  const wantsTemporal = types.includes("fact") && ctx.vaultCtx;
19507
+ const prepStart = nowMs();
19333
19508
  const [queryEmbedding, entityRanking, temporalRanking] = await Promise.all([
19334
19509
  needsChunkEmbedding ? generateEmbedding(query, ctx.embeddingOptions) : Promise.resolve(void 0),
19335
19510
  buildGraphLaneRanking(query, ctx),
19336
19511
  wantsTemporal ? buildTemporalLaneRanking(query, ctx.vaultCtx, options.now) : Promise.resolve([])
19337
19512
  ]);
19338
- const factResults = [];
19339
- const chunkResults = [];
19340
- let vaultSize;
19513
+ prepMs = nowMs() - prepStart;
19341
19514
  if (types.includes("fact") && ctx.vaultCtx && ctx.vaultCache) {
19515
+ const factStart = nowMs();
19342
19516
  const vaultMinScore = options.minScore ?? DEFAULT_FACT_MIN_SCORE;
19343
- const { results, vaultSize: size } = await searchVaultMemoriesWithSize(
19517
+ const {
19518
+ results,
19519
+ vaultSize: size,
19520
+ reranked,
19521
+ hadV2Head: v2Head
19522
+ } = await searchVaultMemoriesWithSize(
19344
19523
  query,
19345
19524
  ctx.vaultCtx,
19346
19525
  ctx.embeddingOptions,
@@ -19391,14 +19570,19 @@ async function recall(query, ctx, options = {}) {
19391
19570
  )
19392
19571
  );
19393
19572
  vaultSize = size;
19573
+ didRerank = reranked;
19574
+ hadV2Head = v2Head;
19575
+ factLaneMs = nowMs() - factStart;
19394
19576
  }
19395
19577
  if (types.includes("chunk") && ctx.storageCtx && queryEmbedding) {
19578
+ const chunkStart = nowMs();
19396
19579
  const chunkMinScore = options.minScore ?? DEFAULT_CHUNK_MIN_SCORE;
19397
19580
  const results = await searchChunksOp(ctx.storageCtx, queryEmbedding, {
19398
19581
  limit: types.includes("fact") ? Math.max(limit * 2, 16) : limit,
19399
19582
  minSimilarity: chunkMinScore,
19400
19583
  embeddingModel: ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL,
19401
- ...options.conversationId && { conversationId: options.conversationId }
19584
+ ...options.conversationId && { conversationId: options.conversationId },
19585
+ ...ctx.chunkCache && { chunkCache: ctx.chunkCache }
19402
19586
  });
19403
19587
  chunkResults.push(
19404
19588
  ...dedupeBy(
@@ -19408,18 +19592,23 @@ async function recall(query, ctx, options = {}) {
19408
19592
  (r) => r.chunkText.trim()
19409
19593
  )
19410
19594
  );
19595
+ chunkLaneMs = nowMs() - chunkStart;
19411
19596
  }
19597
+ const fuseStart = nowMs();
19412
19598
  if (types.length === 1 || factResults.length === 0 || chunkResults.length === 0) {
19413
19599
  const memories2 = [
19414
19600
  ...factResults.map(toFactMemory),
19415
19601
  ...chunkResults.map(toChunkMemory)
19416
19602
  ];
19417
19603
  memories2.sort((a, b) => b.score - a.score);
19604
+ const candidateCount = factResults.length + chunkResults.length;
19605
+ fuseMs = nowMs() - fuseStart;
19606
+ emitDiagnostics(candidateCount);
19418
19607
  return {
19419
19608
  memories: memories2.slice(0, limit),
19420
19609
  usedBudget,
19421
- reranked: flags.rerank,
19422
- candidateCount: factResults.length + chunkResults.length,
19610
+ reranked: didRerank,
19611
+ candidateCount,
19423
19612
  ...vaultSize !== void 0 && { vaultSize }
19424
19613
  };
19425
19614
  }
@@ -19468,10 +19657,12 @@ async function recall(query, ctx, options = {}) {
19468
19657
  suppressed = next;
19469
19658
  memories = selectWith(suppressed);
19470
19659
  }
19660
+ fuseMs = nowMs() - fuseStart;
19661
+ emitDiagnostics(byId.size);
19471
19662
  return {
19472
19663
  memories,
19473
19664
  usedBudget,
19474
- reranked: flags.rerank,
19665
+ reranked: didRerank,
19475
19666
  candidateCount: byId.size,
19476
19667
  ...vaultSize !== void 0 && { vaultSize }
19477
19668
  };
@@ -19630,7 +19821,10 @@ export {
19630
19821
  embedAllMessages,
19631
19822
  chunkAndEmbedMessage,
19632
19823
  chunkAndEmbedAllMessages,
19824
+ RerankerUnavailableError,
19825
+ isRerankerAvailable,
19633
19826
  DEFAULT_VAULT_CACHE_SIZE,
19827
+ LRUCache,
19634
19828
  createVaultEmbeddingCache,
19635
19829
  recall,
19636
19830
  preEmbedVaultMemories,