@anuma/sdk 3.9.3 → 3.9.5

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.
@@ -20053,6 +20053,14 @@ var init_lruCache = __esm({
20053
20053
  });
20054
20054
 
20055
20055
  // src/lib/memory/queryEntities.ts
20056
+ function hasMeaningfulCandidate(candidates) {
20057
+ for (const candidate of candidates) {
20058
+ if (!candidate.split(/\s+/).every((token) => FALLBACK_STOPWORDS.has(token))) {
20059
+ return true;
20060
+ }
20061
+ }
20062
+ return false;
20063
+ }
20056
20064
  function extractQueryEntities(query) {
20057
20065
  if (!query) return [];
20058
20066
  const matches = query.matchAll(ENTITY_REGEX);
@@ -20068,9 +20076,27 @@ function extractQueryEntities(query) {
20068
20076
  seen.add(candidate);
20069
20077
  }
20070
20078
  }
20071
- return [...seen];
20079
+ if (hasMeaningfulCandidate(seen)) return [...seen];
20080
+ return [.../* @__PURE__ */ new Set([...extractFallbackCandidates(query), ...seen])];
20072
20081
  }
20073
- var STOPWORDS2, ENTITY_REGEX;
20082
+ function extractFallbackCandidates(query) {
20083
+ const tokens = (query.match(/\p{L}[\p{L}'-]*/gu) ?? []).map(normalizeEntityName);
20084
+ const out = [];
20085
+ const seen = /* @__PURE__ */ new Set();
20086
+ for (let n = 1; n <= MAX_FALLBACK_TOKENS; n++) {
20087
+ for (let start = 0; start + n <= tokens.length; start++) {
20088
+ const gram = tokens.slice(start, start + n);
20089
+ if (gram.some((t) => t.length < 2 || FALLBACK_STOPWORDS.has(t))) continue;
20090
+ const candidate = gram.join(" ");
20091
+ if (seen.has(candidate)) continue;
20092
+ seen.add(candidate);
20093
+ out.push(candidate);
20094
+ if (out.length >= MAX_FALLBACK_CANDIDATES) return out;
20095
+ }
20096
+ }
20097
+ return out;
20098
+ }
20099
+ var STOPWORDS2, ENTITY_REGEX, FALLBACK_ONLY_STOPWORDS, FALLBACK_STOPWORDS, MAX_FALLBACK_CANDIDATES, MAX_FALLBACK_TOKENS;
20074
20100
  var init_queryEntities = __esm({
20075
20101
  "src/lib/memory/queryEntities.ts"() {
20076
20102
  "use strict";
@@ -20122,6 +20148,10 @@ var init_queryEntities = __esm({
20122
20148
  ].map((w) => w.toLowerCase())
20123
20149
  );
20124
20150
  ENTITY_REGEX = /\b\p{Lu}[\p{L}'-]{2,}(?:\s+\p{Lu}[\p{L}'-]+){0,2}\b/gu;
20151
+ FALLBACK_ONLY_STOPWORDS = "a an and or but nor not if then than because so too also just very really about above after again against all am any anyone anybody anything are around as at be been being before behind below between both by can cannot could currently did do does doing done down during each ever every everybody everyone everything few find finds finding for from get gets getting go goes going gone got had has have having he help her here hers him his hmm i in into is it its knew know knows later like liked likes live lived lives living look looked looking looks made make makes may me meet meets might mine more most must my near need needed needs never nobody nothing now of off okay on once only onto other our ours out over own people person please recently said same say says see seen shall she should since some somebody someone something soon still such talk tell tells thank that the their theirs them there these they think thinks this those thought through to today told tomorrow under until up us want wanted wants was we went were which while will with without work worked working works would yeah year years yep yesterday you your yours aren't can't couldn't didn't doesn't don't hadn't hasn't haven't he's how's i'd i'll i'm i've isn't it's let's she's shouldn't that's there's they're they've wasn't we're we've weren't what's when's where's who's why's won't wouldn't you'll you're you've".split(" ");
20152
+ FALLBACK_STOPWORDS = /* @__PURE__ */ new Set([...STOPWORDS2, ...FALLBACK_ONLY_STOPWORDS]);
20153
+ MAX_FALLBACK_CANDIDATES = 12;
20154
+ MAX_FALLBACK_TOKENS = 3;
20125
20155
  }
20126
20156
  });
20127
20157
 
@@ -21575,13 +21605,12 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
21575
21605
  }));
21576
21606
  return { memories, embeddedItems, queryEmbedding, vaultSize };
21577
21607
  }
21578
- async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, cache, searchOptions) {
21579
- const limit = searchOptions?.limit ?? 5;
21580
- const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
21581
- const scopes = searchOptions?.scopes;
21608
+ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache, searchOptions) {
21582
21609
  if (!query || typeof query !== "string") {
21583
- return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
21610
+ return { memories: [], embeddedItems: [], queryEmbedding: [], vaultSize: 0 };
21584
21611
  }
21612
+ const limit = searchOptions?.limit ?? 5;
21613
+ const scopes = searchOptions?.scopes;
21585
21614
  const folderId = searchOptions?.folderId;
21586
21615
  const queryOpts = {};
21587
21616
  if (scopes?.length) queryOpts.scopes = scopes;
@@ -21608,11 +21637,11 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
21608
21637
  ...forceIncludeIds.length > 0 && { forceIncludeIds }
21609
21638
  });
21610
21639
  if (corpus.vaultSize === 0) {
21611
- return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
21640
+ return { memories: [], embeddedItems: [], queryEmbedding: [], vaultSize: 0 };
21612
21641
  }
21613
21642
  ({ memories, embeddedItems, queryEmbedding, vaultSize } = corpus);
21614
21643
  if (memories.length === 0) {
21615
- return { results: [], vaultSize, reranked: false, hadV2Head: false };
21644
+ return { memories: [], embeddedItems: [], queryEmbedding: [], vaultSize };
21616
21645
  }
21617
21646
  } else {
21618
21647
  const loaded = await getAllVaultMemoriesOp(
@@ -21627,7 +21656,7 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
21627
21656
  );
21628
21657
  }
21629
21658
  if (memories.length === 0) {
21630
- return { results: [], vaultSize: loaded.length, reranked: false, hadV2Head: false };
21659
+ return { memories: [], embeddedItems: [], queryEmbedding: [], vaultSize: loaded.length };
21631
21660
  }
21632
21661
  queryEmbedding = await generateEmbedding(query, embeddingOptions);
21633
21662
  const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
@@ -21692,6 +21721,12 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
21692
21721
  factType: m.factType
21693
21722
  }));
21694
21723
  }
21724
+ return { memories, embeddedItems, queryEmbedding, vaultSize };
21725
+ }
21726
+ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, searchOptions) {
21727
+ const limit = searchOptions?.limit ?? 5;
21728
+ const minSimilarity = searchOptions?.minSimilarity ?? 0.1;
21729
+ const { memories, embeddedItems, queryEmbedding, vaultSize } = prepared;
21695
21730
  if (queryEmbedding.length > 0) {
21696
21731
  const mismatched = embeddedItems.filter(
21697
21732
  (it) => it.embedding.length > 0 && it.embedding.length !== queryEmbedding.length
@@ -21829,6 +21864,25 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
21829
21864
  });
21830
21865
  return stampTimestamps({ results, vaultSize, hadV2Head: results.length > 0 });
21831
21866
  }
21867
+ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, cache, searchOptions) {
21868
+ if (!query || typeof query !== "string") {
21869
+ return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
21870
+ }
21871
+ const prepared = await prepareVaultCandidates(
21872
+ query,
21873
+ vaultCtx,
21874
+ embeddingOptions,
21875
+ cache,
21876
+ searchOptions
21877
+ );
21878
+ if (prepared.vaultSize === 0) {
21879
+ return { results: [], vaultSize: 0, reranked: false, hadV2Head: false };
21880
+ }
21881
+ if (prepared.memories.length === 0) {
21882
+ return { results: [], vaultSize: prepared.vaultSize, reranked: false, hadV2Head: false };
21883
+ }
21884
+ return rankPreparedVaultCandidates(query, prepared, embeddingOptions, searchOptions);
21885
+ }
21832
21886
  async function searchVaultMemories(query, vaultCtx, embeddingOptions, cache, searchOptions) {
21833
21887
  const { results } = await searchVaultMemoriesWithSize(
21834
21888
  query,
@@ -27609,9 +27663,25 @@ async function retain(content, ctx, options = {}) {
27609
27663
  const resolvedScope = options.scope ?? DEFAULT_SCOPE;
27610
27664
  let supersedeTargetIds = [];
27611
27665
  let supersedeContent;
27666
+ let prepared;
27612
27667
  if (enableAutoMerge) {
27668
+ prepared = await prepareVaultCandidates(
27669
+ trimmed,
27670
+ ctx.vaultCtx,
27671
+ ctx.embeddingOptions,
27672
+ ctx.vaultCache,
27673
+ {
27674
+ limit: Math.max(options.consolidateTopK ?? DEFAULT_CONSOLIDATE_TOP_K, 1),
27675
+ useFusion: false,
27676
+ scopes: [resolvedScope],
27677
+ // PR5 — include archived rows as merge candidates so a re-observed fact
27678
+ // resurrects (un-archives) the decayed row instead of duplicating it.
27679
+ includeArchived: true,
27680
+ ...options.folderId !== void 0 && { folderId: options.folderId }
27681
+ }
27682
+ );
27613
27683
  if (options.consolidateOptions) {
27614
- const outcome = await tryConsolidate(trimmed, ctx, options);
27684
+ const outcome = await tryConsolidate(trimmed, ctx, options, prepared);
27615
27685
  if (outcome) {
27616
27686
  if ("done" in outcome) return outcome.done;
27617
27687
  supersedeTargetIds = outcome.supersede;
@@ -27619,23 +27689,14 @@ async function retain(content, ctx, options = {}) {
27619
27689
  }
27620
27690
  }
27621
27691
  if (supersedeTargetIds.length === 0) {
27622
- const matches = await searchVaultMemories(
27692
+ const { results: matches } = await rankPreparedVaultCandidates(
27623
27693
  trimmed,
27624
- ctx.vaultCtx,
27694
+ prepared,
27625
27695
  ctx.embeddingOptions,
27626
- ctx.vaultCache,
27627
27696
  {
27628
27697
  limit: 1,
27629
27698
  minSimilarity: threshold,
27630
- useFusion: false,
27631
- scopes: [resolvedScope],
27632
- // PR5 — include archived rows as merge candidates so a re-observed
27633
- // fact resurrects (un-archives) the decayed row instead of creating a
27634
- // fresh duplicate. The resurrection is applied on the merge write
27635
- // below, but ONLY for a row that is not superseded/deleted (the
27636
- // guards below preserve main's tombstone/supersession suppression).
27637
- includeArchived: true,
27638
- ...options.folderId !== void 0 && { folderId: options.folderId }
27699
+ useFusion: false
27639
27700
  }
27640
27701
  );
27641
27702
  if (matches.length > 0) {
@@ -27683,7 +27744,8 @@ async function retain(content, ctx, options = {}) {
27683
27744
  }
27684
27745
  }
27685
27746
  const contentToWrite = supersedeContent ?? trimmed;
27686
- const embedding = await generateEmbedding(contentToWrite, ctx.embeddingOptions);
27747
+ const reusableQueryEmbedding = supersedeContent === void 0 && prepared && prepared.queryEmbedding.length > 0 ? prepared.queryEmbedding : void 0;
27748
+ const embedding = reusableQueryEmbedding ?? await generateEmbedding(contentToWrite, ctx.embeddingOptions);
27687
27749
  const embeddingModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
27688
27750
  if (options.respectTombstones) {
27689
27751
  const tombstoneId = await findTombstoneMatch(embedding, embeddingModel, resolvedScope, ctx, {
@@ -27812,26 +27874,19 @@ function pickFactTypeUpdate(existing, incoming) {
27812
27874
  function resurrectFields(existing) {
27813
27875
  return typeof existing.archivedAt === "number" ? { restore: true } : { preserveUpdatedAt: true };
27814
27876
  }
27815
- async function tryConsolidate(trimmed, ctx, options) {
27877
+ async function tryConsolidate(trimmed, ctx, options, prepared) {
27816
27878
  const consolidateOptions = options.consolidateOptions;
27817
27879
  if (!consolidateOptions) return null;
27818
27880
  const consolidateThreshold = options.consolidateThreshold ?? DEFAULT_CONSOLIDATE_THRESHOLD;
27819
27881
  const topK = options.consolidateTopK ?? DEFAULT_CONSOLIDATE_TOP_K;
27820
- const resolvedScope = options.scope ?? DEFAULT_SCOPE;
27821
- const matches = await searchVaultMemories(
27882
+ const { results: matches } = await rankPreparedVaultCandidates(
27822
27883
  trimmed,
27823
- ctx.vaultCtx,
27884
+ prepared,
27824
27885
  ctx.embeddingOptions,
27825
- ctx.vaultCache,
27826
27886
  {
27827
27887
  limit: topK,
27828
27888
  minSimilarity: consolidateThreshold,
27829
- useFusion: false,
27830
- scopes: [resolvedScope],
27831
- // PR5 — archived rows are consolidation candidates too, so a paraphrased
27832
- // re-observation resurrects a decayed row rather than duplicating it.
27833
- includeArchived: true,
27834
- ...options.folderId !== void 0 && { folderId: options.folderId }
27889
+ useFusion: false
27835
27890
  }
27836
27891
  );
27837
27892
  if (matches.length === 0) return null;
@@ -88,6 +88,8 @@ import {
88
88
  onClearAllEncryptionState,
89
89
  onKeyAvailable,
90
90
  preEmbedVaultMemories,
91
+ prepareVaultCandidates,
92
+ rankPreparedVaultCandidates,
91
93
  recall,
92
94
  replaceMemoryEntitiesGuardedOp,
93
95
  requestEncryptionKey,
@@ -125,7 +127,7 @@ import {
125
127
  updateVaultMemoryOp,
126
128
  upsertMessageOp,
127
129
  vaultMemoryToStored
128
- } from "./chunk-ICGTS7X6.mjs";
130
+ } from "./chunk-UU2F523R.mjs";
129
131
  import {
130
132
  createStreamingDeAnonymizer,
131
133
  resolvePiiRedactor
@@ -5265,9 +5267,25 @@ async function retain(content, ctx, options = {}) {
5265
5267
  const resolvedScope = options.scope ?? DEFAULT_SCOPE;
5266
5268
  let supersedeTargetIds = [];
5267
5269
  let supersedeContent;
5270
+ let prepared;
5268
5271
  if (enableAutoMerge) {
5272
+ prepared = await prepareVaultCandidates(
5273
+ trimmed,
5274
+ ctx.vaultCtx,
5275
+ ctx.embeddingOptions,
5276
+ ctx.vaultCache,
5277
+ {
5278
+ limit: Math.max(options.consolidateTopK ?? DEFAULT_CONSOLIDATE_TOP_K, 1),
5279
+ useFusion: false,
5280
+ scopes: [resolvedScope],
5281
+ // PR5 — include archived rows as merge candidates so a re-observed fact
5282
+ // resurrects (un-archives) the decayed row instead of duplicating it.
5283
+ includeArchived: true,
5284
+ ...options.folderId !== void 0 && { folderId: options.folderId }
5285
+ }
5286
+ );
5269
5287
  if (options.consolidateOptions) {
5270
- const outcome = await tryConsolidate(trimmed, ctx, options);
5288
+ const outcome = await tryConsolidate(trimmed, ctx, options, prepared);
5271
5289
  if (outcome) {
5272
5290
  if ("done" in outcome) return outcome.done;
5273
5291
  supersedeTargetIds = outcome.supersede;
@@ -5275,23 +5293,14 @@ async function retain(content, ctx, options = {}) {
5275
5293
  }
5276
5294
  }
5277
5295
  if (supersedeTargetIds.length === 0) {
5278
- const matches = await searchVaultMemories(
5296
+ const { results: matches } = await rankPreparedVaultCandidates(
5279
5297
  trimmed,
5280
- ctx.vaultCtx,
5298
+ prepared,
5281
5299
  ctx.embeddingOptions,
5282
- ctx.vaultCache,
5283
5300
  {
5284
5301
  limit: 1,
5285
5302
  minSimilarity: threshold,
5286
- useFusion: false,
5287
- scopes: [resolvedScope],
5288
- // PR5 — include archived rows as merge candidates so a re-observed
5289
- // fact resurrects (un-archives) the decayed row instead of creating a
5290
- // fresh duplicate. The resurrection is applied on the merge write
5291
- // below, but ONLY for a row that is not superseded/deleted (the
5292
- // guards below preserve main's tombstone/supersession suppression).
5293
- includeArchived: true,
5294
- ...options.folderId !== void 0 && { folderId: options.folderId }
5303
+ useFusion: false
5295
5304
  }
5296
5305
  );
5297
5306
  if (matches.length > 0) {
@@ -5339,7 +5348,8 @@ async function retain(content, ctx, options = {}) {
5339
5348
  }
5340
5349
  }
5341
5350
  const contentToWrite = supersedeContent ?? trimmed;
5342
- const embedding = await generateEmbedding(contentToWrite, ctx.embeddingOptions);
5351
+ const reusableQueryEmbedding = supersedeContent === void 0 && prepared && prepared.queryEmbedding.length > 0 ? prepared.queryEmbedding : void 0;
5352
+ const embedding = reusableQueryEmbedding ?? await generateEmbedding(contentToWrite, ctx.embeddingOptions);
5343
5353
  const embeddingModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
5344
5354
  if (options.respectTombstones) {
5345
5355
  const tombstoneId = await findTombstoneMatch(embedding, embeddingModel, resolvedScope, ctx, {
@@ -5468,26 +5478,19 @@ function pickFactTypeUpdate(existing, incoming) {
5468
5478
  function resurrectFields(existing) {
5469
5479
  return typeof existing.archivedAt === "number" ? { restore: true } : { preserveUpdatedAt: true };
5470
5480
  }
5471
- async function tryConsolidate(trimmed, ctx, options) {
5481
+ async function tryConsolidate(trimmed, ctx, options, prepared) {
5472
5482
  const consolidateOptions = options.consolidateOptions;
5473
5483
  if (!consolidateOptions) return null;
5474
5484
  const consolidateThreshold = options.consolidateThreshold ?? DEFAULT_CONSOLIDATE_THRESHOLD;
5475
5485
  const topK = options.consolidateTopK ?? DEFAULT_CONSOLIDATE_TOP_K;
5476
- const resolvedScope = options.scope ?? DEFAULT_SCOPE;
5477
- const matches = await searchVaultMemories(
5486
+ const { results: matches } = await rankPreparedVaultCandidates(
5478
5487
  trimmed,
5479
- ctx.vaultCtx,
5488
+ prepared,
5480
5489
  ctx.embeddingOptions,
5481
- ctx.vaultCache,
5482
5490
  {
5483
5491
  limit: topK,
5484
5492
  minSimilarity: consolidateThreshold,
5485
- useFusion: false,
5486
- scopes: [resolvedScope],
5487
- // PR5 — archived rows are consolidation candidates too, so a paraphrased
5488
- // re-observation resurrects a decayed row rather than duplicating it.
5489
- includeArchived: true,
5490
- ...options.folderId !== void 0 && { folderId: options.folderId }
5493
+ useFusion: false
5491
5494
  }
5492
5495
  );
5493
5496
  if (matches.length === 0) return null;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  recall
3
- } from "./chunk-ICGTS7X6.mjs";
3
+ } from "./chunk-UU2F523R.mjs";
4
4
  import "./chunk-MIXEASUP.mjs";
5
5
  import "./chunk-3RPGXXPZ.mjs";
6
6
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anuma/sdk",
3
- "version": "3.9.3",
3
+ "version": "3.9.5",
4
4
  "description": "",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",