@anuma/sdk 9.1.4 → 9.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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']. */
@@ -5278,7 +5287,8 @@ interface CreateVaultMemoryOptions {
5278
5287
  geohash?: string;
5279
5288
  }
5280
5289
  interface UpdateVaultMemoryOptions {
5281
- content: string;
5290
+ content?: string;
5291
+ expectedContent?: string;
5282
5292
  /** When true, the write is skipped (returns null) if the row carries a profile kind. */
5283
5293
  freeFormOnly?: boolean;
5284
5294
  /**
@@ -5840,9 +5850,10 @@ declare function ttlForType(factType: string | null, policy?: Partial<DecayPolic
5840
5850
  * null `eventTimeEnd` is still ongoing, so this rule does not fire for it.
5841
5851
  * 4. Age fallback — `now - updatedAt > TTL(factType)` → archive. Durable types
5842
5852
  * have Infinity TTL, so this never fires for them; null/unknown use medium.
5843
- * EXCEPTION: a `plan`/`ongoing_context` with a still-upcoming event
5844
- * (`eventTimeEnd >= now`) is kept — it must not age-archive before the event
5845
- * happens; only rule 3 (after it passes) may archive it.
5853
+ * EXCEPTION: a `plan` / `ongoing_context` with an upcoming event or an event
5854
+ * within the grace period (`eventTimeEnd >= now - pastEventGraceMs`) stays
5855
+ * active, even after its activity TTL expires. Rule 3 archives it after the
5856
+ * grace period ends.
5846
5857
  * 5. Otherwise → keep.
5847
5858
  *
5848
5859
  * @param m Plaintext decay inputs for one row.
@@ -6173,7 +6184,9 @@ type MemoryCreate = Pick<CreateVaultMemoryOptions, "content" | "scope" | "factTy
6173
6184
  * `embedding` (with `embeddingModel`) only when you already have the new one.
6174
6185
  * @public
6175
6186
  */
6176
- type MemoryUpdate = Pick<UpdateVaultMemoryOptions, "content" | "scope" | "factType" | "eventTime" | "embedding" | "embeddingModel" | "kind" | "kindValue" | "level">;
6187
+ type MemoryUpdate = Pick<UpdateVaultMemoryOptions, "scope" | "factType" | "eventTime" | "embedding" | "embeddingModel" | "kind" | "kindValue" | "level"> & {
6188
+ content: string;
6189
+ };
6177
6190
  /**
6178
6191
  * Fact-only recall. Conversation chunks are message storage, not memory, so
6179
6192
  * the chunk-lane knobs are not part of this surface; nor is `folderId` (see
@@ -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']. */
@@ -5278,7 +5287,8 @@ interface CreateVaultMemoryOptions {
5278
5287
  geohash?: string;
5279
5288
  }
5280
5289
  interface UpdateVaultMemoryOptions {
5281
- content: string;
5290
+ content?: string;
5291
+ expectedContent?: string;
5282
5292
  /** When true, the write is skipped (returns null) if the row carries a profile kind. */
5283
5293
  freeFormOnly?: boolean;
5284
5294
  /**
@@ -5840,9 +5850,10 @@ declare function ttlForType(factType: string | null, policy?: Partial<DecayPolic
5840
5850
  * null `eventTimeEnd` is still ongoing, so this rule does not fire for it.
5841
5851
  * 4. Age fallback — `now - updatedAt > TTL(factType)` → archive. Durable types
5842
5852
  * have Infinity TTL, so this never fires for them; null/unknown use medium.
5843
- * EXCEPTION: a `plan`/`ongoing_context` with a still-upcoming event
5844
- * (`eventTimeEnd >= now`) is kept — it must not age-archive before the event
5845
- * happens; only rule 3 (after it passes) may archive it.
5853
+ * EXCEPTION: a `plan` / `ongoing_context` with an upcoming event or an event
5854
+ * within the grace period (`eventTimeEnd >= now - pastEventGraceMs`) stays
5855
+ * active, even after its activity TTL expires. Rule 3 archives it after the
5856
+ * grace period ends.
5846
5857
  * 5. Otherwise → keep.
5847
5858
  *
5848
5859
  * @param m Plaintext decay inputs for one row.
@@ -6173,7 +6184,9 @@ type MemoryCreate = Pick<CreateVaultMemoryOptions, "content" | "scope" | "factTy
6173
6184
  * `embedding` (with `embeddingModel`) only when you already have the new one.
6174
6185
  * @public
6175
6186
  */
6176
- type MemoryUpdate = Pick<UpdateVaultMemoryOptions, "content" | "scope" | "factType" | "eventTime" | "embedding" | "embeddingModel" | "kind" | "kindValue" | "level">;
6187
+ type MemoryUpdate = Pick<UpdateVaultMemoryOptions, "scope" | "factType" | "eventTime" | "embedding" | "embeddingModel" | "kind" | "kindValue" | "level"> & {
6188
+ content: string;
6189
+ };
6177
6190
  /**
6178
6191
  * Fact-only recall. Conversation chunks are message storage, not memory, so
6179
6192
  * the chunk-lane knobs are not part of this surface; nor is `folderId` (see
@@ -13,7 +13,7 @@ import {
13
13
  taskTypeHeader,
14
14
  validateEndpointOverride,
15
15
  withInternalFlowMarker
16
- } from "./chunk-AU3Z7NBC.mjs";
16
+ } from "./chunk-QEROZ4VH.mjs";
17
17
  import {
18
18
  BASE_URL,
19
19
  __commonJS,
@@ -15652,15 +15652,16 @@ async function refreshEncryptionKeyIfMatches(walletAddress, probeCiphertext, sig
15652
15652
  if (!parsed) {
15653
15653
  return false;
15654
15654
  }
15655
+ const startEpoch = sessionEpoch;
15655
15656
  const cached = refreshCandidatesByAddress.get(walletAddress);
15656
15657
  if (cached) {
15657
- return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, cached);
15658
+ return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, cached, startEpoch);
15658
15659
  }
15659
15660
  let derivePromise = pendingCandidateDerives.get(walletAddress);
15660
15661
  if (!derivePromise) {
15661
15662
  derivePromise = (async () => {
15662
15663
  const candidates2 = await deriveRefreshCandidates(signMessage, embeddedWalletSigner);
15663
- if (candidates2) {
15664
+ if (candidates2 && sessionEpoch === startEpoch) {
15664
15665
  refreshCandidatesByAddress.set(walletAddress, candidates2);
15665
15666
  }
15666
15667
  return candidates2;
@@ -15672,10 +15673,10 @@ async function refreshEncryptionKeyIfMatches(walletAddress, probeCiphertext, sig
15672
15673
  pendingCandidateDerives.set(walletAddress, derivePromise);
15673
15674
  }
15674
15675
  const candidates = await derivePromise;
15675
- if (!candidates) {
15676
+ if (!candidates || sessionEpoch !== startEpoch) {
15676
15677
  return false;
15677
15678
  }
15678
- return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates);
15679
+ return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates, startEpoch);
15679
15680
  }
15680
15681
  function parsePrefixedCiphertext(probeCiphertext) {
15681
15682
  const version = probeCiphertext.startsWith("enc:v3:") ? "v3" : probeCiphertext.startsWith("enc:v2:") ? "v2" : null;
@@ -15718,7 +15719,7 @@ async function deriveRefreshCandidates(signMessage, embeddedWalletSigner) {
15718
15719
  }
15719
15720
  return { legacy: legacyKey, current: currentKey };
15720
15721
  }
15721
- async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates) {
15722
+ async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates, startEpoch) {
15722
15723
  const candidateHex = parsed.version === "v2" ? candidates.legacy : candidates.current;
15723
15724
  const keyBytes = hexToBytes(candidateHex);
15724
15725
  const candidateCryptoKey = await crypto.subtle.importKey(
@@ -15736,6 +15737,9 @@ async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidat
15736
15737
  );
15737
15738
  return false;
15738
15739
  }
15740
+ if (sessionEpoch !== startEpoch) {
15741
+ return false;
15742
+ }
15739
15743
  setStoredKey(walletAddress, { legacy: candidates.legacy, current: candidates.current });
15740
15744
  cryptoKeyCache.delete(`${walletAddress}:v2`);
15741
15745
  cryptoKeyCache.delete(`${walletAddress}:v3`);
@@ -27359,6 +27363,16 @@ async function updateVaultMemoryOp(ctx, id, opts) {
27359
27363
  const probe = await ctx.vaultMemoryCollection.find(id);
27360
27364
  if (probe.isDeleted || probe.supersededBy || !isOwnedByCtxUser(ctx, probe)) return null;
27361
27365
  if (opts.freeFormOnly && isKinded(probe)) return null;
27366
+ const readStoredContent = probe._getRaw("content");
27367
+ if (opts.expectedContent !== void 0) {
27368
+ const current = await vaultMemoryToStored(
27369
+ probe,
27370
+ ctx.walletAddress,
27371
+ ctx.signMessage,
27372
+ ctx.embeddedWalletSigner
27373
+ );
27374
+ if (current.content !== opts.expectedContent) return null;
27375
+ }
27362
27376
  const levelAfter = (current) => {
27363
27377
  if (opts.level !== void 0) return opts.level;
27364
27378
  if (opts.scope === void 0) return resolveMemoryLevel(current.level, current.scope);
@@ -27366,7 +27380,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
27366
27380
  };
27367
27381
  assertValidKindLevel(opts.kind !== void 0 ? opts.kind : probe.kind, levelAfter(probe));
27368
27382
  const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
27369
- const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
27383
+ const encryptedContent = opts.content !== void 0 && ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
27370
27384
  opts.content,
27371
27385
  ctx.walletAddress,
27372
27386
  ctx.signMessage,
@@ -27374,13 +27388,13 @@ async function updateVaultMemoryOp(ctx, id, opts) {
27374
27388
  ) : opts.content;
27375
27389
  let stale = false;
27376
27390
  const record = probe;
27377
- const originalUpdatedAt = record.updatedAt.getTime();
27378
27391
  await ctx.database.write(async () => {
27379
27392
  await assertCanWrite2(ctx);
27380
- if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record) || opts.freeFormOnly && isKinded(record)) {
27393
+ if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record) || opts.freeFormOnly && isKinded(record) || opts.expectedContent !== void 0 && record._getRaw("content") !== readStoredContent) {
27381
27394
  stale = true;
27382
27395
  return;
27383
27396
  }
27397
+ const originalUpdatedAt = record.updatedAt.getTime();
27384
27398
  const nextKind = opts.kind !== void 0 ? opts.kind : record.kind;
27385
27399
  const nextLevel = levelAfter(record);
27386
27400
  assertValidKindLevel(nextKind, nextLevel);
@@ -27396,7 +27410,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
27396
27410
  replayedObservation = opts.observationSourceIds.every((id2) => observedSources.includes(id2));
27397
27411
  }
27398
27412
  await record.update((r) => {
27399
- r._setRaw("content", encryptedContent);
27413
+ if (encryptedContent !== void 0) r._setRaw("content", encryptedContent);
27400
27414
  if (opts.level !== void 0) {
27401
27415
  r._setRaw("level", nextLevel);
27402
27416
  r._setRaw("scope", scopeForLevel(nextLevel));
@@ -28163,7 +28177,7 @@ function classifyDecay(m, now, policy) {
28163
28177
  if (m.source === "manual" || m.source === SOURCE_PHOTO) return "keep";
28164
28178
  if (isTimeSensitiveType(m.factType) && m.eventTimeEnd !== null) {
28165
28179
  if (m.eventTimeEnd < now - resolved.pastEventGraceMs) return "archive";
28166
- if (m.eventTimeEnd >= now) return "keep";
28180
+ return "keep";
28167
28181
  }
28168
28182
  if (now - lastActivityAt(m) > ttlForType(m.factType, resolved)) return "archive";
28169
28183
  return "keep";
@@ -29821,6 +29835,104 @@ function validate(parsed, originalQuery) {
29821
29835
  return { mode, subQueries };
29822
29836
  }
29823
29837
 
29838
+ // src/lib/memoryVault/vaultPreparation.ts
29839
+ function createVaultPreparation() {
29840
+ return { corpora: /* @__PURE__ */ new WeakMap(), rows: /* @__PURE__ */ new WeakMap() };
29841
+ }
29842
+ var pendingRows = /* @__PURE__ */ new WeakMap();
29843
+ function loadVaultCorpus(ctx, options, preparation) {
29844
+ if (!preparation) return getAllVaultMemoriesOp(ctx, options);
29845
+ const corpusCache = preparation.corpora;
29846
+ let pending = corpusCache.get(ctx);
29847
+ if (!pending) {
29848
+ pending = /* @__PURE__ */ new Map();
29849
+ corpusCache.set(ctx, pending);
29850
+ }
29851
+ const key = JSON.stringify(options ?? {});
29852
+ let request = pending.get(key);
29853
+ if (!request) {
29854
+ const entries = pending;
29855
+ request = getAllVaultMemoriesOp(ctx, options).catch((error) => {
29856
+ entries.delete(key);
29857
+ throw error;
29858
+ });
29859
+ pending.set(key, request);
29860
+ }
29861
+ return request;
29862
+ }
29863
+ function rowRequestsFor(registry, ctx, maskInput) {
29864
+ let byMask = registry.get(ctx);
29865
+ if (!byMask) {
29866
+ byMask = /* @__PURE__ */ new Map();
29867
+ registry.set(ctx, byMask);
29868
+ }
29869
+ let requests = byMask.get(maskInput);
29870
+ if (!requests) {
29871
+ requests = /* @__PURE__ */ new Map();
29872
+ byMask.set(maskInput, requests);
29873
+ }
29874
+ return requests;
29875
+ }
29876
+ function embedVaultRows(ctx, options, rows, preparation) {
29877
+ const pending = rowRequestsFor(pendingRows, ctx, options.maskInput);
29878
+ const prepared = preparation && rowRequestsFor(preparation.rows, ctx, options.maskInput);
29879
+ const model = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
29880
+ const keys = rows.map(
29881
+ (row) => JSON.stringify([
29882
+ row.uniqueId,
29883
+ row.updatedAt?.getTime(),
29884
+ row.content,
29885
+ model,
29886
+ options.baseUrl,
29887
+ options.timeoutMs,
29888
+ options.tokenTimeoutMs,
29889
+ options.totalTimeoutMs
29890
+ ])
29891
+ );
29892
+ const missing = /* @__PURE__ */ new Map();
29893
+ rows.forEach((row, index) => {
29894
+ if (!pending.has(keys[index]) && !prepared?.has(keys[index])) missing.set(keys[index], row);
29895
+ });
29896
+ if (missing.size > 0) {
29897
+ const entries = pending;
29898
+ const batch = Promise.resolve().then(
29899
+ () => generateEmbeddings(
29900
+ [...missing.values()].map((row) => row.content),
29901
+ options
29902
+ )
29903
+ );
29904
+ [...missing].forEach(([key, row], index) => {
29905
+ const request = batch.then((vectors) => {
29906
+ const vector = vectors[index];
29907
+ updateVaultMemoryEmbeddingOp(ctx, row.uniqueId, JSON.stringify(vector), model, {
29908
+ content: row.content,
29909
+ updatedAt: row.updatedAt?.getTime()
29910
+ }).catch(() => {
29911
+ });
29912
+ return vector;
29913
+ }).finally(() => {
29914
+ entries.delete(key);
29915
+ if (entries.size === 0) pendingRows.get(ctx)?.delete(options.maskInput);
29916
+ });
29917
+ pending.set(key, request);
29918
+ });
29919
+ }
29920
+ return Promise.all(
29921
+ keys.map((key) => {
29922
+ const cached = prepared?.get(key);
29923
+ if (cached) return cached;
29924
+ const request = pending.get(key);
29925
+ if (!prepared) return request;
29926
+ const retained = request.catch((error) => {
29927
+ prepared.delete(key);
29928
+ throw error;
29929
+ });
29930
+ prepared.set(key, retained);
29931
+ return retained;
29932
+ })
29933
+ );
29934
+ }
29935
+
29824
29936
  // src/lib/memoryVault/vectorVersion.ts
29825
29937
  var vectorRowVersion = /* @__PURE__ */ new WeakMap();
29826
29938
  function contentFingerprint(content) {
@@ -30383,11 +30495,11 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
30383
30495
  return combined.slice(0, limit);
30384
30496
  }
30385
30497
  async function preEmbedVaultMemories(vaultCtx, embeddingOptions, cache, options) {
30386
- const memories = await getAllVaultMemoriesOp(vaultCtx, options);
30498
+ const memories = await loadVaultCorpus(vaultCtx, options);
30387
30499
  const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
30388
30500
  const uncachedTexts = [];
30389
30501
  const uncachedKeys = [];
30390
- const uncachedIds = [];
30502
+ const uncachedRows = [];
30391
30503
  const uncachedVersions = [];
30392
30504
  for (const m of memories) {
30393
30505
  const content = m.content;
@@ -30406,12 +30518,12 @@ async function preEmbedVaultMemories(vaultCtx, embeddingOptions, cache, options)
30406
30518
  }
30407
30519
  uncachedTexts.push(m.content);
30408
30520
  uncachedKeys.push(m.uniqueId);
30409
- uncachedIds.push(m.uniqueId);
30521
+ uncachedRows.push(m);
30410
30522
  uncachedVersions.push(m.updatedAt);
30411
30523
  }
30412
30524
  }
30413
30525
  if (uncachedTexts.length > 0) {
30414
- const embeddings = await generateEmbeddings(uncachedTexts, embeddingOptions);
30526
+ const embeddings = await embedVaultRows(vaultCtx, embeddingOptions, uncachedRows);
30415
30527
  for (let i = 0; i < uncachedKeys.length; i++) {
30416
30528
  cacheRowVector(
30417
30529
  cache,
@@ -30420,13 +30532,6 @@ async function preEmbedVaultMemories(vaultCtx, embeddingOptions, cache, options)
30420
30532
  uncachedVersions[i],
30421
30533
  uncachedTexts[i]
30422
30534
  );
30423
- updateVaultMemoryEmbeddingOp(
30424
- vaultCtx,
30425
- uncachedIds[i],
30426
- JSON.stringify(embeddings[i]),
30427
- currentModel
30428
- ).catch(() => {
30429
- });
30430
30535
  }
30431
30536
  }
30432
30537
  }
@@ -30568,10 +30673,7 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
30568
30673
  let laneVecs;
30569
30674
  if (opts.embedStats) opts.embedStats.rowsEmbedded += laneRows.length;
30570
30675
  try {
30571
- laneVecs = await generateEmbeddings(
30572
- laneRows.map((m) => m.content),
30573
- embeddingOptions
30574
- );
30676
+ laneVecs = await embedVaultRows(vaultCtx, embeddingOptions, laneRows);
30575
30677
  } catch (err) {
30576
30678
  laneEmbedFailed = true;
30577
30679
  getLogger().warn(
@@ -30585,13 +30687,6 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
30585
30687
  cacheRowVector(cache, m.uniqueId, vec, m.updatedAt, m.content);
30586
30688
  resolvedThisCall.add(m.uniqueId);
30587
30689
  vectored.push({ uniqueId: m.uniqueId, embedding: vec, updatedAt: m.updatedAt });
30588
- updateVaultMemoryEmbeddingOp(
30589
- vaultCtx,
30590
- m.uniqueId,
30591
- JSON.stringify(vecs[i]),
30592
- currentModel
30593
- ).catch(() => {
30594
- });
30595
30690
  });
30596
30691
  }
30597
30692
  }
@@ -30783,9 +30878,10 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
30783
30878
  };
30784
30879
  }
30785
30880
  } else {
30786
- const loaded = await getAllVaultMemoriesOp(
30881
+ const loaded = await loadVaultCorpus(
30787
30882
  vaultCtx,
30788
- Object.keys(queryOpts).length > 0 ? queryOpts : void 0
30883
+ Object.keys(queryOpts).length > 0 ? queryOpts : void 0,
30884
+ searchOptions?.vaultPreparation
30789
30885
  );
30790
30886
  vaultSize = loaded.length;
30791
30887
  rowsDecrypted = loaded.length;
@@ -30858,7 +30954,12 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
30858
30954
  let newEmbeddings;
30859
30955
  embedStats.rowsEmbedded += uncachedTexts.length;
30860
30956
  try {
30861
- newEmbeddings = await generateEmbeddings(uncachedTexts, embeddingOptions);
30957
+ newEmbeddings = await embedVaultRows(
30958
+ vaultCtx,
30959
+ embeddingOptions,
30960
+ uncachedIndices.map((index) => memories[index]),
30961
+ searchOptions?.vaultPreparation
30962
+ );
30862
30963
  } catch (err) {
30863
30964
  embeddingFailure = true;
30864
30965
  getLogger().warn(
@@ -30874,13 +30975,6 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
30874
30975
  memories[uncachedIndices[j]].updatedAt,
30875
30976
  memories[uncachedIndices[j]].content
30876
30977
  );
30877
- updateVaultMemoryEmbeddingOp(
30878
- vaultCtx,
30879
- memories[uncachedIndices[j]].uniqueId,
30880
- JSON.stringify(newEmbeddings[j]),
30881
- currentModel
30882
- ).catch(() => {
30883
- });
30884
30978
  }
30885
30979
  }
30886
30980
  }
@@ -31284,7 +31378,6 @@ async function retainWithPersistence(content, ctx, options = {}) {
31284
31378
  const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
31285
31379
  const resurrect = resurrectFields(existing);
31286
31380
  const updated = await ctx.persistence.update(targetId, {
31287
- content: existing.content,
31288
31381
  freeFormOnly: true,
31289
31382
  proofCountIncrement: 1,
31290
31383
  observationSourceIds: options.sourceChunkIds,
@@ -31488,7 +31581,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
31488
31581
  content: m.content,
31489
31582
  similarity: m.similarity
31490
31583
  }));
31491
- const { consolidateMemory: doConsolidate } = await import("./consolidate-B6OSCZU4.mjs");
31584
+ const { consolidateMemory: doConsolidate } = await import("./consolidate-PYED62LW.mjs");
31492
31585
  const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
31493
31586
  if (decision.action === "create") return decision.fallbackReason ? null : { create: true };
31494
31587
  if (decision.action === "supersede" && decision.content) {
@@ -31523,7 +31616,6 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
31523
31616
  const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
31524
31617
  const resurrect = resurrectFields(existing);
31525
31618
  const updated = await ctx.persistence.update(decision.targetId, {
31526
- content: existing.content,
31527
31619
  freeFormOnly: true,
31528
31620
  proofCountIncrement: 1,
31529
31621
  observationSourceIds: options.sourceChunkIds,
@@ -31551,6 +31643,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
31551
31643
  };
31552
31644
  }
31553
31645
  if (decision.action === "update" && decision.targetId && decision.content) {
31646
+ const expectedContent = candidates.find(
31647
+ (candidate) => candidate.id === decision.targetId
31648
+ )?.content;
31649
+ if (expectedContent === void 0) return null;
31554
31650
  const existing = await ctx.persistence.get(decision.targetId);
31555
31651
  if (!existing || existing.supersededBy) {
31556
31652
  return abandonToRace(
@@ -31558,6 +31654,9 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
31558
31654
  `update: target ${decision.targetId} ${existing ? "superseded" : "deleted"} before the write`
31559
31655
  );
31560
31656
  }
31657
+ if (existing.content !== expectedContent) {
31658
+ return abandonToRace(options, `update: target ${decision.targetId} edited before the write`);
31659
+ }
31561
31660
  const mergedSourceIds = unionStrings(
31562
31661
  existing.sourceChunkIds ?? [],
31563
31662
  options.sourceChunkIds ?? []
@@ -31570,6 +31669,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
31570
31669
  const resurrect = resurrectFields(existing);
31571
31670
  const updated = await ctx.persistence.update(decision.targetId, {
31572
31671
  content: decision.content,
31672
+ expectedContent,
31573
31673
  freeFormOnly: true,
31574
31674
  proofCountIncrement: 1,
31575
31675
  observationSourceIds: options.sourceChunkIds,
@@ -31582,10 +31682,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
31582
31682
  ...factTypeUpdate !== void 0 && { factType: factTypeUpdate }
31583
31683
  });
31584
31684
  if (!updated) {
31585
- await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
31685
+ await assertMergeTargetGoneOrThrow(ctx, decision.targetId, expectedContent);
31586
31686
  return abandonToRace(
31587
31687
  options,
31588
- `update: target ${decision.targetId} deleted mid-write (consolidated rewrite lost)`
31688
+ `update: target ${decision.targetId} changed mid-write (consolidated rewrite lost)`
31589
31689
  );
31590
31690
  }
31591
31691
  cacheRowVector(
@@ -31612,9 +31712,9 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
31612
31712
  );
31613
31713
  return null;
31614
31714
  }
31615
- async function assertMergeTargetGoneOrThrow(ctx, targetId) {
31715
+ async function assertMergeTargetGoneOrThrow(ctx, targetId, expectedContent) {
31616
31716
  const stillExists = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(targetId) : ctx.persistence.get(targetId));
31617
- if (stillExists && (stillExists.kind === null || stillExists.kind === void 0)) {
31717
+ if (stillExists && (stillExists.kind === null || stillExists.kind === void 0) && (expectedContent === void 0 || stillExists.content === expectedContent)) {
31618
31718
  throw new RetainError(
31619
31719
  "merge-not-persisted",
31620
31720
  `retain: merge into memory ${targetId} failed to persist`
@@ -33447,6 +33547,7 @@ async function recall(query, ctx, options = {}) {
33447
33547
  },
33448
33548
  ...options.rrfK !== void 0 && { rrfK: options.rrfK },
33449
33549
  ...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
33550
+ ...options.vaultPreparation && { vaultPreparation: options.vaultPreparation },
33450
33551
  ...subQueries && { subQueries },
33451
33552
  ...options.scopes && { scopes: options.scopes },
33452
33553
  ...options.folderId !== void 0 && { folderId: options.folderId },
@@ -34869,13 +34970,20 @@ async function synthesizeProfile(ctx, options = {}) {
34869
34970
  }
34870
34971
  }
34871
34972
  }
34973
+ const vaultPreparation = createVaultPreparation();
34872
34974
  const settled = await Promise.allSettled(
34873
34975
  facets.map(async (facet) => {
34874
34976
  const prior = previous?.sections.find((s) => s.key === facet.key);
34875
34977
  if (prior && !staleKeys.has(facet.key)) {
34876
34978
  return prior;
34877
34979
  }
34878
- return synthesizeFacet(facet, recallCtx, options, fallbackPriors.get(facet.key));
34980
+ return synthesizeFacet(
34981
+ facet,
34982
+ recallCtx,
34983
+ options,
34984
+ fallbackPriors.get(facet.key),
34985
+ vaultPreparation
34986
+ );
34879
34987
  })
34880
34988
  );
34881
34989
  const sections = settled.map((r, i) => {
@@ -35029,7 +35137,7 @@ async function attributeFacts(ctx, candidates, facets) {
35029
35137
  }
35030
35138
  return keys;
35031
35139
  }
35032
- async function synthesizeFacet(facet, ctx, options, prior) {
35140
+ async function synthesizeFacet(facet, ctx, options, prior, vaultPreparation) {
35033
35141
  const scopes = options.scopes ?? DEFAULT_SCOPES;
35034
35142
  const limit = options.limit ?? DEFAULT_FACET_RECALL_LIMIT;
35035
35143
  const factTypeWeights = { ...DEFAULT_PROFILE_FACT_TYPE_WEIGHTS, ...options.factTypeWeights };
@@ -35046,6 +35154,7 @@ async function synthesizeFacet(facet, ctx, options, prior) {
35046
35154
  };
35047
35155
  }
35048
35156
  const recalled = await recall(facet.query, ctx, {
35157
+ vaultPreparation,
35049
35158
  scopes,
35050
35159
  limit: hasReviewGate ? RECALL_MAX_LIMIT : limit,
35051
35160
  types: ["fact"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anuma/sdk",
3
- "version": "9.1.4",
3
+ "version": "9.1.6",
4
4
  "description": "",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",