@anuma/sdk 6.34.0 → 6.36.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.
@@ -89,9 +89,9 @@ function createSseClient({
89
89
  if (done) break;
90
90
  buffer += value;
91
91
  buffer = buffer.replace(/\r\n?/g, "\n");
92
- const chunks = buffer.split("\n\n");
93
- buffer = chunks.pop() ?? "";
94
- for (const chunk of chunks) {
92
+ const chunks2 = buffer.split("\n\n");
93
+ buffer = chunks2.pop() ?? "";
94
+ for (const chunk of chunks2) {
95
95
  const lines = chunk.split("\n");
96
96
  const dataLines = [];
97
97
  let eventName;
@@ -4731,14 +4731,14 @@ async function updateMessageEmbeddingOp(ctx, uniqueId, vector, embeddingModel) {
4731
4731
  });
4732
4732
  return messageToStored(message, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
4733
4733
  }
4734
- async function updateMessageChunksOp(ctx, uniqueId, chunks, embeddingModel) {
4734
+ async function updateMessageChunksOp(ctx, uniqueId, chunks2, embeddingModel) {
4735
4735
  let message;
4736
4736
  try {
4737
4737
  message = await ctx.messagesCollection.find(uniqueId);
4738
4738
  } catch {
4739
4739
  return null;
4740
4740
  }
4741
- const storedChunks = chunks.map(({ text: _text, ...rest }) => rest);
4741
+ const storedChunks = chunks2.map(({ text: _text, ...rest }) => rest);
4742
4742
  await ctx.database.write(async () => {
4743
4743
  await message.update((msg) => {
4744
4744
  msg._setRaw("chunks", JSON.stringify(storedChunks));
@@ -4782,12 +4782,12 @@ async function stripLegacyChunkTextOp(ctx) {
4782
4782
  const messages = await ctx.messagesCollection.query(Q.where("id", Q.oneOf(changedIds))).fetch();
4783
4783
  const updates = messages.flatMap((message) => {
4784
4784
  const raw = message._raw;
4785
- const chunks = chunksWithoutText(raw.chunks);
4786
- if (!chunks) return [];
4785
+ const chunks2 = chunksWithoutText(raw.chunks);
4786
+ if (!chunks2) return [];
4787
4787
  const updatedAt = raw.updated_at;
4788
4788
  return [
4789
4789
  message.prepareUpdate((msg) => {
4790
- msg._setRaw("chunks", JSON.stringify(chunks));
4790
+ msg._setRaw("chunks", JSON.stringify(chunks2));
4791
4791
  msg._setRaw("updated_at", updatedAt);
4792
4792
  })
4793
4793
  ];
@@ -4997,15 +4997,15 @@ async function searchChunksOp(ctx, queryVector, options) {
4997
4997
  }
4998
4998
  continue;
4999
4999
  }
5000
- const chunks = await readRawJsonField(message, "chunks", ctx.walletAddress);
5001
- if (chunks && chunks.length > 0) {
5002
- const vectors = chunks.map(
5000
+ const chunks2 = await readRawJsonField(message, "chunks", ctx.walletAddress);
5001
+ if (chunks2 && chunks2.length > 0) {
5002
+ const vectors = chunks2.map(
5003
5003
  (chunk) => decodeChunkVector(chunk.vector, () => {
5004
5004
  unreadableVectors++;
5005
5005
  })
5006
5006
  );
5007
5007
  chunkCache?.set(message.id, { version, chunks: vectors });
5008
- for (let ci = 0; ci < chunks.length; ci++) {
5008
+ for (let ci = 0; ci < chunks2.length; ci++) {
5009
5009
  const vec = vectors[ci];
5010
5010
  if (vec.length === 0) continue;
5011
5011
  const similarity = cosineSimilarity(queryVector, vec);
@@ -5013,7 +5013,7 @@ async function searchChunksOp(ctx, queryVector, options) {
5013
5013
  candidates.push({
5014
5014
  message,
5015
5015
  similarity,
5016
- chunkTextSource: { kind: "chunk", chunk: chunks[ci], siblings: chunks }
5016
+ chunkTextSource: { kind: "chunk", chunk: chunks2[ci], siblings: chunks2 }
5017
5017
  });
5018
5018
  }
5019
5019
  }
@@ -5190,7 +5190,7 @@ function chunkText(text12, options) {
5190
5190
  ];
5191
5191
  }
5192
5192
  const sentences = splitIntoSentences(text12);
5193
- const chunks = [];
5193
+ const chunks2 = [];
5194
5194
  let currentChunkSentences = [];
5195
5195
  let currentChunkStart = 0;
5196
5196
  let currentOffset = 0;
@@ -5204,7 +5204,7 @@ function chunkText(text12, options) {
5204
5204
  if (sentence.length > chunkSize) {
5205
5205
  if (currentChunkSentences.length > 0) {
5206
5206
  const chunkText2 = currentChunkSentences.join(" ");
5207
- chunks.push({
5207
+ chunks2.push({
5208
5208
  text: chunkText2,
5209
5209
  startOffset: currentChunkStart,
5210
5210
  endOffset: currentOffset
@@ -5215,7 +5215,7 @@ function chunkText(text12, options) {
5215
5215
  const chunkEnd = Math.min(j + chunkSize, sentence.length);
5216
5216
  const chunk = sentence.slice(j, chunkEnd);
5217
5217
  if (chunk.length >= minChunkSize) {
5218
- chunks.push({
5218
+ chunks2.push({
5219
5219
  text: chunk,
5220
5220
  startOffset: sentenceStart + j,
5221
5221
  endOffset: sentenceStart + chunkEnd
@@ -5229,7 +5229,7 @@ function chunkText(text12, options) {
5229
5229
  const currentText = currentChunkSentences.join(" ");
5230
5230
  const potentialLength = currentText.length + (currentText ? 1 : 0) + sentence.length;
5231
5231
  if (potentialLength > chunkSize && currentChunkSentences.length > 0) {
5232
- chunks.push({
5232
+ chunks2.push({
5233
5233
  text: currentText,
5234
5234
  startOffset: currentChunkStart,
5235
5235
  endOffset: currentOffset
@@ -5260,14 +5260,14 @@ function chunkText(text12, options) {
5260
5260
  if (currentChunkSentences.length > 0) {
5261
5261
  const chunkText2 = currentChunkSentences.join(" ");
5262
5262
  if (chunkText2.length >= minChunkSize) {
5263
- chunks.push({
5263
+ chunks2.push({
5264
5264
  text: chunkText2,
5265
5265
  startOffset: currentChunkStart,
5266
5266
  endOffset: text12.length
5267
5267
  });
5268
5268
  }
5269
5269
  }
5270
- if (chunks.length === 0) {
5270
+ if (chunks2.length === 0) {
5271
5271
  const trimmedText = text12.trim();
5272
5272
  if (trimmedText.length > 0) {
5273
5273
  return [
@@ -5279,7 +5279,7 @@ function chunkText(text12, options) {
5279
5279
  ];
5280
5280
  }
5281
5281
  }
5282
- return chunks;
5282
+ return chunks2;
5283
5283
  }
5284
5284
  function shouldChunkMessage(content, chunkSize = DEFAULT_CHUNK_SIZE) {
5285
5285
  return content.length > chunkSize;
@@ -5497,18 +5497,18 @@ async function embedMany(texts, options, outer) {
5497
5497
  outer
5498
5498
  );
5499
5499
  } else {
5500
- const chunks = [];
5500
+ const chunks2 = [];
5501
5501
  for (let i = 0; i < uncachedTexts.length; i += chunkSize) {
5502
- chunks.push(uncachedTexts.slice(i, i + chunkSize));
5502
+ chunks2.push(uncachedTexts.slice(i, i + chunkSize));
5503
5503
  }
5504
- const allEmbeddings = new Array(chunks.length);
5504
+ const allEmbeddings = new Array(chunks2.length);
5505
5505
  let nextIndex = 0;
5506
5506
  const worker = async () => {
5507
- while (nextIndex < chunks.length) {
5507
+ while (nextIndex < chunks2.length) {
5508
5508
  if (outer?.aborted) throw outer.reason;
5509
5509
  const idx = nextIndex++;
5510
5510
  allEmbeddings[idx] = await generateEmbeddingsBatch(
5511
- chunks[idx],
5511
+ chunks2[idx],
5512
5512
  headers,
5513
5513
  baseUrl,
5514
5514
  embeddingModel,
@@ -5520,7 +5520,7 @@ async function embedMany(texts, options, outer) {
5520
5520
  }
5521
5521
  };
5522
5522
  const workers = Array.from(
5523
- { length: Math.min(DEFAULT_EMBEDDING_BATCH_CONCURRENCY, chunks.length) },
5523
+ { length: Math.min(DEFAULT_EMBEDDING_BATCH_CONCURRENCY, chunks2.length) },
5524
5524
  () => worker()
5525
5525
  );
5526
5526
  await Promise.all(workers);
@@ -11318,6 +11318,15 @@ __decorateClass([
11318
11318
  __decorateClass([
11319
11319
  text6("scope")
11320
11320
  ], VaultMemory.prototype, "scope", 2);
11321
+ __decorateClass([
11322
+ field5("kind")
11323
+ ], VaultMemory.prototype, "kind", 2);
11324
+ __decorateClass([
11325
+ field5("kind_value")
11326
+ ], VaultMemory.prototype, "kindValue", 2);
11327
+ __decorateClass([
11328
+ field5("level")
11329
+ ], VaultMemory.prototype, "level", 2);
11321
11330
  __decorateClass([
11322
11331
  field5("folder_id")
11323
11332
  ], VaultMemory.prototype, "folderId", 2);
@@ -11543,7 +11552,7 @@ __decorateClass([
11543
11552
  ], VaultFolder.prototype, "context", 2);
11544
11553
 
11545
11554
  // src/lib/db/schema.ts
11546
- var SDK_SCHEMA_VERSION = 47;
11555
+ var SDK_SCHEMA_VERSION = 48;
11547
11556
  var sdkSchema = appSchema2({
11548
11557
  version: SDK_SCHEMA_VERSION,
11549
11558
  tables: [
@@ -11638,6 +11647,9 @@ var sdkSchema = appSchema2({
11638
11647
  columns: [
11639
11648
  { name: "content", type: "string" },
11640
11649
  { name: "scope", type: "string", isIndexed: true },
11650
+ { name: "kind", type: "string", isOptional: true, isIndexed: true },
11651
+ { name: "kind_value", type: "string", isOptional: true },
11652
+ { name: "level", type: "string", isOptional: true, isIndexed: true },
11641
11653
  { name: "folder_id", type: "string", isOptional: true, isIndexed: true },
11642
11654
  { name: "created_at", type: "number", isIndexed: true },
11643
11655
  { name: "updated_at", type: "number", isIndexed: true },
@@ -12314,6 +12326,22 @@ var sdkMigrations = schemaMigrations2({
12314
12326
  ]
12315
12327
  })
12316
12328
  ]
12329
+ },
12330
+ {
12331
+ toVersion: 48,
12332
+ steps: [
12333
+ addColumns2({
12334
+ table: "memory_vault",
12335
+ columns: [
12336
+ { name: "kind", type: "string", isOptional: true, isIndexed: true },
12337
+ { name: "kind_value", type: "string", isOptional: true },
12338
+ { name: "level", type: "string", isOptional: true, isIndexed: true }
12339
+ ]
12340
+ }),
12341
+ unsafeExecuteSql(
12342
+ "UPDATE memory_vault SET level = CASE WHEN scope IN ('shared', 'public') THEN 'matching' ELSE 'private' END WHERE level IS NULL;"
12343
+ )
12344
+ ]
12317
12345
  }
12318
12346
  ]
12319
12347
  });
@@ -12835,8 +12863,8 @@ var WatermelonChatStorageAdapter = class {
12835
12863
  updateMessageEmbedding(uniqueId, vector, embeddingModel) {
12836
12864
  return updateMessageEmbeddingOp(this.ctx, uniqueId, vector, embeddingModel);
12837
12865
  }
12838
- updateMessageChunks(uniqueId, chunks, embeddingModel) {
12839
- return updateMessageChunksOp(this.ctx, uniqueId, chunks, embeddingModel);
12866
+ updateMessageChunks(uniqueId, chunks2, embeddingModel) {
12867
+ return updateMessageChunksOp(this.ctx, uniqueId, chunks2, embeddingModel);
12840
12868
  }
12841
12869
  updateMessageError(uniqueId, error) {
12842
12870
  return updateMessageErrorOp(this.ctx, uniqueId, error);
@@ -13450,13 +13478,54 @@ async function decryptVaultMemoryFields(memory, address, signMessage, embeddedWa
13450
13478
  }
13451
13479
  }
13452
13480
  const decryptedContent = await decryptField(memory.content, address);
13481
+ const decryptedKindValue = typeof memory.kindValue === "string" ? await decryptField(memory.kindValue, address) : memory.kindValue;
13453
13482
  return {
13454
13483
  ...memory,
13455
- content: decryptedContent
13484
+ content: decryptedContent,
13485
+ ...decryptedKindValue !== void 0 && { kindValue: decryptedKindValue }
13456
13486
  };
13457
13487
  }
13458
13488
 
13459
13489
  // src/lib/db/memoryVault/types.ts
13490
+ var MEMORY_KINDS = [
13491
+ "display_name",
13492
+ "birth_date",
13493
+ "bio",
13494
+ "occupation",
13495
+ "interest",
13496
+ "gender",
13497
+ "height_cm",
13498
+ "looking_for",
13499
+ "politics",
13500
+ "religion",
13501
+ "ethnicity",
13502
+ "smoking",
13503
+ "drinking",
13504
+ "exercise",
13505
+ "sexuality",
13506
+ "prompt"
13507
+ ];
13508
+ var MEMORY_LEVELS = ["private", "matching", "profile"];
13509
+ var MemoryLevelError = class extends Error {
13510
+ constructor(message) {
13511
+ super(message);
13512
+ this.name = "MemoryLevelError";
13513
+ }
13514
+ };
13515
+ var PUBLISHED_SCOPES = /* @__PURE__ */ new Set(["shared", "public"]);
13516
+ function levelFromScope(scope) {
13517
+ return typeof scope === "string" && PUBLISHED_SCOPES.has(scope) ? "matching" : "private";
13518
+ }
13519
+ function scopeForLevel(level) {
13520
+ return level === "private" ? "private" : "shared";
13521
+ }
13522
+ function resolveMemoryLevel(level, scope) {
13523
+ return typeof level === "string" && MEMORY_LEVELS.includes(level) ? level : levelFromScope(scope);
13524
+ }
13525
+ function levelForScopeChange(current, nextScope) {
13526
+ const implied = levelFromScope(nextScope);
13527
+ return implied === "matching" && resolveMemoryLevel(current.level, current.scope) === "profile" ? "profile" : implied;
13528
+ }
13460
13529
  function parseMedia(value) {
13461
13530
  if (typeof value !== "string" || value === "") return null;
13462
13531
  try {
@@ -13486,6 +13555,56 @@ function visibilityConditions(requested) {
13486
13555
  if (excluded.length === 0) return [];
13487
13556
  return [Q8.or(Q8.where("visibility", null), Q8.where("visibility", Q8.notIn(excluded)))];
13488
13557
  }
13558
+ function isKinded(record2) {
13559
+ return record2.kind !== null && record2.kind !== void 0;
13560
+ }
13561
+ function assertValidKindLevel(kind, level) {
13562
+ const hasKind = kind !== null && kind !== void 0;
13563
+ if (hasKind && !MEMORY_KINDS.includes(kind)) {
13564
+ throw new MemoryLevelError(`Unknown memory kind: ${kind}`);
13565
+ }
13566
+ if (level !== void 0 && !MEMORY_LEVELS.includes(level)) {
13567
+ throw new MemoryLevelError(`Unknown memory level: ${level}`);
13568
+ }
13569
+ if (level === "profile" && !hasKind) {
13570
+ throw new MemoryLevelError("Only a memory with a kind can be at level 'profile'");
13571
+ }
13572
+ }
13573
+ function resolveCreateLevel(opts) {
13574
+ if (opts.level !== void 0) return { level: opts.level, scope: scopeForLevel(opts.level) };
13575
+ if (opts.scope !== void 0) return { level: levelFromScope(opts.scope), scope: opts.scope };
13576
+ return { level: "private", scope: "private" };
13577
+ }
13578
+ async function encryptKindValue(ctx, value) {
13579
+ if (typeof value !== "string" || !ctx.walletAddress || !ctx.signMessage) return value;
13580
+ return encryptVaultMemoryContent(
13581
+ value,
13582
+ ctx.walletAddress,
13583
+ ctx.signMessage,
13584
+ ctx.embeddedWalletSigner
13585
+ );
13586
+ }
13587
+ function levelConditions(requested) {
13588
+ if (!requested?.length) return [];
13589
+ const published = ["shared", "public"];
13590
+ const wantsMatching = requested.includes("matching");
13591
+ const wantsPrivate = requested.includes("private");
13592
+ const unresolved = Q8.or(Q8.where("level", null), Q8.where("level", Q8.notIn([...MEMORY_LEVELS])));
13593
+ const byLevel = Q8.where("level", Q8.oneOf([...requested]));
13594
+ if (wantsMatching && wantsPrivate) return [Q8.or(byLevel, unresolved)];
13595
+ if (wantsMatching) {
13596
+ return [Q8.or(byLevel, Q8.and(unresolved, Q8.where("scope", Q8.oneOf(published))))];
13597
+ }
13598
+ if (wantsPrivate) {
13599
+ return [
13600
+ Q8.or(
13601
+ byLevel,
13602
+ Q8.and(unresolved, Q8.or(Q8.where("scope", null), Q8.where("scope", Q8.notIn(published))))
13603
+ )
13604
+ ];
13605
+ }
13606
+ return [byLevel];
13607
+ }
13489
13608
  function isOwnedByCtxUser(ctx, record2) {
13490
13609
  return ctx.userId === void 0 || record2.userId === ctx.userId;
13491
13610
  }
@@ -13529,6 +13648,9 @@ function vaultMemoryToStoredRaw(memory) {
13529
13648
  uniqueId: memory.id,
13530
13649
  content: memory.content,
13531
13650
  scope: memory.scope,
13651
+ kind: memory.kind ?? null,
13652
+ kindValue: memory.kindValue ?? null,
13653
+ level: resolveMemoryLevel(memory.level, memory.scope),
13532
13654
  folderId: memory.folderId ?? null,
13533
13655
  userId: memory.userId ?? null,
13534
13656
  embedding: memory.embedding ?? null,
@@ -13567,9 +13689,13 @@ async function vaultMemoryToStored(memory, walletAddress, signMessage, embeddedW
13567
13689
  }
13568
13690
  return raw;
13569
13691
  }
13570
- function populateNewVaultMemory(record2, ctx, opts, encryptedContent) {
13692
+ function populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue) {
13693
+ const { level, scope } = resolveCreateLevel(opts);
13571
13694
  record2._setRaw("content", encryptedContent);
13572
- record2._setRaw("scope", opts.scope ?? "private");
13695
+ record2._setRaw("scope", scope);
13696
+ record2._setRaw("level", level);
13697
+ record2._setRaw("kind", opts.kind ?? null);
13698
+ record2._setRaw("kind_value", encryptedKindValue ?? null);
13573
13699
  record2._setRaw("folder_id", opts.folderId ?? null);
13574
13700
  record2._setRaw("user_id", ctx.userId ?? null);
13575
13701
  record2._setRaw("is_deleted", false);
@@ -13603,6 +13729,8 @@ function populateNewVaultMemory(record2, ctx, opts, encryptedContent) {
13603
13729
  }
13604
13730
  }
13605
13731
  async function createVaultMemoryOp(ctx, opts) {
13732
+ assertValidKindLevel(opts.kind, resolveCreateLevel(opts).level);
13733
+ const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
13606
13734
  const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
13607
13735
  opts.content,
13608
13736
  ctx.walletAddress,
@@ -13613,13 +13741,15 @@ async function createVaultMemoryOp(ctx, opts) {
13613
13741
  if (ctx.canWrite && !await ctx.canWrite())
13614
13742
  throw new Error("Memory source is no longer eligible");
13615
13743
  return ctx.vaultMemoryCollection.create(
13616
- (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent)
13744
+ (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue)
13617
13745
  );
13618
13746
  });
13619
13747
  return vaultMemoryToStored(created, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
13620
13748
  }
13621
13749
  async function createSupersedingMemoryOp(ctx, opts, targetId) {
13622
13750
  if (!targetId) return { created: null, retired: false };
13751
+ assertValidKindLevel(opts.kind, resolveCreateLevel(opts).level);
13752
+ const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
13623
13753
  const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
13624
13754
  opts.content,
13625
13755
  ctx.walletAddress,
@@ -13636,9 +13766,10 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
13636
13766
  } catch {
13637
13767
  return;
13638
13768
  }
13639
- if (target.isDeleted || target.supersededBy || !isOwnedByCtxUser(ctx, target)) return;
13769
+ if (target.isDeleted || target.supersededBy || isKinded(target) || !isOwnedByCtxUser(ctx, target))
13770
+ return;
13640
13771
  createdRecord = await ctx.vaultMemoryCollection.create(
13641
- (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent)
13772
+ (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue)
13642
13773
  );
13643
13774
  await target.update((r) => {
13644
13775
  r._setRaw("superseded_by", createdRecord.id);
@@ -13702,6 +13833,10 @@ async function getMemoriesByEventTimeOp(ctx, windowStart, windowEnd) {
13702
13833
  }
13703
13834
  async function createVaultMemoriesBatchOp(ctx, optionsArray) {
13704
13835
  if (optionsArray.length === 0) return [];
13836
+ for (const opts of optionsArray) assertValidKindLevel(opts.kind, resolveCreateLevel(opts).level);
13837
+ const encryptedKindValues = await Promise.all(
13838
+ optionsArray.map((opts) => encryptKindValue(ctx, opts.kindValue))
13839
+ );
13705
13840
  const encryptedContents = await Promise.all(
13706
13841
  optionsArray.map(async (opts) => {
13707
13842
  if (ctx.walletAddress && ctx.signMessage) {
@@ -13720,7 +13855,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
13720
13855
  throw new Error("Memory source is no longer eligible");
13721
13856
  const prepared = optionsArray.map(
13722
13857
  (opts, i) => ctx.vaultMemoryCollection.prepareCreate(
13723
- (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i])
13858
+ (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i], encryptedKindValues[i])
13724
13859
  )
13725
13860
  );
13726
13861
  await ctx.database.batch(...prepared);
@@ -13763,6 +13898,9 @@ function vaultMemoryRawToStoredRaw(raw) {
13763
13898
  uniqueId: raw.id,
13764
13899
  content: raw.content ?? "",
13765
13900
  scope: raw.scope ?? "",
13901
+ kind: raw.kind ?? null,
13902
+ kindValue: raw.kind_value ?? null,
13903
+ level: resolveMemoryLevel(raw.level, raw.scope),
13766
13904
  folderId: raw.folder_id ?? null,
13767
13905
  userId: raw.user_id ?? null,
13768
13906
  embedding: raw.embedding ?? null,
@@ -13806,6 +13944,8 @@ async function getAllVaultMemoriesOp(ctx, options) {
13806
13944
  ...baseVaultConditions(ctx, options),
13807
13945
  ...options?.scopes?.length ? [Q8.where("scope", Q8.oneOf(options.scopes))] : [],
13808
13946
  ...visibilityConditions(options?.visibility),
13947
+ ...levelConditions(options?.levels),
13948
+ ...options?.kinds?.length ? [Q8.where("kind", Q8.oneOf(options.kinds))] : [],
13809
13949
  ...options?.folderId !== void 0 ? [Q8.where("folder_id", options.folderId)] : [],
13810
13950
  ...options?.factTypes?.length ? [Q8.where("fact_type", Q8.oneOf(options.factTypes))] : [],
13811
13951
  Q8.sortBy(options?.since ? "updated_at" : "created_at", Q8.desc),
@@ -13972,6 +14112,14 @@ async function updateVaultMemoryOp(ctx, id, opts) {
13972
14112
  try {
13973
14113
  const probe = await ctx.vaultMemoryCollection.find(id);
13974
14114
  if (probe.isDeleted || probe.supersededBy || !isOwnedByCtxUser(ctx, probe)) return null;
14115
+ if (opts.freeFormOnly && isKinded(probe)) return null;
14116
+ const levelAfter = (current) => {
14117
+ if (opts.level !== void 0) return opts.level;
14118
+ if (opts.scope === void 0) return resolveMemoryLevel(current.level, current.scope);
14119
+ return levelForScopeChange(current, opts.scope);
14120
+ };
14121
+ assertValidKindLevel(opts.kind !== void 0 ? opts.kind : probe.kind, levelAfter(probe));
14122
+ const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
13975
14123
  const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
13976
14124
  opts.content,
13977
14125
  ctx.walletAddress,
@@ -13984,10 +14132,13 @@ async function updateVaultMemoryOp(ctx, id, opts) {
13984
14132
  await ctx.database.write(async () => {
13985
14133
  if (ctx.canWrite && !await ctx.canWrite())
13986
14134
  throw new Error("Memory source is no longer eligible");
13987
- if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
14135
+ if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2) || opts.freeFormOnly && isKinded(record2)) {
13988
14136
  stale = true;
13989
14137
  return;
13990
14138
  }
14139
+ const nextKind = opts.kind !== void 0 ? opts.kind : record2.kind;
14140
+ const nextLevel = levelAfter(record2);
14141
+ assertValidKindLevel(nextKind, nextLevel);
13991
14142
  let observedSources = [];
13992
14143
  let replayedObservation = false;
13993
14144
  if (opts.observationSourceIds?.length) {
@@ -14001,8 +14152,18 @@ async function updateVaultMemoryOp(ctx, id, opts) {
14001
14152
  }
14002
14153
  await record2.update((r) => {
14003
14154
  r._setRaw("content", encryptedContent);
14004
- if (opts.scope !== void 0) {
14155
+ if (opts.level !== void 0) {
14156
+ r._setRaw("level", nextLevel);
14157
+ r._setRaw("scope", scopeForLevel(nextLevel));
14158
+ } else if (opts.scope !== void 0) {
14005
14159
  r._setRaw("scope", opts.scope);
14160
+ r._setRaw("level", nextLevel);
14161
+ }
14162
+ if (opts.kind !== void 0) {
14163
+ r._setRaw("kind", opts.kind);
14164
+ }
14165
+ if (encryptedKindValue !== void 0) {
14166
+ r._setRaw("kind_value", encryptedKindValue);
14006
14167
  }
14007
14168
  if (opts.folderId !== void 0) {
14008
14169
  r._setRaw("folder_id", opts.folderId);
@@ -14061,7 +14222,8 @@ async function updateVaultMemoryOp(ctx, id, opts) {
14061
14222
  ctx.signMessage,
14062
14223
  ctx.embeddedWalletSigner
14063
14224
  );
14064
- } catch {
14225
+ } catch (err) {
14226
+ if (err instanceof MemoryLevelError) throw err;
14065
14227
  return null;
14066
14228
  }
14067
14229
  }
@@ -14197,6 +14359,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
14197
14359
  try {
14198
14360
  const record2 = await ctx.vaultMemoryCollection.find(id);
14199
14361
  if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) return false;
14362
+ if (isKinded(record2)) return false;
14200
14363
  let successor;
14201
14364
  try {
14202
14365
  successor = await ctx.vaultMemoryCollection.find(supersededById);
@@ -14497,7 +14660,10 @@ function assertVaultScopeForSweep(ctx) {
14497
14660
  }
14498
14661
  async function getDecayCandidatesRawOp(ctx) {
14499
14662
  assertVaultScopeForSweep(ctx);
14500
- const results = await ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx, { includeArchived: true, includeQuarantined: true })).unsafeFetchRaw();
14663
+ const results = await ctx.vaultMemoryCollection.query(
14664
+ ...baseVaultConditions(ctx, { includeArchived: true, includeQuarantined: true }),
14665
+ Q8.where("kind", null)
14666
+ ).unsafeFetchRaw();
14501
14667
  return results.map((raw) => ({
14502
14668
  uniqueId: raw.id,
14503
14669
  factType: raw.fact_type ?? null,
@@ -14757,6 +14923,7 @@ async function ingestPublishedPhotoMemoriesOp(ctx, rows) {
14757
14923
  record2._raw.id = row.memoryId;
14758
14924
  record2._setRaw("content", content);
14759
14925
  record2._setRaw("scope", "shared");
14926
+ record2._setRaw("level", "matching");
14760
14927
  record2._setRaw("folder_id", null);
14761
14928
  record2._setRaw("user_id", ctx.userId ?? null);
14762
14929
  record2._setRaw("is_deleted", false);
@@ -15622,6 +15789,7 @@ async function updateVaultFolderOp(ctx, id, opts) {
15622
15789
  for (const memory of memories) {
15623
15790
  updates.push(
15624
15791
  memory.prepareUpdate((r) => {
15792
+ r._setRaw("level", levelForScopeChange(r, opts.scope));
15625
15793
  r._setRaw("scope", opts.scope);
15626
15794
  })
15627
15795
  );
@@ -15643,6 +15811,7 @@ async function deleteVaultFolderOp(ctx, id) {
15643
15811
  const preparedMemories = memories.map(
15644
15812
  (memory) => memory.prepareUpdate((r) => {
15645
15813
  r._setRaw("folder_id", null);
15814
+ r._setRaw("level", levelForScopeChange(r, "private"));
15646
15815
  r._setRaw("scope", "private");
15647
15816
  })
15648
15817
  );
@@ -15679,6 +15848,7 @@ async function moveMemoriesToFolderOp(ctx, memoryIds, folderId) {
15679
15848
  const prepared = memories.map(
15680
15849
  (memory) => memory.prepareUpdate((r) => {
15681
15850
  r._setRaw("folder_id", folderId);
15851
+ r._setRaw("level", levelForScopeChange(r, targetScope));
15682
15852
  r._setRaw("scope", targetScope);
15683
15853
  })
15684
15854
  );
@@ -17986,6 +18156,7 @@ async function retainWithPersistence(content, ctx, options = {}) {
17986
18156
  includeArchived: true,
17987
18157
  ...options.folderId !== void 0 && { folderId: options.folderId }
17988
18158
  });
18159
+ prepared = withoutKindedRows(prepared);
17989
18160
  if (prepared.embeddingFailure || prepared.embeddingsUnavailable) {
17990
18161
  throw new Error(
17991
18162
  "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."
@@ -18027,6 +18198,7 @@ async function retainWithPersistence(content, ctx, options = {}) {
18027
18198
  const resurrect = resurrectFields(existing);
18028
18199
  const updated = await ctx.persistence.update(targetId, {
18029
18200
  content: existing.content,
18201
+ freeFormOnly: true,
18030
18202
  proofCountIncrement: 1,
18031
18203
  observationSourceIds: options.sourceChunkIds,
18032
18204
  sourceChunkIds: mergedSourceIds,
@@ -18155,6 +18327,17 @@ async function retainWithPersistence(content, ctx, options = {}) {
18155
18327
  ...consolidationDecidedCreate && { consolidation: "create" }
18156
18328
  };
18157
18329
  }
18330
+ function withoutKindedRows(prepared) {
18331
+ const kinded = new Set(
18332
+ prepared.memories.filter((m) => m.kind !== null && m.kind !== void 0).map((m) => m.uniqueId)
18333
+ );
18334
+ if (kinded.size === 0) return prepared;
18335
+ return {
18336
+ ...prepared,
18337
+ memories: prepared.memories.filter((m) => !kinded.has(m.uniqueId)),
18338
+ embeddedItems: prepared.embeddedItems.filter((item) => !kinded.has(item.id))
18339
+ };
18340
+ }
18158
18341
  function unionStrings(a, b) {
18159
18342
  return [.../* @__PURE__ */ new Set([...a, ...b])];
18160
18343
  }
@@ -18254,6 +18437,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
18254
18437
  const resurrect = resurrectFields(existing);
18255
18438
  const updated = await ctx.persistence.update(decision.targetId, {
18256
18439
  content: existing.content,
18440
+ freeFormOnly: true,
18257
18441
  proofCountIncrement: 1,
18258
18442
  observationSourceIds: options.sourceChunkIds,
18259
18443
  sourceChunkIds: mergedSourceIds,
@@ -18299,6 +18483,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
18299
18483
  const resurrect = resurrectFields(existing);
18300
18484
  const updated = await ctx.persistence.update(decision.targetId, {
18301
18485
  content: decision.content,
18486
+ freeFormOnly: true,
18302
18487
  proofCountIncrement: 1,
18303
18488
  observationSourceIds: options.sourceChunkIds,
18304
18489
  sourceChunkIds: mergedSourceIds,
@@ -18342,7 +18527,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
18342
18527
  }
18343
18528
  async function assertMergeTargetGoneOrThrow(ctx, targetId) {
18344
18529
  const stillExists = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(targetId) : ctx.persistence.get(targetId));
18345
- if (stillExists) {
18530
+ if (stillExists && (stillExists.kind === null || stillExists.kind === void 0)) {
18346
18531
  throw new Error(`retain: merge into memory ${targetId} failed to persist`);
18347
18532
  }
18348
18533
  }
@@ -20984,6 +21169,65 @@ function createLocalMemoryStore(options) {
20984
21169
  };
20985
21170
  }
20986
21171
 
21172
+ // src/lib/memory/store/memoryKeys.ts
21173
+ var KEY_ID_DOMAIN = "anuma-private-memory-key-id-v1";
21174
+ var MemoryKeyError = class extends Error {
21175
+ constructor(message) {
21176
+ super(message);
21177
+ this.name = "MemoryKeyError";
21178
+ }
21179
+ };
21180
+ async function importAesKey(hex) {
21181
+ return crypto.subtle.importKey(
21182
+ "raw",
21183
+ hexToBytes(hex).buffer,
21184
+ { name: "AES-GCM" },
21185
+ false,
21186
+ ["encrypt", "decrypt"]
21187
+ );
21188
+ }
21189
+ async function deriveMemoryKeyRing(signatureHex) {
21190
+ const v3Hex = await deriveKeyFromSignatureV3(signatureHex);
21191
+ const digest = await crypto.subtle.digest(
21192
+ "SHA-256",
21193
+ new TextEncoder().encode(`${KEY_ID_DOMAIN}:${v3Hex}`)
21194
+ );
21195
+ const keyId = "v3:" + Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
21196
+ return {
21197
+ keyId,
21198
+ v3: await importAesKey(v3Hex),
21199
+ v2: await importAesKey(await deriveKeyFromSignature(signatureHex))
21200
+ };
21201
+ }
21202
+ async function decryptWith(value, rings) {
21203
+ const version = value.startsWith("enc:v3:") ? "v3" : "v2";
21204
+ for (const ring of rings) {
21205
+ try {
21206
+ return await decryptDataWithKey(value.slice(`enc:${version}:`.length), ring[version]);
21207
+ } catch {
21208
+ continue;
21209
+ }
21210
+ }
21211
+ throw new MemoryKeyError(`No supplied key decrypts this enc:${version} field`);
21212
+ }
21213
+ function memoryCipher(canonical) {
21214
+ return {
21215
+ encrypt: async (plaintext) => `enc:v3:${await encryptDataWithKey(plaintext, canonical.v3)}`,
21216
+ decrypt: async (ciphertext) => {
21217
+ if (!ciphertext.startsWith("enc:v3:") || !isEncrypted(ciphertext))
21218
+ throw new MemoryKeyError("Remote memory content must be enc:v3 ciphertext");
21219
+ return decryptWith(ciphertext, [canonical]);
21220
+ }
21221
+ };
21222
+ }
21223
+ async function reencryptMemoryField(value, canonical, fallbacks = []) {
21224
+ const { encrypt } = memoryCipher(canonical);
21225
+ if (!value.startsWith("enc:")) return encrypt(value);
21226
+ if (!isEncrypted(value))
21227
+ throw new MemoryKeyError("Field has an encryption prefix but an invalid payload");
21228
+ return encrypt(await decryptWith(value, [canonical, ...fallbacks]));
21229
+ }
21230
+
20987
21231
  // src/lib/memory/store/remotePersistence.ts
20988
21232
  var RemoteMemoryError = class extends Error {
20989
21233
  constructor(message, status, code) {
@@ -21036,6 +21280,30 @@ var candidateListLimits = [
21036
21280
  ["memory_ids", 1e3],
21037
21281
  ["force_ids", 100]
21038
21282
  ];
21283
+ var queryListLimits = [
21284
+ ["scopes", 20],
21285
+ ["fact_types", 20],
21286
+ ["visibility", 20],
21287
+ ["memory_ids", 1e3],
21288
+ ["topics", 100]
21289
+ ];
21290
+ var queryFields = [
21291
+ "include_deleted",
21292
+ "include_archived",
21293
+ "include_quarantined",
21294
+ "include_superseded",
21295
+ "archived_only",
21296
+ "scopes",
21297
+ "fact_types",
21298
+ "visibility",
21299
+ "memory_ids",
21300
+ "topics",
21301
+ "updated_after",
21302
+ "order",
21303
+ "cursor",
21304
+ "limit",
21305
+ "include_embeddings"
21306
+ ];
21039
21307
  function record(value) {
21040
21308
  return typeof value === "object" && value !== null && !Array.isArray(value);
21041
21309
  }
@@ -21370,6 +21638,35 @@ async function createRemoteMemoryPersistence(options) {
21370
21638
  throw new Error("Invalid nearby batch response");
21371
21639
  return Promise.all(result.items.map((item, i) => decodeCommitted(item, prepared[i])));
21372
21640
  },
21641
+ query: async (queryOptions = {}) => {
21642
+ const { signal, ...query } = queryOptions;
21643
+ if (query.limit !== void 0 && (!Number.isInteger(query.limit) || query.limit < 1 || query.limit > 200))
21644
+ throw new Error("Page limit must be 1\u2013200");
21645
+ for (const [key, max] of queryListLimits) {
21646
+ const values = query[key];
21647
+ if (values && values.length > max)
21648
+ throw new Error(`Query ${key} accepts at most ${max} entries (got ${values.length})`);
21649
+ }
21650
+ const page = await request(
21651
+ "/memories/query",
21652
+ {
21653
+ method: "POST",
21654
+ body: JSON.stringify(
21655
+ Object.fromEntries(
21656
+ queryFields.filter((key) => query[key] !== void 0).map((key) => [key, query[key]])
21657
+ )
21658
+ )
21659
+ },
21660
+ signal
21661
+ );
21662
+ if (!record(page) || !Array.isArray(page.items) || page.next_cursor !== void 0 && typeof page.next_cursor !== "string" || page.changes_cursor !== void 0 && typeof page.changes_cursor !== "string")
21663
+ throw new Error("Invalid nearby private-memory page");
21664
+ return {
21665
+ ...await decodeAll(page.items),
21666
+ ...page.next_cursor !== void 0 && { next_cursor: page.next_cursor },
21667
+ ...page.changes_cursor !== void 0 && { changes_cursor: page.changes_cursor }
21668
+ };
21669
+ },
21373
21670
  candidateSet,
21374
21671
  candidates: async (embedding, candidateOptions = {}) => decodeAll((await fetchCandidates(embedding, candidateOptions, false)).items)
21375
21672
  };
@@ -21394,6 +21691,9 @@ function sourceIds(value) {
21394
21691
  return [];
21395
21692
  }
21396
21693
  }
21694
+ function isMemoryLevel(value) {
21695
+ return MEMORY_LEVELS.includes(value);
21696
+ }
21397
21697
  function stored(row) {
21398
21698
  return {
21399
21699
  uniqueId: row.memory_id,
@@ -21401,6 +21701,9 @@ function stored(row) {
21401
21701
  scope: row.scope,
21402
21702
  folderId: row.folder_id ?? null,
21403
21703
  userId: null,
21704
+ kind: row.kind ?? null,
21705
+ kindValue: row.kind_value ?? null,
21706
+ ...isMemoryLevel(row.level) && { level: row.level },
21404
21707
  embedding: row.embedding ? JSON.stringify(row.embedding) : null,
21405
21708
  embeddingModel: row.embedding_model ?? null,
21406
21709
  sourceChunkIds: row.source_chunk_ids === void 0 ? null : sourceIds(row.source_chunk_ids),
@@ -21622,7 +21925,8 @@ function createRemoteMemoryPipeline(options) {
21622
21925
  create: (input) => write(createRow(input), 0),
21623
21926
  update: async (id, patch) => {
21624
21927
  const existing = await get(id);
21625
- if (!existing) return null;
21928
+ if (!existing || patch.freeFormOnly && existing.kind !== null && existing.kind !== void 0)
21929
+ return null;
21626
21930
  const snapshot = snapshots.get(id);
21627
21931
  const memory = {
21628
21932
  ...snapshot.memory,
@@ -21751,6 +22055,489 @@ function createRemoteMemoryPipeline(options) {
21751
22055
  };
21752
22056
  }
21753
22057
 
22058
+ // src/lib/memory/store/remoteStore.ts
22059
+ import { v7 as uuidv76 } from "uuid";
22060
+ function relevant(change, options) {
22061
+ return options.includeDeleted ? change === "membership" : change !== "embedding" || !!options.embeddings;
22062
+ }
22063
+ function safely(onChange) {
22064
+ try {
22065
+ onChange();
22066
+ } catch (error) {
22067
+ getLogger().warn("[memory/remote-store] Subscriber threw:", error);
22068
+ }
22069
+ }
22070
+ var MAX_BATCH = 50;
22071
+ var MAX_QUERY_IDS = 1e3;
22072
+ var MAX_QUERY_TOPICS = 100;
22073
+ var MAX_QUERY_FILTER = 20;
22074
+ var RemoteMemoryPartialCreateError = class extends Error {
22075
+ constructor(created, cause) {
22076
+ super(`createMany stored ${created.length} memories before a batch failed`);
22077
+ this.created = created;
22078
+ this.cause = cause;
22079
+ this.name = "RemoteMemoryPartialCreateError";
22080
+ }
22081
+ };
22082
+ function warnFailed(failed) {
22083
+ if (failed.length)
22084
+ getLogger().warn(
22085
+ `[memory/remote-store] Skipping ${failed.length} undecryptable row(s)`,
22086
+ failed.map((failure) => failure.memory_id)
22087
+ );
22088
+ }
22089
+ function bounded(filters, key) {
22090
+ const values = filters[key];
22091
+ if (!values || values.length <= MAX_QUERY_FILTER) return [filters];
22092
+ return chunks(values, MAX_QUERY_FILTER).map((chunk) => ({ ...filters, [key]: chunk }));
22093
+ }
22094
+ function chunks(values, size) {
22095
+ const out = [];
22096
+ for (let i = 0; i < values.length; i += size) out.push(values.slice(i, i + size));
22097
+ return out;
22098
+ }
22099
+ function stateFilters(options) {
22100
+ return {
22101
+ include_deleted: options.includeDeleted,
22102
+ include_archived: options.includeArchived,
22103
+ include_quarantined: options.includeQuarantined,
22104
+ include_superseded: options.includeSuperseded
22105
+ };
22106
+ }
22107
+ function hidden(memory, options) {
22108
+ if (memory.trust_tier === "quarantined") return true;
22109
+ if (options.includeDeleted) return false;
22110
+ return !!memory.is_deleted || memory.archived_at !== void 0 && memory.archived_at !== null || !!memory.superseded_by;
22111
+ }
22112
+ function subscriptionKey({ memory, version }, options) {
22113
+ if (hidden(memory, options)) return void 0;
22114
+ if (options.includeDeleted) return String(!!memory.is_deleted);
22115
+ return JSON.stringify([
22116
+ options.embeddings ? version : null,
22117
+ memory.content,
22118
+ memory.scope,
22119
+ memory.updated_at,
22120
+ memory.fact_type,
22121
+ memory.event_time_start,
22122
+ memory.event_time_end,
22123
+ memory.event_time_kind,
22124
+ memory.trust_tier,
22125
+ memory.visibility,
22126
+ memory.published_at,
22127
+ memory.geohash,
22128
+ memory.topics,
22129
+ memory.topics_user_managed,
22130
+ memory.media,
22131
+ memory.source
22132
+ ]);
22133
+ }
22134
+ function topicInputs(topics, source) {
22135
+ return topics.flatMap((topic) => {
22136
+ const name = (typeof topic === "string" ? topic : topic.name).trim();
22137
+ const kind = typeof topic === "string" ? void 0 : topic.kind;
22138
+ return name ? [{ name, ...kind && { kind }, source }] : [];
22139
+ });
22140
+ }
22141
+ function mergeTopics(existing, added) {
22142
+ const byName = /* @__PURE__ */ new Map();
22143
+ for (const topic of [...existing, ...added]) {
22144
+ const key = normalizeEntityName(topic.name);
22145
+ if (!byName.has(key)) byName.set(key, topic);
22146
+ }
22147
+ return [...byName.values()];
22148
+ }
22149
+ function canonicalTopics(row) {
22150
+ return new Set((parseTopics(row.topics) ?? []).map((topic) => normalizeEntityName(topic.name)));
22151
+ }
22152
+ function createRemoteMemoryStore(options) {
22153
+ const { persistence, embeddingOptions } = options;
22154
+ const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
22155
+ const pollIntervalMs = options.pollIntervalMs ?? 6e4;
22156
+ const pipeline = createRemoteMemoryPipeline(options);
22157
+ const subscribers = /* @__PURE__ */ new Set();
22158
+ const seen = /* @__PURE__ */ new Map();
22159
+ let timer;
22160
+ const notify = (change, records = []) => {
22161
+ if (timer) for (const record2 of records) seen.set(record2.memory.memory_id, record2);
22162
+ for (const subscriber of [...subscribers])
22163
+ if (relevant(change, subscriber.options)) safely(subscriber.onChange);
22164
+ };
22165
+ const enumerate = async (filters, max = Infinity) => {
22166
+ const records = [];
22167
+ let cursor2;
22168
+ do {
22169
+ const page = await persistence.query({
22170
+ ...filters,
22171
+ limit: Math.min(200, Math.max(1, max - records.length)),
22172
+ ...cursor2 && { cursor: cursor2 }
22173
+ });
22174
+ warnFailed(page.failed);
22175
+ records.push(...page.items);
22176
+ cursor2 = page.next_cursor;
22177
+ } while (cursor2 && records.length < max);
22178
+ return records.slice(0, max);
22179
+ };
22180
+ const enumerateIds = async (ids, filters) => (await Promise.all(
22181
+ chunks([...new Set(ids)], MAX_QUERY_IDS).map(
22182
+ (memory_ids) => enumerate({ ...filters, memory_ids })
22183
+ )
22184
+ )).flat();
22185
+ const queues = /* @__PURE__ */ new Map();
22186
+ const serialized = (id, task) => {
22187
+ const run = (queues.get(id) ?? Promise.resolve()).then(task, task);
22188
+ const settled = run.catch(() => void 0);
22189
+ queues.set(id, settled);
22190
+ void settled.then(() => {
22191
+ if (queues.get(id) === settled) queues.delete(id);
22192
+ });
22193
+ return run;
22194
+ };
22195
+ const live = async (id) => {
22196
+ const record2 = await persistence.get(id);
22197
+ return record2 && !record2.memory.is_deleted ? record2 : null;
22198
+ };
22199
+ const mutate = async (id, change, edit) => serialized(id, async () => {
22200
+ const record2 = await live(id);
22201
+ if (!record2) return null;
22202
+ const next = edit(structuredClone(record2.memory));
22203
+ if (!next) return null;
22204
+ const saved = await persistence.put(next, record2);
22205
+ notify(change, [saved]);
22206
+ return saved;
22207
+ });
22208
+ const embedInBackground = ({ memory: { memory_id: id, content } }) => {
22209
+ generateEmbedding(content, embeddingOptions).then(
22210
+ (vector) => serialized(id, async () => {
22211
+ const current = await live(id);
22212
+ if (!current || current.memory.content !== content || current.memory.embedding?.length)
22213
+ return;
22214
+ const saved = await persistence.put(
22215
+ { ...current.memory, embedding: storedVector(vector), embedding_model: model },
22216
+ current
22217
+ );
22218
+ notify("embedding", [saved]);
22219
+ })
22220
+ ).catch((error) => {
22221
+ getLogger().warn("[memory/remote-store] Failed to embed memory:", error);
22222
+ });
22223
+ };
22224
+ const newRow = (input) => {
22225
+ const now = Date.now();
22226
+ const scope = input.scope ?? "private";
22227
+ return {
22228
+ memory_id: uuidv76(),
22229
+ content: input.content,
22230
+ scope,
22231
+ level: levelFromScope(scope),
22232
+ created_at: now,
22233
+ updated_at: now,
22234
+ is_deleted: false,
22235
+ ...input.embedding !== void 0 && {
22236
+ embedding: storedVector(JSON.parse(input.embedding)),
22237
+ embedding_model: input.embeddingModel ?? model
22238
+ },
22239
+ proof_count: 1,
22240
+ source: "manual",
22241
+ ...input.eventTime && {
22242
+ event_time_start: input.eventTime.start ?? void 0,
22243
+ event_time_end: input.eventTime.end ?? void 0,
22244
+ event_time_kind: input.eventTime.kind ?? void 0
22245
+ },
22246
+ fact_type: input.factType,
22247
+ geohash: input.geohash,
22248
+ visibility: "private",
22249
+ twin_opt_in: false
22250
+ };
22251
+ };
22252
+ const created = (records, inputs) => {
22253
+ records.forEach((record2, i) => {
22254
+ if (inputs[i].embedding === void 0) embedInBackground(record2);
22255
+ });
22256
+ notify("membership", records);
22257
+ return records.map((record2) => stored(record2.memory));
22258
+ };
22259
+ const asStored = (record2) => record2 ? stored(record2.memory) : null;
22260
+ const everyState = {
22261
+ include_deleted: true,
22262
+ include_archived: true,
22263
+ include_quarantined: true,
22264
+ include_superseded: true
22265
+ };
22266
+ const changesSince = async (cursor2, pending2) => {
22267
+ const records = [];
22268
+ const failed = /* @__PURE__ */ new Set();
22269
+ const collect = (page) => {
22270
+ warnFailed(page.failed);
22271
+ records.push(...page.items);
22272
+ for (const failure of page.failed) failed.add(failure.memory_id);
22273
+ };
22274
+ let resume = cursor2;
22275
+ let next;
22276
+ do {
22277
+ const page = await persistence.query({
22278
+ ...everyState,
22279
+ order: "changed",
22280
+ limit: 200,
22281
+ ...(next ?? resume) && { cursor: next ?? resume }
22282
+ });
22283
+ collect(page);
22284
+ resume = page.changes_cursor ?? resume;
22285
+ next = page.next_cursor;
22286
+ } while (next);
22287
+ for (const memory_ids of chunks([...pending2], MAX_QUERY_IDS)) {
22288
+ let retry;
22289
+ do {
22290
+ const page = await persistence.query({
22291
+ ...everyState,
22292
+ memory_ids,
22293
+ limit: 200,
22294
+ ...retry && { cursor: retry }
22295
+ });
22296
+ collect(page);
22297
+ retry = page.next_cursor;
22298
+ } while (retry);
22299
+ }
22300
+ return { records, resume, failed };
22301
+ };
22302
+ let generation = 0;
22303
+ let ready = false;
22304
+ let cursor;
22305
+ let pending = /* @__PURE__ */ new Set();
22306
+ let polling = false;
22307
+ const poll = () => {
22308
+ if (polling) return;
22309
+ polling = true;
22310
+ const current = generation;
22311
+ changesSince(cursor, pending).then(({ records, resume, failed }) => {
22312
+ if (current !== generation) return;
22313
+ const changed = /* @__PURE__ */ new Set();
22314
+ for (const record2 of records) {
22315
+ const id = record2.memory.memory_id;
22316
+ const previous = seen.get(id);
22317
+ seen.set(id, record2);
22318
+ if (!ready) continue;
22319
+ for (const subscriber of subscribers) {
22320
+ const before = previous && subscriptionKey(previous, subscriber.options);
22321
+ if (before !== subscriptionKey(record2, subscriber.options)) changed.add(subscriber);
22322
+ }
22323
+ }
22324
+ ready = true;
22325
+ cursor = resume;
22326
+ pending = failed;
22327
+ for (const subscriber of changed)
22328
+ if (subscribers.has(subscriber)) safely(subscriber.onChange);
22329
+ }).catch((error) => {
22330
+ getLogger().warn("[memory/remote-store] Subscription poll failed:", error);
22331
+ }).finally(() => {
22332
+ polling = false;
22333
+ });
22334
+ };
22335
+ return {
22336
+ list: async (listOptions = {}) => {
22337
+ const order = listOptions.since ? "updated" : "created";
22338
+ const filters = {
22339
+ ...stateFilters(listOptions),
22340
+ include_embeddings: true,
22341
+ order,
22342
+ ...listOptions.scopes?.length && { scopes: listOptions.scopes },
22343
+ ...listOptions.factTypes?.length && { fact_types: listOptions.factTypes },
22344
+ ...listOptions.visibility?.length && { visibility: listOptions.visibility },
22345
+ ...listOptions.since && { updated_after: listOptions.since.getTime() }
22346
+ };
22347
+ const max = listOptions.limit && listOptions.limit > 0 ? listOptions.limit : Infinity;
22348
+ const variants = bounded(filters, "scopes").flatMap((f) => bounded(f, "fact_types"));
22349
+ if (!listOptions.memoryIds && variants.length === 1)
22350
+ return (await enumerate(filters, max)).map((r) => stored(r.memory));
22351
+ const fetched = await Promise.all(
22352
+ variants.map(
22353
+ (variant) => listOptions.memoryIds ? enumerateIds(listOptions.memoryIds, variant) : enumerate(variant, max)
22354
+ )
22355
+ );
22356
+ const rows = [...new Map(fetched.flat().map((r) => [r.memory.memory_id, r])).values()].map((record2) => stored(record2.memory)).sort(
22357
+ (a, b) => order === "updated" ? b.updatedAt.getTime() - a.updatedAt.getTime() || (a.uniqueId < b.uniqueId ? 1 : -1) : b.createdAt.getTime() - a.createdAt.getTime() || (a.uniqueId < b.uniqueId ? 1 : -1)
22358
+ );
22359
+ return rows.slice(0, max);
22360
+ },
22361
+ get: async (id) => asStored(await live(id)),
22362
+ listArchived: async () => (await enumerate({ archived_only: true, order: "archived", include_embeddings: true })).map(
22363
+ (record2) => stored(record2.memory)
22364
+ ),
22365
+ memoriesByTopics: async (names) => {
22366
+ const wanted = new Set(names.map(normalizeEntityName).filter(Boolean));
22367
+ const out = /* @__PURE__ */ new Map();
22368
+ const pages = await Promise.all(
22369
+ chunks([...wanted], MAX_QUERY_TOPICS).map((topics) => enumerate({ topics }))
22370
+ );
22371
+ for (const { memory } of pages.flat()) {
22372
+ const matched = [...canonicalTopics(memory)].filter((name) => wanted.has(name));
22373
+ if (matched.length) out.set(memory.memory_id, new Set(matched));
22374
+ }
22375
+ return out;
22376
+ },
22377
+ topicsByMemories: async (memoryIds) => {
22378
+ const out = /* @__PURE__ */ new Map();
22379
+ for (const { memory } of await enumerateIds(memoryIds, {
22380
+ include_archived: true,
22381
+ include_superseded: true,
22382
+ include_quarantined: true
22383
+ })) {
22384
+ const topics = canonicalTopics(memory);
22385
+ if (topics.size) out.set(memory.memory_id, topics);
22386
+ }
22387
+ return out;
22388
+ },
22389
+ create: async (input) => {
22390
+ const record2 = await persistence.put(newRow(input), 0);
22391
+ return created([record2], [input])[0];
22392
+ },
22393
+ createMany: async (inputs) => {
22394
+ const out = [];
22395
+ for (const batch of chunks(inputs, MAX_BATCH)) {
22396
+ let records;
22397
+ try {
22398
+ records = await persistence.putMany(
22399
+ batch.map((input) => ({ memory: newRow(input), expectedVersion: 0 }))
22400
+ );
22401
+ } catch (error) {
22402
+ if (out.length === 0) throw error;
22403
+ throw new RemoteMemoryPartialCreateError(out, error);
22404
+ }
22405
+ out.push(...created(records, batch));
22406
+ }
22407
+ return out;
22408
+ },
22409
+ update: async (id, patch) => {
22410
+ const saved = await mutate(id, "edit", (memory) => {
22411
+ if (memory.superseded_by) return null;
22412
+ memory.content = patch.content;
22413
+ memory.updated_at = Date.now();
22414
+ if (patch.scope !== void 0) {
22415
+ memory.level = levelForScopeChange(
22416
+ { level: memory.level, scope: memory.scope },
22417
+ patch.scope
22418
+ );
22419
+ memory.scope = patch.scope;
22420
+ }
22421
+ if (patch.factType !== void 0) memory.fact_type = patch.factType ?? void 0;
22422
+ if (patch.eventTime !== void 0) {
22423
+ memory.event_time_start = patch.eventTime?.start ?? void 0;
22424
+ memory.event_time_end = patch.eventTime?.end ?? void 0;
22425
+ memory.event_time_kind = patch.eventTime?.kind ?? void 0;
22426
+ }
22427
+ if (patch.embedding === void 0 || patch.embedding === null) {
22428
+ memory.embedding = [];
22429
+ delete memory.embedding_model;
22430
+ } else {
22431
+ memory.embedding = storedVector(JSON.parse(patch.embedding));
22432
+ memory.embedding_model = patch.embeddingModel ?? model;
22433
+ }
22434
+ return memory;
22435
+ });
22436
+ if (saved && patch.embedding === void 0) embedInBackground(saved);
22437
+ return asStored(saved);
22438
+ },
22439
+ delete: async (id) => !!await mutate(id, "membership", (memory) => ({ ...memory, is_deleted: true })),
22440
+ supersede: async (id, supersededById) => {
22441
+ if (id === supersededById) return false;
22442
+ const [first, second] = [id, supersededById].sort();
22443
+ return serialized(
22444
+ first,
22445
+ () => serialized(second, async () => {
22446
+ const [old, next] = await Promise.all([live(id), live(supersededById)]);
22447
+ if (!old || !next || old.memory.superseded_by || next.memory.superseded_by) return false;
22448
+ if (old.memory.kind !== void 0 && old.memory.kind !== null) return false;
22449
+ const saved = await persistence.putMany([
22450
+ {
22451
+ memory: { ...old.memory, superseded_by: supersededById, superseded_at: Date.now() },
22452
+ expectedVersion: old
22453
+ },
22454
+ { memory: next.memory, expectedVersion: next }
22455
+ ]);
22456
+ notify("membership", saved);
22457
+ return true;
22458
+ })
22459
+ );
22460
+ },
22461
+ archive: async (id) => !!await mutate(
22462
+ id,
22463
+ "edit",
22464
+ (memory) => memory.archived_at === void 0 || memory.archived_at === null ? { ...memory, archived_at: Date.now() } : null
22465
+ ),
22466
+ restore: (id) => serialized(id, async () => {
22467
+ const record2 = await live(id);
22468
+ if (!record2) return false;
22469
+ if (record2.memory.archived_at === void 0 || record2.memory.archived_at === null)
22470
+ return true;
22471
+ const { archived_at: _archivedAt, ...memory } = record2.memory;
22472
+ notify("edit", [await persistence.put(memory, record2)]);
22473
+ return true;
22474
+ }),
22475
+ setTopics: async (memoryId, topics) => asStored(
22476
+ await mutate(memoryId, "edit", (memory) => ({
22477
+ ...memory,
22478
+ topics: serializeTopics(mergeTopics([], topicInputs(topics, "user"))),
22479
+ topics_user_managed: true,
22480
+ topics_updated_at: Date.now()
22481
+ }))
22482
+ ),
22483
+ addTopics: async (memoryId, topics) => {
22484
+ const added = topicInputs(topics, "auto");
22485
+ const saved = await mutate(memoryId, "edit", (memory) => ({
22486
+ ...memory,
22487
+ topics: serializeTopics(mergeTopics(parseTopics(memory.topics) ?? [], added)),
22488
+ topics_updated_at: Date.now()
22489
+ }));
22490
+ if (!saved) return [];
22491
+ const now = /* @__PURE__ */ new Date();
22492
+ return mergeTopics([], added).map(
22493
+ (topic) => ({
22494
+ uniqueId: normalizeEntityName(topic.name),
22495
+ canonicalName: normalizeEntityName(topic.name),
22496
+ kind: topic.kind ?? null,
22497
+ createdAt: now,
22498
+ updatedAt: now
22499
+ })
22500
+ );
22501
+ },
22502
+ setVisibility: async (id, visibility, visibilityOptions) => asStored(
22503
+ await mutate(id, "edit", (memory) => {
22504
+ memory.visibility = visibility;
22505
+ if (visibility === "private") delete memory.published_at;
22506
+ else memory.published_at ?? (memory.published_at = Date.now());
22507
+ if (visibilityOptions?.twinOptIn !== void 0)
22508
+ memory.twin_opt_in = visibilityOptions.twinOptIn;
22509
+ return memory;
22510
+ })
22511
+ ),
22512
+ recall: (query, recallOptions) => pipeline.recall(query, recallOptions),
22513
+ retain: async (content, retainOptions) => {
22514
+ const result = await pipeline.retain(content, retainOptions);
22515
+ if (result.action === "create" || result.action === "supersede") notify("membership");
22516
+ else if (result.action === "update" || result.action === "merge") notify("edit");
22517
+ return result;
22518
+ },
22519
+ subscribe: (onChange, subscribeOptions = {}) => {
22520
+ const subscriber = { onChange, options: subscribeOptions };
22521
+ subscribers.add(subscriber);
22522
+ if (pollIntervalMs > 0 && !timer) {
22523
+ timer = setInterval(poll, pollIntervalMs);
22524
+ poll();
22525
+ }
22526
+ return () => {
22527
+ subscribers.delete(subscriber);
22528
+ if (subscribers.size || !timer) return;
22529
+ clearInterval(timer);
22530
+ timer = void 0;
22531
+ generation++;
22532
+ seen.clear();
22533
+ ready = false;
22534
+ cursor = void 0;
22535
+ pending = /* @__PURE__ */ new Set();
22536
+ };
22537
+ }
22538
+ };
22539
+ }
22540
+
21754
22541
  // src/lib/memory/synthesizeProfile.ts
21755
22542
  var DEFAULT_SYNTHESIS_MODEL = "inclusionai/ling-2.6-flash";
21756
22543
  var DEFAULT_FACET_RECALL_LIMIT = 20;
@@ -35729,7 +36516,11 @@ export {
35729
36516
  LoggerProvider,
35730
36517
  MAX_HOPS,
35731
36518
  MEDIUM_TTL_MS,
36519
+ MEMORY_KINDS,
36520
+ MEMORY_LEVELS,
35732
36521
  MemoryEntity as MemoryEntityModel,
36522
+ MemoryKeyError,
36523
+ MemoryLevelError,
35733
36524
  NEVER_TTL_MS,
35734
36525
  NODE_BUDGET,
35735
36526
  PAST_EVENT_GRACE_MS,
@@ -35743,6 +36534,7 @@ export {
35743
36534
  RECALL_MAX_LIMIT,
35744
36535
  RECALL_TOOL_NAME,
35745
36536
  RemoteMemoryError,
36537
+ RemoteMemoryPartialCreateError,
35746
36538
  RerankerUnavailableError,
35747
36539
  SDK_SCHEMA_VERSION,
35748
36540
  SERVER_TOOL_DEPENDENCY_SETS,
@@ -35836,6 +36628,7 @@ export {
35836
36628
  createRecallTool,
35837
36629
  createRemoteMemoryPersistence,
35838
36630
  createRemoteMemoryPipeline,
36631
+ createRemoteMemoryStore,
35839
36632
  createSavedToolOp,
35840
36633
  createServerToolsFilter,
35841
36634
  createStockPricePreProcessor,
@@ -35867,6 +36660,7 @@ export {
35867
36660
  deleteVaultMemoryOp,
35868
36661
  dequantizeEmbedding,
35869
36662
  deriveKeyFromSignatureBytes,
36663
+ deriveMemoryKeyRing,
35870
36664
  eagerEmbedContent,
35871
36665
  embedAllMessages,
35872
36666
  embedMessage,
@@ -36006,6 +36800,7 @@ export {
36006
36800
  linkMemoryEntitiesOp,
36007
36801
  maskScopedEmbeddingCache,
36008
36802
  mediaToStored,
36803
+ memoryCipher,
36009
36804
  migrateCalendarToken,
36010
36805
  migrateDisplayResult,
36011
36806
  migrateDriveToken,
@@ -36027,6 +36822,7 @@ export {
36027
36822
  rankProfileCandidates,
36028
36823
  readEncryptedFile,
36029
36824
  recall,
36825
+ reencryptMemoryField,
36030
36826
  reflect,
36031
36827
  refreshCalendarToken,
36032
36828
  refreshDriveToken,