@anuma/sdk 7.0.3 → 7.0.4-next.20261015010856

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.
@@ -3731,8 +3731,9 @@ async function updateConversationPinnedOp(ctx, id, pinned) {
3731
3731
  }
3732
3732
  return false;
3733
3733
  }
3734
- async function getMessagesOp(ctx, convId) {
3735
- const results = await ctx.messagesCollection.query(import_watermelondb2.Q.where("conversation_id", convId), import_watermelondb2.Q.sortBy("message_id", import_watermelondb2.Q.asc)).unsafeFetchRaw();
3734
+ async function getMessagesOp(ctx, convId, opts) {
3735
+ const fetched = await ctx.messagesCollection.query(import_watermelondb2.Q.where("conversation_id", convId), import_watermelondb2.Q.sortBy("message_id", import_watermelondb2.Q.asc)).unsafeFetchRaw();
3736
+ const results = opts?.rawFilter ? fetched.filter(opts.rawFilter) : fetched;
3736
3737
  return Promise.all(
3737
3738
  results.map(
3738
3739
  (raw) => messageRawToStored(raw, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
@@ -5885,6 +5886,37 @@ async function chunkAndEmbedMessage(ctx, messageId, options) {
5885
5886
  }));
5886
5887
  return updateMessageChunksOp(ctx, messageId, messageChunks, embeddingModel);
5887
5888
  }
5889
+ var MIN_SEALED_EMBEDDING_HEX = 256;
5890
+ function rawHasEmbedding(value) {
5891
+ if (Array.isArray(value)) return value.length > 0;
5892
+ if (typeof value !== "string" || value.length === 0) return false;
5893
+ if (isEncrypted(value)) {
5894
+ return value.length - value.indexOf(":", 4) - 1 >= MIN_SEALED_EMBEDDING_HEX;
5895
+ }
5896
+ try {
5897
+ const parsed = JSON.parse(value);
5898
+ return Array.isArray(parsed) && parsed.length > 0;
5899
+ } catch {
5900
+ return false;
5901
+ }
5902
+ }
5903
+ function sealedVersion(value) {
5904
+ if (typeof value !== "string" || !isEncrypted(value)) return null;
5905
+ return value.startsWith("enc:v2:") ? "v2" : "v3";
5906
+ }
5907
+ function mayNeedChunkEmbedding(raw, embeddingModel, filter) {
5908
+ const role = raw.role;
5909
+ if (role === "system") return false;
5910
+ if (filter?.roles && !filter.roles.includes(role ?? "")) return false;
5911
+ if (isNonEmbeddableOrigin(raw.origin, filter?.reembedDiscarded)) {
5912
+ return false;
5913
+ }
5914
+ const model = raw.embedding_model;
5915
+ if (typeof model === "string" && model !== embeddingModel) return true;
5916
+ if (rawHasEmbedding(raw.chunks)) return false;
5917
+ if (rawHasEmbedding(raw.vector) && !filter?.rechunkExisting) return false;
5918
+ return true;
5919
+ }
5888
5920
  async function chunkAndEmbedAllMessages(ctx, options, filter) {
5889
5921
  const embeddingModel = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
5890
5922
  const { chunkSize = DEFAULT_CHUNK_SIZE } = options;
@@ -5897,11 +5929,31 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
5897
5929
  let considered = 0;
5898
5930
  let sealedRowsSeen = 0;
5899
5931
  let rowsSeen = 0;
5932
+ const keptSealed = /* @__PURE__ */ new Map();
5933
+ const candidatesStillSealed = /* @__PURE__ */ new Map();
5934
+ const droppedSealed = /* @__PURE__ */ new Map();
5935
+ const rawFilter = (raw) => {
5936
+ rowsSeen++;
5937
+ const keep = mayNeedChunkEmbedding(raw, embeddingModel, filter);
5938
+ const version = sealedVersion(raw.content);
5939
+ if (!version) return keep;
5940
+ if (keep) {
5941
+ keptSealed.set(version, (keptSealed.get(version) ?? 0) + 1);
5942
+ } else {
5943
+ const dropped = droppedSealed.get(version);
5944
+ if (dropped) dropped.count++;
5945
+ else droppedSealed.set(version, { count: 1, probeId: raw.id });
5946
+ }
5947
+ return keep;
5948
+ };
5900
5949
  for (const conv of targetConversations) {
5901
- const messages = await getMessagesOp(ctx, conv.conversationId);
5950
+ const messages = await getMessagesOp(ctx, conv.conversationId, { rawFilter });
5902
5951
  for (const message of messages) {
5903
- rowsSeen++;
5904
- if (isEncrypted(message.content)) sealedRowsSeen++;
5952
+ const stillSealed = sealedVersion(message.content);
5953
+ if (stillSealed) {
5954
+ sealedRowsSeen++;
5955
+ candidatesStillSealed.set(stillSealed, (candidatesStillSealed.get(stillSealed) ?? 0) + 1);
5956
+ }
5905
5957
  const isStale = message.embeddingModel !== void 0 && message.embeddingModel !== null && message.embeddingModel !== embeddingModel;
5906
5958
  if (message.chunks && message.chunks.length > 0 && !isStale) continue;
5907
5959
  const hasVector = message.vector && message.vector.length > 0;
@@ -5914,6 +5966,7 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
5914
5966
  stillEncrypted++;
5915
5967
  continue;
5916
5968
  }
5969
+ if (isToolResultsRow(message)) continue;
5917
5970
  if (message.content.length < minLength) continue;
5918
5971
  if (shouldChunkMessage(message.content, chunkSize)) {
5919
5972
  longMessages.push({
@@ -5925,6 +5978,12 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
5925
5978
  }
5926
5979
  }
5927
5980
  }
5981
+ for (const [version, dropped] of droppedSealed) {
5982
+ const keyOpenedACandidate = (keptSealed.get(version) ?? 0) > (candidatesStillSealed.get(version) ?? 0);
5983
+ if (keyOpenedACandidate) continue;
5984
+ const probe = await getMessageOp(ctx, dropped.probeId);
5985
+ if (!probe || isEncrypted(probe.content)) sealedRowsSeen += dropped.count;
5986
+ }
5928
5987
  if (stillEncrypted > 0 || sealedRowsSeen > 0) {
5929
5988
  getLogger().error(
5930
5989
  "memoryEngine: messages still encrypted (key unavailable?) \u2014 excluded from embedding",
@@ -12639,6 +12698,11 @@ init_logger();
12639
12698
 
12640
12699
  // src/lib/db/entities/operations.ts
12641
12700
  var import_watermelondb19 = require("@nozbe/watermelondb");
12701
+ async function assertCanWrite(ctx) {
12702
+ if (ctx.canWrite && !await ctx.canWrite()) {
12703
+ throw new Error("Memory source is no longer eligible");
12704
+ }
12705
+ }
12642
12706
  function entityToStored(e) {
12643
12707
  return {
12644
12708
  uniqueId: e.id,
@@ -12779,6 +12843,7 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
12779
12843
  let skipped = false;
12780
12844
  let entities = [];
12781
12845
  await ctx.database.write(async () => {
12846
+ await assertCanWrite(ctx);
12782
12847
  const {
12783
12848
  entities: byName,
12784
12849
  operations: entityOps,
@@ -12854,6 +12919,7 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
12854
12919
  let skipped = false;
12855
12920
  let entities = [];
12856
12921
  await ctx.database.write(async () => {
12922
+ await assertCanWrite(ctx);
12857
12923
  const vaultRow = await findVaultRowInWrite(ctx, memoryId);
12858
12924
  if (options.guarded && autoLinkBlocked(vaultRow)) {
12859
12925
  skipped = true;
@@ -12914,6 +12980,7 @@ async function unlinkMemoryEntitiesOp(ctx, memoryIds) {
12914
12980
  const links = await ctx.memoryEntityCollection.query(import_watermelondb19.Q.where("memory_id", import_watermelondb19.Q.oneOf(Array.from(memoryIds)))).fetch();
12915
12981
  if (links.length === 0) return;
12916
12982
  await ctx.database.write(async () => {
12983
+ await assertCanWrite(ctx);
12917
12984
  await ctx.database.batch(...links.map((l) => l.prepareDestroyPermanently()));
12918
12985
  });
12919
12986
  }
@@ -12922,6 +12989,7 @@ async function unlinkAllMemoryEntitiesForUserOp(ctx, userId) {
12922
12989
  const links = await ctx.memoryEntityCollection.query(import_watermelondb19.Q.where("user_id", userId)).fetch();
12923
12990
  if (links.length === 0) return;
12924
12991
  await ctx.database.write(async () => {
12992
+ await assertCanWrite(ctx);
12925
12993
  await ctx.database.batch(...links.map((l) => l.prepareDestroyPermanently()));
12926
12994
  });
12927
12995
  }
@@ -13086,6 +13154,11 @@ function visibilityConditions(requested) {
13086
13154
  function isKinded(record2) {
13087
13155
  return record2.kind !== null && record2.kind !== void 0;
13088
13156
  }
13157
+ async function assertCanWrite2(ctx) {
13158
+ if (ctx.canWrite && !await ctx.canWrite()) {
13159
+ throw new Error("Memory source is no longer eligible");
13160
+ }
13161
+ }
13089
13162
  function assertValidKindLevel(kind, level) {
13090
13163
  const hasKind = kind !== null && kind !== void 0;
13091
13164
  if (hasKind && !MEMORY_KINDS.includes(kind)) {
@@ -13266,8 +13339,7 @@ async function createVaultMemoryOp(ctx, opts) {
13266
13339
  ctx.embeddedWalletSigner
13267
13340
  ) : opts.content;
13268
13341
  const created = await ctx.database.write(async () => {
13269
- if (ctx.canWrite && !await ctx.canWrite())
13270
- throw new Error("Memory source is no longer eligible");
13342
+ await assertCanWrite2(ctx);
13271
13343
  return ctx.vaultMemoryCollection.create(
13272
13344
  (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue)
13273
13345
  );
@@ -13286,8 +13358,7 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
13286
13358
  ) : opts.content;
13287
13359
  let createdRecord = null;
13288
13360
  await ctx.database.write(async () => {
13289
- if (ctx.canWrite && !await ctx.canWrite())
13290
- throw new Error("Memory source is no longer eligible");
13361
+ await assertCanWrite2(ctx);
13291
13362
  let target;
13292
13363
  try {
13293
13364
  target = await ctx.vaultMemoryCollection.find(targetId);
@@ -13379,8 +13450,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
13379
13450
  })
13380
13451
  );
13381
13452
  const created = await ctx.database.write(async () => {
13382
- if (ctx.canWrite && !await ctx.canWrite())
13383
- throw new Error("Memory source is no longer eligible");
13453
+ await assertCanWrite2(ctx);
13384
13454
  const prepared = optionsArray.map(
13385
13455
  (opts, i) => ctx.vaultMemoryCollection.prepareCreate(
13386
13456
  (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i], encryptedKindValues[i])
@@ -13685,8 +13755,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
13685
13755
  const record2 = probe;
13686
13756
  const originalUpdatedAt = record2.updatedAt.getTime();
13687
13757
  await ctx.database.write(async () => {
13688
- if (ctx.canWrite && !await ctx.canWrite())
13689
- throw new Error("Memory source is no longer eligible");
13758
+ await assertCanWrite2(ctx);
13690
13759
  if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2) || opts.freeFormOnly && isKinded(record2)) {
13691
13760
  stale = true;
13692
13761
  return;
@@ -13797,6 +13866,7 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
13797
13866
  let stale = false;
13798
13867
  const originalUpdatedAt = record2.updatedAt.getTime();
13799
13868
  await ctx.database.write(async (writer) => {
13869
+ await assertCanWrite2(ctx);
13800
13870
  if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
13801
13871
  stale = true;
13802
13872
  return;
@@ -13838,6 +13908,7 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
13838
13908
  const originalUpdatedAt = record2.updatedAt.getTime();
13839
13909
  let cleared = false;
13840
13910
  await ctx.database.write(async () => {
13911
+ await assertCanWrite2(ctx);
13841
13912
  if (options?.unlessTopicsRecorded && parseTopics(record2.topics) !== null) return;
13842
13913
  cleared = true;
13843
13914
  await record2.update((r) => {
@@ -13861,6 +13932,7 @@ async function setMemoryVisibilityOp(ctx, id, opts) {
13861
13932
  if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
13862
13933
  let stale = false;
13863
13934
  await ctx.database.write(async () => {
13935
+ await assertCanWrite2(ctx);
13864
13936
  if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
13865
13937
  stale = true;
13866
13938
  return;
@@ -13889,6 +13961,7 @@ async function deleteVaultMemoryOp(ctx, id) {
13889
13961
  if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
13890
13962
  let stale = false;
13891
13963
  await ctx.database.write(async () => {
13964
+ await assertCanWrite2(ctx);
13892
13965
  if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
13893
13966
  stale = true;
13894
13967
  return;
@@ -13926,8 +13999,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
13926
13999
  }
13927
14000
  let stale = false;
13928
14001
  await ctx.database.write(async () => {
13929
- if (ctx.canWrite && !await ctx.canWrite())
13930
- throw new Error("Memory source is no longer eligible");
14002
+ await assertCanWrite2(ctx);
13931
14003
  if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
13932
14004
  stale = true;
13933
14005
  return;
@@ -14089,6 +14161,7 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
14089
14161
  for (let i = 0; i < uniqueIds.length; i += CHUNK) {
14090
14162
  const chunkIds = uniqueIds.slice(i, i + CHUNK);
14091
14163
  await ctx.database.write(async () => {
14164
+ await assertCanWrite2(ctx);
14092
14165
  const records = [];
14093
14166
  for (const id of chunkIds) {
14094
14167
  try {
@@ -14122,6 +14195,7 @@ async function relinkMemoryTopicsOp(ctx, memoryIds) {
14122
14195
  for (const id of Array.from(new Set(memoryIds))) {
14123
14196
  try {
14124
14197
  await ctx.database.write(async (writer) => {
14198
+ await assertCanWrite2(ctx);
14125
14199
  let record2;
14126
14200
  try {
14127
14201
  record2 = await ctx.vaultMemoryCollection.find(id);
@@ -14152,6 +14226,7 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
14152
14226
  for (let i = 0; i < uniqueIds.length; i += CHUNK) {
14153
14227
  const chunkIds = uniqueIds.slice(i, i + CHUNK);
14154
14228
  await ctx.database.write(async () => {
14229
+ await assertCanWrite2(ctx);
14155
14230
  const writes = [];
14156
14231
  for (const id of chunkIds) {
14157
14232
  let record2;
@@ -14184,6 +14259,7 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
14184
14259
  const records = await ctx.vaultMemoryCollection.query(import_watermelondb20.Q.where("user_id", userId), import_watermelondb20.Q.where("is_deleted", false)).fetch();
14185
14260
  if (records.length === 0) return 0;
14186
14261
  await ctx.database.write(async () => {
14262
+ await assertCanWrite2(ctx);
14187
14263
  const prepared = records.map(
14188
14264
  (record2) => record2.prepareUpdate((r) => {
14189
14265
  r._setRaw("is_deleted", true);
@@ -14238,6 +14314,7 @@ async function archiveVaultMemoryOp(ctx, id, opts) {
14238
14314
  let stale = false;
14239
14315
  const archivedAtValue = opts?.now ?? Date.now();
14240
14316
  await ctx.database.write(async () => {
14317
+ await assertCanWrite2(ctx);
14241
14318
  if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || record2.archivedAt !== null) {
14242
14319
  stale = true;
14243
14320
  return;
@@ -14261,6 +14338,7 @@ async function restoreVaultMemoryOp(ctx, id) {
14261
14338
  if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
14262
14339
  let stale = false;
14263
14340
  await ctx.database.write(async () => {
14341
+ await assertCanWrite2(ctx);
14264
14342
  if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
14265
14343
  stale = true;
14266
14344
  return;
@@ -14281,6 +14359,7 @@ async function hardDeleteDecayedOp(ctx, id, opts) {
14281
14359
  const now = opts.now ?? Date.now();
14282
14360
  let stale = false;
14283
14361
  await ctx.database.write(async () => {
14362
+ await assertCanWrite2(ctx);
14284
14363
  const archivedAt = record2.archivedAt;
14285
14364
  if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
14286
14365
  stale = true;
@@ -14320,6 +14399,7 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding2, embeddingModel,
14320
14399
  }
14321
14400
  let written = false;
14322
14401
  await ctx.database.write(async () => {
14402
+ await assertCanWrite2(ctx);
14323
14403
  if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return;
14324
14404
  const originalUpdatedAt = record2.updatedAt.getTime();
14325
14405
  if (originalUpdatedAt !== readUpdatedAt || record2._getRaw("content") !== readStoredContent)
@@ -17856,6 +17936,13 @@ function restoreCandidates(candidates, redactor, ownNames) {
17856
17936
  ).map((c) => c.candidate);
17857
17937
  }
17858
17938
  async function extractAndRetain(messages, retainCtx, options) {
17939
+ const { memoryStore, signal } = options;
17940
+ if (memoryStore === null) throw new Error("Memory store is not ready");
17941
+ if (memoryStore && options.folderId !== void 0 && options.folderId !== null)
17942
+ throw new Error("Remote memory extraction does not support folders");
17943
+ if (memoryStore && options.extract.piiRedaction && !memoryStore.masksEmbeddingInput)
17944
+ throw new Error("PII-redacted extraction requires a memory store that masks embedding inputs");
17945
+ signal?.throwIfAborted();
17859
17946
  const minConfidence = options.minConfidence ?? DEFAULT_MIN_CONFIDENCE;
17860
17947
  const resolvedConsolidatePii = options.consolidateOptions?.piiRedaction ?? options.extract.piiRedaction;
17861
17948
  const consolidateOptions = options.consolidateOptions !== void 0 ? {
@@ -17889,6 +17976,7 @@ async function extractAndRetain(messages, retainCtx, options) {
17889
17976
  }
17890
17977
  });
17891
17978
  const extractMs = Date.now() - tExtract;
17979
+ signal?.throwIfAborted();
17892
17980
  const filtered = candidates.filter((c) => c.confidence >= minConfidence);
17893
17981
  const log = getLogger();
17894
17982
  const screened = screenCandidatesForInjection(filtered);
@@ -17936,16 +18024,33 @@ async function extractAndRetain(messages, retainCtx, options) {
17936
18024
  const results = [];
17937
18025
  const quarantinedInfo = [];
17938
18026
  let failedWrites = 0;
18027
+ let auditRows;
17939
18028
  const tRetain = Date.now();
17940
18029
  for (const { candidate, isQuarantined, reason, signature } of toRetain) {
17941
18030
  try {
18031
+ signal?.throwIfAborted();
17942
18032
  if (isQuarantined) {
17943
- const existingId = await findQuarantinedDuplicateOp(
17944
- retainCtx.vaultCtx,
17945
- candidate.content,
17946
- candidate.sourceMessageIds,
17947
- { scope: options.scope ?? "private", folderId: options.folderId ?? null }
17948
- ).catch(() => null);
18033
+ let existingId;
18034
+ if (memoryStore) {
18035
+ auditRows ?? (auditRows = memoryStore.list({
18036
+ scopes: [options.scope ?? "private"],
18037
+ includeArchived: true,
18038
+ includeQuarantined: true,
18039
+ includeSuperseded: true
18040
+ }));
18041
+ const sourceKey = [...new Set(candidate.sourceMessageIds)].sort().join("\0");
18042
+ const normalize = (value) => value.normalize("NFKC").trim().replace(/\s+/g, " ").toLowerCase();
18043
+ existingId = (await auditRows).find(
18044
+ (row) => row.trustTier === "quarantined" && row.scope === (options.scope ?? "private") && [...new Set(row.sourceChunkIds ?? [])].sort().join("\0") === sourceKey && normalize(row.content) === normalize(candidate.content)
18045
+ )?.uniqueId ?? null;
18046
+ } else {
18047
+ existingId = await findQuarantinedDuplicateOp(
18048
+ retainCtx.vaultCtx,
18049
+ candidate.content,
18050
+ candidate.sourceMessageIds,
18051
+ { scope: options.scope ?? "private", folderId: options.folderId ?? null }
18052
+ ).catch(() => null);
18053
+ }
17949
18054
  if (existingId) {
17950
18055
  quarantinedInfo.push({
17951
18056
  candidate,
@@ -17956,18 +18061,26 @@ async function extractAndRetain(messages, retainCtx, options) {
17956
18061
  continue;
17957
18062
  }
17958
18063
  }
17959
- const result = await retain(candidate.content, retainCtx, {
18064
+ const retainOptions = {
17960
18065
  source: "auto-extracted",
17961
18066
  sourceChunkIds: candidate.sourceMessageIds,
17962
18067
  respectTombstones: true,
17963
18068
  ...options.scope !== void 0 && { scope: options.scope },
17964
- ...options.folderId !== void 0 && { folderId: options.folderId },
17965
18069
  ...consolidateOptions !== void 0 && { consolidateOptions },
17966
18070
  ...candidate.eventTime !== null && { eventTime: candidate.eventTime },
17967
18071
  factType: candidate.type,
17968
18072
  ...isQuarantined && { trustTier: "quarantined", enableAutoMerge: false }
18073
+ };
18074
+ const result = memoryStore ? await memoryStore.retain(candidate.content, {
18075
+ ...retainOptions,
18076
+ canWrite: retainCtx.vaultCtx.canWrite,
18077
+ signal
18078
+ }) : await retain(candidate.content, retainCtx, {
18079
+ ...retainOptions,
18080
+ ...options.folderId !== void 0 && { folderId: options.folderId }
17969
18081
  });
17970
18082
  if (isQuarantined) {
18083
+ auditRows = void 0;
17971
18084
  const info = {
17972
18085
  candidate,
17973
18086
  memoryId: result.memoryId,
@@ -17986,9 +18099,16 @@ async function extractAndRetain(messages, retainCtx, options) {
17986
18099
  }
17987
18100
  succeededCandidates.push(candidate);
17988
18101
  results.push(result);
17989
- if (result.action !== "suppressed" && options.entityCtx && candidate.entities.length > 0) {
18102
+ if (result.action !== "suppressed" && candidate.entities.length > 0) {
17990
18103
  try {
17991
- if (!await isMemoryTopicsUserManaged(options.entityCtx, result.memoryId)) {
18104
+ signal?.throwIfAborted();
18105
+ if (memoryStore) {
18106
+ await memoryStore.addTopics(result.memoryId, candidate.entities, {
18107
+ unlessUserManaged: true,
18108
+ canWrite: retainCtx.vaultCtx.canWrite,
18109
+ signal
18110
+ });
18111
+ } else if (options.entityCtx && !await isMemoryTopicsUserManaged(options.entityCtx, result.memoryId)) {
17992
18112
  await linkMemoryEntitiesOp(options.entityCtx, result.memoryId, candidate.entities, {
17993
18113
  unlessTopicsUserManaged: true
17994
18114
  });
@@ -18238,7 +18358,7 @@ function createAutoExtractor(options) {
18238
18358
  };
18239
18359
  const consolidateOptions = options.consolidate ? { ...options.consolidate, ...subPassAuth(options.consolidate.baseUrl) } : void 0;
18240
18360
  const injectionClassifierOptions = options.injectionClassifier ? { ...options.injectionClassifier, ...subPassAuth(options.injectionClassifier.baseUrl) } : void 0;
18241
- if (options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
18361
+ if (!options.memoryStore && options.retainCtx.vaultCtx.entityCtx && !options.entityCtx) {
18242
18362
  getLogger().warn(
18243
18363
  "[memory/extract] retainCtx.vaultCtx.entityCtx is set but extractor was created without `entityCtx` \u2014 W5 graph lane will receive no writes"
18244
18364
  );
@@ -18283,6 +18403,8 @@ function createAutoExtractor(options) {
18283
18403
  try {
18284
18404
  const { candidates, results, failedCount, outcome: outcome2, failure, funnel, timings, model } = await extractAndRetain(window2, retainCtx, {
18285
18405
  extract,
18406
+ memoryStore: options.memoryStore,
18407
+ signal: options.signal,
18286
18408
  ...options.minConfidence !== void 0 && { minConfidence: options.minConfidence },
18287
18409
  ...options.entityCtx !== void 0 && { entityCtx: options.entityCtx },
18288
18410
  ...options.scope !== void 0 && { scope: options.scope },
@@ -20384,6 +20506,7 @@ function createLocalMemoryStore(options) {
20384
20506
  database,
20385
20507
  entityCollection: database.get("entity"),
20386
20508
  memoryEntityCollection: database.get("memory_entity"),
20509
+ canWrite: options.canWrite,
20387
20510
  ...userId !== void 0 && { userId },
20388
20511
  ...options.allowUnscopedRows !== void 0 && {
20389
20512
  allowUnscopedRows: options.allowUnscopedRows
@@ -20395,10 +20518,21 @@ function createLocalMemoryStore(options) {
20395
20518
  walletAddress: options.walletAddress,
20396
20519
  signMessage: options.signMessage,
20397
20520
  embeddedWalletSigner: options.embeddedWalletSigner,
20521
+ canWrite: options.canWrite,
20398
20522
  ...userId !== void 0 && { userId },
20399
20523
  ...options.singleTenant !== void 0 && { singleTenant: options.singleTenant },
20400
20524
  entityCtx
20401
20525
  };
20526
+ const assertWrite = async (writeOptions) => {
20527
+ writeOptions?.signal?.throwIfAborted();
20528
+ if (writeOptions?.canWrite && !await writeOptions.canWrite()) {
20529
+ throw new Error("Memory source is no longer eligible");
20530
+ }
20531
+ if (options.canWrite && !await options.canWrite()) {
20532
+ throw new Error("Memory source is no longer eligible");
20533
+ }
20534
+ writeOptions?.signal?.throwIfAborted();
20535
+ };
20402
20536
  const vaultCache = options.vaultCache ?? createVaultEmbeddingCache();
20403
20537
  const ownedBy = userId !== void 0 ? [import_watermelondb23.Q.where("user_id", userId)] : [];
20404
20538
  const linksOwnedBy = userId === void 0 ? [] : options.allowUnscopedRows ? [import_watermelondb23.Q.or(import_watermelondb23.Q.where("user_id", userId), import_watermelondb23.Q.where("user_id", null))] : [import_watermelondb23.Q.where("user_id", userId)];
@@ -20510,9 +20644,25 @@ function createLocalMemoryStore(options) {
20510
20644
  archive: (id) => archiveVaultMemoryOp(vaultCtx, id),
20511
20645
  restore: (id) => restoreVaultMemoryOp(vaultCtx, id),
20512
20646
  setTopics: (memoryId, topics) => setMemoryEntitiesOp(vaultCtx, memoryId, topics),
20513
- addTopics: (memoryId, topics) => database.write(async (writer) => {
20647
+ addTopics: (memoryId, topics, writeOptions) => database.write(async (writer) => {
20648
+ await assertWrite(writeOptions);
20514
20649
  const owned = await vaultCtx.vaultMemoryCollection.query(import_watermelondb23.Q.where("id", memoryId), import_watermelondb23.Q.where("is_deleted", false), ...ownedBy).fetchCount();
20515
- return owned > 0 ? writer.callWriter(() => linkMemoryEntitiesOp(entityCtx, memoryId, topics)) : [];
20650
+ return owned > 0 ? writer.callWriter(
20651
+ () => linkMemoryEntitiesOp(
20652
+ {
20653
+ ...entityCtx,
20654
+ canWrite: async () => {
20655
+ await assertWrite(writeOptions);
20656
+ return true;
20657
+ }
20658
+ },
20659
+ memoryId,
20660
+ topics,
20661
+ {
20662
+ unlessTopicsUserManaged: writeOptions?.unlessUserManaged
20663
+ }
20664
+ )
20665
+ ) : [];
20516
20666
  }),
20517
20667
  setVisibility: (id, visibility, visibilityOptions) => setMemoryVisibilityOp(vaultCtx, id, { visibility, ...visibilityOptions }),
20518
20668
  recall: (query, recallOptions) => recall(
@@ -20522,7 +20672,17 @@ function createLocalMemoryStore(options) {
20522
20672
  ),
20523
20673
  retain: (content, retainOptions) => retain(
20524
20674
  content,
20525
- { vaultCtx, embeddingOptions: options.embeddingOptions, vaultCache },
20675
+ {
20676
+ vaultCtx: {
20677
+ ...vaultCtx,
20678
+ canWrite: async () => {
20679
+ await assertWrite(retainOptions);
20680
+ return true;
20681
+ }
20682
+ },
20683
+ embeddingOptions: options.embeddingOptions,
20684
+ vaultCache
20685
+ },
20526
20686
  retainOptions
20527
20687
  ),
20528
20688
  factSource: {
@@ -21161,7 +21321,14 @@ function stored(row) {
21161
21321
  function createRemoteMemoryPipeline(options) {
21162
21322
  const { persistence, embeddingOptions } = options;
21163
21323
  const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
21164
- const operation = (mode) => {
21324
+ const operation = (mode, writeOptions) => {
21325
+ const signal = writeOptions?.signal;
21326
+ const assertWrite = async () => {
21327
+ signal?.throwIfAborted();
21328
+ if (writeOptions?.canWrite && !await writeOptions.canWrite())
21329
+ throw new Error("Memory source is no longer eligible");
21330
+ signal?.throwIfAborted();
21331
+ };
21165
21332
  const rejectUndecryptable = (failed) => {
21166
21333
  if (!failed.length) return;
21167
21334
  if (mode === "retain")
@@ -21179,7 +21346,7 @@ function createRemoteMemoryPipeline(options) {
21179
21346
  return items.map((item) => stored(item.memory));
21180
21347
  };
21181
21348
  const get = async (id) => {
21182
- const snapshot = snapshots.get(id) ?? await persistence.get(id);
21349
+ const snapshot = snapshots.get(id) ?? await (signal ? persistence.get(id, signal) : persistence.get(id));
21183
21350
  if (!snapshot || snapshot.memory.is_deleted || snapshot.memory.superseded_by) return null;
21184
21351
  snapshots.set(id, snapshot);
21185
21352
  return stored(snapshot.memory);
@@ -21225,7 +21392,7 @@ function createRemoteMemoryPipeline(options) {
21225
21392
  if (forced.size < 100 && temporal[i] !== void 0) forced.add(temporal[i]);
21226
21393
  }
21227
21394
  const forceIds = [...forced];
21228
- const windowOptions = (i, signal) => ({
21395
+ const windowOptions = (i, signal2) => ({
21229
21396
  limit: Math.min(100, Math.max((search.limit ?? 8) * 3, 30)),
21230
21397
  force_ids: i === 0 ? forceIds : [],
21231
21398
  ...search.scopes && { scopes: search.scopes },
@@ -21233,13 +21400,15 @@ function createRemoteMemoryPipeline(options) {
21233
21400
  ...search.memoryIds !== void 0 && { memory_ids: search.memoryIds },
21234
21401
  include_archived: search.includeArchived,
21235
21402
  embedding_model: model,
21236
- ...signal && { signal }
21403
+ ...signal2 && { signal: signal2 }
21237
21404
  });
21238
21405
  const vectors = [queryEmbedding, ...facetEmbeddings];
21239
21406
  let windows;
21240
21407
  if (mode === "retain") {
21241
21408
  windows = await Promise.all(
21242
- vectors.map((embedding2, i) => persistence.candidateSet(embedding2, windowOptions(i)))
21409
+ vectors.map(
21410
+ (embedding2, i) => persistence.candidateSet(embedding2, windowOptions(i, signal))
21411
+ )
21243
21412
  );
21244
21413
  } else {
21245
21414
  const deadline = new AbortController();
@@ -21327,12 +21496,15 @@ function createRemoteMemoryPipeline(options) {
21327
21496
  twin_opt_in: false
21328
21497
  };
21329
21498
  };
21330
- const write = async (memory, snapshot) => remember([await persistence.put(memory, snapshot)])[0];
21499
+ const write = async (memory, snapshot) => {
21500
+ await assertWrite();
21501
+ return remember([await persistence.put(memory, snapshot, signal)])[0];
21502
+ };
21331
21503
  const port = {
21332
21504
  prepare,
21333
21505
  get,
21334
21506
  getFresh: async (id) => {
21335
- const current = await persistence.get(id);
21507
+ const current = await (signal ? persistence.get(id, signal) : persistence.get(id));
21336
21508
  return current && !current.memory.is_deleted && !current.memory.superseded_by ? stored(current.memory) : null;
21337
21509
  },
21338
21510
  tombstones: async (embedding2, embeddingModel, scope, folderId) => {
@@ -21343,7 +21515,8 @@ function createRemoteMemoryPipeline(options) {
21343
21515
  embedding_model: embeddingModel,
21344
21516
  strict_model: true,
21345
21517
  include_deleted: true,
21346
- deleted_only: true
21518
+ deleted_only: true,
21519
+ signal
21347
21520
  });
21348
21521
  rejectUndecryptable(window2.failed);
21349
21522
  return remember(window2.items);
@@ -21399,14 +21572,18 @@ function createRemoteMemoryPipeline(options) {
21399
21572
  if (!target || !newer || id === successor) return false;
21400
21573
  const old = snapshots.get(id);
21401
21574
  const next = snapshots.get(successor);
21575
+ await assertWrite();
21402
21576
  remember(
21403
- await persistence.putMany([
21404
- {
21405
- memory: { ...old.memory, superseded_by: successor, superseded_at: Date.now() },
21406
- expectedVersion: old
21407
- },
21408
- { memory: next.memory, expectedVersion: next }
21409
- ])
21577
+ await persistence.putMany(
21578
+ [
21579
+ {
21580
+ memory: { ...old.memory, superseded_by: successor, superseded_at: Date.now() },
21581
+ expectedVersion: old
21582
+ },
21583
+ { memory: next.memory, expectedVersion: next }
21584
+ ],
21585
+ signal
21586
+ )
21410
21587
  );
21411
21588
  return true;
21412
21589
  },
@@ -21415,18 +21592,22 @@ function createRemoteMemoryPipeline(options) {
21415
21592
  if (!target) return { created: null, retired: false };
21416
21593
  const snapshot = snapshots.get(targetId);
21417
21594
  const successor = createRow(input);
21595
+ await assertWrite();
21418
21596
  const rows = remember(
21419
- await persistence.putMany([
21420
- { memory: successor, expectedVersion: 0 },
21421
- {
21422
- memory: {
21423
- ...snapshot.memory,
21424
- superseded_by: successor.memory_id,
21425
- superseded_at: Date.now()
21426
- },
21427
- expectedVersion: snapshot
21428
- }
21429
- ])
21597
+ await persistence.putMany(
21598
+ [
21599
+ { memory: successor, expectedVersion: 0 },
21600
+ {
21601
+ memory: {
21602
+ ...snapshot.memory,
21603
+ superseded_by: successor.memory_id,
21604
+ superseded_at: Date.now()
21605
+ },
21606
+ expectedVersion: snapshot
21607
+ }
21608
+ ],
21609
+ signal
21610
+ )
21430
21611
  );
21431
21612
  return { created: rows[0], retired: true };
21432
21613
  }
@@ -21459,7 +21640,7 @@ function createRemoteMemoryPipeline(options) {
21459
21640
  factSource,
21460
21641
  recall: async (query, recallOptions = {}) => recall(query, { embeddingOptions, factSource }, { ...recallOptions, types: ["fact"] }),
21461
21642
  retain: async (content, retainOptions) => {
21462
- const { port } = operation("retain");
21643
+ const { port } = operation("retain", retainOptions);
21463
21644
  return retainWithPersistence(
21464
21645
  content,
21465
21646
  {
@@ -22042,16 +22223,21 @@ function createRemoteMemoryStore(options) {
22042
22223
  const record2 = await persistence.get(id);
22043
22224
  return record2 && !record2.memory.is_deleted ? record2 : null;
22044
22225
  };
22045
- const mutateLocked = async (id, change, edit) => {
22046
- const record2 = await live(id);
22226
+ const mutateLocked = async (id, change, edit, writeOptions) => {
22227
+ writeOptions?.signal?.throwIfAborted();
22228
+ const record2 = writeOptions?.signal ? await persistence.get(id, writeOptions.signal) : await live(id);
22047
22229
  if (!record2) return null;
22230
+ if (record2.memory.is_deleted) return null;
22231
+ if (writeOptions?.canWrite && !await writeOptions.canWrite())
22232
+ throw new Error("Memory source is no longer eligible");
22233
+ writeOptions?.signal?.throwIfAborted();
22048
22234
  const next = edit(structuredClone(record2.memory));
22049
22235
  if (!next) return null;
22050
- const saved = await persistence.put(next, record2);
22236
+ const saved = writeOptions?.signal ? await persistence.put(next, record2, writeOptions.signal) : await persistence.put(next, record2);
22051
22237
  notify(typeof change === "function" ? change(record2.memory) : change, [saved]);
22052
22238
  return saved;
22053
22239
  };
22054
- const mutate = (id, change, edit) => serialized(id, () => mutateLocked(id, change, edit));
22240
+ const mutate = (id, change, edit, writeOptions) => serialized(id, () => mutateLocked(id, change, edit, writeOptions));
22055
22241
  const serializedAll = (ids, task) => [...new Set(ids)].sort().reduceRight((inner, id) => () => serialized(id, inner), task)();
22056
22242
  const mutateMany = async (ids, change, edit) => {
22057
22243
  const saved = /* @__PURE__ */ new Map();
@@ -22564,13 +22750,21 @@ function createRemoteMemoryStore(options) {
22564
22750
  }))
22565
22751
  );
22566
22752
  },
22567
- addTopics: async (memoryId, topics) => {
22753
+ addTopics: async (memoryId, topics, writeOptions) => {
22568
22754
  const added = await withKnownKinds(topicInputs(topics, "auto"));
22569
- const saved = await mutate(memoryId, "edit", (memory) => ({
22570
- ...memory,
22571
- topics: serializeTopics(mergeTopics(parseTopics(memory.topics) ?? [], added)),
22572
- topics_updated_at: Date.now()
22573
- }));
22755
+ const saved = await mutate(
22756
+ memoryId,
22757
+ "edit",
22758
+ (memory) => {
22759
+ if (writeOptions?.unlessUserManaged && memory.topics_user_managed) return null;
22760
+ return {
22761
+ ...memory,
22762
+ topics: serializeTopics(mergeTopics(parseTopics(memory.topics) ?? [], added)),
22763
+ topics_updated_at: Date.now()
22764
+ };
22765
+ },
22766
+ writeOptions
22767
+ );
22574
22768
  if (!saved) return [];
22575
22769
  const now = /* @__PURE__ */ new Date();
22576
22770
  return mergeTopics([], added).map(
@@ -23423,6 +23617,7 @@ function createDurableAutoExtractor(options) {
23423
23617
  };
23424
23618
  const folderId = options.folderId ?? null;
23425
23619
  let disposed = false;
23620
+ let activeBatch = null;
23426
23621
  let running = false;
23427
23622
  let wakeRequested = false;
23428
23623
  let timer;
@@ -23459,14 +23654,18 @@ function createDurableAutoExtractor(options) {
23459
23654
  }, delay);
23460
23655
  }
23461
23656
  async function extractBatch(messages, conversationId, ids, jobScope, jobFolderId) {
23657
+ if (disposed) throw new Error("Extraction session was disposed");
23462
23658
  let watchdog;
23463
23659
  let cancelled = false;
23660
+ const controller = new AbortController();
23661
+ activeBatch = controller;
23464
23662
  const model = options.modelForScope?.(jobScope) ?? options.extract.model;
23465
23663
  try {
23466
23664
  return await Promise.race([
23467
23665
  new Promise((resolve, reject) => {
23468
23666
  const worker = createAutoExtractor({
23469
23667
  ...options,
23668
+ signal: controller.signal,
23470
23669
  retainCtx: {
23471
23670
  ...options.retainCtx,
23472
23671
  vaultCtx: {
@@ -23495,6 +23694,8 @@ function createDurableAutoExtractor(options) {
23495
23694
  ]);
23496
23695
  } finally {
23497
23696
  cancelled = true;
23697
+ controller.abort();
23698
+ if (activeBatch === controller) activeBatch = null;
23498
23699
  if (watchdog !== void 0) clearTimeout(watchdog);
23499
23700
  }
23500
23701
  }
@@ -23506,6 +23707,7 @@ function createDurableAutoExtractor(options) {
23506
23707
  for (const message of loaded)
23507
23708
  if (message && message.messageId > 0) sequences.set(message.uniqueId, message.messageId);
23508
23709
  await database.write(async () => {
23710
+ if (disposed) return;
23509
23711
  const current = idsOf(job);
23510
23712
  const acknowledged = ids.filter((id) => current.includes(id));
23511
23713
  if (!acknowledged.length) return;
@@ -23678,6 +23880,7 @@ function createDurableAutoExtractor(options) {
23678
23880
  jobScope,
23679
23881
  jobFolderId
23680
23882
  );
23883
+ if (disposed) throw new Error("Extraction session was disposed");
23681
23884
  options.onTurnComplete?.(result);
23682
23885
  return result;
23683
23886
  };
@@ -23714,6 +23917,7 @@ function createDurableAutoExtractor(options) {
23714
23917
  );
23715
23918
  scheduleAfterSuccess = true;
23716
23919
  } catch (error) {
23920
+ if (disposed) break;
23717
23921
  attempts.set(job.id, attempted + 1);
23718
23922
  retry = true;
23719
23923
  reportError(error, conversationId);
@@ -23736,6 +23940,14 @@ function createDurableAutoExtractor(options) {
23736
23940
  schedule(retry ? options.retryDelayMs ?? 3e4 : 0);
23737
23941
  }
23738
23942
  }
23943
+ function dispose() {
23944
+ disposed = true;
23945
+ activeBatch?.abort(options.signal?.reason);
23946
+ if (timer !== void 0) clearTimeout(timer);
23947
+ options.signal?.removeEventListener("abort", dispose);
23948
+ }
23949
+ if (options.signal?.aborted) dispose();
23950
+ else options.signal?.addEventListener("abort", dispose, { once: true });
23739
23951
  schedule(0);
23740
23952
  return {
23741
23953
  processTurn(messages, conversationId) {
@@ -23815,10 +24027,7 @@ function createDurableAutoExtractor(options) {
23815
24027
  return true;
23816
24028
  },
23817
24029
  isProcessing: () => running,
23818
- dispose() {
23819
- disposed = true;
23820
- if (timer !== void 0) clearTimeout(timer);
23821
- }
24030
+ dispose
23822
24031
  };
23823
24032
  }
23824
24033
 
@@ -27090,6 +27299,7 @@ var CONVERSATION_REDACTOR_LIMIT = 50;
27090
27299
  var NO_CONVERSATION_KEY = "__no_conversation__";
27091
27300
  var NO_STORE_FOLDERS = "Folders are not supported with a memoryStore";
27092
27301
  var NO_STORE_MASK = "piiRedaction needs a memoryStore built with embeddingOptions.maskInput";
27302
+ var MEMORY_STORE_NOT_READY = "Memory store is not ready";
27093
27303
  var conversationRedactors = /* @__PURE__ */ new Map();
27094
27304
  var clientToolFilterCache = /* @__PURE__ */ new Map();
27095
27305
  function getConversationRedactor(conversationId, nerDetector) {
@@ -27234,7 +27444,7 @@ function useChatStorage(options) {
27234
27444
  [resolvedPiiRedaction]
27235
27445
  );
27236
27446
  const maskEmbeddingInput = isPiiRedactor(resolvedPiiRedaction) ? maskForEmbedding : void 0;
27237
- const storeMaskMissing = memoryStore !== void 0 && maskEmbeddingInput !== void 0 && !memoryStore.masksEmbeddingInput;
27447
+ const storeMaskMissing = memoryStore !== void 0 && memoryStore !== null && maskEmbeddingInput !== void 0 && !memoryStore.masksEmbeddingInput;
27238
27448
  const messagesCollection = (0, import_react5.useMemo)(() => database.get("history"), [database]);
27239
27449
  const conversationsCollection = (0, import_react5.useMemo)(
27240
27450
  () => database.get("conversations"),
@@ -27483,6 +27693,7 @@ function useChatStorage(options) {
27483
27693
  }, [vaultEmbeddingCache]);
27484
27694
  const retainVaultMemory = (0, import_react5.useCallback)(
27485
27695
  async (input) => {
27696
+ if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
27486
27697
  if (memoryStore) {
27487
27698
  if (storeMaskMissing) throw new Error(NO_STORE_MASK);
27488
27699
  if (input.folderId !== void 0) throw new Error(NO_STORE_FOLDERS);
@@ -27528,6 +27739,7 @@ function useChatStorage(options) {
27528
27739
  );
27529
27740
  const createMemoryVaultTool2 = (0, import_react5.useCallback)(
27530
27741
  (options2) => {
27742
+ if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
27531
27743
  if (storeMaskMissing) throw new Error(NO_STORE_MASK);
27532
27744
  return createMemoryVaultTool(
27533
27745
  memoryStore ?? vaultCtx,
@@ -27538,6 +27750,7 @@ function useChatStorage(options) {
27538
27750
  );
27539
27751
  const createRecallTool2 = (0, import_react5.useCallback)(
27540
27752
  (toolOptions, callbacks) => {
27753
+ if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
27541
27754
  if (!getToken && !memoryStore) {
27542
27755
  throw new Error("getToken is required for recall tool");
27543
27756
  }
@@ -27583,7 +27796,7 @@ function useChatStorage(options) {
27583
27796
  );
27584
27797
  const recallFn = (0, import_react5.useCallback)(
27585
27798
  async (query, options2) => {
27586
- if (!getToken && !memoryStore) {
27799
+ if (memoryStore === null || !getToken && !memoryStore) {
27587
27800
  return {
27588
27801
  memories: [],
27589
27802
  usedBudget: options2?.budget ?? "low",
@@ -27632,6 +27845,7 @@ function useChatStorage(options) {
27632
27845
  );
27633
27846
  const getVaultMemories = (0, import_react5.useCallback)(
27634
27847
  (options2) => {
27848
+ if (memoryStore === null) return Promise.resolve([]);
27635
27849
  if (!memoryStore) return getAllVaultMemoriesOp(vaultCtx, options2);
27636
27850
  const { folderId, levels, kinds, ...listOptions } = options2 ?? {};
27637
27851
  if (folderId !== void 0) throw new Error(NO_STORE_FOLDERS);
@@ -27642,7 +27856,8 @@ function useChatStorage(options) {
27642
27856
  [vaultCtx, memoryStore]
27643
27857
  );
27644
27858
  const deleteVaultMemory = (0, import_react5.useCallback)(
27645
- (id) => {
27859
+ async (id) => {
27860
+ if (memoryStore === null) throw new Error(MEMORY_STORE_NOT_READY);
27646
27861
  return memoryStore ? memoryStore.delete(id) : deleteVaultMemoryOp(vaultCtx, id);
27647
27862
  },
27648
27863
  [vaultCtx, memoryStore]