@anuma/sdk 4.2.0 → 5.0.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.
- package/dist/expo/{chunk-VBO6KSNQ.mjs → chunk-SIMGZQ4P.mjs} +480 -196
- package/dist/expo/index.cjs +417 -120
- package/dist/expo/index.d.mts +161 -26
- package/dist/expo/index.d.ts +161 -26
- package/dist/expo/index.mjs +22 -6
- package/dist/expo/{recall-OCQOA7M3.mjs → recall-PIDYDFIQ.mjs} +1 -1
- package/dist/index.cjs +31 -17
- package/dist/index.mjs +31 -17
- package/dist/react/{chunk-BS7C4CUW.mjs → chunk-KTBOHRRE.mjs} +480 -196
- package/dist/react/index.cjs +417 -120
- package/dist/react/index.d.mts +155 -26
- package/dist/react/index.d.ts +155 -26
- package/dist/react/index.mjs +22 -6
- package/dist/react/{recall-WXCZHXHZ.mjs → recall-DVX4W2UD.mjs} +1 -1
- package/dist/server/{chunk-WADHFDMA.mjs → chunk-FKVYUOSD.mjs} +480 -196
- package/dist/server/index.cjs +417 -120
- package/dist/server/index.d.mts +154 -25
- package/dist/server/index.d.ts +154 -25
- package/dist/server/index.mjs +22 -6
- package/dist/server/{recall-QTVT7HCZ.mjs → recall-74L75BJ3.mjs} +1 -1
- package/package.json +1 -1
package/dist/react/index.cjs
CHANGED
|
@@ -276,14 +276,11 @@ function notifyKeyAvailable(address) {
|
|
|
276
276
|
}
|
|
277
277
|
}
|
|
278
278
|
}
|
|
279
|
-
function getStoredKey(address) {
|
|
280
|
-
const keys = encryptionKeyStore.get(address);
|
|
281
|
-
return keys?.current ?? null;
|
|
282
|
-
}
|
|
283
279
|
function getStoredKeyByVersion(address, version) {
|
|
284
280
|
const keys = encryptionKeyStore.get(address);
|
|
285
281
|
if (!keys) return null;
|
|
286
|
-
|
|
282
|
+
const value = version === "v2" ? keys.legacy : keys.current;
|
|
283
|
+
return value ?? null;
|
|
287
284
|
}
|
|
288
285
|
function setStoredKey(address, keys) {
|
|
289
286
|
encryptionKeyStore.set(address, keys);
|
|
@@ -292,6 +289,8 @@ function clearEncryptionKey(address) {
|
|
|
292
289
|
encryptionKeyStore.delete(address);
|
|
293
290
|
cryptoKeyCache.delete(`${address}:v2`);
|
|
294
291
|
cryptoKeyCache.delete(`${address}:v3`);
|
|
292
|
+
refreshCandidatesByAddress.delete(address);
|
|
293
|
+
divergentDeriveAddresses.delete(address);
|
|
295
294
|
}
|
|
296
295
|
function clearAllEncryptionState() {
|
|
297
296
|
sessionEpoch += 1;
|
|
@@ -299,6 +298,9 @@ function clearAllEncryptionState() {
|
|
|
299
298
|
cryptoKeyCache.clear();
|
|
300
299
|
keyAvailableCallbacks.clear();
|
|
301
300
|
pendingKeyRequests.clear();
|
|
301
|
+
pendingCandidateDerives.clear();
|
|
302
|
+
refreshCandidatesByAddress.clear();
|
|
303
|
+
divergentDeriveAddresses.clear();
|
|
302
304
|
clearAllKeyPairs();
|
|
303
305
|
for (const cb of clearAllEncryptionStateCallbacks) {
|
|
304
306
|
try {
|
|
@@ -482,9 +484,7 @@ async function getEncryptionKey(address, version = "v3") {
|
|
|
482
484
|
}
|
|
483
485
|
const keyHex = getStoredKeyByVersion(address, version);
|
|
484
486
|
if (!keyHex) {
|
|
485
|
-
throw new
|
|
486
|
-
"Encryption key not found. Please sign a message to generate your encryption key."
|
|
487
|
-
);
|
|
487
|
+
throw new EncryptionKeyMissingError(address, version);
|
|
488
488
|
}
|
|
489
489
|
const keyBytes = hexToBytes(keyHex);
|
|
490
490
|
const cryptoKey = await crypto.subtle.importKey(
|
|
@@ -548,8 +548,42 @@ async function decryptDataBytesFromBytes(encrypted, address, version = "v3") {
|
|
|
548
548
|
);
|
|
549
549
|
return new Uint8Array(decryptedData);
|
|
550
550
|
}
|
|
551
|
-
function hasEncryptionKey(address) {
|
|
552
|
-
return
|
|
551
|
+
function hasEncryptionKey(address, version) {
|
|
552
|
+
return getStoredKeyByVersion(address, version ?? "v3") !== null;
|
|
553
|
+
}
|
|
554
|
+
function seedEncryptionKeys(address, keys) {
|
|
555
|
+
if (!isValidWalletAddress(address)) {
|
|
556
|
+
throw new Error(
|
|
557
|
+
`Invalid wallet address: ${address}. Address must start with 0x and be 42 characters (0x + 40 hex characters).`
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
if (!keys.legacy && !keys.current) {
|
|
561
|
+
throw new Error("seedEncryptionKeys: at least one of legacy or current is required");
|
|
562
|
+
}
|
|
563
|
+
if (keys.legacy !== void 0) {
|
|
564
|
+
assertAes256KeyHex("legacy", keys.legacy);
|
|
565
|
+
}
|
|
566
|
+
if (keys.current !== void 0) {
|
|
567
|
+
assertAes256KeyHex("current", keys.current);
|
|
568
|
+
}
|
|
569
|
+
const existing = encryptionKeyStore.get(address);
|
|
570
|
+
const next = {
|
|
571
|
+
legacy: keys.legacy ?? existing?.legacy,
|
|
572
|
+
current: keys.current ?? existing?.current
|
|
573
|
+
};
|
|
574
|
+
setStoredKey(address, next);
|
|
575
|
+
if (keys.legacy !== void 0) cryptoKeyCache.delete(`${address}:v2`);
|
|
576
|
+
if (keys.current !== void 0) cryptoKeyCache.delete(`${address}:v3`);
|
|
577
|
+
refreshCandidatesByAddress.delete(address);
|
|
578
|
+
divergentDeriveAddresses.delete(address);
|
|
579
|
+
notifyKeyAvailable(address);
|
|
580
|
+
}
|
|
581
|
+
function assertAes256KeyHex(field10, value) {
|
|
582
|
+
if (!AES_256_KEY_HEX.test(value)) {
|
|
583
|
+
throw new Error(
|
|
584
|
+
`seedEncryptionKeys: ${field10} must be 64 hex characters (32-byte AES key), got length ${value.length}`
|
|
585
|
+
);
|
|
586
|
+
}
|
|
553
587
|
}
|
|
554
588
|
async function encryptBytesWithKey(plaintext, key) {
|
|
555
589
|
const plaintextBytes = typeof plaintext === "string" ? SHARED_TEXT_ENCODER.encode(plaintext) : plaintext;
|
|
@@ -598,20 +632,23 @@ async function decryptDataBatch(encryptedValues, address) {
|
|
|
598
632
|
const key = await getEncryptionKey(address);
|
|
599
633
|
return Promise.all(encryptedValues.map((value) => decryptDataWithKey(value, key)));
|
|
600
634
|
}
|
|
601
|
-
async function requestEncryptionKey(walletAddress, signMessage, embeddedWalletSigner) {
|
|
635
|
+
async function requestEncryptionKey(walletAddress, signMessage, embeddedWalletSigner, options) {
|
|
602
636
|
if (!isValidWalletAddress(walletAddress)) {
|
|
603
637
|
throw new Error(
|
|
604
638
|
`Invalid wallet address: ${walletAddress}. Address must start with 0x and be 42 characters (0x + 40 hex characters).`
|
|
605
639
|
);
|
|
606
640
|
}
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
return;
|
|
641
|
+
if (!options?.force && getStoredKeyByVersion(walletAddress, "v3") && getStoredKeyByVersion(walletAddress, "v2")) {
|
|
642
|
+
return true;
|
|
610
643
|
}
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
644
|
+
if (!options?.force && divergentDeriveAddresses.has(walletAddress)) {
|
|
645
|
+
return false;
|
|
646
|
+
}
|
|
647
|
+
if (!options?.force) {
|
|
648
|
+
const pending = pendingKeyRequests.get(walletAddress);
|
|
649
|
+
if (pending) {
|
|
650
|
+
return pending;
|
|
651
|
+
}
|
|
615
652
|
}
|
|
616
653
|
const startEpoch = sessionEpoch;
|
|
617
654
|
const promise = (async () => {
|
|
@@ -639,20 +676,143 @@ async function requestEncryptionKey(walletAddress, signMessage, embeddedWalletSi
|
|
|
639
676
|
deriveKeyFromSignatureV3(signature)
|
|
640
677
|
]);
|
|
641
678
|
if (sessionEpoch !== startEpoch) {
|
|
642
|
-
return;
|
|
679
|
+
return false;
|
|
643
680
|
}
|
|
644
|
-
|
|
681
|
+
const existing = encryptionKeyStore.get(walletAddress);
|
|
682
|
+
if (!options?.force && existing && (existing.legacy || existing.current)) {
|
|
683
|
+
const matchesCurrent = Boolean(existing.current && existing.current === currentKey);
|
|
684
|
+
const matchesLegacy = Boolean(existing.legacy && existing.legacy === legacyKey);
|
|
685
|
+
if (!matchesCurrent && !matchesLegacy) {
|
|
686
|
+
getLogger().warn(
|
|
687
|
+
"requestEncryptionKey: derived keys do not match existing store; leaving unchanged"
|
|
688
|
+
);
|
|
689
|
+
divergentDeriveAddresses.add(walletAddress);
|
|
690
|
+
return false;
|
|
691
|
+
}
|
|
692
|
+
setStoredKey(walletAddress, {
|
|
693
|
+
legacy: existing.legacy ?? legacyKey,
|
|
694
|
+
current: existing.current ?? currentKey
|
|
695
|
+
});
|
|
696
|
+
} else {
|
|
697
|
+
setStoredKey(walletAddress, { legacy: legacyKey, current: currentKey });
|
|
698
|
+
}
|
|
699
|
+
cryptoKeyCache.delete(`${walletAddress}:v2`);
|
|
700
|
+
cryptoKeyCache.delete(`${walletAddress}:v3`);
|
|
701
|
+
refreshCandidatesByAddress.delete(walletAddress);
|
|
702
|
+
divergentDeriveAddresses.delete(walletAddress);
|
|
645
703
|
notifyKeyAvailable(walletAddress);
|
|
704
|
+
return true;
|
|
646
705
|
})();
|
|
647
706
|
pendingKeyRequests.set(walletAddress, promise);
|
|
648
707
|
try {
|
|
649
|
-
await promise;
|
|
708
|
+
return await promise;
|
|
650
709
|
} finally {
|
|
651
710
|
if (pendingKeyRequests.get(walletAddress) === promise) {
|
|
652
711
|
pendingKeyRequests.delete(walletAddress);
|
|
653
712
|
}
|
|
654
713
|
}
|
|
655
714
|
}
|
|
715
|
+
async function refreshEncryptionKeyIfMatches(walletAddress, probeCiphertext, signMessage, embeddedWalletSigner) {
|
|
716
|
+
if (!isValidWalletAddress(walletAddress)) {
|
|
717
|
+
throw new Error(
|
|
718
|
+
`Invalid wallet address: ${walletAddress}. Address must start with 0x and be 42 characters (0x + 40 hex characters).`
|
|
719
|
+
);
|
|
720
|
+
}
|
|
721
|
+
const parsed = parsePrefixedCiphertext(probeCiphertext);
|
|
722
|
+
if (!parsed) {
|
|
723
|
+
return false;
|
|
724
|
+
}
|
|
725
|
+
const cached = refreshCandidatesByAddress.get(walletAddress);
|
|
726
|
+
if (cached) {
|
|
727
|
+
return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, cached);
|
|
728
|
+
}
|
|
729
|
+
let derivePromise = pendingCandidateDerives.get(walletAddress);
|
|
730
|
+
if (!derivePromise) {
|
|
731
|
+
derivePromise = (async () => {
|
|
732
|
+
const candidates2 = await deriveRefreshCandidates(signMessage, embeddedWalletSigner);
|
|
733
|
+
if (candidates2) {
|
|
734
|
+
refreshCandidatesByAddress.set(walletAddress, candidates2);
|
|
735
|
+
}
|
|
736
|
+
return candidates2;
|
|
737
|
+
})().finally(() => {
|
|
738
|
+
if (pendingCandidateDerives.get(walletAddress) === derivePromise) {
|
|
739
|
+
pendingCandidateDerives.delete(walletAddress);
|
|
740
|
+
}
|
|
741
|
+
});
|
|
742
|
+
pendingCandidateDerives.set(walletAddress, derivePromise);
|
|
743
|
+
}
|
|
744
|
+
const candidates = await derivePromise;
|
|
745
|
+
if (!candidates) {
|
|
746
|
+
return false;
|
|
747
|
+
}
|
|
748
|
+
return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates);
|
|
749
|
+
}
|
|
750
|
+
function parsePrefixedCiphertext(probeCiphertext) {
|
|
751
|
+
const version = probeCiphertext.startsWith("enc:v3:") ? "v3" : probeCiphertext.startsWith("enc:v2:") ? "v2" : null;
|
|
752
|
+
if (!version) return null;
|
|
753
|
+
const encryptedData = probeCiphertext.slice(
|
|
754
|
+
version === "v3" ? "enc:v3:".length : "enc:v2:".length
|
|
755
|
+
);
|
|
756
|
+
if (encryptedData.length < 56 || !/^[0-9a-f]+$/i.test(encryptedData)) {
|
|
757
|
+
return null;
|
|
758
|
+
}
|
|
759
|
+
return { version, encryptedData };
|
|
760
|
+
}
|
|
761
|
+
async function deriveRefreshCandidates(signMessage, embeddedWalletSigner) {
|
|
762
|
+
const startEpoch = sessionEpoch;
|
|
763
|
+
const signOptions = { showWalletUIs: false };
|
|
764
|
+
let signature;
|
|
765
|
+
try {
|
|
766
|
+
if (embeddedWalletSigner) {
|
|
767
|
+
signature = await embeddedWalletSigner(SIGN_MESSAGE, signOptions);
|
|
768
|
+
} else {
|
|
769
|
+
signature = await signMessage(SIGN_MESSAGE, signOptions);
|
|
770
|
+
}
|
|
771
|
+
} catch (error) {
|
|
772
|
+
if (embeddedWalletSigner && error instanceof Error) {
|
|
773
|
+
getLogger().warn(
|
|
774
|
+
"Embedded wallet signing failed during key refresh, falling back to standard signMessage:",
|
|
775
|
+
error.message
|
|
776
|
+
);
|
|
777
|
+
signature = await signMessage(SIGN_MESSAGE, signOptions);
|
|
778
|
+
} else {
|
|
779
|
+
throw error;
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
const [legacyKey, currentKey] = await Promise.all([
|
|
783
|
+
deriveKeyFromSignature(signature),
|
|
784
|
+
deriveKeyFromSignatureV3(signature)
|
|
785
|
+
]);
|
|
786
|
+
if (sessionEpoch !== startEpoch) {
|
|
787
|
+
return null;
|
|
788
|
+
}
|
|
789
|
+
return { legacy: legacyKey, current: currentKey };
|
|
790
|
+
}
|
|
791
|
+
async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates) {
|
|
792
|
+
const candidateHex = parsed.version === "v2" ? candidates.legacy : candidates.current;
|
|
793
|
+
const keyBytes = hexToBytes(candidateHex);
|
|
794
|
+
const candidateCryptoKey = await crypto.subtle.importKey(
|
|
795
|
+
"raw",
|
|
796
|
+
keyBytes.buffer,
|
|
797
|
+
{ name: "AES-GCM" },
|
|
798
|
+
false,
|
|
799
|
+
["encrypt", "decrypt"]
|
|
800
|
+
);
|
|
801
|
+
try {
|
|
802
|
+
await decryptDataWithKey(parsed.encryptedData, candidateCryptoKey);
|
|
803
|
+
} catch {
|
|
804
|
+
getLogger().warn(
|
|
805
|
+
"refreshEncryptionKeyIfMatches: candidate keys failed to decrypt probe; leaving store unchanged"
|
|
806
|
+
);
|
|
807
|
+
return false;
|
|
808
|
+
}
|
|
809
|
+
setStoredKey(walletAddress, { legacy: candidates.legacy, current: candidates.current });
|
|
810
|
+
cryptoKeyCache.delete(`${walletAddress}:v2`);
|
|
811
|
+
cryptoKeyCache.delete(`${walletAddress}:v3`);
|
|
812
|
+
divergentDeriveAddresses.delete(walletAddress);
|
|
813
|
+
notifyKeyAvailable(walletAddress);
|
|
814
|
+
return true;
|
|
815
|
+
}
|
|
656
816
|
async function persistKeyPair(address, startEpoch) {
|
|
657
817
|
if (typeof window === "undefined") {
|
|
658
818
|
return;
|
|
@@ -886,15 +1046,28 @@ function useEncryption(signMessage, embeddedWalletSigner) {
|
|
|
886
1046
|
clearKeyPair: (walletAddress) => clearKeyPair(walletAddress)
|
|
887
1047
|
};
|
|
888
1048
|
}
|
|
889
|
-
var SIGN_MESSAGE, encryptionKeyStore, pendingKeyRequests, sessionEpoch, cryptoKeyCache, keyAvailableCallbacks, clearAllEncryptionStateCallbacks, keyPairStore, SHARED_TEXT_ENCODER, SHARED_TEXT_DECODER, KEYPAIR_STORAGE_PREFIX;
|
|
1049
|
+
var SIGN_MESSAGE, EncryptionKeyMissingError, encryptionKeyStore, pendingKeyRequests, pendingCandidateDerives, refreshCandidatesByAddress, divergentDeriveAddresses, sessionEpoch, cryptoKeyCache, keyAvailableCallbacks, clearAllEncryptionStateCallbacks, keyPairStore, SHARED_TEXT_ENCODER, SHARED_TEXT_DECODER, AES_256_KEY_HEX, KEYPAIR_STORAGE_PREFIX;
|
|
890
1050
|
var init_useEncryption = __esm({
|
|
891
1051
|
"src/react/useEncryption.ts"() {
|
|
892
1052
|
"use strict";
|
|
893
1053
|
"use client";
|
|
894
1054
|
init_logger();
|
|
895
1055
|
SIGN_MESSAGE = "The app is asking you to sign this message to generate a key, which will be used to encrypt data.";
|
|
1056
|
+
EncryptionKeyMissingError = class extends Error {
|
|
1057
|
+
constructor(address, version) {
|
|
1058
|
+
super(
|
|
1059
|
+
`Encryption key (${version}) not found for ${address}. Please sign a message to generate your encryption key.`
|
|
1060
|
+
);
|
|
1061
|
+
this.name = "EncryptionKeyMissingError";
|
|
1062
|
+
this.address = address;
|
|
1063
|
+
this.version = version;
|
|
1064
|
+
}
|
|
1065
|
+
};
|
|
896
1066
|
encryptionKeyStore = /* @__PURE__ */ new Map();
|
|
897
1067
|
pendingKeyRequests = /* @__PURE__ */ new Map();
|
|
1068
|
+
pendingCandidateDerives = /* @__PURE__ */ new Map();
|
|
1069
|
+
refreshCandidatesByAddress = /* @__PURE__ */ new Map();
|
|
1070
|
+
divergentDeriveAddresses = /* @__PURE__ */ new Set();
|
|
898
1071
|
sessionEpoch = 0;
|
|
899
1072
|
cryptoKeyCache = /* @__PURE__ */ new Map();
|
|
900
1073
|
keyAvailableCallbacks = /* @__PURE__ */ new Map();
|
|
@@ -902,6 +1075,7 @@ var init_useEncryption = __esm({
|
|
|
902
1075
|
keyPairStore = /* @__PURE__ */ new Map();
|
|
903
1076
|
SHARED_TEXT_ENCODER = new TextEncoder();
|
|
904
1077
|
SHARED_TEXT_DECODER = new TextDecoder();
|
|
1078
|
+
AES_256_KEY_HEX = /^[0-9a-fA-F]{64}$/;
|
|
905
1079
|
KEYPAIR_STORAGE_PREFIX = "ecdh_keypair_";
|
|
906
1080
|
}
|
|
907
1081
|
});
|
|
@@ -954,20 +1128,29 @@ async function encryptField(value, address, signMessage, embeddedWalletSigner, s
|
|
|
954
1128
|
const encrypted = await encryptData(value, address);
|
|
955
1129
|
return `${ENCRYPTION_PREFIX}${encrypted}`;
|
|
956
1130
|
}
|
|
957
|
-
async function
|
|
958
|
-
if (!value) return value;
|
|
1131
|
+
async function decryptFieldDetailed(value, address) {
|
|
1132
|
+
if (!value) return { status: "plaintext", value };
|
|
959
1133
|
const detected = detectEncryptionVersion(value);
|
|
960
|
-
if (!detected) return value;
|
|
1134
|
+
if (!detected) return { status: "plaintext", value };
|
|
961
1135
|
if (detected.encryptedData.length < 56 || !/^[0-9a-f]+$/i.test(detected.encryptedData)) {
|
|
962
|
-
return value;
|
|
1136
|
+
return { status: "invalid_payload", value, version: detected.version };
|
|
963
1137
|
}
|
|
964
1138
|
try {
|
|
965
|
-
|
|
1139
|
+
const plaintext = await decryptData(detected.encryptedData, address, detected.version);
|
|
1140
|
+
return { status: "ok", value: plaintext, version: detected.version };
|
|
966
1141
|
} catch (error) {
|
|
967
|
-
|
|
968
|
-
|
|
1142
|
+
if (error instanceof EncryptionKeyMissingError) {
|
|
1143
|
+
getLogger().warn("Failed to decrypt field (key missing for version):", error.message);
|
|
1144
|
+
return { status: "key_missing", value, version: detected.version };
|
|
1145
|
+
}
|
|
1146
|
+
getLogger().warn("Failed to decrypt field (auth mismatch or crypto error):", error);
|
|
1147
|
+
return { status: "auth_mismatch", value, version: detected.version };
|
|
969
1148
|
}
|
|
970
1149
|
}
|
|
1150
|
+
async function decryptField(value, address) {
|
|
1151
|
+
const result = await decryptFieldDetailed(value, address);
|
|
1152
|
+
return result.value;
|
|
1153
|
+
}
|
|
971
1154
|
async function encryptJsonField(value, address, signMessage, embeddedWalletSigner, skipKeyRequest) {
|
|
972
1155
|
if (!value) return void 0;
|
|
973
1156
|
const jsonString = JSON.stringify(value);
|
|
@@ -1084,20 +1267,40 @@ async function encryptMessageFields(message, address, signMessage, embeddedWalle
|
|
|
1084
1267
|
throw error;
|
|
1085
1268
|
}
|
|
1086
1269
|
}
|
|
1087
|
-
async function
|
|
1088
|
-
if (value === void 0) return void 0;
|
|
1089
|
-
if (value === null) return value;
|
|
1270
|
+
async function decryptMaybeJsonFieldDetailed(value, address) {
|
|
1271
|
+
if (value === void 0) return { value: void 0, status: "plaintext" };
|
|
1272
|
+
if (value === null) return { value, status: "plaintext" };
|
|
1090
1273
|
if (typeof value === "string") {
|
|
1091
1274
|
if (isEncrypted(value)) {
|
|
1092
|
-
|
|
1275
|
+
const detailed = await decryptFieldDetailed(value, address);
|
|
1276
|
+
if (detailed.status !== "ok") {
|
|
1277
|
+
return { value: void 0, status: detailed.status, probe: value };
|
|
1278
|
+
}
|
|
1279
|
+
try {
|
|
1280
|
+
return { value: JSON.parse(detailed.value), status: "ok" };
|
|
1281
|
+
} catch (error) {
|
|
1282
|
+
getLogger().warn("Failed to parse decrypted JSON field:", error);
|
|
1283
|
+
return { value: void 0, status: "invalid_payload", probe: value };
|
|
1284
|
+
}
|
|
1093
1285
|
}
|
|
1094
1286
|
try {
|
|
1095
|
-
return JSON.parse(value);
|
|
1287
|
+
return { value: JSON.parse(value), status: "plaintext" };
|
|
1096
1288
|
} catch {
|
|
1097
|
-
return void 0;
|
|
1289
|
+
return { value: void 0, status: "plaintext" };
|
|
1098
1290
|
}
|
|
1099
1291
|
}
|
|
1100
|
-
return value;
|
|
1292
|
+
return { value, status: "plaintext" };
|
|
1293
|
+
}
|
|
1294
|
+
function worseDecryptStatus(a, b) {
|
|
1295
|
+
if (b === "ok" || b === "plaintext") return a;
|
|
1296
|
+
if (!a || a === "ok" || a === "plaintext") return b;
|
|
1297
|
+
const rank = (s) => {
|
|
1298
|
+
if (s === "auth_mismatch") return 3;
|
|
1299
|
+
if (s === "key_missing") return 2;
|
|
1300
|
+
if (s === "invalid_payload") return 1;
|
|
1301
|
+
return 0;
|
|
1302
|
+
};
|
|
1303
|
+
return rank(b) >= rank(a) ? b : a;
|
|
1101
1304
|
}
|
|
1102
1305
|
async function decryptMessageFields(message, address, signMessage, embeddedWalletSigner) {
|
|
1103
1306
|
if (!address) {
|
|
@@ -1110,33 +1313,82 @@ async function decryptMessageFields(message, address, signMessage, embeddedWalle
|
|
|
1110
1313
|
getLogger().warn("Failed to request encryption key for decryption:", error);
|
|
1111
1314
|
}
|
|
1112
1315
|
}
|
|
1113
|
-
|
|
1114
|
-
const
|
|
1115
|
-
|
|
1316
|
+
let assembled = await assembleDecryptedMessage(message, address);
|
|
1317
|
+
const needsRefresh = assembled.decryptionStatus === "auth_mismatch" || assembled.decryptionStatus === "key_missing";
|
|
1318
|
+
if (needsRefresh && signMessage && assembled.refreshProbe) {
|
|
1319
|
+
try {
|
|
1320
|
+
const refreshed = await refreshEncryptionKeyIfMatches(
|
|
1321
|
+
address,
|
|
1322
|
+
assembled.refreshProbe,
|
|
1323
|
+
signMessage,
|
|
1324
|
+
embeddedWalletSigner
|
|
1325
|
+
);
|
|
1326
|
+
if (refreshed) {
|
|
1327
|
+
assembled = await assembleDecryptedMessage(message, address);
|
|
1328
|
+
}
|
|
1329
|
+
} catch (error) {
|
|
1330
|
+
getLogger().warn("Failed to refresh encryption key after decrypt failure:", error);
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
const { refreshProbe: _probe, ...result } = assembled;
|
|
1334
|
+
return result;
|
|
1335
|
+
}
|
|
1336
|
+
async function assembleDecryptedMessage(message, address) {
|
|
1337
|
+
const contentResult = await decryptFieldDetailed(message.content, address);
|
|
1338
|
+
const thinkingResult = message.thinking ? await decryptFieldDetailed(message.thinking, address) : null;
|
|
1339
|
+
const vectorResult = await decryptMaybeJsonFieldDetailed(
|
|
1116
1340
|
message.vector,
|
|
1117
1341
|
address
|
|
1118
1342
|
);
|
|
1119
|
-
const
|
|
1343
|
+
const chunksResult = await decryptMaybeJsonFieldDetailed(
|
|
1120
1344
|
message.chunks,
|
|
1121
1345
|
address
|
|
1122
1346
|
);
|
|
1123
|
-
const
|
|
1347
|
+
const sourcesResult = await decryptMaybeJsonFieldDetailed(
|
|
1124
1348
|
message.sources,
|
|
1125
1349
|
address
|
|
1126
1350
|
);
|
|
1127
|
-
const
|
|
1351
|
+
const thoughtProcessResult = await decryptMaybeJsonFieldDetailed(
|
|
1128
1352
|
message.thoughtProcess,
|
|
1129
1353
|
address
|
|
1130
1354
|
);
|
|
1131
|
-
|
|
1355
|
+
let decryptionStatus;
|
|
1356
|
+
let refreshProbe;
|
|
1357
|
+
const consider = (status, probe) => {
|
|
1358
|
+
decryptionStatus = worseDecryptStatus(decryptionStatus, status);
|
|
1359
|
+
if (!refreshProbe && probe && (status === "auth_mismatch" || status === "key_missing")) {
|
|
1360
|
+
refreshProbe = probe;
|
|
1361
|
+
}
|
|
1362
|
+
};
|
|
1363
|
+
consider(contentResult.status, isEncrypted(message.content) ? message.content : void 0);
|
|
1364
|
+
if (thinkingResult && message.thinking && typeof message.thinking === "string") {
|
|
1365
|
+
consider(thinkingResult.status, isEncrypted(message.thinking) ? message.thinking : void 0);
|
|
1366
|
+
}
|
|
1367
|
+
if (vectorResult.probe) consider(vectorResult.status, vectorResult.probe);
|
|
1368
|
+
if (chunksResult.probe) consider(chunksResult.status, chunksResult.probe);
|
|
1369
|
+
if (sourcesResult.probe) consider(sourcesResult.status, sourcesResult.probe);
|
|
1370
|
+
if (thoughtProcessResult.probe) {
|
|
1371
|
+
consider(thoughtProcessResult.status, thoughtProcessResult.probe);
|
|
1372
|
+
}
|
|
1373
|
+
const statusForConsumer = decryptionStatus === "ok" || decryptionStatus === "plaintext" || !decryptionStatus ? void 0 : decryptionStatus;
|
|
1374
|
+
const result = {
|
|
1132
1375
|
...message,
|
|
1133
|
-
content:
|
|
1134
|
-
thinking:
|
|
1135
|
-
vector:
|
|
1136
|
-
chunks:
|
|
1137
|
-
sources:
|
|
1138
|
-
thoughtProcess:
|
|
1376
|
+
content: contentResult.value,
|
|
1377
|
+
thinking: thinkingResult ? thinkingResult.value : message.thinking,
|
|
1378
|
+
vector: vectorResult.value,
|
|
1379
|
+
chunks: chunksResult.value,
|
|
1380
|
+
sources: sourcesResult.value,
|
|
1381
|
+
thoughtProcess: thoughtProcessResult.value
|
|
1139
1382
|
};
|
|
1383
|
+
if (statusForConsumer) {
|
|
1384
|
+
result.decryptionStatus = statusForConsumer;
|
|
1385
|
+
} else {
|
|
1386
|
+
delete result.decryptionStatus;
|
|
1387
|
+
}
|
|
1388
|
+
if (refreshProbe) {
|
|
1389
|
+
result.refreshProbe = refreshProbe;
|
|
1390
|
+
}
|
|
1391
|
+
return result;
|
|
1140
1392
|
}
|
|
1141
1393
|
var init_encryption = __esm({
|
|
1142
1394
|
"src/lib/db/chat/encryption.ts"() {
|
|
@@ -6432,11 +6684,11 @@ async function decomposeQuery(query, options) {
|
|
|
6432
6684
|
userMessage: `Classify the following memory query and decompose if composite. Respond with JSON only \u2014 do not answer the question, do not ask for clarification.
|
|
6433
6685
|
|
|
6434
6686
|
Query: ${trimmed}`,
|
|
6435
|
-
// Decompose runs
|
|
6687
|
+
// Decompose runs ahead of recall in the tool layer — tighter than the
|
|
6436
6688
|
// portalLlm default (consolidate/extract can wait longer).
|
|
6437
6689
|
timeoutMs: 2e4,
|
|
6438
6690
|
// No internal retry: a failure degrades to the safe `{specific,[query]}`
|
|
6439
|
-
// fallback below
|
|
6691
|
+
// fallback below. The agent/tool loop is the retry surface (719/B4).
|
|
6440
6692
|
maxAttempts: 1,
|
|
6441
6693
|
tag: "memory/decompose",
|
|
6442
6694
|
...options.fetchFn && { fetchFn: options.fetchFn }
|
|
@@ -6448,12 +6700,28 @@ Query: ${trimmed}`,
|
|
|
6448
6700
|
if (parsed === null) return fallback;
|
|
6449
6701
|
return validate(parsed, trimmed) ?? fallback;
|
|
6450
6702
|
}
|
|
6703
|
+
function normalizeSubQueries(raw) {
|
|
6704
|
+
if (!raw || raw.length === 0) return [];
|
|
6705
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6706
|
+
const out = [];
|
|
6707
|
+
for (const s of raw) {
|
|
6708
|
+
if (typeof s !== "string") continue;
|
|
6709
|
+
const t = s.trim();
|
|
6710
|
+
if (t.length === 0) continue;
|
|
6711
|
+
const key = t.toLowerCase();
|
|
6712
|
+
if (seen.has(key)) continue;
|
|
6713
|
+
seen.add(key);
|
|
6714
|
+
out.push(t);
|
|
6715
|
+
if (out.length >= MAX_SUB_QUERIES) break;
|
|
6716
|
+
}
|
|
6717
|
+
return out;
|
|
6718
|
+
}
|
|
6451
6719
|
function validate(parsed, originalQuery) {
|
|
6452
6720
|
if (typeof parsed !== "object" || parsed === null) return null;
|
|
6453
6721
|
const obj = parsed;
|
|
6454
6722
|
const mode = obj.mode === "composite" ? "composite" : "specific";
|
|
6455
6723
|
if (!Array.isArray(obj.subQueries)) return null;
|
|
6456
|
-
const subQueries = obj.subQueries
|
|
6724
|
+
const subQueries = normalizeSubQueries(obj.subQueries);
|
|
6457
6725
|
if (subQueries.length === 0) return null;
|
|
6458
6726
|
if (mode === "specific") {
|
|
6459
6727
|
return { mode: "specific", subQueries: [originalQuery] };
|
|
@@ -7070,12 +7338,12 @@ __export(recall_exports, {
|
|
|
7070
7338
|
function flagsForBudget(budget) {
|
|
7071
7339
|
switch (budget) {
|
|
7072
7340
|
case "high":
|
|
7073
|
-
return { rerank: true,
|
|
7341
|
+
return { rerank: true, traverse: true };
|
|
7074
7342
|
case "mid":
|
|
7075
|
-
return { rerank: true,
|
|
7343
|
+
return { rerank: true, traverse: false };
|
|
7076
7344
|
case "low":
|
|
7077
7345
|
default:
|
|
7078
|
-
return { rerank: false,
|
|
7346
|
+
return { rerank: false, traverse: false };
|
|
7079
7347
|
}
|
|
7080
7348
|
}
|
|
7081
7349
|
function dedupeBy(items, ...keys) {
|
|
@@ -7094,10 +7362,10 @@ function dedupeBy(items, ...keys) {
|
|
|
7094
7362
|
async function recall(query, ctx, options = {}) {
|
|
7095
7363
|
const types = options.types ?? ["fact"];
|
|
7096
7364
|
const limit = options.limit ?? DEFAULT_LIMIT;
|
|
7097
|
-
const
|
|
7098
|
-
const flags = flagsForBudget(
|
|
7099
|
-
const
|
|
7100
|
-
const
|
|
7365
|
+
const usedBudget = options.budget ?? DEFAULT_BUDGET;
|
|
7366
|
+
const flags = flagsForBudget(usedBudget);
|
|
7367
|
+
const normalizedFacets = normalizeSubQueries(options.subQueries);
|
|
7368
|
+
const subQueries = normalizedFacets.length >= 2 ? normalizedFacets : void 0;
|
|
7101
7369
|
const t0 = nowMs();
|
|
7102
7370
|
let prepMs = 0;
|
|
7103
7371
|
let factLaneMs = 0;
|
|
@@ -7118,7 +7386,9 @@ async function recall(query, ctx, options = {}) {
|
|
|
7118
7386
|
if (flags.rerank && factResults.length > 0 && hadV2Head && !didRerank) {
|
|
7119
7387
|
degraded.push("rerank-unavailable");
|
|
7120
7388
|
}
|
|
7121
|
-
if (
|
|
7389
|
+
if (usedBudget === "high" && options.decomposeOptions && !subQueries && !options.graphRefine) {
|
|
7390
|
+
degraded.push("decompose-moved");
|
|
7391
|
+
}
|
|
7122
7392
|
if (embeddingsUnavailable) degraded.push("embeddings-unavailable");
|
|
7123
7393
|
const diagnostics = {
|
|
7124
7394
|
usedBudget,
|
|
@@ -7231,10 +7501,8 @@ async function recall(query, ctx, options = {}) {
|
|
|
7231
7501
|
},
|
|
7232
7502
|
...options.rrfK !== void 0 && { rrfK: options.rrfK },
|
|
7233
7503
|
...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
|
|
7234
|
-
|
|
7235
|
-
|
|
7236
|
-
decomposeOptions: options.decomposeOptions
|
|
7237
|
-
},
|
|
7504
|
+
// 719/B4 — composite facets arrive pre-built; no LLM call here.
|
|
7505
|
+
...subQueries && { subQueries },
|
|
7238
7506
|
...options.scopes && { scopes: options.scopes },
|
|
7239
7507
|
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
7240
7508
|
...options.factTypes?.length && { factTypes: options.factTypes },
|
|
@@ -7471,6 +7739,7 @@ var init_recall = __esm({
|
|
|
7471
7739
|
init_logger();
|
|
7472
7740
|
init_constants();
|
|
7473
7741
|
init_embeddings();
|
|
7742
|
+
init_decomposeQuery();
|
|
7474
7743
|
init_searchTool();
|
|
7475
7744
|
init_graphTraversal();
|
|
7476
7745
|
init_observationTrend();
|
|
@@ -8416,52 +8685,51 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
8416
8685
|
...searchOptions?.rrfK !== void 0 && { rrfK: searchOptions.rrfK },
|
|
8417
8686
|
...searchOptions?.factTypeWeights && { factTypeWeights: searchOptions.factTypeWeights }
|
|
8418
8687
|
};
|
|
8419
|
-
|
|
8420
|
-
|
|
8421
|
-
|
|
8422
|
-
|
|
8423
|
-
|
|
8424
|
-
|
|
8425
|
-
|
|
8426
|
-
|
|
8427
|
-
|
|
8428
|
-
|
|
8429
|
-
|
|
8430
|
-
|
|
8431
|
-
|
|
8432
|
-
|
|
8433
|
-
|
|
8434
|
-
|
|
8435
|
-
|
|
8436
|
-
|
|
8437
|
-
|
|
8438
|
-
|
|
8439
|
-
|
|
8440
|
-
|
|
8441
|
-
|
|
8442
|
-
|
|
8443
|
-
|
|
8444
|
-
|
|
8445
|
-
|
|
8446
|
-
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
|
|
8453
|
-
|
|
8454
|
-
|
|
8455
|
-
|
|
8456
|
-
|
|
8457
|
-
|
|
8458
|
-
|
|
8459
|
-
|
|
8460
|
-
|
|
8461
|
-
|
|
8462
|
-
|
|
8463
|
-
|
|
8464
|
-
}
|
|
8688
|
+
const normalizedFacets = normalizeSubQueries(searchOptions?.subQueries);
|
|
8689
|
+
const facetQueries = normalizedFacets.length >= 2 ? normalizedFacets : void 0;
|
|
8690
|
+
if (useFusion && !embeddingsUnavailable && facetQueries) {
|
|
8691
|
+
let subEmbeddings;
|
|
8692
|
+
try {
|
|
8693
|
+
subEmbeddings = await generateEmbeddings(facetQueries, embeddingOptions);
|
|
8694
|
+
} catch (err) {
|
|
8695
|
+
getLogger().warn(
|
|
8696
|
+
"memoryVault: sub-query embedding failed \u2014 falling back to single-query ranking: " + (err instanceof Error ? err.message : String(err))
|
|
8697
|
+
);
|
|
8698
|
+
subEmbeddings = [];
|
|
8699
|
+
}
|
|
8700
|
+
const subEmbeddingsUsable = facetQueries.length > 0 && subEmbeddings.length === facetQueries.length && subEmbeddings.every((v) => v.length > 0 && v.length === queryEmbedding.length);
|
|
8701
|
+
if (subEmbeddings.length > 0 && !subEmbeddingsUsable) {
|
|
8702
|
+
getLogger().warn(
|
|
8703
|
+
`memoryVault: sub-query embedding returned ${subEmbeddings.length} vectors (dims ${subEmbeddings.map((v) => v.length).join(",")}) for ${facetQueries.length} sub-queries against a ${queryEmbedding.length}-dim query \u2014 falling back to single-query ranking`
|
|
8704
|
+
);
|
|
8705
|
+
}
|
|
8706
|
+
if (subEmbeddingsUsable) {
|
|
8707
|
+
const subQueries = facetQueries.map((sq, i) => ({
|
|
8708
|
+
query: sq,
|
|
8709
|
+
embedding: subEmbeddings[i]
|
|
8710
|
+
}));
|
|
8711
|
+
const v2HeadStats = { hadResults: false };
|
|
8712
|
+
const composite = await rankComposite(query, queryEmbedding, subQueries, embeddedItems, {
|
|
8713
|
+
limit,
|
|
8714
|
+
minSimilarity,
|
|
8715
|
+
rerank: !!searchOptions?.rerank,
|
|
8716
|
+
...searchOptions?.rerankTopN !== void 0 && {
|
|
8717
|
+
rerankTopN: searchOptions.rerankTopN
|
|
8718
|
+
},
|
|
8719
|
+
...searchOptions?.ceWeight !== void 0 && { ceWeight: searchOptions.ceWeight },
|
|
8720
|
+
...searchOptions?.mmr !== void 0 && { mmr: searchOptions.mmr },
|
|
8721
|
+
...tuning,
|
|
8722
|
+
...searchOptions?.entityRanking && { entityRanking: searchOptions.entityRanking },
|
|
8723
|
+
...searchOptions?.temporalRanking && { temporalRanking: searchOptions.temporalRanking },
|
|
8724
|
+
rerankStats,
|
|
8725
|
+
v2HeadStats
|
|
8726
|
+
});
|
|
8727
|
+
return stampTimestamps({
|
|
8728
|
+
results: composite,
|
|
8729
|
+
vaultSize,
|
|
8730
|
+
reranked: rerankStats.applied,
|
|
8731
|
+
hadV2Head: v2HeadStats.hadResults
|
|
8732
|
+
});
|
|
8465
8733
|
}
|
|
8466
8734
|
}
|
|
8467
8735
|
if (useFusion && searchOptions?.rerank) {
|
|
@@ -8521,6 +8789,12 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
8521
8789
|
rankedOnCosine: false
|
|
8522
8790
|
};
|
|
8523
8791
|
}
|
|
8792
|
+
if (searchOptions?.decompose === "llm" && normalizeSubQueries(searchOptions.subQueries).length < 2 && !warnedProgrammaticDecomposeIgnored) {
|
|
8793
|
+
warnedProgrammaticDecomposeIgnored = true;
|
|
8794
|
+
getLogger().warn(
|
|
8795
|
+
'memoryVault: decompose:"llm" is ignored by searchVaultMemories \u2014 pass subQueries or use createMemoryVaultSearchTool / createRecallTool (719/B4)'
|
|
8796
|
+
);
|
|
8797
|
+
}
|
|
8524
8798
|
const prepared = await prepareVaultCandidates(
|
|
8525
8799
|
query,
|
|
8526
8800
|
vaultCtx,
|
|
@@ -8625,7 +8899,8 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
8625
8899
|
return "Error: A search query is required.";
|
|
8626
8900
|
}
|
|
8627
8901
|
try {
|
|
8628
|
-
const
|
|
8902
|
+
const wantsDecompose = searchOptions?.decompose === "llm" && !!searchOptions.decomposeOptions;
|
|
8903
|
+
const budget = wantsDecompose ? "high" : searchOptions?.rerank ? "mid" : "low";
|
|
8629
8904
|
const folderId = searchOptions?.folderId ?? argFolderId;
|
|
8630
8905
|
if (searchOptions?.useFusion === false) {
|
|
8631
8906
|
const { results: legacy, embeddingsUnavailable } = await searchVaultMemoriesWithSize(
|
|
@@ -8649,6 +8924,13 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
8649
8924
|
legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
|
|
8650
8925
|
);
|
|
8651
8926
|
}
|
|
8927
|
+
let subQueries;
|
|
8928
|
+
if (wantsDecompose && searchOptions?.decomposeOptions) {
|
|
8929
|
+
const decomp = await decomposeQuery(query, searchOptions.decomposeOptions);
|
|
8930
|
+
if (decomp.mode === "composite" && decomp.subQueries.length >= 2) {
|
|
8931
|
+
subQueries = decomp.subQueries;
|
|
8932
|
+
}
|
|
8933
|
+
}
|
|
8652
8934
|
const { recall: recall2 } = await Promise.resolve().then(() => (init_recall(), recall_exports));
|
|
8653
8935
|
let recallDegraded = [];
|
|
8654
8936
|
const result = await recall2(
|
|
@@ -8665,9 +8947,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
8665
8947
|
...tuningForward,
|
|
8666
8948
|
...folderId !== void 0 && { folderId },
|
|
8667
8949
|
...searchOptions?.scopes && { scopes: searchOptions.scopes },
|
|
8668
|
-
...
|
|
8669
|
-
decomposeOptions: searchOptions.decomposeOptions
|
|
8670
|
-
}
|
|
8950
|
+
...subQueries && { subQueries }
|
|
8671
8951
|
}
|
|
8672
8952
|
);
|
|
8673
8953
|
if (result.vaultSize === 0) {
|
|
@@ -8697,7 +8977,7 @@ ${formatted}`;
|
|
|
8697
8977
|
}
|
|
8698
8978
|
};
|
|
8699
8979
|
}
|
|
8700
|
-
var SUPERSESSION_SIMILARITY_THRESHOLD, SUPERSESSION_MIN_AGE_GAP_MS, SUPERSESSION_BOOST_FACTOR, SUPERSESSION_MAX_WINDOW, EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL;
|
|
8980
|
+
var warnedProgrammaticDecomposeIgnored, SUPERSESSION_SIMILARITY_THRESHOLD, SUPERSESSION_MIN_AGE_GAP_MS, SUPERSESSION_BOOST_FACTOR, SUPERSESSION_MAX_WINDOW, EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL;
|
|
8701
8981
|
var init_searchTool = __esm({
|
|
8702
8982
|
"src/lib/memoryVault/searchTool.ts"() {
|
|
8703
8983
|
"use strict";
|
|
@@ -8715,6 +8995,7 @@ var init_searchTool = __esm({
|
|
|
8715
8995
|
init_bm25();
|
|
8716
8996
|
init_decomposeQuery();
|
|
8717
8997
|
init_lruCache();
|
|
8998
|
+
warnedProgrammaticDecomposeIgnored = false;
|
|
8718
8999
|
SUPERSESSION_SIMILARITY_THRESHOLD = 0.7;
|
|
8719
9000
|
SUPERSESSION_MIN_AGE_GAP_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
8720
9001
|
SUPERSESSION_BOOST_FACTOR = 0.8;
|
|
@@ -8938,6 +9219,7 @@ __export(index_exports, {
|
|
|
8938
9219
|
DropboxAuthProvider: () => DropboxAuthProvider,
|
|
8939
9220
|
ENTITY_FANOUT: () => ENTITY_FANOUT,
|
|
8940
9221
|
ENTITY_KINDS: () => ENTITY_KINDS,
|
|
9222
|
+
EncryptionKeyMissingError: () => EncryptionKeyMissingError,
|
|
8941
9223
|
EntityModel: () => Entity,
|
|
8942
9224
|
ExcelProcessor: () => ExcelProcessor,
|
|
8943
9225
|
FILE_PLACEHOLDER_PREFIX: () => FILE_PLACEHOLDER_PREFIX,
|
|
@@ -9228,6 +9510,7 @@ __export(index_exports, {
|
|
|
9228
9510
|
reflect: () => reflect,
|
|
9229
9511
|
refreshCalendarToken: () => refreshCalendarToken,
|
|
9230
9512
|
refreshDriveToken: () => refreshDriveToken,
|
|
9513
|
+
refreshEncryptionKeyIfMatches: () => refreshEncryptionKeyIfMatches,
|
|
9231
9514
|
refreshGithubToken: () => refreshGithubToken,
|
|
9232
9515
|
refreshNotionToken: () => refreshNotionToken,
|
|
9233
9516
|
relinkMemoryTopicsOp: () => relinkMemoryTopicsOp,
|
|
@@ -9259,6 +9542,7 @@ __export(index_exports, {
|
|
|
9259
9542
|
searchMediaOp: () => searchMediaOp,
|
|
9260
9543
|
searchMessagesOp: () => searchMessagesOp,
|
|
9261
9544
|
searchVaultMemories: () => searchVaultMemories,
|
|
9545
|
+
seedEncryptionKeys: () => seedEncryptionKeys,
|
|
9262
9546
|
selectServerToolsForPrompt: () => selectServerToolsForPrompt,
|
|
9263
9547
|
serializeJsx: () => serializeJsx,
|
|
9264
9548
|
setLogger: () => setLogger,
|
|
@@ -17759,6 +18043,7 @@ function rankProfileCandidates(inputs, now = Date.now(), options = {}) {
|
|
|
17759
18043
|
init_recall();
|
|
17760
18044
|
|
|
17761
18045
|
// src/lib/memory/recallTool.ts
|
|
18046
|
+
init_decomposeQuery();
|
|
17762
18047
|
init_recall();
|
|
17763
18048
|
init_recallConstants();
|
|
17764
18049
|
var DEFAULT_LIMIT2 = 8;
|
|
@@ -17856,7 +18141,7 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
17856
18141
|
type: "function",
|
|
17857
18142
|
function: {
|
|
17858
18143
|
name: RECALL_TOOL_NAME,
|
|
17859
|
-
description:
|
|
18144
|
+
description: `Search the user's memory across stored facts/preferences and past conversation excerpts. Returns a unified ranked list \u2014 facts carry an \`id\` you can reference; conversation excerpts carry a date and role. Use this whenever the user's question may relate to anything previously discussed or saved (preferences, prior decisions, past topics). Phrase the query naturally. For multi-faceted / overview questions ("tell me about the user", "what's my tech stack"), prefer several targeted searches \u2014 one facet each (e.g. name, work, hobbies) \u2014 over a single broad query; fuse the results yourself.`,
|
|
17860
18145
|
arguments: {
|
|
17861
18146
|
type: "object",
|
|
17862
18147
|
properties: {
|
|
@@ -17911,6 +18196,13 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
17911
18196
|
let surfaced = 0;
|
|
17912
18197
|
try {
|
|
17913
18198
|
let recallDegraded = [];
|
|
18199
|
+
let subQueries;
|
|
18200
|
+
if (defaultBudget === "high" && toolOptions?.decomposeOptions) {
|
|
18201
|
+
const decomp = await decomposeQuery(query, toolOptions.decomposeOptions);
|
|
18202
|
+
if (decomp.mode === "composite" && decomp.subQueries.length >= 2) {
|
|
18203
|
+
subQueries = decomp.subQueries;
|
|
18204
|
+
}
|
|
18205
|
+
}
|
|
17914
18206
|
const recallOpts = {
|
|
17915
18207
|
onDiagnostics: (d) => {
|
|
17916
18208
|
recallDegraded = d.degraded;
|
|
@@ -17924,10 +18216,12 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
17924
18216
|
...toolOptions?.excludeConversationId && {
|
|
17925
18217
|
excludeConversationId: toolOptions.excludeConversationId
|
|
17926
18218
|
},
|
|
17927
|
-
|
|
17928
|
-
|
|
17929
|
-
|
|
17930
|
-
|
|
18219
|
+
// Do NOT forward decomposeOptions into recall() — rewrite already
|
|
18220
|
+
// ran above, and forwarding would falsely trip `decompose-moved`
|
|
18221
|
+
// on every specific-mode high-budget call. graphRefine auth can
|
|
18222
|
+
// be threaded later when the tool opts into that path.
|
|
18223
|
+
...toolOptions?.now !== void 0 && { now: toolOptions.now },
|
|
18224
|
+
...subQueries && { subQueries }
|
|
17931
18225
|
};
|
|
17932
18226
|
const result = await recall(query, ctx, recallOpts);
|
|
17933
18227
|
if (callbacks?.onChunksRetrieved) {
|
|
@@ -33898,6 +34192,7 @@ function renderAnumaJsx(jsx3) {
|
|
|
33898
34192
|
DropboxAuthProvider,
|
|
33899
34193
|
ENTITY_FANOUT,
|
|
33900
34194
|
ENTITY_KINDS,
|
|
34195
|
+
EncryptionKeyMissingError,
|
|
33901
34196
|
EntityModel,
|
|
33902
34197
|
ExcelProcessor,
|
|
33903
34198
|
FILE_PLACEHOLDER_PREFIX,
|
|
@@ -34188,6 +34483,7 @@ function renderAnumaJsx(jsx3) {
|
|
|
34188
34483
|
reflect,
|
|
34189
34484
|
refreshCalendarToken,
|
|
34190
34485
|
refreshDriveToken,
|
|
34486
|
+
refreshEncryptionKeyIfMatches,
|
|
34191
34487
|
refreshGithubToken,
|
|
34192
34488
|
refreshNotionToken,
|
|
34193
34489
|
relinkMemoryTopicsOp,
|
|
@@ -34219,6 +34515,7 @@ function renderAnumaJsx(jsx3) {
|
|
|
34219
34515
|
searchMediaOp,
|
|
34220
34516
|
searchMessagesOp,
|
|
34221
34517
|
searchVaultMemories,
|
|
34518
|
+
seedEncryptionKeys,
|
|
34222
34519
|
selectServerToolsForPrompt,
|
|
34223
34520
|
serializeJsx,
|
|
34224
34521
|
setLogger,
|