@anuma/sdk 6.33.2 → 6.34.0

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.
@@ -2622,13 +2622,13 @@ async function searchChunksOp(ctx, queryVector, options) {
2622
2622
  const storedById = new Map(
2623
2623
  await Promise.all(
2624
2624
  Array.from(uniqueMessages, async ([id, m]) => {
2625
- const stored = await messageRawToStored(
2625
+ const stored2 = await messageRawToStored(
2626
2626
  m,
2627
2627
  ctx.walletAddress,
2628
2628
  ctx.signMessage,
2629
2629
  ctx.embeddedWalletSigner
2630
2630
  );
2631
- return [id, stored];
2631
+ return [id, stored2];
2632
2632
  })
2633
2633
  )
2634
2634
  );
@@ -2646,18 +2646,18 @@ async function searchChunksOp(ctx, queryVector, options) {
2646
2646
  })
2647
2647
  );
2648
2648
  return topK.map(({ message, similarity, chunkTextSource }) => {
2649
- const stored = { ...storedById.get(message.id) };
2649
+ const stored2 = { ...storedById.get(message.id) };
2650
2650
  let chunkText2;
2651
2651
  if (chunkTextSource.kind === "chunk") {
2652
- chunkText2 = resolveChunkText(stored.content, chunkTextSource.chunk, chunkTextSource.siblings);
2652
+ chunkText2 = resolveChunkText(stored2.content, chunkTextSource.chunk, chunkTextSource.siblings);
2653
2653
  } else if (chunkTextSource.kind === "chunk-cached") {
2654
2654
  const state = chunkStateByMsgId.get(message.id);
2655
2655
  const chunk = state && state.version === chunkTextSource.version ? state.chunks[chunkTextSource.chunkIndex] : void 0;
2656
- chunkText2 = resolveChunkText(stored.content, chunk, state?.chunks);
2656
+ chunkText2 = resolveChunkText(stored2.content, chunk, state?.chunks);
2657
2657
  } else {
2658
- chunkText2 = stored.content;
2658
+ chunkText2 = stored2.content;
2659
2659
  }
2660
- return { chunkText: chunkText2, message: stored, similarity };
2660
+ return { chunkText: chunkText2, message: stored2, similarity };
2661
2661
  });
2662
2662
  }
2663
2663
  function makeSyntheticStoredMessage(opts) {
@@ -3776,7 +3776,7 @@ async function embedOne(text12, options, outer) {
3776
3776
  }
3777
3777
  var DEFAULT_EMBEDDING_BATCH_SIZE = 100;
3778
3778
  var DEFAULT_EMBEDDING_BATCH_CONCURRENCY = 3;
3779
- async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage, maskInput, timeoutMs) {
3779
+ async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage, maskInput, timeoutMs, outer) {
3780
3780
  const response = await withEmbeddingRetry(
3781
3781
  () => withDeadline(
3782
3782
  (signal) => postApiV1Embeddings({
@@ -3786,8 +3786,10 @@ async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage,
3786
3786
  ...signal && { signal }
3787
3787
  }),
3788
3788
  timeoutMs,
3789
- "embedding batch request"
3790
- )
3789
+ "embedding batch request",
3790
+ outer
3791
+ ),
3792
+ outer
3791
3793
  );
3792
3794
  if (response.error) {
3793
3795
  throw embeddingErrorFrom(response);
@@ -3805,6 +3807,11 @@ async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage,
3805
3807
  }
3806
3808
  async function generateEmbeddings(texts, options) {
3807
3809
  if (texts.length === 0) return [];
3810
+ const total = options.totalTimeoutMs;
3811
+ if (total === void 0) return embedMany(texts, options, void 0);
3812
+ return withDeadline((signal) => embedMany(texts, options, signal), total, "embedding batch");
3813
+ }
3814
+ async function embedMany(texts, options, outer) {
3808
3815
  const { baseUrl = BASE_URL, model, batchSize, cache } = options;
3809
3816
  const timeoutMs = options.timeoutMs ?? DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS;
3810
3817
  const chunkSize = batchSize ?? DEFAULT_EMBEDDING_BATCH_SIZE;
@@ -3825,7 +3832,8 @@ async function generateEmbeddings(texts, options) {
3825
3832
  if (uncachedTexts.length === 0) {
3826
3833
  return results;
3827
3834
  }
3828
- const headers = await resolveAuthHeaders(options);
3835
+ const headers = await resolveAuthHeaders(options, outer);
3836
+ if (outer?.aborted) throw outer.reason;
3829
3837
  const embeddingModel = model ?? DEFAULT_API_EMBEDDING_MODEL;
3830
3838
  let newEmbeddings;
3831
3839
  if (uncachedTexts.length <= chunkSize) {
@@ -3836,7 +3844,8 @@ async function generateEmbeddings(texts, options) {
3836
3844
  embeddingModel,
3837
3845
  options.onUsage,
3838
3846
  options.maskInput,
3839
- timeoutMs
3847
+ timeoutMs,
3848
+ outer
3840
3849
  );
3841
3850
  } else {
3842
3851
  const chunks = [];
@@ -3847,6 +3856,7 @@ async function generateEmbeddings(texts, options) {
3847
3856
  let nextIndex = 0;
3848
3857
  const worker = async () => {
3849
3858
  while (nextIndex < chunks.length) {
3859
+ if (outer?.aborted) throw outer.reason;
3850
3860
  const idx = nextIndex++;
3851
3861
  allEmbeddings[idx] = await generateEmbeddingsBatch(
3852
3862
  chunks[idx],
@@ -3855,7 +3865,8 @@ async function generateEmbeddings(texts, options) {
3855
3865
  embeddingModel,
3856
3866
  options.onUsage,
3857
3867
  options.maskInput,
3858
- timeoutMs
3868
+ timeoutMs,
3869
+ outer
3859
3870
  );
3860
3871
  }
3861
3872
  };
@@ -3866,6 +3877,7 @@ async function generateEmbeddings(texts, options) {
3866
3877
  await Promise.all(workers);
3867
3878
  newEmbeddings = allEmbeddings.flat();
3868
3879
  }
3880
+ if (outer?.aborted) throw outer.reason;
3869
3881
  for (let i = 0; i < uncachedIndices.length; i++) {
3870
3882
  const f32Embedding = Float32Array.from(newEmbeddings[i]);
3871
3883
  results[uncachedIndices[i]] = Array.from(f32Embedding);
@@ -8940,15 +8952,15 @@ function createSummaryContext(database) {
8940
8952
  summariesCollection: database.get("conversation_summaries")
8941
8953
  };
8942
8954
  }
8943
- function modelToStored(record) {
8955
+ function modelToStored(record2) {
8944
8956
  return {
8945
- uniqueId: record.id,
8946
- conversationId: record.conversationId,
8947
- summary: record.summary,
8948
- summarizedUpTo: record.summarizedUpTo,
8949
- tokenCount: record.tokenCount,
8950
- createdAt: record.createdAt,
8951
- updatedAt: record.updatedAt
8957
+ uniqueId: record2.id,
8958
+ conversationId: record2.conversationId,
8959
+ summary: record2.summary,
8960
+ summarizedUpTo: record2.summarizedUpTo,
8961
+ tokenCount: record2.tokenCount,
8962
+ createdAt: record2.createdAt,
8963
+ updatedAt: record2.updatedAt
8952
8964
  };
8953
8965
  }
8954
8966
  async function getConversationSummaryOp(ctx, conversationId) {
@@ -8957,17 +8969,17 @@ async function getConversationSummaryOp(ctx, conversationId) {
8957
8969
  return modelToStored(results[0]);
8958
8970
  }
8959
8971
  async function upsertConversationSummaryOp(ctx, conversationId, summary, summarizedUpTo, tokenCount) {
8960
- let record;
8972
+ let record2;
8961
8973
  await ctx.database.write(async () => {
8962
8974
  const existing = await ctx.summariesCollection.query(Q2.where("conversation_id", conversationId)).fetch();
8963
8975
  if (existing.length > 0) {
8964
- record = await existing[0].update((rec) => {
8976
+ record2 = await existing[0].update((rec) => {
8965
8977
  rec.summary = summary;
8966
8978
  rec.summarizedUpTo = summarizedUpTo;
8967
8979
  rec.tokenCount = tokenCount;
8968
8980
  });
8969
8981
  } else {
8970
- record = await ctx.summariesCollection.create((rec) => {
8982
+ record2 = await ctx.summariesCollection.create((rec) => {
8971
8983
  rec.conversationId = conversationId;
8972
8984
  rec.summary = summary;
8973
8985
  rec.summarizedUpTo = summarizedUpTo;
@@ -8975,13 +8987,13 @@ async function upsertConversationSummaryOp(ctx, conversationId, summary, summari
8975
8987
  });
8976
8988
  }
8977
8989
  });
8978
- return modelToStored(record);
8990
+ return modelToStored(record2);
8979
8991
  }
8980
8992
  async function deleteConversationSummaryOp(ctx, conversationId) {
8981
8993
  await ctx.database.write(async () => {
8982
8994
  const existing = await ctx.summariesCollection.query(Q2.where("conversation_id", conversationId)).fetch();
8983
- for (const record of existing) {
8984
- await record.destroyPermanently();
8995
+ for (const record2 of existing) {
8996
+ await record2.destroyPermanently();
8985
8997
  }
8986
8998
  });
8987
8999
  }
@@ -10486,25 +10498,25 @@ async function upsertEntitiesInWrite(ctx, entities) {
10486
10498
  const kindBackfills = existing.filter((e) => {
10487
10499
  const incoming = kindByName.get(e.canonicalName);
10488
10500
  return incoming !== void 0 && (e.kind === null || e.kind === void 0 || e.kind === "");
10489
- }).map((record) => ({ record, kind: kindByName.get(record.canonicalName) }));
10501
+ }).map((record2) => ({ record: record2, kind: kindByName.get(record2.canonicalName) }));
10490
10502
  const missing = unique.filter((n) => !existingNames.has(n));
10491
10503
  const created = missing.map(
10492
- (name) => ctx.entityCollection.prepareCreate((record) => {
10493
- record._setRaw("canonical_name", name);
10504
+ (name) => ctx.entityCollection.prepareCreate((record2) => {
10505
+ record2._setRaw("canonical_name", name);
10494
10506
  const kind = kindByName.get(name);
10495
- if (kind !== void 0) record._setRaw("kind", kind);
10507
+ if (kind !== void 0) record2._setRaw("kind", kind);
10496
10508
  })
10497
10509
  );
10498
10510
  for (const e of existing) out.set(e.canonicalName, entityToStored(e));
10499
- for (const record of created) out.set(record.canonicalName, entityToStored(record));
10500
- for (const { record, kind } of kindBackfills) {
10501
- out.set(record.canonicalName, { ...entityToStored(record), kind });
10511
+ for (const record2 of created) out.set(record2.canonicalName, entityToStored(record2));
10512
+ for (const { record: record2, kind } of kindBackfills) {
10513
+ out.set(record2.canonicalName, { ...entityToStored(record2), kind });
10502
10514
  }
10503
10515
  return { entities: out, operations: created, kindBackfills };
10504
10516
  }
10505
10517
  function prepareKindBackfills(backfills) {
10506
10518
  return backfills.map(
10507
- ({ record, kind }) => record.prepareUpdate((r) => {
10519
+ ({ record: record2, kind }) => record2.prepareUpdate((r) => {
10508
10520
  r._setRaw("kind", kind);
10509
10521
  })
10510
10522
  );
@@ -10535,10 +10547,10 @@ function displayNamesOf(entities) {
10535
10547
  }
10536
10548
  return out;
10537
10549
  }
10538
- function topicsEqual(stored, computed) {
10539
- if (stored === null || stored.length !== computed.length) return false;
10550
+ function topicsEqual(stored2, computed) {
10551
+ if (stored2 === null || stored2.length !== computed.length) return false;
10540
10552
  const key = (t) => JSON.stringify([t.name, t.kind ?? null, t.source]);
10541
- const storedKeys = stored.map(key).sort();
10553
+ const storedKeys = stored2.map(key).sort();
10542
10554
  const computedKeys = computed.map(key).sort();
10543
10555
  return storedKeys.every((k, i) => k === computedKeys[i]);
10544
10556
  }
@@ -10604,10 +10616,10 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
10604
10616
  return;
10605
10617
  }
10606
10618
  const linkOps = toCreate.map(
10607
- (e) => ctx.memoryEntityCollection.prepareCreate((record) => {
10608
- record._setRaw("memory_id", memoryId);
10609
- record._setRaw("entity_id", e.uniqueId);
10610
- if (userId !== void 0) record._setRaw("user_id", userId);
10619
+ (e) => ctx.memoryEntityCollection.prepareCreate((record2) => {
10620
+ record2._setRaw("memory_id", memoryId);
10621
+ record2._setRaw("entity_id", e.uniqueId);
10622
+ if (userId !== void 0) record2._setRaw("user_id", userId);
10611
10623
  })
10612
10624
  );
10613
10625
  await ctx.database.batch(
@@ -10675,10 +10687,10 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
10675
10687
  ...entityOps,
10676
10688
  ...prepareKindBackfills(kindBackfills),
10677
10689
  ...toCreate.map(
10678
- (e) => ctx.memoryEntityCollection.prepareCreate((record) => {
10679
- record._setRaw("memory_id", memoryId);
10680
- record._setRaw("entity_id", e.uniqueId);
10681
- if (userId !== void 0) record._setRaw("user_id", userId);
10690
+ (e) => ctx.memoryEntityCollection.prepareCreate((record2) => {
10691
+ record2._setRaw("memory_id", memoryId);
10692
+ record2._setRaw("entity_id", e.uniqueId);
10693
+ if (userId !== void 0) record2._setRaw("user_id", userId);
10682
10694
  })
10683
10695
  ),
10684
10696
  ...toDestroy.map((l) => l.prepareDestroyPermanently()),
@@ -10831,8 +10843,8 @@ function visibilityConditions(requested) {
10831
10843
  if (excluded.length === 0) return [];
10832
10844
  return [Q5.or(Q5.where("visibility", null), Q5.where("visibility", Q5.notIn(excluded)))];
10833
10845
  }
10834
- function isOwnedByCtxUser(ctx, record) {
10835
- return ctx.userId === void 0 || record.userId === ctx.userId;
10846
+ function isOwnedByCtxUser(ctx, record2) {
10847
+ return ctx.userId === void 0 || record2.userId === ctx.userId;
10836
10848
  }
10837
10849
  function baseVaultConditions(ctx, options) {
10838
10850
  return [
@@ -10912,39 +10924,39 @@ async function vaultMemoryToStored(memory, walletAddress, signMessage, embeddedW
10912
10924
  }
10913
10925
  return raw;
10914
10926
  }
10915
- function populateNewVaultMemory(record, ctx, opts, encryptedContent) {
10916
- record._setRaw("content", encryptedContent);
10917
- record._setRaw("scope", opts.scope ?? "private");
10918
- record._setRaw("folder_id", opts.folderId ?? null);
10919
- record._setRaw("user_id", ctx.userId ?? null);
10920
- record._setRaw("is_deleted", false);
10927
+ function populateNewVaultMemory(record2, ctx, opts, encryptedContent) {
10928
+ record2._setRaw("content", encryptedContent);
10929
+ record2._setRaw("scope", opts.scope ?? "private");
10930
+ record2._setRaw("folder_id", opts.folderId ?? null);
10931
+ record2._setRaw("user_id", ctx.userId ?? null);
10932
+ record2._setRaw("is_deleted", false);
10921
10933
  if (opts.embedding !== void 0) {
10922
- record._setRaw("embedding", opts.embedding);
10923
- record._setRaw("embedding_model", opts.embeddingModel ?? null);
10934
+ record2._setRaw("embedding", opts.embedding);
10935
+ record2._setRaw("embedding_model", opts.embeddingModel ?? null);
10924
10936
  }
10925
10937
  if (opts.sourceChunkIds !== void 0) {
10926
- record._setRaw("source_chunk_ids", JSON.stringify(opts.sourceChunkIds));
10938
+ record2._setRaw("source_chunk_ids", JSON.stringify(opts.sourceChunkIds));
10927
10939
  }
10928
- record._setRaw("proof_count", opts.proofCount ?? 1);
10929
- record._setRaw("source", opts.source ?? "manual");
10940
+ record2._setRaw("proof_count", opts.proofCount ?? 1);
10941
+ record2._setRaw("source", opts.source ?? "manual");
10930
10942
  if (opts.eventTime) {
10931
- record._setRaw("event_time_start", opts.eventTime.start ?? null);
10932
- record._setRaw("event_time_end", opts.eventTime.end ?? null);
10933
- record._setRaw("event_time_kind", opts.eventTime.kind ?? null);
10943
+ record2._setRaw("event_time_start", opts.eventTime.start ?? null);
10944
+ record2._setRaw("event_time_end", opts.eventTime.end ?? null);
10945
+ record2._setRaw("event_time_kind", opts.eventTime.kind ?? null);
10934
10946
  }
10935
10947
  if (opts.factType !== void 0) {
10936
- record._setRaw("fact_type", opts.factType);
10948
+ record2._setRaw("fact_type", opts.factType);
10937
10949
  }
10938
10950
  if (opts.trustTier !== void 0) {
10939
- record._setRaw("trust_tier", normalizeTrustTier(opts.trustTier));
10951
+ record2._setRaw("trust_tier", normalizeTrustTier(opts.trustTier));
10940
10952
  }
10941
- record._setRaw("visibility", opts.visibility ?? "private");
10942
- record._setRaw(
10953
+ record2._setRaw("visibility", opts.visibility ?? "private");
10954
+ record2._setRaw(
10943
10955
  "published_at",
10944
10956
  opts.visibility && opts.visibility !== "private" ? opts.publishedAt ?? Date.now() : null
10945
10957
  );
10946
10958
  if (opts.geohash !== void 0) {
10947
- record._setRaw("geohash", opts.geohash);
10959
+ record2._setRaw("geohash", opts.geohash);
10948
10960
  }
10949
10961
  }
10950
10962
  async function createVaultMemoryOp(ctx, opts) {
@@ -10958,7 +10970,7 @@ async function createVaultMemoryOp(ctx, opts) {
10958
10970
  if (ctx.canWrite && !await ctx.canWrite())
10959
10971
  throw new Error("Memory source is no longer eligible");
10960
10972
  return ctx.vaultMemoryCollection.create(
10961
- (record) => populateNewVaultMemory(record, ctx, opts, encryptedContent)
10973
+ (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent)
10962
10974
  );
10963
10975
  });
10964
10976
  return vaultMemoryToStored(created, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
@@ -10983,7 +10995,7 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
10983
10995
  }
10984
10996
  if (target.isDeleted || target.supersededBy || !isOwnedByCtxUser(ctx, target)) return;
10985
10997
  createdRecord = await ctx.vaultMemoryCollection.create(
10986
- (record) => populateNewVaultMemory(record, ctx, opts, encryptedContent)
10998
+ (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent)
10987
10999
  );
10988
11000
  await target.update((r) => {
10989
11001
  r._setRaw("superseded_by", createdRecord.id);
@@ -11065,7 +11077,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
11065
11077
  throw new Error("Memory source is no longer eligible");
11066
11078
  const prepared = optionsArray.map(
11067
11079
  (opts, i) => ctx.vaultMemoryCollection.prepareCreate(
11068
- (record) => populateNewVaultMemory(record, ctx, opts, encryptedContents[i])
11080
+ (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i])
11069
11081
  )
11070
11082
  );
11071
11083
  await ctx.database.batch(...prepared);
@@ -11073,16 +11085,16 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
11073
11085
  });
11074
11086
  return Promise.all(
11075
11087
  created.map(
11076
- (record) => vaultMemoryToStored(record, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
11088
+ (record2) => vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
11077
11089
  )
11078
11090
  );
11079
11091
  }
11080
11092
  async function getVaultMemoryOp(ctx, id) {
11081
11093
  try {
11082
- const record = await ctx.vaultMemoryCollection.find(id);
11083
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return null;
11094
+ const record2 = await ctx.vaultMemoryCollection.find(id);
11095
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
11084
11096
  return vaultMemoryToStored(
11085
- record,
11097
+ record2,
11086
11098
  ctx.walletAddress,
11087
11099
  ctx.signMessage,
11088
11100
  ctx.embeddedWalletSigner
@@ -11140,11 +11152,11 @@ function vaultMemoryRawToStoredRaw(raw) {
11140
11152
  };
11141
11153
  }
11142
11154
  async function vaultMemoryRawToStored(raw, walletAddress, signMessage, embeddedWalletSigner) {
11143
- const stored = vaultMemoryRawToStoredRaw(raw);
11155
+ const stored2 = vaultMemoryRawToStoredRaw(raw);
11144
11156
  if (walletAddress) {
11145
- return decryptVaultMemoryFields(stored, walletAddress, signMessage, embeddedWalletSigner);
11157
+ return decryptVaultMemoryFields(stored2, walletAddress, signMessage, embeddedWalletSigner);
11146
11158
  }
11147
- return stored;
11159
+ return stored2;
11148
11160
  }
11149
11161
  async function getAllVaultMemoriesOp(ctx, options) {
11150
11162
  const conditions = [
@@ -11296,13 +11308,13 @@ async function getVaultMemoriesByIdsOp(ctx, ids, options) {
11296
11308
  async function getAllVaultMemoryContentsOp(ctx, options) {
11297
11309
  const results = await ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx, options)).unsafeFetchRaw();
11298
11310
  return mapInBatches(results, async (raw) => {
11299
- const stored = await vaultMemoryRawToStored(
11311
+ const stored2 = await vaultMemoryRawToStored(
11300
11312
  raw,
11301
11313
  ctx.walletAddress,
11302
11314
  ctx.signMessage,
11303
11315
  ctx.embeddedWalletSigner
11304
11316
  );
11305
- return stored.content;
11317
+ return stored2.content;
11306
11318
  });
11307
11319
  }
11308
11320
  async function countActiveVaultMemoriesOp(ctx) {
@@ -11324,12 +11336,12 @@ async function updateVaultMemoryOp(ctx, id, opts) {
11324
11336
  ctx.embeddedWalletSigner
11325
11337
  ) : opts.content;
11326
11338
  let stale = false;
11327
- const record = probe;
11328
- const originalUpdatedAt = record.updatedAt.getTime();
11339
+ const record2 = probe;
11340
+ const originalUpdatedAt = record2.updatedAt.getTime();
11329
11341
  await ctx.database.write(async () => {
11330
11342
  if (ctx.canWrite && !await ctx.canWrite())
11331
11343
  throw new Error("Memory source is no longer eligible");
11332
- if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record)) {
11344
+ if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
11333
11345
  stale = true;
11334
11346
  return;
11335
11347
  }
@@ -11337,14 +11349,14 @@ async function updateVaultMemoryOp(ctx, id, opts) {
11337
11349
  let replayedObservation = false;
11338
11350
  if (opts.observationSourceIds?.length) {
11339
11351
  try {
11340
- const parsed = JSON.parse(record.sourceChunkIds ?? "[]");
11352
+ const parsed = JSON.parse(record2.sourceChunkIds ?? "[]");
11341
11353
  if (Array.isArray(parsed))
11342
11354
  observedSources = parsed.filter((id2) => typeof id2 === "string");
11343
11355
  } catch {
11344
11356
  }
11345
11357
  replayedObservation = opts.observationSourceIds.every((id2) => observedSources.includes(id2));
11346
11358
  }
11347
- await record.update((r) => {
11359
+ await record2.update((r) => {
11348
11360
  r._setRaw("content", encryptedContent);
11349
11361
  if (opts.scope !== void 0) {
11350
11362
  r._setRaw("scope", opts.scope);
@@ -11401,7 +11413,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
11401
11413
  });
11402
11414
  if (stale) return null;
11403
11415
  return vaultMemoryToStored(
11404
- record,
11416
+ record2,
11405
11417
  ctx.walletAddress,
11406
11418
  ctx.signMessage,
11407
11419
  ctx.embeddedWalletSigner
@@ -11415,21 +11427,21 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
11415
11427
  if (!entityCtx) {
11416
11428
  throw new Error("setMemoryEntitiesOp requires ctx.entityCtx (entity collections)");
11417
11429
  }
11418
- let record;
11430
+ let record2;
11419
11431
  try {
11420
- record = await ctx.vaultMemoryCollection.find(memoryId);
11432
+ record2 = await ctx.vaultMemoryCollection.find(memoryId);
11421
11433
  } catch {
11422
11434
  return null;
11423
11435
  }
11424
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return null;
11436
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
11425
11437
  let stale = false;
11426
- const originalUpdatedAt = record.updatedAt.getTime();
11438
+ const originalUpdatedAt = record2.updatedAt.getTime();
11427
11439
  await ctx.database.write(async (writer) => {
11428
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
11440
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
11429
11441
  stale = true;
11430
11442
  return;
11431
11443
  }
11432
- await record.update((r) => {
11444
+ await record2.update((r) => {
11433
11445
  r._setRaw("topics_user_managed", true);
11434
11446
  r._setRaw("updated_at", originalUpdatedAt);
11435
11447
  });
@@ -11453,25 +11465,25 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
11453
11465
  );
11454
11466
  });
11455
11467
  if (stale) return null;
11456
- return vaultMemoryToStored(record, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
11468
+ return vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
11457
11469
  }
11458
11470
  async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
11459
- let record;
11471
+ let record2;
11460
11472
  try {
11461
- record = await ctx.vaultMemoryCollection.find(memoryId);
11473
+ record2 = await ctx.vaultMemoryCollection.find(memoryId);
11462
11474
  } catch {
11463
11475
  return false;
11464
11476
  }
11465
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
11466
- const originalUpdatedAt = record.updatedAt.getTime();
11477
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
11478
+ const originalUpdatedAt = record2.updatedAt.getTime();
11467
11479
  let cleared = false;
11468
11480
  await ctx.database.write(async () => {
11469
- if (options?.unlessTopicsRecorded && parseTopics(record.topics) !== null) return;
11481
+ if (options?.unlessTopicsRecorded && parseTopics(record2.topics) !== null) return;
11470
11482
  cleared = true;
11471
- await record.update((r) => {
11483
+ await record2.update((r) => {
11472
11484
  r._setRaw("topics_user_managed", false);
11473
11485
  r._setRaw("topics_extracted_version", null);
11474
- if (record.topicsExtractedAt === null) {
11486
+ if (record2.topicsExtractedAt === null) {
11475
11487
  r._setRaw("topics_extracted_at", originalUpdatedAt);
11476
11488
  }
11477
11489
  r._setRaw("updated_at", originalUpdatedAt);
@@ -11480,22 +11492,22 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
11480
11492
  return cleared;
11481
11493
  }
11482
11494
  async function setMemoryVisibilityOp(ctx, id, opts) {
11483
- let record;
11495
+ let record2;
11484
11496
  try {
11485
- record = await ctx.vaultMemoryCollection.find(id);
11497
+ record2 = await ctx.vaultMemoryCollection.find(id);
11486
11498
  } catch {
11487
11499
  return null;
11488
11500
  }
11489
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return null;
11501
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
11490
11502
  let stale = false;
11491
11503
  await ctx.database.write(async () => {
11492
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
11504
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
11493
11505
  stale = true;
11494
11506
  return;
11495
11507
  }
11496
- const currentUpdatedAt = record.updatedAt.getTime();
11497
- const currentPublishedAt = record.publishedAt ?? null;
11498
- await record.update((r) => {
11508
+ const currentUpdatedAt = record2.updatedAt.getTime();
11509
+ const currentPublishedAt = record2.publishedAt ?? null;
11510
+ await record2.update((r) => {
11499
11511
  r._setRaw("visibility", opts.visibility);
11500
11512
  if (opts.visibility === "private") {
11501
11513
  r._setRaw("published_at", null);
@@ -11509,19 +11521,19 @@ async function setMemoryVisibilityOp(ctx, id, opts) {
11509
11521
  });
11510
11522
  });
11511
11523
  if (stale) return null;
11512
- return vaultMemoryToStored(record, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
11524
+ return vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
11513
11525
  }
11514
11526
  async function deleteVaultMemoryOp(ctx, id) {
11515
11527
  try {
11516
- const record = await ctx.vaultMemoryCollection.find(id);
11517
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
11528
+ const record2 = await ctx.vaultMemoryCollection.find(id);
11529
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
11518
11530
  let stale = false;
11519
11531
  await ctx.database.write(async () => {
11520
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
11532
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
11521
11533
  stale = true;
11522
11534
  return;
11523
11535
  }
11524
- await record.update((r) => {
11536
+ await record2.update((r) => {
11525
11537
  r._setRaw("is_deleted", true);
11526
11538
  });
11527
11539
  });
@@ -11540,8 +11552,8 @@ async function deleteVaultMemoryOp(ctx, id) {
11540
11552
  async function supersedeVaultMemoryOp(ctx, id, supersededById) {
11541
11553
  if (id === supersededById) return false;
11542
11554
  try {
11543
- const record = await ctx.vaultMemoryCollection.find(id);
11544
- if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record)) return false;
11555
+ const record2 = await ctx.vaultMemoryCollection.find(id);
11556
+ if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) return false;
11545
11557
  let successor;
11546
11558
  try {
11547
11559
  successor = await ctx.vaultMemoryCollection.find(supersededById);
@@ -11555,7 +11567,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
11555
11567
  await ctx.database.write(async () => {
11556
11568
  if (ctx.canWrite && !await ctx.canWrite())
11557
11569
  throw new Error("Memory source is no longer eligible");
11558
- if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record)) {
11570
+ if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
11559
11571
  stale = true;
11560
11572
  return;
11561
11573
  }
@@ -11563,7 +11575,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
11563
11575
  stale = true;
11564
11576
  return;
11565
11577
  }
11566
- await record.update((r) => {
11578
+ await record2.update((r) => {
11567
11579
  r._setRaw("superseded_by", supersededById);
11568
11580
  r._setRaw("superseded_at", Date.now());
11569
11581
  });
@@ -11582,7 +11594,7 @@ async function getUnfiledVaultMemoriesOp(ctx) {
11582
11594
  const results = await ctx.vaultMemoryCollection.query(...conditions).fetch();
11583
11595
  return mapInBatches(
11584
11596
  results,
11585
- (record) => vaultMemoryToStored(record, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
11597
+ (record2) => vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
11586
11598
  );
11587
11599
  }
11588
11600
  var TOPICS_EXTRACTION_VERSION = 3;
@@ -11724,17 +11736,17 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
11724
11736
  }
11725
11737
  }
11726
11738
  const eligible = records.filter(
11727
- (record) => !record.isDeleted && isOwnedByCtxUser(ctx, record) && !record.topicsUserManaged
11739
+ (record2) => !record2.isDeleted && isOwnedByCtxUser(ctx, record2) && !record2.topicsUserManaged
11728
11740
  );
11729
- const prepared = eligible.map((record) => {
11730
- const originalUpdatedAt = record.updatedAt.getTime();
11731
- return record.prepareUpdate((r) => {
11741
+ const prepared = eligible.map((record2) => {
11742
+ const originalUpdatedAt = record2.updatedAt.getTime();
11743
+ return record2.prepareUpdate((r) => {
11732
11744
  r._setRaw("topics_extracted_at", extractedAt);
11733
11745
  r._setRaw("topics_extracted_version", version);
11734
11746
  r._setRaw("updated_at", originalUpdatedAt);
11735
11747
  });
11736
11748
  });
11737
- for (const record of eligible) stamped.push(record.id);
11749
+ for (const record2 of eligible) stamped.push(record2.id);
11738
11750
  if (prepared.length > 0) await ctx.database.batch(...prepared);
11739
11751
  });
11740
11752
  }
@@ -11749,14 +11761,14 @@ async function relinkMemoryTopicsOp(ctx, memoryIds) {
11749
11761
  for (const id of Array.from(new Set(memoryIds))) {
11750
11762
  try {
11751
11763
  await ctx.database.write(async (writer) => {
11752
- let record;
11764
+ let record2;
11753
11765
  try {
11754
- record = await ctx.vaultMemoryCollection.find(id);
11766
+ record2 = await ctx.vaultMemoryCollection.find(id);
11755
11767
  } catch {
11756
11768
  return;
11757
11769
  }
11758
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return;
11759
- const topics = parseTopics(record.topics);
11770
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return;
11771
+ const topics = parseTopics(record2.topics);
11760
11772
  if (topics === null) return;
11761
11773
  await writer.callWriter(() => relinkMemoryEntitiesFromTopicsOp(entityCtx, id, topics));
11762
11774
  relinked.push(id);
@@ -11781,20 +11793,20 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
11781
11793
  await ctx.database.write(async () => {
11782
11794
  const writes = [];
11783
11795
  for (const id of chunkIds) {
11784
- let record;
11796
+ let record2;
11785
11797
  try {
11786
- record = await ctx.vaultMemoryCollection.find(id);
11798
+ record2 = await ctx.vaultMemoryCollection.find(id);
11787
11799
  } catch {
11788
11800
  continue;
11789
11801
  }
11790
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) continue;
11791
- if (parseTopics(record.topics) !== null) continue;
11802
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) continue;
11803
+ if (parseTopics(record2.topics) !== null) continue;
11792
11804
  const links = await entityCtx.memoryEntityCollection.query(Q5.where("memory_id", id)).unsafeFetchRaw();
11793
11805
  const entityIds = links.map((l) => String(l.entity_id));
11794
11806
  if (entityIds.length === 0) continue;
11795
11807
  const entities = await entityCtx.entityCollection.query(Q5.where("id", Q5.oneOf(entityIds))).fetch();
11796
11808
  if (entities.length === 0) continue;
11797
- const source = record.topicsUserManaged ? "user" : "auto";
11809
+ const source = record2.topicsUserManaged ? "user" : "auto";
11798
11810
  const write = await resolveMemoryTopicsWrite(entityCtx, id, entities, [], source);
11799
11811
  if (write) writes.push(write);
11800
11812
  }
@@ -11812,7 +11824,7 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
11812
11824
  if (records.length === 0) return 0;
11813
11825
  await ctx.database.write(async () => {
11814
11826
  const prepared = records.map(
11815
- (record) => record.prepareUpdate((r) => {
11827
+ (record2) => record2.prepareUpdate((r) => {
11816
11828
  r._setRaw("is_deleted", true);
11817
11829
  })
11818
11830
  );
@@ -11857,20 +11869,20 @@ async function getDecayCandidatesRawOp(ctx) {
11857
11869
  }
11858
11870
  async function archiveVaultMemoryOp(ctx, id, opts) {
11859
11871
  try {
11860
- const record = await ctx.vaultMemoryCollection.find(id);
11861
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
11872
+ const record2 = await ctx.vaultMemoryCollection.find(id);
11873
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
11862
11874
  let stale = false;
11863
11875
  const archivedAtValue = opts?.now ?? Date.now();
11864
11876
  await ctx.database.write(async () => {
11865
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record) || record.archivedAt !== null) {
11877
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || record2.archivedAt !== null) {
11866
11878
  stale = true;
11867
11879
  return;
11868
11880
  }
11869
- if (opts?.expectedUpdatedAt !== void 0 && record.updatedAt.getTime() !== opts.expectedUpdatedAt || opts?.expectedLastObservedAt !== void 0 && (record.lastObservedAt ?? null) !== opts.expectedLastObservedAt) {
11881
+ if (opts?.expectedUpdatedAt !== void 0 && record2.updatedAt.getTime() !== opts.expectedUpdatedAt || opts?.expectedLastObservedAt !== void 0 && (record2.lastObservedAt ?? null) !== opts.expectedLastObservedAt) {
11870
11882
  stale = true;
11871
11883
  return;
11872
11884
  }
11873
- await record.update((r) => {
11885
+ await record2.update((r) => {
11874
11886
  r._setRaw("archived_at", archivedAtValue);
11875
11887
  });
11876
11888
  });
@@ -11881,15 +11893,15 @@ async function archiveVaultMemoryOp(ctx, id, opts) {
11881
11893
  }
11882
11894
  async function restoreVaultMemoryOp(ctx, id) {
11883
11895
  try {
11884
- const record = await ctx.vaultMemoryCollection.find(id);
11885
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
11896
+ const record2 = await ctx.vaultMemoryCollection.find(id);
11897
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
11886
11898
  let stale = false;
11887
11899
  await ctx.database.write(async () => {
11888
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
11900
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
11889
11901
  stale = true;
11890
11902
  return;
11891
11903
  }
11892
- await record.update((r) => {
11904
+ await record2.update((r) => {
11893
11905
  r._setRaw("archived_at", null);
11894
11906
  });
11895
11907
  });
@@ -11900,17 +11912,17 @@ async function restoreVaultMemoryOp(ctx, id) {
11900
11912
  }
11901
11913
  async function hardDeleteDecayedOp(ctx, id, opts) {
11902
11914
  try {
11903
- const record = await ctx.vaultMemoryCollection.find(id);
11904
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
11915
+ const record2 = await ctx.vaultMemoryCollection.find(id);
11916
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
11905
11917
  const now = opts.now ?? Date.now();
11906
11918
  let stale = false;
11907
11919
  await ctx.database.write(async () => {
11908
- const archivedAt = record.archivedAt;
11909
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
11920
+ const archivedAt = record2.archivedAt;
11921
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
11910
11922
  stale = true;
11911
11923
  return;
11912
11924
  }
11913
- await record.update((r) => {
11925
+ await record2.update((r) => {
11914
11926
  r._setRaw("is_deleted", true);
11915
11927
  });
11916
11928
  });
@@ -11928,14 +11940,14 @@ async function hardDeleteDecayedOp(ctx, id, opts) {
11928
11940
  }
11929
11941
  async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel, expected) {
11930
11942
  try {
11931
- const record = await ctx.vaultMemoryCollection.find(id);
11932
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
11933
- const readUpdatedAt = record.updatedAt.getTime();
11934
- const readStoredContent = record._getRaw("content");
11943
+ const record2 = await ctx.vaultMemoryCollection.find(id);
11944
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
11945
+ const readUpdatedAt = record2.updatedAt.getTime();
11946
+ const readStoredContent = record2._getRaw("content");
11935
11947
  if (expected?.updatedAt !== void 0 && expected.updatedAt !== readUpdatedAt) return false;
11936
11948
  if (expected?.content !== void 0) {
11937
11949
  const current = await vaultMemoryToStored(
11938
- record,
11950
+ record2,
11939
11951
  ctx.walletAddress,
11940
11952
  ctx.signMessage,
11941
11953
  ctx.embeddedWalletSigner
@@ -11944,11 +11956,11 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel,
11944
11956
  }
11945
11957
  let written = false;
11946
11958
  await ctx.database.write(async () => {
11947
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return;
11948
- const originalUpdatedAt = record.updatedAt.getTime();
11949
- if (originalUpdatedAt !== readUpdatedAt || record._getRaw("content") !== readStoredContent)
11959
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return;
11960
+ const originalUpdatedAt = record2.updatedAt.getTime();
11961
+ if (originalUpdatedAt !== readUpdatedAt || record2._getRaw("content") !== readStoredContent)
11950
11962
  return;
11951
- await record.update((r) => {
11963
+ await record2.update((r) => {
11952
11964
  r._setRaw("embedding", embedding);
11953
11965
  r._setRaw("embedding_model", embeddingModel);
11954
11966
  r._setRaw("updated_at", originalUpdatedAt);
@@ -11963,8 +11975,8 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel,
11963
11975
  function normalizeForDedupe(content) {
11964
11976
  return content.normalize("NFKC").trim().replace(/\s+/g, " ").toLowerCase();
11965
11977
  }
11966
- async function findQuarantinedDuplicateOp(ctx, content, sourceIds, where) {
11967
- const wanted = [...new Set(sourceIds)].sort().join("\0");
11978
+ async function findQuarantinedDuplicateOp(ctx, content, sourceIds2, where) {
11979
+ const wanted = [...new Set(sourceIds2)].sort().join("\0");
11968
11980
  const target = normalizeForDedupe(content);
11969
11981
  const rows = await ctx.vaultMemoryCollection.query(
11970
11982
  Q5.where("trust_tier", "quarantined"),
@@ -11983,13 +11995,13 @@ async function findQuarantinedDuplicateOp(ctx, content, sourceIds, where) {
11983
11995
  if (!Array.isArray(ids)) continue;
11984
11996
  const key = [...new Set(ids.filter((id) => typeof id === "string"))].sort().join("\0");
11985
11997
  if (key !== wanted) continue;
11986
- const stored = await vaultMemoryRawToStored(
11998
+ const stored2 = await vaultMemoryRawToStored(
11987
11999
  raw,
11988
12000
  ctx.walletAddress,
11989
12001
  ctx.signMessage,
11990
12002
  ctx.embeddedWalletSigner
11991
12003
  );
11992
- if (normalizeForDedupe(stored.content) === target) return stored.uniqueId;
12004
+ if (normalizeForDedupe(stored2.content) === target) return stored2.uniqueId;
11993
12005
  }
11994
12006
  return null;
11995
12007
  }
@@ -12098,25 +12110,25 @@ async function ingestPublishedPhotoMemoriesOp(ctx, rows) {
12098
12110
  inserted = writable.length;
12099
12111
  if (writable.length === 0) return;
12100
12112
  const prepared = writable.map(
12101
- ({ row, content }) => ctx.vaultMemoryCollection.prepareCreate((record) => {
12102
- record._raw.id = row.memoryId;
12103
- record._setRaw("content", content);
12104
- record._setRaw("scope", "shared");
12105
- record._setRaw("folder_id", null);
12106
- record._setRaw("user_id", ctx.userId ?? null);
12107
- record._setRaw("is_deleted", false);
12108
- record._setRaw("proof_count", 1);
12109
- record._setRaw("source", SOURCE_PHOTO);
12110
- record._setRaw(
12113
+ ({ row, content }) => ctx.vaultMemoryCollection.prepareCreate((record2) => {
12114
+ record2._raw.id = row.memoryId;
12115
+ record2._setRaw("content", content);
12116
+ record2._setRaw("scope", "shared");
12117
+ record2._setRaw("folder_id", null);
12118
+ record2._setRaw("user_id", ctx.userId ?? null);
12119
+ record2._setRaw("is_deleted", false);
12120
+ record2._setRaw("proof_count", 1);
12121
+ record2._setRaw("source", SOURCE_PHOTO);
12122
+ record2._setRaw(
12111
12123
  "media",
12112
12124
  row.media && row.media.length > 0 ? JSON.stringify(row.media) : null
12113
12125
  );
12114
- record._setRaw("visibility", "public");
12115
- record._setRaw("published_at", now);
12126
+ record2._setRaw("visibility", "public");
12127
+ record2._setRaw("published_at", now);
12116
12128
  if (row.eventTime) {
12117
- record._setRaw("event_time_start", row.eventTime.start ?? null);
12118
- record._setRaw("event_time_end", row.eventTime.end ?? null);
12119
- record._setRaw("event_time_kind", row.eventTime.kind ?? null);
12129
+ record2._setRaw("event_time_start", row.eventTime.start ?? null);
12130
+ record2._setRaw("event_time_end", row.eventTime.end ?? null);
12131
+ record2._setRaw("event_time_kind", row.eventTime.kind ?? null);
12120
12132
  }
12121
12133
  })
12122
12134
  );
@@ -12480,11 +12492,11 @@ function folderToStored(folder) {
12480
12492
  }
12481
12493
  async function createVaultFolderOp(ctx, opts) {
12482
12494
  const created = await ctx.database.write(async () => {
12483
- return ctx.vaultFolderCollection.create((record) => {
12484
- record._setRaw("name", opts.name);
12485
- record._setRaw("scope", opts.scope ?? "private");
12486
- record._setRaw("is_system", opts.isSystem ?? false);
12487
- record._setRaw("is_deleted", false);
12495
+ return ctx.vaultFolderCollection.create((record2) => {
12496
+ record2._setRaw("name", opts.name);
12497
+ record2._setRaw("scope", opts.scope ?? "private");
12498
+ record2._setRaw("is_system", opts.isSystem ?? false);
12499
+ record2._setRaw("is_deleted", false);
12488
12500
  });
12489
12501
  });
12490
12502
  return folderToStored(created);
@@ -12495,14 +12507,14 @@ async function getAllVaultFoldersOp(ctx) {
12495
12507
  }
12496
12508
  async function updateVaultFolderOp(ctx, id, opts) {
12497
12509
  try {
12498
- const record = await ctx.vaultFolderCollection.find(id);
12499
- if (record.isDeleted) return null;
12500
- const scopeChanged = opts.scope !== void 0 && opts.scope !== record.scope;
12510
+ const record2 = await ctx.vaultFolderCollection.find(id);
12511
+ if (record2.isDeleted) return null;
12512
+ const scopeChanged = opts.scope !== void 0 && opts.scope !== record2.scope;
12501
12513
  const updated = await ctx.database.write(async () => {
12502
12514
  const memories = scopeChanged ? await ctx.vaultMemoryCollection.query(Q6.where("folder_id", id), Q6.where("is_deleted", false)).fetch() : [];
12503
12515
  const updates = [];
12504
12516
  updates.push(
12505
- record.prepareUpdate((r) => {
12517
+ record2.prepareUpdate((r) => {
12506
12518
  if (opts.name !== void 0) r._setRaw("name", opts.name);
12507
12519
  if (opts.scope !== void 0) r._setRaw("scope", opts.scope);
12508
12520
  })
@@ -12524,8 +12536,8 @@ async function updateVaultFolderOp(ctx, id, opts) {
12524
12536
  }
12525
12537
  async function deleteVaultFolderOp(ctx, id) {
12526
12538
  try {
12527
- const record = await ctx.vaultFolderCollection.find(id);
12528
- if (record.isDeleted) return false;
12539
+ const record2 = await ctx.vaultFolderCollection.find(id);
12540
+ if (record2.isDeleted) return false;
12529
12541
  await ctx.database.write(async () => {
12530
12542
  const memories = await ctx.vaultMemoryCollection.query(Q6.where("folder_id", id), Q6.where("is_deleted", false)).fetch();
12531
12543
  const preparedMemories = memories.map(
@@ -12534,7 +12546,7 @@ async function deleteVaultFolderOp(ctx, id) {
12534
12546
  r._setRaw("scope", "private");
12535
12547
  })
12536
12548
  );
12537
- const preparedFolder = record.prepareUpdate((r) => {
12549
+ const preparedFolder = record2.prepareUpdate((r) => {
12538
12550
  r._setRaw("is_deleted", true);
12539
12551
  });
12540
12552
  await ctx.database.batch(...preparedMemories, preparedFolder);
@@ -12580,11 +12592,11 @@ async function moveMemoriesToFolderOp(ctx, memoryIds, folderId) {
12580
12592
  }
12581
12593
  async function updateVaultFolderContextOp(ctx, id, context) {
12582
12594
  try {
12583
- const record = await ctx.vaultFolderCollection.find(id);
12584
- if (record.isDeleted) return null;
12595
+ const record2 = await ctx.vaultFolderCollection.find(id);
12596
+ if (record2.isDeleted) return null;
12585
12597
  const updated = await ctx.database.write(async () => {
12586
12598
  await ctx.database.batch(
12587
- record.prepareUpdate((r) => {
12599
+ record2.prepareUpdate((r) => {
12588
12600
  r._setRaw("context", context);
12589
12601
  })
12590
12602
  );
@@ -14641,7 +14653,7 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
14641
14653
  if (useFusion && !embeddingsUnavailable && facetQueries) {
14642
14654
  let subEmbeddings;
14643
14655
  try {
14644
- subEmbeddings = await generateEmbeddings(facetQueries, embeddingOptions);
14656
+ subEmbeddings = prepared.facetEmbeddings ?? await generateEmbeddings(facetQueries, embeddingOptions);
14645
14657
  } catch (err) {
14646
14658
  getLogger().warn(
14647
14659
  "memoryVault: sub-query embedding failed \u2014 falling back to single-query ranking: " + (err instanceof Error ? err.message : String(err))
@@ -14826,6 +14838,35 @@ var DEFAULT_SCOPE = "private";
14826
14838
  var DEFAULT_CONSOLIDATE_THRESHOLD = 0.55;
14827
14839
  var DEFAULT_CONSOLIDATE_TOP_K = 20;
14828
14840
  async function retain(content, ctx, options = {}) {
14841
+ return retainWithPersistence(
14842
+ content,
14843
+ {
14844
+ embeddingOptions: ctx.embeddingOptions,
14845
+ vaultCache: ctx.vaultCache,
14846
+ persistence: {
14847
+ prepare: (query, searchOptions) => prepareVaultCandidates(
14848
+ query,
14849
+ ctx.vaultCtx,
14850
+ ctx.embeddingOptions,
14851
+ ctx.vaultCache,
14852
+ searchOptions
14853
+ ),
14854
+ get: (id) => getVaultMemoryOp(ctx.vaultCtx, id),
14855
+ tombstones: (_embedding, _model, scope, folderId) => getAllVaultMemoriesOp(ctx.vaultCtx, {
14856
+ includeDeleted: true,
14857
+ scopes: [scope],
14858
+ ...folderId !== void 0 && { folderId }
14859
+ }),
14860
+ create: (input) => createVaultMemoryOp(ctx.vaultCtx, input),
14861
+ update: (id, patch) => updateVaultMemoryOp(ctx.vaultCtx, id, patch),
14862
+ supersede: (id, successor) => supersedeVaultMemoryOp(ctx.vaultCtx, id, successor),
14863
+ createSuperseding: (input, target) => createSupersedingMemoryOp(ctx.vaultCtx, input, target)
14864
+ }
14865
+ },
14866
+ options
14867
+ );
14868
+ }
14869
+ async function retainWithPersistence(content, ctx, options = {}) {
14829
14870
  const trimmed = content.trim();
14830
14871
  if (trimmed.length === 0) {
14831
14872
  throw new Error("retain: content cannot be empty");
@@ -14838,19 +14879,13 @@ async function retain(content, ctx, options = {}) {
14838
14879
  let supersedeContent;
14839
14880
  let prepared;
14840
14881
  if (enableAutoMerge) {
14841
- prepared = await prepareVaultCandidates(
14842
- trimmed,
14843
- ctx.vaultCtx,
14844
- ctx.embeddingOptions,
14845
- ctx.vaultCache,
14846
- {
14847
- limit: Math.max(options.consolidateTopK ?? DEFAULT_CONSOLIDATE_TOP_K, 1),
14848
- useFusion: false,
14849
- scopes: [resolvedScope],
14850
- includeArchived: true,
14851
- ...options.folderId !== void 0 && { folderId: options.folderId }
14852
- }
14853
- );
14882
+ prepared = await ctx.persistence.prepare(trimmed, {
14883
+ limit: Math.max(options.consolidateTopK ?? DEFAULT_CONSOLIDATE_TOP_K, 1),
14884
+ useFusion: false,
14885
+ scopes: [resolvedScope],
14886
+ includeArchived: true,
14887
+ ...options.folderId !== void 0 && { folderId: options.folderId }
14888
+ });
14854
14889
  if (prepared.embeddingFailure || prepared.embeddingsUnavailable) {
14855
14890
  throw new Error(
14856
14891
  "retain: embeddings unavailable \u2014 refusing to auto-merge against an inert cosine lane, which would create a duplicate instead of merging into the existing memory. Retry when embeddings recover, or pass enableAutoMerge: false to force a create."
@@ -14881,7 +14916,7 @@ async function retain(content, ctx, options = {}) {
14881
14916
  );
14882
14917
  if (matches.length > 0) {
14883
14918
  const targetId = matches[0].uniqueId;
14884
- const existing = await getVaultMemoryOp(ctx.vaultCtx, targetId);
14919
+ const existing = await ctx.persistence.get(targetId);
14885
14920
  if (existing && !existing.supersededBy) {
14886
14921
  const mergedSourceIds = unionStrings(
14887
14922
  existing.sourceChunkIds ?? [],
@@ -14890,7 +14925,7 @@ async function retain(content, ctx, options = {}) {
14890
14925
  const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
14891
14926
  const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
14892
14927
  const resurrect = resurrectFields(existing);
14893
- const updated = await updateVaultMemoryOp(ctx.vaultCtx, targetId, {
14928
+ const updated = await ctx.persistence.update(targetId, {
14894
14929
  content: existing.content,
14895
14930
  proofCountIncrement: 1,
14896
14931
  observationSourceIds: options.sourceChunkIds,
@@ -14917,7 +14952,8 @@ async function retain(content, ctx, options = {}) {
14917
14952
  }
14918
14953
  const contentToWrite = supersedeContent ?? trimmed;
14919
14954
  const reusableQueryEmbedding = supersedeContent === void 0 && prepared && prepared.queryEmbedding.length > 0 ? prepared.queryEmbedding : void 0;
14920
- const embedding = reusableQueryEmbedding ?? await generateEmbedding(contentToWrite, ctx.embeddingOptions);
14955
+ const generatedEmbedding = reusableQueryEmbedding ?? await generateEmbedding(contentToWrite, ctx.embeddingOptions);
14956
+ const embedding = ctx.normalizeEmbedding?.(generatedEmbedding) ?? generatedEmbedding;
14921
14957
  const embeddingModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
14922
14958
  if (options.respectTombstones) {
14923
14959
  const tombstone = await findTombstoneMatch(embedding, embeddingModel, resolvedScope, ctx, {
@@ -14957,8 +14993,7 @@ async function retain(content, ctx, options = {}) {
14957
14993
  };
14958
14994
  if (supersedeTargetIds.length > 0) {
14959
14995
  const [primaryTargetId, ...restTargetIds] = supersedeTargetIds;
14960
- const { created: created2, retired } = await createSupersedingMemoryOp(
14961
- ctx.vaultCtx,
14996
+ const { created: created2, retired } = await ctx.persistence.createSuperseding(
14962
14997
  createOpts,
14963
14998
  primaryTargetId
14964
14999
  );
@@ -14974,11 +15009,11 @@ async function retain(content, ctx, options = {}) {
14974
15009
  for (const staleId of restTargetIds) {
14975
15010
  let ok = false;
14976
15011
  try {
14977
- ok = await supersedeVaultMemoryOp(ctx.vaultCtx, staleId, created2.uniqueId) === true;
15012
+ ok = await ctx.persistence.supersede(staleId, created2.uniqueId) === true;
14978
15013
  } catch {
14979
15014
  }
14980
15015
  if (ok) continue;
14981
- const stillLive = await getVaultMemoryOp(ctx.vaultCtx, staleId).catch(() => null);
15016
+ const stillLive = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(staleId) : ctx.persistence.get(staleId)).catch(() => null);
14982
15017
  if (stillLive && !stillLive.supersededBy) liveLeftovers.push(staleId);
14983
15018
  }
14984
15019
  if (liveLeftovers.length > 0) {
@@ -15005,7 +15040,7 @@ async function retain(content, ctx, options = {}) {
15005
15040
  `supersede: primary target ${primaryTargetId} retired or deleted inside the atomic write`
15006
15041
  );
15007
15042
  }
15008
- const created = await createVaultMemoryOp(ctx.vaultCtx, createOpts);
15043
+ const created = await ctx.persistence.create(createOpts);
15009
15044
  cacheRowVector(
15010
15045
  ctx.vaultCache,
15011
15046
  created.uniqueId,
@@ -15024,11 +15059,7 @@ function unionStrings(a, b) {
15024
15059
  return [.../* @__PURE__ */ new Set([...a, ...b])];
15025
15060
  }
15026
15061
  async function findTombstoneMatch(embedding, embeddingModel, scope, ctx, opts) {
15027
- const rows = await getAllVaultMemoriesOp(ctx.vaultCtx, {
15028
- includeDeleted: true,
15029
- scopes: [scope],
15030
- ...opts.folderId !== void 0 && { folderId: opts.folderId }
15031
- });
15062
+ const rows = await ctx.persistence.tombstones(embedding, embeddingModel, scope, opts.folderId);
15032
15063
  let bestId = null;
15033
15064
  let bestSim = opts.threshold;
15034
15065
  for (const row of rows) {
@@ -15095,7 +15126,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
15095
15126
  if (requestedIds.length === 0) return null;
15096
15127
  const valid = [];
15097
15128
  for (const id of requestedIds) {
15098
- const existing = await getVaultMemoryOp(ctx.vaultCtx, id);
15129
+ const existing = await ctx.persistence.get(id);
15099
15130
  if (existing && !existing.supersededBy) valid.push(id);
15100
15131
  }
15101
15132
  if (valid.length === 0) {
@@ -15107,7 +15138,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
15107
15138
  return { supersede: valid, content: decision.content };
15108
15139
  }
15109
15140
  if (decision.action === "noop" && decision.targetId) {
15110
- const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
15141
+ const existing = await ctx.persistence.get(decision.targetId);
15111
15142
  if (!existing || existing.supersededBy) {
15112
15143
  return abandonToRace(
15113
15144
  options,
@@ -15121,7 +15152,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
15121
15152
  const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
15122
15153
  const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
15123
15154
  const resurrect = resurrectFields(existing);
15124
- const updated = await updateVaultMemoryOp(ctx.vaultCtx, decision.targetId, {
15155
+ const updated = await ctx.persistence.update(decision.targetId, {
15125
15156
  content: existing.content,
15126
15157
  proofCountIncrement: 1,
15127
15158
  observationSourceIds: options.sourceChunkIds,
@@ -15149,7 +15180,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
15149
15180
  };
15150
15181
  }
15151
15182
  if (decision.action === "update" && decision.targetId && decision.content) {
15152
- const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
15183
+ const existing = await ctx.persistence.get(decision.targetId);
15153
15184
  if (!existing || existing.supersededBy) {
15154
15185
  return abandonToRace(
15155
15186
  options,
@@ -15160,12 +15191,13 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
15160
15191
  existing.sourceChunkIds ?? [],
15161
15192
  options.sourceChunkIds ?? []
15162
15193
  );
15163
- const newEmbedding = await generateEmbedding(decision.content, ctx.embeddingOptions);
15194
+ const generatedEmbedding = await generateEmbedding(decision.content, ctx.embeddingOptions);
15195
+ const newEmbedding = ctx.normalizeEmbedding?.(generatedEmbedding) ?? generatedEmbedding;
15164
15196
  const consolidatedModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
15165
15197
  const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
15166
15198
  const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
15167
15199
  const resurrect = resurrectFields(existing);
15168
- const updated = await updateVaultMemoryOp(ctx.vaultCtx, decision.targetId, {
15200
+ const updated = await ctx.persistence.update(decision.targetId, {
15169
15201
  content: decision.content,
15170
15202
  proofCountIncrement: 1,
15171
15203
  observationSourceIds: options.sourceChunkIds,
@@ -15209,7 +15241,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
15209
15241
  return null;
15210
15242
  }
15211
15243
  async function assertMergeTargetGoneOrThrow(ctx, targetId) {
15212
- const stillExists = await getVaultMemoryOp(ctx.vaultCtx, targetId);
15244
+ const stillExists = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(targetId) : ctx.persistence.get(targetId));
15213
15245
  if (stillExists) {
15214
15246
  throw new Error(`retain: merge into memory ${targetId} failed to persist`);
15215
15247
  }
@@ -15724,9 +15756,9 @@ function createAutoExtractor(options) {
15724
15756
  const persistCursor = (conversationId, messages, advancedToId, contiguous) => {
15725
15757
  if (!cursorStore || conversationId === void 0 || !contiguous) return;
15726
15758
  try {
15727
- const stored = cursorStore.get(conversationId);
15728
- if (stored && stored !== advancedToId) {
15729
- const storedIdx = messages.findIndex((m) => m.id === stored);
15759
+ const stored2 = cursorStore.get(conversationId);
15760
+ if (stored2 && stored2 !== advancedToId) {
15761
+ const storedIdx = messages.findIndex((m) => m.id === stored2);
15730
15762
  const newIdx = messages.findIndex((m) => m.id === advancedToId);
15731
15763
  if (storedIdx !== -1 && newIdx !== -1 && storedIdx >= newIdx) return;
15732
15764
  }
@@ -16695,7 +16727,7 @@ async function recall(query, ctx, options = {}) {
16695
16727
  if (graphLaneFailed) degraded.push("graph-lane-failed");
16696
16728
  if (temporalLaneFailed) degraded.push("temporal-lane-failed");
16697
16729
  if (chunksScopeRestricted) degraded.push("chunks-scope-restricted");
16698
- const laneRan = types.includes("fact") && !!ctx.vaultCtx && !!ctx.vaultCache || types.includes("chunk") && !!ctx.storageCtx || chunksScopeRestricted && !!ctx.storageCtx;
16730
+ const laneRan = types.includes("fact") && (!!ctx.factSource || !!ctx.vaultCtx && !!ctx.vaultCache) || types.includes("chunk") && !!ctx.storageCtx || chunksScopeRestricted && !!ctx.storageCtx;
16699
16731
  const scores = admitted.map((m) => m.score);
16700
16732
  const minScoreApplied = factResults.length > 0 ? factFloor : chunkResults.length > 0 ? chunkFloor : factFloor >= 0 ? factFloor : chunkFloor;
16701
16733
  const diagnostics = {
@@ -16737,7 +16769,7 @@ async function recall(query, ctx, options = {}) {
16737
16769
  return { memories: [], usedBudget, reranked: false, candidateCount: 0 };
16738
16770
  }
16739
16771
  const needsChunkEmbedding = types.includes("chunk") && ctx.storageCtx;
16740
- const wantsTemporal = types.includes("fact") && ctx.vaultCtx;
16772
+ const wantsTemporal = types.includes("fact") && (ctx.factSource || ctx.vaultCtx);
16741
16773
  const graphRefiner = flags.traverse && options.graphRefine && options.decomposeOptions ? createLlmNeighborRefiner(options.decomposeOptions) : void 0;
16742
16774
  const queryEmbedTotalTimeoutMs = options.queryEmbedTotalTimeoutMs ?? DEFAULT_QUERY_EMBED_TOTAL_TIMEOUT_MS;
16743
16775
  const prepStart = nowMs2();
@@ -16767,7 +16799,7 @@ async function recall(query, ctx, options = {}) {
16767
16799
  safeLane(
16768
16800
  "graph",
16769
16801
  () => graphLaneFailed = true,
16770
- () => buildGraphLaneRanking(query, ctx, flags.traverse, {
16802
+ () => ctx.factSource ? ctx.factSource.graphRanking(query, flags.traverse, options) : buildGraphLaneRanking(query, ctx, flags.traverse, {
16771
16803
  ...options.maxHops !== void 0 && { maxHops: options.maxHops },
16772
16804
  ...options.entityFanout !== void 0 && { entityFanout: options.entityFanout },
16773
16805
  ...options.nodeBudget !== void 0 && { nodeBudget: options.nodeBudget },
@@ -16778,13 +16810,13 @@ async function recall(query, ctx, options = {}) {
16778
16810
  wantsTemporal ? safeLane(
16779
16811
  "temporal",
16780
16812
  () => temporalLaneFailed = true,
16781
- () => buildTemporalLaneRanking(query, ctx.vaultCtx, options.now)
16813
+ () => ctx.factSource ? ctx.factSource.temporalRanking(query, options.now) : buildTemporalLaneRanking(query, ctx.vaultCtx, options.now)
16782
16814
  ) : Promise.resolve([])
16783
16815
  ]);
16784
16816
  prepMs = nowMs2() - prepStart;
16785
16817
  graphLaneCount = entityRanking.length;
16786
16818
  temporalLaneCount = temporalRanking.length;
16787
- if (types.includes("fact") && ctx.vaultCtx && ctx.vaultCache) {
16819
+ if (types.includes("fact") && (ctx.factSource || ctx.vaultCtx && ctx.vaultCache)) {
16788
16820
  const factStart = nowMs2();
16789
16821
  const vaultMinScore = options.minScore ?? DEFAULT_FACT_MIN_SCORE;
16790
16822
  factFloor = vaultMinScore;
@@ -16800,50 +16832,50 @@ async function recall(query, ctx, options = {}) {
16800
16832
  rankedOnCosine: factRankedOnCosine,
16801
16833
  decryptLast: factDecryptLast,
16802
16834
  rowsDecrypted: factRowsDecrypted
16803
- } = await searchVaultMemoriesWithSize(
16804
- query,
16835
+ } = await (ctx.factSource?.search.bind(ctx.factSource) ?? ((searchQuery, searchOptions) => searchVaultMemoriesWithSize(
16836
+ searchQuery,
16805
16837
  ctx.vaultCtx,
16806
16838
  ctx.embeddingOptions,
16807
16839
  ctx.vaultCache,
16808
- {
16809
- limit: types.includes("chunk") ? Math.max(limit * 2, 16) : limit,
16810
- minSimilarity: vaultMinScore,
16811
- useFusion: true,
16812
- rerank: flags.rerank,
16813
- ...options.rerankTopN !== void 0 && { rerankTopN: options.rerankTopN },
16814
- ...options.ceWeight !== void 0 && { ceWeight: options.ceWeight },
16815
- ...options.rerankLoadTimeoutMs !== void 0 && {
16816
- rerankLoadTimeoutMs: options.rerankLoadTimeoutMs
16817
- },
16818
- ...options.recencyAlpha !== void 0 && { recencyAlpha: options.recencyAlpha },
16819
- ...options.recency && { recency: options.recency },
16820
- ...options.mmr !== void 0 && { mmr: options.mmr },
16821
- ...options.supersessionBoost !== void 0 && {
16822
- supersessionBoost: options.supersessionBoost
16823
- },
16824
- ...options.supersessionWindow !== void 0 && {
16825
- supersessionWindow: options.supersessionWindow
16826
- },
16827
- ...options.proofCountAlpha !== void 0 && {
16828
- proofCountAlpha: options.proofCountAlpha
16829
- },
16830
- ...options.bm25AdmissionDivisor !== void 0 && {
16831
- bm25AdmissionDivisor: options.bm25AdmissionDivisor
16832
- },
16833
- ...options.rrfK !== void 0 && { rrfK: options.rrfK },
16834
- ...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
16835
- ...subQueries && { subQueries },
16836
- ...options.scopes && { scopes: options.scopes },
16837
- ...options.folderId !== void 0 && { folderId: options.folderId },
16838
- ...options.factTypes?.length && { factTypes: options.factTypes },
16839
- ...options.memoryIds !== void 0 && { memoryIds: options.memoryIds },
16840
- ...options.factTypeWeights && { factTypeWeights: options.factTypeWeights },
16841
- ...entityRanking.length > 0 && { entityRanking },
16842
- ...temporalRanking.length > 0 && { temporalRanking },
16843
- ...needsChunkEmbedding && { queryEmbedding: queryEmbedding ?? [] },
16844
- queryEmbedTotalTimeoutMs
16845
- }
16846
- );
16840
+ searchOptions
16841
+ )))(query, {
16842
+ limit: types.includes("chunk") ? Math.max(limit * 2, 16) : limit,
16843
+ minSimilarity: vaultMinScore,
16844
+ useFusion: true,
16845
+ rerank: flags.rerank,
16846
+ ...options.rerankTopN !== void 0 && { rerankTopN: options.rerankTopN },
16847
+ ...options.ceWeight !== void 0 && { ceWeight: options.ceWeight },
16848
+ ...options.rerankLoadTimeoutMs !== void 0 && {
16849
+ rerankLoadTimeoutMs: options.rerankLoadTimeoutMs
16850
+ },
16851
+ ...options.recencyAlpha !== void 0 && { recencyAlpha: options.recencyAlpha },
16852
+ ...options.recency && { recency: options.recency },
16853
+ ...options.mmr !== void 0 && { mmr: options.mmr },
16854
+ ...options.supersessionBoost !== void 0 && {
16855
+ supersessionBoost: options.supersessionBoost
16856
+ },
16857
+ ...options.supersessionWindow !== void 0 && {
16858
+ supersessionWindow: options.supersessionWindow
16859
+ },
16860
+ ...options.proofCountAlpha !== void 0 && {
16861
+ proofCountAlpha: options.proofCountAlpha
16862
+ },
16863
+ ...options.bm25AdmissionDivisor !== void 0 && {
16864
+ bm25AdmissionDivisor: options.bm25AdmissionDivisor
16865
+ },
16866
+ ...options.rrfK !== void 0 && { rrfK: options.rrfK },
16867
+ ...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
16868
+ ...subQueries && { subQueries },
16869
+ ...options.scopes && { scopes: options.scopes },
16870
+ ...options.folderId !== void 0 && { folderId: options.folderId },
16871
+ ...options.factTypes?.length && { factTypes: options.factTypes },
16872
+ ...options.memoryIds !== void 0 && { memoryIds: options.memoryIds },
16873
+ ...options.factTypeWeights && { factTypeWeights: options.factTypeWeights },
16874
+ ...entityRanking.length > 0 && { entityRanking },
16875
+ ...temporalRanking.length > 0 && { temporalRanking },
16876
+ ...needsChunkEmbedding && { queryEmbedding: queryEmbedding ?? [] },
16877
+ queryEmbedTotalTimeoutMs
16878
+ });
16847
16879
  factResults.push(
16848
16880
  ...dedupeBy(
16849
16881
  results,
@@ -17648,26 +17680,26 @@ async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
17648
17680
  };
17649
17681
  const inputs = [];
17650
17682
  for (const id of new Set(memoryIds)) {
17651
- let record;
17683
+ let record2;
17652
17684
  try {
17653
- record = await ctx.vaultMemoryCollection.find(id);
17685
+ record2 = await ctx.vaultMemoryCollection.find(id);
17654
17686
  } catch (err) {
17655
17687
  log.warn("[memory/topics] vault lookup failed for extraction", err);
17656
17688
  skip(id, "not-found");
17657
17689
  continue;
17658
17690
  }
17659
- if (record.isDeleted || ctx.userId !== void 0 && record.userId !== ctx.userId || record.topicsUserManaged) {
17691
+ if (record2.isDeleted || ctx.userId !== void 0 && record2.userId !== ctx.userId || record2.topicsUserManaged) {
17660
17692
  skip(id, "excluded");
17661
17693
  continue;
17662
17694
  }
17663
17695
  try {
17664
- const stored = await vaultMemoryToStored(
17665
- record,
17696
+ const stored2 = await vaultMemoryToStored(
17697
+ record2,
17666
17698
  ctx.walletAddress,
17667
17699
  ctx.signMessage,
17668
17700
  ctx.embeddedWalletSigner
17669
17701
  );
17670
- inputs.push({ id, content: stored.content });
17702
+ inputs.push({ id, content: stored2.content });
17671
17703
  } catch (err) {
17672
17704
  log.warn("[memory/topics] failed to load memory for extraction", err);
17673
17705
  skip(id, "unreadable");
@@ -17852,6 +17884,773 @@ function createLocalMemoryStore(options) {
17852
17884
  };
17853
17885
  }
17854
17886
 
17887
+ // src/lib/memory/store/remotePersistence.ts
17888
+ var RemoteMemoryError = class extends Error {
17889
+ constructor(message, status, code) {
17890
+ super(message);
17891
+ this.status = status;
17892
+ this.code = code;
17893
+ this.name = "RemoteMemoryError";
17894
+ }
17895
+ };
17896
+ var ciphertextPattern = /^enc:v\d+:[0-9a-f]+$/i;
17897
+ var memoryFields = {
17898
+ memory_id: true,
17899
+ content: true,
17900
+ scope: true,
17901
+ created_at: true,
17902
+ updated_at: true,
17903
+ is_deleted: true,
17904
+ embedding: true,
17905
+ embedding_model: true,
17906
+ kind: true,
17907
+ kind_value: true,
17908
+ level: true,
17909
+ folder_id: true,
17910
+ source_chunk_ids: true,
17911
+ proof_count: true,
17912
+ source: true,
17913
+ event_time_start: true,
17914
+ event_time_end: true,
17915
+ event_time_kind: true,
17916
+ topics_user_managed: true,
17917
+ topics: true,
17918
+ topics_updated_at: true,
17919
+ media: true,
17920
+ topics_extracted_at: true,
17921
+ topics_extracted_version: true,
17922
+ superseded_by: true,
17923
+ superseded_at: true,
17924
+ last_observed_at: true,
17925
+ fact_type: true,
17926
+ archived_at: true,
17927
+ trust_tier: true,
17928
+ visibility: true,
17929
+ twin_opt_in: true,
17930
+ published_at: true,
17931
+ geohash: true
17932
+ };
17933
+ var candidateListLimits = [
17934
+ ["scopes", 20],
17935
+ ["fact_types", 20],
17936
+ ["memory_ids", 1e3],
17937
+ ["force_ids", 100]
17938
+ ];
17939
+ function record(value) {
17940
+ return typeof value === "object" && value !== null && !Array.isArray(value);
17941
+ }
17942
+ function memoryRecord(value) {
17943
+ if (!record(value) || !record(value.memory) || typeof value.memory.memory_id !== "string" || typeof value.memory.content !== "string" || typeof value.memory.scope !== "string" || typeof value.memory.created_at !== "number" || typeof value.memory.updated_at !== "number" || typeof value.memory.is_deleted !== "boolean" || !Number.isSafeInteger(value.version) || value.version < 1 || typeof value.server_updated_at !== "string" || value.score !== void 0 && (typeof value.score !== "number" || !Number.isFinite(value.score))) {
17944
+ throw new Error("Invalid nearby private-memory response");
17945
+ }
17946
+ return value;
17947
+ }
17948
+ async function createRemoteMemoryPersistence(options) {
17949
+ const base = new URL(options.baseUrl);
17950
+ if (!/^https?:$/.test(base.protocol) || base.username || base.password || base.search || base.hash) {
17951
+ throw new Error(
17952
+ "baseUrl must be an HTTP(S) origin or base path without credentials, query or fragment"
17953
+ );
17954
+ }
17955
+ if (!options.keyId || options.keyId.length > 256)
17956
+ throw new Error("A canonical keyId is required");
17957
+ const timeoutMs = options.timeoutMs ?? 3e4;
17958
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0)
17959
+ throw new Error("timeoutMs must be a positive number");
17960
+ const root = base.href.replace(/\/$/, "") + "/api/private-memories";
17961
+ const fetcher = options.fetch ?? globalThis.fetch;
17962
+ const request = async (path, init = {}, signal) => {
17963
+ const controller = new AbortController();
17964
+ let timedOut = false;
17965
+ const timer = setTimeout(() => {
17966
+ timedOut = true;
17967
+ controller.abort();
17968
+ }, timeoutMs);
17969
+ const forwardAbort = () => controller.abort(signal?.reason);
17970
+ if (signal?.aborted) forwardAbort();
17971
+ else signal?.addEventListener("abort", forwardAbort, { once: true });
17972
+ let rejectAborted;
17973
+ const aborted = new Promise((_, reject) => {
17974
+ rejectAborted = () => reject(
17975
+ controller.signal.reason instanceof Error ? controller.signal.reason : new Error("Nearby request aborted")
17976
+ );
17977
+ if (controller.signal.aborted) rejectAborted();
17978
+ else controller.signal.addEventListener("abort", rejectAborted, { once: true });
17979
+ });
17980
+ aborted.catch(() => void 0);
17981
+ try {
17982
+ const token = await Promise.race([options.getToken(), aborted]);
17983
+ if (controller.signal.aborted) await aborted;
17984
+ if (!token) throw new RemoteMemoryError("Authentication required", 401);
17985
+ const response = await fetcher(root + path, {
17986
+ ...init,
17987
+ headers: {
17988
+ Authorization: `Bearer ${token}`,
17989
+ ...init.body ? { "Content-Type": "application/json" } : {}
17990
+ },
17991
+ redirect: "error",
17992
+ signal: controller.signal
17993
+ });
17994
+ if (!response.ok) {
17995
+ const body = await response.json().catch(() => null);
17996
+ throw new RemoteMemoryError(
17997
+ record(body) && typeof body.detail === "string" ? body.detail : `Nearby request failed (${response.status})`,
17998
+ response.status,
17999
+ record(body) && typeof body.code === "string" ? body.code : void 0
18000
+ );
18001
+ }
18002
+ return await response.json();
18003
+ } catch (error) {
18004
+ if (timedOut) throw new RemoteMemoryError("Nearby request timed out", 408, "timeout");
18005
+ throw error;
18006
+ } finally {
18007
+ clearTimeout(timer);
18008
+ signal?.removeEventListener("abort", forwardAbort);
18009
+ if (rejectAborted) controller.signal.removeEventListener("abort", rejectAborted);
18010
+ }
18011
+ };
18012
+ const account = await request("/account", {}, options.signal);
18013
+ if (!record(account) || account.state !== "active") {
18014
+ throw new RemoteMemoryError(
18015
+ "Complete and verify migration before using remote memories",
18016
+ 409,
18017
+ "memory_not_active"
18018
+ );
18019
+ }
18020
+ if (account.key_id !== options.keyId) {
18021
+ throw new RemoteMemoryError(
18022
+ "The canonical memory key does not match this account",
18023
+ 409,
18024
+ "key_mismatch"
18025
+ );
18026
+ }
18027
+ const snapshots = /* @__PURE__ */ new WeakMap();
18028
+ const decode = async (value) => {
18029
+ const item = memoryRecord(value);
18030
+ const decrypt = async (ciphertext) => {
18031
+ if (!ciphertextPattern.test(ciphertext))
18032
+ throw new Error("Nearby returned unencrypted memory content");
18033
+ const plaintext = await options.decrypt(ciphertext);
18034
+ if (plaintext === ciphertext) throw new Error("Memory decryption failed");
18035
+ return plaintext;
18036
+ };
18037
+ const decoded = {
18038
+ ...item,
18039
+ memory: {
18040
+ ...item.memory,
18041
+ content: await decrypt(item.memory.content),
18042
+ ...item.memory.kind_value !== void 0 && {
18043
+ kind_value: await decrypt(item.memory.kind_value)
18044
+ }
18045
+ }
18046
+ };
18047
+ return remember(decoded, item);
18048
+ };
18049
+ const remember = (decoded, item) => {
18050
+ snapshots.set(decoded, {
18051
+ id: item.memory.memory_id,
18052
+ version: item.version,
18053
+ content: decoded.memory.content,
18054
+ kindValue: decoded.memory.kind_value,
18055
+ encryptedContent: item.memory.content,
18056
+ encryptedKindValue: item.memory.kind_value
18057
+ });
18058
+ return decoded;
18059
+ };
18060
+ const decodeAll = async (values) => {
18061
+ const records = values.map(memoryRecord);
18062
+ const settled = await Promise.allSettled(records.map(decode));
18063
+ const items = [];
18064
+ const failed = [];
18065
+ settled.forEach((result, i) => {
18066
+ if (result.status === "fulfilled") items.push(result.value);
18067
+ else
18068
+ failed.push({
18069
+ memory_id: records[i].memory.memory_id,
18070
+ version: records[i].version,
18071
+ error: result.reason instanceof Error ? result.reason : new Error(String(result.reason))
18072
+ });
18073
+ });
18074
+ return { items, failed };
18075
+ };
18076
+ const decodeCommitted = async (value, write) => {
18077
+ const item = memoryRecord(value);
18078
+ if (item.memory.memory_id !== write.body.memory.memory_id || item.memory.content !== write.body.memory.content || item.memory.kind_value !== write.body.memory.kind_value)
18079
+ return decode(item);
18080
+ return remember(
18081
+ {
18082
+ ...item,
18083
+ memory: {
18084
+ ...item.memory,
18085
+ content: write.content,
18086
+ ...write.kindValue !== void 0 && { kind_value: write.kindValue }
18087
+ }
18088
+ },
18089
+ item
18090
+ );
18091
+ };
18092
+ const encryptField2 = async (plaintext) => {
18093
+ const ciphertext = await options.encrypt(plaintext);
18094
+ if (ciphertext === plaintext || !ciphertextPattern.test(ciphertext))
18095
+ throw new Error("Field encryption must return SDK ciphertext; refusing to upload plaintext");
18096
+ return ciphertext;
18097
+ };
18098
+ const memoryPath = (id) => {
18099
+ if (!id || id.length > 128) throw new Error("memory_id must be 1\u2013128 characters");
18100
+ return "/memories/" + encodeURIComponent(id);
18101
+ };
18102
+ const prepareWrite = async (memory, expectedVersion, signal) => {
18103
+ const unknown = Object.keys(memory).filter(
18104
+ (key) => !Object.prototype.hasOwnProperty.call(memoryFields, key)
18105
+ );
18106
+ if (unknown.length) {
18107
+ throw new RemoteMemoryError(
18108
+ `Unknown private-memory fields (${unknown.join(", ")}); refusing to forward them`,
18109
+ 400,
18110
+ "unknown_field"
18111
+ );
18112
+ }
18113
+ memory = { ...memory, ...memory.embedding && { embedding: [...memory.embedding] } };
18114
+ const path = memoryPath(memory.memory_id);
18115
+ const snapshot = typeof expectedVersion === "number" ? void 0 : snapshots.get(expectedVersion);
18116
+ if (typeof expectedVersion !== "number" && (!snapshot || snapshot.id !== memory.memory_id || snapshot.version !== expectedVersion.version))
18117
+ throw new Error(
18118
+ "Expected snapshot must be an unmodified version from this persistence instance"
18119
+ );
18120
+ expectedVersion = typeof expectedVersion === "number" ? expectedVersion : snapshot.version;
18121
+ if (!Number.isSafeInteger(expectedVersion) || expectedVersion < 0)
18122
+ throw new Error("expectedVersion must be a nonnegative integer");
18123
+ const conflict = () => new RemoteMemoryError("The memory changed since it was read", 409, "version_conflict");
18124
+ let existing;
18125
+ if (expectedVersion !== 0 && !snapshot) {
18126
+ try {
18127
+ existing = memoryRecord(await request(path, {}, signal));
18128
+ } catch (error) {
18129
+ if (error instanceof RemoteMemoryError && error.status === 404) throw conflict();
18130
+ throw error;
18131
+ }
18132
+ }
18133
+ if (existing && existing.version !== expectedVersion) throw conflict();
18134
+ const decoded = existing ? await decode(existing).catch(() => void 0) : void 0;
18135
+ const content = (snapshot?.content ?? decoded?.memory.content) === memory.content ? snapshot?.encryptedContent ?? existing.memory.content : await encryptField2(memory.content);
18136
+ const kindValue = memory.kind_value === void 0 ? void 0 : (snapshot?.kindValue ?? decoded?.memory.kind_value) === memory.kind_value ? snapshot?.encryptedKindValue ?? existing.memory.kind_value : await encryptField2(memory.kind_value);
18137
+ return {
18138
+ body: {
18139
+ expected_version: expectedVersion,
18140
+ memory: { ...memory, content, ...kindValue !== void 0 && { kind_value: kindValue } }
18141
+ },
18142
+ content: memory.content,
18143
+ kindValue: memory.kind_value
18144
+ };
18145
+ };
18146
+ const fetchCandidates = async (embedding, candidateOptions, withCounts) => {
18147
+ const limit = candidateOptions.limit ?? 100;
18148
+ if (!Number.isInteger(limit) || limit < 1 || limit > 100)
18149
+ throw new Error("Candidate limit must be 1\u2013100");
18150
+ for (const [key, max] of candidateListLimits) {
18151
+ const values = candidateOptions[key];
18152
+ if (values && values.length > max)
18153
+ throw new Error(`Candidate ${key} accepts at most ${max} entries (got ${values.length})`);
18154
+ }
18155
+ const result = await request(
18156
+ "/candidates",
18157
+ {
18158
+ method: "POST",
18159
+ body: JSON.stringify({
18160
+ embedding,
18161
+ limit,
18162
+ force_ids: candidateOptions.force_ids ?? [],
18163
+ ...withCounts && { with_counts: true },
18164
+ ...Object.fromEntries(
18165
+ [
18166
+ "scopes",
18167
+ "memory_ids",
18168
+ "embedding_model",
18169
+ "strict_model",
18170
+ "include_deleted",
18171
+ "deleted_only"
18172
+ ].filter(
18173
+ (key) => candidateOptions[key] !== void 0
18174
+ ).map((key) => [key, candidateOptions[key]])
18175
+ ),
18176
+ ...candidateOptions.fact_types !== void 0 && {
18177
+ fact_types: candidateOptions.fact_types
18178
+ },
18179
+ ...candidateOptions.include_archived !== void 0 && {
18180
+ include_archived: candidateOptions.include_archived
18181
+ },
18182
+ ...candidateOptions.include_quarantined !== void 0 && {
18183
+ include_quarantined: candidateOptions.include_quarantined
18184
+ },
18185
+ ...candidateOptions.include_superseded !== void 0 && {
18186
+ include_superseded: candidateOptions.include_superseded
18187
+ }
18188
+ })
18189
+ },
18190
+ candidateOptions.signal
18191
+ );
18192
+ if (!record(result) || !Array.isArray(result.items))
18193
+ throw new Error("Invalid nearby candidate response");
18194
+ return result;
18195
+ };
18196
+ const candidateSet = async (embedding, candidateOptions = {}) => {
18197
+ const result = await fetchCandidates(embedding, candidateOptions, true);
18198
+ if (!Number.isSafeInteger(result.total_count) || result.total_count < 0 || !Number.isSafeInteger(result.unavailable_count) || result.unavailable_count < 0)
18199
+ throw new Error("Invalid nearby candidate response");
18200
+ return {
18201
+ ...await decodeAll(result.items),
18202
+ total_count: result.total_count,
18203
+ unavailable_count: result.unavailable_count
18204
+ };
18205
+ };
18206
+ return {
18207
+ get: async (id, signal) => {
18208
+ try {
18209
+ return await decode(await request(memoryPath(id), {}, signal));
18210
+ } catch (error) {
18211
+ if (error instanceof RemoteMemoryError && error.status === 404) return null;
18212
+ throw error;
18213
+ }
18214
+ },
18215
+ list: async (listOptions = {}) => {
18216
+ const { signal, ...query } = listOptions;
18217
+ if (query.limit !== void 0 && (!Number.isInteger(query.limit) || query.limit < 1 || query.limit > 200)) {
18218
+ throw new Error("Page limit must be 1\u2013200");
18219
+ }
18220
+ const params = new URLSearchParams();
18221
+ for (const key of [
18222
+ "cursor",
18223
+ "limit",
18224
+ "include_deleted",
18225
+ "include_archived",
18226
+ "include_quarantined",
18227
+ "include_superseded",
18228
+ "include_embeddings"
18229
+ ]) {
18230
+ if (query[key] !== void 0) params.set(key, String(query[key]));
18231
+ }
18232
+ const page = await request("/memories?" + params.toString(), {}, signal);
18233
+ if (!record(page) || !Array.isArray(page.items) || page.next_cursor !== void 0 && typeof page.next_cursor !== "string") {
18234
+ throw new Error("Invalid nearby private-memory page");
18235
+ }
18236
+ return {
18237
+ ...await decodeAll(page.items),
18238
+ ...page.next_cursor !== void 0 && { next_cursor: page.next_cursor }
18239
+ };
18240
+ },
18241
+ put: async (memory, expectedVersion, signal) => {
18242
+ const write = await prepareWrite(memory, expectedVersion, signal);
18243
+ return decodeCommitted(
18244
+ await request(
18245
+ memoryPath(write.body.memory.memory_id),
18246
+ {
18247
+ method: "PUT",
18248
+ body: JSON.stringify({ key_id: options.keyId, ...write.body })
18249
+ },
18250
+ signal
18251
+ ),
18252
+ write
18253
+ );
18254
+ },
18255
+ putMany: async (writes, signal) => {
18256
+ if (writes.length < 1 || writes.length > 50 || new Set(writes.map((w) => w.memory.memory_id)).size !== writes.length)
18257
+ throw new Error("Batch must contain 1\u201350 distinct memory ids");
18258
+ const prepared = await Promise.all(
18259
+ writes.map((w) => prepareWrite(w.memory, w.expectedVersion, signal))
18260
+ );
18261
+ const result = await request(
18262
+ "/memories/batch",
18263
+ {
18264
+ method: "POST",
18265
+ body: JSON.stringify({ key_id: options.keyId, writes: prepared.map((w) => w.body) })
18266
+ },
18267
+ signal
18268
+ );
18269
+ if (!record(result) || !Array.isArray(result.items) || result.items.length !== prepared.length)
18270
+ throw new Error("Invalid nearby batch response");
18271
+ return Promise.all(result.items.map((item, i) => decodeCommitted(item, prepared[i])));
18272
+ },
18273
+ candidateSet,
18274
+ candidates: async (embedding, candidateOptions = {}) => decodeAll((await fetchCandidates(embedding, candidateOptions, false)).items)
18275
+ };
18276
+ }
18277
+
18278
+ // src/lib/memory/store/remotePipeline.ts
18279
+ import { v7 as uuidv74 } from "uuid";
18280
+ function storedVector(vector) {
18281
+ if (!Array.isArray(vector) || vector.length !== 1536 && vector.length !== 4096 || vector.some((v) => !Number.isFinite(v)))
18282
+ throw new Error("Remote memories require a finite 1536/4096-dimensional vector");
18283
+ const out = vector.slice(0, 1536);
18284
+ const norm = Math.sqrt(out.reduce((sum, v) => sum + v * v, 0));
18285
+ if (!norm) throw new Error("Remote query/content vector has no direction after MRL truncation");
18286
+ return out.map((v) => v / norm);
18287
+ }
18288
+ function sourceIds(value) {
18289
+ if (!value) return [];
18290
+ try {
18291
+ const parsed = JSON.parse(value);
18292
+ return Array.isArray(parsed) ? parsed.filter((id) => typeof id === "string") : [];
18293
+ } catch {
18294
+ return [];
18295
+ }
18296
+ }
18297
+ function stored(row) {
18298
+ return {
18299
+ uniqueId: row.memory_id,
18300
+ content: row.content,
18301
+ scope: row.scope,
18302
+ folderId: row.folder_id ?? null,
18303
+ userId: null,
18304
+ embedding: row.embedding ? JSON.stringify(row.embedding) : null,
18305
+ embeddingModel: row.embedding_model ?? null,
18306
+ sourceChunkIds: row.source_chunk_ids === void 0 ? null : sourceIds(row.source_chunk_ids),
18307
+ proofCount: row.proof_count ?? null,
18308
+ source: row.source ?? null,
18309
+ media: parseMedia(row.media),
18310
+ eventTimeStart: row.event_time_start ?? null,
18311
+ eventTimeEnd: row.event_time_end ?? null,
18312
+ eventTimeKind: row.event_time_kind ?? null,
18313
+ topicsUserManaged: row.topics_user_managed ?? false,
18314
+ topics: parseTopics(row.topics),
18315
+ topicsUpdatedAt: row.topics_updated_at ?? null,
18316
+ topicsExtractedAt: row.topics_extracted_at ?? null,
18317
+ topicsExtractedVersion: row.topics_extracted_version ?? null,
18318
+ supersededBy: row.superseded_by ?? null,
18319
+ supersededAt: row.superseded_at ?? null,
18320
+ lastObservedAt: row.last_observed_at ?? null,
18321
+ factType: row.fact_type ?? null,
18322
+ archivedAt: row.archived_at ?? null,
18323
+ trustTier: row.trust_tier ?? null,
18324
+ visibility: row.visibility === "public" ? "public" : "private",
18325
+ twinOptIn: row.twin_opt_in ?? false,
18326
+ publishedAt: row.published_at ?? null,
18327
+ geohash: row.geohash ?? null,
18328
+ createdAt: new Date(row.created_at),
18329
+ updatedAt: new Date(row.updated_at),
18330
+ isDeleted: row.is_deleted
18331
+ };
18332
+ }
18333
+ function createRemoteMemoryPipeline(options) {
18334
+ const { persistence, embeddingOptions } = options;
18335
+ const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
18336
+ const operation = (mode) => {
18337
+ const rejectUndecryptable = (failed) => {
18338
+ if (!failed.length) return;
18339
+ if (mode === "retain")
18340
+ throw new Error(
18341
+ `Remote memories could not decrypt ${failed.length} candidate row(s); refusing to retain until they are repaired`
18342
+ );
18343
+ getLogger().warn(
18344
+ `[memory/remote] Skipping ${failed.length} undecryptable candidate row(s)`,
18345
+ failed.map((failure) => failure.memory_id)
18346
+ );
18347
+ };
18348
+ const snapshots = /* @__PURE__ */ new Map();
18349
+ const remember = (items) => {
18350
+ items.forEach((item) => snapshots.set(item.memory.memory_id, item));
18351
+ return items.map((item) => stored(item.memory));
18352
+ };
18353
+ const get = async (id) => {
18354
+ const snapshot = snapshots.get(id) ?? await persistence.get(id);
18355
+ if (!snapshot || snapshot.memory.is_deleted || snapshot.memory.superseded_by) return null;
18356
+ snapshots.set(id, snapshot);
18357
+ return stored(snapshot.memory);
18358
+ };
18359
+ const prepare = async (query, search = {}) => {
18360
+ if (search.folderId !== void 0)
18361
+ throw new Error("Remote memories do not support folder filters");
18362
+ const facets = normalizeSubQueries(search.subQueries);
18363
+ const facetQueries = facets.length >= 2 ? facets : [];
18364
+ const start = Date.now();
18365
+ const budgetMs = search.queryEmbedTotalTimeoutMs ?? 8e3;
18366
+ const embed = (texts) => generateEmbeddings(texts, {
18367
+ ...embeddingOptions,
18368
+ totalTimeoutMs: budgetMs
18369
+ });
18370
+ const embedFacets = async () => {
18371
+ if (!facetQueries.length) return [];
18372
+ try {
18373
+ const vectors2 = await embed(facetQueries);
18374
+ if (vectors2.length !== facetQueries.length)
18375
+ throw new Error("Incomplete facet embeddings");
18376
+ return vectors2.map(storedVector);
18377
+ } catch (error) {
18378
+ getLogger().warn(
18379
+ "[memory/remote] Facet embeddings unavailable; using primary query",
18380
+ error
18381
+ );
18382
+ return [];
18383
+ }
18384
+ };
18385
+ const [primary, facetEmbeddings] = await Promise.all([
18386
+ search.queryEmbedding ?? embed([query]).then((vectors2) => vectors2[0]),
18387
+ embedFacets()
18388
+ ]);
18389
+ const queryEmbedding = storedVector(primary);
18390
+ const queryEmbedMs = Date.now() - start;
18391
+ const graph = search.entityRanking ?? [];
18392
+ const temporal = search.temporalRanking ?? [];
18393
+ const forced = /* @__PURE__ */ new Set();
18394
+ for (let i = 0; i < Math.max(graph.length, temporal.length) && forced.size < 100; i++) {
18395
+ if (graph[i] !== void 0) forced.add(graph[i]);
18396
+ if (forced.size < 100 && temporal[i] !== void 0) forced.add(temporal[i]);
18397
+ }
18398
+ const forceIds = [...forced];
18399
+ const windowOptions = (i, signal) => ({
18400
+ limit: Math.min(100, Math.max((search.limit ?? 8) * 3, 30)),
18401
+ force_ids: i === 0 ? forceIds : [],
18402
+ ...search.scopes && { scopes: search.scopes },
18403
+ ...search.factTypes && { fact_types: search.factTypes },
18404
+ ...search.memoryIds !== void 0 && { memory_ids: search.memoryIds },
18405
+ include_archived: search.includeArchived,
18406
+ embedding_model: model,
18407
+ ...signal && { signal }
18408
+ });
18409
+ const vectors = [queryEmbedding, ...facetEmbeddings];
18410
+ let windows;
18411
+ if (mode === "retain") {
18412
+ windows = await Promise.all(
18413
+ vectors.map((embedding, i) => persistence.candidateSet(embedding, windowOptions(i)))
18414
+ );
18415
+ } else {
18416
+ const deadline = new AbortController();
18417
+ const timer = setTimeout(
18418
+ () => deadline.abort(
18419
+ new RemoteMemoryError("Remote recall exceeded its query budget", 408, "timeout")
18420
+ ),
18421
+ Math.max(0, start + budgetMs - Date.now())
18422
+ );
18423
+ try {
18424
+ windows = await Promise.all(
18425
+ vectors.map(
18426
+ (embedding, i) => persistence.candidates(embedding, windowOptions(i, deadline.signal))
18427
+ )
18428
+ );
18429
+ } finally {
18430
+ clearTimeout(timer);
18431
+ }
18432
+ }
18433
+ rejectUndecryptable([
18434
+ ...new Map(
18435
+ windows.flatMap((window2) => window2.failed).map((failure) => [failure.memory_id, failure])
18436
+ ).values()
18437
+ ]);
18438
+ const items = [
18439
+ ...new Map(
18440
+ windows.flatMap((window2) => window2.items).map((item) => [item.memory.memory_id, item])
18441
+ ).values()
18442
+ ];
18443
+ const memories = remember(items);
18444
+ return {
18445
+ memories,
18446
+ embeddedItems: memories.map((memory) => ({
18447
+ id: memory.uniqueId,
18448
+ content: memory.content,
18449
+ embedding: JSON.parse(memory.embedding ?? "[]"),
18450
+ createdAt: memory.createdAt,
18451
+ updatedAt: memory.updatedAt,
18452
+ proofCount: memory.proofCount,
18453
+ lastObservedAt: memory.lastObservedAt,
18454
+ eventTimeStart: memory.eventTimeStart,
18455
+ eventTimeEnd: memory.eventTimeEnd,
18456
+ eventTimeKind: memory.eventTimeKind === "point" || memory.eventTimeKind === "range" || memory.eventTimeKind === "ongoing" ? memory.eventTimeKind : null,
18457
+ factType: memory.factType,
18458
+ sourceChunkIds: memory.sourceChunkIds
18459
+ })),
18460
+ queryEmbedding,
18461
+ facetEmbeddings,
18462
+ vaultSize: Math.max(windows[0].total_count ?? 0, items.length),
18463
+ embeddingFailure: windows.some((window2) => (window2.unavailable_count ?? 0) > 0),
18464
+ embeddingsUnavailable: (windows[0].total_count ?? items.length) > 0 && !memories.some((memory) => memory.embedding),
18465
+ decryptLast: true,
18466
+ rowsDecrypted: items.length,
18467
+ queryEmbedMs,
18468
+ rowsEmbedded: 0
18469
+ };
18470
+ };
18471
+ const createRow = (input) => {
18472
+ if (input.folderId !== void 0 && input.folderId !== null)
18473
+ throw new Error("Remote memories do not support folders");
18474
+ const now = Date.now();
18475
+ return {
18476
+ memory_id: uuidv74(),
18477
+ content: input.content,
18478
+ scope: input.scope ?? "private",
18479
+ created_at: now,
18480
+ updated_at: now,
18481
+ is_deleted: false,
18482
+ ...input.embedding !== void 0 && {
18483
+ embedding: storedVector(JSON.parse(input.embedding)),
18484
+ embedding_model: input.embeddingModel
18485
+ },
18486
+ source_chunk_ids: JSON.stringify(input.sourceChunkIds ?? []),
18487
+ proof_count: input.proofCount ?? 1,
18488
+ source: input.source ?? "manual",
18489
+ ...input.eventTime && {
18490
+ event_time_start: input.eventTime.start ?? void 0,
18491
+ event_time_end: input.eventTime.end ?? void 0,
18492
+ event_time_kind: input.eventTime.kind ?? void 0
18493
+ },
18494
+ fact_type: input.factType,
18495
+ trust_tier: normalizeTrustTier(input.trustTier) ?? void 0,
18496
+ geohash: input.geohash,
18497
+ visibility: "private",
18498
+ twin_opt_in: false
18499
+ };
18500
+ };
18501
+ const write = async (memory, snapshot) => remember([await persistence.put(memory, snapshot)])[0];
18502
+ const port = {
18503
+ prepare,
18504
+ get,
18505
+ getFresh: async (id) => {
18506
+ const current = await persistence.get(id);
18507
+ return current && !current.memory.is_deleted && !current.memory.superseded_by ? stored(current.memory) : null;
18508
+ },
18509
+ tombstones: async (embedding, embeddingModel, scope, folderId) => {
18510
+ if (folderId !== void 0) throw new Error("Remote memories do not support folders");
18511
+ const window2 = await persistence.candidateSet(storedVector(embedding), {
18512
+ limit: 1,
18513
+ scopes: [scope],
18514
+ embedding_model: embeddingModel,
18515
+ strict_model: true,
18516
+ include_deleted: true,
18517
+ deleted_only: true
18518
+ });
18519
+ rejectUndecryptable(window2.failed);
18520
+ return remember(window2.items);
18521
+ },
18522
+ create: (input) => write(createRow(input), 0),
18523
+ update: async (id, patch) => {
18524
+ const existing = await get(id);
18525
+ if (!existing) return null;
18526
+ const snapshot = snapshots.get(id);
18527
+ const memory = {
18528
+ ...snapshot.memory,
18529
+ content: patch.content,
18530
+ updated_at: patch.preserveUpdatedAt ? snapshot.memory.updated_at : Date.now()
18531
+ };
18532
+ if (patch.scope !== void 0) memory.scope = patch.scope;
18533
+ if (patch.embedding === void 0 && patch.content !== snapshot.memory.content) {
18534
+ delete memory.embedding;
18535
+ delete memory.embedding_model;
18536
+ }
18537
+ if (patch.embedding !== void 0) {
18538
+ memory.embedding = patch.embedding === null ? [] : storedVector(JSON.parse(patch.embedding));
18539
+ memory.embedding_model = patch.embeddingModel ?? void 0;
18540
+ }
18541
+ const observed = sourceIds(memory.source_chunk_ids);
18542
+ const replay = !!patch.observationSourceIds?.length && patch.observationSourceIds.every((id2) => observed.includes(id2));
18543
+ if (patch.sourceChunkIds !== void 0)
18544
+ memory.source_chunk_ids = JSON.stringify(
18545
+ patch.observationSourceIds?.length ? [.../* @__PURE__ */ new Set([...observed, ...patch.sourceChunkIds])] : patch.sourceChunkIds
18546
+ );
18547
+ if (!replay) {
18548
+ if (patch.proofCountIncrement !== void 0)
18549
+ memory.proof_count = (memory.proof_count ?? 1) + patch.proofCountIncrement;
18550
+ else if (patch.proofCount !== void 0) memory.proof_count = patch.proofCount;
18551
+ if (patch.lastObservedAt !== void 0) memory.last_observed_at = patch.lastObservedAt;
18552
+ }
18553
+ if (patch.source !== void 0) memory.source = patch.source;
18554
+ if (patch.factType !== void 0) memory.fact_type = patch.factType;
18555
+ if (patch.trustTier !== void 0)
18556
+ memory.trust_tier = normalizeTrustTier(patch.trustTier) ?? void 0;
18557
+ if (patch.topicsUserManaged !== void 0)
18558
+ memory.topics_user_managed = patch.topicsUserManaged;
18559
+ if (patch.eventTime !== void 0) {
18560
+ memory.event_time_start = patch.eventTime.start ?? void 0;
18561
+ memory.event_time_end = patch.eventTime.end ?? void 0;
18562
+ memory.event_time_kind = patch.eventTime.kind ?? void 0;
18563
+ }
18564
+ if (patch.restore) memory.archived_at = void 0;
18565
+ return write(memory, snapshot);
18566
+ },
18567
+ supersede: async (id, successor) => {
18568
+ const [target, newer] = await Promise.all([get(id), get(successor)]);
18569
+ if (!target || !newer || id === successor) return false;
18570
+ const old = snapshots.get(id);
18571
+ const next = snapshots.get(successor);
18572
+ remember(
18573
+ await persistence.putMany([
18574
+ {
18575
+ memory: { ...old.memory, superseded_by: successor, superseded_at: Date.now() },
18576
+ expectedVersion: old
18577
+ },
18578
+ { memory: next.memory, expectedVersion: next }
18579
+ ])
18580
+ );
18581
+ return true;
18582
+ },
18583
+ createSuperseding: async (input, targetId) => {
18584
+ const target = await get(targetId);
18585
+ if (!target) return { created: null, retired: false };
18586
+ const snapshot = snapshots.get(targetId);
18587
+ const successor = createRow(input);
18588
+ const rows = remember(
18589
+ await persistence.putMany([
18590
+ { memory: successor, expectedVersion: 0 },
18591
+ {
18592
+ memory: {
18593
+ ...snapshot.memory,
18594
+ superseded_by: successor.memory_id,
18595
+ superseded_at: Date.now()
18596
+ },
18597
+ expectedVersion: snapshot
18598
+ }
18599
+ ])
18600
+ );
18601
+ return { created: rows[0], retired: true };
18602
+ }
18603
+ };
18604
+ return { prepare, port };
18605
+ };
18606
+ return {
18607
+ recall: async (query, recallOptions = {}) => {
18608
+ const { prepare } = operation("recall");
18609
+ return recall(
18610
+ query,
18611
+ {
18612
+ embeddingOptions,
18613
+ factSource: {
18614
+ graphRanking: options.graphRanking,
18615
+ temporalRanking: options.temporalRanking,
18616
+ search: async (text12, searchOptions) => {
18617
+ const prepared = await prepare(text12, searchOptions);
18618
+ const ranked = await rankPreparedVaultCandidates(
18619
+ text12,
18620
+ prepared,
18621
+ embeddingOptions,
18622
+ searchOptions
18623
+ );
18624
+ return {
18625
+ ...ranked,
18626
+ rankedOnCosine: prepared.memories.length > 0 && !prepared.embeddingsUnavailable,
18627
+ decryptLast: true,
18628
+ rowsDecrypted: prepared.rowsDecrypted,
18629
+ queryEmbedMs: prepared.queryEmbedMs,
18630
+ rowsEmbedded: 0
18631
+ };
18632
+ }
18633
+ }
18634
+ },
18635
+ { ...recallOptions, types: ["fact"] }
18636
+ );
18637
+ },
18638
+ retain: async (content, retainOptions) => {
18639
+ const { port } = operation("retain");
18640
+ return retainWithPersistence(
18641
+ content,
18642
+ {
18643
+ persistence: port,
18644
+ embeddingOptions,
18645
+ vaultCache: /* @__PURE__ */ new Map(),
18646
+ normalizeEmbedding: storedVector
18647
+ },
18648
+ retainOptions
18649
+ );
18650
+ }
18651
+ };
18652
+ }
18653
+
17855
18654
  // src/lib/memory/synthesizeProfile.ts
17856
18655
  var DEFAULT_SYNTHESIS_MODEL = "inclusionai/ling-2.6-flash";
17857
18656
  var DEFAULT_FACET_RECALL_LIMIT = 20;
@@ -21262,7 +22061,7 @@ function useChat(options) {
21262
22061
 
21263
22062
  // src/expo/useChatStorage.ts
21264
22063
  import { useCallback as useCallback4, useEffect as useEffect4, useMemo, useRef as useRef4, useState as useState4 } from "react";
21265
- import { v7 as uuidv75 } from "uuid";
22064
+ import { v7 as uuidv76 } from "uuid";
21266
22065
 
21267
22066
  // src/lib/chat/assembleMessages.ts
21268
22067
  function assembleMessagesWithHistory(historyMessages, callerMessages, summarySystemMessage) {
@@ -21919,9 +22718,9 @@ async function decryptMediaFields(media, address, signMessage, embeddedWalletSig
21919
22718
  }
21920
22719
 
21921
22720
  // src/lib/db/media/types.ts
21922
- import { v7 as uuidv74 } from "uuid";
22721
+ import { v7 as uuidv75 } from "uuid";
21923
22722
  function generateMediaId() {
21924
- return `media_${uuidv74()}`;
22723
+ return `media_${uuidv75()}`;
21925
22724
  }
21926
22725
 
21927
22726
  // src/lib/db/media/operations.ts
@@ -22128,10 +22927,10 @@ function extractImageModelFromToolEvents(toolCallEvents) {
22128
22927
  }
22129
22928
  return void 0;
22130
22929
  }
22131
- function storedToLlmapiMessage(stored) {
22132
- const content = [{ type: "text", text: stored.content }];
22133
- if (stored.role !== "assistant" && stored.files?.length) {
22134
- for (const file of stored.files) {
22930
+ function storedToLlmapiMessage(stored2) {
22931
+ const content = [{ type: "text", text: stored2.content }];
22932
+ if (stored2.role !== "assistant" && stored2.files?.length) {
22933
+ for (const file of stored2.files) {
22135
22934
  if (isSendableImageURL(file.url)) {
22136
22935
  content.push({
22137
22936
  type: "image_url",
@@ -22141,11 +22940,11 @@ function storedToLlmapiMessage(stored) {
22141
22940
  }
22142
22941
  }
22143
22942
  const messages = [];
22144
- if (stored.role === "assistant" && stored.toolCallEvents?.length) {
22943
+ if (stored2.role === "assistant" && stored2.toolCallEvents?.length) {
22145
22944
  messages.push({
22146
- role: stored.role,
22945
+ role: stored2.role,
22147
22946
  content: void 0,
22148
- tool_calls: stored.toolCallEvents.map((event) => ({
22947
+ tool_calls: stored2.toolCallEvents.map((event) => ({
22149
22948
  id: event.id,
22150
22949
  type: "function",
22151
22950
  function: {
@@ -22154,7 +22953,7 @@ function storedToLlmapiMessage(stored) {
22154
22953
  }
22155
22954
  }))
22156
22955
  });
22157
- for (const event of stored.toolCallEvents) {
22956
+ for (const event of stored2.toolCallEvents) {
22158
22957
  if (event.id && event.output !== void 0 && event.output !== null) {
22159
22958
  messages.push({
22160
22959
  role: "tool",
@@ -22163,14 +22962,14 @@ function storedToLlmapiMessage(stored) {
22163
22962
  });
22164
22963
  }
22165
22964
  }
22166
- const postToolText = stored.content.replace(/!\[[^\]]*\]\(https?:\/\/[a-z0-9]+\.r2\.cloudflarestorage\.com\/[^)]+\)/g, "").replace(/https?:\/\/[a-z0-9]+\.r2\.cloudflarestorage\.com\/[^\s)]+/g, "").replace(/!\[[^\]]*\]\(https?:\/\/[^)\s]+\/api\/v1\/media\/[^/)\s]+\/[^)]+\)/g, "").replace(/https?:\/\/[^\s)]+\/api\/v1\/media\/[^/\s)]+\/[^\s)]+/g, "").replace(/\n{3,}/g, "\n\n").trim();
22965
+ const postToolText = stored2.content.replace(/!\[[^\]]*\]\(https?:\/\/[a-z0-9]+\.r2\.cloudflarestorage\.com\/[^)]+\)/g, "").replace(/https?:\/\/[a-z0-9]+\.r2\.cloudflarestorage\.com\/[^\s)]+/g, "").replace(/!\[[^\]]*\]\(https?:\/\/[^)\s]+\/api\/v1\/media\/[^/)\s]+\/[^)]+\)/g, "").replace(/https?:\/\/[^\s)]+\/api\/v1\/media\/[^/\s)]+\/[^\s)]+/g, "").replace(/\n{3,}/g, "\n\n").trim();
22167
22966
  messages.push({
22168
- role: stored.role,
22967
+ role: stored2.role,
22169
22968
  content: [{ type: "text", text: postToolText }]
22170
22969
  });
22171
22970
  } else {
22172
22971
  messages.push({
22173
- role: stored.role,
22972
+ role: stored2.role,
22174
22973
  content
22175
22974
  });
22176
22975
  }
@@ -22877,7 +23676,7 @@ function useChatStorage(options) {
22877
23676
  };
22878
23677
  };
22879
23678
  pendingResumeRef.current = null;
22880
- const effectiveAssistantUniqueId = assistantUniqueId ?? (resumable ? `msg_${uuidv75()}` : void 0);
23679
+ const effectiveAssistantUniqueId = assistantUniqueId ?? (resumable ? `msg_${uuidv76()}` : void 0);
22881
23680
  const embedToolText = (text12, mask, masked, token) => {
22882
23681
  const opts = {
22883
23682
  getToken: token,
@@ -23395,7 +24194,7 @@ function useChatStorage(options) {
23395
24194
  const detachedResult = result;
23396
24195
  if (detachedResult.detached) {
23397
24196
  recordToolSetTurn(database, convId, matchedToolSets);
23398
- const rowId = effectiveAssistantUniqueId ?? `msg_${uuidv75()}`;
24197
+ const rowId = effectiveAssistantUniqueId ?? `msg_${uuidv76()}`;
23399
24198
  pendingResumeRef.current = {
23400
24199
  handle: detachedResult.resume ?? null,
23401
24200
  convId,
@@ -23914,6 +24713,7 @@ export {
23914
24713
  QueueManager,
23915
24714
  RECALL_MAX_LIMIT,
23916
24715
  RECALL_TOOL_NAME,
24716
+ RemoteMemoryError,
23917
24717
  RerankerUnavailableError,
23918
24718
  SDK_SCHEMA_VERSION,
23919
24719
  SHORT_TTL_MS,
@@ -23977,6 +24777,8 @@ export {
23977
24777
  createNotionTools,
23978
24778
  createPlatformCursorStore,
23979
24779
  createRecallTool,
24780
+ createRemoteMemoryPersistence,
24781
+ createRemoteMemoryPipeline,
23980
24782
  createStockPricePreProcessor,
23981
24783
  createStreamingDeAnonymizer,
23982
24784
  createVaultEmbeddingCache,