@anuma/sdk 9.1.4 → 9.1.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.
@@ -2520,15 +2520,16 @@ async function refreshEncryptionKeyIfMatches(walletAddress, probeCiphertext, sig
2520
2520
  if (!parsed) {
2521
2521
  return false;
2522
2522
  }
2523
+ const startEpoch = sessionEpoch;
2523
2524
  const cached = refreshCandidatesByAddress.get(walletAddress);
2524
2525
  if (cached) {
2525
- return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, cached);
2526
+ return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, cached, startEpoch);
2526
2527
  }
2527
2528
  let derivePromise = pendingCandidateDerives.get(walletAddress);
2528
2529
  if (!derivePromise) {
2529
2530
  derivePromise = (async () => {
2530
2531
  const candidates2 = await deriveRefreshCandidates(signMessage, embeddedWalletSigner);
2531
- if (candidates2) {
2532
+ if (candidates2 && sessionEpoch === startEpoch) {
2532
2533
  refreshCandidatesByAddress.set(walletAddress, candidates2);
2533
2534
  }
2534
2535
  return candidates2;
@@ -2540,10 +2541,10 @@ async function refreshEncryptionKeyIfMatches(walletAddress, probeCiphertext, sig
2540
2541
  pendingCandidateDerives.set(walletAddress, derivePromise);
2541
2542
  }
2542
2543
  const candidates = await derivePromise;
2543
- if (!candidates) {
2544
+ if (!candidates || sessionEpoch !== startEpoch) {
2544
2545
  return false;
2545
2546
  }
2546
- return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates);
2547
+ return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates, startEpoch);
2547
2548
  }
2548
2549
  function parsePrefixedCiphertext(probeCiphertext) {
2549
2550
  const version = probeCiphertext.startsWith("enc:v3:") ? "v3" : probeCiphertext.startsWith("enc:v2:") ? "v2" : null;
@@ -2586,7 +2587,7 @@ async function deriveRefreshCandidates(signMessage, embeddedWalletSigner) {
2586
2587
  }
2587
2588
  return { legacy: legacyKey, current: currentKey };
2588
2589
  }
2589
- async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates) {
2590
+ async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates, startEpoch) {
2590
2591
  const candidateHex = parsed.version === "v2" ? candidates.legacy : candidates.current;
2591
2592
  const keyBytes = hexToBytes(candidateHex);
2592
2593
  const candidateCryptoKey = await crypto.subtle.importKey(
@@ -2604,6 +2605,9 @@ async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidat
2604
2605
  );
2605
2606
  return false;
2606
2607
  }
2608
+ if (sessionEpoch !== startEpoch) {
2609
+ return false;
2610
+ }
2607
2611
  setStoredKey(walletAddress, { legacy: candidates.legacy, current: candidates.current });
2608
2612
  cryptoKeyCache.delete(`${walletAddress}:v2`);
2609
2613
  cryptoKeyCache.delete(`${walletAddress}:v3`);
@@ -17284,6 +17288,104 @@ function validate(parsed, originalQuery) {
17284
17288
  return { mode, subQueries };
17285
17289
  }
17286
17290
 
17291
+ // src/lib/memoryVault/vaultPreparation.ts
17292
+ function createVaultPreparation() {
17293
+ return { corpora: /* @__PURE__ */ new WeakMap(), rows: /* @__PURE__ */ new WeakMap() };
17294
+ }
17295
+ var pendingRows = /* @__PURE__ */ new WeakMap();
17296
+ function loadVaultCorpus(ctx, options, preparation) {
17297
+ if (!preparation) return getAllVaultMemoriesOp(ctx, options);
17298
+ const corpusCache = preparation.corpora;
17299
+ let pending = corpusCache.get(ctx);
17300
+ if (!pending) {
17301
+ pending = /* @__PURE__ */ new Map();
17302
+ corpusCache.set(ctx, pending);
17303
+ }
17304
+ const key = JSON.stringify(options ?? {});
17305
+ let request = pending.get(key);
17306
+ if (!request) {
17307
+ const entries = pending;
17308
+ request = getAllVaultMemoriesOp(ctx, options).catch((error) => {
17309
+ entries.delete(key);
17310
+ throw error;
17311
+ });
17312
+ pending.set(key, request);
17313
+ }
17314
+ return request;
17315
+ }
17316
+ function rowRequestsFor(registry2, ctx, maskInput) {
17317
+ let byMask = registry2.get(ctx);
17318
+ if (!byMask) {
17319
+ byMask = /* @__PURE__ */ new Map();
17320
+ registry2.set(ctx, byMask);
17321
+ }
17322
+ let requests = byMask.get(maskInput);
17323
+ if (!requests) {
17324
+ requests = /* @__PURE__ */ new Map();
17325
+ byMask.set(maskInput, requests);
17326
+ }
17327
+ return requests;
17328
+ }
17329
+ function embedVaultRows(ctx, options, rows, preparation) {
17330
+ const pending = rowRequestsFor(pendingRows, ctx, options.maskInput);
17331
+ const prepared = preparation && rowRequestsFor(preparation.rows, ctx, options.maskInput);
17332
+ const model = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
17333
+ const keys = rows.map(
17334
+ (row) => JSON.stringify([
17335
+ row.uniqueId,
17336
+ row.updatedAt?.getTime(),
17337
+ row.content,
17338
+ model,
17339
+ options.baseUrl,
17340
+ options.timeoutMs,
17341
+ options.tokenTimeoutMs,
17342
+ options.totalTimeoutMs
17343
+ ])
17344
+ );
17345
+ const missing = /* @__PURE__ */ new Map();
17346
+ rows.forEach((row, index) => {
17347
+ if (!pending.has(keys[index]) && !prepared?.has(keys[index])) missing.set(keys[index], row);
17348
+ });
17349
+ if (missing.size > 0) {
17350
+ const entries = pending;
17351
+ const batch = Promise.resolve().then(
17352
+ () => generateEmbeddings(
17353
+ [...missing.values()].map((row) => row.content),
17354
+ options
17355
+ )
17356
+ );
17357
+ [...missing].forEach(([key, row], index) => {
17358
+ const request = batch.then((vectors) => {
17359
+ const vector = vectors[index];
17360
+ updateVaultMemoryEmbeddingOp(ctx, row.uniqueId, JSON.stringify(vector), model, {
17361
+ content: row.content,
17362
+ updatedAt: row.updatedAt?.getTime()
17363
+ }).catch(() => {
17364
+ });
17365
+ return vector;
17366
+ }).finally(() => {
17367
+ entries.delete(key);
17368
+ if (entries.size === 0) pendingRows.get(ctx)?.delete(options.maskInput);
17369
+ });
17370
+ pending.set(key, request);
17371
+ });
17372
+ }
17373
+ return Promise.all(
17374
+ keys.map((key) => {
17375
+ const cached = prepared?.get(key);
17376
+ if (cached) return cached;
17377
+ const request = pending.get(key);
17378
+ if (!prepared) return request;
17379
+ const retained = request.catch((error) => {
17380
+ prepared.delete(key);
17381
+ throw error;
17382
+ });
17383
+ prepared.set(key, retained);
17384
+ return retained;
17385
+ })
17386
+ );
17387
+ }
17388
+
17287
17389
  // src/lib/memoryVault/vectorVersion.ts
17288
17390
  var vectorRowVersion = /* @__PURE__ */ new WeakMap();
17289
17391
  function contentFingerprint(content) {
@@ -17846,11 +17948,11 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
17846
17948
  return combined.slice(0, limit);
17847
17949
  }
17848
17950
  async function preEmbedVaultMemories(vaultCtx, embeddingOptions, cache, options) {
17849
- const memories = await getAllVaultMemoriesOp(vaultCtx, options);
17951
+ const memories = await loadVaultCorpus(vaultCtx, options);
17850
17952
  const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
17851
17953
  const uncachedTexts = [];
17852
17954
  const uncachedKeys = [];
17853
- const uncachedIds = [];
17955
+ const uncachedRows = [];
17854
17956
  const uncachedVersions = [];
17855
17957
  for (const m of memories) {
17856
17958
  const content = m.content;
@@ -17869,12 +17971,12 @@ async function preEmbedVaultMemories(vaultCtx, embeddingOptions, cache, options)
17869
17971
  }
17870
17972
  uncachedTexts.push(m.content);
17871
17973
  uncachedKeys.push(m.uniqueId);
17872
- uncachedIds.push(m.uniqueId);
17974
+ uncachedRows.push(m);
17873
17975
  uncachedVersions.push(m.updatedAt);
17874
17976
  }
17875
17977
  }
17876
17978
  if (uncachedTexts.length > 0) {
17877
- const embeddings = await generateEmbeddings(uncachedTexts, embeddingOptions);
17979
+ const embeddings = await embedVaultRows(vaultCtx, embeddingOptions, uncachedRows);
17878
17980
  for (let i = 0; i < uncachedKeys.length; i++) {
17879
17981
  cacheRowVector(
17880
17982
  cache,
@@ -17883,13 +17985,6 @@ async function preEmbedVaultMemories(vaultCtx, embeddingOptions, cache, options)
17883
17985
  uncachedVersions[i],
17884
17986
  uncachedTexts[i]
17885
17987
  );
17886
- updateVaultMemoryEmbeddingOp(
17887
- vaultCtx,
17888
- uncachedIds[i],
17889
- JSON.stringify(embeddings[i]),
17890
- currentModel
17891
- ).catch(() => {
17892
- });
17893
17988
  }
17894
17989
  }
17895
17990
  }
@@ -18031,10 +18126,7 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
18031
18126
  let laneVecs;
18032
18127
  if (opts.embedStats) opts.embedStats.rowsEmbedded += laneRows.length;
18033
18128
  try {
18034
- laneVecs = await generateEmbeddings(
18035
- laneRows.map((m) => m.content),
18036
- embeddingOptions
18037
- );
18129
+ laneVecs = await embedVaultRows(vaultCtx, embeddingOptions, laneRows);
18038
18130
  } catch (err) {
18039
18131
  laneEmbedFailed = true;
18040
18132
  getLogger().warn(
@@ -18048,13 +18140,6 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
18048
18140
  cacheRowVector(cache, m.uniqueId, vec, m.updatedAt, m.content);
18049
18141
  resolvedThisCall.add(m.uniqueId);
18050
18142
  vectored.push({ uniqueId: m.uniqueId, embedding: vec, updatedAt: m.updatedAt });
18051
- updateVaultMemoryEmbeddingOp(
18052
- vaultCtx,
18053
- m.uniqueId,
18054
- JSON.stringify(vecs[i]),
18055
- currentModel
18056
- ).catch(() => {
18057
- });
18058
18143
  });
18059
18144
  }
18060
18145
  }
@@ -18246,9 +18331,10 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
18246
18331
  };
18247
18332
  }
18248
18333
  } else {
18249
- const loaded = await getAllVaultMemoriesOp(
18334
+ const loaded = await loadVaultCorpus(
18250
18335
  vaultCtx,
18251
- Object.keys(queryOpts).length > 0 ? queryOpts : void 0
18336
+ Object.keys(queryOpts).length > 0 ? queryOpts : void 0,
18337
+ searchOptions?.vaultPreparation
18252
18338
  );
18253
18339
  vaultSize = loaded.length;
18254
18340
  rowsDecrypted = loaded.length;
@@ -18321,7 +18407,12 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
18321
18407
  let newEmbeddings;
18322
18408
  embedStats.rowsEmbedded += uncachedTexts.length;
18323
18409
  try {
18324
- newEmbeddings = await generateEmbeddings(uncachedTexts, embeddingOptions);
18410
+ newEmbeddings = await embedVaultRows(
18411
+ vaultCtx,
18412
+ embeddingOptions,
18413
+ uncachedIndices.map((index) => memories[index]),
18414
+ searchOptions?.vaultPreparation
18415
+ );
18325
18416
  } catch (err) {
18326
18417
  embeddingFailure = true;
18327
18418
  getLogger().warn(
@@ -18337,13 +18428,6 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
18337
18428
  memories[uncachedIndices[j]].updatedAt,
18338
18429
  memories[uncachedIndices[j]].content
18339
18430
  );
18340
- updateVaultMemoryEmbeddingOp(
18341
- vaultCtx,
18342
- memories[uncachedIndices[j]].uniqueId,
18343
- JSON.stringify(newEmbeddings[j]),
18344
- currentModel
18345
- ).catch(() => {
18346
- });
18347
18431
  }
18348
18432
  }
18349
18433
  }
@@ -20898,6 +20982,7 @@ async function recall(query, ctx, options = {}) {
20898
20982
  },
20899
20983
  ...options.rrfK !== void 0 && { rrfK: options.rrfK },
20900
20984
  ...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
20985
+ ...options.vaultPreparation && { vaultPreparation: options.vaultPreparation },
20901
20986
  ...subQueries && { subQueries },
20902
20987
  ...options.scopes && { scopes: options.scopes },
20903
20988
  ...options.folderId !== void 0 && { folderId: options.folderId },
@@ -24503,13 +24588,20 @@ async function synthesizeProfile(ctx, options = {}) {
24503
24588
  }
24504
24589
  }
24505
24590
  }
24591
+ const vaultPreparation = createVaultPreparation();
24506
24592
  const settled = await Promise.allSettled(
24507
24593
  facets.map(async (facet) => {
24508
24594
  const prior = previous?.sections.find((s) => s.key === facet.key);
24509
24595
  if (prior && !staleKeys.has(facet.key)) {
24510
24596
  return prior;
24511
24597
  }
24512
- return synthesizeFacet(facet, recallCtx, options, fallbackPriors.get(facet.key));
24598
+ return synthesizeFacet(
24599
+ facet,
24600
+ recallCtx,
24601
+ options,
24602
+ fallbackPriors.get(facet.key),
24603
+ vaultPreparation
24604
+ );
24513
24605
  })
24514
24606
  );
24515
24607
  const sections = settled.map((r, i) => {
@@ -24663,7 +24755,7 @@ async function attributeFacts(ctx, candidates, facets) {
24663
24755
  }
24664
24756
  return keys;
24665
24757
  }
24666
- async function synthesizeFacet(facet, ctx, options, prior) {
24758
+ async function synthesizeFacet(facet, ctx, options, prior, vaultPreparation) {
24667
24759
  const scopes = options.scopes ?? DEFAULT_SCOPES;
24668
24760
  const limit = options.limit ?? DEFAULT_FACET_RECALL_LIMIT;
24669
24761
  const factTypeWeights = { ...DEFAULT_PROFILE_FACT_TYPE_WEIGHTS, ...options.factTypeWeights };
@@ -24680,6 +24772,7 @@ async function synthesizeFacet(facet, ctx, options, prior) {
24680
24772
  };
24681
24773
  }
24682
24774
  const recalled = await recall(facet.query, ctx, {
24775
+ vaultPreparation,
24683
24776
  scopes,
24684
24777
  limit: hasReviewGate ? RECALL_MAX_LIMIT : limit,
24685
24778
  types: ["fact"],
@@ -3902,6 +3902,13 @@ interface RecencyOptions {
3902
3902
  noDateMultiplier?: number;
3903
3903
  }
3904
3904
 
3905
+ type VaultCorpusCache = WeakMap<VaultMemoryOperationsContext, Map<string, Promise<StoredVaultMemory[]>>>;
3906
+ type RowRequests = Map<EmbeddingOptions["maskInput"], Map<string, Promise<number[]>>>;
3907
+ interface VaultPreparation {
3908
+ corpora: VaultCorpusCache;
3909
+ rows: WeakMap<VaultMemoryOperationsContext, RowRequests>;
3910
+ }
3911
+
3905
3912
  declare const DEFAULT_VAULT_CACHE_SIZE = 5000;
3906
3913
  /**
3907
3914
  * Create a VaultEmbeddingCache backed by an LRU with a default cap of
@@ -3919,6 +3926,7 @@ type VaultEmbeddingCache = Map<string, Float32Array>;
3919
3926
  * Options for the vault search tool.
3920
3927
  */
3921
3928
  interface MemoryVaultSearchOptions {
3929
+ /** @internal */ vaultPreparation?: VaultPreparation;
3922
3930
  onCandidateCount?: (count: number) => void;
3923
3931
  /** Maximum number of results to return (default: 5) */
3924
3932
  limit?: number;
@@ -4441,6 +4449,7 @@ interface RankedMemory {
4441
4449
  updatedAt: Date;
4442
4450
  }
4443
4451
  interface RecallOptions {
4452
+ /** @internal */ vaultPreparation?: VaultPreparation;
4444
4453
  /** Embedding cache shared with the rest of the turn, so the query is embedded once across lanes and the send. */
4445
4454
  embeddingCache?: Map<string, Float32Array>;
4446
4455
  /** Which kinds to search. Default: ['fact']. */
@@ -3902,6 +3902,13 @@ interface RecencyOptions {
3902
3902
  noDateMultiplier?: number;
3903
3903
  }
3904
3904
 
3905
+ type VaultCorpusCache = WeakMap<VaultMemoryOperationsContext, Map<string, Promise<StoredVaultMemory[]>>>;
3906
+ type RowRequests = Map<EmbeddingOptions["maskInput"], Map<string, Promise<number[]>>>;
3907
+ interface VaultPreparation {
3908
+ corpora: VaultCorpusCache;
3909
+ rows: WeakMap<VaultMemoryOperationsContext, RowRequests>;
3910
+ }
3911
+
3905
3912
  declare const DEFAULT_VAULT_CACHE_SIZE = 5000;
3906
3913
  /**
3907
3914
  * Create a VaultEmbeddingCache backed by an LRU with a default cap of
@@ -3919,6 +3926,7 @@ type VaultEmbeddingCache = Map<string, Float32Array>;
3919
3926
  * Options for the vault search tool.
3920
3927
  */
3921
3928
  interface MemoryVaultSearchOptions {
3929
+ /** @internal */ vaultPreparation?: VaultPreparation;
3922
3930
  onCandidateCount?: (count: number) => void;
3923
3931
  /** Maximum number of results to return (default: 5) */
3924
3932
  limit?: number;
@@ -4441,6 +4449,7 @@ interface RankedMemory {
4441
4449
  updatedAt: Date;
4442
4450
  }
4443
4451
  interface RecallOptions {
4452
+ /** @internal */ vaultPreparation?: VaultPreparation;
4444
4453
  /** Embedding cache shared with the rest of the turn, so the query is embedded once across lanes and the send. */
4445
4454
  embeddingCache?: Map<string, Float32Array>;
4446
4455
  /** Which kinds to search. Default: ['fact']. */
@@ -923,15 +923,16 @@ async function refreshEncryptionKeyIfMatches(walletAddress, probeCiphertext, sig
923
923
  if (!parsed) {
924
924
  return false;
925
925
  }
926
+ const startEpoch = sessionEpoch;
926
927
  const cached = refreshCandidatesByAddress.get(walletAddress);
927
928
  if (cached) {
928
- return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, cached);
929
+ return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, cached, startEpoch);
929
930
  }
930
931
  let derivePromise = pendingCandidateDerives.get(walletAddress);
931
932
  if (!derivePromise) {
932
933
  derivePromise = (async () => {
933
934
  const candidates2 = await deriveRefreshCandidates(signMessage, embeddedWalletSigner);
934
- if (candidates2) {
935
+ if (candidates2 && sessionEpoch === startEpoch) {
935
936
  refreshCandidatesByAddress.set(walletAddress, candidates2);
936
937
  }
937
938
  return candidates2;
@@ -943,10 +944,10 @@ async function refreshEncryptionKeyIfMatches(walletAddress, probeCiphertext, sig
943
944
  pendingCandidateDerives.set(walletAddress, derivePromise);
944
945
  }
945
946
  const candidates = await derivePromise;
946
- if (!candidates) {
947
+ if (!candidates || sessionEpoch !== startEpoch) {
947
948
  return false;
948
949
  }
949
- return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates);
950
+ return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates, startEpoch);
950
951
  }
951
952
  function parsePrefixedCiphertext(probeCiphertext) {
952
953
  const version = probeCiphertext.startsWith("enc:v3:") ? "v3" : probeCiphertext.startsWith("enc:v2:") ? "v2" : null;
@@ -989,7 +990,7 @@ async function deriveRefreshCandidates(signMessage, embeddedWalletSigner) {
989
990
  }
990
991
  return { legacy: legacyKey, current: currentKey };
991
992
  }
992
- async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates) {
993
+ async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates, startEpoch) {
993
994
  const candidateHex = parsed.version === "v2" ? candidates.legacy : candidates.current;
994
995
  const keyBytes = hexToBytes(candidateHex);
995
996
  const candidateCryptoKey = await crypto.subtle.importKey(
@@ -1007,6 +1008,9 @@ async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidat
1007
1008
  );
1008
1009
  return false;
1009
1010
  }
1011
+ if (sessionEpoch !== startEpoch) {
1012
+ return false;
1013
+ }
1010
1014
  setStoredKey(walletAddress, { legacy: candidates.legacy, current: candidates.current });
1011
1015
  cryptoKeyCache.delete(`${walletAddress}:v2`);
1012
1016
  cryptoKeyCache.delete(`${walletAddress}:v3`);
@@ -15635,6 +15639,104 @@ function validate(parsed, originalQuery) {
15635
15639
  return { mode, subQueries };
15636
15640
  }
15637
15641
 
15642
+ // src/lib/memoryVault/vaultPreparation.ts
15643
+ function createVaultPreparation() {
15644
+ return { corpora: /* @__PURE__ */ new WeakMap(), rows: /* @__PURE__ */ new WeakMap() };
15645
+ }
15646
+ var pendingRows = /* @__PURE__ */ new WeakMap();
15647
+ function loadVaultCorpus(ctx, options, preparation) {
15648
+ if (!preparation) return getAllVaultMemoriesOp(ctx, options);
15649
+ const corpusCache = preparation.corpora;
15650
+ let pending = corpusCache.get(ctx);
15651
+ if (!pending) {
15652
+ pending = /* @__PURE__ */ new Map();
15653
+ corpusCache.set(ctx, pending);
15654
+ }
15655
+ const key = JSON.stringify(options ?? {});
15656
+ let request = pending.get(key);
15657
+ if (!request) {
15658
+ const entries = pending;
15659
+ request = getAllVaultMemoriesOp(ctx, options).catch((error) => {
15660
+ entries.delete(key);
15661
+ throw error;
15662
+ });
15663
+ pending.set(key, request);
15664
+ }
15665
+ return request;
15666
+ }
15667
+ function rowRequestsFor(registry2, ctx, maskInput) {
15668
+ let byMask = registry2.get(ctx);
15669
+ if (!byMask) {
15670
+ byMask = /* @__PURE__ */ new Map();
15671
+ registry2.set(ctx, byMask);
15672
+ }
15673
+ let requests = byMask.get(maskInput);
15674
+ if (!requests) {
15675
+ requests = /* @__PURE__ */ new Map();
15676
+ byMask.set(maskInput, requests);
15677
+ }
15678
+ return requests;
15679
+ }
15680
+ function embedVaultRows(ctx, options, rows, preparation) {
15681
+ const pending = rowRequestsFor(pendingRows, ctx, options.maskInput);
15682
+ const prepared = preparation && rowRequestsFor(preparation.rows, ctx, options.maskInput);
15683
+ const model = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
15684
+ const keys = rows.map(
15685
+ (row) => JSON.stringify([
15686
+ row.uniqueId,
15687
+ row.updatedAt?.getTime(),
15688
+ row.content,
15689
+ model,
15690
+ options.baseUrl,
15691
+ options.timeoutMs,
15692
+ options.tokenTimeoutMs,
15693
+ options.totalTimeoutMs
15694
+ ])
15695
+ );
15696
+ const missing = /* @__PURE__ */ new Map();
15697
+ rows.forEach((row, index) => {
15698
+ if (!pending.has(keys[index]) && !prepared?.has(keys[index])) missing.set(keys[index], row);
15699
+ });
15700
+ if (missing.size > 0) {
15701
+ const entries = pending;
15702
+ const batch = Promise.resolve().then(
15703
+ () => generateEmbeddings(
15704
+ [...missing.values()].map((row) => row.content),
15705
+ options
15706
+ )
15707
+ );
15708
+ [...missing].forEach(([key, row], index) => {
15709
+ const request = batch.then((vectors) => {
15710
+ const vector = vectors[index];
15711
+ updateVaultMemoryEmbeddingOp(ctx, row.uniqueId, JSON.stringify(vector), model, {
15712
+ content: row.content,
15713
+ updatedAt: row.updatedAt?.getTime()
15714
+ }).catch(() => {
15715
+ });
15716
+ return vector;
15717
+ }).finally(() => {
15718
+ entries.delete(key);
15719
+ if (entries.size === 0) pendingRows.get(ctx)?.delete(options.maskInput);
15720
+ });
15721
+ pending.set(key, request);
15722
+ });
15723
+ }
15724
+ return Promise.all(
15725
+ keys.map((key) => {
15726
+ const cached = prepared?.get(key);
15727
+ if (cached) return cached;
15728
+ const request = pending.get(key);
15729
+ if (!prepared) return request;
15730
+ const retained = request.catch((error) => {
15731
+ prepared.delete(key);
15732
+ throw error;
15733
+ });
15734
+ prepared.set(key, retained);
15735
+ return retained;
15736
+ })
15737
+ );
15738
+ }
15739
+
15638
15740
  // src/lib/memoryVault/vectorVersion.ts
15639
15741
  var vectorRowVersion = /* @__PURE__ */ new WeakMap();
15640
15742
  function contentFingerprint(content) {
@@ -16197,11 +16299,11 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
16197
16299
  return combined.slice(0, limit);
16198
16300
  }
16199
16301
  async function preEmbedVaultMemories(vaultCtx, embeddingOptions, cache, options) {
16200
- const memories = await getAllVaultMemoriesOp(vaultCtx, options);
16302
+ const memories = await loadVaultCorpus(vaultCtx, options);
16201
16303
  const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
16202
16304
  const uncachedTexts = [];
16203
16305
  const uncachedKeys = [];
16204
- const uncachedIds = [];
16306
+ const uncachedRows = [];
16205
16307
  const uncachedVersions = [];
16206
16308
  for (const m of memories) {
16207
16309
  const content = m.content;
@@ -16220,12 +16322,12 @@ async function preEmbedVaultMemories(vaultCtx, embeddingOptions, cache, options)
16220
16322
  }
16221
16323
  uncachedTexts.push(m.content);
16222
16324
  uncachedKeys.push(m.uniqueId);
16223
- uncachedIds.push(m.uniqueId);
16325
+ uncachedRows.push(m);
16224
16326
  uncachedVersions.push(m.updatedAt);
16225
16327
  }
16226
16328
  }
16227
16329
  if (uncachedTexts.length > 0) {
16228
- const embeddings = await generateEmbeddings(uncachedTexts, embeddingOptions);
16330
+ const embeddings = await embedVaultRows(vaultCtx, embeddingOptions, uncachedRows);
16229
16331
  for (let i = 0; i < uncachedKeys.length; i++) {
16230
16332
  cacheRowVector(
16231
16333
  cache,
@@ -16234,13 +16336,6 @@ async function preEmbedVaultMemories(vaultCtx, embeddingOptions, cache, options)
16234
16336
  uncachedVersions[i],
16235
16337
  uncachedTexts[i]
16236
16338
  );
16237
- updateVaultMemoryEmbeddingOp(
16238
- vaultCtx,
16239
- uncachedIds[i],
16240
- JSON.stringify(embeddings[i]),
16241
- currentModel
16242
- ).catch(() => {
16243
- });
16244
16339
  }
16245
16340
  }
16246
16341
  }
@@ -16382,10 +16477,7 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
16382
16477
  let laneVecs;
16383
16478
  if (opts.embedStats) opts.embedStats.rowsEmbedded += laneRows.length;
16384
16479
  try {
16385
- laneVecs = await generateEmbeddings(
16386
- laneRows.map((m) => m.content),
16387
- embeddingOptions
16388
- );
16480
+ laneVecs = await embedVaultRows(vaultCtx, embeddingOptions, laneRows);
16389
16481
  } catch (err) {
16390
16482
  laneEmbedFailed = true;
16391
16483
  getLogger().warn(
@@ -16399,13 +16491,6 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
16399
16491
  cacheRowVector(cache, m.uniqueId, vec, m.updatedAt, m.content);
16400
16492
  resolvedThisCall.add(m.uniqueId);
16401
16493
  vectored.push({ uniqueId: m.uniqueId, embedding: vec, updatedAt: m.updatedAt });
16402
- updateVaultMemoryEmbeddingOp(
16403
- vaultCtx,
16404
- m.uniqueId,
16405
- JSON.stringify(vecs[i]),
16406
- currentModel
16407
- ).catch(() => {
16408
- });
16409
16494
  });
16410
16495
  }
16411
16496
  }
@@ -16597,9 +16682,10 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
16597
16682
  };
16598
16683
  }
16599
16684
  } else {
16600
- const loaded = await getAllVaultMemoriesOp(
16685
+ const loaded = await loadVaultCorpus(
16601
16686
  vaultCtx,
16602
- Object.keys(queryOpts).length > 0 ? queryOpts : void 0
16687
+ Object.keys(queryOpts).length > 0 ? queryOpts : void 0,
16688
+ searchOptions?.vaultPreparation
16603
16689
  );
16604
16690
  vaultSize = loaded.length;
16605
16691
  rowsDecrypted = loaded.length;
@@ -16672,7 +16758,12 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
16672
16758
  let newEmbeddings;
16673
16759
  embedStats.rowsEmbedded += uncachedTexts.length;
16674
16760
  try {
16675
- newEmbeddings = await generateEmbeddings(uncachedTexts, embeddingOptions);
16761
+ newEmbeddings = await embedVaultRows(
16762
+ vaultCtx,
16763
+ embeddingOptions,
16764
+ uncachedIndices.map((index) => memories[index]),
16765
+ searchOptions?.vaultPreparation
16766
+ );
16676
16767
  } catch (err) {
16677
16768
  embeddingFailure = true;
16678
16769
  getLogger().warn(
@@ -16688,13 +16779,6 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
16688
16779
  memories[uncachedIndices[j]].updatedAt,
16689
16780
  memories[uncachedIndices[j]].content
16690
16781
  );
16691
- updateVaultMemoryEmbeddingOp(
16692
- vaultCtx,
16693
- memories[uncachedIndices[j]].uniqueId,
16694
- JSON.stringify(newEmbeddings[j]),
16695
- currentModel
16696
- ).catch(() => {
16697
- });
16698
16782
  }
16699
16783
  }
16700
16784
  }
@@ -19235,6 +19319,7 @@ async function recall(query, ctx, options = {}) {
19235
19319
  },
19236
19320
  ...options.rrfK !== void 0 && { rrfK: options.rrfK },
19237
19321
  ...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
19322
+ ...options.vaultPreparation && { vaultPreparation: options.vaultPreparation },
19238
19323
  ...subQueries && { subQueries },
19239
19324
  ...options.scopes && { scopes: options.scopes },
19240
19325
  ...options.folderId !== void 0 && { folderId: options.folderId },
@@ -22825,13 +22910,20 @@ async function synthesizeProfile(ctx, options = {}) {
22825
22910
  }
22826
22911
  }
22827
22912
  }
22913
+ const vaultPreparation = createVaultPreparation();
22828
22914
  const settled = await Promise.allSettled(
22829
22915
  facets.map(async (facet) => {
22830
22916
  const prior = previous?.sections.find((s) => s.key === facet.key);
22831
22917
  if (prior && !staleKeys.has(facet.key)) {
22832
22918
  return prior;
22833
22919
  }
22834
- return synthesizeFacet(facet, recallCtx, options, fallbackPriors.get(facet.key));
22920
+ return synthesizeFacet(
22921
+ facet,
22922
+ recallCtx,
22923
+ options,
22924
+ fallbackPriors.get(facet.key),
22925
+ vaultPreparation
22926
+ );
22835
22927
  })
22836
22928
  );
22837
22929
  const sections = settled.map((r, i) => {
@@ -22985,7 +23077,7 @@ async function attributeFacts(ctx, candidates, facets) {
22985
23077
  }
22986
23078
  return keys;
22987
23079
  }
22988
- async function synthesizeFacet(facet, ctx, options, prior) {
23080
+ async function synthesizeFacet(facet, ctx, options, prior, vaultPreparation) {
22989
23081
  const scopes = options.scopes ?? DEFAULT_SCOPES;
22990
23082
  const limit = options.limit ?? DEFAULT_FACET_RECALL_LIMIT;
22991
23083
  const factTypeWeights = { ...DEFAULT_PROFILE_FACT_TYPE_WEIGHTS, ...options.factTypeWeights };
@@ -23002,6 +23094,7 @@ async function synthesizeFacet(facet, ctx, options, prior) {
23002
23094
  };
23003
23095
  }
23004
23096
  const recalled = await recall(facet.query, ctx, {
23097
+ vaultPreparation,
23005
23098
  scopes,
23006
23099
  limit: hasReviewGate ? RECALL_MAX_LIMIT : limit,
23007
23100
  types: ["fact"],