@anuma/sdk 3.9.4 → 3.9.6

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.
@@ -4786,24 +4786,25 @@ function tokenize(text) {
4786
4786
  if (!m) return [];
4787
4787
  return m.filter((t) => !STOPWORDS.has(t));
4788
4788
  }
4789
- function scoreBM25(query, items) {
4790
- const queryTerms = tokenize(query);
4791
- if (queryTerms.length === 0 || items.length === 0) return /* @__PURE__ */ new Map();
4789
+ function prepareBM25Corpus(items) {
4790
+ const ids = items.map((i) => i.id);
4792
4791
  const docTokens = items.map((i) => tokenize(i.content));
4793
4792
  const docLens = docTokens.map((t) => t.length);
4794
- const avgdl = docLens.reduce((a, b) => a + b, 0) / docLens.length;
4795
- const queryTermSet = new Set(queryTerms);
4793
+ const avgdl = docLens.length ? docLens.reduce((a, b) => a + b, 0) / docLens.length : 0;
4796
4794
  const df = /* @__PURE__ */ new Map();
4797
4795
  for (const tokens of docTokens) {
4798
- const seen = /* @__PURE__ */ new Set();
4799
- for (const t of tokens) {
4800
- if (queryTermSet.has(t)) seen.add(t);
4801
- }
4796
+ const seen = new Set(tokens);
4802
4797
  for (const t of seen) df.set(t, (df.get(t) ?? 0) + 1);
4803
4798
  }
4804
- const N = items.length;
4799
+ return { ids, docTokens, docLens, avgdl, df, n: items.length };
4800
+ }
4801
+ function scoreBM25Prepared(query, corpus) {
4802
+ const queryTerms = tokenize(query);
4805
4803
  const scores = /* @__PURE__ */ new Map();
4806
- for (let i = 0; i < items.length; i++) {
4804
+ if (queryTerms.length === 0 || corpus.n === 0) return scores;
4805
+ const queryTermSet = new Set(queryTerms);
4806
+ const { ids, docTokens, docLens, avgdl, df, n: N } = corpus;
4807
+ for (let i = 0; i < N; i++) {
4807
4808
  const tokens = docTokens[i];
4808
4809
  const dl = docLens[i];
4809
4810
  if (dl === 0) continue;
@@ -4819,10 +4820,15 @@ function scoreBM25(query, items) {
4819
4820
  const tfNorm = f * (K1 + 1) / (f + K1 * (1 - B + B * dl / avgdl));
4820
4821
  score += idf * tfNorm;
4821
4822
  }
4822
- scores.set(items[i].id, score);
4823
+ scores.set(ids[i], score);
4823
4824
  }
4824
4825
  return scores;
4825
4826
  }
4827
+ function scoreBM25(query, items) {
4828
+ if (items.length === 0) return /* @__PURE__ */ new Map();
4829
+ if (tokenize(query).length === 0) return /* @__PURE__ */ new Map();
4830
+ return scoreBM25Prepared(query, prepareBM25Corpus(items));
4831
+ }
4826
4832
 
4827
4833
  // src/lib/memoryVault/decomposeQuery.ts
4828
4834
  var DEFAULT_MODEL = "inclusionai/ling-2.6-flash";
@@ -5077,7 +5083,7 @@ function rankFusedVaultMemories(query, queryEmbedding, items, options) {
5077
5083
  }
5078
5084
  });
5079
5085
  const baseIds = new Set(baseRanked.map((r) => r.uniqueId));
5080
- const bm25Scores = scoreBM25(
5086
+ const bm25Scores = options?.preparedBM25Corpus ? scoreBM25Prepared(query, options.preparedBM25Corpus) : scoreBM25(
5081
5087
  query,
5082
5088
  items.map((i) => ({ id: i.id, content: i.content }))
5083
5089
  );
@@ -5274,7 +5280,11 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
5274
5280
  const limit = options?.limit ?? 5;
5275
5281
  const perFacetTopN = options?.perFacetTopN ?? 10;
5276
5282
  if (items.length === 0 || subQueries.length === 0) return [];
5283
+ const preparedBM25Corpus = prepareBM25Corpus(
5284
+ items.map((i) => ({ id: i.id, content: i.content }))
5285
+ );
5277
5286
  const facetTuning = {
5287
+ preparedBM25Corpus,
5278
5288
  ...options?.recencyAlpha !== void 0 && { recencyAlpha: options.recencyAlpha },
5279
5289
  ...options?.recency && { recency: options.recency },
5280
5290
  ...options?.supersessionBoost !== void 0 && {
@@ -5584,13 +5594,12 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
5584
5594
  }));
5585
5595
  return { memories, embeddedItems, queryEmbedding, vaultSize };
5586
5596
  }
5587
- async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, cache, searchOptions) {
5588
- const limit = searchOptions?.limit ?? 5;
5589
- const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
5590
- const scopes = searchOptions?.scopes;
5597
+ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache, searchOptions) {
5591
5598
  if (!query || typeof query !== "string") {
5592
- return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
5599
+ return { memories: [], embeddedItems: [], queryEmbedding: [], vaultSize: 0 };
5593
5600
  }
5601
+ const limit = searchOptions?.limit ?? 5;
5602
+ const scopes = searchOptions?.scopes;
5594
5603
  const folderId = searchOptions?.folderId;
5595
5604
  const queryOpts = {};
5596
5605
  if (scopes?.length) queryOpts.scopes = scopes;
@@ -5617,11 +5626,11 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
5617
5626
  ...forceIncludeIds.length > 0 && { forceIncludeIds }
5618
5627
  });
5619
5628
  if (corpus.vaultSize === 0) {
5620
- return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
5629
+ return { memories: [], embeddedItems: [], queryEmbedding: [], vaultSize: 0 };
5621
5630
  }
5622
5631
  ({ memories, embeddedItems, queryEmbedding, vaultSize } = corpus);
5623
5632
  if (memories.length === 0) {
5624
- return { results: [], vaultSize, reranked: false, hadV2Head: false };
5633
+ return { memories: [], embeddedItems: [], queryEmbedding: [], vaultSize };
5625
5634
  }
5626
5635
  } else {
5627
5636
  const loaded = await getAllVaultMemoriesOp(
@@ -5636,7 +5645,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
5636
5645
  );
5637
5646
  }
5638
5647
  if (memories.length === 0) {
5639
- return { results: [], vaultSize: loaded.length, reranked: false, hadV2Head: false };
5648
+ return { memories: [], embeddedItems: [], queryEmbedding: [], vaultSize: loaded.length };
5640
5649
  }
5641
5650
  queryEmbedding = await generateEmbedding(query, embeddingOptions);
5642
5651
  const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
@@ -5701,6 +5710,12 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
5701
5710
  factType: m.factType
5702
5711
  }));
5703
5712
  }
5713
+ return { memories, embeddedItems, queryEmbedding, vaultSize };
5714
+ }
5715
+ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, searchOptions) {
5716
+ const limit = searchOptions?.limit ?? 5;
5717
+ const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
5718
+ const { memories, embeddedItems, queryEmbedding, vaultSize } = prepared;
5704
5719
  if (queryEmbedding.length > 0) {
5705
5720
  const mismatched = embeddedItems.filter(
5706
5721
  (it) => it.embedding.length > 0 && it.embedding.length !== queryEmbedding.length
@@ -5838,6 +5853,25 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
5838
5853
  });
5839
5854
  return stampTimestamps({ results, vaultSize, hadV2Head: results.length > 0 });
5840
5855
  }
5856
+ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, cache, searchOptions) {
5857
+ if (!query || typeof query !== "string") {
5858
+ return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
5859
+ }
5860
+ const prepared = await prepareVaultCandidates(
5861
+ query,
5862
+ vaultCtx,
5863
+ embeddingOptions,
5864
+ cache,
5865
+ searchOptions
5866
+ );
5867
+ if (prepared.vaultSize === 0) {
5868
+ return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
5869
+ }
5870
+ if (prepared.memories.length === 0) {
5871
+ return { results: [], vaultSize: prepared.vaultSize, reranked: false, hadV2Head: false };
5872
+ }
5873
+ return rankPreparedVaultCandidates(query, prepared, embeddingOptions, searchOptions);
5874
+ }
5841
5875
  async function searchVaultMemories(query, vaultCtx, embeddingOptions, cache, searchOptions) {
5842
5876
  const { results } = await searchVaultMemoriesWithSize(
5843
5877
  query,
@@ -5925,7 +5959,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
5925
5959
  legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
5926
5960
  );
5927
5961
  }
5928
- const { recall: recall2 } = await import("./recall-F33QYRYU.mjs");
5962
+ const { recall: recall2 } = await import("./recall-ELUJPQQB.mjs");
5929
5963
  const result = await recall2(
5930
5964
  query,
5931
5965
  { vaultCtx, embeddingOptions, vaultCache: cache },
@@ -6984,6 +7018,8 @@ export {
6984
7018
  recall,
6985
7019
  preEmbedVaultMemories,
6986
7020
  eagerEmbedContent,
7021
+ prepareVaultCandidates,
7022
+ rankPreparedVaultCandidates,
6987
7023
  searchVaultMemories,
6988
7024
  createMemoryVaultSearchTool
6989
7025
  };
@@ -8,7 +8,7 @@ import {
8
8
  import "./chunk-GYKJOWEO.mjs";
9
9
 
10
10
  // src/lib/memory/consolidate.ts
11
- var DEFAULT_MODEL = "inclusionai/ling-2.6-flash";
11
+ var DEFAULT_CONSOLIDATION_MODEL = "inclusionai/ling-2.6-flash";
12
12
  var DEFAULT_CONSOLIDATE_ATTEMPTS = 3;
13
13
  var DEFAULT_CONSOLIDATE_TOTAL_TIMEOUT_MS = 2e4;
14
14
  var SYSTEM_PROMPT = `You consolidate a new memory against existing memories from the same user.
@@ -70,7 +70,7 @@ ${candidateText}`;
70
70
  ...options.apiKey !== void 0 && { apiKey: options.apiKey },
71
71
  ...options.getToken !== void 0 && { getToken: options.getToken },
72
72
  ...options.baseUrl !== void 0 && { baseUrl: options.baseUrl },
73
- model: options.model ?? DEFAULT_MODEL,
73
+ model: options.model ?? DEFAULT_CONSOLIDATION_MODEL,
74
74
  systemPrompt: SYSTEM_PROMPT,
75
75
  userMessage,
76
76
  tag: "memory/consolidate",
@@ -147,5 +147,6 @@ function validate(parsed, newContent, validIds) {
147
147
  return { action: "update", targetId, content: c };
148
148
  }
149
149
  export {
150
+ DEFAULT_CONSOLIDATION_MODEL,
150
151
  consolidateMemory
151
152
  };
@@ -5869,24 +5869,25 @@ function tokenize(text12) {
5869
5869
  if (!m) return [];
5870
5870
  return m.filter((t) => !STOPWORDS.has(t));
5871
5871
  }
5872
- function scoreBM25(query, items) {
5873
- const queryTerms = tokenize(query);
5874
- if (queryTerms.length === 0 || items.length === 0) return /* @__PURE__ */ new Map();
5872
+ function prepareBM25Corpus(items) {
5873
+ const ids = items.map((i) => i.id);
5875
5874
  const docTokens = items.map((i) => tokenize(i.content));
5876
5875
  const docLens = docTokens.map((t) => t.length);
5877
- const avgdl = docLens.reduce((a, b) => a + b, 0) / docLens.length;
5878
- const queryTermSet = new Set(queryTerms);
5876
+ const avgdl = docLens.length ? docLens.reduce((a, b) => a + b, 0) / docLens.length : 0;
5879
5877
  const df = /* @__PURE__ */ new Map();
5880
5878
  for (const tokens of docTokens) {
5881
- const seen = /* @__PURE__ */ new Set();
5882
- for (const t of tokens) {
5883
- if (queryTermSet.has(t)) seen.add(t);
5884
- }
5879
+ const seen = new Set(tokens);
5885
5880
  for (const t of seen) df.set(t, (df.get(t) ?? 0) + 1);
5886
5881
  }
5887
- const N = items.length;
5882
+ return { ids, docTokens, docLens, avgdl, df, n: items.length };
5883
+ }
5884
+ function scoreBM25Prepared(query, corpus) {
5885
+ const queryTerms = tokenize(query);
5888
5886
  const scores = /* @__PURE__ */ new Map();
5889
- for (let i = 0; i < items.length; i++) {
5887
+ if (queryTerms.length === 0 || corpus.n === 0) return scores;
5888
+ const queryTermSet = new Set(queryTerms);
5889
+ const { ids, docTokens, docLens, avgdl, df, n: N } = corpus;
5890
+ for (let i = 0; i < N; i++) {
5890
5891
  const tokens = docTokens[i];
5891
5892
  const dl = docLens[i];
5892
5893
  if (dl === 0) continue;
@@ -5902,10 +5903,15 @@ function scoreBM25(query, items) {
5902
5903
  const tfNorm = f * (K1 + 1) / (f + K1 * (1 - B + B * dl / avgdl));
5903
5904
  score += idf * tfNorm;
5904
5905
  }
5905
- scores.set(items[i].id, score);
5906
+ scores.set(ids[i], score);
5906
5907
  }
5907
5908
  return scores;
5908
5909
  }
5910
+ function scoreBM25(query, items) {
5911
+ if (items.length === 0) return /* @__PURE__ */ new Map();
5912
+ if (tokenize(query).length === 0) return /* @__PURE__ */ new Map();
5913
+ return scoreBM25Prepared(query, prepareBM25Corpus(items));
5914
+ }
5909
5915
  var K1, B, TOKEN_RE, STOPWORDS;
5910
5916
  var init_bm25 = __esm({
5911
5917
  "src/lib/memoryVault/bm25.ts"() {
@@ -7226,7 +7232,7 @@ function rankFusedVaultMemories(query, queryEmbedding, items, options) {
7226
7232
  }
7227
7233
  });
7228
7234
  const baseIds = new Set(baseRanked.map((r) => r.uniqueId));
7229
- const bm25Scores = scoreBM25(
7235
+ const bm25Scores = options?.preparedBM25Corpus ? scoreBM25Prepared(query, options.preparedBM25Corpus) : scoreBM25(
7230
7236
  query,
7231
7237
  items.map((i) => ({ id: i.id, content: i.content }))
7232
7238
  );
@@ -7423,7 +7429,11 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
7423
7429
  const limit = options?.limit ?? 5;
7424
7430
  const perFacetTopN = options?.perFacetTopN ?? 10;
7425
7431
  if (items.length === 0 || subQueries.length === 0) return [];
7432
+ const preparedBM25Corpus = prepareBM25Corpus(
7433
+ items.map((i) => ({ id: i.id, content: i.content }))
7434
+ );
7426
7435
  const facetTuning = {
7436
+ preparedBM25Corpus,
7427
7437
  ...options?.recencyAlpha !== void 0 && { recencyAlpha: options.recencyAlpha },
7428
7438
  ...options?.recency && { recency: options.recency },
7429
7439
  ...options?.supersessionBoost !== void 0 && {
@@ -7733,13 +7743,12 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
7733
7743
  }));
7734
7744
  return { memories, embeddedItems, queryEmbedding, vaultSize };
7735
7745
  }
7736
- async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, cache, searchOptions) {
7737
- const limit = searchOptions?.limit ?? 5;
7738
- const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
7739
- const scopes = searchOptions?.scopes;
7746
+ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache, searchOptions) {
7740
7747
  if (!query || typeof query !== "string") {
7741
- return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
7748
+ return { memories: [], embeddedItems: [], queryEmbedding: [], vaultSize: 0 };
7742
7749
  }
7750
+ const limit = searchOptions?.limit ?? 5;
7751
+ const scopes = searchOptions?.scopes;
7743
7752
  const folderId = searchOptions?.folderId;
7744
7753
  const queryOpts = {};
7745
7754
  if (scopes?.length) queryOpts.scopes = scopes;
@@ -7766,11 +7775,11 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
7766
7775
  ...forceIncludeIds.length > 0 && { forceIncludeIds }
7767
7776
  });
7768
7777
  if (corpus.vaultSize === 0) {
7769
- return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
7778
+ return { memories: [], embeddedItems: [], queryEmbedding: [], vaultSize: 0 };
7770
7779
  }
7771
7780
  ({ memories, embeddedItems, queryEmbedding, vaultSize } = corpus);
7772
7781
  if (memories.length === 0) {
7773
- return { results: [], vaultSize, reranked: false, hadV2Head: false };
7782
+ return { memories: [], embeddedItems: [], queryEmbedding: [], vaultSize };
7774
7783
  }
7775
7784
  } else {
7776
7785
  const loaded = await getAllVaultMemoriesOp(
@@ -7785,7 +7794,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
7785
7794
  );
7786
7795
  }
7787
7796
  if (memories.length === 0) {
7788
- return { results: [], vaultSize: loaded.length, reranked: false, hadV2Head: false };
7797
+ return { memories: [], embeddedItems: [], queryEmbedding: [], vaultSize: loaded.length };
7789
7798
  }
7790
7799
  queryEmbedding = await generateEmbedding(query, embeddingOptions);
7791
7800
  const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
@@ -7850,6 +7859,12 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
7850
7859
  factType: m.factType
7851
7860
  }));
7852
7861
  }
7862
+ return { memories, embeddedItems, queryEmbedding, vaultSize };
7863
+ }
7864
+ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, searchOptions) {
7865
+ const limit = searchOptions?.limit ?? 5;
7866
+ const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
7867
+ const { memories, embeddedItems, queryEmbedding, vaultSize } = prepared;
7853
7868
  if (queryEmbedding.length > 0) {
7854
7869
  const mismatched = embeddedItems.filter(
7855
7870
  (it) => it.embedding.length > 0 && it.embedding.length !== queryEmbedding.length
@@ -7987,6 +8002,25 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
7987
8002
  });
7988
8003
  return stampTimestamps({ results, vaultSize, hadV2Head: results.length > 0 });
7989
8004
  }
8005
+ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, cache, searchOptions) {
8006
+ if (!query || typeof query !== "string") {
8007
+ return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
8008
+ }
8009
+ const prepared = await prepareVaultCandidates(
8010
+ query,
8011
+ vaultCtx,
8012
+ embeddingOptions,
8013
+ cache,
8014
+ searchOptions
8015
+ );
8016
+ if (prepared.vaultSize === 0) {
8017
+ return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
8018
+ }
8019
+ if (prepared.memories.length === 0) {
8020
+ return { results: [], vaultSize: prepared.vaultSize, reranked: false, hadV2Head: false };
8021
+ }
8022
+ return rankPreparedVaultCandidates(query, prepared, embeddingOptions, searchOptions);
8023
+ }
7990
8024
  async function searchVaultMemories(query, vaultCtx, embeddingOptions, cache, searchOptions) {
7991
8025
  const { results } = await searchVaultMemoriesWithSize(
7992
8026
  query,
@@ -8145,6 +8179,7 @@ var init_searchTool = __esm({
8145
8179
  // src/lib/memory/consolidate.ts
8146
8180
  var consolidate_exports = {};
8147
8181
  __export(consolidate_exports, {
8182
+ DEFAULT_CONSOLIDATION_MODEL: () => DEFAULT_CONSOLIDATION_MODEL,
8148
8183
  consolidateMemory: () => consolidateMemory
8149
8184
  });
8150
8185
  async function consolidateMemory(newContent, candidates, options) {
@@ -8173,7 +8208,7 @@ ${candidateText}`;
8173
8208
  ...options.apiKey !== void 0 && { apiKey: options.apiKey },
8174
8209
  ...options.getToken !== void 0 && { getToken: options.getToken },
8175
8210
  ...options.baseUrl !== void 0 && { baseUrl: options.baseUrl },
8176
- model: options.model ?? DEFAULT_MODEL3,
8211
+ model: options.model ?? DEFAULT_CONSOLIDATION_MODEL,
8177
8212
  systemPrompt: SYSTEM_PROMPT3,
8178
8213
  userMessage,
8179
8214
  tag: "memory/consolidate",
@@ -8249,14 +8284,14 @@ function validate2(parsed, newContent, validIds) {
8249
8284
  if (!targetId || !validIds.has(targetId)) return null;
8250
8285
  return { action: "update", targetId, content: c };
8251
8286
  }
8252
- var DEFAULT_MODEL3, DEFAULT_CONSOLIDATE_ATTEMPTS, DEFAULT_CONSOLIDATE_TOTAL_TIMEOUT_MS, SYSTEM_PROMPT3;
8287
+ var DEFAULT_CONSOLIDATION_MODEL, DEFAULT_CONSOLIDATE_ATTEMPTS, DEFAULT_CONSOLIDATE_TOTAL_TIMEOUT_MS, SYSTEM_PROMPT3;
8253
8288
  var init_consolidate = __esm({
8254
8289
  "src/lib/memory/consolidate.ts"() {
8255
8290
  "use strict";
8256
8291
  init_logger();
8257
8292
  init_redactor();
8258
8293
  init_portalLlm();
8259
- DEFAULT_MODEL3 = "inclusionai/ling-2.6-flash";
8294
+ DEFAULT_CONSOLIDATION_MODEL = "inclusionai/ling-2.6-flash";
8260
8295
  DEFAULT_CONSOLIDATE_ATTEMPTS = 3;
8261
8296
  DEFAULT_CONSOLIDATE_TOTAL_TIMEOUT_MS = 2e4;
8262
8297
  SYSTEM_PROMPT3 = `You consolidate a new memory against existing memories from the same user.
@@ -15800,9 +15835,25 @@ async function retain(content, ctx, options = {}) {
15800
15835
  const resolvedScope = options.scope ?? DEFAULT_SCOPE;
15801
15836
  let supersedeTargetIds = [];
15802
15837
  let supersedeContent;
15838
+ let prepared;
15803
15839
  if (enableAutoMerge) {
15840
+ prepared = await prepareVaultCandidates(
15841
+ trimmed,
15842
+ ctx.vaultCtx,
15843
+ ctx.embeddingOptions,
15844
+ ctx.vaultCache,
15845
+ {
15846
+ limit: Math.max(options.consolidateTopK ?? DEFAULT_CONSOLIDATE_TOP_K, 1),
15847
+ useFusion: false,
15848
+ scopes: [resolvedScope],
15849
+ // PR5 — include archived rows as merge candidates so a re-observed fact
15850
+ // resurrects (un-archives) the decayed row instead of duplicating it.
15851
+ includeArchived: true,
15852
+ ...options.folderId !== void 0 && { folderId: options.folderId }
15853
+ }
15854
+ );
15804
15855
  if (options.consolidateOptions) {
15805
- const outcome = await tryConsolidate(trimmed, ctx, options);
15856
+ const outcome = await tryConsolidate(trimmed, ctx, options, prepared);
15806
15857
  if (outcome) {
15807
15858
  if ("done" in outcome) return outcome.done;
15808
15859
  supersedeTargetIds = outcome.supersede;
@@ -15810,23 +15861,14 @@ async function retain(content, ctx, options = {}) {
15810
15861
  }
15811
15862
  }
15812
15863
  if (supersedeTargetIds.length === 0) {
15813
- const matches = await searchVaultMemories(
15864
+ const { results: matches } = await rankPreparedVaultCandidates(
15814
15865
  trimmed,
15815
- ctx.vaultCtx,
15866
+ prepared,
15816
15867
  ctx.embeddingOptions,
15817
- ctx.vaultCache,
15818
15868
  {
15819
15869
  limit: 1,
15820
15870
  minSimilarity: threshold,
15821
- useFusion: false,
15822
- scopes: [resolvedScope],
15823
- // PR5 — include archived rows as merge candidates so a re-observed
15824
- // fact resurrects (un-archives) the decayed row instead of creating a
15825
- // fresh duplicate. The resurrection is applied on the merge write
15826
- // below, but ONLY for a row that is not superseded/deleted (the
15827
- // guards below preserve main's tombstone/supersession suppression).
15828
- includeArchived: true,
15829
- ...options.folderId !== void 0 && { folderId: options.folderId }
15871
+ useFusion: false
15830
15872
  }
15831
15873
  );
15832
15874
  if (matches.length > 0) {
@@ -15874,7 +15916,8 @@ async function retain(content, ctx, options = {}) {
15874
15916
  }
15875
15917
  }
15876
15918
  const contentToWrite = supersedeContent ?? trimmed;
15877
- const embedding = await generateEmbedding(contentToWrite, ctx.embeddingOptions);
15919
+ const reusableQueryEmbedding = supersedeContent === void 0 && prepared && prepared.queryEmbedding.length > 0 ? prepared.queryEmbedding : void 0;
15920
+ const embedding = reusableQueryEmbedding ?? await generateEmbedding(contentToWrite, ctx.embeddingOptions);
15878
15921
  const embeddingModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
15879
15922
  if (options.respectTombstones) {
15880
15923
  const tombstoneId = await findTombstoneMatch(embedding, embeddingModel, resolvedScope, ctx, {
@@ -16003,26 +16046,19 @@ function pickFactTypeUpdate(existing, incoming) {
16003
16046
  function resurrectFields(existing) {
16004
16047
  return typeof existing.archivedAt === "number" ? { restore: true } : { preserveUpdatedAt: true };
16005
16048
  }
16006
- async function tryConsolidate(trimmed, ctx, options) {
16049
+ async function tryConsolidate(trimmed, ctx, options, prepared) {
16007
16050
  const consolidateOptions = options.consolidateOptions;
16008
16051
  if (!consolidateOptions) return null;
16009
16052
  const consolidateThreshold = options.consolidateThreshold ?? DEFAULT_CONSOLIDATE_THRESHOLD;
16010
16053
  const topK = options.consolidateTopK ?? DEFAULT_CONSOLIDATE_TOP_K;
16011
- const resolvedScope = options.scope ?? DEFAULT_SCOPE;
16012
- const matches = await searchVaultMemories(
16054
+ const { results: matches } = await rankPreparedVaultCandidates(
16013
16055
  trimmed,
16014
- ctx.vaultCtx,
16056
+ prepared,
16015
16057
  ctx.embeddingOptions,
16016
- ctx.vaultCache,
16017
16058
  {
16018
16059
  limit: topK,
16019
16060
  minSimilarity: consolidateThreshold,
16020
- useFusion: false,
16021
- scopes: [resolvedScope],
16022
- // PR5 — archived rows are consolidation candidates too, so a paraphrased
16023
- // re-observation resurrects a decayed row rather than duplicating it.
16024
- includeArchived: true,
16025
- ...options.folderId !== void 0 && { folderId: options.folderId }
16061
+ useFusion: false
16026
16062
  }
16027
16063
  );
16028
16064
  if (matches.length === 0) return null;
@@ -16805,7 +16841,7 @@ function classifyDecay(m, now, policy) {
16805
16841
  init_logger();
16806
16842
  init_redactor();
16807
16843
  init_portalLlm();
16808
- var DEFAULT_MODEL4 = "inclusionai/ling-2.6-flash";
16844
+ var DEFAULT_MODEL3 = "inclusionai/ling-2.6-flash";
16809
16845
  var DEFAULT_ATTEMPTS2 = 2;
16810
16846
  var DEFAULT_TOTAL_TIMEOUT_MS2 = 12e3;
16811
16847
  var MAX_CONTENT_CHARS = 400;
@@ -16844,7 +16880,7 @@ function createLlmDecayClassifier(options) {
16844
16880
  ...options.apiKey !== void 0 && { apiKey: options.apiKey },
16845
16881
  ...options.getToken !== void 0 && { getToken: options.getToken },
16846
16882
  ...options.baseUrl !== void 0 && { baseUrl: options.baseUrl },
16847
- model: options.model ?? DEFAULT_MODEL4,
16883
+ model: options.model ?? DEFAULT_MODEL3,
16848
16884
  systemPrompt: SYSTEM_PROMPT5,
16849
16885
  userMessage: `Memory content:
16850
16886
  ${safe}
@@ -17277,7 +17313,7 @@ init_logger();
17277
17313
  init_portalLlm();
17278
17314
  init_recall();
17279
17315
  var DEFAULT_BASE_URL2 = BASE_URL;
17280
- var DEFAULT_MODEL5 = "anthropic/claude-sonnet-4-6";
17316
+ var DEFAULT_MODEL4 = "anthropic/claude-sonnet-4-6";
17281
17317
  var DEFAULT_MAX_TOKENS = 4096;
17282
17318
  var REQUEST_TIMEOUT_MS = 6e4;
17283
17319
  var DEFAULT_SYSTEM_PROMPT = `You are a personal assistant with access to the user's memory. Answer the user's question using the supplied memories as evidence.
@@ -17309,7 +17345,7 @@ async function reflect(query, ctx, options) {
17309
17345
  const evidence = recalledMemories.map((m, i) => `[${i + 1}] (id: ${m.id}, kind: ${m.kind})
17310
17346
  ${m.content}`).join("\n\n");
17311
17347
  const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL2;
17312
- const model = options.llmModel ?? DEFAULT_MODEL5;
17348
+ const model = options.llmModel ?? DEFAULT_MODEL4;
17313
17349
  const wantsStructured = !!options.responseSchema;
17314
17350
  const sendResponseFormat = wantsStructured && supportsResponseFormat(model, "json_schema");
17315
17351
  const basePrompt = options.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;
@@ -125,6 +125,8 @@ import {
125
125
  postAuthOauthByProviderRefresh,
126
126
  postAuthOauthByProviderRevoke,
127
127
  preEmbedVaultMemories,
128
+ prepareVaultCandidates,
129
+ rankPreparedVaultCandidates,
128
130
  recall,
129
131
  replaceMemoryEntitiesGuardedOp,
130
132
  requestEncryptionKey,
@@ -153,7 +155,7 @@ import {
153
155
  updateVaultMemoryOp,
154
156
  useEncryption,
155
157
  vaultMemoryToStored
156
- } from "./chunk-P5ED24DP.mjs";
158
+ } from "./chunk-YGCJX5YW.mjs";
157
159
  import {
158
160
  PiiRedactor,
159
161
  createStreamingDeAnonymizer,
@@ -7181,9 +7183,25 @@ async function retain(content, ctx, options = {}) {
7181
7183
  const resolvedScope = options.scope ?? DEFAULT_SCOPE;
7182
7184
  let supersedeTargetIds = [];
7183
7185
  let supersedeContent;
7186
+ let prepared;
7184
7187
  if (enableAutoMerge) {
7188
+ prepared = await prepareVaultCandidates(
7189
+ trimmed,
7190
+ ctx.vaultCtx,
7191
+ ctx.embeddingOptions,
7192
+ ctx.vaultCache,
7193
+ {
7194
+ limit: Math.max(options.consolidateTopK ?? DEFAULT_CONSOLIDATE_TOP_K, 1),
7195
+ useFusion: false,
7196
+ scopes: [resolvedScope],
7197
+ // PR5 — include archived rows as merge candidates so a re-observed fact
7198
+ // resurrects (un-archives) the decayed row instead of duplicating it.
7199
+ includeArchived: true,
7200
+ ...options.folderId !== void 0 && { folderId: options.folderId }
7201
+ }
7202
+ );
7185
7203
  if (options.consolidateOptions) {
7186
- const outcome = await tryConsolidate(trimmed, ctx, options);
7204
+ const outcome = await tryConsolidate(trimmed, ctx, options, prepared);
7187
7205
  if (outcome) {
7188
7206
  if ("done" in outcome) return outcome.done;
7189
7207
  supersedeTargetIds = outcome.supersede;
@@ -7191,23 +7209,14 @@ async function retain(content, ctx, options = {}) {
7191
7209
  }
7192
7210
  }
7193
7211
  if (supersedeTargetIds.length === 0) {
7194
- const matches = await searchVaultMemories(
7212
+ const { results: matches } = await rankPreparedVaultCandidates(
7195
7213
  trimmed,
7196
- ctx.vaultCtx,
7214
+ prepared,
7197
7215
  ctx.embeddingOptions,
7198
- ctx.vaultCache,
7199
7216
  {
7200
7217
  limit: 1,
7201
7218
  minSimilarity: threshold,
7202
- useFusion: false,
7203
- scopes: [resolvedScope],
7204
- // PR5 — include archived rows as merge candidates so a re-observed
7205
- // fact resurrects (un-archives) the decayed row instead of creating a
7206
- // fresh duplicate. The resurrection is applied on the merge write
7207
- // below, but ONLY for a row that is not superseded/deleted (the
7208
- // guards below preserve main's tombstone/supersession suppression).
7209
- includeArchived: true,
7210
- ...options.folderId !== void 0 && { folderId: options.folderId }
7219
+ useFusion: false
7211
7220
  }
7212
7221
  );
7213
7222
  if (matches.length > 0) {
@@ -7255,7 +7264,8 @@ async function retain(content, ctx, options = {}) {
7255
7264
  }
7256
7265
  }
7257
7266
  const contentToWrite = supersedeContent ?? trimmed;
7258
- const embedding = await generateEmbedding(contentToWrite, ctx.embeddingOptions);
7267
+ const reusableQueryEmbedding = supersedeContent === void 0 && prepared && prepared.queryEmbedding.length > 0 ? prepared.queryEmbedding : void 0;
7268
+ const embedding = reusableQueryEmbedding ?? await generateEmbedding(contentToWrite, ctx.embeddingOptions);
7259
7269
  const embeddingModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
7260
7270
  if (options.respectTombstones) {
7261
7271
  const tombstoneId = await findTombstoneMatch(embedding, embeddingModel, resolvedScope, ctx, {
@@ -7384,26 +7394,19 @@ function pickFactTypeUpdate(existing, incoming) {
7384
7394
  function resurrectFields(existing) {
7385
7395
  return typeof existing.archivedAt === "number" ? { restore: true } : { preserveUpdatedAt: true };
7386
7396
  }
7387
- async function tryConsolidate(trimmed, ctx, options) {
7397
+ async function tryConsolidate(trimmed, ctx, options, prepared) {
7388
7398
  const consolidateOptions = options.consolidateOptions;
7389
7399
  if (!consolidateOptions) return null;
7390
7400
  const consolidateThreshold = options.consolidateThreshold ?? DEFAULT_CONSOLIDATE_THRESHOLD;
7391
7401
  const topK = options.consolidateTopK ?? DEFAULT_CONSOLIDATE_TOP_K;
7392
- const resolvedScope = options.scope ?? DEFAULT_SCOPE;
7393
- const matches = await searchVaultMemories(
7402
+ const { results: matches } = await rankPreparedVaultCandidates(
7394
7403
  trimmed,
7395
- ctx.vaultCtx,
7404
+ prepared,
7396
7405
  ctx.embeddingOptions,
7397
- ctx.vaultCache,
7398
7406
  {
7399
7407
  limit: topK,
7400
7408
  minSimilarity: consolidateThreshold,
7401
- useFusion: false,
7402
- scopes: [resolvedScope],
7403
- // PR5 — archived rows are consolidation candidates too, so a paraphrased
7404
- // re-observation resurrects a decayed row rather than duplicating it.
7405
- includeArchived: true,
7406
- ...options.folderId !== void 0 && { folderId: options.folderId }
7409
+ useFusion: false
7407
7410
  }
7408
7411
  );
7409
7412
  if (matches.length === 0) return null;
@@ -7412,7 +7415,7 @@ async function tryConsolidate(trimmed, ctx, options) {
7412
7415
  content: m.content,
7413
7416
  similarity: m.similarity
7414
7417
  }));
7415
- const { consolidateMemory: doConsolidate } = await import("./consolidate-7UUX56GM.mjs");
7418
+ const { consolidateMemory: doConsolidate } = await import("./consolidate-54UWIMP6.mjs");
7416
7419
  const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
7417
7420
  if (decision.action === "create") return null;
7418
7421
  if (decision.action === "supersede" && decision.content) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  recall
3
- } from "./chunk-4VXLX7SL.mjs";
3
+ } from "./chunk-YGCJX5YW.mjs";
4
4
  import "./chunk-BOY27A2C.mjs";
5
5
  import "./chunk-GYKJOWEO.mjs";
6
6
  export {