@anuma/sdk 7.0.0 → 7.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.
package/dist/index.mjs CHANGED
@@ -1148,6 +1148,192 @@ function attachFileContextToLastUserMessage(messages, fileContext) {
1148
1148
  return result;
1149
1149
  }
1150
1150
 
1151
+ // src/lib/logger.ts
1152
+ var consoleLogger = {
1153
+ debug: console.log.bind(console),
1154
+ info: console.info.bind(console),
1155
+ warn: console.warn.bind(console),
1156
+ error: console.error.bind(console)
1157
+ };
1158
+ var noopLogger = {
1159
+ debug: () => {
1160
+ },
1161
+ info: () => {
1162
+ },
1163
+ warn: () => {
1164
+ },
1165
+ error: () => {
1166
+ }
1167
+ };
1168
+ var LOGGER_STATE_KEY = /* @__PURE__ */ Symbol.for("@anuma/sdk/logger/v1");
1169
+ var loggerGlobal = globalThis;
1170
+ var fallbackLoggerState = { logger: consoleLogger };
1171
+ var fallbackWarned = false;
1172
+ function getLoggerState() {
1173
+ try {
1174
+ return loggerGlobal[LOGGER_STATE_KEY] ?? (loggerGlobal[LOGGER_STATE_KEY] = fallbackLoggerState);
1175
+ } catch {
1176
+ if (!fallbackWarned) {
1177
+ fallbackWarned = true;
1178
+ fallbackLoggerState.logger.warn(
1179
+ "@anuma/sdk: the global object rejects new properties. This entrypoint keeps its own logger, so setLogger does not reach other entrypoints."
1180
+ );
1181
+ }
1182
+ return fallbackLoggerState;
1183
+ }
1184
+ }
1185
+ function setLogger(logger) {
1186
+ getLoggerState().logger = logger;
1187
+ }
1188
+ function getLogger() {
1189
+ return getLoggerState().logger;
1190
+ }
1191
+
1192
+ // src/react/useEncryption.ts
1193
+ var EncryptionKeyMissingError = class extends Error {
1194
+ constructor(address, version) {
1195
+ super(
1196
+ `Encryption key (${version}) not found for ${address}. Please sign a message to generate your encryption key.`
1197
+ );
1198
+ this.name = "EncryptionKeyMissingError";
1199
+ this.address = address;
1200
+ this.version = version;
1201
+ }
1202
+ };
1203
+ var encryptionKeyStore = /* @__PURE__ */ new Map();
1204
+ var cryptoKeyCache = /* @__PURE__ */ new Map();
1205
+ var clearAllEncryptionStateCallbacks = /* @__PURE__ */ new Set();
1206
+ function onClearAllEncryptionState(callback) {
1207
+ clearAllEncryptionStateCallbacks.add(callback);
1208
+ return () => {
1209
+ clearAllEncryptionStateCallbacks.delete(callback);
1210
+ };
1211
+ }
1212
+ function getStoredKeyByVersion(address, version) {
1213
+ const keys = encryptionKeyStore.get(address);
1214
+ if (!keys) return null;
1215
+ const value = version === "v2" ? keys.legacy : keys.current;
1216
+ return value ?? null;
1217
+ }
1218
+ function hexNibble(code) {
1219
+ if (code >= 48 && code <= 57) return code - 48;
1220
+ if (code >= 65 && code <= 70) return code - 55;
1221
+ if (code >= 97 && code <= 102) return code - 87;
1222
+ return -1;
1223
+ }
1224
+ function hexToBytes(hex) {
1225
+ if (typeof hex !== "string") {
1226
+ throw new TypeError(
1227
+ "hexToBytes: expected a hex string. Pass raw signature bytes to deriveKeyFromSignatureBytes instead of stringifying them."
1228
+ );
1229
+ }
1230
+ const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
1231
+ if (cleanHex.length === 0 || cleanHex.length % 2 !== 0) {
1232
+ throw new Error(
1233
+ `hexToBytes: invalid hex string (expected a non-empty even length, got ${cleanHex.length})`
1234
+ );
1235
+ }
1236
+ const bytes = new Uint8Array(cleanHex.length / 2);
1237
+ for (let i = 0; i < cleanHex.length; i += 2) {
1238
+ const hi = hexNibble(cleanHex.charCodeAt(i));
1239
+ const lo = hexNibble(cleanHex.charCodeAt(i + 1));
1240
+ if (hi < 0 || lo < 0) {
1241
+ throw new Error(`hexToBytes: invalid hex string (non-hex character at index ${i})`);
1242
+ }
1243
+ bytes[i / 2] = hi << 4 | lo;
1244
+ }
1245
+ return bytes;
1246
+ }
1247
+ var SHARED_TEXT_ENCODER = new TextEncoder();
1248
+ var SHARED_TEXT_DECODER = new TextDecoder();
1249
+ async function getEncryptionKey(address, version = "v3") {
1250
+ const cacheKey = `${address}:${version}`;
1251
+ const cachedKey = cryptoKeyCache.get(cacheKey);
1252
+ if (cachedKey) {
1253
+ return cachedKey;
1254
+ }
1255
+ const keyHex = getStoredKeyByVersion(address, version);
1256
+ if (!keyHex) {
1257
+ throw new EncryptionKeyMissingError(address, version);
1258
+ }
1259
+ const keyBytes = hexToBytes(keyHex);
1260
+ const cryptoKey = await crypto.subtle.importKey(
1261
+ "raw",
1262
+ keyBytes.buffer,
1263
+ { name: "AES-GCM" },
1264
+ false,
1265
+ ["encrypt", "decrypt"]
1266
+ );
1267
+ cryptoKeyCache.set(cacheKey, cryptoKey);
1268
+ return cryptoKey;
1269
+ }
1270
+ async function decryptData(encryptedHex, address, version = "v3") {
1271
+ const key = await getEncryptionKey(address, version);
1272
+ return decryptDataWithKey(encryptedHex, key);
1273
+ }
1274
+ function hasEncryptionKey(address, version) {
1275
+ return getStoredKeyByVersion(address, version ?? "v3") !== null;
1276
+ }
1277
+ async function decryptDataWithKey(encryptedHex, key) {
1278
+ const combined = hexToBytes(encryptedHex);
1279
+ const iv = combined.subarray(0, 12);
1280
+ const encryptedData = combined.subarray(12);
1281
+ const decryptedData = await crypto.subtle.decrypt(
1282
+ {
1283
+ name: "AES-GCM",
1284
+ iv
1285
+ },
1286
+ key,
1287
+ encryptedData
1288
+ );
1289
+ return SHARED_TEXT_DECODER.decode(decryptedData);
1290
+ }
1291
+
1292
+ // src/lib/db/encryption-utils.ts
1293
+ function isEncrypted(value) {
1294
+ const prefix = value.startsWith("enc:v3:") ? "enc:v3:" : value.startsWith("enc:v2:") ? "enc:v2:" : null;
1295
+ if (!prefix) return false;
1296
+ const payload = value.slice(prefix.length);
1297
+ return payload.length >= 56 && /^[0-9a-f]+$/i.test(payload);
1298
+ }
1299
+ function hasEncryptedToolPayload(event) {
1300
+ return [event.arguments, event.output].some(
1301
+ (value) => typeof value === "string" && isEncrypted(value)
1302
+ );
1303
+ }
1304
+ function detectEncryptionVersion(value) {
1305
+ if (value.startsWith("enc:v3:")) {
1306
+ return { version: "v3", encryptedData: value.slice("enc:v3:".length) };
1307
+ }
1308
+ if (value.startsWith("enc:v2:")) {
1309
+ return { version: "v2", encryptedData: value.slice("enc:v2:".length) };
1310
+ }
1311
+ return null;
1312
+ }
1313
+ async function decryptFieldDetailed(value, address) {
1314
+ if (!value) return { status: "plaintext", value };
1315
+ const detected = detectEncryptionVersion(value);
1316
+ if (!detected) return { status: "plaintext", value };
1317
+ if (detected.encryptedData.length < 56 || !/^[0-9a-f]+$/i.test(detected.encryptedData)) {
1318
+ return { status: "invalid_payload", value, version: detected.version };
1319
+ }
1320
+ try {
1321
+ const plaintext = await decryptData(detected.encryptedData, address, detected.version);
1322
+ return { status: "ok", value: plaintext, version: detected.version };
1323
+ } catch (error) {
1324
+ if (error instanceof EncryptionKeyMissingError) {
1325
+ getLogger().warn("Failed to decrypt field (key missing for version):", error.message);
1326
+ return { status: "key_missing", value, version: detected.version };
1327
+ }
1328
+ getLogger().warn("Failed to decrypt field (auth mismatch or crypto error):", error);
1329
+ return { status: "auth_mismatch", value, version: detected.version };
1330
+ }
1331
+ }
1332
+ async function decryptField(value, address) {
1333
+ const result = await decryptFieldDetailed(value, address);
1334
+ return result.value;
1335
+ }
1336
+
1151
1337
  // src/lib/chat/reservationReceipts.ts
1152
1338
  var ACTIONS = [
1153
1339
  {
@@ -1169,7 +1355,8 @@ function extractReservationReceipts(toolCallEvents) {
1169
1355
  for (const event of toolCallEvents ?? []) {
1170
1356
  const action = ACTIONS.find((a) => event.name?.endsWith(a.tool));
1171
1357
  const output = event.output ?? "";
1172
- if (!action || !output || NOT_AN_ATTEMPT.test(output)) continue;
1358
+ if (!action || !output || hasEncryptedToolPayload(event) || NOT_AN_ATTEMPT.test(output))
1359
+ continue;
1173
1360
  const kept = latest.get(action.kind)?.status;
1174
1361
  if (kept === "made") continue;
1175
1362
  const receipt = toReceipt(action, event.arguments ?? "", output);
@@ -1418,187 +1605,6 @@ function getImageModel(r) {
1418
1605
  return r.image_model;
1419
1606
  }
1420
1607
 
1421
- // src/lib/logger.ts
1422
- var consoleLogger = {
1423
- debug: console.log.bind(console),
1424
- info: console.info.bind(console),
1425
- warn: console.warn.bind(console),
1426
- error: console.error.bind(console)
1427
- };
1428
- var noopLogger = {
1429
- debug: () => {
1430
- },
1431
- info: () => {
1432
- },
1433
- warn: () => {
1434
- },
1435
- error: () => {
1436
- }
1437
- };
1438
- var LOGGER_STATE_KEY = /* @__PURE__ */ Symbol.for("@anuma/sdk/logger/v1");
1439
- var loggerGlobal = globalThis;
1440
- var fallbackLoggerState = { logger: consoleLogger };
1441
- var fallbackWarned = false;
1442
- function getLoggerState() {
1443
- try {
1444
- return loggerGlobal[LOGGER_STATE_KEY] ?? (loggerGlobal[LOGGER_STATE_KEY] = fallbackLoggerState);
1445
- } catch {
1446
- if (!fallbackWarned) {
1447
- fallbackWarned = true;
1448
- fallbackLoggerState.logger.warn(
1449
- "@anuma/sdk: the global object rejects new properties. This entrypoint keeps its own logger, so setLogger does not reach other entrypoints."
1450
- );
1451
- }
1452
- return fallbackLoggerState;
1453
- }
1454
- }
1455
- function setLogger(logger) {
1456
- getLoggerState().logger = logger;
1457
- }
1458
- function getLogger() {
1459
- return getLoggerState().logger;
1460
- }
1461
-
1462
- // src/react/useEncryption.ts
1463
- var EncryptionKeyMissingError = class extends Error {
1464
- constructor(address, version) {
1465
- super(
1466
- `Encryption key (${version}) not found for ${address}. Please sign a message to generate your encryption key.`
1467
- );
1468
- this.name = "EncryptionKeyMissingError";
1469
- this.address = address;
1470
- this.version = version;
1471
- }
1472
- };
1473
- var encryptionKeyStore = /* @__PURE__ */ new Map();
1474
- var cryptoKeyCache = /* @__PURE__ */ new Map();
1475
- var clearAllEncryptionStateCallbacks = /* @__PURE__ */ new Set();
1476
- function onClearAllEncryptionState(callback) {
1477
- clearAllEncryptionStateCallbacks.add(callback);
1478
- return () => {
1479
- clearAllEncryptionStateCallbacks.delete(callback);
1480
- };
1481
- }
1482
- function getStoredKeyByVersion(address, version) {
1483
- const keys = encryptionKeyStore.get(address);
1484
- if (!keys) return null;
1485
- const value = version === "v2" ? keys.legacy : keys.current;
1486
- return value ?? null;
1487
- }
1488
- function hexNibble(code) {
1489
- if (code >= 48 && code <= 57) return code - 48;
1490
- if (code >= 65 && code <= 70) return code - 55;
1491
- if (code >= 97 && code <= 102) return code - 87;
1492
- return -1;
1493
- }
1494
- function hexToBytes(hex) {
1495
- if (typeof hex !== "string") {
1496
- throw new TypeError(
1497
- "hexToBytes: expected a hex string. Pass raw signature bytes to deriveKeyFromSignatureBytes instead of stringifying them."
1498
- );
1499
- }
1500
- const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
1501
- if (cleanHex.length === 0 || cleanHex.length % 2 !== 0) {
1502
- throw new Error(
1503
- `hexToBytes: invalid hex string (expected a non-empty even length, got ${cleanHex.length})`
1504
- );
1505
- }
1506
- const bytes = new Uint8Array(cleanHex.length / 2);
1507
- for (let i = 0; i < cleanHex.length; i += 2) {
1508
- const hi = hexNibble(cleanHex.charCodeAt(i));
1509
- const lo = hexNibble(cleanHex.charCodeAt(i + 1));
1510
- if (hi < 0 || lo < 0) {
1511
- throw new Error(`hexToBytes: invalid hex string (non-hex character at index ${i})`);
1512
- }
1513
- bytes[i / 2] = hi << 4 | lo;
1514
- }
1515
- return bytes;
1516
- }
1517
- var SHARED_TEXT_ENCODER = new TextEncoder();
1518
- var SHARED_TEXT_DECODER = new TextDecoder();
1519
- async function getEncryptionKey(address, version = "v3") {
1520
- const cacheKey = `${address}:${version}`;
1521
- const cachedKey = cryptoKeyCache.get(cacheKey);
1522
- if (cachedKey) {
1523
- return cachedKey;
1524
- }
1525
- const keyHex = getStoredKeyByVersion(address, version);
1526
- if (!keyHex) {
1527
- throw new EncryptionKeyMissingError(address, version);
1528
- }
1529
- const keyBytes = hexToBytes(keyHex);
1530
- const cryptoKey = await crypto.subtle.importKey(
1531
- "raw",
1532
- keyBytes.buffer,
1533
- { name: "AES-GCM" },
1534
- false,
1535
- ["encrypt", "decrypt"]
1536
- );
1537
- cryptoKeyCache.set(cacheKey, cryptoKey);
1538
- return cryptoKey;
1539
- }
1540
- async function decryptData(encryptedHex, address, version = "v3") {
1541
- const key = await getEncryptionKey(address, version);
1542
- return decryptDataWithKey(encryptedHex, key);
1543
- }
1544
- function hasEncryptionKey(address, version) {
1545
- return getStoredKeyByVersion(address, version ?? "v3") !== null;
1546
- }
1547
- async function decryptDataWithKey(encryptedHex, key) {
1548
- const combined = hexToBytes(encryptedHex);
1549
- const iv = combined.subarray(0, 12);
1550
- const encryptedData = combined.subarray(12);
1551
- const decryptedData = await crypto.subtle.decrypt(
1552
- {
1553
- name: "AES-GCM",
1554
- iv
1555
- },
1556
- key,
1557
- encryptedData
1558
- );
1559
- return SHARED_TEXT_DECODER.decode(decryptedData);
1560
- }
1561
-
1562
- // src/lib/db/encryption-utils.ts
1563
- function isEncrypted(value) {
1564
- const prefix = value.startsWith("enc:v3:") ? "enc:v3:" : value.startsWith("enc:v2:") ? "enc:v2:" : null;
1565
- if (!prefix) return false;
1566
- const payload = value.slice(prefix.length);
1567
- return payload.length >= 56 && /^[0-9a-f]+$/i.test(payload);
1568
- }
1569
- function detectEncryptionVersion(value) {
1570
- if (value.startsWith("enc:v3:")) {
1571
- return { version: "v3", encryptedData: value.slice("enc:v3:".length) };
1572
- }
1573
- if (value.startsWith("enc:v2:")) {
1574
- return { version: "v2", encryptedData: value.slice("enc:v2:".length) };
1575
- }
1576
- return null;
1577
- }
1578
- async function decryptFieldDetailed(value, address) {
1579
- if (!value) return { status: "plaintext", value };
1580
- const detected = detectEncryptionVersion(value);
1581
- if (!detected) return { status: "plaintext", value };
1582
- if (detected.encryptedData.length < 56 || !/^[0-9a-f]+$/i.test(detected.encryptedData)) {
1583
- return { status: "invalid_payload", value, version: detected.version };
1584
- }
1585
- try {
1586
- const plaintext = await decryptData(detected.encryptedData, address, detected.version);
1587
- return { status: "ok", value: plaintext, version: detected.version };
1588
- } catch (error) {
1589
- if (error instanceof EncryptionKeyMissingError) {
1590
- getLogger().warn("Failed to decrypt field (key missing for version):", error.message);
1591
- return { status: "key_missing", value, version: detected.version };
1592
- }
1593
- getLogger().warn("Failed to decrypt field (auth mismatch or crypto error):", error);
1594
- return { status: "auth_mismatch", value, version: detected.version };
1595
- }
1596
- }
1597
- async function decryptField(value, address) {
1598
- const result = await decryptFieldDetailed(value, address);
1599
- return result.value;
1600
- }
1601
-
1602
1608
  // src/lib/db/chat/lazyDecrypt.ts
1603
1609
  var LRU_CAPACITY = 256;
1604
1610
  var titleCache = /* @__PURE__ */ new Map();
@@ -1566,6 +1566,7 @@ __export(index_exports, {
1566
1566
  encryptDataBatch: () => encryptDataBatch,
1567
1567
  encryptDataBytes: () => encryptDataBytes,
1568
1568
  encryptDataWithKey: () => encryptDataWithKey,
1569
+ encryptToolCallEventsOp: () => encryptToolCallEventsOp,
1569
1570
  ensureDefaultFoldersOp: () => ensureDefaultFoldersOp,
1570
1571
  expandToolSetsAdditive: () => expandToolSetsAdditive,
1571
1572
  exportElementToPdf: () => exportElementToPdf,
@@ -3593,6 +3594,11 @@ function isEncrypted(value) {
3593
3594
  const payload = value.slice(prefix.length);
3594
3595
  return payload.length >= 56 && /^[0-9a-f]+$/i.test(payload);
3595
3596
  }
3597
+ function hasEncryptedToolPayload(event) {
3598
+ return [event.arguments, event.output].some(
3599
+ (value) => typeof value === "string" && isEncrypted(value)
3600
+ );
3601
+ }
3596
3602
  function detectEncryptionVersion(value) {
3597
3603
  if (value.startsWith("enc:v3:")) {
3598
3604
  return { version: "v3", encryptedData: value.slice("enc:v3:".length) };
@@ -3730,6 +3736,12 @@ async function encryptMessageFields(message, address, signMessage, embeddedWalle
3730
3736
  const encryptedChunks = msg.chunks ? await encryptJsonField(msg.chunks, address, signMessage, embeddedWalletSigner, true) : void 0;
3731
3737
  const encryptedSources = msg.sources ? await encryptJsonField(msg.sources, address, signMessage, embeddedWalletSigner, true) : void 0;
3732
3738
  const encryptedThoughtProcess = msg.thoughtProcess ? await encryptJsonField(msg.thoughtProcess, address, signMessage, embeddedWalletSigner, true) : void 0;
3739
+ const encryptedToolCallEvents = Array.isArray(msg.toolCallEvents) ? await encryptToolCallEvents(
3740
+ msg.toolCallEvents,
3741
+ address,
3742
+ signMessage,
3743
+ embeddedWalletSigner
3744
+ ) : void 0;
3733
3745
  return {
3734
3746
  ...message,
3735
3747
  ...encryptedContent !== void 0 && { content: encryptedContent },
@@ -3737,13 +3749,31 @@ async function encryptMessageFields(message, address, signMessage, embeddedWalle
3737
3749
  ...encryptedVector !== void 0 && { vector: encryptedVector },
3738
3750
  ...encryptedChunks !== void 0 && { chunks: encryptedChunks },
3739
3751
  ...encryptedSources !== void 0 && { sources: encryptedSources },
3740
- ...encryptedThoughtProcess !== void 0 && { thoughtProcess: encryptedThoughtProcess }
3752
+ ...encryptedThoughtProcess !== void 0 && { thoughtProcess: encryptedThoughtProcess },
3753
+ ...encryptedToolCallEvents !== void 0 && { toolCallEvents: encryptedToolCallEvents }
3741
3754
  };
3742
3755
  } catch (error) {
3743
3756
  getLogger().warn("Failed to encrypt message fields:", error);
3744
3757
  throw error;
3745
3758
  }
3746
3759
  }
3760
+ function mapToolCallPayloads(events, transform) {
3761
+ return Promise.all(
3762
+ events.map(async (event) => {
3763
+ if (!event || typeof event !== "object") return event;
3764
+ const mapped = { ...event };
3765
+ if (typeof event.arguments === "string") mapped.arguments = await transform(event.arguments);
3766
+ if (typeof event.output === "string") mapped.output = await transform(event.output);
3767
+ return mapped;
3768
+ })
3769
+ );
3770
+ }
3771
+ function encryptToolCallEvents(events, address, signMessage, embeddedWalletSigner) {
3772
+ return mapToolCallPayloads(
3773
+ events,
3774
+ (value) => encryptField(value, address, signMessage, embeddedWalletSigner, true)
3775
+ );
3776
+ }
3747
3777
  async function decryptMaybeJsonFieldDetailed(value, address) {
3748
3778
  if (value === void 0) return { value: void 0, status: "plaintext" };
3749
3779
  if (value === null) return { value, status: "plaintext" };
@@ -3829,6 +3859,10 @@ async function assembleDecryptedMessage(message, address) {
3829
3859
  message.thoughtProcess,
3830
3860
  address
3831
3861
  );
3862
+ const toolCallEventsResult = await decryptMaybeJsonFieldDetailed(
3863
+ message.toolCallEvents,
3864
+ address
3865
+ );
3832
3866
  let decryptionStatus;
3833
3867
  let refreshProbe;
3834
3868
  const consider = (status, probe) => {
@@ -3847,6 +3881,14 @@ async function assembleDecryptedMessage(message, address) {
3847
3881
  if (thoughtProcessResult.probe) {
3848
3882
  consider(thoughtProcessResult.status, thoughtProcessResult.probe);
3849
3883
  }
3884
+ if (toolCallEventsResult.probe) {
3885
+ consider(toolCallEventsResult.status, toolCallEventsResult.probe);
3886
+ }
3887
+ const toolCallEvents = Array.isArray(toolCallEventsResult.value) ? await mapToolCallPayloads(toolCallEventsResult.value, async (value) => {
3888
+ const detailed = await decryptFieldDetailed(value, address);
3889
+ consider(detailed.status, isEncrypted(value) ? value : void 0);
3890
+ return detailed.value;
3891
+ }) : void 0;
3850
3892
  const statusForConsumer = decryptionStatus === "ok" || decryptionStatus === "plaintext" || !decryptionStatus ? void 0 : decryptionStatus;
3851
3893
  const result = {
3852
3894
  ...message,
@@ -3855,7 +3897,8 @@ async function assembleDecryptedMessage(message, address) {
3855
3897
  vector: vectorResult.value,
3856
3898
  chunks: chunksResult.value,
3857
3899
  sources: sourcesResult.value,
3858
- thoughtProcess: thoughtProcessResult.value
3900
+ thoughtProcess: thoughtProcessResult.value,
3901
+ toolCallEvents
3859
3902
  };
3860
3903
  if (statusForConsumer) {
3861
3904
  result.decryptionStatus = statusForConsumer;
@@ -4649,7 +4692,7 @@ async function updateMessageChunksOp(ctx, uniqueId, chunks3, embeddingModel) {
4649
4692
  });
4650
4693
  return messageToStored(message, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
4651
4694
  }
4652
- var STRIP_CHUNK_TEXT_PAGE_SIZE = 100;
4695
+ var RAW_REPAIR_PAGE_SIZE = 100;
4653
4696
  function chunksWithoutText(raw) {
4654
4697
  if (typeof raw !== "string") return null;
4655
4698
  let parsed;
@@ -4672,8 +4715,8 @@ function chunksWithoutText(raw) {
4672
4715
  async function stripLegacyChunkTextOp(ctx) {
4673
4716
  const candidateIds = await ctx.messagesCollection.query(import_watermelondb2.Q.where("chunks", import_watermelondb2.Q.like(`%${import_watermelondb2.Q.sanitizeLikeString('"text":')}%`))).fetchIds();
4674
4717
  let stripped = 0;
4675
- for (let start = 0; start < candidateIds.length; start += STRIP_CHUNK_TEXT_PAGE_SIZE) {
4676
- const pageIds = candidateIds.slice(start, start + STRIP_CHUNK_TEXT_PAGE_SIZE);
4718
+ for (let start = 0; start < candidateIds.length; start += RAW_REPAIR_PAGE_SIZE) {
4719
+ const pageIds = candidateIds.slice(start, start + RAW_REPAIR_PAGE_SIZE);
4677
4720
  const rows = await ctx.messagesCollection.query(import_watermelondb2.Q.where("id", import_watermelondb2.Q.oneOf(pageIds))).unsafeFetchRaw();
4678
4721
  const changedIds = rows.filter((row) => chunksWithoutText(row.chunks) !== null).map((row) => String(row.id));
4679
4722
  if (changedIds.length === 0) continue;
@@ -4697,6 +4740,88 @@ async function stripLegacyChunkTextOp(ctx) {
4697
4740
  }
4698
4741
  return stripped;
4699
4742
  }
4743
+ async function encryptedToolCallEventsColumn(raw, address, signMessage, embeddedWalletSigner) {
4744
+ if (typeof raw !== "string") return null;
4745
+ let parsed;
4746
+ try {
4747
+ parsed = JSON.parse(raw);
4748
+ } catch {
4749
+ return null;
4750
+ }
4751
+ if (!Array.isArray(parsed)) return null;
4752
+ const column = JSON.stringify(
4753
+ await encryptToolCallEvents(
4754
+ parsed,
4755
+ address,
4756
+ signMessage,
4757
+ embeddedWalletSigner
4758
+ )
4759
+ );
4760
+ return column === JSON.stringify(parsed) ? null : column;
4761
+ }
4762
+ async function encryptToolCallEventsOp(ctx) {
4763
+ const { walletAddress: address, signMessage, embeddedWalletSigner } = ctx;
4764
+ if (!address || !signMessage) return 0;
4765
+ if (!await requestEncryptionKey(address, signMessage, embeddedWalletSigner)) return 0;
4766
+ if (!hasEncryptionKey(address)) return 0;
4767
+ if (!await savedKeyOpensExistingData(ctx, address, signMessage, embeddedWalletSigner)) {
4768
+ return 0;
4769
+ }
4770
+ const candidateIds = await ctx.messagesCollection.query(
4771
+ import_watermelondb2.Q.where("tool_call_events", import_watermelondb2.Q.notEq(null)),
4772
+ import_watermelondb2.Q.where("tool_call_events", import_watermelondb2.Q.notIn(["", "[]"]))
4773
+ ).fetchIds();
4774
+ let encrypted = 0;
4775
+ for (let start = 0; start < candidateIds.length; start += RAW_REPAIR_PAGE_SIZE) {
4776
+ const pageIds = candidateIds.slice(start, start + RAW_REPAIR_PAGE_SIZE);
4777
+ const rows = await ctx.messagesCollection.query(import_watermelondb2.Q.where("id", import_watermelondb2.Q.oneOf(pageIds))).unsafeFetchRaw();
4778
+ const repairs = /* @__PURE__ */ new Map();
4779
+ for (const row of rows) {
4780
+ const column = await encryptedToolCallEventsColumn(
4781
+ row.tool_call_events,
4782
+ address,
4783
+ signMessage,
4784
+ embeddedWalletSigner
4785
+ );
4786
+ if (column !== null) repairs.set(String(row.id), { raw: row.tool_call_events, column });
4787
+ }
4788
+ if (repairs.size === 0) continue;
4789
+ await ctx.database.write(async () => {
4790
+ const messages = (await ctx.messagesCollection.query(import_watermelondb2.Q.where("id", import_watermelondb2.Q.oneOf([...repairs.keys()]))).fetch()).filter(
4791
+ (message) => message._raw.tool_call_events === repairs.get(message.id)?.raw
4792
+ );
4793
+ if (messages.length === 0) return;
4794
+ const conversationIds = [...new Set(messages.map((message) => message.conversationId))];
4795
+ const conversations = await ctx.conversationsCollection.query(import_watermelondb2.Q.where("conversation_id", import_watermelondb2.Q.oneOf(conversationIds))).fetch();
4796
+ await ctx.database.batch(
4797
+ ...messages.map(
4798
+ (message) => message.prepareUpdate((msg) => {
4799
+ msg._setRaw("tool_call_events", repairs.get(message.id).column);
4800
+ })
4801
+ ),
4802
+ ...conversations.map((conversation) => conversation.prepareUpdate(() => {
4803
+ }))
4804
+ );
4805
+ encrypted += messages.length;
4806
+ });
4807
+ }
4808
+ return encrypted;
4809
+ }
4810
+ async function savedKeyOpensExistingData(ctx, address, signMessage, embeddedWalletSigner) {
4811
+ const v3Probe = await findEncryptedContent(ctx, "enc:v3:%");
4812
+ if (v3Probe) {
4813
+ const { status } = await decryptFieldDetailed(v3Probe, address);
4814
+ if (status !== "auth_mismatch" && status !== "key_missing") return true;
4815
+ return refreshEncryptionKeyIfMatches(address, v3Probe, signMessage, embeddedWalletSigner);
4816
+ }
4817
+ const v2Probe = await findEncryptedContent(ctx, "enc:v2:%");
4818
+ if (!v2Probe) return true;
4819
+ return refreshEncryptionKeyIfMatches(address, v2Probe, signMessage, embeddedWalletSigner);
4820
+ }
4821
+ async function findEncryptedContent(ctx, pattern) {
4822
+ const [row] = await ctx.messagesCollection.query(import_watermelondb2.Q.where("content", import_watermelondb2.Q.like(pattern)), import_watermelondb2.Q.take(1)).unsafeFetchRaw();
4823
+ return row ? String(row.content) : null;
4824
+ }
4700
4825
  async function updateMessageErrorOp(ctx, uniqueId, error) {
4701
4826
  let message;
4702
4827
  try {
@@ -6575,7 +6700,8 @@ function extractReservationReceipts(toolCallEvents) {
6575
6700
  for (const event of toolCallEvents ?? []) {
6576
6701
  const action = ACTIONS.find((a) => event.name?.endsWith(a.tool));
6577
6702
  const output = event.output ?? "";
6578
- if (!action || !output || NOT_AN_ATTEMPT.test(output)) continue;
6703
+ if (!action || !output || hasEncryptedToolPayload(event) || NOT_AN_ATTEMPT.test(output))
6704
+ continue;
6579
6705
  const kept = latest.get(action.kind)?.status;
6580
6706
  if (kept === "made") continue;
6581
6707
  const receipt = toReceipt(action, event.arguments ?? "", output);
@@ -32041,11 +32167,12 @@ async function storedToLlmapiMessage(stored2, encryptionKey, resolveMediaByIds)
32041
32167
  textContent = textContent.replace(/\n{3,}/g, "\n\n").trim();
32042
32168
  const content = [{ type: "text", text: textContent }, ...imageParts];
32043
32169
  const messages = [];
32044
- if (stored2.role === "assistant" && stored2.toolCallEvents?.length) {
32170
+ const toolCallEvents = Array.isArray(stored2.toolCallEvents) ? stored2.toolCallEvents.filter((event) => !hasEncryptedToolPayload(event)) : [];
32171
+ if (stored2.role === "assistant" && toolCallEvents.length) {
32045
32172
  messages.push({
32046
32173
  role: stored2.role,
32047
32174
  content: void 0,
32048
- tool_calls: stored2.toolCallEvents.map((event) => ({
32175
+ tool_calls: toolCallEvents.map((event) => ({
32049
32176
  id: event.id,
32050
32177
  type: "function",
32051
32178
  function: {
@@ -32054,7 +32181,7 @@ async function storedToLlmapiMessage(stored2, encryptionKey, resolveMediaByIds)
32054
32181
  }
32055
32182
  }))
32056
32183
  });
32057
- for (const event of stored2.toolCallEvents) {
32184
+ for (const event of toolCallEvents) {
32058
32185
  if (event.id && event.output !== void 0 && event.output !== null) {
32059
32186
  messages.push({
32060
32187
  role: "tool",
@@ -37042,6 +37169,7 @@ function useWalletBinding(options = {}) {
37042
37169
  encryptDataBatch,
37043
37170
  encryptDataBytes,
37044
37171
  encryptDataWithKey,
37172
+ encryptToolCallEventsOp,
37045
37173
  ensureDefaultFoldersOp,
37046
37174
  expandToolSetsAdditive,
37047
37175
  exportElementToPdf,