@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.
@@ -1424,7 +1424,11 @@ __export(index_exports, {
1424
1424
  LoggerProvider: () => LoggerProvider,
1425
1425
  MAX_HOPS: () => MAX_HOPS,
1426
1426
  MEDIUM_TTL_MS: () => MEDIUM_TTL_MS,
1427
+ MEMORY_KINDS: () => MEMORY_KINDS,
1428
+ MEMORY_LEVELS: () => MEMORY_LEVELS,
1427
1429
  MemoryEntityModel: () => MemoryEntity,
1430
+ MemoryKeyError: () => MemoryKeyError,
1431
+ MemoryLevelError: () => MemoryLevelError,
1428
1432
  NEVER_TTL_MS: () => NEVER_TTL_MS,
1429
1433
  NODE_BUDGET: () => NODE_BUDGET,
1430
1434
  PAST_EVENT_GRACE_MS: () => PAST_EVENT_GRACE_MS,
@@ -1438,6 +1442,7 @@ __export(index_exports, {
1438
1442
  RECALL_MAX_LIMIT: () => RECALL_MAX_LIMIT,
1439
1443
  RECALL_TOOL_NAME: () => RECALL_TOOL_NAME,
1440
1444
  RemoteMemoryError: () => RemoteMemoryError,
1445
+ RemoteMemoryPartialCreateError: () => RemoteMemoryPartialCreateError,
1441
1446
  RerankerUnavailableError: () => RerankerUnavailableError,
1442
1447
  SDK_SCHEMA_VERSION: () => SDK_SCHEMA_VERSION,
1443
1448
  SERVER_TOOL_DEPENDENCY_SETS: () => SERVER_TOOL_DEPENDENCY_SETS,
@@ -1531,6 +1536,7 @@ __export(index_exports, {
1531
1536
  createRecallTool: () => createRecallTool,
1532
1537
  createRemoteMemoryPersistence: () => createRemoteMemoryPersistence,
1533
1538
  createRemoteMemoryPipeline: () => createRemoteMemoryPipeline,
1539
+ createRemoteMemoryStore: () => createRemoteMemoryStore,
1534
1540
  createSavedToolOp: () => createSavedToolOp,
1535
1541
  createServerToolsFilter: () => createServerToolsFilter,
1536
1542
  createStockPricePreProcessor: () => createStockPricePreProcessor,
@@ -1562,6 +1568,7 @@ __export(index_exports, {
1562
1568
  deleteVaultMemoryOp: () => deleteVaultMemoryOp,
1563
1569
  dequantizeEmbedding: () => dequantizeEmbedding,
1564
1570
  deriveKeyFromSignatureBytes: () => deriveKeyFromSignatureBytes,
1571
+ deriveMemoryKeyRing: () => deriveMemoryKeyRing,
1565
1572
  eagerEmbedContent: () => eagerEmbedContent,
1566
1573
  embedAllMessages: () => embedAllMessages,
1567
1574
  embedMessage: () => embedMessage,
@@ -1701,6 +1708,7 @@ __export(index_exports, {
1701
1708
  linkMemoryEntitiesOp: () => linkMemoryEntitiesOp,
1702
1709
  maskScopedEmbeddingCache: () => maskScopedEmbeddingCache,
1703
1710
  mediaToStored: () => mediaToStored,
1711
+ memoryCipher: () => memoryCipher,
1704
1712
  migrateCalendarToken: () => migrateCalendarToken,
1705
1713
  migrateDisplayResult: () => migrateDisplayResult,
1706
1714
  migrateDriveToken: () => migrateDriveToken,
@@ -1722,6 +1730,7 @@ __export(index_exports, {
1722
1730
  rankProfileCandidates: () => rankProfileCandidates,
1723
1731
  readEncryptedFile: () => readEncryptedFile,
1724
1732
  recall: () => recall,
1733
+ reencryptMemoryField: () => reencryptMemoryField,
1725
1734
  reflect: () => reflect,
1726
1735
  refreshCalendarToken: () => refreshCalendarToken,
1727
1736
  refreshDriveToken: () => refreshDriveToken,
@@ -1901,9 +1910,9 @@ function createSseClient({
1901
1910
  if (done) break;
1902
1911
  buffer += value;
1903
1912
  buffer = buffer.replace(/\r\n?/g, "\n");
1904
- const chunks = buffer.split("\n\n");
1905
- buffer = chunks.pop() ?? "";
1906
- for (const chunk of chunks) {
1913
+ const chunks2 = buffer.split("\n\n");
1914
+ buffer = chunks2.pop() ?? "";
1915
+ for (const chunk of chunks2) {
1907
1916
  const lines = chunk.split("\n");
1908
1917
  const dataLines = [];
1909
1918
  let eventName;
@@ -6555,14 +6564,14 @@ async function updateMessageEmbeddingOp(ctx, uniqueId, vector, embeddingModel) {
6555
6564
  });
6556
6565
  return messageToStored(message, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
6557
6566
  }
6558
- async function updateMessageChunksOp(ctx, uniqueId, chunks, embeddingModel) {
6567
+ async function updateMessageChunksOp(ctx, uniqueId, chunks2, embeddingModel) {
6559
6568
  let message;
6560
6569
  try {
6561
6570
  message = await ctx.messagesCollection.find(uniqueId);
6562
6571
  } catch {
6563
6572
  return null;
6564
6573
  }
6565
- const storedChunks = chunks.map(({ text: _text, ...rest }) => rest);
6574
+ const storedChunks = chunks2.map(({ text: _text, ...rest }) => rest);
6566
6575
  await ctx.database.write(async () => {
6567
6576
  await message.update((msg) => {
6568
6577
  msg._setRaw("chunks", JSON.stringify(storedChunks));
@@ -6606,12 +6615,12 @@ async function stripLegacyChunkTextOp(ctx) {
6606
6615
  const messages = await ctx.messagesCollection.query(import_watermelondb2.Q.where("id", import_watermelondb2.Q.oneOf(changedIds))).fetch();
6607
6616
  const updates = messages.flatMap((message) => {
6608
6617
  const raw = message._raw;
6609
- const chunks = chunksWithoutText(raw.chunks);
6610
- if (!chunks) return [];
6618
+ const chunks2 = chunksWithoutText(raw.chunks);
6619
+ if (!chunks2) return [];
6611
6620
  const updatedAt = raw.updated_at;
6612
6621
  return [
6613
6622
  message.prepareUpdate((msg) => {
6614
- msg._setRaw("chunks", JSON.stringify(chunks));
6623
+ msg._setRaw("chunks", JSON.stringify(chunks2));
6615
6624
  msg._setRaw("updated_at", updatedAt);
6616
6625
  })
6617
6626
  ];
@@ -6821,15 +6830,15 @@ async function searchChunksOp(ctx, queryVector, options) {
6821
6830
  }
6822
6831
  continue;
6823
6832
  }
6824
- const chunks = await readRawJsonField(message, "chunks", ctx.walletAddress);
6825
- if (chunks && chunks.length > 0) {
6826
- const vectors = chunks.map(
6833
+ const chunks2 = await readRawJsonField(message, "chunks", ctx.walletAddress);
6834
+ if (chunks2 && chunks2.length > 0) {
6835
+ const vectors = chunks2.map(
6827
6836
  (chunk) => decodeChunkVector(chunk.vector, () => {
6828
6837
  unreadableVectors++;
6829
6838
  })
6830
6839
  );
6831
6840
  chunkCache?.set(message.id, { version, chunks: vectors });
6832
- for (let ci = 0; ci < chunks.length; ci++) {
6841
+ for (let ci = 0; ci < chunks2.length; ci++) {
6833
6842
  const vec = vectors[ci];
6834
6843
  if (vec.length === 0) continue;
6835
6844
  const similarity = cosineSimilarity(queryVector, vec);
@@ -6837,7 +6846,7 @@ async function searchChunksOp(ctx, queryVector, options) {
6837
6846
  candidates.push({
6838
6847
  message,
6839
6848
  similarity,
6840
- chunkTextSource: { kind: "chunk", chunk: chunks[ci], siblings: chunks }
6849
+ chunkTextSource: { kind: "chunk", chunk: chunks2[ci], siblings: chunks2 }
6841
6850
  });
6842
6851
  }
6843
6852
  }
@@ -7017,7 +7026,7 @@ function chunkText(text12, options) {
7017
7026
  ];
7018
7027
  }
7019
7028
  const sentences = splitIntoSentences(text12);
7020
- const chunks = [];
7029
+ const chunks2 = [];
7021
7030
  let currentChunkSentences = [];
7022
7031
  let currentChunkStart = 0;
7023
7032
  let currentOffset = 0;
@@ -7031,7 +7040,7 @@ function chunkText(text12, options) {
7031
7040
  if (sentence.length > chunkSize) {
7032
7041
  if (currentChunkSentences.length > 0) {
7033
7042
  const chunkText2 = currentChunkSentences.join(" ");
7034
- chunks.push({
7043
+ chunks2.push({
7035
7044
  text: chunkText2,
7036
7045
  startOffset: currentChunkStart,
7037
7046
  endOffset: currentOffset
@@ -7042,7 +7051,7 @@ function chunkText(text12, options) {
7042
7051
  const chunkEnd = Math.min(j + chunkSize, sentence.length);
7043
7052
  const chunk = sentence.slice(j, chunkEnd);
7044
7053
  if (chunk.length >= minChunkSize) {
7045
- chunks.push({
7054
+ chunks2.push({
7046
7055
  text: chunk,
7047
7056
  startOffset: sentenceStart + j,
7048
7057
  endOffset: sentenceStart + chunkEnd
@@ -7056,7 +7065,7 @@ function chunkText(text12, options) {
7056
7065
  const currentText = currentChunkSentences.join(" ");
7057
7066
  const potentialLength = currentText.length + (currentText ? 1 : 0) + sentence.length;
7058
7067
  if (potentialLength > chunkSize && currentChunkSentences.length > 0) {
7059
- chunks.push({
7068
+ chunks2.push({
7060
7069
  text: currentText,
7061
7070
  startOffset: currentChunkStart,
7062
7071
  endOffset: currentOffset
@@ -7087,14 +7096,14 @@ function chunkText(text12, options) {
7087
7096
  if (currentChunkSentences.length > 0) {
7088
7097
  const chunkText2 = currentChunkSentences.join(" ");
7089
7098
  if (chunkText2.length >= minChunkSize) {
7090
- chunks.push({
7099
+ chunks2.push({
7091
7100
  text: chunkText2,
7092
7101
  startOffset: currentChunkStart,
7093
7102
  endOffset: text12.length
7094
7103
  });
7095
7104
  }
7096
7105
  }
7097
- if (chunks.length === 0) {
7106
+ if (chunks2.length === 0) {
7098
7107
  const trimmedText = text12.trim();
7099
7108
  if (trimmedText.length > 0) {
7100
7109
  return [
@@ -7106,7 +7115,7 @@ function chunkText(text12, options) {
7106
7115
  ];
7107
7116
  }
7108
7117
  }
7109
- return chunks;
7118
+ return chunks2;
7110
7119
  }
7111
7120
  function shouldChunkMessage(content, chunkSize = DEFAULT_CHUNK_SIZE) {
7112
7121
  return content.length > chunkSize;
@@ -7325,18 +7334,18 @@ async function embedMany(texts, options, outer) {
7325
7334
  outer
7326
7335
  );
7327
7336
  } else {
7328
- const chunks = [];
7337
+ const chunks2 = [];
7329
7338
  for (let i = 0; i < uncachedTexts.length; i += chunkSize) {
7330
- chunks.push(uncachedTexts.slice(i, i + chunkSize));
7339
+ chunks2.push(uncachedTexts.slice(i, i + chunkSize));
7331
7340
  }
7332
- const allEmbeddings = new Array(chunks.length);
7341
+ const allEmbeddings = new Array(chunks2.length);
7333
7342
  let nextIndex = 0;
7334
7343
  const worker = async () => {
7335
- while (nextIndex < chunks.length) {
7344
+ while (nextIndex < chunks2.length) {
7336
7345
  if (outer?.aborted) throw outer.reason;
7337
7346
  const idx = nextIndex++;
7338
7347
  allEmbeddings[idx] = await generateEmbeddingsBatch(
7339
- chunks[idx],
7348
+ chunks2[idx],
7340
7349
  headers,
7341
7350
  baseUrl,
7342
7351
  embeddingModel,
@@ -7348,7 +7357,7 @@ async function embedMany(texts, options, outer) {
7348
7357
  }
7349
7358
  };
7350
7359
  const workers = Array.from(
7351
- { length: Math.min(DEFAULT_EMBEDDING_BATCH_CONCURRENCY, chunks.length) },
7360
+ { length: Math.min(DEFAULT_EMBEDDING_BATCH_CONCURRENCY, chunks2.length) },
7352
7361
  () => worker()
7353
7362
  );
7354
7363
  await Promise.all(workers);
@@ -13155,6 +13164,15 @@ __decorateClass([
13155
13164
  __decorateClass([
13156
13165
  (0, import_decorators6.text)("scope")
13157
13166
  ], VaultMemory.prototype, "scope", 2);
13167
+ __decorateClass([
13168
+ (0, import_decorators6.field)("kind")
13169
+ ], VaultMemory.prototype, "kind", 2);
13170
+ __decorateClass([
13171
+ (0, import_decorators6.field)("kind_value")
13172
+ ], VaultMemory.prototype, "kindValue", 2);
13173
+ __decorateClass([
13174
+ (0, import_decorators6.field)("level")
13175
+ ], VaultMemory.prototype, "level", 2);
13158
13176
  __decorateClass([
13159
13177
  (0, import_decorators6.field)("folder_id")
13160
13178
  ], VaultMemory.prototype, "folderId", 2);
@@ -13380,7 +13398,7 @@ __decorateClass([
13380
13398
  ], VaultFolder.prototype, "context", 2);
13381
13399
 
13382
13400
  // src/lib/db/schema.ts
13383
- var SDK_SCHEMA_VERSION = 47;
13401
+ var SDK_SCHEMA_VERSION = 48;
13384
13402
  var sdkSchema = (0, import_watermelondb19.appSchema)({
13385
13403
  version: SDK_SCHEMA_VERSION,
13386
13404
  tables: [
@@ -13475,6 +13493,9 @@ var sdkSchema = (0, import_watermelondb19.appSchema)({
13475
13493
  columns: [
13476
13494
  { name: "content", type: "string" },
13477
13495
  { name: "scope", type: "string", isIndexed: true },
13496
+ { name: "kind", type: "string", isOptional: true, isIndexed: true },
13497
+ { name: "kind_value", type: "string", isOptional: true },
13498
+ { name: "level", type: "string", isOptional: true, isIndexed: true },
13478
13499
  { name: "folder_id", type: "string", isOptional: true, isIndexed: true },
13479
13500
  { name: "created_at", type: "number", isIndexed: true },
13480
13501
  { name: "updated_at", type: "number", isIndexed: true },
@@ -14151,6 +14172,22 @@ var sdkMigrations = (0, import_migrations2.schemaMigrations)({
14151
14172
  ]
14152
14173
  })
14153
14174
  ]
14175
+ },
14176
+ {
14177
+ toVersion: 48,
14178
+ steps: [
14179
+ (0, import_migrations2.addColumns)({
14180
+ table: "memory_vault",
14181
+ columns: [
14182
+ { name: "kind", type: "string", isOptional: true, isIndexed: true },
14183
+ { name: "kind_value", type: "string", isOptional: true },
14184
+ { name: "level", type: "string", isOptional: true, isIndexed: true }
14185
+ ]
14186
+ }),
14187
+ (0, import_migrations2.unsafeExecuteSql)(
14188
+ "UPDATE memory_vault SET level = CASE WHEN scope IN ('shared', 'public') THEN 'matching' ELSE 'private' END WHERE level IS NULL;"
14189
+ )
14190
+ ]
14154
14191
  }
14155
14192
  ]
14156
14193
  });
@@ -14674,8 +14711,8 @@ var WatermelonChatStorageAdapter = class {
14674
14711
  updateMessageEmbedding(uniqueId, vector, embeddingModel) {
14675
14712
  return updateMessageEmbeddingOp(this.ctx, uniqueId, vector, embeddingModel);
14676
14713
  }
14677
- updateMessageChunks(uniqueId, chunks, embeddingModel) {
14678
- return updateMessageChunksOp(this.ctx, uniqueId, chunks, embeddingModel);
14714
+ updateMessageChunks(uniqueId, chunks2, embeddingModel) {
14715
+ return updateMessageChunksOp(this.ctx, uniqueId, chunks2, embeddingModel);
14679
14716
  }
14680
14717
  updateMessageError(uniqueId, error) {
14681
14718
  return updateMessageErrorOp(this.ctx, uniqueId, error);
@@ -15292,13 +15329,54 @@ async function decryptVaultMemoryFields(memory, address, signMessage, embeddedWa
15292
15329
  }
15293
15330
  }
15294
15331
  const decryptedContent = await decryptField(memory.content, address);
15332
+ const decryptedKindValue = typeof memory.kindValue === "string" ? await decryptField(memory.kindValue, address) : memory.kindValue;
15295
15333
  return {
15296
15334
  ...memory,
15297
- content: decryptedContent
15335
+ content: decryptedContent,
15336
+ ...decryptedKindValue !== void 0 && { kindValue: decryptedKindValue }
15298
15337
  };
15299
15338
  }
15300
15339
 
15301
15340
  // src/lib/db/memoryVault/types.ts
15341
+ var MEMORY_KINDS = [
15342
+ "display_name",
15343
+ "birth_date",
15344
+ "bio",
15345
+ "occupation",
15346
+ "interest",
15347
+ "gender",
15348
+ "height_cm",
15349
+ "looking_for",
15350
+ "politics",
15351
+ "religion",
15352
+ "ethnicity",
15353
+ "smoking",
15354
+ "drinking",
15355
+ "exercise",
15356
+ "sexuality",
15357
+ "prompt"
15358
+ ];
15359
+ var MEMORY_LEVELS = ["private", "matching", "profile"];
15360
+ var MemoryLevelError = class extends Error {
15361
+ constructor(message) {
15362
+ super(message);
15363
+ this.name = "MemoryLevelError";
15364
+ }
15365
+ };
15366
+ var PUBLISHED_SCOPES = /* @__PURE__ */ new Set(["shared", "public"]);
15367
+ function levelFromScope(scope) {
15368
+ return typeof scope === "string" && PUBLISHED_SCOPES.has(scope) ? "matching" : "private";
15369
+ }
15370
+ function scopeForLevel(level) {
15371
+ return level === "private" ? "private" : "shared";
15372
+ }
15373
+ function resolveMemoryLevel(level, scope) {
15374
+ return typeof level === "string" && MEMORY_LEVELS.includes(level) ? level : levelFromScope(scope);
15375
+ }
15376
+ function levelForScopeChange(current, nextScope) {
15377
+ const implied = levelFromScope(nextScope);
15378
+ return implied === "matching" && resolveMemoryLevel(current.level, current.scope) === "profile" ? "profile" : implied;
15379
+ }
15302
15380
  function parseMedia(value) {
15303
15381
  if (typeof value !== "string" || value === "") return null;
15304
15382
  try {
@@ -15328,6 +15406,56 @@ function visibilityConditions(requested) {
15328
15406
  if (excluded.length === 0) return [];
15329
15407
  return [import_watermelondb23.Q.or(import_watermelondb23.Q.where("visibility", null), import_watermelondb23.Q.where("visibility", import_watermelondb23.Q.notIn(excluded)))];
15330
15408
  }
15409
+ function isKinded(record2) {
15410
+ return record2.kind !== null && record2.kind !== void 0;
15411
+ }
15412
+ function assertValidKindLevel(kind, level) {
15413
+ const hasKind = kind !== null && kind !== void 0;
15414
+ if (hasKind && !MEMORY_KINDS.includes(kind)) {
15415
+ throw new MemoryLevelError(`Unknown memory kind: ${kind}`);
15416
+ }
15417
+ if (level !== void 0 && !MEMORY_LEVELS.includes(level)) {
15418
+ throw new MemoryLevelError(`Unknown memory level: ${level}`);
15419
+ }
15420
+ if (level === "profile" && !hasKind) {
15421
+ throw new MemoryLevelError("Only a memory with a kind can be at level 'profile'");
15422
+ }
15423
+ }
15424
+ function resolveCreateLevel(opts) {
15425
+ if (opts.level !== void 0) return { level: opts.level, scope: scopeForLevel(opts.level) };
15426
+ if (opts.scope !== void 0) return { level: levelFromScope(opts.scope), scope: opts.scope };
15427
+ return { level: "private", scope: "private" };
15428
+ }
15429
+ async function encryptKindValue(ctx, value) {
15430
+ if (typeof value !== "string" || !ctx.walletAddress || !ctx.signMessage) return value;
15431
+ return encryptVaultMemoryContent(
15432
+ value,
15433
+ ctx.walletAddress,
15434
+ ctx.signMessage,
15435
+ ctx.embeddedWalletSigner
15436
+ );
15437
+ }
15438
+ function levelConditions(requested) {
15439
+ if (!requested?.length) return [];
15440
+ const published = ["shared", "public"];
15441
+ const wantsMatching = requested.includes("matching");
15442
+ const wantsPrivate = requested.includes("private");
15443
+ const unresolved = import_watermelondb23.Q.or(import_watermelondb23.Q.where("level", null), import_watermelondb23.Q.where("level", import_watermelondb23.Q.notIn([...MEMORY_LEVELS])));
15444
+ const byLevel = import_watermelondb23.Q.where("level", import_watermelondb23.Q.oneOf([...requested]));
15445
+ if (wantsMatching && wantsPrivate) return [import_watermelondb23.Q.or(byLevel, unresolved)];
15446
+ if (wantsMatching) {
15447
+ return [import_watermelondb23.Q.or(byLevel, import_watermelondb23.Q.and(unresolved, import_watermelondb23.Q.where("scope", import_watermelondb23.Q.oneOf(published))))];
15448
+ }
15449
+ if (wantsPrivate) {
15450
+ return [
15451
+ import_watermelondb23.Q.or(
15452
+ byLevel,
15453
+ import_watermelondb23.Q.and(unresolved, import_watermelondb23.Q.or(import_watermelondb23.Q.where("scope", null), import_watermelondb23.Q.where("scope", import_watermelondb23.Q.notIn(published))))
15454
+ )
15455
+ ];
15456
+ }
15457
+ return [byLevel];
15458
+ }
15331
15459
  function isOwnedByCtxUser(ctx, record2) {
15332
15460
  return ctx.userId === void 0 || record2.userId === ctx.userId;
15333
15461
  }
@@ -15371,6 +15499,9 @@ function vaultMemoryToStoredRaw(memory) {
15371
15499
  uniqueId: memory.id,
15372
15500
  content: memory.content,
15373
15501
  scope: memory.scope,
15502
+ kind: memory.kind ?? null,
15503
+ kindValue: memory.kindValue ?? null,
15504
+ level: resolveMemoryLevel(memory.level, memory.scope),
15374
15505
  folderId: memory.folderId ?? null,
15375
15506
  userId: memory.userId ?? null,
15376
15507
  embedding: memory.embedding ?? null,
@@ -15409,9 +15540,13 @@ async function vaultMemoryToStored(memory, walletAddress, signMessage, embeddedW
15409
15540
  }
15410
15541
  return raw;
15411
15542
  }
15412
- function populateNewVaultMemory(record2, ctx, opts, encryptedContent) {
15543
+ function populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue) {
15544
+ const { level, scope } = resolveCreateLevel(opts);
15413
15545
  record2._setRaw("content", encryptedContent);
15414
- record2._setRaw("scope", opts.scope ?? "private");
15546
+ record2._setRaw("scope", scope);
15547
+ record2._setRaw("level", level);
15548
+ record2._setRaw("kind", opts.kind ?? null);
15549
+ record2._setRaw("kind_value", encryptedKindValue ?? null);
15415
15550
  record2._setRaw("folder_id", opts.folderId ?? null);
15416
15551
  record2._setRaw("user_id", ctx.userId ?? null);
15417
15552
  record2._setRaw("is_deleted", false);
@@ -15445,6 +15580,8 @@ function populateNewVaultMemory(record2, ctx, opts, encryptedContent) {
15445
15580
  }
15446
15581
  }
15447
15582
  async function createVaultMemoryOp(ctx, opts) {
15583
+ assertValidKindLevel(opts.kind, resolveCreateLevel(opts).level);
15584
+ const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
15448
15585
  const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
15449
15586
  opts.content,
15450
15587
  ctx.walletAddress,
@@ -15455,13 +15592,15 @@ async function createVaultMemoryOp(ctx, opts) {
15455
15592
  if (ctx.canWrite && !await ctx.canWrite())
15456
15593
  throw new Error("Memory source is no longer eligible");
15457
15594
  return ctx.vaultMemoryCollection.create(
15458
- (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent)
15595
+ (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue)
15459
15596
  );
15460
15597
  });
15461
15598
  return vaultMemoryToStored(created, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
15462
15599
  }
15463
15600
  async function createSupersedingMemoryOp(ctx, opts, targetId) {
15464
15601
  if (!targetId) return { created: null, retired: false };
15602
+ assertValidKindLevel(opts.kind, resolveCreateLevel(opts).level);
15603
+ const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
15465
15604
  const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
15466
15605
  opts.content,
15467
15606
  ctx.walletAddress,
@@ -15478,9 +15617,10 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
15478
15617
  } catch {
15479
15618
  return;
15480
15619
  }
15481
- if (target.isDeleted || target.supersededBy || !isOwnedByCtxUser(ctx, target)) return;
15620
+ if (target.isDeleted || target.supersededBy || isKinded(target) || !isOwnedByCtxUser(ctx, target))
15621
+ return;
15482
15622
  createdRecord = await ctx.vaultMemoryCollection.create(
15483
- (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent)
15623
+ (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContent, encryptedKindValue)
15484
15624
  );
15485
15625
  await target.update((r) => {
15486
15626
  r._setRaw("superseded_by", createdRecord.id);
@@ -15544,6 +15684,10 @@ async function getMemoriesByEventTimeOp(ctx, windowStart, windowEnd) {
15544
15684
  }
15545
15685
  async function createVaultMemoriesBatchOp(ctx, optionsArray) {
15546
15686
  if (optionsArray.length === 0) return [];
15687
+ for (const opts of optionsArray) assertValidKindLevel(opts.kind, resolveCreateLevel(opts).level);
15688
+ const encryptedKindValues = await Promise.all(
15689
+ optionsArray.map((opts) => encryptKindValue(ctx, opts.kindValue))
15690
+ );
15547
15691
  const encryptedContents = await Promise.all(
15548
15692
  optionsArray.map(async (opts) => {
15549
15693
  if (ctx.walletAddress && ctx.signMessage) {
@@ -15562,7 +15706,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
15562
15706
  throw new Error("Memory source is no longer eligible");
15563
15707
  const prepared = optionsArray.map(
15564
15708
  (opts, i) => ctx.vaultMemoryCollection.prepareCreate(
15565
- (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i])
15709
+ (record2) => populateNewVaultMemory(record2, ctx, opts, encryptedContents[i], encryptedKindValues[i])
15566
15710
  )
15567
15711
  );
15568
15712
  await ctx.database.batch(...prepared);
@@ -15605,6 +15749,9 @@ function vaultMemoryRawToStoredRaw(raw) {
15605
15749
  uniqueId: raw.id,
15606
15750
  content: raw.content ?? "",
15607
15751
  scope: raw.scope ?? "",
15752
+ kind: raw.kind ?? null,
15753
+ kindValue: raw.kind_value ?? null,
15754
+ level: resolveMemoryLevel(raw.level, raw.scope),
15608
15755
  folderId: raw.folder_id ?? null,
15609
15756
  userId: raw.user_id ?? null,
15610
15757
  embedding: raw.embedding ?? null,
@@ -15648,6 +15795,8 @@ async function getAllVaultMemoriesOp(ctx, options) {
15648
15795
  ...baseVaultConditions(ctx, options),
15649
15796
  ...options?.scopes?.length ? [import_watermelondb23.Q.where("scope", import_watermelondb23.Q.oneOf(options.scopes))] : [],
15650
15797
  ...visibilityConditions(options?.visibility),
15798
+ ...levelConditions(options?.levels),
15799
+ ...options?.kinds?.length ? [import_watermelondb23.Q.where("kind", import_watermelondb23.Q.oneOf(options.kinds))] : [],
15651
15800
  ...options?.folderId !== void 0 ? [import_watermelondb23.Q.where("folder_id", options.folderId)] : [],
15652
15801
  ...options?.factTypes?.length ? [import_watermelondb23.Q.where("fact_type", import_watermelondb23.Q.oneOf(options.factTypes))] : [],
15653
15802
  import_watermelondb23.Q.sortBy(options?.since ? "updated_at" : "created_at", import_watermelondb23.Q.desc),
@@ -15814,6 +15963,14 @@ async function updateVaultMemoryOp(ctx, id, opts) {
15814
15963
  try {
15815
15964
  const probe = await ctx.vaultMemoryCollection.find(id);
15816
15965
  if (probe.isDeleted || probe.supersededBy || !isOwnedByCtxUser(ctx, probe)) return null;
15966
+ if (opts.freeFormOnly && isKinded(probe)) return null;
15967
+ const levelAfter = (current) => {
15968
+ if (opts.level !== void 0) return opts.level;
15969
+ if (opts.scope === void 0) return resolveMemoryLevel(current.level, current.scope);
15970
+ return levelForScopeChange(current, opts.scope);
15971
+ };
15972
+ assertValidKindLevel(opts.kind !== void 0 ? opts.kind : probe.kind, levelAfter(probe));
15973
+ const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
15817
15974
  const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
15818
15975
  opts.content,
15819
15976
  ctx.walletAddress,
@@ -15826,10 +15983,13 @@ async function updateVaultMemoryOp(ctx, id, opts) {
15826
15983
  await ctx.database.write(async () => {
15827
15984
  if (ctx.canWrite && !await ctx.canWrite())
15828
15985
  throw new Error("Memory source is no longer eligible");
15829
- if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) {
15986
+ if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2) || opts.freeFormOnly && isKinded(record2)) {
15830
15987
  stale = true;
15831
15988
  return;
15832
15989
  }
15990
+ const nextKind = opts.kind !== void 0 ? opts.kind : record2.kind;
15991
+ const nextLevel = levelAfter(record2);
15992
+ assertValidKindLevel(nextKind, nextLevel);
15833
15993
  let observedSources = [];
15834
15994
  let replayedObservation = false;
15835
15995
  if (opts.observationSourceIds?.length) {
@@ -15843,8 +16003,18 @@ async function updateVaultMemoryOp(ctx, id, opts) {
15843
16003
  }
15844
16004
  await record2.update((r) => {
15845
16005
  r._setRaw("content", encryptedContent);
15846
- if (opts.scope !== void 0) {
16006
+ if (opts.level !== void 0) {
16007
+ r._setRaw("level", nextLevel);
16008
+ r._setRaw("scope", scopeForLevel(nextLevel));
16009
+ } else if (opts.scope !== void 0) {
15847
16010
  r._setRaw("scope", opts.scope);
16011
+ r._setRaw("level", nextLevel);
16012
+ }
16013
+ if (opts.kind !== void 0) {
16014
+ r._setRaw("kind", opts.kind);
16015
+ }
16016
+ if (encryptedKindValue !== void 0) {
16017
+ r._setRaw("kind_value", encryptedKindValue);
15848
16018
  }
15849
16019
  if (opts.folderId !== void 0) {
15850
16020
  r._setRaw("folder_id", opts.folderId);
@@ -15903,7 +16073,8 @@ async function updateVaultMemoryOp(ctx, id, opts) {
15903
16073
  ctx.signMessage,
15904
16074
  ctx.embeddedWalletSigner
15905
16075
  );
15906
- } catch {
16076
+ } catch (err) {
16077
+ if (err instanceof MemoryLevelError) throw err;
15907
16078
  return null;
15908
16079
  }
15909
16080
  }
@@ -16039,6 +16210,7 @@ async function supersedeVaultMemoryOp(ctx, id, supersededById) {
16039
16210
  try {
16040
16211
  const record2 = await ctx.vaultMemoryCollection.find(id);
16041
16212
  if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2)) return false;
16213
+ if (isKinded(record2)) return false;
16042
16214
  let successor;
16043
16215
  try {
16044
16216
  successor = await ctx.vaultMemoryCollection.find(supersededById);
@@ -16339,7 +16511,10 @@ function assertVaultScopeForSweep(ctx) {
16339
16511
  }
16340
16512
  async function getDecayCandidatesRawOp(ctx) {
16341
16513
  assertVaultScopeForSweep(ctx);
16342
- const results = await ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx, { includeArchived: true, includeQuarantined: true })).unsafeFetchRaw();
16514
+ const results = await ctx.vaultMemoryCollection.query(
16515
+ ...baseVaultConditions(ctx, { includeArchived: true, includeQuarantined: true }),
16516
+ import_watermelondb23.Q.where("kind", null)
16517
+ ).unsafeFetchRaw();
16343
16518
  return results.map((raw) => ({
16344
16519
  uniqueId: raw.id,
16345
16520
  factType: raw.fact_type ?? null,
@@ -16600,6 +16775,7 @@ async function ingestPublishedPhotoMemoriesOp(ctx, rows) {
16600
16775
  record2._raw.id = row.memoryId;
16601
16776
  record2._setRaw("content", content);
16602
16777
  record2._setRaw("scope", "shared");
16778
+ record2._setRaw("level", "matching");
16603
16779
  record2._setRaw("folder_id", null);
16604
16780
  record2._setRaw("user_id", ctx.userId ?? null);
16605
16781
  record2._setRaw("is_deleted", false);
@@ -17466,6 +17642,7 @@ async function updateVaultFolderOp(ctx, id, opts) {
17466
17642
  for (const memory of memories) {
17467
17643
  updates.push(
17468
17644
  memory.prepareUpdate((r) => {
17645
+ r._setRaw("level", levelForScopeChange(r, opts.scope));
17469
17646
  r._setRaw("scope", opts.scope);
17470
17647
  })
17471
17648
  );
@@ -17487,6 +17664,7 @@ async function deleteVaultFolderOp(ctx, id) {
17487
17664
  const preparedMemories = memories.map(
17488
17665
  (memory) => memory.prepareUpdate((r) => {
17489
17666
  r._setRaw("folder_id", null);
17667
+ r._setRaw("level", levelForScopeChange(r, "private"));
17490
17668
  r._setRaw("scope", "private");
17491
17669
  })
17492
17670
  );
@@ -17523,6 +17701,7 @@ async function moveMemoriesToFolderOp(ctx, memoryIds, folderId) {
17523
17701
  const prepared = memories.map(
17524
17702
  (memory) => memory.prepareUpdate((r) => {
17525
17703
  r._setRaw("folder_id", folderId);
17704
+ r._setRaw("level", levelForScopeChange(r, targetScope));
17526
17705
  r._setRaw("scope", targetScope);
17527
17706
  })
17528
17707
  );
@@ -19855,6 +20034,7 @@ async function retainWithPersistence(content, ctx, options = {}) {
19855
20034
  includeArchived: true,
19856
20035
  ...options.folderId !== void 0 && { folderId: options.folderId }
19857
20036
  });
20037
+ prepared = withoutKindedRows(prepared);
19858
20038
  if (prepared.embeddingFailure || prepared.embeddingsUnavailable) {
19859
20039
  throw new Error(
19860
20040
  "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."
@@ -19896,6 +20076,7 @@ async function retainWithPersistence(content, ctx, options = {}) {
19896
20076
  const resurrect = resurrectFields(existing);
19897
20077
  const updated = await ctx.persistence.update(targetId, {
19898
20078
  content: existing.content,
20079
+ freeFormOnly: true,
19899
20080
  proofCountIncrement: 1,
19900
20081
  observationSourceIds: options.sourceChunkIds,
19901
20082
  sourceChunkIds: mergedSourceIds,
@@ -20024,6 +20205,17 @@ async function retainWithPersistence(content, ctx, options = {}) {
20024
20205
  ...consolidationDecidedCreate && { consolidation: "create" }
20025
20206
  };
20026
20207
  }
20208
+ function withoutKindedRows(prepared) {
20209
+ const kinded = new Set(
20210
+ prepared.memories.filter((m) => m.kind !== null && m.kind !== void 0).map((m) => m.uniqueId)
20211
+ );
20212
+ if (kinded.size === 0) return prepared;
20213
+ return {
20214
+ ...prepared,
20215
+ memories: prepared.memories.filter((m) => !kinded.has(m.uniqueId)),
20216
+ embeddedItems: prepared.embeddedItems.filter((item) => !kinded.has(item.id))
20217
+ };
20218
+ }
20027
20219
  function unionStrings(a, b) {
20028
20220
  return [.../* @__PURE__ */ new Set([...a, ...b])];
20029
20221
  }
@@ -20123,6 +20315,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
20123
20315
  const resurrect = resurrectFields(existing);
20124
20316
  const updated = await ctx.persistence.update(decision.targetId, {
20125
20317
  content: existing.content,
20318
+ freeFormOnly: true,
20126
20319
  proofCountIncrement: 1,
20127
20320
  observationSourceIds: options.sourceChunkIds,
20128
20321
  sourceChunkIds: mergedSourceIds,
@@ -20168,6 +20361,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
20168
20361
  const resurrect = resurrectFields(existing);
20169
20362
  const updated = await ctx.persistence.update(decision.targetId, {
20170
20363
  content: decision.content,
20364
+ freeFormOnly: true,
20171
20365
  proofCountIncrement: 1,
20172
20366
  observationSourceIds: options.sourceChunkIds,
20173
20367
  sourceChunkIds: mergedSourceIds,
@@ -20211,7 +20405,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
20211
20405
  }
20212
20406
  async function assertMergeTargetGoneOrThrow(ctx, targetId) {
20213
20407
  const stillExists = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(targetId) : ctx.persistence.get(targetId));
20214
- if (stillExists) {
20408
+ if (stillExists && (stillExists.kind === null || stillExists.kind === void 0)) {
20215
20409
  throw new Error(`retain: merge into memory ${targetId} failed to persist`);
20216
20410
  }
20217
20411
  }
@@ -22874,6 +23068,65 @@ function createLocalMemoryStore(options) {
22874
23068
  };
22875
23069
  }
22876
23070
 
23071
+ // src/lib/memory/store/memoryKeys.ts
23072
+ var KEY_ID_DOMAIN = "anuma-private-memory-key-id-v1";
23073
+ var MemoryKeyError = class extends Error {
23074
+ constructor(message) {
23075
+ super(message);
23076
+ this.name = "MemoryKeyError";
23077
+ }
23078
+ };
23079
+ async function importAesKey(hex) {
23080
+ return crypto.subtle.importKey(
23081
+ "raw",
23082
+ hexToBytes(hex).buffer,
23083
+ { name: "AES-GCM" },
23084
+ false,
23085
+ ["encrypt", "decrypt"]
23086
+ );
23087
+ }
23088
+ async function deriveMemoryKeyRing(signatureHex) {
23089
+ const v3Hex = await deriveKeyFromSignatureV3(signatureHex);
23090
+ const digest = await crypto.subtle.digest(
23091
+ "SHA-256",
23092
+ new TextEncoder().encode(`${KEY_ID_DOMAIN}:${v3Hex}`)
23093
+ );
23094
+ const keyId = "v3:" + Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
23095
+ return {
23096
+ keyId,
23097
+ v3: await importAesKey(v3Hex),
23098
+ v2: await importAesKey(await deriveKeyFromSignature(signatureHex))
23099
+ };
23100
+ }
23101
+ async function decryptWith(value, rings) {
23102
+ const version = value.startsWith("enc:v3:") ? "v3" : "v2";
23103
+ for (const ring of rings) {
23104
+ try {
23105
+ return await decryptDataWithKey(value.slice(`enc:${version}:`.length), ring[version]);
23106
+ } catch {
23107
+ continue;
23108
+ }
23109
+ }
23110
+ throw new MemoryKeyError(`No supplied key decrypts this enc:${version} field`);
23111
+ }
23112
+ function memoryCipher(canonical) {
23113
+ return {
23114
+ encrypt: async (plaintext) => `enc:v3:${await encryptDataWithKey(plaintext, canonical.v3)}`,
23115
+ decrypt: async (ciphertext) => {
23116
+ if (!ciphertext.startsWith("enc:v3:") || !isEncrypted(ciphertext))
23117
+ throw new MemoryKeyError("Remote memory content must be enc:v3 ciphertext");
23118
+ return decryptWith(ciphertext, [canonical]);
23119
+ }
23120
+ };
23121
+ }
23122
+ async function reencryptMemoryField(value, canonical, fallbacks = []) {
23123
+ const { encrypt } = memoryCipher(canonical);
23124
+ if (!value.startsWith("enc:")) return encrypt(value);
23125
+ if (!isEncrypted(value))
23126
+ throw new MemoryKeyError("Field has an encryption prefix but an invalid payload");
23127
+ return encrypt(await decryptWith(value, [canonical, ...fallbacks]));
23128
+ }
23129
+
22877
23130
  // src/lib/memory/store/remotePersistence.ts
22878
23131
  var RemoteMemoryError = class extends Error {
22879
23132
  constructor(message, status, code) {
@@ -22926,6 +23179,30 @@ var candidateListLimits = [
22926
23179
  ["memory_ids", 1e3],
22927
23180
  ["force_ids", 100]
22928
23181
  ];
23182
+ var queryListLimits = [
23183
+ ["scopes", 20],
23184
+ ["fact_types", 20],
23185
+ ["visibility", 20],
23186
+ ["memory_ids", 1e3],
23187
+ ["topics", 100]
23188
+ ];
23189
+ var queryFields = [
23190
+ "include_deleted",
23191
+ "include_archived",
23192
+ "include_quarantined",
23193
+ "include_superseded",
23194
+ "archived_only",
23195
+ "scopes",
23196
+ "fact_types",
23197
+ "visibility",
23198
+ "memory_ids",
23199
+ "topics",
23200
+ "updated_after",
23201
+ "order",
23202
+ "cursor",
23203
+ "limit",
23204
+ "include_embeddings"
23205
+ ];
22929
23206
  function record(value) {
22930
23207
  return typeof value === "object" && value !== null && !Array.isArray(value);
22931
23208
  }
@@ -23260,6 +23537,35 @@ async function createRemoteMemoryPersistence(options) {
23260
23537
  throw new Error("Invalid nearby batch response");
23261
23538
  return Promise.all(result.items.map((item, i) => decodeCommitted(item, prepared[i])));
23262
23539
  },
23540
+ query: async (queryOptions = {}) => {
23541
+ const { signal, ...query } = queryOptions;
23542
+ if (query.limit !== void 0 && (!Number.isInteger(query.limit) || query.limit < 1 || query.limit > 200))
23543
+ throw new Error("Page limit must be 1\u2013200");
23544
+ for (const [key, max] of queryListLimits) {
23545
+ const values = query[key];
23546
+ if (values && values.length > max)
23547
+ throw new Error(`Query ${key} accepts at most ${max} entries (got ${values.length})`);
23548
+ }
23549
+ const page = await request(
23550
+ "/memories/query",
23551
+ {
23552
+ method: "POST",
23553
+ body: JSON.stringify(
23554
+ Object.fromEntries(
23555
+ queryFields.filter((key) => query[key] !== void 0).map((key) => [key, query[key]])
23556
+ )
23557
+ )
23558
+ },
23559
+ signal
23560
+ );
23561
+ 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")
23562
+ throw new Error("Invalid nearby private-memory page");
23563
+ return {
23564
+ ...await decodeAll(page.items),
23565
+ ...page.next_cursor !== void 0 && { next_cursor: page.next_cursor },
23566
+ ...page.changes_cursor !== void 0 && { changes_cursor: page.changes_cursor }
23567
+ };
23568
+ },
23263
23569
  candidateSet,
23264
23570
  candidates: async (embedding, candidateOptions = {}) => decodeAll((await fetchCandidates(embedding, candidateOptions, false)).items)
23265
23571
  };
@@ -23285,6 +23591,9 @@ function sourceIds(value) {
23285
23591
  return [];
23286
23592
  }
23287
23593
  }
23594
+ function isMemoryLevel(value) {
23595
+ return MEMORY_LEVELS.includes(value);
23596
+ }
23288
23597
  function stored(row) {
23289
23598
  return {
23290
23599
  uniqueId: row.memory_id,
@@ -23292,6 +23601,9 @@ function stored(row) {
23292
23601
  scope: row.scope,
23293
23602
  folderId: row.folder_id ?? null,
23294
23603
  userId: null,
23604
+ kind: row.kind ?? null,
23605
+ kindValue: row.kind_value ?? null,
23606
+ ...isMemoryLevel(row.level) && { level: row.level },
23295
23607
  embedding: row.embedding ? JSON.stringify(row.embedding) : null,
23296
23608
  embeddingModel: row.embedding_model ?? null,
23297
23609
  sourceChunkIds: row.source_chunk_ids === void 0 ? null : sourceIds(row.source_chunk_ids),
@@ -23513,7 +23825,8 @@ function createRemoteMemoryPipeline(options) {
23513
23825
  create: (input) => write(createRow(input), 0),
23514
23826
  update: async (id, patch) => {
23515
23827
  const existing = await get(id);
23516
- if (!existing) return null;
23828
+ if (!existing || patch.freeFormOnly && existing.kind !== null && existing.kind !== void 0)
23829
+ return null;
23517
23830
  const snapshot = snapshots.get(id);
23518
23831
  const memory = {
23519
23832
  ...snapshot.memory,
@@ -23642,6 +23955,490 @@ function createRemoteMemoryPipeline(options) {
23642
23955
  };
23643
23956
  }
23644
23957
 
23958
+ // src/lib/memory/store/remoteStore.ts
23959
+ var import_uuid6 = require("uuid");
23960
+ init_logger();
23961
+ function relevant(change, options) {
23962
+ return options.includeDeleted ? change === "membership" : change !== "embedding" || !!options.embeddings;
23963
+ }
23964
+ function safely(onChange) {
23965
+ try {
23966
+ onChange();
23967
+ } catch (error) {
23968
+ getLogger().warn("[memory/remote-store] Subscriber threw:", error);
23969
+ }
23970
+ }
23971
+ var MAX_BATCH = 50;
23972
+ var MAX_QUERY_IDS = 1e3;
23973
+ var MAX_QUERY_TOPICS = 100;
23974
+ var MAX_QUERY_FILTER = 20;
23975
+ var RemoteMemoryPartialCreateError = class extends Error {
23976
+ constructor(created, cause) {
23977
+ super(`createMany stored ${created.length} memories before a batch failed`);
23978
+ this.created = created;
23979
+ this.cause = cause;
23980
+ this.name = "RemoteMemoryPartialCreateError";
23981
+ }
23982
+ };
23983
+ function warnFailed(failed) {
23984
+ if (failed.length)
23985
+ getLogger().warn(
23986
+ `[memory/remote-store] Skipping ${failed.length} undecryptable row(s)`,
23987
+ failed.map((failure) => failure.memory_id)
23988
+ );
23989
+ }
23990
+ function bounded(filters, key) {
23991
+ const values = filters[key];
23992
+ if (!values || values.length <= MAX_QUERY_FILTER) return [filters];
23993
+ return chunks(values, MAX_QUERY_FILTER).map((chunk) => ({ ...filters, [key]: chunk }));
23994
+ }
23995
+ function chunks(values, size) {
23996
+ const out = [];
23997
+ for (let i = 0; i < values.length; i += size) out.push(values.slice(i, i + size));
23998
+ return out;
23999
+ }
24000
+ function stateFilters(options) {
24001
+ return {
24002
+ include_deleted: options.includeDeleted,
24003
+ include_archived: options.includeArchived,
24004
+ include_quarantined: options.includeQuarantined,
24005
+ include_superseded: options.includeSuperseded
24006
+ };
24007
+ }
24008
+ function hidden(memory, options) {
24009
+ if (memory.trust_tier === "quarantined") return true;
24010
+ if (options.includeDeleted) return false;
24011
+ return !!memory.is_deleted || memory.archived_at !== void 0 && memory.archived_at !== null || !!memory.superseded_by;
24012
+ }
24013
+ function subscriptionKey({ memory, version }, options) {
24014
+ if (hidden(memory, options)) return void 0;
24015
+ if (options.includeDeleted) return String(!!memory.is_deleted);
24016
+ return JSON.stringify([
24017
+ options.embeddings ? version : null,
24018
+ memory.content,
24019
+ memory.scope,
24020
+ memory.updated_at,
24021
+ memory.fact_type,
24022
+ memory.event_time_start,
24023
+ memory.event_time_end,
24024
+ memory.event_time_kind,
24025
+ memory.trust_tier,
24026
+ memory.visibility,
24027
+ memory.published_at,
24028
+ memory.geohash,
24029
+ memory.topics,
24030
+ memory.topics_user_managed,
24031
+ memory.media,
24032
+ memory.source
24033
+ ]);
24034
+ }
24035
+ function topicInputs(topics, source) {
24036
+ return topics.flatMap((topic) => {
24037
+ const name = (typeof topic === "string" ? topic : topic.name).trim();
24038
+ const kind = typeof topic === "string" ? void 0 : topic.kind;
24039
+ return name ? [{ name, ...kind && { kind }, source }] : [];
24040
+ });
24041
+ }
24042
+ function mergeTopics(existing, added) {
24043
+ const byName = /* @__PURE__ */ new Map();
24044
+ for (const topic of [...existing, ...added]) {
24045
+ const key = normalizeEntityName(topic.name);
24046
+ if (!byName.has(key)) byName.set(key, topic);
24047
+ }
24048
+ return [...byName.values()];
24049
+ }
24050
+ function canonicalTopics(row) {
24051
+ return new Set((parseTopics(row.topics) ?? []).map((topic) => normalizeEntityName(topic.name)));
24052
+ }
24053
+ function createRemoteMemoryStore(options) {
24054
+ const { persistence, embeddingOptions } = options;
24055
+ const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
24056
+ const pollIntervalMs = options.pollIntervalMs ?? 6e4;
24057
+ const pipeline = createRemoteMemoryPipeline(options);
24058
+ const subscribers = /* @__PURE__ */ new Set();
24059
+ const seen = /* @__PURE__ */ new Map();
24060
+ let timer;
24061
+ const notify = (change, records = []) => {
24062
+ if (timer) for (const record2 of records) seen.set(record2.memory.memory_id, record2);
24063
+ for (const subscriber of [...subscribers])
24064
+ if (relevant(change, subscriber.options)) safely(subscriber.onChange);
24065
+ };
24066
+ const enumerate = async (filters, max = Infinity) => {
24067
+ const records = [];
24068
+ let cursor2;
24069
+ do {
24070
+ const page = await persistence.query({
24071
+ ...filters,
24072
+ limit: Math.min(200, Math.max(1, max - records.length)),
24073
+ ...cursor2 && { cursor: cursor2 }
24074
+ });
24075
+ warnFailed(page.failed);
24076
+ records.push(...page.items);
24077
+ cursor2 = page.next_cursor;
24078
+ } while (cursor2 && records.length < max);
24079
+ return records.slice(0, max);
24080
+ };
24081
+ const enumerateIds = async (ids, filters) => (await Promise.all(
24082
+ chunks([...new Set(ids)], MAX_QUERY_IDS).map(
24083
+ (memory_ids) => enumerate({ ...filters, memory_ids })
24084
+ )
24085
+ )).flat();
24086
+ const queues = /* @__PURE__ */ new Map();
24087
+ const serialized = (id, task) => {
24088
+ const run = (queues.get(id) ?? Promise.resolve()).then(task, task);
24089
+ const settled = run.catch(() => void 0);
24090
+ queues.set(id, settled);
24091
+ void settled.then(() => {
24092
+ if (queues.get(id) === settled) queues.delete(id);
24093
+ });
24094
+ return run;
24095
+ };
24096
+ const live = async (id) => {
24097
+ const record2 = await persistence.get(id);
24098
+ return record2 && !record2.memory.is_deleted ? record2 : null;
24099
+ };
24100
+ const mutate = async (id, change, edit) => serialized(id, async () => {
24101
+ const record2 = await live(id);
24102
+ if (!record2) return null;
24103
+ const next = edit(structuredClone(record2.memory));
24104
+ if (!next) return null;
24105
+ const saved = await persistence.put(next, record2);
24106
+ notify(change, [saved]);
24107
+ return saved;
24108
+ });
24109
+ const embedInBackground = ({ memory: { memory_id: id, content } }) => {
24110
+ generateEmbedding(content, embeddingOptions).then(
24111
+ (vector) => serialized(id, async () => {
24112
+ const current = await live(id);
24113
+ if (!current || current.memory.content !== content || current.memory.embedding?.length)
24114
+ return;
24115
+ const saved = await persistence.put(
24116
+ { ...current.memory, embedding: storedVector(vector), embedding_model: model },
24117
+ current
24118
+ );
24119
+ notify("embedding", [saved]);
24120
+ })
24121
+ ).catch((error) => {
24122
+ getLogger().warn("[memory/remote-store] Failed to embed memory:", error);
24123
+ });
24124
+ };
24125
+ const newRow = (input) => {
24126
+ const now = Date.now();
24127
+ const scope = input.scope ?? "private";
24128
+ return {
24129
+ memory_id: (0, import_uuid6.v7)(),
24130
+ content: input.content,
24131
+ scope,
24132
+ level: levelFromScope(scope),
24133
+ created_at: now,
24134
+ updated_at: now,
24135
+ is_deleted: false,
24136
+ ...input.embedding !== void 0 && {
24137
+ embedding: storedVector(JSON.parse(input.embedding)),
24138
+ embedding_model: input.embeddingModel ?? model
24139
+ },
24140
+ proof_count: 1,
24141
+ source: "manual",
24142
+ ...input.eventTime && {
24143
+ event_time_start: input.eventTime.start ?? void 0,
24144
+ event_time_end: input.eventTime.end ?? void 0,
24145
+ event_time_kind: input.eventTime.kind ?? void 0
24146
+ },
24147
+ fact_type: input.factType,
24148
+ geohash: input.geohash,
24149
+ visibility: "private",
24150
+ twin_opt_in: false
24151
+ };
24152
+ };
24153
+ const created = (records, inputs) => {
24154
+ records.forEach((record2, i) => {
24155
+ if (inputs[i].embedding === void 0) embedInBackground(record2);
24156
+ });
24157
+ notify("membership", records);
24158
+ return records.map((record2) => stored(record2.memory));
24159
+ };
24160
+ const asStored = (record2) => record2 ? stored(record2.memory) : null;
24161
+ const everyState = {
24162
+ include_deleted: true,
24163
+ include_archived: true,
24164
+ include_quarantined: true,
24165
+ include_superseded: true
24166
+ };
24167
+ const changesSince = async (cursor2, pending2) => {
24168
+ const records = [];
24169
+ const failed = /* @__PURE__ */ new Set();
24170
+ const collect = (page) => {
24171
+ warnFailed(page.failed);
24172
+ records.push(...page.items);
24173
+ for (const failure of page.failed) failed.add(failure.memory_id);
24174
+ };
24175
+ let resume = cursor2;
24176
+ let next;
24177
+ do {
24178
+ const page = await persistence.query({
24179
+ ...everyState,
24180
+ order: "changed",
24181
+ limit: 200,
24182
+ ...(next ?? resume) && { cursor: next ?? resume }
24183
+ });
24184
+ collect(page);
24185
+ resume = page.changes_cursor ?? resume;
24186
+ next = page.next_cursor;
24187
+ } while (next);
24188
+ for (const memory_ids of chunks([...pending2], MAX_QUERY_IDS)) {
24189
+ let retry;
24190
+ do {
24191
+ const page = await persistence.query({
24192
+ ...everyState,
24193
+ memory_ids,
24194
+ limit: 200,
24195
+ ...retry && { cursor: retry }
24196
+ });
24197
+ collect(page);
24198
+ retry = page.next_cursor;
24199
+ } while (retry);
24200
+ }
24201
+ return { records, resume, failed };
24202
+ };
24203
+ let generation = 0;
24204
+ let ready = false;
24205
+ let cursor;
24206
+ let pending = /* @__PURE__ */ new Set();
24207
+ let polling = false;
24208
+ const poll = () => {
24209
+ if (polling) return;
24210
+ polling = true;
24211
+ const current = generation;
24212
+ changesSince(cursor, pending).then(({ records, resume, failed }) => {
24213
+ if (current !== generation) return;
24214
+ const changed = /* @__PURE__ */ new Set();
24215
+ for (const record2 of records) {
24216
+ const id = record2.memory.memory_id;
24217
+ const previous = seen.get(id);
24218
+ seen.set(id, record2);
24219
+ if (!ready) continue;
24220
+ for (const subscriber of subscribers) {
24221
+ const before = previous && subscriptionKey(previous, subscriber.options);
24222
+ if (before !== subscriptionKey(record2, subscriber.options)) changed.add(subscriber);
24223
+ }
24224
+ }
24225
+ ready = true;
24226
+ cursor = resume;
24227
+ pending = failed;
24228
+ for (const subscriber of changed)
24229
+ if (subscribers.has(subscriber)) safely(subscriber.onChange);
24230
+ }).catch((error) => {
24231
+ getLogger().warn("[memory/remote-store] Subscription poll failed:", error);
24232
+ }).finally(() => {
24233
+ polling = false;
24234
+ });
24235
+ };
24236
+ return {
24237
+ list: async (listOptions = {}) => {
24238
+ const order = listOptions.since ? "updated" : "created";
24239
+ const filters = {
24240
+ ...stateFilters(listOptions),
24241
+ include_embeddings: true,
24242
+ order,
24243
+ ...listOptions.scopes?.length && { scopes: listOptions.scopes },
24244
+ ...listOptions.factTypes?.length && { fact_types: listOptions.factTypes },
24245
+ ...listOptions.visibility?.length && { visibility: listOptions.visibility },
24246
+ ...listOptions.since && { updated_after: listOptions.since.getTime() }
24247
+ };
24248
+ const max = listOptions.limit && listOptions.limit > 0 ? listOptions.limit : Infinity;
24249
+ const variants = bounded(filters, "scopes").flatMap((f) => bounded(f, "fact_types"));
24250
+ if (!listOptions.memoryIds && variants.length === 1)
24251
+ return (await enumerate(filters, max)).map((r) => stored(r.memory));
24252
+ const fetched = await Promise.all(
24253
+ variants.map(
24254
+ (variant) => listOptions.memoryIds ? enumerateIds(listOptions.memoryIds, variant) : enumerate(variant, max)
24255
+ )
24256
+ );
24257
+ const rows = [...new Map(fetched.flat().map((r) => [r.memory.memory_id, r])).values()].map((record2) => stored(record2.memory)).sort(
24258
+ (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)
24259
+ );
24260
+ return rows.slice(0, max);
24261
+ },
24262
+ get: async (id) => asStored(await live(id)),
24263
+ listArchived: async () => (await enumerate({ archived_only: true, order: "archived", include_embeddings: true })).map(
24264
+ (record2) => stored(record2.memory)
24265
+ ),
24266
+ memoriesByTopics: async (names) => {
24267
+ const wanted = new Set(names.map(normalizeEntityName).filter(Boolean));
24268
+ const out = /* @__PURE__ */ new Map();
24269
+ const pages = await Promise.all(
24270
+ chunks([...wanted], MAX_QUERY_TOPICS).map((topics) => enumerate({ topics }))
24271
+ );
24272
+ for (const { memory } of pages.flat()) {
24273
+ const matched = [...canonicalTopics(memory)].filter((name) => wanted.has(name));
24274
+ if (matched.length) out.set(memory.memory_id, new Set(matched));
24275
+ }
24276
+ return out;
24277
+ },
24278
+ topicsByMemories: async (memoryIds) => {
24279
+ const out = /* @__PURE__ */ new Map();
24280
+ for (const { memory } of await enumerateIds(memoryIds, {
24281
+ include_archived: true,
24282
+ include_superseded: true,
24283
+ include_quarantined: true
24284
+ })) {
24285
+ const topics = canonicalTopics(memory);
24286
+ if (topics.size) out.set(memory.memory_id, topics);
24287
+ }
24288
+ return out;
24289
+ },
24290
+ create: async (input) => {
24291
+ const record2 = await persistence.put(newRow(input), 0);
24292
+ return created([record2], [input])[0];
24293
+ },
24294
+ createMany: async (inputs) => {
24295
+ const out = [];
24296
+ for (const batch of chunks(inputs, MAX_BATCH)) {
24297
+ let records;
24298
+ try {
24299
+ records = await persistence.putMany(
24300
+ batch.map((input) => ({ memory: newRow(input), expectedVersion: 0 }))
24301
+ );
24302
+ } catch (error) {
24303
+ if (out.length === 0) throw error;
24304
+ throw new RemoteMemoryPartialCreateError(out, error);
24305
+ }
24306
+ out.push(...created(records, batch));
24307
+ }
24308
+ return out;
24309
+ },
24310
+ update: async (id, patch) => {
24311
+ const saved = await mutate(id, "edit", (memory) => {
24312
+ if (memory.superseded_by) return null;
24313
+ memory.content = patch.content;
24314
+ memory.updated_at = Date.now();
24315
+ if (patch.scope !== void 0) {
24316
+ memory.level = levelForScopeChange(
24317
+ { level: memory.level, scope: memory.scope },
24318
+ patch.scope
24319
+ );
24320
+ memory.scope = patch.scope;
24321
+ }
24322
+ if (patch.factType !== void 0) memory.fact_type = patch.factType ?? void 0;
24323
+ if (patch.eventTime !== void 0) {
24324
+ memory.event_time_start = patch.eventTime?.start ?? void 0;
24325
+ memory.event_time_end = patch.eventTime?.end ?? void 0;
24326
+ memory.event_time_kind = patch.eventTime?.kind ?? void 0;
24327
+ }
24328
+ if (patch.embedding === void 0 || patch.embedding === null) {
24329
+ memory.embedding = [];
24330
+ delete memory.embedding_model;
24331
+ } else {
24332
+ memory.embedding = storedVector(JSON.parse(patch.embedding));
24333
+ memory.embedding_model = patch.embeddingModel ?? model;
24334
+ }
24335
+ return memory;
24336
+ });
24337
+ if (saved && patch.embedding === void 0) embedInBackground(saved);
24338
+ return asStored(saved);
24339
+ },
24340
+ delete: async (id) => !!await mutate(id, "membership", (memory) => ({ ...memory, is_deleted: true })),
24341
+ supersede: async (id, supersededById) => {
24342
+ if (id === supersededById) return false;
24343
+ const [first, second] = [id, supersededById].sort();
24344
+ return serialized(
24345
+ first,
24346
+ () => serialized(second, async () => {
24347
+ const [old, next] = await Promise.all([live(id), live(supersededById)]);
24348
+ if (!old || !next || old.memory.superseded_by || next.memory.superseded_by) return false;
24349
+ if (old.memory.kind !== void 0 && old.memory.kind !== null) return false;
24350
+ const saved = await persistence.putMany([
24351
+ {
24352
+ memory: { ...old.memory, superseded_by: supersededById, superseded_at: Date.now() },
24353
+ expectedVersion: old
24354
+ },
24355
+ { memory: next.memory, expectedVersion: next }
24356
+ ]);
24357
+ notify("membership", saved);
24358
+ return true;
24359
+ })
24360
+ );
24361
+ },
24362
+ archive: async (id) => !!await mutate(
24363
+ id,
24364
+ "edit",
24365
+ (memory) => memory.archived_at === void 0 || memory.archived_at === null ? { ...memory, archived_at: Date.now() } : null
24366
+ ),
24367
+ restore: (id) => serialized(id, async () => {
24368
+ const record2 = await live(id);
24369
+ if (!record2) return false;
24370
+ if (record2.memory.archived_at === void 0 || record2.memory.archived_at === null)
24371
+ return true;
24372
+ const { archived_at: _archivedAt, ...memory } = record2.memory;
24373
+ notify("edit", [await persistence.put(memory, record2)]);
24374
+ return true;
24375
+ }),
24376
+ setTopics: async (memoryId, topics) => asStored(
24377
+ await mutate(memoryId, "edit", (memory) => ({
24378
+ ...memory,
24379
+ topics: serializeTopics(mergeTopics([], topicInputs(topics, "user"))),
24380
+ topics_user_managed: true,
24381
+ topics_updated_at: Date.now()
24382
+ }))
24383
+ ),
24384
+ addTopics: async (memoryId, topics) => {
24385
+ const added = topicInputs(topics, "auto");
24386
+ const saved = await mutate(memoryId, "edit", (memory) => ({
24387
+ ...memory,
24388
+ topics: serializeTopics(mergeTopics(parseTopics(memory.topics) ?? [], added)),
24389
+ topics_updated_at: Date.now()
24390
+ }));
24391
+ if (!saved) return [];
24392
+ const now = /* @__PURE__ */ new Date();
24393
+ return mergeTopics([], added).map(
24394
+ (topic) => ({
24395
+ uniqueId: normalizeEntityName(topic.name),
24396
+ canonicalName: normalizeEntityName(topic.name),
24397
+ kind: topic.kind ?? null,
24398
+ createdAt: now,
24399
+ updatedAt: now
24400
+ })
24401
+ );
24402
+ },
24403
+ setVisibility: async (id, visibility, visibilityOptions) => asStored(
24404
+ await mutate(id, "edit", (memory) => {
24405
+ memory.visibility = visibility;
24406
+ if (visibility === "private") delete memory.published_at;
24407
+ else memory.published_at ?? (memory.published_at = Date.now());
24408
+ if (visibilityOptions?.twinOptIn !== void 0)
24409
+ memory.twin_opt_in = visibilityOptions.twinOptIn;
24410
+ return memory;
24411
+ })
24412
+ ),
24413
+ recall: (query, recallOptions) => pipeline.recall(query, recallOptions),
24414
+ retain: async (content, retainOptions) => {
24415
+ const result = await pipeline.retain(content, retainOptions);
24416
+ if (result.action === "create" || result.action === "supersede") notify("membership");
24417
+ else if (result.action === "update" || result.action === "merge") notify("edit");
24418
+ return result;
24419
+ },
24420
+ subscribe: (onChange, subscribeOptions = {}) => {
24421
+ const subscriber = { onChange, options: subscribeOptions };
24422
+ subscribers.add(subscriber);
24423
+ if (pollIntervalMs > 0 && !timer) {
24424
+ timer = setInterval(poll, pollIntervalMs);
24425
+ poll();
24426
+ }
24427
+ return () => {
24428
+ subscribers.delete(subscriber);
24429
+ if (subscribers.size || !timer) return;
24430
+ clearInterval(timer);
24431
+ timer = void 0;
24432
+ generation++;
24433
+ seen.clear();
24434
+ ready = false;
24435
+ cursor = void 0;
24436
+ pending = /* @__PURE__ */ new Set();
24437
+ };
24438
+ }
24439
+ };
24440
+ }
24441
+
23645
24442
  // src/lib/memory/synthesizeProfile.ts
23646
24443
  init_internalFlowMarker();
23647
24444
  init_logger();
@@ -37621,7 +38418,11 @@ function useWalletBinding(options = {}) {
37621
38418
  LoggerProvider,
37622
38419
  MAX_HOPS,
37623
38420
  MEDIUM_TTL_MS,
38421
+ MEMORY_KINDS,
38422
+ MEMORY_LEVELS,
37624
38423
  MemoryEntityModel,
38424
+ MemoryKeyError,
38425
+ MemoryLevelError,
37625
38426
  NEVER_TTL_MS,
37626
38427
  NODE_BUDGET,
37627
38428
  PAST_EVENT_GRACE_MS,
@@ -37635,6 +38436,7 @@ function useWalletBinding(options = {}) {
37635
38436
  RECALL_MAX_LIMIT,
37636
38437
  RECALL_TOOL_NAME,
37637
38438
  RemoteMemoryError,
38439
+ RemoteMemoryPartialCreateError,
37638
38440
  RerankerUnavailableError,
37639
38441
  SDK_SCHEMA_VERSION,
37640
38442
  SERVER_TOOL_DEPENDENCY_SETS,
@@ -37728,6 +38530,7 @@ function useWalletBinding(options = {}) {
37728
38530
  createRecallTool,
37729
38531
  createRemoteMemoryPersistence,
37730
38532
  createRemoteMemoryPipeline,
38533
+ createRemoteMemoryStore,
37731
38534
  createSavedToolOp,
37732
38535
  createServerToolsFilter,
37733
38536
  createStockPricePreProcessor,
@@ -37759,6 +38562,7 @@ function useWalletBinding(options = {}) {
37759
38562
  deleteVaultMemoryOp,
37760
38563
  dequantizeEmbedding,
37761
38564
  deriveKeyFromSignatureBytes,
38565
+ deriveMemoryKeyRing,
37762
38566
  eagerEmbedContent,
37763
38567
  embedAllMessages,
37764
38568
  embedMessage,
@@ -37898,6 +38702,7 @@ function useWalletBinding(options = {}) {
37898
38702
  linkMemoryEntitiesOp,
37899
38703
  maskScopedEmbeddingCache,
37900
38704
  mediaToStored,
38705
+ memoryCipher,
37901
38706
  migrateCalendarToken,
37902
38707
  migrateDisplayResult,
37903
38708
  migrateDriveToken,
@@ -37919,6 +38724,7 @@ function useWalletBinding(options = {}) {
37919
38724
  rankProfileCandidates,
37920
38725
  readEncryptedFile,
37921
38726
  recall,
38727
+ reencryptMemoryField,
37922
38728
  reflect,
37923
38729
  refreshCalendarToken,
37924
38730
  refreshDriveToken,