@anuma/sdk 6.35.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.
@@ -1427,6 +1427,7 @@ __export(index_exports, {
1427
1427
  MEMORY_KINDS: () => MEMORY_KINDS,
1428
1428
  MEMORY_LEVELS: () => MEMORY_LEVELS,
1429
1429
  MemoryEntityModel: () => MemoryEntity,
1430
+ MemoryKeyError: () => MemoryKeyError,
1430
1431
  MemoryLevelError: () => MemoryLevelError,
1431
1432
  NEVER_TTL_MS: () => NEVER_TTL_MS,
1432
1433
  NODE_BUDGET: () => NODE_BUDGET,
@@ -1441,6 +1442,7 @@ __export(index_exports, {
1441
1442
  RECALL_MAX_LIMIT: () => RECALL_MAX_LIMIT,
1442
1443
  RECALL_TOOL_NAME: () => RECALL_TOOL_NAME,
1443
1444
  RemoteMemoryError: () => RemoteMemoryError,
1445
+ RemoteMemoryPartialCreateError: () => RemoteMemoryPartialCreateError,
1444
1446
  RerankerUnavailableError: () => RerankerUnavailableError,
1445
1447
  SDK_SCHEMA_VERSION: () => SDK_SCHEMA_VERSION,
1446
1448
  SERVER_TOOL_DEPENDENCY_SETS: () => SERVER_TOOL_DEPENDENCY_SETS,
@@ -1534,6 +1536,7 @@ __export(index_exports, {
1534
1536
  createRecallTool: () => createRecallTool,
1535
1537
  createRemoteMemoryPersistence: () => createRemoteMemoryPersistence,
1536
1538
  createRemoteMemoryPipeline: () => createRemoteMemoryPipeline,
1539
+ createRemoteMemoryStore: () => createRemoteMemoryStore,
1537
1540
  createSavedToolOp: () => createSavedToolOp,
1538
1541
  createServerToolsFilter: () => createServerToolsFilter,
1539
1542
  createStockPricePreProcessor: () => createStockPricePreProcessor,
@@ -1565,6 +1568,7 @@ __export(index_exports, {
1565
1568
  deleteVaultMemoryOp: () => deleteVaultMemoryOp,
1566
1569
  dequantizeEmbedding: () => dequantizeEmbedding,
1567
1570
  deriveKeyFromSignatureBytes: () => deriveKeyFromSignatureBytes,
1571
+ deriveMemoryKeyRing: () => deriveMemoryKeyRing,
1568
1572
  eagerEmbedContent: () => eagerEmbedContent,
1569
1573
  embedAllMessages: () => embedAllMessages,
1570
1574
  embedMessage: () => embedMessage,
@@ -1704,6 +1708,7 @@ __export(index_exports, {
1704
1708
  linkMemoryEntitiesOp: () => linkMemoryEntitiesOp,
1705
1709
  maskScopedEmbeddingCache: () => maskScopedEmbeddingCache,
1706
1710
  mediaToStored: () => mediaToStored,
1711
+ memoryCipher: () => memoryCipher,
1707
1712
  migrateCalendarToken: () => migrateCalendarToken,
1708
1713
  migrateDisplayResult: () => migrateDisplayResult,
1709
1714
  migrateDriveToken: () => migrateDriveToken,
@@ -1725,6 +1730,7 @@ __export(index_exports, {
1725
1730
  rankProfileCandidates: () => rankProfileCandidates,
1726
1731
  readEncryptedFile: () => readEncryptedFile,
1727
1732
  recall: () => recall,
1733
+ reencryptMemoryField: () => reencryptMemoryField,
1728
1734
  reflect: () => reflect,
1729
1735
  refreshCalendarToken: () => refreshCalendarToken,
1730
1736
  refreshDriveToken: () => refreshDriveToken,
@@ -1904,9 +1910,9 @@ function createSseClient({
1904
1910
  if (done) break;
1905
1911
  buffer += value;
1906
1912
  buffer = buffer.replace(/\r\n?/g, "\n");
1907
- const chunks = buffer.split("\n\n");
1908
- buffer = chunks.pop() ?? "";
1909
- for (const chunk of chunks) {
1913
+ const chunks2 = buffer.split("\n\n");
1914
+ buffer = chunks2.pop() ?? "";
1915
+ for (const chunk of chunks2) {
1910
1916
  const lines = chunk.split("\n");
1911
1917
  const dataLines = [];
1912
1918
  let eventName;
@@ -6558,14 +6564,14 @@ async function updateMessageEmbeddingOp(ctx, uniqueId, vector, embeddingModel) {
6558
6564
  });
6559
6565
  return messageToStored(message, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
6560
6566
  }
6561
- async function updateMessageChunksOp(ctx, uniqueId, chunks, embeddingModel) {
6567
+ async function updateMessageChunksOp(ctx, uniqueId, chunks2, embeddingModel) {
6562
6568
  let message;
6563
6569
  try {
6564
6570
  message = await ctx.messagesCollection.find(uniqueId);
6565
6571
  } catch {
6566
6572
  return null;
6567
6573
  }
6568
- const storedChunks = chunks.map(({ text: _text, ...rest }) => rest);
6574
+ const storedChunks = chunks2.map(({ text: _text, ...rest }) => rest);
6569
6575
  await ctx.database.write(async () => {
6570
6576
  await message.update((msg) => {
6571
6577
  msg._setRaw("chunks", JSON.stringify(storedChunks));
@@ -6609,12 +6615,12 @@ async function stripLegacyChunkTextOp(ctx) {
6609
6615
  const messages = await ctx.messagesCollection.query(import_watermelondb2.Q.where("id", import_watermelondb2.Q.oneOf(changedIds))).fetch();
6610
6616
  const updates = messages.flatMap((message) => {
6611
6617
  const raw = message._raw;
6612
- const chunks = chunksWithoutText(raw.chunks);
6613
- if (!chunks) return [];
6618
+ const chunks2 = chunksWithoutText(raw.chunks);
6619
+ if (!chunks2) return [];
6614
6620
  const updatedAt = raw.updated_at;
6615
6621
  return [
6616
6622
  message.prepareUpdate((msg) => {
6617
- msg._setRaw("chunks", JSON.stringify(chunks));
6623
+ msg._setRaw("chunks", JSON.stringify(chunks2));
6618
6624
  msg._setRaw("updated_at", updatedAt);
6619
6625
  })
6620
6626
  ];
@@ -6824,15 +6830,15 @@ async function searchChunksOp(ctx, queryVector, options) {
6824
6830
  }
6825
6831
  continue;
6826
6832
  }
6827
- const chunks = await readRawJsonField(message, "chunks", ctx.walletAddress);
6828
- if (chunks && chunks.length > 0) {
6829
- const vectors = chunks.map(
6833
+ const chunks2 = await readRawJsonField(message, "chunks", ctx.walletAddress);
6834
+ if (chunks2 && chunks2.length > 0) {
6835
+ const vectors = chunks2.map(
6830
6836
  (chunk) => decodeChunkVector(chunk.vector, () => {
6831
6837
  unreadableVectors++;
6832
6838
  })
6833
6839
  );
6834
6840
  chunkCache?.set(message.id, { version, chunks: vectors });
6835
- for (let ci = 0; ci < chunks.length; ci++) {
6841
+ for (let ci = 0; ci < chunks2.length; ci++) {
6836
6842
  const vec = vectors[ci];
6837
6843
  if (vec.length === 0) continue;
6838
6844
  const similarity = cosineSimilarity(queryVector, vec);
@@ -6840,7 +6846,7 @@ async function searchChunksOp(ctx, queryVector, options) {
6840
6846
  candidates.push({
6841
6847
  message,
6842
6848
  similarity,
6843
- chunkTextSource: { kind: "chunk", chunk: chunks[ci], siblings: chunks }
6849
+ chunkTextSource: { kind: "chunk", chunk: chunks2[ci], siblings: chunks2 }
6844
6850
  });
6845
6851
  }
6846
6852
  }
@@ -7020,7 +7026,7 @@ function chunkText(text12, options) {
7020
7026
  ];
7021
7027
  }
7022
7028
  const sentences = splitIntoSentences(text12);
7023
- const chunks = [];
7029
+ const chunks2 = [];
7024
7030
  let currentChunkSentences = [];
7025
7031
  let currentChunkStart = 0;
7026
7032
  let currentOffset = 0;
@@ -7034,7 +7040,7 @@ function chunkText(text12, options) {
7034
7040
  if (sentence.length > chunkSize) {
7035
7041
  if (currentChunkSentences.length > 0) {
7036
7042
  const chunkText2 = currentChunkSentences.join(" ");
7037
- chunks.push({
7043
+ chunks2.push({
7038
7044
  text: chunkText2,
7039
7045
  startOffset: currentChunkStart,
7040
7046
  endOffset: currentOffset
@@ -7045,7 +7051,7 @@ function chunkText(text12, options) {
7045
7051
  const chunkEnd = Math.min(j + chunkSize, sentence.length);
7046
7052
  const chunk = sentence.slice(j, chunkEnd);
7047
7053
  if (chunk.length >= minChunkSize) {
7048
- chunks.push({
7054
+ chunks2.push({
7049
7055
  text: chunk,
7050
7056
  startOffset: sentenceStart + j,
7051
7057
  endOffset: sentenceStart + chunkEnd
@@ -7059,7 +7065,7 @@ function chunkText(text12, options) {
7059
7065
  const currentText = currentChunkSentences.join(" ");
7060
7066
  const potentialLength = currentText.length + (currentText ? 1 : 0) + sentence.length;
7061
7067
  if (potentialLength > chunkSize && currentChunkSentences.length > 0) {
7062
- chunks.push({
7068
+ chunks2.push({
7063
7069
  text: currentText,
7064
7070
  startOffset: currentChunkStart,
7065
7071
  endOffset: currentOffset
@@ -7090,14 +7096,14 @@ function chunkText(text12, options) {
7090
7096
  if (currentChunkSentences.length > 0) {
7091
7097
  const chunkText2 = currentChunkSentences.join(" ");
7092
7098
  if (chunkText2.length >= minChunkSize) {
7093
- chunks.push({
7099
+ chunks2.push({
7094
7100
  text: chunkText2,
7095
7101
  startOffset: currentChunkStart,
7096
7102
  endOffset: text12.length
7097
7103
  });
7098
7104
  }
7099
7105
  }
7100
- if (chunks.length === 0) {
7106
+ if (chunks2.length === 0) {
7101
7107
  const trimmedText = text12.trim();
7102
7108
  if (trimmedText.length > 0) {
7103
7109
  return [
@@ -7109,7 +7115,7 @@ function chunkText(text12, options) {
7109
7115
  ];
7110
7116
  }
7111
7117
  }
7112
- return chunks;
7118
+ return chunks2;
7113
7119
  }
7114
7120
  function shouldChunkMessage(content, chunkSize = DEFAULT_CHUNK_SIZE) {
7115
7121
  return content.length > chunkSize;
@@ -7328,18 +7334,18 @@ async function embedMany(texts, options, outer) {
7328
7334
  outer
7329
7335
  );
7330
7336
  } else {
7331
- const chunks = [];
7337
+ const chunks2 = [];
7332
7338
  for (let i = 0; i < uncachedTexts.length; i += chunkSize) {
7333
- chunks.push(uncachedTexts.slice(i, i + chunkSize));
7339
+ chunks2.push(uncachedTexts.slice(i, i + chunkSize));
7334
7340
  }
7335
- const allEmbeddings = new Array(chunks.length);
7341
+ const allEmbeddings = new Array(chunks2.length);
7336
7342
  let nextIndex = 0;
7337
7343
  const worker = async () => {
7338
- while (nextIndex < chunks.length) {
7344
+ while (nextIndex < chunks2.length) {
7339
7345
  if (outer?.aborted) throw outer.reason;
7340
7346
  const idx = nextIndex++;
7341
7347
  allEmbeddings[idx] = await generateEmbeddingsBatch(
7342
- chunks[idx],
7348
+ chunks2[idx],
7343
7349
  headers,
7344
7350
  baseUrl,
7345
7351
  embeddingModel,
@@ -7351,7 +7357,7 @@ async function embedMany(texts, options, outer) {
7351
7357
  }
7352
7358
  };
7353
7359
  const workers = Array.from(
7354
- { length: Math.min(DEFAULT_EMBEDDING_BATCH_CONCURRENCY, chunks.length) },
7360
+ { length: Math.min(DEFAULT_EMBEDDING_BATCH_CONCURRENCY, chunks2.length) },
7355
7361
  () => worker()
7356
7362
  );
7357
7363
  await Promise.all(workers);
@@ -14705,8 +14711,8 @@ var WatermelonChatStorageAdapter = class {
14705
14711
  updateMessageEmbedding(uniqueId, vector, embeddingModel) {
14706
14712
  return updateMessageEmbeddingOp(this.ctx, uniqueId, vector, embeddingModel);
14707
14713
  }
14708
- updateMessageChunks(uniqueId, chunks, embeddingModel) {
14709
- return updateMessageChunksOp(this.ctx, uniqueId, chunks, embeddingModel);
14714
+ updateMessageChunks(uniqueId, chunks2, embeddingModel) {
14715
+ return updateMessageChunksOp(this.ctx, uniqueId, chunks2, embeddingModel);
14710
14716
  }
14711
14717
  updateMessageError(uniqueId, error) {
14712
14718
  return updateMessageErrorOp(this.ctx, uniqueId, error);
@@ -23062,6 +23068,65 @@ function createLocalMemoryStore(options) {
23062
23068
  };
23063
23069
  }
23064
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
+
23065
23130
  // src/lib/memory/store/remotePersistence.ts
23066
23131
  var RemoteMemoryError = class extends Error {
23067
23132
  constructor(message, status, code) {
@@ -23114,6 +23179,30 @@ var candidateListLimits = [
23114
23179
  ["memory_ids", 1e3],
23115
23180
  ["force_ids", 100]
23116
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
+ ];
23117
23206
  function record(value) {
23118
23207
  return typeof value === "object" && value !== null && !Array.isArray(value);
23119
23208
  }
@@ -23448,6 +23537,35 @@ async function createRemoteMemoryPersistence(options) {
23448
23537
  throw new Error("Invalid nearby batch response");
23449
23538
  return Promise.all(result.items.map((item, i) => decodeCommitted(item, prepared[i])));
23450
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
+ },
23451
23569
  candidateSet,
23452
23570
  candidates: async (embedding, candidateOptions = {}) => decodeAll((await fetchCandidates(embedding, candidateOptions, false)).items)
23453
23571
  };
@@ -23837,6 +23955,490 @@ function createRemoteMemoryPipeline(options) {
23837
23955
  };
23838
23956
  }
23839
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
+
23840
24442
  // src/lib/memory/synthesizeProfile.ts
23841
24443
  init_internalFlowMarker();
23842
24444
  init_logger();
@@ -37819,6 +38421,7 @@ function useWalletBinding(options = {}) {
37819
38421
  MEMORY_KINDS,
37820
38422
  MEMORY_LEVELS,
37821
38423
  MemoryEntityModel,
38424
+ MemoryKeyError,
37822
38425
  MemoryLevelError,
37823
38426
  NEVER_TTL_MS,
37824
38427
  NODE_BUDGET,
@@ -37833,6 +38436,7 @@ function useWalletBinding(options = {}) {
37833
38436
  RECALL_MAX_LIMIT,
37834
38437
  RECALL_TOOL_NAME,
37835
38438
  RemoteMemoryError,
38439
+ RemoteMemoryPartialCreateError,
37836
38440
  RerankerUnavailableError,
37837
38441
  SDK_SCHEMA_VERSION,
37838
38442
  SERVER_TOOL_DEPENDENCY_SETS,
@@ -37926,6 +38530,7 @@ function useWalletBinding(options = {}) {
37926
38530
  createRecallTool,
37927
38531
  createRemoteMemoryPersistence,
37928
38532
  createRemoteMemoryPipeline,
38533
+ createRemoteMemoryStore,
37929
38534
  createSavedToolOp,
37930
38535
  createServerToolsFilter,
37931
38536
  createStockPricePreProcessor,
@@ -37957,6 +38562,7 @@ function useWalletBinding(options = {}) {
37957
38562
  deleteVaultMemoryOp,
37958
38563
  dequantizeEmbedding,
37959
38564
  deriveKeyFromSignatureBytes,
38565
+ deriveMemoryKeyRing,
37960
38566
  eagerEmbedContent,
37961
38567
  embedAllMessages,
37962
38568
  embedMessage,
@@ -38096,6 +38702,7 @@ function useWalletBinding(options = {}) {
38096
38702
  linkMemoryEntitiesOp,
38097
38703
  maskScopedEmbeddingCache,
38098
38704
  mediaToStored,
38705
+ memoryCipher,
38099
38706
  migrateCalendarToken,
38100
38707
  migrateDisplayResult,
38101
38708
  migrateDriveToken,
@@ -38117,6 +38724,7 @@ function useWalletBinding(options = {}) {
38117
38724
  rankProfileCandidates,
38118
38725
  readEncryptedFile,
38119
38726
  recall,
38727
+ reencryptMemoryField,
38120
38728
  reflect,
38121
38729
  refreshCalendarToken,
38122
38730
  refreshDriveToken,