@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.
@@ -1399,6 +1399,7 @@ __export(index_exports, {
1399
1399
  QueueManager: () => QueueManager,
1400
1400
  RECALL_MAX_LIMIT: () => RECALL_MAX_LIMIT,
1401
1401
  RECALL_TOOL_NAME: () => RECALL_TOOL_NAME,
1402
+ RemoteMemoryError: () => RemoteMemoryError,
1402
1403
  RerankerUnavailableError: () => RerankerUnavailableError,
1403
1404
  SDK_SCHEMA_VERSION: () => SDK_SCHEMA_VERSION,
1404
1405
  SHORT_TTL_MS: () => SHORT_TTL_MS,
@@ -1462,6 +1463,8 @@ __export(index_exports, {
1462
1463
  createNotionTools: () => createNotionTools,
1463
1464
  createPlatformCursorStore: () => createPlatformCursorStore,
1464
1465
  createRecallTool: () => createRecallTool,
1466
+ createRemoteMemoryPersistence: () => createRemoteMemoryPersistence,
1467
+ createRemoteMemoryPipeline: () => createRemoteMemoryPipeline,
1465
1468
  createStockPricePreProcessor: () => createStockPricePreProcessor,
1466
1469
  createStreamingDeAnonymizer: () => createStreamingDeAnonymizer,
1467
1470
  createVaultEmbeddingCache: () => createVaultEmbeddingCache,
@@ -4177,13 +4180,13 @@ async function searchChunksOp(ctx, queryVector, options) {
4177
4180
  const storedById = new Map(
4178
4181
  await Promise.all(
4179
4182
  Array.from(uniqueMessages, async ([id, m]) => {
4180
- const stored = await messageRawToStored(
4183
+ const stored2 = await messageRawToStored(
4181
4184
  m,
4182
4185
  ctx.walletAddress,
4183
4186
  ctx.signMessage,
4184
4187
  ctx.embeddedWalletSigner
4185
4188
  );
4186
- return [id, stored];
4189
+ return [id, stored2];
4187
4190
  })
4188
4191
  )
4189
4192
  );
@@ -4201,18 +4204,18 @@ async function searchChunksOp(ctx, queryVector, options) {
4201
4204
  })
4202
4205
  );
4203
4206
  return topK.map(({ message, similarity, chunkTextSource }) => {
4204
- const stored = { ...storedById.get(message.id) };
4207
+ const stored2 = { ...storedById.get(message.id) };
4205
4208
  let chunkText2;
4206
4209
  if (chunkTextSource.kind === "chunk") {
4207
- chunkText2 = resolveChunkText(stored.content, chunkTextSource.chunk, chunkTextSource.siblings);
4210
+ chunkText2 = resolveChunkText(stored2.content, chunkTextSource.chunk, chunkTextSource.siblings);
4208
4211
  } else if (chunkTextSource.kind === "chunk-cached") {
4209
4212
  const state = chunkStateByMsgId.get(message.id);
4210
4213
  const chunk = state && state.version === chunkTextSource.version ? state.chunks[chunkTextSource.chunkIndex] : void 0;
4211
- chunkText2 = resolveChunkText(stored.content, chunk, state?.chunks);
4214
+ chunkText2 = resolveChunkText(stored2.content, chunk, state?.chunks);
4212
4215
  } else {
4213
- chunkText2 = stored.content;
4216
+ chunkText2 = stored2.content;
4214
4217
  }
4215
- return { chunkText: chunkText2, message: stored, similarity };
4218
+ return { chunkText: chunkText2, message: stored2, similarity };
4216
4219
  });
4217
4220
  }
4218
4221
  function makeSyntheticStoredMessage(opts) {
@@ -5336,7 +5339,7 @@ async function embedOne(text12, options, outer) {
5336
5339
  }
5337
5340
  var DEFAULT_EMBEDDING_BATCH_SIZE = 100;
5338
5341
  var DEFAULT_EMBEDDING_BATCH_CONCURRENCY = 3;
5339
- async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage, maskInput, timeoutMs) {
5342
+ async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage, maskInput, timeoutMs, outer) {
5340
5343
  const response = await withEmbeddingRetry(
5341
5344
  () => withDeadline(
5342
5345
  (signal) => postApiV1Embeddings({
@@ -5346,8 +5349,10 @@ async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage,
5346
5349
  ...signal && { signal }
5347
5350
  }),
5348
5351
  timeoutMs,
5349
- "embedding batch request"
5350
- )
5352
+ "embedding batch request",
5353
+ outer
5354
+ ),
5355
+ outer
5351
5356
  );
5352
5357
  if (response.error) {
5353
5358
  throw embeddingErrorFrom(response);
@@ -5365,6 +5370,11 @@ async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage,
5365
5370
  }
5366
5371
  async function generateEmbeddings(texts, options) {
5367
5372
  if (texts.length === 0) return [];
5373
+ const total = options.totalTimeoutMs;
5374
+ if (total === void 0) return embedMany(texts, options, void 0);
5375
+ return withDeadline((signal) => embedMany(texts, options, signal), total, "embedding batch");
5376
+ }
5377
+ async function embedMany(texts, options, outer) {
5368
5378
  const { baseUrl = BASE_URL, model, batchSize, cache } = options;
5369
5379
  const timeoutMs = options.timeoutMs ?? DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS;
5370
5380
  const chunkSize = batchSize ?? DEFAULT_EMBEDDING_BATCH_SIZE;
@@ -5385,7 +5395,8 @@ async function generateEmbeddings(texts, options) {
5385
5395
  if (uncachedTexts.length === 0) {
5386
5396
  return results;
5387
5397
  }
5388
- const headers = await resolveAuthHeaders(options);
5398
+ const headers = await resolveAuthHeaders(options, outer);
5399
+ if (outer?.aborted) throw outer.reason;
5389
5400
  const embeddingModel = model ?? DEFAULT_API_EMBEDDING_MODEL;
5390
5401
  let newEmbeddings;
5391
5402
  if (uncachedTexts.length <= chunkSize) {
@@ -5396,7 +5407,8 @@ async function generateEmbeddings(texts, options) {
5396
5407
  embeddingModel,
5397
5408
  options.onUsage,
5398
5409
  options.maskInput,
5399
- timeoutMs
5410
+ timeoutMs,
5411
+ outer
5400
5412
  );
5401
5413
  } else {
5402
5414
  const chunks = [];
@@ -5407,6 +5419,7 @@ async function generateEmbeddings(texts, options) {
5407
5419
  let nextIndex = 0;
5408
5420
  const worker = async () => {
5409
5421
  while (nextIndex < chunks.length) {
5422
+ if (outer?.aborted) throw outer.reason;
5410
5423
  const idx = nextIndex++;
5411
5424
  allEmbeddings[idx] = await generateEmbeddingsBatch(
5412
5425
  chunks[idx],
@@ -5415,7 +5428,8 @@ async function generateEmbeddings(texts, options) {
5415
5428
  embeddingModel,
5416
5429
  options.onUsage,
5417
5430
  options.maskInput,
5418
- timeoutMs
5431
+ timeoutMs,
5432
+ outer
5419
5433
  );
5420
5434
  }
5421
5435
  };
@@ -5426,6 +5440,7 @@ async function generateEmbeddings(texts, options) {
5426
5440
  await Promise.all(workers);
5427
5441
  newEmbeddings = allEmbeddings.flat();
5428
5442
  }
5443
+ if (outer?.aborted) throw outer.reason;
5429
5444
  for (let i = 0; i < uncachedIndices.length; i++) {
5430
5445
  const f32Embedding = Float32Array.from(newEmbeddings[i]);
5431
5446
  results[uncachedIndices[i]] = Array.from(f32Embedding);
@@ -10514,15 +10529,15 @@ function createSummaryContext(database) {
10514
10529
  summariesCollection: database.get("conversation_summaries")
10515
10530
  };
10516
10531
  }
10517
- function modelToStored(record) {
10532
+ function modelToStored(record2) {
10518
10533
  return {
10519
- uniqueId: record.id,
10520
- conversationId: record.conversationId,
10521
- summary: record.summary,
10522
- summarizedUpTo: record.summarizedUpTo,
10523
- tokenCount: record.tokenCount,
10524
- createdAt: record.createdAt,
10525
- updatedAt: record.updatedAt
10534
+ uniqueId: record2.id,
10535
+ conversationId: record2.conversationId,
10536
+ summary: record2.summary,
10537
+ summarizedUpTo: record2.summarizedUpTo,
10538
+ tokenCount: record2.tokenCount,
10539
+ createdAt: record2.createdAt,
10540
+ updatedAt: record2.updatedAt
10526
10541
  };
10527
10542
  }
10528
10543
  async function getConversationSummaryOp(ctx, conversationId) {
@@ -10531,17 +10546,17 @@ async function getConversationSummaryOp(ctx, conversationId) {
10531
10546
  return modelToStored(results[0]);
10532
10547
  }
10533
10548
  async function upsertConversationSummaryOp(ctx, conversationId, summary, summarizedUpTo, tokenCount) {
10534
- let record;
10549
+ let record2;
10535
10550
  await ctx.database.write(async () => {
10536
10551
  const existing = await ctx.summariesCollection.query(import_watermelondb5.Q.where("conversation_id", conversationId)).fetch();
10537
10552
  if (existing.length > 0) {
10538
- record = await existing[0].update((rec) => {
10553
+ record2 = await existing[0].update((rec) => {
10539
10554
  rec.summary = summary;
10540
10555
  rec.summarizedUpTo = summarizedUpTo;
10541
10556
  rec.tokenCount = tokenCount;
10542
10557
  });
10543
10558
  } else {
10544
- record = await ctx.summariesCollection.create((rec) => {
10559
+ record2 = await ctx.summariesCollection.create((rec) => {
10545
10560
  rec.conversationId = conversationId;
10546
10561
  rec.summary = summary;
10547
10562
  rec.summarizedUpTo = summarizedUpTo;
@@ -10549,13 +10564,13 @@ async function upsertConversationSummaryOp(ctx, conversationId, summary, summari
10549
10564
  });
10550
10565
  }
10551
10566
  });
10552
- return modelToStored(record);
10567
+ return modelToStored(record2);
10553
10568
  }
10554
10569
  async function deleteConversationSummaryOp(ctx, conversationId) {
10555
10570
  await ctx.database.write(async () => {
10556
10571
  const existing = await ctx.summariesCollection.query(import_watermelondb5.Q.where("conversation_id", conversationId)).fetch();
10557
- for (const record of existing) {
10558
- await record.destroyPermanently();
10572
+ for (const record2 of existing) {
10573
+ await record2.destroyPermanently();
10559
10574
  }
10560
10575
  });
10561
10576
  }
@@ -12056,25 +12071,25 @@ async function upsertEntitiesInWrite(ctx, entities) {
12056
12071
  const kindBackfills = existing.filter((e) => {
12057
12072
  const incoming = kindByName.get(e.canonicalName);
12058
12073
  return incoming !== void 0 && (e.kind === null || e.kind === void 0 || e.kind === "");
12059
- }).map((record) => ({ record, kind: kindByName.get(record.canonicalName) }));
12074
+ }).map((record2) => ({ record: record2, kind: kindByName.get(record2.canonicalName) }));
12060
12075
  const missing = unique.filter((n) => !existingNames.has(n));
12061
12076
  const created = missing.map(
12062
- (name) => ctx.entityCollection.prepareCreate((record) => {
12063
- record._setRaw("canonical_name", name);
12077
+ (name) => ctx.entityCollection.prepareCreate((record2) => {
12078
+ record2._setRaw("canonical_name", name);
12064
12079
  const kind = kindByName.get(name);
12065
- if (kind !== void 0) record._setRaw("kind", kind);
12080
+ if (kind !== void 0) record2._setRaw("kind", kind);
12066
12081
  })
12067
12082
  );
12068
12083
  for (const e of existing) out.set(e.canonicalName, entityToStored(e));
12069
- for (const record of created) out.set(record.canonicalName, entityToStored(record));
12070
- for (const { record, kind } of kindBackfills) {
12071
- out.set(record.canonicalName, { ...entityToStored(record), kind });
12084
+ for (const record2 of created) out.set(record2.canonicalName, entityToStored(record2));
12085
+ for (const { record: record2, kind } of kindBackfills) {
12086
+ out.set(record2.canonicalName, { ...entityToStored(record2), kind });
12072
12087
  }
12073
12088
  return { entities: out, operations: created, kindBackfills };
12074
12089
  }
12075
12090
  function prepareKindBackfills(backfills) {
12076
12091
  return backfills.map(
12077
- ({ record, kind }) => record.prepareUpdate((r) => {
12092
+ ({ record: record2, kind }) => record2.prepareUpdate((r) => {
12078
12093
  r._setRaw("kind", kind);
12079
12094
  })
12080
12095
  );
@@ -12105,10 +12120,10 @@ function displayNamesOf(entities) {
12105
12120
  }
12106
12121
  return out;
12107
12122
  }
12108
- function topicsEqual(stored, computed) {
12109
- if (stored === null || stored.length !== computed.length) return false;
12123
+ function topicsEqual(stored2, computed) {
12124
+ if (stored2 === null || stored2.length !== computed.length) return false;
12110
12125
  const key = (t) => JSON.stringify([t.name, t.kind ?? null, t.source]);
12111
- const storedKeys = stored.map(key).sort();
12126
+ const storedKeys = stored2.map(key).sort();
12112
12127
  const computedKeys = computed.map(key).sort();
12113
12128
  return storedKeys.every((k, i) => k === computedKeys[i]);
12114
12129
  }
@@ -12174,10 +12189,10 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
12174
12189
  return;
12175
12190
  }
12176
12191
  const linkOps = toCreate.map(
12177
- (e) => ctx.memoryEntityCollection.prepareCreate((record) => {
12178
- record._setRaw("memory_id", memoryId);
12179
- record._setRaw("entity_id", e.uniqueId);
12180
- if (userId !== void 0) record._setRaw("user_id", userId);
12192
+ (e) => ctx.memoryEntityCollection.prepareCreate((record2) => {
12193
+ record2._setRaw("memory_id", memoryId);
12194
+ record2._setRaw("entity_id", e.uniqueId);
12195
+ if (userId !== void 0) record2._setRaw("user_id", userId);
12181
12196
  })
12182
12197
  );
12183
12198
  await ctx.database.batch(
@@ -12245,10 +12260,10 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
12245
12260
  ...entityOps,
12246
12261
  ...prepareKindBackfills(kindBackfills),
12247
12262
  ...toCreate.map(
12248
- (e) => ctx.memoryEntityCollection.prepareCreate((record) => {
12249
- record._setRaw("memory_id", memoryId);
12250
- record._setRaw("entity_id", e.uniqueId);
12251
- if (userId !== void 0) record._setRaw("user_id", userId);
12263
+ (e) => ctx.memoryEntityCollection.prepareCreate((record2) => {
12264
+ record2._setRaw("memory_id", memoryId);
12265
+ record2._setRaw("entity_id", e.uniqueId);
12266
+ if (userId !== void 0) record2._setRaw("user_id", userId);
12252
12267
  })
12253
12268
  ),
12254
12269
  ...toDestroy.map((l) => l.prepareDestroyPermanently()),
@@ -12402,8 +12417,8 @@ function visibilityConditions(requested) {
12402
12417
  if (excluded.length === 0) return [];
12403
12418
  return [import_watermelondb20.Q.or(import_watermelondb20.Q.where("visibility", null), import_watermelondb20.Q.where("visibility", import_watermelondb20.Q.notIn(excluded)))];
12404
12419
  }
12405
- function isOwnedByCtxUser(ctx, record) {
12406
- return ctx.userId === void 0 || record.userId === ctx.userId;
12420
+ function isOwnedByCtxUser(ctx, record2) {
12421
+ return ctx.userId === void 0 || record2.userId === ctx.userId;
12407
12422
  }
12408
12423
  function baseVaultConditions(ctx, options) {
12409
12424
  return [
@@ -12483,39 +12498,39 @@ async function vaultMemoryToStored(memory, walletAddress, signMessage, embeddedW
12483
12498
  }
12484
12499
  return raw;
12485
12500
  }
12486
- function populateNewVaultMemory(record, ctx, opts, encryptedContent) {
12487
- record._setRaw("content", encryptedContent);
12488
- record._setRaw("scope", opts.scope ?? "private");
12489
- record._setRaw("folder_id", opts.folderId ?? null);
12490
- record._setRaw("user_id", ctx.userId ?? null);
12491
- record._setRaw("is_deleted", false);
12501
+ function populateNewVaultMemory(record2, ctx, opts, encryptedContent) {
12502
+ record2._setRaw("content", encryptedContent);
12503
+ record2._setRaw("scope", opts.scope ?? "private");
12504
+ record2._setRaw("folder_id", opts.folderId ?? null);
12505
+ record2._setRaw("user_id", ctx.userId ?? null);
12506
+ record2._setRaw("is_deleted", false);
12492
12507
  if (opts.embedding !== void 0) {
12493
- record._setRaw("embedding", opts.embedding);
12494
- record._setRaw("embedding_model", opts.embeddingModel ?? null);
12508
+ record2._setRaw("embedding", opts.embedding);
12509
+ record2._setRaw("embedding_model", opts.embeddingModel ?? null);
12495
12510
  }
12496
12511
  if (opts.sourceChunkIds !== void 0) {
12497
- record._setRaw("source_chunk_ids", JSON.stringify(opts.sourceChunkIds));
12512
+ record2._setRaw("source_chunk_ids", JSON.stringify(opts.sourceChunkIds));
12498
12513
  }
12499
- record._setRaw("proof_count", opts.proofCount ?? 1);
12500
- record._setRaw("source", opts.source ?? "manual");
12514
+ record2._setRaw("proof_count", opts.proofCount ?? 1);
12515
+ record2._setRaw("source", opts.source ?? "manual");
12501
12516
  if (opts.eventTime) {
12502
- record._setRaw("event_time_start", opts.eventTime.start ?? null);
12503
- record._setRaw("event_time_end", opts.eventTime.end ?? null);
12504
- record._setRaw("event_time_kind", opts.eventTime.kind ?? null);
12517
+ record2._setRaw("event_time_start", opts.eventTime.start ?? null);
12518
+ record2._setRaw("event_time_end", opts.eventTime.end ?? null);
12519
+ record2._setRaw("event_time_kind", opts.eventTime.kind ?? null);
12505
12520
  }
12506
12521
  if (opts.factType !== void 0) {
12507
- record._setRaw("fact_type", opts.factType);
12522
+ record2._setRaw("fact_type", opts.factType);
12508
12523
  }
12509
12524
  if (opts.trustTier !== void 0) {
12510
- record._setRaw("trust_tier", normalizeTrustTier(opts.trustTier));
12525
+ record2._setRaw("trust_tier", normalizeTrustTier(opts.trustTier));
12511
12526
  }
12512
- record._setRaw("visibility", opts.visibility ?? "private");
12513
- record._setRaw(
12527
+ record2._setRaw("visibility", opts.visibility ?? "private");
12528
+ record2._setRaw(
12514
12529
  "published_at",
12515
12530
  opts.visibility && opts.visibility !== "private" ? opts.publishedAt ?? Date.now() : null
12516
12531
  );
12517
12532
  if (opts.geohash !== void 0) {
12518
- record._setRaw("geohash", opts.geohash);
12533
+ record2._setRaw("geohash", opts.geohash);
12519
12534
  }
12520
12535
  }
12521
12536
  async function createVaultMemoryOp(ctx, opts) {
@@ -12529,7 +12544,7 @@ async function createVaultMemoryOp(ctx, opts) {
12529
12544
  if (ctx.canWrite && !await ctx.canWrite())
12530
12545
  throw new Error("Memory source is no longer eligible");
12531
12546
  return ctx.vaultMemoryCollection.create(
12532
- (record) => populateNewVaultMemory(record, ctx, opts, encryptedContent)
12547
+ (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent)
12533
12548
  );
12534
12549
  });
12535
12550
  return vaultMemoryToStored(created, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
@@ -12554,7 +12569,7 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
12554
12569
  }
12555
12570
  if (target.isDeleted || target.supersededBy || !isOwnedByCtxUser(ctx, target)) return;
12556
12571
  createdRecord = await ctx.vaultMemoryCollection.create(
12557
- (record) => populateNewVaultMemory(record, ctx, opts, encryptedContent)
12572
+ (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent)
12558
12573
  );
12559
12574
  await target.update((r) => {
12560
12575
  r._setRaw("superseded_by", createdRecord.id);
@@ -12636,7 +12651,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
12636
12651
  throw new Error("Memory source is no longer eligible");
12637
12652
  const prepared = optionsArray.map(
12638
12653
  (opts, i) => ctx.vaultMemoryCollection.prepareCreate(
12639
- (record) => populateNewVaultMemory(record, ctx, opts, encryptedContents[i])
12654
+ (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i])
12640
12655
  )
12641
12656
  );
12642
12657
  await ctx.database.batch(...prepared);
@@ -12644,16 +12659,16 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
12644
12659
  });
12645
12660
  return Promise.all(
12646
12661
  created.map(
12647
- (record) => vaultMemoryToStored(record, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
12662
+ (record2) => vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
12648
12663
  )
12649
12664
  );
12650
12665
  }
12651
12666
  async function getVaultMemoryOp(ctx, id) {
12652
12667
  try {
12653
- const record = await ctx.vaultMemoryCollection.find(id);
12654
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return null;
12668
+ const record2 = await ctx.vaultMemoryCollection.find(id);
12669
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
12655
12670
  return vaultMemoryToStored(
12656
- record,
12671
+ record2,
12657
12672
  ctx.walletAddress,
12658
12673
  ctx.signMessage,
12659
12674
  ctx.embeddedWalletSigner
@@ -12711,11 +12726,11 @@ function vaultMemoryRawToStoredRaw(raw) {
12711
12726
  };
12712
12727
  }
12713
12728
  async function vaultMemoryRawToStored(raw, walletAddress, signMessage, embeddedWalletSigner) {
12714
- const stored = vaultMemoryRawToStoredRaw(raw);
12729
+ const stored2 = vaultMemoryRawToStoredRaw(raw);
12715
12730
  if (walletAddress) {
12716
- return decryptVaultMemoryFields(stored, walletAddress, signMessage, embeddedWalletSigner);
12731
+ return decryptVaultMemoryFields(stored2, walletAddress, signMessage, embeddedWalletSigner);
12717
12732
  }
12718
- return stored;
12733
+ return stored2;
12719
12734
  }
12720
12735
  async function getAllVaultMemoriesOp(ctx, options) {
12721
12736
  const conditions = [
@@ -12867,13 +12882,13 @@ async function getVaultMemoriesByIdsOp(ctx, ids, options) {
12867
12882
  async function getAllVaultMemoryContentsOp(ctx, options) {
12868
12883
  const results = await ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx, options)).unsafeFetchRaw();
12869
12884
  return mapInBatches(results, async (raw) => {
12870
- const stored = await vaultMemoryRawToStored(
12885
+ const stored2 = await vaultMemoryRawToStored(
12871
12886
  raw,
12872
12887
  ctx.walletAddress,
12873
12888
  ctx.signMessage,
12874
12889
  ctx.embeddedWalletSigner
12875
12890
  );
12876
- return stored.content;
12891
+ return stored2.content;
12877
12892
  });
12878
12893
  }
12879
12894
  async function countActiveVaultMemoriesOp(ctx) {
@@ -12895,12 +12910,12 @@ async function updateVaultMemoryOp(ctx, id, opts) {
12895
12910
  ctx.embeddedWalletSigner
12896
12911
  ) : opts.content;
12897
12912
  let stale = false;
12898
- const record = probe;
12899
- const originalUpdatedAt = record.updatedAt.getTime();
12913
+ const record2 = probe;
12914
+ const originalUpdatedAt = record2.updatedAt.getTime();
12900
12915
  await ctx.database.write(async () => {
12901
12916
  if (ctx.canWrite && !await ctx.canWrite())
12902
12917
  throw new Error("Memory source is no longer eligible");
12903
- if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record)) {
12918
+ if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
12904
12919
  stale = true;
12905
12920
  return;
12906
12921
  }
@@ -12908,14 +12923,14 @@ async function updateVaultMemoryOp(ctx, id, opts) {
12908
12923
  let replayedObservation = false;
12909
12924
  if (opts.observationSourceIds?.length) {
12910
12925
  try {
12911
- const parsed = JSON.parse(record.sourceChunkIds ?? "[]");
12926
+ const parsed = JSON.parse(record2.sourceChunkIds ?? "[]");
12912
12927
  if (Array.isArray(parsed))
12913
12928
  observedSources = parsed.filter((id2) => typeof id2 === "string");
12914
12929
  } catch {
12915
12930
  }
12916
12931
  replayedObservation = opts.observationSourceIds.every((id2) => observedSources.includes(id2));
12917
12932
  }
12918
- await record.update((r) => {
12933
+ await record2.update((r) => {
12919
12934
  r._setRaw("content", encryptedContent);
12920
12935
  if (opts.scope !== void 0) {
12921
12936
  r._setRaw("scope", opts.scope);
@@ -12972,7 +12987,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
12972
12987
  });
12973
12988
  if (stale) return null;
12974
12989
  return vaultMemoryToStored(
12975
- record,
12990
+ record2,
12976
12991
  ctx.walletAddress,
12977
12992
  ctx.signMessage,
12978
12993
  ctx.embeddedWalletSigner
@@ -12986,21 +13001,21 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
12986
13001
  if (!entityCtx) {
12987
13002
  throw new Error("setMemoryEntitiesOp requires ctx.entityCtx (entity collections)");
12988
13003
  }
12989
- let record;
13004
+ let record2;
12990
13005
  try {
12991
- record = await ctx.vaultMemoryCollection.find(memoryId);
13006
+ record2 = await ctx.vaultMemoryCollection.find(memoryId);
12992
13007
  } catch {
12993
13008
  return null;
12994
13009
  }
12995
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return null;
13010
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
12996
13011
  let stale = false;
12997
- const originalUpdatedAt = record.updatedAt.getTime();
13012
+ const originalUpdatedAt = record2.updatedAt.getTime();
12998
13013
  await ctx.database.write(async (writer) => {
12999
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
13014
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
13000
13015
  stale = true;
13001
13016
  return;
13002
13017
  }
13003
- await record.update((r) => {
13018
+ await record2.update((r) => {
13004
13019
  r._setRaw("topics_user_managed", true);
13005
13020
  r._setRaw("updated_at", originalUpdatedAt);
13006
13021
  });
@@ -13024,25 +13039,25 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
13024
13039
  );
13025
13040
  });
13026
13041
  if (stale) return null;
13027
- return vaultMemoryToStored(record, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
13042
+ return vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
13028
13043
  }
13029
13044
  async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
13030
- let record;
13045
+ let record2;
13031
13046
  try {
13032
- record = await ctx.vaultMemoryCollection.find(memoryId);
13047
+ record2 = await ctx.vaultMemoryCollection.find(memoryId);
13033
13048
  } catch {
13034
13049
  return false;
13035
13050
  }
13036
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
13037
- const originalUpdatedAt = record.updatedAt.getTime();
13051
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
13052
+ const originalUpdatedAt = record2.updatedAt.getTime();
13038
13053
  let cleared = false;
13039
13054
  await ctx.database.write(async () => {
13040
- if (options?.unlessTopicsRecorded && parseTopics(record.topics) !== null) return;
13055
+ if (options?.unlessTopicsRecorded && parseTopics(record2.topics) !== null) return;
13041
13056
  cleared = true;
13042
- await record.update((r) => {
13057
+ await record2.update((r) => {
13043
13058
  r._setRaw("topics_user_managed", false);
13044
13059
  r._setRaw("topics_extracted_version", null);
13045
- if (record.topicsExtractedAt === null) {
13060
+ if (record2.topicsExtractedAt === null) {
13046
13061
  r._setRaw("topics_extracted_at", originalUpdatedAt);
13047
13062
  }
13048
13063
  r._setRaw("updated_at", originalUpdatedAt);
@@ -13051,22 +13066,22 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
13051
13066
  return cleared;
13052
13067
  }
13053
13068
  async function setMemoryVisibilityOp(ctx, id, opts) {
13054
- let record;
13069
+ let record2;
13055
13070
  try {
13056
- record = await ctx.vaultMemoryCollection.find(id);
13071
+ record2 = await ctx.vaultMemoryCollection.find(id);
13057
13072
  } catch {
13058
13073
  return null;
13059
13074
  }
13060
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return null;
13075
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return null;
13061
13076
  let stale = false;
13062
13077
  await ctx.database.write(async () => {
13063
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
13078
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
13064
13079
  stale = true;
13065
13080
  return;
13066
13081
  }
13067
- const currentUpdatedAt = record.updatedAt.getTime();
13068
- const currentPublishedAt = record.publishedAt ?? null;
13069
- await record.update((r) => {
13082
+ const currentUpdatedAt = record2.updatedAt.getTime();
13083
+ const currentPublishedAt = record2.publishedAt ?? null;
13084
+ await record2.update((r) => {
13070
13085
  r._setRaw("visibility", opts.visibility);
13071
13086
  if (opts.visibility === "private") {
13072
13087
  r._setRaw("published_at", null);
@@ -13080,19 +13095,19 @@ async function setMemoryVisibilityOp(ctx, id, opts) {
13080
13095
  });
13081
13096
  });
13082
13097
  if (stale) return null;
13083
- return vaultMemoryToStored(record, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
13098
+ return vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
13084
13099
  }
13085
13100
  async function deleteVaultMemoryOp(ctx, id) {
13086
13101
  try {
13087
- const record = await ctx.vaultMemoryCollection.find(id);
13088
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
13102
+ const record2 = await ctx.vaultMemoryCollection.find(id);
13103
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
13089
13104
  let stale = false;
13090
13105
  await ctx.database.write(async () => {
13091
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
13106
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
13092
13107
  stale = true;
13093
13108
  return;
13094
13109
  }
13095
- await record.update((r) => {
13110
+ await record2.update((r) => {
13096
13111
  r._setRaw("is_deleted", true);
13097
13112
  });
13098
13113
  });
@@ -13111,8 +13126,8 @@ async function deleteVaultMemoryOp(ctx, id) {
13111
13126
  async function supersedeVaultMemoryOp(ctx, id, supersededById) {
13112
13127
  if (id === supersededById) return false;
13113
13128
  try {
13114
- const record = await ctx.vaultMemoryCollection.find(id);
13115
- if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record)) return false;
13129
+ const record2 = await ctx.vaultMemoryCollection.find(id);
13130
+ if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) return false;
13116
13131
  let successor;
13117
13132
  try {
13118
13133
  successor = await ctx.vaultMemoryCollection.find(supersededById);
@@ -13126,7 +13141,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
13126
13141
  await ctx.database.write(async () => {
13127
13142
  if (ctx.canWrite && !await ctx.canWrite())
13128
13143
  throw new Error("Memory source is no longer eligible");
13129
- if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record)) {
13144
+ if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
13130
13145
  stale = true;
13131
13146
  return;
13132
13147
  }
@@ -13134,7 +13149,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
13134
13149
  stale = true;
13135
13150
  return;
13136
13151
  }
13137
- await record.update((r) => {
13152
+ await record2.update((r) => {
13138
13153
  r._setRaw("superseded_by", supersededById);
13139
13154
  r._setRaw("superseded_at", Date.now());
13140
13155
  });
@@ -13153,7 +13168,7 @@ async function getUnfiledVaultMemoriesOp(ctx) {
13153
13168
  const results = await ctx.vaultMemoryCollection.query(...conditions).fetch();
13154
13169
  return mapInBatches(
13155
13170
  results,
13156
- (record) => vaultMemoryToStored(record, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
13171
+ (record2) => vaultMemoryToStored(record2, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
13157
13172
  );
13158
13173
  }
13159
13174
  var TOPICS_EXTRACTION_VERSION = 3;
@@ -13295,17 +13310,17 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
13295
13310
  }
13296
13311
  }
13297
13312
  const eligible = records.filter(
13298
- (record) => !record.isDeleted && isOwnedByCtxUser(ctx, record) && !record.topicsUserManaged
13313
+ (record2) => !record2.isDeleted && isOwnedByCtxUser(ctx, record2) && !record2.topicsUserManaged
13299
13314
  );
13300
- const prepared = eligible.map((record) => {
13301
- const originalUpdatedAt = record.updatedAt.getTime();
13302
- return record.prepareUpdate((r) => {
13315
+ const prepared = eligible.map((record2) => {
13316
+ const originalUpdatedAt = record2.updatedAt.getTime();
13317
+ return record2.prepareUpdate((r) => {
13303
13318
  r._setRaw("topics_extracted_at", extractedAt);
13304
13319
  r._setRaw("topics_extracted_version", version);
13305
13320
  r._setRaw("updated_at", originalUpdatedAt);
13306
13321
  });
13307
13322
  });
13308
- for (const record of eligible) stamped.push(record.id);
13323
+ for (const record2 of eligible) stamped.push(record2.id);
13309
13324
  if (prepared.length > 0) await ctx.database.batch(...prepared);
13310
13325
  });
13311
13326
  }
@@ -13320,14 +13335,14 @@ async function relinkMemoryTopicsOp(ctx, memoryIds) {
13320
13335
  for (const id of Array.from(new Set(memoryIds))) {
13321
13336
  try {
13322
13337
  await ctx.database.write(async (writer) => {
13323
- let record;
13338
+ let record2;
13324
13339
  try {
13325
- record = await ctx.vaultMemoryCollection.find(id);
13340
+ record2 = await ctx.vaultMemoryCollection.find(id);
13326
13341
  } catch {
13327
13342
  return;
13328
13343
  }
13329
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return;
13330
- const topics = parseTopics(record.topics);
13344
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return;
13345
+ const topics = parseTopics(record2.topics);
13331
13346
  if (topics === null) return;
13332
13347
  await writer.callWriter(() => relinkMemoryEntitiesFromTopicsOp(entityCtx, id, topics));
13333
13348
  relinked.push(id);
@@ -13352,20 +13367,20 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
13352
13367
  await ctx.database.write(async () => {
13353
13368
  const writes = [];
13354
13369
  for (const id of chunkIds) {
13355
- let record;
13370
+ let record2;
13356
13371
  try {
13357
- record = await ctx.vaultMemoryCollection.find(id);
13372
+ record2 = await ctx.vaultMemoryCollection.find(id);
13358
13373
  } catch {
13359
13374
  continue;
13360
13375
  }
13361
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) continue;
13362
- if (parseTopics(record.topics) !== null) continue;
13376
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) continue;
13377
+ if (parseTopics(record2.topics) !== null) continue;
13363
13378
  const links = await entityCtx.memoryEntityCollection.query(import_watermelondb20.Q.where("memory_id", id)).unsafeFetchRaw();
13364
13379
  const entityIds = links.map((l) => String(l.entity_id));
13365
13380
  if (entityIds.length === 0) continue;
13366
13381
  const entities = await entityCtx.entityCollection.query(import_watermelondb20.Q.where("id", import_watermelondb20.Q.oneOf(entityIds))).fetch();
13367
13382
  if (entities.length === 0) continue;
13368
- const source = record.topicsUserManaged ? "user" : "auto";
13383
+ const source = record2.topicsUserManaged ? "user" : "auto";
13369
13384
  const write = await resolveMemoryTopicsWrite(entityCtx, id, entities, [], source);
13370
13385
  if (write) writes.push(write);
13371
13386
  }
@@ -13383,7 +13398,7 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
13383
13398
  if (records.length === 0) return 0;
13384
13399
  await ctx.database.write(async () => {
13385
13400
  const prepared = records.map(
13386
- (record) => record.prepareUpdate((r) => {
13401
+ (record2) => record2.prepareUpdate((r) => {
13387
13402
  r._setRaw("is_deleted", true);
13388
13403
  })
13389
13404
  );
@@ -13428,20 +13443,20 @@ async function getDecayCandidatesRawOp(ctx) {
13428
13443
  }
13429
13444
  async function archiveVaultMemoryOp(ctx, id, opts) {
13430
13445
  try {
13431
- const record = await ctx.vaultMemoryCollection.find(id);
13432
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
13446
+ const record2 = await ctx.vaultMemoryCollection.find(id);
13447
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
13433
13448
  let stale = false;
13434
13449
  const archivedAtValue = opts?.now ?? Date.now();
13435
13450
  await ctx.database.write(async () => {
13436
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record) || record.archivedAt !== null) {
13451
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || record2.archivedAt !== null) {
13437
13452
  stale = true;
13438
13453
  return;
13439
13454
  }
13440
- if (opts?.expectedUpdatedAt !== void 0 && record.updatedAt.getTime() !== opts.expectedUpdatedAt || opts?.expectedLastObservedAt !== void 0 && (record.lastObservedAt ?? null) !== opts.expectedLastObservedAt) {
13455
+ if (opts?.expectedUpdatedAt !== void 0 && record2.updatedAt.getTime() !== opts.expectedUpdatedAt || opts?.expectedLastObservedAt !== void 0 && (record2.lastObservedAt ?? null) !== opts.expectedLastObservedAt) {
13441
13456
  stale = true;
13442
13457
  return;
13443
13458
  }
13444
- await record.update((r) => {
13459
+ await record2.update((r) => {
13445
13460
  r._setRaw("archived_at", archivedAtValue);
13446
13461
  });
13447
13462
  });
@@ -13452,15 +13467,15 @@ async function archiveVaultMemoryOp(ctx, id, opts) {
13452
13467
  }
13453
13468
  async function restoreVaultMemoryOp(ctx, id) {
13454
13469
  try {
13455
- const record = await ctx.vaultMemoryCollection.find(id);
13456
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
13470
+ const record2 = await ctx.vaultMemoryCollection.find(id);
13471
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
13457
13472
  let stale = false;
13458
13473
  await ctx.database.write(async () => {
13459
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
13474
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) {
13460
13475
  stale = true;
13461
13476
  return;
13462
13477
  }
13463
- await record.update((r) => {
13478
+ await record2.update((r) => {
13464
13479
  r._setRaw("archived_at", null);
13465
13480
  });
13466
13481
  });
@@ -13471,17 +13486,17 @@ async function restoreVaultMemoryOp(ctx, id) {
13471
13486
  }
13472
13487
  async function hardDeleteDecayedOp(ctx, id, opts) {
13473
13488
  try {
13474
- const record = await ctx.vaultMemoryCollection.find(id);
13475
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
13489
+ const record2 = await ctx.vaultMemoryCollection.find(id);
13490
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
13476
13491
  const now = opts.now ?? Date.now();
13477
13492
  let stale = false;
13478
13493
  await ctx.database.write(async () => {
13479
- const archivedAt = record.archivedAt;
13480
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
13494
+ const archivedAt = record2.archivedAt;
13495
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
13481
13496
  stale = true;
13482
13497
  return;
13483
13498
  }
13484
- await record.update((r) => {
13499
+ await record2.update((r) => {
13485
13500
  r._setRaw("is_deleted", true);
13486
13501
  });
13487
13502
  });
@@ -13499,14 +13514,14 @@ async function hardDeleteDecayedOp(ctx, id, opts) {
13499
13514
  }
13500
13515
  async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel, expected) {
13501
13516
  try {
13502
- const record = await ctx.vaultMemoryCollection.find(id);
13503
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
13504
- const readUpdatedAt = record.updatedAt.getTime();
13505
- const readStoredContent = record._getRaw("content");
13517
+ const record2 = await ctx.vaultMemoryCollection.find(id);
13518
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return false;
13519
+ const readUpdatedAt = record2.updatedAt.getTime();
13520
+ const readStoredContent = record2._getRaw("content");
13506
13521
  if (expected?.updatedAt !== void 0 && expected.updatedAt !== readUpdatedAt) return false;
13507
13522
  if (expected?.content !== void 0) {
13508
13523
  const current = await vaultMemoryToStored(
13509
- record,
13524
+ record2,
13510
13525
  ctx.walletAddress,
13511
13526
  ctx.signMessage,
13512
13527
  ctx.embeddedWalletSigner
@@ -13515,11 +13530,11 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel,
13515
13530
  }
13516
13531
  let written = false;
13517
13532
  await ctx.database.write(async () => {
13518
- if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return;
13519
- const originalUpdatedAt = record.updatedAt.getTime();
13520
- if (originalUpdatedAt !== readUpdatedAt || record._getRaw("content") !== readStoredContent)
13533
+ if (record2.isDeleted || !isOwnedByCtxUser(ctx, record2)) return;
13534
+ const originalUpdatedAt = record2.updatedAt.getTime();
13535
+ if (originalUpdatedAt !== readUpdatedAt || record2._getRaw("content") !== readStoredContent)
13521
13536
  return;
13522
- await record.update((r) => {
13537
+ await record2.update((r) => {
13523
13538
  r._setRaw("embedding", embedding);
13524
13539
  r._setRaw("embedding_model", embeddingModel);
13525
13540
  r._setRaw("updated_at", originalUpdatedAt);
@@ -13534,8 +13549,8 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel,
13534
13549
  function normalizeForDedupe(content) {
13535
13550
  return content.normalize("NFKC").trim().replace(/\s+/g, " ").toLowerCase();
13536
13551
  }
13537
- async function findQuarantinedDuplicateOp(ctx, content, sourceIds, where) {
13538
- const wanted = [...new Set(sourceIds)].sort().join("\0");
13552
+ async function findQuarantinedDuplicateOp(ctx, content, sourceIds2, where) {
13553
+ const wanted = [...new Set(sourceIds2)].sort().join("\0");
13539
13554
  const target = normalizeForDedupe(content);
13540
13555
  const rows = await ctx.vaultMemoryCollection.query(
13541
13556
  import_watermelondb20.Q.where("trust_tier", "quarantined"),
@@ -13554,13 +13569,13 @@ async function findQuarantinedDuplicateOp(ctx, content, sourceIds, where) {
13554
13569
  if (!Array.isArray(ids)) continue;
13555
13570
  const key = [...new Set(ids.filter((id) => typeof id === "string"))].sort().join("\0");
13556
13571
  if (key !== wanted) continue;
13557
- const stored = await vaultMemoryRawToStored(
13572
+ const stored2 = await vaultMemoryRawToStored(
13558
13573
  raw,
13559
13574
  ctx.walletAddress,
13560
13575
  ctx.signMessage,
13561
13576
  ctx.embeddedWalletSigner
13562
13577
  );
13563
- if (normalizeForDedupe(stored.content) === target) return stored.uniqueId;
13578
+ if (normalizeForDedupe(stored2.content) === target) return stored2.uniqueId;
13564
13579
  }
13565
13580
  return null;
13566
13581
  }
@@ -13670,25 +13685,25 @@ async function ingestPublishedPhotoMemoriesOp(ctx, rows) {
13670
13685
  inserted = writable.length;
13671
13686
  if (writable.length === 0) return;
13672
13687
  const prepared = writable.map(
13673
- ({ row, content }) => ctx.vaultMemoryCollection.prepareCreate((record) => {
13674
- record._raw.id = row.memoryId;
13675
- record._setRaw("content", content);
13676
- record._setRaw("scope", "shared");
13677
- record._setRaw("folder_id", null);
13678
- record._setRaw("user_id", ctx.userId ?? null);
13679
- record._setRaw("is_deleted", false);
13680
- record._setRaw("proof_count", 1);
13681
- record._setRaw("source", SOURCE_PHOTO);
13682
- record._setRaw(
13688
+ ({ row, content }) => ctx.vaultMemoryCollection.prepareCreate((record2) => {
13689
+ record2._raw.id = row.memoryId;
13690
+ record2._setRaw("content", content);
13691
+ record2._setRaw("scope", "shared");
13692
+ record2._setRaw("folder_id", null);
13693
+ record2._setRaw("user_id", ctx.userId ?? null);
13694
+ record2._setRaw("is_deleted", false);
13695
+ record2._setRaw("proof_count", 1);
13696
+ record2._setRaw("source", SOURCE_PHOTO);
13697
+ record2._setRaw(
13683
13698
  "media",
13684
13699
  row.media && row.media.length > 0 ? JSON.stringify(row.media) : null
13685
13700
  );
13686
- record._setRaw("visibility", "public");
13687
- record._setRaw("published_at", now);
13701
+ record2._setRaw("visibility", "public");
13702
+ record2._setRaw("published_at", now);
13688
13703
  if (row.eventTime) {
13689
- record._setRaw("event_time_start", row.eventTime.start ?? null);
13690
- record._setRaw("event_time_end", row.eventTime.end ?? null);
13691
- record._setRaw("event_time_kind", row.eventTime.kind ?? null);
13704
+ record2._setRaw("event_time_start", row.eventTime.start ?? null);
13705
+ record2._setRaw("event_time_end", row.eventTime.end ?? null);
13706
+ record2._setRaw("event_time_kind", row.eventTime.kind ?? null);
13692
13707
  }
13693
13708
  })
13694
13709
  );
@@ -14053,11 +14068,11 @@ function folderToStored(folder) {
14053
14068
  }
14054
14069
  async function createVaultFolderOp(ctx, opts) {
14055
14070
  const created = await ctx.database.write(async () => {
14056
- return ctx.vaultFolderCollection.create((record) => {
14057
- record._setRaw("name", opts.name);
14058
- record._setRaw("scope", opts.scope ?? "private");
14059
- record._setRaw("is_system", opts.isSystem ?? false);
14060
- record._setRaw("is_deleted", false);
14071
+ return ctx.vaultFolderCollection.create((record2) => {
14072
+ record2._setRaw("name", opts.name);
14073
+ record2._setRaw("scope", opts.scope ?? "private");
14074
+ record2._setRaw("is_system", opts.isSystem ?? false);
14075
+ record2._setRaw("is_deleted", false);
14061
14076
  });
14062
14077
  });
14063
14078
  return folderToStored(created);
@@ -14068,14 +14083,14 @@ async function getAllVaultFoldersOp(ctx) {
14068
14083
  }
14069
14084
  async function updateVaultFolderOp(ctx, id, opts) {
14070
14085
  try {
14071
- const record = await ctx.vaultFolderCollection.find(id);
14072
- if (record.isDeleted) return null;
14073
- const scopeChanged = opts.scope !== void 0 && opts.scope !== record.scope;
14086
+ const record2 = await ctx.vaultFolderCollection.find(id);
14087
+ if (record2.isDeleted) return null;
14088
+ const scopeChanged = opts.scope !== void 0 && opts.scope !== record2.scope;
14074
14089
  const updated = await ctx.database.write(async () => {
14075
14090
  const memories = scopeChanged ? await ctx.vaultMemoryCollection.query(import_watermelondb21.Q.where("folder_id", id), import_watermelondb21.Q.where("is_deleted", false)).fetch() : [];
14076
14091
  const updates = [];
14077
14092
  updates.push(
14078
- record.prepareUpdate((r) => {
14093
+ record2.prepareUpdate((r) => {
14079
14094
  if (opts.name !== void 0) r._setRaw("name", opts.name);
14080
14095
  if (opts.scope !== void 0) r._setRaw("scope", opts.scope);
14081
14096
  })
@@ -14097,8 +14112,8 @@ async function updateVaultFolderOp(ctx, id, opts) {
14097
14112
  }
14098
14113
  async function deleteVaultFolderOp(ctx, id) {
14099
14114
  try {
14100
- const record = await ctx.vaultFolderCollection.find(id);
14101
- if (record.isDeleted) return false;
14115
+ const record2 = await ctx.vaultFolderCollection.find(id);
14116
+ if (record2.isDeleted) return false;
14102
14117
  await ctx.database.write(async () => {
14103
14118
  const memories = await ctx.vaultMemoryCollection.query(import_watermelondb21.Q.where("folder_id", id), import_watermelondb21.Q.where("is_deleted", false)).fetch();
14104
14119
  const preparedMemories = memories.map(
@@ -14107,7 +14122,7 @@ async function deleteVaultFolderOp(ctx, id) {
14107
14122
  r._setRaw("scope", "private");
14108
14123
  })
14109
14124
  );
14110
- const preparedFolder = record.prepareUpdate((r) => {
14125
+ const preparedFolder = record2.prepareUpdate((r) => {
14111
14126
  r._setRaw("is_deleted", true);
14112
14127
  });
14113
14128
  await ctx.database.batch(...preparedMemories, preparedFolder);
@@ -14153,11 +14168,11 @@ async function moveMemoriesToFolderOp(ctx, memoryIds, folderId) {
14153
14168
  }
14154
14169
  async function updateVaultFolderContextOp(ctx, id, context) {
14155
14170
  try {
14156
- const record = await ctx.vaultFolderCollection.find(id);
14157
- if (record.isDeleted) return null;
14171
+ const record2 = await ctx.vaultFolderCollection.find(id);
14172
+ if (record2.isDeleted) return null;
14158
14173
  const updated = await ctx.database.write(async () => {
14159
14174
  await ctx.database.batch(
14160
- record.prepareUpdate((r) => {
14175
+ record2.prepareUpdate((r) => {
14161
14176
  r._setRaw("context", context);
14162
14177
  })
14163
14178
  );
@@ -16235,7 +16250,7 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
16235
16250
  if (useFusion && !embeddingsUnavailable && facetQueries) {
16236
16251
  let subEmbeddings;
16237
16252
  try {
16238
- subEmbeddings = await generateEmbeddings(facetQueries, embeddingOptions);
16253
+ subEmbeddings = prepared.facetEmbeddings ?? await generateEmbeddings(facetQueries, embeddingOptions);
16239
16254
  } catch (err) {
16240
16255
  getLogger().warn(
16241
16256
  "memoryVault: sub-query embedding failed \u2014 falling back to single-query ranking: " + (err instanceof Error ? err.message : String(err))
@@ -16421,6 +16436,35 @@ var DEFAULT_SCOPE = "private";
16421
16436
  var DEFAULT_CONSOLIDATE_THRESHOLD = 0.55;
16422
16437
  var DEFAULT_CONSOLIDATE_TOP_K = 20;
16423
16438
  async function retain(content, ctx, options = {}) {
16439
+ return retainWithPersistence(
16440
+ content,
16441
+ {
16442
+ embeddingOptions: ctx.embeddingOptions,
16443
+ vaultCache: ctx.vaultCache,
16444
+ persistence: {
16445
+ prepare: (query, searchOptions) => prepareVaultCandidates(
16446
+ query,
16447
+ ctx.vaultCtx,
16448
+ ctx.embeddingOptions,
16449
+ ctx.vaultCache,
16450
+ searchOptions
16451
+ ),
16452
+ get: (id) => getVaultMemoryOp(ctx.vaultCtx, id),
16453
+ tombstones: (_embedding, _model, scope, folderId) => getAllVaultMemoriesOp(ctx.vaultCtx, {
16454
+ includeDeleted: true,
16455
+ scopes: [scope],
16456
+ ...folderId !== void 0 && { folderId }
16457
+ }),
16458
+ create: (input) => createVaultMemoryOp(ctx.vaultCtx, input),
16459
+ update: (id, patch) => updateVaultMemoryOp(ctx.vaultCtx, id, patch),
16460
+ supersede: (id, successor) => supersedeVaultMemoryOp(ctx.vaultCtx, id, successor),
16461
+ createSuperseding: (input, target) => createSupersedingMemoryOp(ctx.vaultCtx, input, target)
16462
+ }
16463
+ },
16464
+ options
16465
+ );
16466
+ }
16467
+ async function retainWithPersistence(content, ctx, options = {}) {
16424
16468
  const trimmed = content.trim();
16425
16469
  if (trimmed.length === 0) {
16426
16470
  throw new Error("retain: content cannot be empty");
@@ -16433,19 +16477,13 @@ async function retain(content, ctx, options = {}) {
16433
16477
  let supersedeContent;
16434
16478
  let prepared;
16435
16479
  if (enableAutoMerge) {
16436
- prepared = await prepareVaultCandidates(
16437
- trimmed,
16438
- ctx.vaultCtx,
16439
- ctx.embeddingOptions,
16440
- ctx.vaultCache,
16441
- {
16442
- limit: Math.max(options.consolidateTopK ?? DEFAULT_CONSOLIDATE_TOP_K, 1),
16443
- useFusion: false,
16444
- scopes: [resolvedScope],
16445
- includeArchived: true,
16446
- ...options.folderId !== void 0 && { folderId: options.folderId }
16447
- }
16448
- );
16480
+ prepared = await ctx.persistence.prepare(trimmed, {
16481
+ limit: Math.max(options.consolidateTopK ?? DEFAULT_CONSOLIDATE_TOP_K, 1),
16482
+ useFusion: false,
16483
+ scopes: [resolvedScope],
16484
+ includeArchived: true,
16485
+ ...options.folderId !== void 0 && { folderId: options.folderId }
16486
+ });
16449
16487
  if (prepared.embeddingFailure || prepared.embeddingsUnavailable) {
16450
16488
  throw new Error(
16451
16489
  "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."
@@ -16476,7 +16514,7 @@ async function retain(content, ctx, options = {}) {
16476
16514
  );
16477
16515
  if (matches.length > 0) {
16478
16516
  const targetId = matches[0].uniqueId;
16479
- const existing = await getVaultMemoryOp(ctx.vaultCtx, targetId);
16517
+ const existing = await ctx.persistence.get(targetId);
16480
16518
  if (existing && !existing.supersededBy) {
16481
16519
  const mergedSourceIds = unionStrings(
16482
16520
  existing.sourceChunkIds ?? [],
@@ -16485,7 +16523,7 @@ async function retain(content, ctx, options = {}) {
16485
16523
  const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
16486
16524
  const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
16487
16525
  const resurrect = resurrectFields(existing);
16488
- const updated = await updateVaultMemoryOp(ctx.vaultCtx, targetId, {
16526
+ const updated = await ctx.persistence.update(targetId, {
16489
16527
  content: existing.content,
16490
16528
  proofCountIncrement: 1,
16491
16529
  observationSourceIds: options.sourceChunkIds,
@@ -16512,7 +16550,8 @@ async function retain(content, ctx, options = {}) {
16512
16550
  }
16513
16551
  const contentToWrite = supersedeContent ?? trimmed;
16514
16552
  const reusableQueryEmbedding = supersedeContent === void 0 && prepared && prepared.queryEmbedding.length > 0 ? prepared.queryEmbedding : void 0;
16515
- const embedding = reusableQueryEmbedding ?? await generateEmbedding(contentToWrite, ctx.embeddingOptions);
16553
+ const generatedEmbedding = reusableQueryEmbedding ?? await generateEmbedding(contentToWrite, ctx.embeddingOptions);
16554
+ const embedding = ctx.normalizeEmbedding?.(generatedEmbedding) ?? generatedEmbedding;
16516
16555
  const embeddingModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
16517
16556
  if (options.respectTombstones) {
16518
16557
  const tombstone = await findTombstoneMatch(embedding, embeddingModel, resolvedScope, ctx, {
@@ -16552,8 +16591,7 @@ async function retain(content, ctx, options = {}) {
16552
16591
  };
16553
16592
  if (supersedeTargetIds.length > 0) {
16554
16593
  const [primaryTargetId, ...restTargetIds] = supersedeTargetIds;
16555
- const { created: created2, retired } = await createSupersedingMemoryOp(
16556
- ctx.vaultCtx,
16594
+ const { created: created2, retired } = await ctx.persistence.createSuperseding(
16557
16595
  createOpts,
16558
16596
  primaryTargetId
16559
16597
  );
@@ -16569,11 +16607,11 @@ async function retain(content, ctx, options = {}) {
16569
16607
  for (const staleId of restTargetIds) {
16570
16608
  let ok = false;
16571
16609
  try {
16572
- ok = await supersedeVaultMemoryOp(ctx.vaultCtx, staleId, created2.uniqueId) === true;
16610
+ ok = await ctx.persistence.supersede(staleId, created2.uniqueId) === true;
16573
16611
  } catch {
16574
16612
  }
16575
16613
  if (ok) continue;
16576
- const stillLive = await getVaultMemoryOp(ctx.vaultCtx, staleId).catch(() => null);
16614
+ const stillLive = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(staleId) : ctx.persistence.get(staleId)).catch(() => null);
16577
16615
  if (stillLive && !stillLive.supersededBy) liveLeftovers.push(staleId);
16578
16616
  }
16579
16617
  if (liveLeftovers.length > 0) {
@@ -16600,7 +16638,7 @@ async function retain(content, ctx, options = {}) {
16600
16638
  `supersede: primary target ${primaryTargetId} retired or deleted inside the atomic write`
16601
16639
  );
16602
16640
  }
16603
- const created = await createVaultMemoryOp(ctx.vaultCtx, createOpts);
16641
+ const created = await ctx.persistence.create(createOpts);
16604
16642
  cacheRowVector(
16605
16643
  ctx.vaultCache,
16606
16644
  created.uniqueId,
@@ -16619,11 +16657,7 @@ function unionStrings(a, b) {
16619
16657
  return [.../* @__PURE__ */ new Set([...a, ...b])];
16620
16658
  }
16621
16659
  async function findTombstoneMatch(embedding, embeddingModel, scope, ctx, opts) {
16622
- const rows = await getAllVaultMemoriesOp(ctx.vaultCtx, {
16623
- includeDeleted: true,
16624
- scopes: [scope],
16625
- ...opts.folderId !== void 0 && { folderId: opts.folderId }
16626
- });
16660
+ const rows = await ctx.persistence.tombstones(embedding, embeddingModel, scope, opts.folderId);
16627
16661
  let bestId = null;
16628
16662
  let bestSim = opts.threshold;
16629
16663
  for (const row of rows) {
@@ -16690,7 +16724,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
16690
16724
  if (requestedIds.length === 0) return null;
16691
16725
  const valid = [];
16692
16726
  for (const id of requestedIds) {
16693
- const existing = await getVaultMemoryOp(ctx.vaultCtx, id);
16727
+ const existing = await ctx.persistence.get(id);
16694
16728
  if (existing && !existing.supersededBy) valid.push(id);
16695
16729
  }
16696
16730
  if (valid.length === 0) {
@@ -16702,7 +16736,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
16702
16736
  return { supersede: valid, content: decision.content };
16703
16737
  }
16704
16738
  if (decision.action === "noop" && decision.targetId) {
16705
- const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
16739
+ const existing = await ctx.persistence.get(decision.targetId);
16706
16740
  if (!existing || existing.supersededBy) {
16707
16741
  return abandonToRace(
16708
16742
  options,
@@ -16716,7 +16750,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
16716
16750
  const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
16717
16751
  const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
16718
16752
  const resurrect = resurrectFields(existing);
16719
- const updated = await updateVaultMemoryOp(ctx.vaultCtx, decision.targetId, {
16753
+ const updated = await ctx.persistence.update(decision.targetId, {
16720
16754
  content: existing.content,
16721
16755
  proofCountIncrement: 1,
16722
16756
  observationSourceIds: options.sourceChunkIds,
@@ -16744,7 +16778,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
16744
16778
  };
16745
16779
  }
16746
16780
  if (decision.action === "update" && decision.targetId && decision.content) {
16747
- const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
16781
+ const existing = await ctx.persistence.get(decision.targetId);
16748
16782
  if (!existing || existing.supersededBy) {
16749
16783
  return abandonToRace(
16750
16784
  options,
@@ -16755,12 +16789,13 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
16755
16789
  existing.sourceChunkIds ?? [],
16756
16790
  options.sourceChunkIds ?? []
16757
16791
  );
16758
- const newEmbedding = await generateEmbedding(decision.content, ctx.embeddingOptions);
16792
+ const generatedEmbedding = await generateEmbedding(decision.content, ctx.embeddingOptions);
16793
+ const newEmbedding = ctx.normalizeEmbedding?.(generatedEmbedding) ?? generatedEmbedding;
16759
16794
  const consolidatedModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
16760
16795
  const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
16761
16796
  const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
16762
16797
  const resurrect = resurrectFields(existing);
16763
- const updated = await updateVaultMemoryOp(ctx.vaultCtx, decision.targetId, {
16798
+ const updated = await ctx.persistence.update(decision.targetId, {
16764
16799
  content: decision.content,
16765
16800
  proofCountIncrement: 1,
16766
16801
  observationSourceIds: options.sourceChunkIds,
@@ -16804,7 +16839,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
16804
16839
  return null;
16805
16840
  }
16806
16841
  async function assertMergeTargetGoneOrThrow(ctx, targetId) {
16807
- const stillExists = await getVaultMemoryOp(ctx.vaultCtx, targetId);
16842
+ const stillExists = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(targetId) : ctx.persistence.get(targetId));
16808
16843
  if (stillExists) {
16809
16844
  throw new Error(`retain: merge into memory ${targetId} failed to persist`);
16810
16845
  }
@@ -17321,9 +17356,9 @@ function createAutoExtractor(options) {
17321
17356
  const persistCursor = (conversationId, messages, advancedToId, contiguous) => {
17322
17357
  if (!cursorStore || conversationId === void 0 || !contiguous) return;
17323
17358
  try {
17324
- const stored = cursorStore.get(conversationId);
17325
- if (stored && stored !== advancedToId) {
17326
- const storedIdx = messages.findIndex((m) => m.id === stored);
17359
+ const stored2 = cursorStore.get(conversationId);
17360
+ if (stored2 && stored2 !== advancedToId) {
17361
+ const storedIdx = messages.findIndex((m) => m.id === stored2);
17327
17362
  const newIdx = messages.findIndex((m) => m.id === advancedToId);
17328
17363
  if (storedIdx !== -1 && newIdx !== -1 && storedIdx >= newIdx) return;
17329
17364
  }
@@ -18303,7 +18338,7 @@ async function recall(query, ctx, options = {}) {
18303
18338
  if (graphLaneFailed) degraded.push("graph-lane-failed");
18304
18339
  if (temporalLaneFailed) degraded.push("temporal-lane-failed");
18305
18340
  if (chunksScopeRestricted) degraded.push("chunks-scope-restricted");
18306
- const laneRan = types.includes("fact") && !!ctx.vaultCtx && !!ctx.vaultCache || types.includes("chunk") && !!ctx.storageCtx || chunksScopeRestricted && !!ctx.storageCtx;
18341
+ const laneRan = types.includes("fact") && (!!ctx.factSource || !!ctx.vaultCtx && !!ctx.vaultCache) || types.includes("chunk") && !!ctx.storageCtx || chunksScopeRestricted && !!ctx.storageCtx;
18307
18342
  const scores = admitted.map((m) => m.score);
18308
18343
  const minScoreApplied = factResults.length > 0 ? factFloor : chunkResults.length > 0 ? chunkFloor : factFloor >= 0 ? factFloor : chunkFloor;
18309
18344
  const diagnostics = {
@@ -18345,7 +18380,7 @@ async function recall(query, ctx, options = {}) {
18345
18380
  return { memories: [], usedBudget, reranked: false, candidateCount: 0 };
18346
18381
  }
18347
18382
  const needsChunkEmbedding = types.includes("chunk") && ctx.storageCtx;
18348
- const wantsTemporal = types.includes("fact") && ctx.vaultCtx;
18383
+ const wantsTemporal = types.includes("fact") && (ctx.factSource || ctx.vaultCtx);
18349
18384
  const graphRefiner = flags.traverse && options.graphRefine && options.decomposeOptions ? createLlmNeighborRefiner(options.decomposeOptions) : void 0;
18350
18385
  const queryEmbedTotalTimeoutMs = options.queryEmbedTotalTimeoutMs ?? DEFAULT_QUERY_EMBED_TOTAL_TIMEOUT_MS;
18351
18386
  const prepStart = nowMs2();
@@ -18375,7 +18410,7 @@ async function recall(query, ctx, options = {}) {
18375
18410
  safeLane(
18376
18411
  "graph",
18377
18412
  () => graphLaneFailed = true,
18378
- () => buildGraphLaneRanking(query, ctx, flags.traverse, {
18413
+ () => ctx.factSource ? ctx.factSource.graphRanking(query, flags.traverse, options) : buildGraphLaneRanking(query, ctx, flags.traverse, {
18379
18414
  ...options.maxHops !== void 0 && { maxHops: options.maxHops },
18380
18415
  ...options.entityFanout !== void 0 && { entityFanout: options.entityFanout },
18381
18416
  ...options.nodeBudget !== void 0 && { nodeBudget: options.nodeBudget },
@@ -18386,13 +18421,13 @@ async function recall(query, ctx, options = {}) {
18386
18421
  wantsTemporal ? safeLane(
18387
18422
  "temporal",
18388
18423
  () => temporalLaneFailed = true,
18389
- () => buildTemporalLaneRanking(query, ctx.vaultCtx, options.now)
18424
+ () => ctx.factSource ? ctx.factSource.temporalRanking(query, options.now) : buildTemporalLaneRanking(query, ctx.vaultCtx, options.now)
18390
18425
  ) : Promise.resolve([])
18391
18426
  ]);
18392
18427
  prepMs = nowMs2() - prepStart;
18393
18428
  graphLaneCount = entityRanking.length;
18394
18429
  temporalLaneCount = temporalRanking.length;
18395
- if (types.includes("fact") && ctx.vaultCtx && ctx.vaultCache) {
18430
+ if (types.includes("fact") && (ctx.factSource || ctx.vaultCtx && ctx.vaultCache)) {
18396
18431
  const factStart = nowMs2();
18397
18432
  const vaultMinScore = options.minScore ?? DEFAULT_FACT_MIN_SCORE;
18398
18433
  factFloor = vaultMinScore;
@@ -18408,50 +18443,50 @@ async function recall(query, ctx, options = {}) {
18408
18443
  rankedOnCosine: factRankedOnCosine,
18409
18444
  decryptLast: factDecryptLast,
18410
18445
  rowsDecrypted: factRowsDecrypted
18411
- } = await searchVaultMemoriesWithSize(
18412
- query,
18446
+ } = await (ctx.factSource?.search.bind(ctx.factSource) ?? ((searchQuery, searchOptions) => searchVaultMemoriesWithSize(
18447
+ searchQuery,
18413
18448
  ctx.vaultCtx,
18414
18449
  ctx.embeddingOptions,
18415
18450
  ctx.vaultCache,
18416
- {
18417
- limit: types.includes("chunk") ? Math.max(limit * 2, 16) : limit,
18418
- minSimilarity: vaultMinScore,
18419
- useFusion: true,
18420
- rerank: flags.rerank,
18421
- ...options.rerankTopN !== void 0 && { rerankTopN: options.rerankTopN },
18422
- ...options.ceWeight !== void 0 && { ceWeight: options.ceWeight },
18423
- ...options.rerankLoadTimeoutMs !== void 0 && {
18424
- rerankLoadTimeoutMs: options.rerankLoadTimeoutMs
18425
- },
18426
- ...options.recencyAlpha !== void 0 && { recencyAlpha: options.recencyAlpha },
18427
- ...options.recency && { recency: options.recency },
18428
- ...options.mmr !== void 0 && { mmr: options.mmr },
18429
- ...options.supersessionBoost !== void 0 && {
18430
- supersessionBoost: options.supersessionBoost
18431
- },
18432
- ...options.supersessionWindow !== void 0 && {
18433
- supersessionWindow: options.supersessionWindow
18434
- },
18435
- ...options.proofCountAlpha !== void 0 && {
18436
- proofCountAlpha: options.proofCountAlpha
18437
- },
18438
- ...options.bm25AdmissionDivisor !== void 0 && {
18439
- bm25AdmissionDivisor: options.bm25AdmissionDivisor
18440
- },
18441
- ...options.rrfK !== void 0 && { rrfK: options.rrfK },
18442
- ...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
18443
- ...subQueries && { subQueries },
18444
- ...options.scopes && { scopes: options.scopes },
18445
- ...options.folderId !== void 0 && { folderId: options.folderId },
18446
- ...options.factTypes?.length && { factTypes: options.factTypes },
18447
- ...options.memoryIds !== void 0 && { memoryIds: options.memoryIds },
18448
- ...options.factTypeWeights && { factTypeWeights: options.factTypeWeights },
18449
- ...entityRanking.length > 0 && { entityRanking },
18450
- ...temporalRanking.length > 0 && { temporalRanking },
18451
- ...needsChunkEmbedding && { queryEmbedding: queryEmbedding ?? [] },
18452
- queryEmbedTotalTimeoutMs
18453
- }
18454
- );
18451
+ searchOptions
18452
+ )))(query, {
18453
+ limit: types.includes("chunk") ? Math.max(limit * 2, 16) : limit,
18454
+ minSimilarity: vaultMinScore,
18455
+ useFusion: true,
18456
+ rerank: flags.rerank,
18457
+ ...options.rerankTopN !== void 0 && { rerankTopN: options.rerankTopN },
18458
+ ...options.ceWeight !== void 0 && { ceWeight: options.ceWeight },
18459
+ ...options.rerankLoadTimeoutMs !== void 0 && {
18460
+ rerankLoadTimeoutMs: options.rerankLoadTimeoutMs
18461
+ },
18462
+ ...options.recencyAlpha !== void 0 && { recencyAlpha: options.recencyAlpha },
18463
+ ...options.recency && { recency: options.recency },
18464
+ ...options.mmr !== void 0 && { mmr: options.mmr },
18465
+ ...options.supersessionBoost !== void 0 && {
18466
+ supersessionBoost: options.supersessionBoost
18467
+ },
18468
+ ...options.supersessionWindow !== void 0 && {
18469
+ supersessionWindow: options.supersessionWindow
18470
+ },
18471
+ ...options.proofCountAlpha !== void 0 && {
18472
+ proofCountAlpha: options.proofCountAlpha
18473
+ },
18474
+ ...options.bm25AdmissionDivisor !== void 0 && {
18475
+ bm25AdmissionDivisor: options.bm25AdmissionDivisor
18476
+ },
18477
+ ...options.rrfK !== void 0 && { rrfK: options.rrfK },
18478
+ ...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
18479
+ ...subQueries && { subQueries },
18480
+ ...options.scopes && { scopes: options.scopes },
18481
+ ...options.folderId !== void 0 && { folderId: options.folderId },
18482
+ ...options.factTypes?.length && { factTypes: options.factTypes },
18483
+ ...options.memoryIds !== void 0 && { memoryIds: options.memoryIds },
18484
+ ...options.factTypeWeights && { factTypeWeights: options.factTypeWeights },
18485
+ ...entityRanking.length > 0 && { entityRanking },
18486
+ ...temporalRanking.length > 0 && { temporalRanking },
18487
+ ...needsChunkEmbedding && { queryEmbedding: queryEmbedding ?? [] },
18488
+ queryEmbedTotalTimeoutMs
18489
+ });
18455
18490
  factResults.push(
18456
18491
  ...dedupeBy(
18457
18492
  results,
@@ -19264,26 +19299,26 @@ async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
19264
19299
  };
19265
19300
  const inputs = [];
19266
19301
  for (const id of new Set(memoryIds)) {
19267
- let record;
19302
+ let record2;
19268
19303
  try {
19269
- record = await ctx.vaultMemoryCollection.find(id);
19304
+ record2 = await ctx.vaultMemoryCollection.find(id);
19270
19305
  } catch (err) {
19271
19306
  log.warn("[memory/topics] vault lookup failed for extraction", err);
19272
19307
  skip(id, "not-found");
19273
19308
  continue;
19274
19309
  }
19275
- if (record.isDeleted || ctx.userId !== void 0 && record.userId !== ctx.userId || record.topicsUserManaged) {
19310
+ if (record2.isDeleted || ctx.userId !== void 0 && record2.userId !== ctx.userId || record2.topicsUserManaged) {
19276
19311
  skip(id, "excluded");
19277
19312
  continue;
19278
19313
  }
19279
19314
  try {
19280
- const stored = await vaultMemoryToStored(
19281
- record,
19315
+ const stored2 = await vaultMemoryToStored(
19316
+ record2,
19282
19317
  ctx.walletAddress,
19283
19318
  ctx.signMessage,
19284
19319
  ctx.embeddedWalletSigner
19285
19320
  );
19286
- inputs.push({ id, content: stored.content });
19321
+ inputs.push({ id, content: stored2.content });
19287
19322
  } catch (err) {
19288
19323
  log.warn("[memory/topics] failed to load memory for extraction", err);
19289
19324
  skip(id, "unreadable");
@@ -19468,6 +19503,774 @@ function createLocalMemoryStore(options) {
19468
19503
  };
19469
19504
  }
19470
19505
 
19506
+ // src/lib/memory/store/remotePersistence.ts
19507
+ var RemoteMemoryError = class extends Error {
19508
+ constructor(message, status, code) {
19509
+ super(message);
19510
+ this.status = status;
19511
+ this.code = code;
19512
+ this.name = "RemoteMemoryError";
19513
+ }
19514
+ };
19515
+ var ciphertextPattern = /^enc:v\d+:[0-9a-f]+$/i;
19516
+ var memoryFields = {
19517
+ memory_id: true,
19518
+ content: true,
19519
+ scope: true,
19520
+ created_at: true,
19521
+ updated_at: true,
19522
+ is_deleted: true,
19523
+ embedding: true,
19524
+ embedding_model: true,
19525
+ kind: true,
19526
+ kind_value: true,
19527
+ level: true,
19528
+ folder_id: true,
19529
+ source_chunk_ids: true,
19530
+ proof_count: true,
19531
+ source: true,
19532
+ event_time_start: true,
19533
+ event_time_end: true,
19534
+ event_time_kind: true,
19535
+ topics_user_managed: true,
19536
+ topics: true,
19537
+ topics_updated_at: true,
19538
+ media: true,
19539
+ topics_extracted_at: true,
19540
+ topics_extracted_version: true,
19541
+ superseded_by: true,
19542
+ superseded_at: true,
19543
+ last_observed_at: true,
19544
+ fact_type: true,
19545
+ archived_at: true,
19546
+ trust_tier: true,
19547
+ visibility: true,
19548
+ twin_opt_in: true,
19549
+ published_at: true,
19550
+ geohash: true
19551
+ };
19552
+ var candidateListLimits = [
19553
+ ["scopes", 20],
19554
+ ["fact_types", 20],
19555
+ ["memory_ids", 1e3],
19556
+ ["force_ids", 100]
19557
+ ];
19558
+ function record(value) {
19559
+ return typeof value === "object" && value !== null && !Array.isArray(value);
19560
+ }
19561
+ function memoryRecord(value) {
19562
+ 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))) {
19563
+ throw new Error("Invalid nearby private-memory response");
19564
+ }
19565
+ return value;
19566
+ }
19567
+ async function createRemoteMemoryPersistence(options) {
19568
+ const base = new URL(options.baseUrl);
19569
+ if (!/^https?:$/.test(base.protocol) || base.username || base.password || base.search || base.hash) {
19570
+ throw new Error(
19571
+ "baseUrl must be an HTTP(S) origin or base path without credentials, query or fragment"
19572
+ );
19573
+ }
19574
+ if (!options.keyId || options.keyId.length > 256)
19575
+ throw new Error("A canonical keyId is required");
19576
+ const timeoutMs = options.timeoutMs ?? 3e4;
19577
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0)
19578
+ throw new Error("timeoutMs must be a positive number");
19579
+ const root = base.href.replace(/\/$/, "") + "/api/private-memories";
19580
+ const fetcher = options.fetch ?? globalThis.fetch;
19581
+ const request = async (path, init = {}, signal) => {
19582
+ const controller = new AbortController();
19583
+ let timedOut = false;
19584
+ const timer = setTimeout(() => {
19585
+ timedOut = true;
19586
+ controller.abort();
19587
+ }, timeoutMs);
19588
+ const forwardAbort = () => controller.abort(signal?.reason);
19589
+ if (signal?.aborted) forwardAbort();
19590
+ else signal?.addEventListener("abort", forwardAbort, { once: true });
19591
+ let rejectAborted;
19592
+ const aborted = new Promise((_, reject) => {
19593
+ rejectAborted = () => reject(
19594
+ controller.signal.reason instanceof Error ? controller.signal.reason : new Error("Nearby request aborted")
19595
+ );
19596
+ if (controller.signal.aborted) rejectAborted();
19597
+ else controller.signal.addEventListener("abort", rejectAborted, { once: true });
19598
+ });
19599
+ aborted.catch(() => void 0);
19600
+ try {
19601
+ const token = await Promise.race([options.getToken(), aborted]);
19602
+ if (controller.signal.aborted) await aborted;
19603
+ if (!token) throw new RemoteMemoryError("Authentication required", 401);
19604
+ const response = await fetcher(root + path, {
19605
+ ...init,
19606
+ headers: {
19607
+ Authorization: `Bearer ${token}`,
19608
+ ...init.body ? { "Content-Type": "application/json" } : {}
19609
+ },
19610
+ redirect: "error",
19611
+ signal: controller.signal
19612
+ });
19613
+ if (!response.ok) {
19614
+ const body = await response.json().catch(() => null);
19615
+ throw new RemoteMemoryError(
19616
+ record(body) && typeof body.detail === "string" ? body.detail : `Nearby request failed (${response.status})`,
19617
+ response.status,
19618
+ record(body) && typeof body.code === "string" ? body.code : void 0
19619
+ );
19620
+ }
19621
+ return await response.json();
19622
+ } catch (error) {
19623
+ if (timedOut) throw new RemoteMemoryError("Nearby request timed out", 408, "timeout");
19624
+ throw error;
19625
+ } finally {
19626
+ clearTimeout(timer);
19627
+ signal?.removeEventListener("abort", forwardAbort);
19628
+ if (rejectAborted) controller.signal.removeEventListener("abort", rejectAborted);
19629
+ }
19630
+ };
19631
+ const account = await request("/account", {}, options.signal);
19632
+ if (!record(account) || account.state !== "active") {
19633
+ throw new RemoteMemoryError(
19634
+ "Complete and verify migration before using remote memories",
19635
+ 409,
19636
+ "memory_not_active"
19637
+ );
19638
+ }
19639
+ if (account.key_id !== options.keyId) {
19640
+ throw new RemoteMemoryError(
19641
+ "The canonical memory key does not match this account",
19642
+ 409,
19643
+ "key_mismatch"
19644
+ );
19645
+ }
19646
+ const snapshots = /* @__PURE__ */ new WeakMap();
19647
+ const decode = async (value) => {
19648
+ const item = memoryRecord(value);
19649
+ const decrypt = async (ciphertext) => {
19650
+ if (!ciphertextPattern.test(ciphertext))
19651
+ throw new Error("Nearby returned unencrypted memory content");
19652
+ const plaintext = await options.decrypt(ciphertext);
19653
+ if (plaintext === ciphertext) throw new Error("Memory decryption failed");
19654
+ return plaintext;
19655
+ };
19656
+ const decoded = {
19657
+ ...item,
19658
+ memory: {
19659
+ ...item.memory,
19660
+ content: await decrypt(item.memory.content),
19661
+ ...item.memory.kind_value !== void 0 && {
19662
+ kind_value: await decrypt(item.memory.kind_value)
19663
+ }
19664
+ }
19665
+ };
19666
+ return remember(decoded, item);
19667
+ };
19668
+ const remember = (decoded, item) => {
19669
+ snapshots.set(decoded, {
19670
+ id: item.memory.memory_id,
19671
+ version: item.version,
19672
+ content: decoded.memory.content,
19673
+ kindValue: decoded.memory.kind_value,
19674
+ encryptedContent: item.memory.content,
19675
+ encryptedKindValue: item.memory.kind_value
19676
+ });
19677
+ return decoded;
19678
+ };
19679
+ const decodeAll = async (values) => {
19680
+ const records = values.map(memoryRecord);
19681
+ const settled = await Promise.allSettled(records.map(decode));
19682
+ const items = [];
19683
+ const failed = [];
19684
+ settled.forEach((result, i) => {
19685
+ if (result.status === "fulfilled") items.push(result.value);
19686
+ else
19687
+ failed.push({
19688
+ memory_id: records[i].memory.memory_id,
19689
+ version: records[i].version,
19690
+ error: result.reason instanceof Error ? result.reason : new Error(String(result.reason))
19691
+ });
19692
+ });
19693
+ return { items, failed };
19694
+ };
19695
+ const decodeCommitted = async (value, write) => {
19696
+ const item = memoryRecord(value);
19697
+ 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)
19698
+ return decode(item);
19699
+ return remember(
19700
+ {
19701
+ ...item,
19702
+ memory: {
19703
+ ...item.memory,
19704
+ content: write.content,
19705
+ ...write.kindValue !== void 0 && { kind_value: write.kindValue }
19706
+ }
19707
+ },
19708
+ item
19709
+ );
19710
+ };
19711
+ const encryptField2 = async (plaintext) => {
19712
+ const ciphertext = await options.encrypt(plaintext);
19713
+ if (ciphertext === plaintext || !ciphertextPattern.test(ciphertext))
19714
+ throw new Error("Field encryption must return SDK ciphertext; refusing to upload plaintext");
19715
+ return ciphertext;
19716
+ };
19717
+ const memoryPath = (id) => {
19718
+ if (!id || id.length > 128) throw new Error("memory_id must be 1\u2013128 characters");
19719
+ return "/memories/" + encodeURIComponent(id);
19720
+ };
19721
+ const prepareWrite = async (memory, expectedVersion, signal) => {
19722
+ const unknown = Object.keys(memory).filter(
19723
+ (key) => !Object.prototype.hasOwnProperty.call(memoryFields, key)
19724
+ );
19725
+ if (unknown.length) {
19726
+ throw new RemoteMemoryError(
19727
+ `Unknown private-memory fields (${unknown.join(", ")}); refusing to forward them`,
19728
+ 400,
19729
+ "unknown_field"
19730
+ );
19731
+ }
19732
+ memory = { ...memory, ...memory.embedding && { embedding: [...memory.embedding] } };
19733
+ const path = memoryPath(memory.memory_id);
19734
+ const snapshot = typeof expectedVersion === "number" ? void 0 : snapshots.get(expectedVersion);
19735
+ if (typeof expectedVersion !== "number" && (!snapshot || snapshot.id !== memory.memory_id || snapshot.version !== expectedVersion.version))
19736
+ throw new Error(
19737
+ "Expected snapshot must be an unmodified version from this persistence instance"
19738
+ );
19739
+ expectedVersion = typeof expectedVersion === "number" ? expectedVersion : snapshot.version;
19740
+ if (!Number.isSafeInteger(expectedVersion) || expectedVersion < 0)
19741
+ throw new Error("expectedVersion must be a nonnegative integer");
19742
+ const conflict = () => new RemoteMemoryError("The memory changed since it was read", 409, "version_conflict");
19743
+ let existing;
19744
+ if (expectedVersion !== 0 && !snapshot) {
19745
+ try {
19746
+ existing = memoryRecord(await request(path, {}, signal));
19747
+ } catch (error) {
19748
+ if (error instanceof RemoteMemoryError && error.status === 404) throw conflict();
19749
+ throw error;
19750
+ }
19751
+ }
19752
+ if (existing && existing.version !== expectedVersion) throw conflict();
19753
+ const decoded = existing ? await decode(existing).catch(() => void 0) : void 0;
19754
+ const content = (snapshot?.content ?? decoded?.memory.content) === memory.content ? snapshot?.encryptedContent ?? existing.memory.content : await encryptField2(memory.content);
19755
+ 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);
19756
+ return {
19757
+ body: {
19758
+ expected_version: expectedVersion,
19759
+ memory: { ...memory, content, ...kindValue !== void 0 && { kind_value: kindValue } }
19760
+ },
19761
+ content: memory.content,
19762
+ kindValue: memory.kind_value
19763
+ };
19764
+ };
19765
+ const fetchCandidates = async (embedding, candidateOptions, withCounts) => {
19766
+ const limit = candidateOptions.limit ?? 100;
19767
+ if (!Number.isInteger(limit) || limit < 1 || limit > 100)
19768
+ throw new Error("Candidate limit must be 1\u2013100");
19769
+ for (const [key, max] of candidateListLimits) {
19770
+ const values = candidateOptions[key];
19771
+ if (values && values.length > max)
19772
+ throw new Error(`Candidate ${key} accepts at most ${max} entries (got ${values.length})`);
19773
+ }
19774
+ const result = await request(
19775
+ "/candidates",
19776
+ {
19777
+ method: "POST",
19778
+ body: JSON.stringify({
19779
+ embedding,
19780
+ limit,
19781
+ force_ids: candidateOptions.force_ids ?? [],
19782
+ ...withCounts && { with_counts: true },
19783
+ ...Object.fromEntries(
19784
+ [
19785
+ "scopes",
19786
+ "memory_ids",
19787
+ "embedding_model",
19788
+ "strict_model",
19789
+ "include_deleted",
19790
+ "deleted_only"
19791
+ ].filter(
19792
+ (key) => candidateOptions[key] !== void 0
19793
+ ).map((key) => [key, candidateOptions[key]])
19794
+ ),
19795
+ ...candidateOptions.fact_types !== void 0 && {
19796
+ fact_types: candidateOptions.fact_types
19797
+ },
19798
+ ...candidateOptions.include_archived !== void 0 && {
19799
+ include_archived: candidateOptions.include_archived
19800
+ },
19801
+ ...candidateOptions.include_quarantined !== void 0 && {
19802
+ include_quarantined: candidateOptions.include_quarantined
19803
+ },
19804
+ ...candidateOptions.include_superseded !== void 0 && {
19805
+ include_superseded: candidateOptions.include_superseded
19806
+ }
19807
+ })
19808
+ },
19809
+ candidateOptions.signal
19810
+ );
19811
+ if (!record(result) || !Array.isArray(result.items))
19812
+ throw new Error("Invalid nearby candidate response");
19813
+ return result;
19814
+ };
19815
+ const candidateSet = async (embedding, candidateOptions = {}) => {
19816
+ const result = await fetchCandidates(embedding, candidateOptions, true);
19817
+ if (!Number.isSafeInteger(result.total_count) || result.total_count < 0 || !Number.isSafeInteger(result.unavailable_count) || result.unavailable_count < 0)
19818
+ throw new Error("Invalid nearby candidate response");
19819
+ return {
19820
+ ...await decodeAll(result.items),
19821
+ total_count: result.total_count,
19822
+ unavailable_count: result.unavailable_count
19823
+ };
19824
+ };
19825
+ return {
19826
+ get: async (id, signal) => {
19827
+ try {
19828
+ return await decode(await request(memoryPath(id), {}, signal));
19829
+ } catch (error) {
19830
+ if (error instanceof RemoteMemoryError && error.status === 404) return null;
19831
+ throw error;
19832
+ }
19833
+ },
19834
+ list: async (listOptions = {}) => {
19835
+ const { signal, ...query } = listOptions;
19836
+ if (query.limit !== void 0 && (!Number.isInteger(query.limit) || query.limit < 1 || query.limit > 200)) {
19837
+ throw new Error("Page limit must be 1\u2013200");
19838
+ }
19839
+ const params = new URLSearchParams();
19840
+ for (const key of [
19841
+ "cursor",
19842
+ "limit",
19843
+ "include_deleted",
19844
+ "include_archived",
19845
+ "include_quarantined",
19846
+ "include_superseded",
19847
+ "include_embeddings"
19848
+ ]) {
19849
+ if (query[key] !== void 0) params.set(key, String(query[key]));
19850
+ }
19851
+ const page = await request("/memories?" + params.toString(), {}, signal);
19852
+ if (!record(page) || !Array.isArray(page.items) || page.next_cursor !== void 0 && typeof page.next_cursor !== "string") {
19853
+ throw new Error("Invalid nearby private-memory page");
19854
+ }
19855
+ return {
19856
+ ...await decodeAll(page.items),
19857
+ ...page.next_cursor !== void 0 && { next_cursor: page.next_cursor }
19858
+ };
19859
+ },
19860
+ put: async (memory, expectedVersion, signal) => {
19861
+ const write = await prepareWrite(memory, expectedVersion, signal);
19862
+ return decodeCommitted(
19863
+ await request(
19864
+ memoryPath(write.body.memory.memory_id),
19865
+ {
19866
+ method: "PUT",
19867
+ body: JSON.stringify({ key_id: options.keyId, ...write.body })
19868
+ },
19869
+ signal
19870
+ ),
19871
+ write
19872
+ );
19873
+ },
19874
+ putMany: async (writes, signal) => {
19875
+ if (writes.length < 1 || writes.length > 50 || new Set(writes.map((w) => w.memory.memory_id)).size !== writes.length)
19876
+ throw new Error("Batch must contain 1\u201350 distinct memory ids");
19877
+ const prepared = await Promise.all(
19878
+ writes.map((w) => prepareWrite(w.memory, w.expectedVersion, signal))
19879
+ );
19880
+ const result = await request(
19881
+ "/memories/batch",
19882
+ {
19883
+ method: "POST",
19884
+ body: JSON.stringify({ key_id: options.keyId, writes: prepared.map((w) => w.body) })
19885
+ },
19886
+ signal
19887
+ );
19888
+ if (!record(result) || !Array.isArray(result.items) || result.items.length !== prepared.length)
19889
+ throw new Error("Invalid nearby batch response");
19890
+ return Promise.all(result.items.map((item, i) => decodeCommitted(item, prepared[i])));
19891
+ },
19892
+ candidateSet,
19893
+ candidates: async (embedding, candidateOptions = {}) => decodeAll((await fetchCandidates(embedding, candidateOptions, false)).items)
19894
+ };
19895
+ }
19896
+
19897
+ // src/lib/memory/store/remotePipeline.ts
19898
+ var import_uuid4 = require("uuid");
19899
+ init_logger();
19900
+ function storedVector(vector) {
19901
+ if (!Array.isArray(vector) || vector.length !== 1536 && vector.length !== 4096 || vector.some((v) => !Number.isFinite(v)))
19902
+ throw new Error("Remote memories require a finite 1536/4096-dimensional vector");
19903
+ const out = vector.slice(0, 1536);
19904
+ const norm = Math.sqrt(out.reduce((sum, v) => sum + v * v, 0));
19905
+ if (!norm) throw new Error("Remote query/content vector has no direction after MRL truncation");
19906
+ return out.map((v) => v / norm);
19907
+ }
19908
+ function sourceIds(value) {
19909
+ if (!value) return [];
19910
+ try {
19911
+ const parsed = JSON.parse(value);
19912
+ return Array.isArray(parsed) ? parsed.filter((id) => typeof id === "string") : [];
19913
+ } catch {
19914
+ return [];
19915
+ }
19916
+ }
19917
+ function stored(row) {
19918
+ return {
19919
+ uniqueId: row.memory_id,
19920
+ content: row.content,
19921
+ scope: row.scope,
19922
+ folderId: row.folder_id ?? null,
19923
+ userId: null,
19924
+ embedding: row.embedding ? JSON.stringify(row.embedding) : null,
19925
+ embeddingModel: row.embedding_model ?? null,
19926
+ sourceChunkIds: row.source_chunk_ids === void 0 ? null : sourceIds(row.source_chunk_ids),
19927
+ proofCount: row.proof_count ?? null,
19928
+ source: row.source ?? null,
19929
+ media: parseMedia(row.media),
19930
+ eventTimeStart: row.event_time_start ?? null,
19931
+ eventTimeEnd: row.event_time_end ?? null,
19932
+ eventTimeKind: row.event_time_kind ?? null,
19933
+ topicsUserManaged: row.topics_user_managed ?? false,
19934
+ topics: parseTopics(row.topics),
19935
+ topicsUpdatedAt: row.topics_updated_at ?? null,
19936
+ topicsExtractedAt: row.topics_extracted_at ?? null,
19937
+ topicsExtractedVersion: row.topics_extracted_version ?? null,
19938
+ supersededBy: row.superseded_by ?? null,
19939
+ supersededAt: row.superseded_at ?? null,
19940
+ lastObservedAt: row.last_observed_at ?? null,
19941
+ factType: row.fact_type ?? null,
19942
+ archivedAt: row.archived_at ?? null,
19943
+ trustTier: row.trust_tier ?? null,
19944
+ visibility: row.visibility === "public" ? "public" : "private",
19945
+ twinOptIn: row.twin_opt_in ?? false,
19946
+ publishedAt: row.published_at ?? null,
19947
+ geohash: row.geohash ?? null,
19948
+ createdAt: new Date(row.created_at),
19949
+ updatedAt: new Date(row.updated_at),
19950
+ isDeleted: row.is_deleted
19951
+ };
19952
+ }
19953
+ function createRemoteMemoryPipeline(options) {
19954
+ const { persistence, embeddingOptions } = options;
19955
+ const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
19956
+ const operation = (mode) => {
19957
+ const rejectUndecryptable = (failed) => {
19958
+ if (!failed.length) return;
19959
+ if (mode === "retain")
19960
+ throw new Error(
19961
+ `Remote memories could not decrypt ${failed.length} candidate row(s); refusing to retain until they are repaired`
19962
+ );
19963
+ getLogger().warn(
19964
+ `[memory/remote] Skipping ${failed.length} undecryptable candidate row(s)`,
19965
+ failed.map((failure) => failure.memory_id)
19966
+ );
19967
+ };
19968
+ const snapshots = /* @__PURE__ */ new Map();
19969
+ const remember = (items) => {
19970
+ items.forEach((item) => snapshots.set(item.memory.memory_id, item));
19971
+ return items.map((item) => stored(item.memory));
19972
+ };
19973
+ const get = async (id) => {
19974
+ const snapshot = snapshots.get(id) ?? await persistence.get(id);
19975
+ if (!snapshot || snapshot.memory.is_deleted || snapshot.memory.superseded_by) return null;
19976
+ snapshots.set(id, snapshot);
19977
+ return stored(snapshot.memory);
19978
+ };
19979
+ const prepare = async (query, search = {}) => {
19980
+ if (search.folderId !== void 0)
19981
+ throw new Error("Remote memories do not support folder filters");
19982
+ const facets = normalizeSubQueries(search.subQueries);
19983
+ const facetQueries = facets.length >= 2 ? facets : [];
19984
+ const start = Date.now();
19985
+ const budgetMs = search.queryEmbedTotalTimeoutMs ?? 8e3;
19986
+ const embed = (texts) => generateEmbeddings(texts, {
19987
+ ...embeddingOptions,
19988
+ totalTimeoutMs: budgetMs
19989
+ });
19990
+ const embedFacets = async () => {
19991
+ if (!facetQueries.length) return [];
19992
+ try {
19993
+ const vectors2 = await embed(facetQueries);
19994
+ if (vectors2.length !== facetQueries.length)
19995
+ throw new Error("Incomplete facet embeddings");
19996
+ return vectors2.map(storedVector);
19997
+ } catch (error) {
19998
+ getLogger().warn(
19999
+ "[memory/remote] Facet embeddings unavailable; using primary query",
20000
+ error
20001
+ );
20002
+ return [];
20003
+ }
20004
+ };
20005
+ const [primary, facetEmbeddings] = await Promise.all([
20006
+ search.queryEmbedding ?? embed([query]).then((vectors2) => vectors2[0]),
20007
+ embedFacets()
20008
+ ]);
20009
+ const queryEmbedding = storedVector(primary);
20010
+ const queryEmbedMs = Date.now() - start;
20011
+ const graph = search.entityRanking ?? [];
20012
+ const temporal = search.temporalRanking ?? [];
20013
+ const forced = /* @__PURE__ */ new Set();
20014
+ for (let i = 0; i < Math.max(graph.length, temporal.length) && forced.size < 100; i++) {
20015
+ if (graph[i] !== void 0) forced.add(graph[i]);
20016
+ if (forced.size < 100 && temporal[i] !== void 0) forced.add(temporal[i]);
20017
+ }
20018
+ const forceIds = [...forced];
20019
+ const windowOptions = (i, signal) => ({
20020
+ limit: Math.min(100, Math.max((search.limit ?? 8) * 3, 30)),
20021
+ force_ids: i === 0 ? forceIds : [],
20022
+ ...search.scopes && { scopes: search.scopes },
20023
+ ...search.factTypes && { fact_types: search.factTypes },
20024
+ ...search.memoryIds !== void 0 && { memory_ids: search.memoryIds },
20025
+ include_archived: search.includeArchived,
20026
+ embedding_model: model,
20027
+ ...signal && { signal }
20028
+ });
20029
+ const vectors = [queryEmbedding, ...facetEmbeddings];
20030
+ let windows;
20031
+ if (mode === "retain") {
20032
+ windows = await Promise.all(
20033
+ vectors.map((embedding, i) => persistence.candidateSet(embedding, windowOptions(i)))
20034
+ );
20035
+ } else {
20036
+ const deadline = new AbortController();
20037
+ const timer = setTimeout(
20038
+ () => deadline.abort(
20039
+ new RemoteMemoryError("Remote recall exceeded its query budget", 408, "timeout")
20040
+ ),
20041
+ Math.max(0, start + budgetMs - Date.now())
20042
+ );
20043
+ try {
20044
+ windows = await Promise.all(
20045
+ vectors.map(
20046
+ (embedding, i) => persistence.candidates(embedding, windowOptions(i, deadline.signal))
20047
+ )
20048
+ );
20049
+ } finally {
20050
+ clearTimeout(timer);
20051
+ }
20052
+ }
20053
+ rejectUndecryptable([
20054
+ ...new Map(
20055
+ windows.flatMap((window2) => window2.failed).map((failure) => [failure.memory_id, failure])
20056
+ ).values()
20057
+ ]);
20058
+ const items = [
20059
+ ...new Map(
20060
+ windows.flatMap((window2) => window2.items).map((item) => [item.memory.memory_id, item])
20061
+ ).values()
20062
+ ];
20063
+ const memories = remember(items);
20064
+ return {
20065
+ memories,
20066
+ embeddedItems: memories.map((memory) => ({
20067
+ id: memory.uniqueId,
20068
+ content: memory.content,
20069
+ embedding: JSON.parse(memory.embedding ?? "[]"),
20070
+ createdAt: memory.createdAt,
20071
+ updatedAt: memory.updatedAt,
20072
+ proofCount: memory.proofCount,
20073
+ lastObservedAt: memory.lastObservedAt,
20074
+ eventTimeStart: memory.eventTimeStart,
20075
+ eventTimeEnd: memory.eventTimeEnd,
20076
+ eventTimeKind: memory.eventTimeKind === "point" || memory.eventTimeKind === "range" || memory.eventTimeKind === "ongoing" ? memory.eventTimeKind : null,
20077
+ factType: memory.factType,
20078
+ sourceChunkIds: memory.sourceChunkIds
20079
+ })),
20080
+ queryEmbedding,
20081
+ facetEmbeddings,
20082
+ vaultSize: Math.max(windows[0].total_count ?? 0, items.length),
20083
+ embeddingFailure: windows.some((window2) => (window2.unavailable_count ?? 0) > 0),
20084
+ embeddingsUnavailable: (windows[0].total_count ?? items.length) > 0 && !memories.some((memory) => memory.embedding),
20085
+ decryptLast: true,
20086
+ rowsDecrypted: items.length,
20087
+ queryEmbedMs,
20088
+ rowsEmbedded: 0
20089
+ };
20090
+ };
20091
+ const createRow = (input) => {
20092
+ if (input.folderId !== void 0 && input.folderId !== null)
20093
+ throw new Error("Remote memories do not support folders");
20094
+ const now = Date.now();
20095
+ return {
20096
+ memory_id: (0, import_uuid4.v7)(),
20097
+ content: input.content,
20098
+ scope: input.scope ?? "private",
20099
+ created_at: now,
20100
+ updated_at: now,
20101
+ is_deleted: false,
20102
+ ...input.embedding !== void 0 && {
20103
+ embedding: storedVector(JSON.parse(input.embedding)),
20104
+ embedding_model: input.embeddingModel
20105
+ },
20106
+ source_chunk_ids: JSON.stringify(input.sourceChunkIds ?? []),
20107
+ proof_count: input.proofCount ?? 1,
20108
+ source: input.source ?? "manual",
20109
+ ...input.eventTime && {
20110
+ event_time_start: input.eventTime.start ?? void 0,
20111
+ event_time_end: input.eventTime.end ?? void 0,
20112
+ event_time_kind: input.eventTime.kind ?? void 0
20113
+ },
20114
+ fact_type: input.factType,
20115
+ trust_tier: normalizeTrustTier(input.trustTier) ?? void 0,
20116
+ geohash: input.geohash,
20117
+ visibility: "private",
20118
+ twin_opt_in: false
20119
+ };
20120
+ };
20121
+ const write = async (memory, snapshot) => remember([await persistence.put(memory, snapshot)])[0];
20122
+ const port = {
20123
+ prepare,
20124
+ get,
20125
+ getFresh: async (id) => {
20126
+ const current = await persistence.get(id);
20127
+ return current && !current.memory.is_deleted && !current.memory.superseded_by ? stored(current.memory) : null;
20128
+ },
20129
+ tombstones: async (embedding, embeddingModel, scope, folderId) => {
20130
+ if (folderId !== void 0) throw new Error("Remote memories do not support folders");
20131
+ const window2 = await persistence.candidateSet(storedVector(embedding), {
20132
+ limit: 1,
20133
+ scopes: [scope],
20134
+ embedding_model: embeddingModel,
20135
+ strict_model: true,
20136
+ include_deleted: true,
20137
+ deleted_only: true
20138
+ });
20139
+ rejectUndecryptable(window2.failed);
20140
+ return remember(window2.items);
20141
+ },
20142
+ create: (input) => write(createRow(input), 0),
20143
+ update: async (id, patch) => {
20144
+ const existing = await get(id);
20145
+ if (!existing) return null;
20146
+ const snapshot = snapshots.get(id);
20147
+ const memory = {
20148
+ ...snapshot.memory,
20149
+ content: patch.content,
20150
+ updated_at: patch.preserveUpdatedAt ? snapshot.memory.updated_at : Date.now()
20151
+ };
20152
+ if (patch.scope !== void 0) memory.scope = patch.scope;
20153
+ if (patch.embedding === void 0 && patch.content !== snapshot.memory.content) {
20154
+ delete memory.embedding;
20155
+ delete memory.embedding_model;
20156
+ }
20157
+ if (patch.embedding !== void 0) {
20158
+ memory.embedding = patch.embedding === null ? [] : storedVector(JSON.parse(patch.embedding));
20159
+ memory.embedding_model = patch.embeddingModel ?? void 0;
20160
+ }
20161
+ const observed = sourceIds(memory.source_chunk_ids);
20162
+ const replay = !!patch.observationSourceIds?.length && patch.observationSourceIds.every((id2) => observed.includes(id2));
20163
+ if (patch.sourceChunkIds !== void 0)
20164
+ memory.source_chunk_ids = JSON.stringify(
20165
+ patch.observationSourceIds?.length ? [.../* @__PURE__ */ new Set([...observed, ...patch.sourceChunkIds])] : patch.sourceChunkIds
20166
+ );
20167
+ if (!replay) {
20168
+ if (patch.proofCountIncrement !== void 0)
20169
+ memory.proof_count = (memory.proof_count ?? 1) + patch.proofCountIncrement;
20170
+ else if (patch.proofCount !== void 0) memory.proof_count = patch.proofCount;
20171
+ if (patch.lastObservedAt !== void 0) memory.last_observed_at = patch.lastObservedAt;
20172
+ }
20173
+ if (patch.source !== void 0) memory.source = patch.source;
20174
+ if (patch.factType !== void 0) memory.fact_type = patch.factType;
20175
+ if (patch.trustTier !== void 0)
20176
+ memory.trust_tier = normalizeTrustTier(patch.trustTier) ?? void 0;
20177
+ if (patch.topicsUserManaged !== void 0)
20178
+ memory.topics_user_managed = patch.topicsUserManaged;
20179
+ if (patch.eventTime !== void 0) {
20180
+ memory.event_time_start = patch.eventTime.start ?? void 0;
20181
+ memory.event_time_end = patch.eventTime.end ?? void 0;
20182
+ memory.event_time_kind = patch.eventTime.kind ?? void 0;
20183
+ }
20184
+ if (patch.restore) memory.archived_at = void 0;
20185
+ return write(memory, snapshot);
20186
+ },
20187
+ supersede: async (id, successor) => {
20188
+ const [target, newer] = await Promise.all([get(id), get(successor)]);
20189
+ if (!target || !newer || id === successor) return false;
20190
+ const old = snapshots.get(id);
20191
+ const next = snapshots.get(successor);
20192
+ remember(
20193
+ await persistence.putMany([
20194
+ {
20195
+ memory: { ...old.memory, superseded_by: successor, superseded_at: Date.now() },
20196
+ expectedVersion: old
20197
+ },
20198
+ { memory: next.memory, expectedVersion: next }
20199
+ ])
20200
+ );
20201
+ return true;
20202
+ },
20203
+ createSuperseding: async (input, targetId) => {
20204
+ const target = await get(targetId);
20205
+ if (!target) return { created: null, retired: false };
20206
+ const snapshot = snapshots.get(targetId);
20207
+ const successor = createRow(input);
20208
+ const rows = remember(
20209
+ await persistence.putMany([
20210
+ { memory: successor, expectedVersion: 0 },
20211
+ {
20212
+ memory: {
20213
+ ...snapshot.memory,
20214
+ superseded_by: successor.memory_id,
20215
+ superseded_at: Date.now()
20216
+ },
20217
+ expectedVersion: snapshot
20218
+ }
20219
+ ])
20220
+ );
20221
+ return { created: rows[0], retired: true };
20222
+ }
20223
+ };
20224
+ return { prepare, port };
20225
+ };
20226
+ return {
20227
+ recall: async (query, recallOptions = {}) => {
20228
+ const { prepare } = operation("recall");
20229
+ return recall(
20230
+ query,
20231
+ {
20232
+ embeddingOptions,
20233
+ factSource: {
20234
+ graphRanking: options.graphRanking,
20235
+ temporalRanking: options.temporalRanking,
20236
+ search: async (text12, searchOptions) => {
20237
+ const prepared = await prepare(text12, searchOptions);
20238
+ const ranked = await rankPreparedVaultCandidates(
20239
+ text12,
20240
+ prepared,
20241
+ embeddingOptions,
20242
+ searchOptions
20243
+ );
20244
+ return {
20245
+ ...ranked,
20246
+ rankedOnCosine: prepared.memories.length > 0 && !prepared.embeddingsUnavailable,
20247
+ decryptLast: true,
20248
+ rowsDecrypted: prepared.rowsDecrypted,
20249
+ queryEmbedMs: prepared.queryEmbedMs,
20250
+ rowsEmbedded: 0
20251
+ };
20252
+ }
20253
+ }
20254
+ },
20255
+ { ...recallOptions, types: ["fact"] }
20256
+ );
20257
+ },
20258
+ retain: async (content, retainOptions) => {
20259
+ const { port } = operation("retain");
20260
+ return retainWithPersistence(
20261
+ content,
20262
+ {
20263
+ persistence: port,
20264
+ embeddingOptions,
20265
+ vaultCache: /* @__PURE__ */ new Map(),
20266
+ normalizeEmbedding: storedVector
20267
+ },
20268
+ retainOptions
20269
+ );
20270
+ }
20271
+ };
20272
+ }
20273
+
19471
20274
  // src/lib/memory/synthesizeProfile.ts
19472
20275
  init_internalFlowMarker();
19473
20276
  init_logger();
@@ -22893,7 +23696,7 @@ function useChat(options) {
22893
23696
 
22894
23697
  // src/expo/useChatStorage.ts
22895
23698
  var import_react5 = require("react");
22896
- var import_uuid5 = require("uuid");
23699
+ var import_uuid6 = require("uuid");
22897
23700
  init_clientConfig();
22898
23701
 
22899
23702
  // src/lib/chat/assembleMessages.ts
@@ -23556,9 +24359,9 @@ async function decryptMediaFields(media, address, signMessage, embeddedWalletSig
23556
24359
  }
23557
24360
 
23558
24361
  // src/lib/db/media/types.ts
23559
- var import_uuid4 = require("uuid");
24362
+ var import_uuid5 = require("uuid");
23560
24363
  function generateMediaId() {
23561
- return `media_${(0, import_uuid4.v7)()}`;
24364
+ return `media_${(0, import_uuid5.v7)()}`;
23562
24365
  }
23563
24366
 
23564
24367
  // src/lib/db/media/operations.ts
@@ -23769,10 +24572,10 @@ function extractImageModelFromToolEvents(toolCallEvents) {
23769
24572
  }
23770
24573
  return void 0;
23771
24574
  }
23772
- function storedToLlmapiMessage(stored) {
23773
- const content = [{ type: "text", text: stored.content }];
23774
- if (stored.role !== "assistant" && stored.files?.length) {
23775
- for (const file of stored.files) {
24575
+ function storedToLlmapiMessage(stored2) {
24576
+ const content = [{ type: "text", text: stored2.content }];
24577
+ if (stored2.role !== "assistant" && stored2.files?.length) {
24578
+ for (const file of stored2.files) {
23776
24579
  if (isSendableImageURL(file.url)) {
23777
24580
  content.push({
23778
24581
  type: "image_url",
@@ -23782,11 +24585,11 @@ function storedToLlmapiMessage(stored) {
23782
24585
  }
23783
24586
  }
23784
24587
  const messages = [];
23785
- if (stored.role === "assistant" && stored.toolCallEvents?.length) {
24588
+ if (stored2.role === "assistant" && stored2.toolCallEvents?.length) {
23786
24589
  messages.push({
23787
- role: stored.role,
24590
+ role: stored2.role,
23788
24591
  content: void 0,
23789
- tool_calls: stored.toolCallEvents.map((event) => ({
24592
+ tool_calls: stored2.toolCallEvents.map((event) => ({
23790
24593
  id: event.id,
23791
24594
  type: "function",
23792
24595
  function: {
@@ -23795,7 +24598,7 @@ function storedToLlmapiMessage(stored) {
23795
24598
  }
23796
24599
  }))
23797
24600
  });
23798
- for (const event of stored.toolCallEvents) {
24601
+ for (const event of stored2.toolCallEvents) {
23799
24602
  if (event.id && event.output !== void 0 && event.output !== null) {
23800
24603
  messages.push({
23801
24604
  role: "tool",
@@ -23804,14 +24607,14 @@ function storedToLlmapiMessage(stored) {
23804
24607
  });
23805
24608
  }
23806
24609
  }
23807
- 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();
24610
+ 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();
23808
24611
  messages.push({
23809
- role: stored.role,
24612
+ role: stored2.role,
23810
24613
  content: [{ type: "text", text: postToolText }]
23811
24614
  });
23812
24615
  } else {
23813
24616
  messages.push({
23814
- role: stored.role,
24617
+ role: stored2.role,
23815
24618
  content
23816
24619
  });
23817
24620
  }
@@ -24518,7 +25321,7 @@ function useChatStorage(options) {
24518
25321
  };
24519
25322
  };
24520
25323
  pendingResumeRef.current = null;
24521
- const effectiveAssistantUniqueId = assistantUniqueId ?? (resumable ? `msg_${(0, import_uuid5.v7)()}` : void 0);
25324
+ const effectiveAssistantUniqueId = assistantUniqueId ?? (resumable ? `msg_${(0, import_uuid6.v7)()}` : void 0);
24522
25325
  const embedToolText = (text12, mask, masked, token) => {
24523
25326
  const opts = {
24524
25327
  getToken: token,
@@ -25036,7 +25839,7 @@ function useChatStorage(options) {
25036
25839
  const detachedResult = result;
25037
25840
  if (detachedResult.detached) {
25038
25841
  recordToolSetTurn(database, convId, matchedToolSets);
25039
- const rowId = effectiveAssistantUniqueId ?? `msg_${(0, import_uuid5.v7)()}`;
25842
+ const rowId = effectiveAssistantUniqueId ?? `msg_${(0, import_uuid6.v7)()}`;
25040
25843
  pendingResumeRef.current = {
25041
25844
  handle: detachedResult.resume ?? null,
25042
25845
  convId,
@@ -25556,6 +26359,7 @@ function useChatStorage(options) {
25556
26359
  QueueManager,
25557
26360
  RECALL_MAX_LIMIT,
25558
26361
  RECALL_TOOL_NAME,
26362
+ RemoteMemoryError,
25559
26363
  RerankerUnavailableError,
25560
26364
  SDK_SCHEMA_VERSION,
25561
26365
  SHORT_TTL_MS,
@@ -25619,6 +26423,8 @@ function useChatStorage(options) {
25619
26423
  createNotionTools,
25620
26424
  createPlatformCursorStore,
25621
26425
  createRecallTool,
26426
+ createRemoteMemoryPersistence,
26427
+ createRemoteMemoryPipeline,
25622
26428
  createStockPricePreProcessor,
25623
26429
  createStreamingDeAnonymizer,
25624
26430
  createVaultEmbeddingCache,