@anuma/sdk 9.1.3 → 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 },
@@ -22927,6 +23012,8 @@ async function backfillTopics(ctx) {
22927
23012
  if (topicless.length > 0) await backfillMemoryTopicsOp(ctx, topicless);
22928
23013
  }
22929
23014
  async function migrateMemoriesToRemote(options) {
23015
+ if (typeof options.withWriteBarrier !== "function" || typeof options.onActivated !== "function")
23016
+ throw new Error("A write barrier and a remote store handoff are required");
22930
23017
  const { canonical, signal } = options;
22931
23018
  const rings = [canonical, ...options.fallbacks ?? []];
22932
23019
  const model = options.embeddingOptions?.model ?? DEFAULT_API_EMBEDDING_MODEL;
@@ -22954,93 +23041,98 @@ async function migrateMemoriesToRemote(options) {
22954
23041
  const placeholders = /* @__PURE__ */ new Set();
22955
23042
  const truncated = /* @__PURE__ */ new Set();
22956
23043
  let imported = 0;
22957
- for (let pass = 0; ; pass++) {
22958
- const rows = await getAllVaultMemoryRowsOp(options.vaultCtx);
22959
- for (const raw of rows) if (invalid2(raw)) skipped.set(String(raw.id), "invalid");
22960
- const candidates = rows.filter((raw) => !skipped.has(String(raw.id)));
22961
- const missing = await missingIds(request, candidates.map(revision), signal);
22962
- const pending = /* @__PURE__ */ new Map();
22963
- for (const raw of candidates)
22964
- if (missing.has(raw.id)) pending.set(raw.id, raw.updated_at);
22965
- if (pending.size === 0 && !active) {
22966
- const remote = await remoteMetadata(
22967
- request,
22968
- candidates.map((raw) => raw.id),
22969
- signal
22970
- );
22971
- const needsVector = (raw, server) => !!options.embeddingOptions && !embedding(raw, model) && server.embedding_model !== model;
22972
- for (const raw of candidates) {
22973
- const server = remote.get(raw.id);
22974
- if (server && server.updated_at === raw.updated_at && (!sameMetadata2(raw, server, model) || needsVector(raw, server)))
22975
- pending.set(raw.id, raw.updated_at + 1);
22976
- }
22977
- }
22978
- if (pending.size === 0) {
22979
- const result = (state) => ({
22980
- state,
22981
- total: rows.length,
22982
- imported,
22983
- skipped: [...skipped].map(([memoryId, reason]) => ({ memoryId, reason })),
22984
- reembedded: reembedded.size,
22985
- unembedded: unembedded.size,
22986
- placeholderTombstones: placeholders.size,
22987
- truncatedSourceChunkIds: truncated.size
22988
- });
22989
- if (skipped.size > 0 && !options.allowSkipped) return result("migrating");
22990
- if (!claimed) await importBatch(request, canonical.keyId, [], signal);
22991
- if (!active)
22992
- await request(
22993
- "/account",
22994
- { method: "PUT", body: JSON.stringify({ state: "active" }) },
23044
+ const uploadPasses = async (finalizing = false) => {
23045
+ for (let pass = 0; ; pass++) {
23046
+ const rows = await getAllVaultMemoryRowsOp(options.vaultCtx);
23047
+ for (const raw of rows) if (invalid2(raw)) skipped.set(String(raw.id), "invalid");
23048
+ const candidates = rows.filter((raw) => !skipped.has(String(raw.id)));
23049
+ const missing = await missingIds(request, candidates.map(revision), signal);
23050
+ const pending = /* @__PURE__ */ new Map();
23051
+ for (const raw of candidates)
23052
+ if (missing.has(raw.id)) pending.set(raw.id, raw.updated_at);
23053
+ if (pending.size === 0 && !active) {
23054
+ const remote = await remoteMetadata(
23055
+ request,
23056
+ candidates.map((raw) => raw.id),
22995
23057
  signal
22996
23058
  );
22997
- return result("active");
22998
- }
22999
- if (pass >= MAX_UPLOAD_PASSES)
23000
- throw new RemoteMemoryError(
23001
- "Nearby still reports memories missing after importing them",
23002
- 409,
23003
- "migration_incomplete"
23004
- );
23005
- const prepared = [];
23006
- for (const raw of candidates) {
23007
- const updatedAt = pending.get(raw.id);
23008
- if (updatedAt === void 0) continue;
23009
- try {
23010
- prepared.push(await prepareRow(raw, canonical, rings, model, updatedAt));
23011
- } catch (error) {
23012
- if (!(error instanceof MemoryKeyError)) throw error;
23013
- skipped.set(raw.id, "unreadable");
23014
- }
23015
- }
23016
- const usable = new Set(prepared.filter((p) => p.row.embedding).map((p) => p.row.memory_id));
23017
- if (options.embeddingOptions)
23018
- await embedMissing(prepared, options.embeddingOptions, model, signal);
23019
- const local = new Map(candidates.map((raw) => [raw.id, raw]));
23020
- const upload = [];
23021
- for (const { row, plaintext } of prepared) {
23022
- const id2 = row.memory_id;
23023
- if (!fitsNearby(row)) {
23024
- skipped.set(id2, "invalid");
23025
- continue;
23059
+ const needsVector = (raw, server) => !!options.embeddingOptions && !embedding(raw, model) && server.embedding_model !== model;
23060
+ for (const raw of candidates) {
23061
+ const server = remote.get(raw.id);
23062
+ if (server && server.updated_at === raw.updated_at && (!sameMetadata2(raw, server, model) || needsVector(raw, server)))
23063
+ pending.set(raw.id, raw.updated_at + 1);
23064
+ }
23065
+ }
23066
+ if (pending.size === 0) {
23067
+ const result = (state) => ({
23068
+ state,
23069
+ total: rows.length,
23070
+ imported,
23071
+ skipped: [...skipped].map(([memoryId, reason]) => ({ memoryId, reason })),
23072
+ reembedded: reembedded.size,
23073
+ unembedded: unembedded.size,
23074
+ placeholderTombstones: placeholders.size,
23075
+ truncatedSourceChunkIds: truncated.size
23076
+ });
23077
+ if (skipped.size > 0 && !options.allowSkipped) return result("migrating");
23078
+ if (!finalizing) return options.withWriteBarrier(() => uploadPasses(true));
23079
+ if (!claimed) await importBatch(request, canonical.keyId, [], signal);
23080
+ if (!active)
23081
+ await request(
23082
+ "/account",
23083
+ { method: "PUT", body: JSON.stringify({ state: "active" }) },
23084
+ signal
23085
+ );
23086
+ await options.onActivated();
23087
+ return result("active");
23088
+ }
23089
+ if (pass >= MAX_UPLOAD_PASSES)
23090
+ throw new RemoteMemoryError(
23091
+ "Nearby still reports memories missing after importing them",
23092
+ 409,
23093
+ "migration_incomplete"
23094
+ );
23095
+ const prepared = [];
23096
+ for (const raw of candidates) {
23097
+ const updatedAt = pending.get(raw.id);
23098
+ if (updatedAt === void 0) continue;
23099
+ try {
23100
+ prepared.push(await prepareRow(raw, canonical, rings, model, updatedAt));
23101
+ } catch (error) {
23102
+ if (!(error instanceof MemoryKeyError)) throw error;
23103
+ skipped.set(raw.id, "unreadable");
23104
+ }
23105
+ }
23106
+ const usable = new Set(prepared.filter((p) => p.row.embedding).map((p) => p.row.memory_id));
23107
+ if (options.embeddingOptions)
23108
+ await embedMissing(prepared, options.embeddingOptions, model, signal);
23109
+ const local = new Map(candidates.map((raw) => [raw.id, raw]));
23110
+ const upload = [];
23111
+ for (const { row, plaintext } of prepared) {
23112
+ const id2 = row.memory_id;
23113
+ if (!fitsNearby(row)) {
23114
+ skipped.set(id2, "invalid");
23115
+ continue;
23116
+ }
23117
+ upload.push(row);
23118
+ const track = (set, on) => on ? set.add(id2) : set.delete(id2);
23119
+ track(reembedded, !!row.embedding && !usable.has(id2));
23120
+ track(unembedded, !row.embedding);
23121
+ track(placeholders, plaintext === void 0);
23122
+ track(truncated, row.source_chunk_ids !== text13(local.get(id2).source_chunk_ids));
23026
23123
  }
23027
- upload.push(row);
23028
- const track = (set, on) => on ? set.add(id2) : set.delete(id2);
23029
- track(reembedded, !!row.embedding && !usable.has(id2));
23030
- track(unembedded, !row.embedding);
23031
- track(placeholders, plaintext === void 0);
23032
- track(truncated, row.source_chunk_ids !== text13(local.get(id2).source_chunk_ids));
23033
- }
23034
- let sent = 0;
23035
- options.onProgress?.({ imported: sent, toImport: upload.length });
23036
- for (const batch of chunks(upload, IMPORT_BATCH)) {
23037
- await importBatch(request, canonical.keyId, batch, signal);
23038
- claimed = true;
23039
- sent += batch.length;
23124
+ let sent = 0;
23040
23125
  options.onProgress?.({ imported: sent, toImport: upload.length });
23126
+ for (const batch of chunks(upload, IMPORT_BATCH)) {
23127
+ await importBatch(request, canonical.keyId, batch, signal);
23128
+ claimed = true;
23129
+ sent += batch.length;
23130
+ options.onProgress?.({ imported: sent, toImport: upload.length });
23131
+ }
23132
+ imported += sent;
23041
23133
  }
23042
- imported += sent;
23043
- }
23134
+ };
23135
+ return uploadPasses();
23044
23136
  }
23045
23137
 
23046
23138
  // src/lib/memory/store/remoteStore.ts
@@ -24496,13 +24588,20 @@ async function synthesizeProfile(ctx, options = {}) {
24496
24588
  }
24497
24589
  }
24498
24590
  }
24591
+ const vaultPreparation = createVaultPreparation();
24499
24592
  const settled = await Promise.allSettled(
24500
24593
  facets.map(async (facet) => {
24501
24594
  const prior = previous?.sections.find((s) => s.key === facet.key);
24502
24595
  if (prior && !staleKeys.has(facet.key)) {
24503
24596
  return prior;
24504
24597
  }
24505
- 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
+ );
24506
24605
  })
24507
24606
  );
24508
24607
  const sections = settled.map((r, i) => {
@@ -24656,7 +24755,7 @@ async function attributeFacts(ctx, candidates, facets) {
24656
24755
  }
24657
24756
  return keys;
24658
24757
  }
24659
- async function synthesizeFacet(facet, ctx, options, prior) {
24758
+ async function synthesizeFacet(facet, ctx, options, prior, vaultPreparation) {
24660
24759
  const scopes = options.scopes ?? DEFAULT_SCOPES;
24661
24760
  const limit = options.limit ?? DEFAULT_FACET_RECALL_LIMIT;
24662
24761
  const factTypeWeights = { ...DEFAULT_PROFILE_FACT_TYPE_WEIGHTS, ...options.factTypeWeights };
@@ -24673,6 +24772,7 @@ async function synthesizeFacet(facet, ctx, options, prior) {
24673
24772
  };
24674
24773
  }
24675
24774
  const recalled = await recall(facet.query, ctx, {
24775
+ vaultPreparation,
24676
24776
  scopes,
24677
24777
  limit: hasReviewGate ? RECALL_MAX_LIMIT : limit,
24678
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']. */
@@ -9931,6 +9940,10 @@ interface MemoryMigrationOptions extends Pick<RemoteMemoryPersistenceOptions, "b
9931
9940
  name: string;
9932
9941
  kind?: string;
9933
9942
  }[];
9943
+ /** Drain all local memory writes, block new writes until the task returns, and retain the block if the remote handoff fails. */
9944
+ withWriteBarrier: (task: () => Promise<MemoryMigrationResult>) => Promise<MemoryMigrationResult>;
9945
+ /** Route all subsequent memory writes to the remote store before this callback returns. */
9946
+ onActivated: () => void | Promise<void>;
9934
9947
  signal?: AbortSignal;
9935
9948
  onProgress?: (progress: MemoryMigrationProgress) => void;
9936
9949
  }
@@ -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']. */
@@ -9931,6 +9940,10 @@ interface MemoryMigrationOptions extends Pick<RemoteMemoryPersistenceOptions, "b
9931
9940
  name: string;
9932
9941
  kind?: string;
9933
9942
  }[];
9943
+ /** Drain all local memory writes, block new writes until the task returns, and retain the block if the remote handoff fails. */
9944
+ withWriteBarrier: (task: () => Promise<MemoryMigrationResult>) => Promise<MemoryMigrationResult>;
9945
+ /** Route all subsequent memory writes to the remote store before this callback returns. */
9946
+ onActivated: () => void | Promise<void>;
9934
9947
  signal?: AbortSignal;
9935
9948
  onProgress?: (progress: MemoryMigrationProgress) => void;
9936
9949
  }