@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.
@@ -540,15 +540,16 @@ async function refreshEncryptionKeyIfMatches(walletAddress, probeCiphertext, sig
540
540
  if (!parsed) {
541
541
  return false;
542
542
  }
543
+ const startEpoch = sessionEpoch;
543
544
  const cached = refreshCandidatesByAddress.get(walletAddress);
544
545
  if (cached) {
545
- return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, cached);
546
+ return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, cached, startEpoch);
546
547
  }
547
548
  let derivePromise = pendingCandidateDerives.get(walletAddress);
548
549
  if (!derivePromise) {
549
550
  derivePromise = (async () => {
550
551
  const candidates2 = await deriveRefreshCandidates(signMessage, embeddedWalletSigner);
551
- if (candidates2) {
552
+ if (candidates2 && sessionEpoch === startEpoch) {
552
553
  refreshCandidatesByAddress.set(walletAddress, candidates2);
553
554
  }
554
555
  return candidates2;
@@ -560,10 +561,10 @@ async function refreshEncryptionKeyIfMatches(walletAddress, probeCiphertext, sig
560
561
  pendingCandidateDerives.set(walletAddress, derivePromise);
561
562
  }
562
563
  const candidates = await derivePromise;
563
- if (!candidates) {
564
+ if (!candidates || sessionEpoch !== startEpoch) {
564
565
  return false;
565
566
  }
566
- return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates);
567
+ return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates, startEpoch);
567
568
  }
568
569
  function parsePrefixedCiphertext(probeCiphertext) {
569
570
  const version = probeCiphertext.startsWith("enc:v3:") ? "v3" : probeCiphertext.startsWith("enc:v2:") ? "v2" : null;
@@ -606,7 +607,7 @@ async function deriveRefreshCandidates(signMessage, embeddedWalletSigner) {
606
607
  }
607
608
  return { legacy: legacyKey, current: currentKey };
608
609
  }
609
- async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates) {
610
+ async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates, startEpoch) {
610
611
  const candidateHex = parsed.version === "v2" ? candidates.legacy : candidates.current;
611
612
  const keyBytes = hexToBytes(candidateHex);
612
613
  const candidateCryptoKey = await crypto.subtle.importKey(
@@ -624,6 +625,9 @@ async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidat
624
625
  );
625
626
  return false;
626
627
  }
628
+ if (sessionEpoch !== startEpoch) {
629
+ return false;
630
+ }
627
631
  setStoredKey(walletAddress, { legacy: candidates.legacy, current: candidates.current });
628
632
  cryptoKeyCache.delete(`${walletAddress}:v2`);
629
633
  cryptoKeyCache.delete(`${walletAddress}:v3`);
@@ -17714,6 +17718,104 @@ function validate(parsed, originalQuery) {
17714
17718
  return { mode, subQueries };
17715
17719
  }
17716
17720
 
17721
+ // src/lib/memoryVault/vaultPreparation.ts
17722
+ function createVaultPreparation() {
17723
+ return { corpora: /* @__PURE__ */ new WeakMap(), rows: /* @__PURE__ */ new WeakMap() };
17724
+ }
17725
+ var pendingRows = /* @__PURE__ */ new WeakMap();
17726
+ function loadVaultCorpus(ctx, options, preparation) {
17727
+ if (!preparation) return getAllVaultMemoriesOp(ctx, options);
17728
+ const corpusCache = preparation.corpora;
17729
+ let pending = corpusCache.get(ctx);
17730
+ if (!pending) {
17731
+ pending = /* @__PURE__ */ new Map();
17732
+ corpusCache.set(ctx, pending);
17733
+ }
17734
+ const key = JSON.stringify(options ?? {});
17735
+ let request = pending.get(key);
17736
+ if (!request) {
17737
+ const entries = pending;
17738
+ request = getAllVaultMemoriesOp(ctx, options).catch((error) => {
17739
+ entries.delete(key);
17740
+ throw error;
17741
+ });
17742
+ pending.set(key, request);
17743
+ }
17744
+ return request;
17745
+ }
17746
+ function rowRequestsFor(registry2, ctx, maskInput) {
17747
+ let byMask = registry2.get(ctx);
17748
+ if (!byMask) {
17749
+ byMask = /* @__PURE__ */ new Map();
17750
+ registry2.set(ctx, byMask);
17751
+ }
17752
+ let requests = byMask.get(maskInput);
17753
+ if (!requests) {
17754
+ requests = /* @__PURE__ */ new Map();
17755
+ byMask.set(maskInput, requests);
17756
+ }
17757
+ return requests;
17758
+ }
17759
+ function embedVaultRows(ctx, options, rows, preparation) {
17760
+ const pending = rowRequestsFor(pendingRows, ctx, options.maskInput);
17761
+ const prepared = preparation && rowRequestsFor(preparation.rows, ctx, options.maskInput);
17762
+ const model = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
17763
+ const keys = rows.map(
17764
+ (row) => JSON.stringify([
17765
+ row.uniqueId,
17766
+ row.updatedAt?.getTime(),
17767
+ row.content,
17768
+ model,
17769
+ options.baseUrl,
17770
+ options.timeoutMs,
17771
+ options.tokenTimeoutMs,
17772
+ options.totalTimeoutMs
17773
+ ])
17774
+ );
17775
+ const missing = /* @__PURE__ */ new Map();
17776
+ rows.forEach((row, index) => {
17777
+ if (!pending.has(keys[index]) && !prepared?.has(keys[index])) missing.set(keys[index], row);
17778
+ });
17779
+ if (missing.size > 0) {
17780
+ const entries = pending;
17781
+ const batch = Promise.resolve().then(
17782
+ () => generateEmbeddings(
17783
+ [...missing.values()].map((row) => row.content),
17784
+ options
17785
+ )
17786
+ );
17787
+ [...missing].forEach(([key, row], index) => {
17788
+ const request = batch.then((vectors) => {
17789
+ const vector = vectors[index];
17790
+ updateVaultMemoryEmbeddingOp(ctx, row.uniqueId, JSON.stringify(vector), model, {
17791
+ content: row.content,
17792
+ updatedAt: row.updatedAt?.getTime()
17793
+ }).catch(() => {
17794
+ });
17795
+ return vector;
17796
+ }).finally(() => {
17797
+ entries.delete(key);
17798
+ if (entries.size === 0) pendingRows.get(ctx)?.delete(options.maskInput);
17799
+ });
17800
+ pending.set(key, request);
17801
+ });
17802
+ }
17803
+ return Promise.all(
17804
+ keys.map((key) => {
17805
+ const cached = prepared?.get(key);
17806
+ if (cached) return cached;
17807
+ const request = pending.get(key);
17808
+ if (!prepared) return request;
17809
+ const retained = request.catch((error) => {
17810
+ prepared.delete(key);
17811
+ throw error;
17812
+ });
17813
+ prepared.set(key, retained);
17814
+ return retained;
17815
+ })
17816
+ );
17817
+ }
17818
+
17717
17819
  // src/lib/memoryVault/vectorVersion.ts
17718
17820
  var vectorRowVersion = /* @__PURE__ */ new WeakMap();
17719
17821
  function contentFingerprint(content) {
@@ -18276,11 +18378,11 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
18276
18378
  return combined.slice(0, limit);
18277
18379
  }
18278
18380
  async function preEmbedVaultMemories(vaultCtx, embeddingOptions, cache, options) {
18279
- const memories = await getAllVaultMemoriesOp(vaultCtx, options);
18381
+ const memories = await loadVaultCorpus(vaultCtx, options);
18280
18382
  const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
18281
18383
  const uncachedTexts = [];
18282
18384
  const uncachedKeys = [];
18283
- const uncachedIds = [];
18385
+ const uncachedRows = [];
18284
18386
  const uncachedVersions = [];
18285
18387
  for (const m of memories) {
18286
18388
  const content = m.content;
@@ -18299,12 +18401,12 @@ async function preEmbedVaultMemories(vaultCtx, embeddingOptions, cache, options)
18299
18401
  }
18300
18402
  uncachedTexts.push(m.content);
18301
18403
  uncachedKeys.push(m.uniqueId);
18302
- uncachedIds.push(m.uniqueId);
18404
+ uncachedRows.push(m);
18303
18405
  uncachedVersions.push(m.updatedAt);
18304
18406
  }
18305
18407
  }
18306
18408
  if (uncachedTexts.length > 0) {
18307
- const embeddings = await generateEmbeddings(uncachedTexts, embeddingOptions);
18409
+ const embeddings = await embedVaultRows(vaultCtx, embeddingOptions, uncachedRows);
18308
18410
  for (let i = 0; i < uncachedKeys.length; i++) {
18309
18411
  cacheRowVector(
18310
18412
  cache,
@@ -18313,13 +18415,6 @@ async function preEmbedVaultMemories(vaultCtx, embeddingOptions, cache, options)
18313
18415
  uncachedVersions[i],
18314
18416
  uncachedTexts[i]
18315
18417
  );
18316
- updateVaultMemoryEmbeddingOp(
18317
- vaultCtx,
18318
- uncachedIds[i],
18319
- JSON.stringify(embeddings[i]),
18320
- currentModel
18321
- ).catch(() => {
18322
- });
18323
18418
  }
18324
18419
  }
18325
18420
  }
@@ -18461,10 +18556,7 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
18461
18556
  let laneVecs;
18462
18557
  if (opts.embedStats) opts.embedStats.rowsEmbedded += laneRows.length;
18463
18558
  try {
18464
- laneVecs = await generateEmbeddings(
18465
- laneRows.map((m) => m.content),
18466
- embeddingOptions
18467
- );
18559
+ laneVecs = await embedVaultRows(vaultCtx, embeddingOptions, laneRows);
18468
18560
  } catch (err) {
18469
18561
  laneEmbedFailed = true;
18470
18562
  getLogger().warn(
@@ -18478,13 +18570,6 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
18478
18570
  cacheRowVector(cache, m.uniqueId, vec, m.updatedAt, m.content);
18479
18571
  resolvedThisCall.add(m.uniqueId);
18480
18572
  vectored.push({ uniqueId: m.uniqueId, embedding: vec, updatedAt: m.updatedAt });
18481
- updateVaultMemoryEmbeddingOp(
18482
- vaultCtx,
18483
- m.uniqueId,
18484
- JSON.stringify(vecs[i]),
18485
- currentModel
18486
- ).catch(() => {
18487
- });
18488
18573
  });
18489
18574
  }
18490
18575
  }
@@ -18676,9 +18761,10 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
18676
18761
  };
18677
18762
  }
18678
18763
  } else {
18679
- const loaded = await getAllVaultMemoriesOp(
18764
+ const loaded = await loadVaultCorpus(
18680
18765
  vaultCtx,
18681
- Object.keys(queryOpts).length > 0 ? queryOpts : void 0
18766
+ Object.keys(queryOpts).length > 0 ? queryOpts : void 0,
18767
+ searchOptions?.vaultPreparation
18682
18768
  );
18683
18769
  vaultSize = loaded.length;
18684
18770
  rowsDecrypted = loaded.length;
@@ -18751,7 +18837,12 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
18751
18837
  let newEmbeddings;
18752
18838
  embedStats.rowsEmbedded += uncachedTexts.length;
18753
18839
  try {
18754
- newEmbeddings = await generateEmbeddings(uncachedTexts, embeddingOptions);
18840
+ newEmbeddings = await embedVaultRows(
18841
+ vaultCtx,
18842
+ embeddingOptions,
18843
+ uncachedIndices.map((index) => memories[index]),
18844
+ searchOptions?.vaultPreparation
18845
+ );
18755
18846
  } catch (err) {
18756
18847
  embeddingFailure = true;
18757
18848
  getLogger().warn(
@@ -18767,13 +18858,6 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
18767
18858
  memories[uncachedIndices[j]].updatedAt,
18768
18859
  memories[uncachedIndices[j]].content
18769
18860
  );
18770
- updateVaultMemoryEmbeddingOp(
18771
- vaultCtx,
18772
- memories[uncachedIndices[j]].uniqueId,
18773
- JSON.stringify(newEmbeddings[j]),
18774
- currentModel
18775
- ).catch(() => {
18776
- });
18777
18861
  }
18778
18862
  }
18779
18863
  }
@@ -21340,6 +21424,7 @@ async function recall(query, ctx, options = {}) {
21340
21424
  },
21341
21425
  ...options.rrfK !== void 0 && { rrfK: options.rrfK },
21342
21426
  ...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
21427
+ ...options.vaultPreparation && { vaultPreparation: options.vaultPreparation },
21343
21428
  ...subQueries && { subQueries },
21344
21429
  ...options.scopes && { scopes: options.scopes },
21345
21430
  ...options.folderId !== void 0 && { folderId: options.folderId },
@@ -24930,13 +25015,20 @@ async function synthesizeProfile(ctx, options = {}) {
24930
25015
  }
24931
25016
  }
24932
25017
  }
25018
+ const vaultPreparation = createVaultPreparation();
24933
25019
  const settled = await Promise.allSettled(
24934
25020
  facets.map(async (facet) => {
24935
25021
  const prior = previous?.sections.find((s) => s.key === facet.key);
24936
25022
  if (prior && !staleKeys.has(facet.key)) {
24937
25023
  return prior;
24938
25024
  }
24939
- return synthesizeFacet(facet, recallCtx, options, fallbackPriors.get(facet.key));
25025
+ return synthesizeFacet(
25026
+ facet,
25027
+ recallCtx,
25028
+ options,
25029
+ fallbackPriors.get(facet.key),
25030
+ vaultPreparation
25031
+ );
24940
25032
  })
24941
25033
  );
24942
25034
  const sections = settled.map((r, i) => {
@@ -25090,7 +25182,7 @@ async function attributeFacts(ctx, candidates, facets) {
25090
25182
  }
25091
25183
  return keys;
25092
25184
  }
25093
- async function synthesizeFacet(facet, ctx, options, prior) {
25185
+ async function synthesizeFacet(facet, ctx, options, prior, vaultPreparation) {
25094
25186
  const scopes = options.scopes ?? DEFAULT_SCOPES;
25095
25187
  const limit = options.limit ?? DEFAULT_FACET_RECALL_LIMIT;
25096
25188
  const factTypeWeights = { ...DEFAULT_PROFILE_FACT_TYPE_WEIGHTS, ...options.factTypeWeights };
@@ -25107,6 +25199,7 @@ async function synthesizeFacet(facet, ctx, options, prior) {
25107
25199
  };
25108
25200
  }
25109
25201
  const recalled = await recall(facet.query, ctx, {
25202
+ vaultPreparation,
25110
25203
  scopes,
25111
25204
  limit: hasReviewGate ? RECALL_MAX_LIMIT : limit,
25112
25205
  types: ["fact"],
@@ -17323,15 +17323,16 @@ async function refreshEncryptionKeyIfMatches(walletAddress, probeCiphertext, sig
17323
17323
  if (!parsed) {
17324
17324
  return false;
17325
17325
  }
17326
+ const startEpoch = sessionEpoch;
17326
17327
  const cached = refreshCandidatesByAddress.get(walletAddress);
17327
17328
  if (cached) {
17328
- return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, cached);
17329
+ return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, cached, startEpoch);
17329
17330
  }
17330
17331
  let derivePromise = pendingCandidateDerives.get(walletAddress);
17331
17332
  if (!derivePromise) {
17332
17333
  derivePromise = (async () => {
17333
17334
  const candidates2 = await deriveRefreshCandidates(signMessage, embeddedWalletSigner);
17334
- if (candidates2) {
17335
+ if (candidates2 && sessionEpoch === startEpoch) {
17335
17336
  refreshCandidatesByAddress.set(walletAddress, candidates2);
17336
17337
  }
17337
17338
  return candidates2;
@@ -17343,10 +17344,10 @@ async function refreshEncryptionKeyIfMatches(walletAddress, probeCiphertext, sig
17343
17344
  pendingCandidateDerives.set(walletAddress, derivePromise);
17344
17345
  }
17345
17346
  const candidates = await derivePromise;
17346
- if (!candidates) {
17347
+ if (!candidates || sessionEpoch !== startEpoch) {
17347
17348
  return false;
17348
17349
  }
17349
- return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates);
17350
+ return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates, startEpoch);
17350
17351
  }
17351
17352
  function parsePrefixedCiphertext(probeCiphertext) {
17352
17353
  const version = probeCiphertext.startsWith("enc:v3:") ? "v3" : probeCiphertext.startsWith("enc:v2:") ? "v2" : null;
@@ -17389,7 +17390,7 @@ async function deriveRefreshCandidates(signMessage, embeddedWalletSigner) {
17389
17390
  }
17390
17391
  return { legacy: legacyKey, current: currentKey };
17391
17392
  }
17392
- async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates) {
17393
+ async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates, startEpoch) {
17393
17394
  const candidateHex = parsed.version === "v2" ? candidates.legacy : candidates.current;
17394
17395
  const keyBytes = hexToBytes(candidateHex);
17395
17396
  const candidateCryptoKey = await crypto.subtle.importKey(
@@ -17407,6 +17408,9 @@ async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidat
17407
17408
  );
17408
17409
  return false;
17409
17410
  }
17411
+ if (sessionEpoch !== startEpoch) {
17412
+ return false;
17413
+ }
17410
17414
  setStoredKey(walletAddress, { legacy: candidates.legacy, current: candidates.current });
17411
17415
  cryptoKeyCache.delete(`${walletAddress}:v2`);
17412
17416
  cryptoKeyCache.delete(`${walletAddress}:v3`);
@@ -31550,6 +31554,104 @@ function validate(parsed, originalQuery) {
31550
31554
  return { mode, subQueries };
31551
31555
  }
31552
31556
 
31557
+ // src/lib/memoryVault/vaultPreparation.ts
31558
+ function createVaultPreparation() {
31559
+ return { corpora: /* @__PURE__ */ new WeakMap(), rows: /* @__PURE__ */ new WeakMap() };
31560
+ }
31561
+ var pendingRows = /* @__PURE__ */ new WeakMap();
31562
+ function loadVaultCorpus(ctx, options, preparation) {
31563
+ if (!preparation) return getAllVaultMemoriesOp(ctx, options);
31564
+ const corpusCache = preparation.corpora;
31565
+ let pending = corpusCache.get(ctx);
31566
+ if (!pending) {
31567
+ pending = /* @__PURE__ */ new Map();
31568
+ corpusCache.set(ctx, pending);
31569
+ }
31570
+ const key = JSON.stringify(options ?? {});
31571
+ let request = pending.get(key);
31572
+ if (!request) {
31573
+ const entries = pending;
31574
+ request = getAllVaultMemoriesOp(ctx, options).catch((error) => {
31575
+ entries.delete(key);
31576
+ throw error;
31577
+ });
31578
+ pending.set(key, request);
31579
+ }
31580
+ return request;
31581
+ }
31582
+ function rowRequestsFor(registry, ctx, maskInput) {
31583
+ let byMask = registry.get(ctx);
31584
+ if (!byMask) {
31585
+ byMask = /* @__PURE__ */ new Map();
31586
+ registry.set(ctx, byMask);
31587
+ }
31588
+ let requests = byMask.get(maskInput);
31589
+ if (!requests) {
31590
+ requests = /* @__PURE__ */ new Map();
31591
+ byMask.set(maskInput, requests);
31592
+ }
31593
+ return requests;
31594
+ }
31595
+ function embedVaultRows(ctx, options, rows, preparation) {
31596
+ const pending = rowRequestsFor(pendingRows, ctx, options.maskInput);
31597
+ const prepared = preparation && rowRequestsFor(preparation.rows, ctx, options.maskInput);
31598
+ const model = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
31599
+ const keys = rows.map(
31600
+ (row) => JSON.stringify([
31601
+ row.uniqueId,
31602
+ row.updatedAt?.getTime(),
31603
+ row.content,
31604
+ model,
31605
+ options.baseUrl,
31606
+ options.timeoutMs,
31607
+ options.tokenTimeoutMs,
31608
+ options.totalTimeoutMs
31609
+ ])
31610
+ );
31611
+ const missing = /* @__PURE__ */ new Map();
31612
+ rows.forEach((row, index) => {
31613
+ if (!pending.has(keys[index]) && !prepared?.has(keys[index])) missing.set(keys[index], row);
31614
+ });
31615
+ if (missing.size > 0) {
31616
+ const entries = pending;
31617
+ const batch = Promise.resolve().then(
31618
+ () => generateEmbeddings(
31619
+ [...missing.values()].map((row) => row.content),
31620
+ options
31621
+ )
31622
+ );
31623
+ [...missing].forEach(([key, row], index) => {
31624
+ const request = batch.then((vectors) => {
31625
+ const vector = vectors[index];
31626
+ updateVaultMemoryEmbeddingOp(ctx, row.uniqueId, JSON.stringify(vector), model, {
31627
+ content: row.content,
31628
+ updatedAt: row.updatedAt?.getTime()
31629
+ }).catch(() => {
31630
+ });
31631
+ return vector;
31632
+ }).finally(() => {
31633
+ entries.delete(key);
31634
+ if (entries.size === 0) pendingRows.get(ctx)?.delete(options.maskInput);
31635
+ });
31636
+ pending.set(key, request);
31637
+ });
31638
+ }
31639
+ return Promise.all(
31640
+ keys.map((key) => {
31641
+ const cached = prepared?.get(key);
31642
+ if (cached) return cached;
31643
+ const request = pending.get(key);
31644
+ if (!prepared) return request;
31645
+ const retained = request.catch((error) => {
31646
+ prepared.delete(key);
31647
+ throw error;
31648
+ });
31649
+ prepared.set(key, retained);
31650
+ return retained;
31651
+ })
31652
+ );
31653
+ }
31654
+
31553
31655
  // src/lib/memoryVault/vectorVersion.ts
31554
31656
  var vectorRowVersion = /* @__PURE__ */ new WeakMap();
31555
31657
  function contentFingerprint(content) {
@@ -32112,11 +32214,11 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
32112
32214
  return combined.slice(0, limit);
32113
32215
  }
32114
32216
  async function preEmbedVaultMemories(vaultCtx, embeddingOptions, cache, options) {
32115
- const memories = await getAllVaultMemoriesOp(vaultCtx, options);
32217
+ const memories = await loadVaultCorpus(vaultCtx, options);
32116
32218
  const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
32117
32219
  const uncachedTexts = [];
32118
32220
  const uncachedKeys = [];
32119
- const uncachedIds = [];
32221
+ const uncachedRows = [];
32120
32222
  const uncachedVersions = [];
32121
32223
  for (const m of memories) {
32122
32224
  const content = m.content;
@@ -32135,12 +32237,12 @@ async function preEmbedVaultMemories(vaultCtx, embeddingOptions, cache, options)
32135
32237
  }
32136
32238
  uncachedTexts.push(m.content);
32137
32239
  uncachedKeys.push(m.uniqueId);
32138
- uncachedIds.push(m.uniqueId);
32240
+ uncachedRows.push(m);
32139
32241
  uncachedVersions.push(m.updatedAt);
32140
32242
  }
32141
32243
  }
32142
32244
  if (uncachedTexts.length > 0) {
32143
- const embeddings = await generateEmbeddings(uncachedTexts, embeddingOptions);
32245
+ const embeddings = await embedVaultRows(vaultCtx, embeddingOptions, uncachedRows);
32144
32246
  for (let i = 0; i < uncachedKeys.length; i++) {
32145
32247
  cacheRowVector(
32146
32248
  cache,
@@ -32149,13 +32251,6 @@ async function preEmbedVaultMemories(vaultCtx, embeddingOptions, cache, options)
32149
32251
  uncachedVersions[i],
32150
32252
  uncachedTexts[i]
32151
32253
  );
32152
- updateVaultMemoryEmbeddingOp(
32153
- vaultCtx,
32154
- uncachedIds[i],
32155
- JSON.stringify(embeddings[i]),
32156
- currentModel
32157
- ).catch(() => {
32158
- });
32159
32254
  }
32160
32255
  }
32161
32256
  }
@@ -32297,10 +32392,7 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
32297
32392
  let laneVecs;
32298
32393
  if (opts.embedStats) opts.embedStats.rowsEmbedded += laneRows.length;
32299
32394
  try {
32300
- laneVecs = await generateEmbeddings(
32301
- laneRows.map((m) => m.content),
32302
- embeddingOptions
32303
- );
32395
+ laneVecs = await embedVaultRows(vaultCtx, embeddingOptions, laneRows);
32304
32396
  } catch (err) {
32305
32397
  laneEmbedFailed = true;
32306
32398
  getLogger().warn(
@@ -32314,13 +32406,6 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
32314
32406
  cacheRowVector(cache, m.uniqueId, vec, m.updatedAt, m.content);
32315
32407
  resolvedThisCall.add(m.uniqueId);
32316
32408
  vectored.push({ uniqueId: m.uniqueId, embedding: vec, updatedAt: m.updatedAt });
32317
- updateVaultMemoryEmbeddingOp(
32318
- vaultCtx,
32319
- m.uniqueId,
32320
- JSON.stringify(vecs[i]),
32321
- currentModel
32322
- ).catch(() => {
32323
- });
32324
32409
  });
32325
32410
  }
32326
32411
  }
@@ -32512,9 +32597,10 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
32512
32597
  };
32513
32598
  }
32514
32599
  } else {
32515
- const loaded = await getAllVaultMemoriesOp(
32600
+ const loaded = await loadVaultCorpus(
32516
32601
  vaultCtx,
32517
- Object.keys(queryOpts).length > 0 ? queryOpts : void 0
32602
+ Object.keys(queryOpts).length > 0 ? queryOpts : void 0,
32603
+ searchOptions?.vaultPreparation
32518
32604
  );
32519
32605
  vaultSize = loaded.length;
32520
32606
  rowsDecrypted = loaded.length;
@@ -32587,7 +32673,12 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
32587
32673
  let newEmbeddings;
32588
32674
  embedStats.rowsEmbedded += uncachedTexts.length;
32589
32675
  try {
32590
- newEmbeddings = await generateEmbeddings(uncachedTexts, embeddingOptions);
32676
+ newEmbeddings = await embedVaultRows(
32677
+ vaultCtx,
32678
+ embeddingOptions,
32679
+ uncachedIndices.map((index) => memories[index]),
32680
+ searchOptions?.vaultPreparation
32681
+ );
32591
32682
  } catch (err) {
32592
32683
  embeddingFailure = true;
32593
32684
  getLogger().warn(
@@ -32603,13 +32694,6 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
32603
32694
  memories[uncachedIndices[j]].updatedAt,
32604
32695
  memories[uncachedIndices[j]].content
32605
32696
  );
32606
- updateVaultMemoryEmbeddingOp(
32607
- vaultCtx,
32608
- memories[uncachedIndices[j]].uniqueId,
32609
- JSON.stringify(newEmbeddings[j]),
32610
- currentModel
32611
- ).catch(() => {
32612
- });
32613
32697
  }
32614
32698
  }
32615
32699
  }
@@ -35190,6 +35274,7 @@ async function recall(query, ctx, options = {}) {
35190
35274
  },
35191
35275
  ...options.rrfK !== void 0 && { rrfK: options.rrfK },
35192
35276
  ...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
35277
+ ...options.vaultPreparation && { vaultPreparation: options.vaultPreparation },
35193
35278
  ...subQueries && { subQueries },
35194
35279
  ...options.scopes && { scopes: options.scopes },
35195
35280
  ...options.folderId !== void 0 && { folderId: options.folderId },
@@ -36622,13 +36707,20 @@ async function synthesizeProfile(ctx, options = {}) {
36622
36707
  }
36623
36708
  }
36624
36709
  }
36710
+ const vaultPreparation = createVaultPreparation();
36625
36711
  const settled = await Promise.allSettled(
36626
36712
  facets.map(async (facet) => {
36627
36713
  const prior = previous?.sections.find((s) => s.key === facet.key);
36628
36714
  if (prior && !staleKeys.has(facet.key)) {
36629
36715
  return prior;
36630
36716
  }
36631
- return synthesizeFacet(facet, recallCtx, options, fallbackPriors.get(facet.key));
36717
+ return synthesizeFacet(
36718
+ facet,
36719
+ recallCtx,
36720
+ options,
36721
+ fallbackPriors.get(facet.key),
36722
+ vaultPreparation
36723
+ );
36632
36724
  })
36633
36725
  );
36634
36726
  const sections = settled.map((r, i) => {
@@ -36782,7 +36874,7 @@ async function attributeFacts(ctx, candidates, facets) {
36782
36874
  }
36783
36875
  return keys;
36784
36876
  }
36785
- async function synthesizeFacet(facet, ctx, options, prior) {
36877
+ async function synthesizeFacet(facet, ctx, options, prior, vaultPreparation) {
36786
36878
  const scopes = options.scopes ?? DEFAULT_SCOPES;
36787
36879
  const limit = options.limit ?? DEFAULT_FACET_RECALL_LIMIT;
36788
36880
  const factTypeWeights = { ...DEFAULT_PROFILE_FACT_TYPE_WEIGHTS, ...options.factTypeWeights };
@@ -36799,6 +36891,7 @@ async function synthesizeFacet(facet, ctx, options, prior) {
36799
36891
  };
36800
36892
  }
36801
36893
  const recalled = await recall(facet.query, ctx, {
36894
+ vaultPreparation,
36802
36895
  scopes,
36803
36896
  limit: hasReviewGate ? RECALL_MAX_LIMIT : limit,
36804
36897
  types: ["fact"],
@@ -3365,6 +3365,13 @@ interface RecencyOptions {
3365
3365
  noDateMultiplier?: number;
3366
3366
  }
3367
3367
 
3368
+ type VaultCorpusCache = WeakMap<VaultMemoryOperationsContext, Map<string, Promise<StoredVaultMemory[]>>>;
3369
+ type RowRequests = Map<EmbeddingOptions["maskInput"], Map<string, Promise<number[]>>>;
3370
+ interface VaultPreparation {
3371
+ corpora: VaultCorpusCache;
3372
+ rows: WeakMap<VaultMemoryOperationsContext, RowRequests>;
3373
+ }
3374
+
3368
3375
  declare const DEFAULT_VAULT_CACHE_SIZE = 5000;
3369
3376
  /**
3370
3377
  * Create a VaultEmbeddingCache backed by an LRU with a default cap of
@@ -3382,6 +3389,7 @@ type VaultEmbeddingCache = Map<string, Float32Array>;
3382
3389
  * Options for the vault search tool.
3383
3390
  */
3384
3391
  interface MemoryVaultSearchOptions {
3392
+ /** @internal */ vaultPreparation?: VaultPreparation;
3385
3393
  onCandidateCount?: (count: number) => void;
3386
3394
  /** Maximum number of results to return (default: 5) */
3387
3395
  limit?: number;
@@ -4059,6 +4067,7 @@ interface RankedMemory {
4059
4067
  updatedAt: Date;
4060
4068
  }
4061
4069
  interface RecallOptions {
4070
+ /** @internal */ vaultPreparation?: VaultPreparation;
4062
4071
  /** Embedding cache shared with the rest of the turn, so the query is embedded once across lanes and the send. */
4063
4072
  embeddingCache?: Map<string, Float32Array>;
4064
4073
  /** Which kinds to search. Default: ['fact']. */
@@ -3365,6 +3365,13 @@ interface RecencyOptions {
3365
3365
  noDateMultiplier?: number;
3366
3366
  }
3367
3367
 
3368
+ type VaultCorpusCache = WeakMap<VaultMemoryOperationsContext, Map<string, Promise<StoredVaultMemory[]>>>;
3369
+ type RowRequests = Map<EmbeddingOptions["maskInput"], Map<string, Promise<number[]>>>;
3370
+ interface VaultPreparation {
3371
+ corpora: VaultCorpusCache;
3372
+ rows: WeakMap<VaultMemoryOperationsContext, RowRequests>;
3373
+ }
3374
+
3368
3375
  declare const DEFAULT_VAULT_CACHE_SIZE = 5000;
3369
3376
  /**
3370
3377
  * Create a VaultEmbeddingCache backed by an LRU with a default cap of
@@ -3382,6 +3389,7 @@ type VaultEmbeddingCache = Map<string, Float32Array>;
3382
3389
  * Options for the vault search tool.
3383
3390
  */
3384
3391
  interface MemoryVaultSearchOptions {
3392
+ /** @internal */ vaultPreparation?: VaultPreparation;
3385
3393
  onCandidateCount?: (count: number) => void;
3386
3394
  /** Maximum number of results to return (default: 5) */
3387
3395
  limit?: number;
@@ -4059,6 +4067,7 @@ interface RankedMemory {
4059
4067
  updatedAt: Date;
4060
4068
  }
4061
4069
  interface RecallOptions {
4070
+ /** @internal */ vaultPreparation?: VaultPreparation;
4062
4071
  /** Embedding cache shared with the rest of the turn, so the query is embedded once across lanes and the send. */
4063
4072
  embeddingCache?: Map<string, Float32Array>;
4064
4073
  /** Which kinds to search. Default: ['fact']. */