@anuma/sdk 7.6.1 → 8.0.1

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.
@@ -2420,16 +2420,19 @@ async function updateMessageEmbeddingOp(ctx, uniqueId, vector, embeddingModel) {
2420
2420
  } catch {
2421
2421
  return null;
2422
2422
  }
2423
+ const address = ctx.walletAddress;
2423
2424
  await ctx.database.write(async () => {
2425
+ const key = await resolveMessageEmbeddingKey(address, message.content);
2426
+ const storedVector2 = await serializeMessageEmbedding(key, vector);
2424
2427
  await message.update((msg) => {
2425
- msg._setRaw("vector", JSON.stringify(vector));
2428
+ msg._setRaw("vector", storedVector2);
2426
2429
  if (msg.origin === "chunks_discarded" && vector.length > 0) {
2427
2430
  msg._setRaw("origin", "message");
2428
2431
  }
2429
2432
  msg._setRaw("embedding_model", embeddingModel);
2430
2433
  });
2431
2434
  });
2432
- return messageToStored(message, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
2435
+ return messageToStored(message, ctx.walletAddress);
2433
2436
  }
2434
2437
  async function updateMessageChunksOp(ctx, uniqueId, chunks3, embeddingModel) {
2435
2438
  let message;
@@ -2439,16 +2442,123 @@ async function updateMessageChunksOp(ctx, uniqueId, chunks3, embeddingModel) {
2439
2442
  return null;
2440
2443
  }
2441
2444
  const storedChunks = chunks3.map(({ text: _text, ...rest }) => rest);
2445
+ const address = ctx.walletAddress;
2442
2446
  await ctx.database.write(async () => {
2447
+ const key = await resolveMessageEmbeddingKey(address, message.content);
2448
+ const serializedChunks = await serializeMessageEmbedding(key, storedChunks);
2443
2449
  await message.update((msg) => {
2444
- msg._setRaw("chunks", JSON.stringify(storedChunks));
2450
+ msg._setRaw("chunks", serializedChunks);
2445
2451
  if (msg.origin === "chunks_discarded" && storedChunks.length > 0 && storedChunks.every((chunk) => chunk.vector.length > 0)) {
2446
2452
  msg._setRaw("origin", "message");
2447
2453
  }
2448
2454
  msg._setRaw("embedding_model", embeddingModel);
2449
2455
  });
2450
2456
  });
2451
- return messageToStored(message, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
2457
+ return messageToStored(message, ctx.walletAddress);
2458
+ }
2459
+ async function resolveMessageEmbeddingKey(address, content) {
2460
+ if (!address || !isEncrypted(content)) return null;
2461
+ const key = await getEncryptionKey(address, "v3");
2462
+ const contentKey = content.startsWith("enc:v2:") ? await getEncryptionKey(address, "v2") : key;
2463
+ try {
2464
+ await decryptDataWithKey(content.slice("enc:vN:".length), contentKey);
2465
+ } catch {
2466
+ throw new Error("Cannot decrypt the message with the cached wallet key");
2467
+ }
2468
+ return key;
2469
+ }
2470
+ async function serializeMessageEmbedding(key, value) {
2471
+ const json4 = JSON.stringify(value);
2472
+ return key ? `enc:v3:${await encryptDataWithKey(json4, key)}` : json4;
2473
+ }
2474
+ async function decryptMessageEmbeddingFields(raw, walletAddress) {
2475
+ const result = { ...raw };
2476
+ for (const column of ["vector", "chunks"]) {
2477
+ const value = raw[column];
2478
+ if (typeof value !== "string" || !value.startsWith("enc:")) continue;
2479
+ const decrypted = walletAddress ? await decryptField(value, walletAddress) : value;
2480
+ result[column] = decrypted.startsWith("enc:") ? void 0 : decrypted;
2481
+ }
2482
+ return result;
2483
+ }
2484
+ async function sealLegacyMessageEmbeddingsOp(ctx) {
2485
+ if (!ctx.walletAddress) return 0;
2486
+ const candidateIds = await ctx.messagesCollection.query(
2487
+ Q.where("content", Q.like("enc:%")),
2488
+ Q.or(
2489
+ ...["vector", "chunks"].map(
2490
+ (column) => Q.and(
2491
+ Q.where(column, Q.notEq(null)),
2492
+ Q.where(column, Q.notEq("")),
2493
+ Q.where(column, Q.notLike("enc:%"))
2494
+ )
2495
+ )
2496
+ )
2497
+ ).fetchIds();
2498
+ let sealed = 0;
2499
+ let undecryptable = 0;
2500
+ for (let start = 0; start < candidateIds.length; start += 50) {
2501
+ const pageIds = candidateIds.slice(start, start + 50);
2502
+ await ctx.database.write(async () => {
2503
+ const pageMessages = await ctx.messagesCollection.query(Q.where("id", Q.oneOf(pageIds))).fetch();
2504
+ for (const message of pageMessages) {
2505
+ if (!isEncrypted(message.content)) continue;
2506
+ const content = await decryptFieldDetailed(message.content, ctx.walletAddress);
2507
+ if (content.status === "key_missing") {
2508
+ throw new Error("Cannot decrypt the message with the cached wallet key");
2509
+ }
2510
+ if (content.status !== "ok") {
2511
+ undecryptable++;
2512
+ continue;
2513
+ }
2514
+ const plaintext = content.value;
2515
+ const key = await resolveMessageEmbeddingKey(ctx.walletAddress, message.content);
2516
+ const updates = {};
2517
+ for (const column of ["vector", "chunks"]) {
2518
+ const value = message._getRaw(column);
2519
+ if (typeof value !== "string" || value.startsWith("enc:") || !value) continue;
2520
+ let parsed;
2521
+ try {
2522
+ parsed = JSON.parse(value);
2523
+ } catch {
2524
+ updates[column] = null;
2525
+ continue;
2526
+ }
2527
+ if (!Array.isArray(parsed)) {
2528
+ updates[column] = null;
2529
+ continue;
2530
+ }
2531
+ if (column === "chunks") {
2532
+ const chunks3 = parsed;
2533
+ if (chunks3.some(
2534
+ (chunk) => !chunk || !Number.isInteger(chunk.startOffset) || !Number.isInteger(chunk.endOffset) || chunk.startOffset < 0 || chunk.endOffset <= chunk.startOffset || chunk.endOffset > plaintext.length
2535
+ )) {
2536
+ updates.chunks = null;
2537
+ updates.vector = null;
2538
+ updates.origin = message.origin === "tool_result" ? "tool_result" : "chunks_discarded";
2539
+ break;
2540
+ }
2541
+ parsed = chunks3.map(({ text: _text, ...rest }) => rest);
2542
+ }
2543
+ updates[column] = await serializeMessageEmbedding(key, parsed);
2544
+ }
2545
+ if (Object.keys(updates).length === 0) continue;
2546
+ const updatedAt = Number(message._getRaw("updated_at"));
2547
+ const discarded = updates.origin !== void 0;
2548
+ await message.update((msg) => {
2549
+ for (const [column, value] of Object.entries(updates)) msg._setRaw(column, value);
2550
+ msg._setRaw("updated_at", discarded ? Math.max(Date.now(), updatedAt + 1) : updatedAt);
2551
+ });
2552
+ sealed++;
2553
+ }
2554
+ });
2555
+ }
2556
+ if (undecryptable > 0) {
2557
+ getLogger().warn(
2558
+ `Skipped ${undecryptable} message embeddings that the cached wallet key cannot decrypt`
2559
+ );
2560
+ }
2561
+ return sealed;
2452
2562
  }
2453
2563
  var RAW_REPAIR_PAGE_SIZE = 100;
2454
2564
  function chunksWithoutText(raw) {
@@ -26391,6 +26501,8 @@ function useChatStorage(options) {
26391
26501
  embeddedWalletSigner
26392
26502
  ]
26393
26503
  );
26504
+ const storageCtxRef = useRef4(storageCtx);
26505
+ storageCtxRef.current = storageCtx;
26394
26506
  const vaultMemoryCollection = useMemo(
26395
26507
  () => database.get("memory_vault"),
26396
26508
  [database]
@@ -26494,24 +26606,12 @@ function useChatStorage(options) {
26494
26606
  refreshQueueStatus();
26495
26607
  return queueManager.onQueueChange(walletAddress, refreshQueueStatus);
26496
26608
  }, [walletAddress, refreshQueueStatus]);
26497
- useEffect4(() => {
26498
- if (!walletAddress || !enableQueue || !autoFlushOnKeyAvailable || !signMessage) return;
26499
- return onKeyAvailable(walletAddress, () => {
26500
- flushQueue().catch((err) => {
26501
- getLogger().warn("[useChatStorage] Auto-flush failed:", err);
26502
- });
26503
- });
26504
- }, [walletAddress, enableQueue, autoFlushOnKeyAvailable, signMessage, flushQueue]);
26505
26609
  useEffect4(() => {
26506
26610
  if (!getWalletAddress || walletAddress) return;
26507
26611
  const poller = new WalletPoller();
26508
26612
  return poller.startPolling(getWalletAddress, () => {
26509
26613
  });
26510
26614
  }, [getWalletAddress, walletAddress]);
26511
- const isEncryptionReady = useCallback4(() => {
26512
- if (!walletAddress || !signMessage) return true;
26513
- return hasEncryptionKey(walletAddress);
26514
- }, [walletAddress, signMessage]);
26515
26615
  const pendingOpsRef = useRef4([]);
26516
26616
  const syntheticConvIdsRef = useRef4(/* @__PURE__ */ new Set());
26517
26617
  useEffect4(() => {
@@ -26524,34 +26624,49 @@ function useChatStorage(options) {
26524
26624
  pendingOpsRef.current = [];
26525
26625
  refreshQueueStatus();
26526
26626
  }, [walletAddress, enableQueue, refreshQueueStatus]);
26627
+ useEffect4(() => {
26628
+ if (!walletAddress || !enableQueue || !autoFlushOnKeyAvailable || !signMessage) return;
26629
+ return onKeyAvailable(walletAddress, () => {
26630
+ flushQueue().catch((err) => {
26631
+ getLogger().warn("[useChatStorage] Auto-flush failed:", err);
26632
+ });
26633
+ });
26634
+ }, [walletAddress, enableQueue, autoFlushOnKeyAvailable, signMessage, flushQueue]);
26527
26635
  const writeOrQueue = useCallback4(
26528
26636
  async (opType, payload, directWrite, makeSynthetic, dependencies = []) => {
26529
- if (isEncryptionReady()) {
26530
- const result2 = await directWrite();
26637
+ const currentStorageCtx = storageCtx.walletAddress ? storageCtx : storageCtxRef.current;
26638
+ const currentWalletAddress = currentStorageCtx.walletAddress;
26639
+ if (enableQueue && signMessage && !currentWalletAddress && getWalletAddress) {
26640
+ pendingOpsRef.current.push({ type: opType, payload, dependencies });
26641
+ return { result: makeSynthetic(), queued: true };
26642
+ }
26643
+ if (!currentWalletAddress || !currentStorageCtx.signMessage || hasEncryptionKey(currentWalletAddress)) {
26644
+ const result2 = await directWrite(currentStorageCtx);
26531
26645
  return { result: result2, queued: false };
26532
26646
  }
26533
26647
  if (!enableQueue) {
26534
- const result2 = await directWrite();
26648
+ const result2 = await directWrite(currentStorageCtx);
26535
26649
  return { result: result2, queued: false };
26536
26650
  }
26537
- if (!walletAddress && getWalletAddress) {
26538
- pendingOpsRef.current.push({ type: opType, payload, dependencies });
26539
- return { result: makeSynthetic(), queued: true };
26540
- }
26541
- if (walletAddress) {
26542
- const queueId = queueManager.queueOperation(walletAddress, opType, payload, dependencies);
26651
+ if (currentWalletAddress) {
26652
+ const queueId = queueManager.queueOperation(
26653
+ currentWalletAddress,
26654
+ opType,
26655
+ payload,
26656
+ dependencies
26657
+ );
26543
26658
  if (queueId === null) {
26544
26659
  getLogger().warn("[useChatStorage] Queue full, falling back to direct write");
26545
- const result2 = await directWrite();
26660
+ const result2 = await directWrite(currentStorageCtx);
26546
26661
  return { result: result2, queued: false };
26547
26662
  }
26548
- refreshQueueStatus();
26663
+ setQueueStatus(queueManager.getStatus(currentWalletAddress));
26549
26664
  return { result: makeSynthetic(), queued: true, queueId };
26550
26665
  }
26551
- const result = await directWrite();
26666
+ const result = await directWrite(currentStorageCtx);
26552
26667
  return { result, queued: false };
26553
26668
  },
26554
- [isEncryptionReady, enableQueue, walletAddress, getWalletAddress, refreshQueueStatus]
26669
+ [storageCtx, enableQueue, signMessage, getWalletAddress]
26555
26670
  );
26556
26671
  const embedMessageAsync = useCallback4(
26557
26672
  async (message, mask = maskForEmbedding) => {
@@ -26825,7 +26940,7 @@ function useChatStorage(options) {
26825
26940
  const { result, queued } = await writeOrQueue(
26826
26941
  "createConversation",
26827
26942
  conversationOpts,
26828
- () => createConversationOp(storageCtx, conversationOpts, defaultConversationTitle),
26943
+ (ctx) => createConversationOp(ctx, conversationOpts, defaultConversationTitle),
26829
26944
  () => makeSyntheticStoredConversation(conversationOpts, defaultConversationTitle)
26830
26945
  );
26831
26946
  if (queued) {
@@ -26834,7 +26949,7 @@ function useChatStorage(options) {
26834
26949
  setCurrentConversationId(result.conversationId);
26835
26950
  return result;
26836
26951
  },
26837
- [storageCtx, defaultConversationTitle, writeOrQueue]
26952
+ [defaultConversationTitle, writeOrQueue]
26838
26953
  );
26839
26954
  const getConversation = useCallback4(
26840
26955
  async (id) => {
@@ -26850,24 +26965,24 @@ function useChatStorage(options) {
26850
26965
  const { result } = await writeOrQueue(
26851
26966
  "updateConversationTitle",
26852
26967
  { conversationId: id, title },
26853
- () => updateConversationTitleOp(storageCtx, id, title),
26968
+ (ctx) => updateConversationTitleOp(ctx, id, title),
26854
26969
  () => true
26855
26970
  );
26856
26971
  return result;
26857
26972
  },
26858
- [storageCtx, writeOrQueue]
26973
+ [writeOrQueue]
26859
26974
  );
26860
26975
  const updateConversationPinned = useCallback4(
26861
26976
  async (id, pinned) => {
26862
26977
  const { result } = await writeOrQueue(
26863
26978
  "updateConversationPinned",
26864
26979
  { conversationId: id, pinned },
26865
- () => updateConversationPinnedOp(storageCtx, id, pinned),
26980
+ (ctx) => updateConversationPinnedOp(ctx, id, pinned),
26866
26981
  () => true
26867
26982
  );
26868
26983
  return result;
26869
26984
  },
26870
- [storageCtx, writeOrQueue]
26985
+ [writeOrQueue]
26871
26986
  );
26872
26987
  const deleteConversation = useCallback4(
26873
26988
  async (id) => {
@@ -27085,7 +27200,7 @@ function useChatStorage(options) {
27085
27200
  const { result } = await writeOrQueue(
27086
27201
  "createMessage",
27087
27202
  rowOpts,
27088
- () => upsertMessageOp(storageCtx, rowOpts),
27203
+ (currentStorageCtx) => upsertMessageOp(currentStorageCtx, rowOpts),
27089
27204
  () => makeSyntheticStoredMessage(rowOpts),
27090
27205
  ctx.userMessageQueueId ? [ctx.userMessageQueueId] : []
27091
27206
  );
@@ -27547,7 +27662,7 @@ function useChatStorage(options) {
27547
27662
  const userMsgResult = await writeOrQueue(
27548
27663
  "createMessage",
27549
27664
  userMsgOpts,
27550
- () => createMessageOp(storageCtx, userMsgOpts),
27665
+ (ctx) => createMessageOp(ctx, userMsgOpts),
27551
27666
  () => makeSyntheticStoredMessage(userMsgOpts)
27552
27667
  );
27553
27668
  storedUserMessage = userMsgResult.result;
@@ -27896,7 +28011,7 @@ function useChatStorage(options) {
27896
28011
  const assistantMsgResult = await writeOrQueue(
27897
28012
  "createMessage",
27898
28013
  assistantMsgOpts,
27899
- () => createMessageOp(storageCtx, assistantMsgOpts),
28014
+ (ctx) => createMessageOp(ctx, assistantMsgOpts),
27900
28015
  () => makeSyntheticStoredMessage(assistantMsgOpts),
27901
28016
  userMsgQueueId ? [userMsgQueueId] : []
27902
28017
  );
@@ -27928,7 +28043,7 @@ function useChatStorage(options) {
27928
28043
  const toolResultsWrite = await writeOrQueue(
27929
28044
  "createMessage",
27930
28045
  toolResultsOpts,
27931
- () => createMessageOp(storageCtx, toolResultsOpts),
28046
+ (ctx) => createMessageOp(ctx, toolResultsOpts),
27932
28047
  () => makeSyntheticStoredMessage(toolResultsOpts),
27933
28048
  assistantMsgQueueId ? [assistantMsgQueueId] : []
27934
28049
  );
@@ -27971,7 +28086,6 @@ function useChatStorage(options) {
27971
28086
  walletAddress,
27972
28087
  signMessage,
27973
28088
  embeddedWalletSigner,
27974
- isEncryptionReady,
27975
28089
  enableQueue,
27976
28090
  getWalletAddress,
27977
28091
  refreshQueueStatus,
@@ -28289,6 +28403,7 @@ export {
28289
28403
  createWebSearchPreProcessor,
28290
28404
  decodeChunkVector,
28291
28405
  decryptConversationTitle,
28406
+ decryptMessageEmbeddingFields,
28292
28407
  deleteAllVaultMemoriesForUserOp,
28293
28408
  deleteMessageOp,
28294
28409
  deleteVaultFolderOp,
@@ -28369,6 +28484,7 @@ export {
28369
28484
  sdkMigrations,
28370
28485
  sdkModelClasses,
28371
28486
  sdkSchema,
28487
+ sealLegacyMessageEmbeddingsOp,
28372
28488
  searchVaultMemories,
28373
28489
  seedEncryptionKeys,
28374
28490
  setLogger,
@@ -1564,6 +1564,7 @@ __export(index_exports, {
1564
1564
  decryptDataBytes: () => decryptDataBytes,
1565
1565
  decryptDataBytesFromBytes: () => decryptDataBytesFromBytes,
1566
1566
  decryptDataWithKey: () => decryptDataWithKey,
1567
+ decryptMessageEmbeddingFields: () => decryptMessageEmbeddingFields,
1567
1568
  defaultServerToolsFilter: () => defaultServerToolsFilter,
1568
1569
  deleteAllAppFilesOp: () => deleteAllAppFilesOp,
1569
1570
  deleteAllVaultMemoriesForUserOp: () => deleteAllVaultMemoriesForUserOp,
@@ -1744,6 +1745,7 @@ __export(index_exports, {
1744
1745
  sdkMigrations: () => sdkMigrations,
1745
1746
  sdkModelClasses: () => sdkModelClasses,
1746
1747
  sdkSchema: () => sdkSchema,
1748
+ sealLegacyMessageEmbeddingsOp: () => sealLegacyMessageEmbeddingsOp,
1747
1749
  searchChunksOp: () => searchChunksOp,
1748
1750
  searchMediaOp: () => searchMediaOp,
1749
1751
  searchMessagesOp: () => searchMessagesOp,
@@ -4714,16 +4716,19 @@ async function updateMessageEmbeddingOp(ctx, uniqueId, vector, embeddingModel) {
4714
4716
  } catch {
4715
4717
  return null;
4716
4718
  }
4719
+ const address = ctx.walletAddress;
4717
4720
  await ctx.database.write(async () => {
4721
+ const key = await resolveMessageEmbeddingKey(address, message.content);
4722
+ const storedVector2 = await serializeMessageEmbedding(key, vector);
4718
4723
  await message.update((msg) => {
4719
- msg._setRaw("vector", JSON.stringify(vector));
4724
+ msg._setRaw("vector", storedVector2);
4720
4725
  if (msg.origin === "chunks_discarded" && vector.length > 0) {
4721
4726
  msg._setRaw("origin", "message");
4722
4727
  }
4723
4728
  msg._setRaw("embedding_model", embeddingModel);
4724
4729
  });
4725
4730
  });
4726
- return messageToStored(message, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
4731
+ return messageToStored(message, ctx.walletAddress);
4727
4732
  }
4728
4733
  async function updateMessageChunksOp(ctx, uniqueId, chunks3, embeddingModel) {
4729
4734
  let message;
@@ -4733,16 +4738,123 @@ async function updateMessageChunksOp(ctx, uniqueId, chunks3, embeddingModel) {
4733
4738
  return null;
4734
4739
  }
4735
4740
  const storedChunks = chunks3.map(({ text: _text, ...rest }) => rest);
4741
+ const address = ctx.walletAddress;
4736
4742
  await ctx.database.write(async () => {
4743
+ const key = await resolveMessageEmbeddingKey(address, message.content);
4744
+ const serializedChunks = await serializeMessageEmbedding(key, storedChunks);
4737
4745
  await message.update((msg) => {
4738
- msg._setRaw("chunks", JSON.stringify(storedChunks));
4746
+ msg._setRaw("chunks", serializedChunks);
4739
4747
  if (msg.origin === "chunks_discarded" && storedChunks.length > 0 && storedChunks.every((chunk) => chunk.vector.length > 0)) {
4740
4748
  msg._setRaw("origin", "message");
4741
4749
  }
4742
4750
  msg._setRaw("embedding_model", embeddingModel);
4743
4751
  });
4744
4752
  });
4745
- return messageToStored(message, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
4753
+ return messageToStored(message, ctx.walletAddress);
4754
+ }
4755
+ async function resolveMessageEmbeddingKey(address, content) {
4756
+ if (!address || !isEncrypted(content)) return null;
4757
+ const key = await getEncryptionKey(address, "v3");
4758
+ const contentKey = content.startsWith("enc:v2:") ? await getEncryptionKey(address, "v2") : key;
4759
+ try {
4760
+ await decryptDataWithKey(content.slice("enc:vN:".length), contentKey);
4761
+ } catch {
4762
+ throw new Error("Cannot decrypt the message with the cached wallet key");
4763
+ }
4764
+ return key;
4765
+ }
4766
+ async function serializeMessageEmbedding(key, value) {
4767
+ const json4 = JSON.stringify(value);
4768
+ return key ? `enc:v3:${await encryptDataWithKey(json4, key)}` : json4;
4769
+ }
4770
+ async function decryptMessageEmbeddingFields(raw, walletAddress) {
4771
+ const result = { ...raw };
4772
+ for (const column of ["vector", "chunks"]) {
4773
+ const value = raw[column];
4774
+ if (typeof value !== "string" || !value.startsWith("enc:")) continue;
4775
+ const decrypted = walletAddress ? await decryptField(value, walletAddress) : value;
4776
+ result[column] = decrypted.startsWith("enc:") ? void 0 : decrypted;
4777
+ }
4778
+ return result;
4779
+ }
4780
+ async function sealLegacyMessageEmbeddingsOp(ctx) {
4781
+ if (!ctx.walletAddress) return 0;
4782
+ const candidateIds = await ctx.messagesCollection.query(
4783
+ import_watermelondb2.Q.where("content", import_watermelondb2.Q.like("enc:%")),
4784
+ import_watermelondb2.Q.or(
4785
+ ...["vector", "chunks"].map(
4786
+ (column) => import_watermelondb2.Q.and(
4787
+ import_watermelondb2.Q.where(column, import_watermelondb2.Q.notEq(null)),
4788
+ import_watermelondb2.Q.where(column, import_watermelondb2.Q.notEq("")),
4789
+ import_watermelondb2.Q.where(column, import_watermelondb2.Q.notLike("enc:%"))
4790
+ )
4791
+ )
4792
+ )
4793
+ ).fetchIds();
4794
+ let sealed = 0;
4795
+ let undecryptable = 0;
4796
+ for (let start = 0; start < candidateIds.length; start += 50) {
4797
+ const pageIds = candidateIds.slice(start, start + 50);
4798
+ await ctx.database.write(async () => {
4799
+ const pageMessages = await ctx.messagesCollection.query(import_watermelondb2.Q.where("id", import_watermelondb2.Q.oneOf(pageIds))).fetch();
4800
+ for (const message of pageMessages) {
4801
+ if (!isEncrypted(message.content)) continue;
4802
+ const content = await decryptFieldDetailed(message.content, ctx.walletAddress);
4803
+ if (content.status === "key_missing") {
4804
+ throw new Error("Cannot decrypt the message with the cached wallet key");
4805
+ }
4806
+ if (content.status !== "ok") {
4807
+ undecryptable++;
4808
+ continue;
4809
+ }
4810
+ const plaintext = content.value;
4811
+ const key = await resolveMessageEmbeddingKey(ctx.walletAddress, message.content);
4812
+ const updates = {};
4813
+ for (const column of ["vector", "chunks"]) {
4814
+ const value = message._getRaw(column);
4815
+ if (typeof value !== "string" || value.startsWith("enc:") || !value) continue;
4816
+ let parsed;
4817
+ try {
4818
+ parsed = JSON.parse(value);
4819
+ } catch {
4820
+ updates[column] = null;
4821
+ continue;
4822
+ }
4823
+ if (!Array.isArray(parsed)) {
4824
+ updates[column] = null;
4825
+ continue;
4826
+ }
4827
+ if (column === "chunks") {
4828
+ const chunks3 = parsed;
4829
+ if (chunks3.some(
4830
+ (chunk) => !chunk || !Number.isInteger(chunk.startOffset) || !Number.isInteger(chunk.endOffset) || chunk.startOffset < 0 || chunk.endOffset <= chunk.startOffset || chunk.endOffset > plaintext.length
4831
+ )) {
4832
+ updates.chunks = null;
4833
+ updates.vector = null;
4834
+ updates.origin = message.origin === "tool_result" ? "tool_result" : "chunks_discarded";
4835
+ break;
4836
+ }
4837
+ parsed = chunks3.map(({ text: _text, ...rest }) => rest);
4838
+ }
4839
+ updates[column] = await serializeMessageEmbedding(key, parsed);
4840
+ }
4841
+ if (Object.keys(updates).length === 0) continue;
4842
+ const updatedAt = Number(message._getRaw("updated_at"));
4843
+ const discarded = updates.origin !== void 0;
4844
+ await message.update((msg) => {
4845
+ for (const [column, value] of Object.entries(updates)) msg._setRaw(column, value);
4846
+ msg._setRaw("updated_at", discarded ? Math.max(Date.now(), updatedAt + 1) : updatedAt);
4847
+ });
4848
+ sealed++;
4849
+ }
4850
+ });
4851
+ }
4852
+ if (undecryptable > 0) {
4853
+ getLogger().warn(
4854
+ `Skipped ${undecryptable} message embeddings that the cached wallet key cannot decrypt`
4855
+ );
4856
+ }
4857
+ return sealed;
4746
4858
  }
4747
4859
  var RAW_REPAIR_PAGE_SIZE = 100;
4748
4860
  function chunksWithoutText(raw) {
@@ -33357,6 +33469,8 @@ function useChatStorage(options) {
33357
33469
  embeddedWalletSigner
33358
33470
  ]
33359
33471
  );
33472
+ const storageCtxRef = (0, import_react6.useRef)(storageCtx);
33473
+ storageCtxRef.current = storageCtx;
33360
33474
  const mediaCtx = (0, import_react6.useMemo)(
33361
33475
  () => ({
33362
33476
  database,
@@ -33493,14 +33607,6 @@ function useChatStorage(options) {
33493
33607
  refreshQueueStatus();
33494
33608
  return queueManager.onQueueChange(walletAddress, refreshQueueStatus);
33495
33609
  }, [walletAddress, refreshQueueStatus]);
33496
- (0, import_react6.useEffect)(() => {
33497
- if (!walletAddress || !enableQueue || !autoFlushOnKeyAvailable || !signMessage) return;
33498
- return onKeyAvailable(walletAddress, () => {
33499
- flushQueue().catch((err) => {
33500
- getLogger().warn("[useChatStorage] Auto-flush failed:", err);
33501
- });
33502
- });
33503
- }, [walletAddress, enableQueue, autoFlushOnKeyAvailable, signMessage, flushQueue]);
33504
33610
  (0, import_react6.useEffect)(() => {
33505
33611
  if (!getWalletAddress || walletAddress) return;
33506
33612
  const poller = new WalletPoller();
@@ -33524,34 +33630,49 @@ function useChatStorage(options) {
33524
33630
  pendingOpsRef.current = [];
33525
33631
  refreshQueueStatus();
33526
33632
  }, [walletAddress, enableQueue, refreshQueueStatus]);
33633
+ (0, import_react6.useEffect)(() => {
33634
+ if (!walletAddress || !enableQueue || !autoFlushOnKeyAvailable || !signMessage) return;
33635
+ return onKeyAvailable(walletAddress, () => {
33636
+ flushQueue().catch((err) => {
33637
+ getLogger().warn("[useChatStorage] Auto-flush failed:", err);
33638
+ });
33639
+ });
33640
+ }, [walletAddress, enableQueue, autoFlushOnKeyAvailable, signMessage, flushQueue]);
33527
33641
  const writeOrQueue = (0, import_react6.useCallback)(
33528
33642
  async (opType, payload, directWrite, makeSynthetic, dependencies = []) => {
33529
- if (isEncryptionReady()) {
33530
- const result2 = await directWrite();
33643
+ const currentStorageCtx = storageCtx.walletAddress ? storageCtx : storageCtxRef.current;
33644
+ const currentWalletAddress = currentStorageCtx.walletAddress;
33645
+ if (enableQueue && signMessage && !currentWalletAddress && getWalletAddress) {
33646
+ pendingOpsRef.current.push({ type: opType, payload, dependencies });
33647
+ return { result: makeSynthetic(), queued: true };
33648
+ }
33649
+ if (!currentWalletAddress || !currentStorageCtx.signMessage || hasEncryptionKey(currentWalletAddress)) {
33650
+ const result2 = await directWrite(currentStorageCtx);
33531
33651
  return { result: result2, queued: false };
33532
33652
  }
33533
33653
  if (!enableQueue) {
33534
- const result2 = await directWrite();
33654
+ const result2 = await directWrite(currentStorageCtx);
33535
33655
  return { result: result2, queued: false };
33536
33656
  }
33537
- if (!walletAddress && getWalletAddress) {
33538
- pendingOpsRef.current.push({ type: opType, payload, dependencies });
33539
- return { result: makeSynthetic(), queued: true };
33540
- }
33541
- if (walletAddress) {
33542
- const queueId = queueManager.queueOperation(walletAddress, opType, payload, dependencies);
33657
+ if (currentWalletAddress) {
33658
+ const queueId = queueManager.queueOperation(
33659
+ currentWalletAddress,
33660
+ opType,
33661
+ payload,
33662
+ dependencies
33663
+ );
33543
33664
  if (queueId === null) {
33544
33665
  getLogger().warn("[useChatStorage] Queue full, falling back to direct write");
33545
- const result2 = await directWrite();
33666
+ const result2 = await directWrite(currentStorageCtx);
33546
33667
  return { result: result2, queued: false };
33547
33668
  }
33548
- refreshQueueStatus();
33669
+ setQueueStatus(queueManager.getStatus(currentWalletAddress));
33549
33670
  return { result: makeSynthetic(), queued: true, queueId };
33550
33671
  }
33551
- const result = await directWrite();
33672
+ const result = await directWrite(currentStorageCtx);
33552
33673
  return { result, queued: false };
33553
33674
  },
33554
- [isEncryptionReady, enableQueue, walletAddress, getWalletAddress, refreshQueueStatus]
33675
+ [storageCtx, enableQueue, signMessage, getWalletAddress]
33555
33676
  );
33556
33677
  const embedMessageAsync = (0, import_react6.useCallback)(
33557
33678
  async (message, mask = maskForEmbedding) => {
@@ -33891,7 +34012,7 @@ function useChatStorage(options) {
33891
34012
  const { result, queued, queueId } = await writeOrQueue(
33892
34013
  "createConversation",
33893
34014
  conversationOpts,
33894
- () => createConversationOp(storageCtx, conversationOpts, defaultConversationTitle),
34015
+ (ctx) => createConversationOp(ctx, conversationOpts, defaultConversationTitle),
33895
34016
  () => makeSyntheticStoredConversation(conversationOpts, defaultConversationTitle)
33896
34017
  );
33897
34018
  if (queued) {
@@ -33903,7 +34024,7 @@ function useChatStorage(options) {
33903
34024
  setCurrentConversationId(result.conversationId);
33904
34025
  return result;
33905
34026
  },
33906
- [storageCtx, defaultConversationTitle, writeOrQueue]
34027
+ [defaultConversationTitle, writeOrQueue]
33907
34028
  );
33908
34029
  const getConversation = (0, import_react6.useCallback)(
33909
34030
  async (id) => {
@@ -33919,24 +34040,24 @@ function useChatStorage(options) {
33919
34040
  const { result } = await writeOrQueue(
33920
34041
  "updateConversationTitle",
33921
34042
  { conversationId: id, title },
33922
- () => updateConversationTitleOp(storageCtx, id, title),
34043
+ (ctx) => updateConversationTitleOp(ctx, id, title),
33923
34044
  () => true
33924
34045
  );
33925
34046
  return result;
33926
34047
  },
33927
- [storageCtx, writeOrQueue]
34048
+ [writeOrQueue]
33928
34049
  );
33929
34050
  const updateConversationPinned = (0, import_react6.useCallback)(
33930
34051
  async (id, pinned) => {
33931
34052
  const { result } = await writeOrQueue(
33932
34053
  "updateConversationPinned",
33933
34054
  { conversationId: id, pinned },
33934
- () => updateConversationPinnedOp(storageCtx, id, pinned),
34055
+ (ctx) => updateConversationPinnedOp(ctx, id, pinned),
33935
34056
  () => true
33936
34057
  );
33937
34058
  return result;
33938
34059
  },
33939
- [storageCtx, writeOrQueue]
34060
+ [writeOrQueue]
33940
34061
  );
33941
34062
  const deleteConversation = (0, import_react6.useCallback)(
33942
34063
  async (id) => {
@@ -34595,7 +34716,7 @@ function useChatStorage(options) {
34595
34716
  const userMsgResult = await writeOrQueue(
34596
34717
  "createMessage",
34597
34718
  userMsgOpts,
34598
- () => createMessageOp(storageCtx, userMsgOpts),
34719
+ (ctx) => createMessageOp(ctx, userMsgOpts),
34599
34720
  () => makeSyntheticStoredMessage(userMsgOpts),
34600
34721
  convId && syntheticConvQueueIdsRef.current.has(convId) ? [syntheticConvQueueIdsRef.current.get(convId)] : []
34601
34722
  );
@@ -34916,7 +35037,7 @@ function useChatStorage(options) {
34916
35037
  const assistantMsgResult = await writeOrQueue(
34917
35038
  "createMessage",
34918
35039
  assistantMsgOpts,
34919
- () => createMessageOp(storageCtx, assistantMsgOpts),
35040
+ (ctx) => createMessageOp(ctx, assistantMsgOpts),
34920
35041
  () => makeSyntheticStoredMessage(assistantMsgOpts),
34921
35042
  userMsgQueueId ? [userMsgQueueId] : []
34922
35043
  );
@@ -34967,7 +35088,7 @@ function useChatStorage(options) {
34967
35088
  const toolResultsWrite = await writeOrQueue(
34968
35089
  "createMessage",
34969
35090
  toolResultsOpts,
34970
- () => createMessageOp(storageCtx, toolResultsOpts),
35091
+ (ctx) => createMessageOp(ctx, toolResultsOpts),
34971
35092
  () => makeSyntheticStoredMessage(toolResultsOpts),
34972
35093
  assistantMsgQueueId ? [assistantMsgQueueId] : []
34973
35094
  );
@@ -38196,6 +38317,7 @@ function useWalletBinding(options = {}) {
38196
38317
  decryptDataBytes,
38197
38318
  decryptDataBytesFromBytes,
38198
38319
  decryptDataWithKey,
38320
+ decryptMessageEmbeddingFields,
38199
38321
  defaultServerToolsFilter,
38200
38322
  deleteAllAppFilesOp,
38201
38323
  deleteAllVaultMemoriesForUserOp,
@@ -38376,6 +38498,7 @@ function useWalletBinding(options = {}) {
38376
38498
  sdkMigrations,
38377
38499
  sdkModelClasses,
38378
38500
  sdkSchema,
38501
+ sealLegacyMessageEmbeddingsOp,
38379
38502
  searchChunksOp,
38380
38503
  searchMediaOp,
38381
38504
  searchMessagesOp,