@anuma/sdk 10.9.0 → 11.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/{consolidate-7QUL3TOE.mjs → consolidate-QBV3DDHU.mjs} +1 -1
- package/dist/expo/index.cjs +3446 -2649
- package/dist/expo/index.d.mts +967 -873
- package/dist/expo/index.d.ts +967 -873
- package/dist/expo/index.mjs +2966 -2177
- package/dist/react/index.cjs +1186 -684
- package/dist/react/index.d.mts +720 -715
- package/dist/react/index.d.ts +720 -715
- package/dist/react/index.mjs +1182 -684
- package/dist/server/index.cjs +19 -13
- package/dist/server/index.d.mts +4 -2
- package/dist/server/index.d.ts +4 -2
- package/dist/server/index.mjs +19 -13
- package/package.json +1 -1
- package/dist/expo/{chunk-4SOUKJD5.mjs → chunk-VNTEHEGI.mjs} +957 -957
package/dist/react/index.mjs
CHANGED
|
@@ -544,9 +544,9 @@ async function refreshEncryptionKeyIfMatches(walletAddress, probeCiphertext, sig
|
|
|
544
544
|
return false;
|
|
545
545
|
}
|
|
546
546
|
const startEpoch = sessionEpoch;
|
|
547
|
-
const
|
|
548
|
-
if (
|
|
549
|
-
return tryCommitCandidatesIfProbeMatches(walletAddress, parsed,
|
|
547
|
+
const cached2 = refreshCandidatesByAddress.get(walletAddress);
|
|
548
|
+
if (cached2) {
|
|
549
|
+
return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, cached2, startEpoch);
|
|
550
550
|
}
|
|
551
551
|
let derivePromise = pendingCandidateDerives.get(walletAddress);
|
|
552
552
|
if (!derivePromise) {
|
|
@@ -895,10 +895,10 @@ function parsePlaintextToken(raw, walletAddress) {
|
|
|
895
895
|
return null;
|
|
896
896
|
}
|
|
897
897
|
if (!parsed || typeof parsed !== "object") return null;
|
|
898
|
-
const
|
|
899
|
-
const data =
|
|
898
|
+
const record3 = parsed;
|
|
899
|
+
const data = record3.token?.accessToken ? record3.token : record3;
|
|
900
900
|
if (!data?.accessToken) return null;
|
|
901
|
-
if (
|
|
901
|
+
if (record3.wallet && record3.wallet !== walletAddress) return null;
|
|
902
902
|
return data;
|
|
903
903
|
}
|
|
904
904
|
function promoteUnscopedRow(raw, data, store, scopedKey, unscopedKey, walletAddress) {
|
|
@@ -990,10 +990,10 @@ async function discoverOAuthMetadata() {
|
|
|
990
990
|
}
|
|
991
991
|
async function getOAuthMetadata() {
|
|
992
992
|
if (typeof window !== "undefined") {
|
|
993
|
-
const
|
|
994
|
-
if (
|
|
993
|
+
const cached2 = sessionStorage.getItem(OAUTH_METADATA_KEY);
|
|
994
|
+
if (cached2) {
|
|
995
995
|
try {
|
|
996
|
-
return JSON.parse(
|
|
996
|
+
return JSON.parse(cached2);
|
|
997
997
|
} catch {
|
|
998
998
|
}
|
|
999
999
|
}
|
|
@@ -1097,8 +1097,8 @@ async function storeTokenData(data, walletAddress) {
|
|
|
1097
1097
|
} catch {
|
|
1098
1098
|
}
|
|
1099
1099
|
}
|
|
1100
|
-
const
|
|
1101
|
-
sessionStorage.setItem(getTokenStorageKey(walletAddress), JSON.stringify(
|
|
1100
|
+
const record3 = { wallet: walletAddress, token: data };
|
|
1101
|
+
sessionStorage.setItem(getTokenStorageKey(walletAddress), JSON.stringify(record3));
|
|
1102
1102
|
}
|
|
1103
1103
|
async function getStoredTokenData(walletAddress) {
|
|
1104
1104
|
if (typeof window === "undefined") return null;
|
|
@@ -1502,25 +1502,25 @@ var TRUNCATION_MARKER_HEAD = "... (tool output truncated, ";
|
|
|
1502
1502
|
var TRUNCATION_MARKER_TAIL = " characters omitted)";
|
|
1503
1503
|
var MAX_PERSISTED_TOOL_RESULT_CHARS = 1e5;
|
|
1504
1504
|
function buildToolResultContent(results) {
|
|
1505
|
-
const
|
|
1505
|
+
const entries2 = results.map(
|
|
1506
1506
|
(r) => `Tool "${r.name}" returned: ${JSON.stringify(r.result)}`.replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029")
|
|
1507
1507
|
);
|
|
1508
|
-
const framing = HEADER.length + FOOTER.length + ENTRY_SEPARATOR.length * Math.max(0,
|
|
1509
|
-
const summary = capEntries(
|
|
1508
|
+
const framing = HEADER.length + FOOTER.length + ENTRY_SEPARATOR.length * Math.max(0, entries2.length - 1);
|
|
1509
|
+
const summary = capEntries(entries2, MAX_PERSISTED_TOOL_RESULT_CHARS - framing).join(
|
|
1510
1510
|
ENTRY_SEPARATOR
|
|
1511
1511
|
);
|
|
1512
1512
|
return `${HEADER}${summary}${FOOTER}`;
|
|
1513
1513
|
}
|
|
1514
|
-
function capToolResultEntries(
|
|
1515
|
-
return capEntries(
|
|
1514
|
+
function capToolResultEntries(entries2, budget) {
|
|
1515
|
+
return capEntries(entries2, budget);
|
|
1516
1516
|
}
|
|
1517
|
-
function capEntries(
|
|
1518
|
-
const smallestFirst =
|
|
1519
|
-
const capped = [...
|
|
1517
|
+
function capEntries(entries2, budget) {
|
|
1518
|
+
const smallestFirst = entries2.map((_, index) => index).sort((a, b) => entries2[a].length - entries2[b].length);
|
|
1519
|
+
const capped = [...entries2];
|
|
1520
1520
|
let remaining = budget;
|
|
1521
|
-
let unassigned =
|
|
1521
|
+
let unassigned = entries2.length;
|
|
1522
1522
|
for (const index of smallestFirst) {
|
|
1523
|
-
capped[index] = truncateEntry(
|
|
1523
|
+
capped[index] = truncateEntry(entries2[index], Math.floor(remaining / unassigned));
|
|
1524
1524
|
remaining -= capped[index].length;
|
|
1525
1525
|
unassigned--;
|
|
1526
1526
|
}
|
|
@@ -2408,11 +2408,11 @@ var ToolCallEventIndex = class {
|
|
|
2408
2408
|
this.pending = /* @__PURE__ */ new Map();
|
|
2409
2409
|
this.resetCount = collection.database._resetCount;
|
|
2410
2410
|
collection.experimentalSubscribe((changes) => {
|
|
2411
|
-
for (const { record:
|
|
2411
|
+
for (const { record: record3, type } of changes) {
|
|
2412
2412
|
this.replace(
|
|
2413
|
-
|
|
2414
|
-
type === "destroyed" ? void 0 :
|
|
2415
|
-
type === "destroyed" ? void 0 :
|
|
2413
|
+
record3.id,
|
|
2414
|
+
type === "destroyed" ? void 0 : record3.conversationId,
|
|
2415
|
+
type === "destroyed" ? void 0 : record3._getRaw("tool_call_events")
|
|
2416
2416
|
);
|
|
2417
2417
|
}
|
|
2418
2418
|
});
|
|
@@ -3538,7 +3538,7 @@ async function updateMessageErrorOp(ctx, uniqueId, error) {
|
|
|
3538
3538
|
}
|
|
3539
3539
|
await ctx.database.write(async () => {
|
|
3540
3540
|
await message.update((msg) => {
|
|
3541
|
-
msg._setRaw("error", error);
|
|
3541
|
+
msg._setRaw("error", error ?? "");
|
|
3542
3542
|
});
|
|
3543
3543
|
});
|
|
3544
3544
|
return messageToStored(message, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
@@ -3855,15 +3855,15 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
3855
3855
|
staleSkipped++;
|
|
3856
3856
|
continue;
|
|
3857
3857
|
}
|
|
3858
|
-
const
|
|
3859
|
-
if (!
|
|
3858
|
+
const cached2 = chunkCache?.get(key3.id);
|
|
3859
|
+
if (!cached2 || cached2.version !== key3.version) {
|
|
3860
3860
|
missIds.push(key3.id);
|
|
3861
3861
|
continue;
|
|
3862
3862
|
}
|
|
3863
3863
|
cacheHits++;
|
|
3864
|
-
if (
|
|
3865
|
-
for (let ci = 0; ci <
|
|
3866
|
-
const vec =
|
|
3864
|
+
if (cached2.chunks.length > 0) {
|
|
3865
|
+
for (let ci = 0; ci < cached2.chunks.length; ci++) {
|
|
3866
|
+
const vec = cached2.chunks[ci];
|
|
3867
3867
|
if (vec.length === 0) continue;
|
|
3868
3868
|
const similarity = cosineSimilarity(queryVector, vec);
|
|
3869
3869
|
if (similarity >= minSimilarity) {
|
|
@@ -3876,8 +3876,8 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
3876
3876
|
});
|
|
3877
3877
|
}
|
|
3878
3878
|
}
|
|
3879
|
-
} else if (
|
|
3880
|
-
const similarity = cosineSimilarity(queryVector,
|
|
3879
|
+
} else if (cached2.fallback) {
|
|
3880
|
+
const similarity = cosineSimilarity(queryVector, cached2.fallback);
|
|
3881
3881
|
if (similarity >= minSimilarity) {
|
|
3882
3882
|
candidates.push({
|
|
3883
3883
|
id: key3.id,
|
|
@@ -4690,11 +4690,11 @@ var mergeConfigs = (a, b) => {
|
|
|
4690
4690
|
return config;
|
|
4691
4691
|
};
|
|
4692
4692
|
var headersEntries = (headers) => {
|
|
4693
|
-
const
|
|
4693
|
+
const entries2 = [];
|
|
4694
4694
|
headers.forEach((value, key3) => {
|
|
4695
|
-
|
|
4695
|
+
entries2.push([key3, value]);
|
|
4696
4696
|
});
|
|
4697
|
-
return
|
|
4697
|
+
return entries2;
|
|
4698
4698
|
};
|
|
4699
4699
|
var mergeHeaders = (...headers) => {
|
|
4700
4700
|
const mergedHeaders = new Headers();
|
|
@@ -5169,9 +5169,9 @@ async function embedOne(text16, options, outer) {
|
|
|
5169
5169
|
const { cache } = options;
|
|
5170
5170
|
if (!cache) return Array.from(await requestEmbedding(text16, options, outer));
|
|
5171
5171
|
const model = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
5172
|
-
const
|
|
5173
|
-
const cachedModel =
|
|
5174
|
-
if (
|
|
5172
|
+
const cached2 = cache.get(text16);
|
|
5173
|
+
const cachedModel = cached2 && cachedEmbeddingModels.get(cached2);
|
|
5174
|
+
if (cached2 && (cachedModel === void 0 || cachedModel === model)) return Array.from(cached2);
|
|
5175
5175
|
const inFlight = inFlightByCache.get(cache) ?? /* @__PURE__ */ new Map();
|
|
5176
5176
|
inFlightByCache.set(cache, inFlight);
|
|
5177
5177
|
const requestKey = JSON.stringify([model, text16]);
|
|
@@ -5286,10 +5286,10 @@ async function embedMany(texts, options, outer) {
|
|
|
5286
5286
|
const uncachedTexts = [];
|
|
5287
5287
|
for (let i = 0; i < texts.length; i++) {
|
|
5288
5288
|
if (cache) {
|
|
5289
|
-
const
|
|
5290
|
-
const cachedModel =
|
|
5291
|
-
if (
|
|
5292
|
-
results[i] = Array.from(
|
|
5289
|
+
const cached2 = cache.get(texts[i]);
|
|
5290
|
+
const cachedModel = cached2 && cachedEmbeddingModels.get(cached2);
|
|
5291
|
+
if (cached2 && (cachedModel === void 0 || cachedModel === embeddingModel)) {
|
|
5292
|
+
results[i] = Array.from(cached2);
|
|
5293
5293
|
continue;
|
|
5294
5294
|
}
|
|
5295
5295
|
}
|
|
@@ -5730,58 +5730,337 @@ function parseTopics(value) {
|
|
|
5730
5730
|
return out;
|
|
5731
5731
|
}
|
|
5732
5732
|
|
|
5733
|
+
// src/lib/memory/store/topicCodec.ts
|
|
5734
|
+
var ciphertextPattern = /^enc:v\d+:[0-9a-f]+$/i;
|
|
5735
|
+
var topicHashPattern = /^[0-9a-f]{64}$/;
|
|
5736
|
+
var MAX_SEALED_TOPIC_NAME_BYTES = 1024;
|
|
5737
|
+
function normalizeTopicName(name) {
|
|
5738
|
+
return normalizeEntityName(name).normalize("NFC");
|
|
5739
|
+
}
|
|
5740
|
+
function sealedTopicNamesFit(json5) {
|
|
5741
|
+
return (entries(json5) ?? []).every(
|
|
5742
|
+
(entry) => !hashed(entry) || typeof entry.name !== "string" || entry.name.length <= MAX_SEALED_TOPIC_NAME_BYTES
|
|
5743
|
+
);
|
|
5744
|
+
}
|
|
5745
|
+
function record(value) {
|
|
5746
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5747
|
+
}
|
|
5748
|
+
function hashed(entry) {
|
|
5749
|
+
return record(entry) && typeof entry.name_hash === "string";
|
|
5750
|
+
}
|
|
5751
|
+
function entries(json5) {
|
|
5752
|
+
if (typeof json5 !== "string") return void 0;
|
|
5753
|
+
try {
|
|
5754
|
+
const parsed = JSON.parse(json5);
|
|
5755
|
+
return Array.isArray(parsed) ? parsed : void 0;
|
|
5756
|
+
} catch {
|
|
5757
|
+
return void 0;
|
|
5758
|
+
}
|
|
5759
|
+
}
|
|
5760
|
+
function cached(cache, key3, load) {
|
|
5761
|
+
let pending = cache.get(key3);
|
|
5762
|
+
if (!pending) {
|
|
5763
|
+
const loading = load();
|
|
5764
|
+
pending = loading;
|
|
5765
|
+
cache.set(key3, loading);
|
|
5766
|
+
loading.catch(() => {
|
|
5767
|
+
if (cache.get(key3) === loading) cache.delete(key3);
|
|
5768
|
+
});
|
|
5769
|
+
}
|
|
5770
|
+
return pending;
|
|
5771
|
+
}
|
|
5772
|
+
function createTopicCodec(cipher) {
|
|
5773
|
+
const hashes = /* @__PURE__ */ new Map();
|
|
5774
|
+
const opened = /* @__PURE__ */ new Map();
|
|
5775
|
+
const seals = /* @__PURE__ */ new Map();
|
|
5776
|
+
const legacyNames = /* @__PURE__ */ new Map();
|
|
5777
|
+
const hash = async (name) => {
|
|
5778
|
+
const normalized2 = normalizeTopicName(name);
|
|
5779
|
+
if (!normalized2) return null;
|
|
5780
|
+
return cached(hashes, normalized2, async () => {
|
|
5781
|
+
const digest = await cipher.hashTopic(normalized2);
|
|
5782
|
+
if (!topicHashPattern.test(digest))
|
|
5783
|
+
throw new Error("Topic hashing must return 64 lowercase hex characters");
|
|
5784
|
+
return digest;
|
|
5785
|
+
});
|
|
5786
|
+
};
|
|
5787
|
+
const seal = async (display) => {
|
|
5788
|
+
const nameHash = await hash(display);
|
|
5789
|
+
if (nameHash === null) return null;
|
|
5790
|
+
return cached(seals, display, async () => {
|
|
5791
|
+
const name = await cipher.encrypt(display);
|
|
5792
|
+
if (name === display || !ciphertextPattern.test(name))
|
|
5793
|
+
throw new Error(
|
|
5794
|
+
"Topic encryption must return SDK ciphertext; refusing to upload plaintext"
|
|
5795
|
+
);
|
|
5796
|
+
opened.set(name, Promise.resolve(display));
|
|
5797
|
+
return { name_hash: nameHash, name };
|
|
5798
|
+
});
|
|
5799
|
+
};
|
|
5800
|
+
const plain2 = (name) => {
|
|
5801
|
+
if (!ciphertextPattern.test(name)) return Promise.resolve(name);
|
|
5802
|
+
let pending = legacyNames.get(name);
|
|
5803
|
+
if (!pending) {
|
|
5804
|
+
pending = cipher.decrypt(name).catch(() => name);
|
|
5805
|
+
legacyNames.set(name, pending);
|
|
5806
|
+
}
|
|
5807
|
+
return pending;
|
|
5808
|
+
};
|
|
5809
|
+
const open = async ({ name, name_hash: nameHash }) => {
|
|
5810
|
+
if (nameHash === void 0) return plain2(name);
|
|
5811
|
+
if (typeof name !== "string" || typeof nameHash !== "string" || !topicHashPattern.test(nameHash) || !ciphertextPattern.test(name))
|
|
5812
|
+
throw new Error("Nearby returned a malformed topic name");
|
|
5813
|
+
const plaintext = await cached(opened, name, async () => {
|
|
5814
|
+
const value = await cipher.decrypt(name);
|
|
5815
|
+
if (value === name) throw new Error("Topic decryption failed");
|
|
5816
|
+
return value;
|
|
5817
|
+
});
|
|
5818
|
+
if (await hash(plaintext) !== nameHash) throw new Error("Topic name does not match its hash");
|
|
5819
|
+
if (!seals.has(plaintext)) seals.set(plaintext, Promise.resolve({ name_hash: nameHash, name }));
|
|
5820
|
+
return plaintext;
|
|
5821
|
+
};
|
|
5822
|
+
return {
|
|
5823
|
+
hash,
|
|
5824
|
+
seal,
|
|
5825
|
+
open,
|
|
5826
|
+
encodeTopics: async (json5) => {
|
|
5827
|
+
const list = entries(json5);
|
|
5828
|
+
if (!list) return json5;
|
|
5829
|
+
const sealed2 = await Promise.all(
|
|
5830
|
+
list.map(async (entry) => {
|
|
5831
|
+
if (!record(entry) || typeof entry.name !== "string") return null;
|
|
5832
|
+
const name = await seal(await plain2(entry.name));
|
|
5833
|
+
return name && { ...entry, name: name.name, name_hash: name.name_hash };
|
|
5834
|
+
})
|
|
5835
|
+
);
|
|
5836
|
+
return JSON.stringify(sealed2.filter((entry) => entry !== null));
|
|
5837
|
+
},
|
|
5838
|
+
decodeTopics: async (json5) => {
|
|
5839
|
+
const list = entries(json5);
|
|
5840
|
+
if (!list?.some(
|
|
5841
|
+
(entry) => hashed(entry) || record(entry) && typeof entry.name === "string" && ciphertextPattern.test(entry.name)
|
|
5842
|
+
))
|
|
5843
|
+
return json5;
|
|
5844
|
+
const decoded = await Promise.all(
|
|
5845
|
+
list.map(async (entry) => {
|
|
5846
|
+
if (!hashed(entry))
|
|
5847
|
+
return record(entry) && typeof entry.name === "string" ? { ...entry, name: await plain2(entry.name) } : entry;
|
|
5848
|
+
const { name_hash: nameHash, ...rest } = entry;
|
|
5849
|
+
return { ...rest, name: await open({ name: entry.name, name_hash: nameHash }) };
|
|
5850
|
+
})
|
|
5851
|
+
);
|
|
5852
|
+
return JSON.stringify(decoded);
|
|
5853
|
+
},
|
|
5854
|
+
isLegacy: (json5) => (entries(json5) ?? []).some(
|
|
5855
|
+
(entry) => record(entry) && typeof entry.name === "string" && !hashed(entry)
|
|
5856
|
+
),
|
|
5857
|
+
matchesLegacy: async (json5, names, hashes2) => {
|
|
5858
|
+
const list = typeof json5 === "string" ? entries(json5) ?? [] : [];
|
|
5859
|
+
if (list.some((entry) => hashed(entry) && hashes2.has(entry.name_hash))) return false;
|
|
5860
|
+
const legacy = await Promise.all(
|
|
5861
|
+
list.map(
|
|
5862
|
+
async (entry) => record(entry) && typeof entry.name === "string" && !hashed(entry) ? normalizeTopicName(await plain2(entry.name)) : null
|
|
5863
|
+
)
|
|
5864
|
+
);
|
|
5865
|
+
return legacy.some((name) => name !== null && names.has(name));
|
|
5866
|
+
},
|
|
5867
|
+
encodeCatalog: async (topic2) => {
|
|
5868
|
+
const sealed2 = await seal(normalizeTopicName(await plain2(topic2.name)));
|
|
5869
|
+
return sealed2 && { ...topic2, name: sealed2.name, name_hash: sealed2.name_hash };
|
|
5870
|
+
},
|
|
5871
|
+
decodeCatalog: async (item) => {
|
|
5872
|
+
const { name_hash: nameHash, ...rest } = item;
|
|
5873
|
+
return { ...rest, name: await open({ name: item.name, name_hash: nameHash }) };
|
|
5874
|
+
}
|
|
5875
|
+
};
|
|
5876
|
+
}
|
|
5877
|
+
|
|
5733
5878
|
// src/lib/memory/store/remoteTopics.ts
|
|
5879
|
+
var RETIRE_CONCURRENCY = 8;
|
|
5734
5880
|
function topic(value) {
|
|
5735
5881
|
const t = value;
|
|
5736
|
-
if (!t || typeof t.name !== "string" || !t.name || !Number.isSafeInteger(t.version) || t.version < 1 || typeof t.is_deleted !== "boolean" || typeof t.server_updated_at !== "string" || t.kind !== void 0 && typeof t.kind !== "string")
|
|
5882
|
+
if (!t || typeof t.name !== "string" || !t.name || t.name_hash !== void 0 && typeof t.name_hash !== "string" || !Number.isSafeInteger(t.version) || t.version < 1 || typeof t.is_deleted !== "boolean" || typeof t.server_updated_at !== "string" || t.kind !== void 0 && typeof t.kind !== "string")
|
|
5737
5883
|
throw new Error("Invalid nearby topic");
|
|
5738
5884
|
return t;
|
|
5739
5885
|
}
|
|
5740
|
-
function
|
|
5886
|
+
async function wireTopics(request, signal) {
|
|
5887
|
+
const out = [];
|
|
5888
|
+
let cursor;
|
|
5889
|
+
do {
|
|
5890
|
+
const page = await request(
|
|
5891
|
+
"/topics?limit=200" + (cursor ? `&cursor=${encodeURIComponent(cursor)}` : ""),
|
|
5892
|
+
{},
|
|
5893
|
+
signal
|
|
5894
|
+
);
|
|
5895
|
+
if (!Array.isArray(page.items) || page.next_cursor !== void 0 && typeof page.next_cursor !== "string")
|
|
5896
|
+
throw new Error("Invalid nearby topic page");
|
|
5897
|
+
out.push(...page.items.map(topic));
|
|
5898
|
+
cursor = page.next_cursor;
|
|
5899
|
+
} while (cursor);
|
|
5900
|
+
return out;
|
|
5901
|
+
}
|
|
5902
|
+
function hashesOf(items) {
|
|
5903
|
+
return new Set(items.flatMap((t) => t.name_hash === void 0 ? [] : [t.name_hash]));
|
|
5904
|
+
}
|
|
5905
|
+
async function sealedImport(request, codec, topics, signal) {
|
|
5906
|
+
let oversized = 0;
|
|
5907
|
+
for (let i = 0; i < topics.length; i += 50) {
|
|
5908
|
+
signal?.throwIfAborted();
|
|
5909
|
+
const sealed2 = (await Promise.all(topics.slice(i, i + 50).map((t) => codec.encodeCatalog(t)))).filter((t) => {
|
|
5910
|
+
if (t === null) return false;
|
|
5911
|
+
if (t.name.length <= MAX_SEALED_TOPIC_NAME_BYTES) return true;
|
|
5912
|
+
oversized++;
|
|
5913
|
+
return false;
|
|
5914
|
+
});
|
|
5915
|
+
if (sealed2.length)
|
|
5916
|
+
await request(
|
|
5917
|
+
"/topics/import",
|
|
5918
|
+
{ method: "POST", body: JSON.stringify({ topics: sealed2 }) },
|
|
5919
|
+
signal
|
|
5920
|
+
);
|
|
5921
|
+
}
|
|
5922
|
+
signal?.throwIfAborted();
|
|
5923
|
+
if (oversized)
|
|
5924
|
+
getLogger().warn(
|
|
5925
|
+
`[memory/remote] Skipped ${oversized} topic catalog entries whose sealed name exceeds ${MAX_SEALED_TOPIC_NAME_BYTES} bytes`
|
|
5926
|
+
);
|
|
5927
|
+
}
|
|
5928
|
+
function createRemoteTopicPersistence(request, codec) {
|
|
5929
|
+
let legacyOnly = /* @__PURE__ */ new Set();
|
|
5741
5930
|
return {
|
|
5742
5931
|
topics: async () => {
|
|
5743
|
-
const
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5932
|
+
const items = await wireTopics(request);
|
|
5933
|
+
const hashed2 = hashesOf(items);
|
|
5934
|
+
const legacy = /* @__PURE__ */ new Set();
|
|
5935
|
+
const decoded = await Promise.all(
|
|
5936
|
+
items.map(async (item) => {
|
|
5937
|
+
const plain2 = await codec.decodeCatalog(item);
|
|
5938
|
+
const name = normalizeTopicName(plain2.name);
|
|
5939
|
+
if (item.name_hash === void 0) {
|
|
5940
|
+
const hash = await codec.hash(name);
|
|
5941
|
+
if (hash !== null && hashed2.has(hash)) return null;
|
|
5942
|
+
legacy.add(name);
|
|
5943
|
+
}
|
|
5944
|
+
return { ...plain2, name };
|
|
5945
|
+
})
|
|
5946
|
+
);
|
|
5947
|
+
legacyOnly = legacy;
|
|
5948
|
+
return decoded.filter((t) => t !== null);
|
|
5756
5949
|
},
|
|
5757
5950
|
putTopic: async (value, expectedVersion) => {
|
|
5758
5951
|
if (!Number.isSafeInteger(expectedVersion) || expectedVersion < 0)
|
|
5759
5952
|
throw new Error("Expected topic version must be a nonnegative integer");
|
|
5760
|
-
|
|
5953
|
+
const sealed2 = await codec.encodeCatalog(value);
|
|
5954
|
+
if (!sealed2) throw new Error("Topic name must not be empty");
|
|
5955
|
+
const saved = topic(
|
|
5761
5956
|
await request("/topics", {
|
|
5762
5957
|
method: "PUT",
|
|
5763
|
-
body: JSON.stringify({
|
|
5958
|
+
body: JSON.stringify({
|
|
5959
|
+
topic: sealed2,
|
|
5960
|
+
expected_version: legacyOnly.has(normalizeTopicName(value.name)) ? 0 : expectedVersion
|
|
5961
|
+
})
|
|
5764
5962
|
})
|
|
5765
5963
|
);
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5964
|
+
const decoded = await codec.decodeCatalog(saved);
|
|
5965
|
+
legacyOnly.delete(decoded.name);
|
|
5966
|
+
return decoded;
|
|
5967
|
+
},
|
|
5968
|
+
importTopics: (topics, signal) => sealedImport(
|
|
5969
|
+
request,
|
|
5970
|
+
codec,
|
|
5971
|
+
topics.map(({ name, kind }) => ({ name, ...kind !== void 0 && { kind } })),
|
|
5972
|
+
signal
|
|
5973
|
+
)
|
|
5974
|
+
};
|
|
5975
|
+
}
|
|
5976
|
+
async function retireLegacyTopics(request, codec, topics, imported, signal) {
|
|
5977
|
+
const failures = [];
|
|
5978
|
+
const put = async (topic2, expectedVersion) => {
|
|
5979
|
+
try {
|
|
5980
|
+
await request(
|
|
5981
|
+
"/topics",
|
|
5982
|
+
{ method: "PUT", body: JSON.stringify({ topic: topic2, expected_version: expectedVersion }) },
|
|
5983
|
+
signal
|
|
5984
|
+
);
|
|
5985
|
+
return "saved";
|
|
5986
|
+
} catch (error) {
|
|
5987
|
+
if (signal?.aborted) throw error;
|
|
5988
|
+
if (error instanceof RemoteMemoryError && error.status === 409) return "conflict";
|
|
5989
|
+
failures.push(error);
|
|
5990
|
+
return "failed";
|
|
5991
|
+
}
|
|
5992
|
+
};
|
|
5993
|
+
const retire = (item) => put(
|
|
5994
|
+
{ name: item.name, ...item.kind !== void 0 && { kind: item.kind }, is_deleted: true },
|
|
5995
|
+
item.version
|
|
5996
|
+
);
|
|
5997
|
+
const changed = [];
|
|
5998
|
+
let next = 0;
|
|
5999
|
+
const worker = async () => {
|
|
6000
|
+
while (next < topics.length) {
|
|
5779
6001
|
signal?.throwIfAborted();
|
|
6002
|
+
const item = topics[next++];
|
|
6003
|
+
if (await retire(item) === "conflict") changed.push(item);
|
|
5780
6004
|
}
|
|
5781
6005
|
};
|
|
6006
|
+
await Promise.all(
|
|
6007
|
+
Array.from({ length: Math.min(RETIRE_CONCURRENCY, topics.length) }, () => worker())
|
|
6008
|
+
);
|
|
6009
|
+
if (changed.length) {
|
|
6010
|
+
const current = await wireTopics(request, signal);
|
|
6011
|
+
for (const stale of changed) {
|
|
6012
|
+
const legacy = current.find((t) => t.name_hash === void 0 && t.name === stale.name);
|
|
6013
|
+
if (!legacy || legacy.is_deleted) continue;
|
|
6014
|
+
const hash = await codec.hash(await codec.open(legacy));
|
|
6015
|
+
const copy = current.find((t) => t.name_hash !== void 0 && t.name_hash === hash);
|
|
6016
|
+
if (!copy || hash === null) continue;
|
|
6017
|
+
const newer = imported.has(hash) || Date.parse(legacy.server_updated_at) > Date.parse(copy.server_updated_at);
|
|
6018
|
+
if (newer && (copy.is_deleted || legacy.kind !== copy.kind)) {
|
|
6019
|
+
const sealed2 = await codec.encodeCatalog({
|
|
6020
|
+
name: legacy.name,
|
|
6021
|
+
...legacy.kind !== void 0 && { kind: legacy.kind },
|
|
6022
|
+
is_deleted: false
|
|
6023
|
+
});
|
|
6024
|
+
if (!sealed2 || await put(sealed2, copy.version) !== "saved") continue;
|
|
6025
|
+
}
|
|
6026
|
+
await retire(legacy);
|
|
6027
|
+
}
|
|
6028
|
+
}
|
|
6029
|
+
if (failures.length)
|
|
6030
|
+
getLogger().warn(
|
|
6031
|
+
`[memory/remote] Could not retire ${failures.length} upgraded topic catalog entries:`,
|
|
6032
|
+
failures[0]
|
|
6033
|
+
);
|
|
6034
|
+
}
|
|
6035
|
+
async function upgradeLegacyTopicCatalog(request, codec, signal) {
|
|
6036
|
+
const items = await wireTopics(request, signal);
|
|
6037
|
+
const hashed2 = hashesOf(items);
|
|
6038
|
+
const hashes = await Promise.all(
|
|
6039
|
+
items.map(
|
|
6040
|
+
async (item) => item.name_hash === void 0 ? codec.hash(await codec.open(item)) : null
|
|
6041
|
+
)
|
|
6042
|
+
);
|
|
6043
|
+
const sources = /* @__PURE__ */ new Map();
|
|
6044
|
+
const live2 = [];
|
|
6045
|
+
items.forEach((item, i) => {
|
|
6046
|
+
const hash = hashes[i];
|
|
6047
|
+
if (hash === null) return;
|
|
6048
|
+
if (!item.is_deleted) live2.push(item);
|
|
6049
|
+
if (hashed2.has(hash)) return;
|
|
6050
|
+
const source = sources.get(hash);
|
|
6051
|
+
if (!source || source.is_deleted && !item.is_deleted) sources.set(hash, item);
|
|
6052
|
+
});
|
|
6053
|
+
const legacy = [...sources.values()].map((item) => ({
|
|
6054
|
+
name: item.name,
|
|
6055
|
+
...item.kind !== void 0 && { kind: item.kind },
|
|
6056
|
+
...item.is_deleted && { is_deleted: true }
|
|
6057
|
+
}));
|
|
6058
|
+
await sealedImport(request, codec, legacy, signal);
|
|
6059
|
+
await retireLegacyTopics(request, codec, live2, new Set(sources.keys()), signal);
|
|
6060
|
+
return legacy.length;
|
|
5782
6061
|
}
|
|
5783
6062
|
async function createRemoteTopic(persistence, name) {
|
|
5784
|
-
const canonical =
|
|
6063
|
+
const canonical = normalizeTopicName(name);
|
|
5785
6064
|
if (!canonical) return null;
|
|
5786
6065
|
const existing = (await persistence.topics()).find((t) => t.name === canonical);
|
|
5787
6066
|
if (existing && !existing.is_deleted) return canonical;
|
|
@@ -5869,7 +6148,10 @@ var RemoteMemoryError = class extends Error {
|
|
|
5869
6148
|
this.name = "RemoteMemoryError";
|
|
5870
6149
|
}
|
|
5871
6150
|
};
|
|
5872
|
-
var
|
|
6151
|
+
var TOPIC_UPGRADE_PROCESSOR = "topic-hash-v1";
|
|
6152
|
+
var TOPIC_UPGRADE_PAGE = 50;
|
|
6153
|
+
var LEGACY_TOPIC_CURSOR = "legacy-topics:";
|
|
6154
|
+
var LEGACY_TOPIC_RECHECK_MS = 6e4;
|
|
5873
6155
|
var memoryFields = {
|
|
5874
6156
|
memory_id: true,
|
|
5875
6157
|
content: true,
|
|
@@ -5929,7 +6211,8 @@ var queryFields = [
|
|
|
5929
6211
|
"fact_types",
|
|
5930
6212
|
"visibility",
|
|
5931
6213
|
"memory_ids",
|
|
5932
|
-
"
|
|
6214
|
+
"topic_hashes",
|
|
6215
|
+
"topics_legacy",
|
|
5933
6216
|
"updated_after",
|
|
5934
6217
|
"topics_due",
|
|
5935
6218
|
"topics_extracted",
|
|
@@ -5939,11 +6222,17 @@ var queryFields = [
|
|
|
5939
6222
|
"limit",
|
|
5940
6223
|
"include_embeddings"
|
|
5941
6224
|
];
|
|
5942
|
-
function
|
|
6225
|
+
function isVersionConflict(error) {
|
|
6226
|
+
return error instanceof RemoteMemoryError && error.code === "version_conflict";
|
|
6227
|
+
}
|
|
6228
|
+
function isRejectedRow(error) {
|
|
6229
|
+
return error instanceof RemoteMemoryError && error.status === 400;
|
|
6230
|
+
}
|
|
6231
|
+
function record2(value) {
|
|
5943
6232
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5944
6233
|
}
|
|
5945
6234
|
function memoryRecord(value) {
|
|
5946
|
-
if (!
|
|
6235
|
+
if (!record2(value) || !record2(value.memory) || typeof value.memory.memory_id !== "string" || typeof value.memory.content !== "string" || typeof value.memory.scope !== "string" || typeof value.memory.created_at !== "number" || typeof value.memory.updated_at !== "number" || typeof value.memory.is_deleted !== "boolean" || !Number.isSafeInteger(value.version) || value.version < 1 || typeof value.server_updated_at !== "string" || value.score !== void 0 && (typeof value.score !== "number" || !Number.isFinite(value.score))) {
|
|
5947
6236
|
throw new Error("Invalid nearby private-memory response");
|
|
5948
6237
|
}
|
|
5949
6238
|
return value;
|
|
@@ -6023,14 +6312,14 @@ function createNearbyRequest(options, apiPath = "/api/private-memories") {
|
|
|
6023
6312
|
const body = await response.json().catch(() => null);
|
|
6024
6313
|
const retryAfter = parseRetryAfterMs(response.headers.get("Retry-After"));
|
|
6025
6314
|
const error = new RemoteMemoryError(
|
|
6026
|
-
|
|
6315
|
+
record2(body) && typeof body.detail === "string" ? body.detail : `Nearby request failed (${response.status})`,
|
|
6027
6316
|
response.status,
|
|
6028
|
-
|
|
6317
|
+
record2(body) && typeof body.code === "string" ? body.code : void 0,
|
|
6029
6318
|
retryAfter ?? void 0,
|
|
6030
|
-
|
|
6319
|
+
record2(body) && typeof body.rate_limit_bucket === "string" ? body.rate_limit_bucket : void 0
|
|
6031
6320
|
);
|
|
6032
6321
|
if (response.status === 429 && retryAfter !== null && retryAfter > 0 && (!error.code || error.code === "rate_limited")) {
|
|
6033
|
-
const bucket = error.rateLimitBucket && budgets.includes(error.rateLimitBucket) ? error.rateLimitBucket :
|
|
6322
|
+
const bucket = error.rateLimitBucket && budgets.includes(error.rateLimitBucket) ? error.rateLimitBucket : record2(body) && (body.limit_scope === "account" || body.limit_scope === "ip") && !error.rateLimitBucket ? "*" : route;
|
|
6034
6323
|
cooldowns.set(bucket, { until: Date.now() + retryAfter, error });
|
|
6035
6324
|
}
|
|
6036
6325
|
throw error;
|
|
@@ -6053,7 +6342,7 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
6053
6342
|
throw new Error("A canonical keyId is required");
|
|
6054
6343
|
const request = createNearbyRequest(options);
|
|
6055
6344
|
const account = await request("/account", {}, options.signal);
|
|
6056
|
-
if (!
|
|
6345
|
+
if (!record2(account) || account.state !== "active") {
|
|
6057
6346
|
throw new RemoteMemoryError(
|
|
6058
6347
|
"Complete and verify migration before using remote memories",
|
|
6059
6348
|
409,
|
|
@@ -6067,6 +6356,25 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
6067
6356
|
"key_mismatch"
|
|
6068
6357
|
);
|
|
6069
6358
|
}
|
|
6359
|
+
const codec = createTopicCodec(options);
|
|
6360
|
+
let legacyTopicRows = typeof account.legacy_topic_memories === "number" && account.legacy_topic_memories > 0;
|
|
6361
|
+
if (typeof account.legacy_topic_catalog === "number" && account.legacy_topic_catalog > 0)
|
|
6362
|
+
void upgradeLegacyTopicCatalog(request, codec, options.signal).catch((error) => {
|
|
6363
|
+
if (!options.signal?.aborted)
|
|
6364
|
+
getLogger().warn("[memory/remote] Topic catalog upgrade failed:", error);
|
|
6365
|
+
});
|
|
6366
|
+
let legacyCheckedAt = Date.now();
|
|
6367
|
+
let legacyCheck;
|
|
6368
|
+
const recheckLegacyTopicRows = () => {
|
|
6369
|
+
if (legacyCheck || Date.now() - legacyCheckedAt < LEGACY_TOPIC_RECHECK_MS) return;
|
|
6370
|
+
legacyCheckedAt = Date.now();
|
|
6371
|
+
legacyCheck = request("/account", {}, options.signal).then((current) => {
|
|
6372
|
+
if (record2(current) && current.legacy_topic_memories === 0) legacyTopicRows = false;
|
|
6373
|
+
}).catch(() => {
|
|
6374
|
+
}).finally(() => {
|
|
6375
|
+
legacyCheck = void 0;
|
|
6376
|
+
});
|
|
6377
|
+
};
|
|
6070
6378
|
const snapshots = /* @__PURE__ */ new WeakMap();
|
|
6071
6379
|
const decode = async (value) => {
|
|
6072
6380
|
const item = memoryRecord(value);
|
|
@@ -6084,6 +6392,9 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
6084
6392
|
content: item.memory.is_deleted && item.memory.content === "" ? "" : await decrypt(item.memory.content),
|
|
6085
6393
|
...item.memory.kind_value !== void 0 && {
|
|
6086
6394
|
kind_value: await decrypt(item.memory.kind_value)
|
|
6395
|
+
},
|
|
6396
|
+
...item.memory.topics !== void 0 && {
|
|
6397
|
+
topics: await codec.decodeTopics(item.memory.topics)
|
|
6087
6398
|
}
|
|
6088
6399
|
}
|
|
6089
6400
|
};
|
|
@@ -6095,8 +6406,10 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
6095
6406
|
version: item.version,
|
|
6096
6407
|
content: decoded.memory.content,
|
|
6097
6408
|
kindValue: decoded.memory.kind_value,
|
|
6409
|
+
topics: decoded.memory.topics,
|
|
6098
6410
|
encryptedContent: item.memory.content,
|
|
6099
|
-
encryptedKindValue: item.memory.kind_value
|
|
6411
|
+
encryptedKindValue: item.memory.kind_value,
|
|
6412
|
+
encryptedTopics: item.memory.topics
|
|
6100
6413
|
});
|
|
6101
6414
|
return decoded;
|
|
6102
6415
|
};
|
|
@@ -6118,7 +6431,7 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
6118
6431
|
};
|
|
6119
6432
|
const decodeCommitted = async (value, write) => {
|
|
6120
6433
|
const item = memoryRecord(value);
|
|
6121
|
-
if (item.memory.memory_id !== write.body.memory.memory_id || item.memory.content !== write.body.memory.content || item.memory.kind_value !== write.body.memory.kind_value)
|
|
6434
|
+
if (item.memory.memory_id !== write.body.memory.memory_id || item.memory.content !== write.body.memory.content || item.memory.kind_value !== write.body.memory.kind_value || item.memory.topics !== write.body.memory.topics)
|
|
6122
6435
|
return decode(item);
|
|
6123
6436
|
return remember(
|
|
6124
6437
|
{
|
|
@@ -6126,7 +6439,8 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
6126
6439
|
memory: {
|
|
6127
6440
|
...item.memory,
|
|
6128
6441
|
content: write.content,
|
|
6129
|
-
...write.kindValue !== void 0 && { kind_value: write.kindValue }
|
|
6442
|
+
...write.kindValue !== void 0 && { kind_value: write.kindValue },
|
|
6443
|
+
...write.topics !== void 0 && { topics: write.topics }
|
|
6130
6444
|
}
|
|
6131
6445
|
},
|
|
6132
6446
|
item
|
|
@@ -6178,13 +6492,21 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
6178
6492
|
const reusableContent = snapshot?.encryptedContent ?? existing?.memory.content;
|
|
6179
6493
|
const content = reusableContent && (snapshot?.content ?? decoded?.memory.content) === memory.content ? reusableContent : await encryptField2(memory.content);
|
|
6180
6494
|
const kindValue = memory.kind_value === void 0 ? void 0 : (snapshot?.kindValue ?? decoded?.memory.kind_value) === memory.kind_value ? snapshot?.encryptedKindValue ?? existing.memory.kind_value : await encryptField2(memory.kind_value);
|
|
6495
|
+
const wireTopics2 = snapshot ? snapshot.encryptedTopics : existing?.memory.topics;
|
|
6496
|
+
const topics = memory.topics === void 0 ? void 0 : (snapshot?.topics ?? decoded?.memory.topics) === memory.topics && wireTopics2 !== void 0 && !codec.isLegacy(wireTopics2) ? wireTopics2 : await codec.encodeTopics(memory.topics);
|
|
6181
6497
|
return {
|
|
6182
6498
|
body: {
|
|
6183
6499
|
expected_version: expectedVersion,
|
|
6184
|
-
memory: {
|
|
6500
|
+
memory: {
|
|
6501
|
+
...memory,
|
|
6502
|
+
content,
|
|
6503
|
+
...kindValue !== void 0 && { kind_value: kindValue },
|
|
6504
|
+
...topics !== void 0 && { topics }
|
|
6505
|
+
}
|
|
6185
6506
|
},
|
|
6186
6507
|
content: memory.content,
|
|
6187
|
-
kindValue: memory.kind_value
|
|
6508
|
+
kindValue: memory.kind_value,
|
|
6509
|
+
topics: memory.topics
|
|
6188
6510
|
};
|
|
6189
6511
|
};
|
|
6190
6512
|
const fetchCandidates = async (embedding2, candidateOptions, withCounts) => {
|
|
@@ -6233,32 +6555,72 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
6233
6555
|
},
|
|
6234
6556
|
candidateOptions.signal
|
|
6235
6557
|
);
|
|
6236
|
-
if (!
|
|
6558
|
+
if (!record2(result) || !Array.isArray(result.items))
|
|
6237
6559
|
throw new Error("Invalid nearby candidate response");
|
|
6238
6560
|
return result;
|
|
6239
6561
|
};
|
|
6240
6562
|
const fetchQueryPage = async (queryOptions) => {
|
|
6241
|
-
const { signal, ...
|
|
6242
|
-
if (
|
|
6563
|
+
const { signal, topics: names, ...wire2 } = queryOptions;
|
|
6564
|
+
if (wire2.limit !== void 0 && (!Number.isInteger(wire2.limit) || wire2.limit < 1 || wire2.limit > 200))
|
|
6243
6565
|
throw new Error("Page limit must be 1\u2013200");
|
|
6244
6566
|
for (const [key3, max] of queryListLimits) {
|
|
6245
|
-
const values =
|
|
6567
|
+
const values = queryOptions[key3];
|
|
6246
6568
|
if (values && values.length > max)
|
|
6247
6569
|
throw new Error(`Query ${key3} accepts at most ${max} entries (got ${values.length})`);
|
|
6248
6570
|
}
|
|
6571
|
+
const body = wire2;
|
|
6572
|
+
if (names === void 0) return postQuery(body, signal);
|
|
6573
|
+
const hashes = [
|
|
6574
|
+
...new Set(
|
|
6575
|
+
(await Promise.all(names.map((name) => codec.hash(name)))).filter((h) => h !== null)
|
|
6576
|
+
)
|
|
6577
|
+
];
|
|
6578
|
+
if (names.length > 0 && hashes.length === 0) return { items: [] };
|
|
6579
|
+
if (hashes.length > 0 && wire2.cursor?.startsWith(LEGACY_TOPIC_CURSOR)) {
|
|
6580
|
+
const page2 = await postQuery(
|
|
6581
|
+
{
|
|
6582
|
+
...wire2,
|
|
6583
|
+
cursor: wire2.cursor.slice(LEGACY_TOPIC_CURSOR.length) || void 0,
|
|
6584
|
+
topics_legacy: true
|
|
6585
|
+
},
|
|
6586
|
+
signal
|
|
6587
|
+
);
|
|
6588
|
+
const wanted = new Set(names.map(normalizeTopicName));
|
|
6589
|
+
const hashed2 = new Set(hashes);
|
|
6590
|
+
const matches = await Promise.all(
|
|
6591
|
+
page2.items.map(
|
|
6592
|
+
(item) => codec.matchesLegacy(
|
|
6593
|
+
record2(item) && record2(item.memory) ? item.memory.topics : void 0,
|
|
6594
|
+
wanted,
|
|
6595
|
+
hashed2
|
|
6596
|
+
)
|
|
6597
|
+
)
|
|
6598
|
+
);
|
|
6599
|
+
return {
|
|
6600
|
+
...page2,
|
|
6601
|
+
items: page2.items.filter((_, i) => matches[i]),
|
|
6602
|
+
next_cursor: page2.next_cursor === void 0 ? void 0 : LEGACY_TOPIC_CURSOR + page2.next_cursor
|
|
6603
|
+
};
|
|
6604
|
+
}
|
|
6605
|
+
const page = await postQuery({ ...body, topic_hashes: hashes }, signal);
|
|
6606
|
+
if (hashes.length === 0 || page.next_cursor !== void 0 || !legacyTopicRows) return page;
|
|
6607
|
+
recheckLegacyTopicRows();
|
|
6608
|
+
return { ...page, next_cursor: LEGACY_TOPIC_CURSOR };
|
|
6609
|
+
};
|
|
6610
|
+
const postQuery = async (body, signal) => {
|
|
6249
6611
|
const page = await request(
|
|
6250
6612
|
"/memories/query",
|
|
6251
6613
|
{
|
|
6252
6614
|
method: "POST",
|
|
6253
6615
|
body: JSON.stringify(
|
|
6254
6616
|
Object.fromEntries(
|
|
6255
|
-
queryFields.filter((key3) =>
|
|
6617
|
+
queryFields.filter((key3) => body[key3] !== void 0).map((key3) => [key3, body[key3]])
|
|
6256
6618
|
)
|
|
6257
6619
|
)
|
|
6258
6620
|
},
|
|
6259
6621
|
signal
|
|
6260
6622
|
);
|
|
6261
|
-
if (!
|
|
6623
|
+
if (!record2(page) || !Array.isArray(page.items) || page.next_cursor !== void 0 && typeof page.next_cursor !== "string" || page.changes_cursor !== void 0 && typeof page.changes_cursor !== "string")
|
|
6262
6624
|
throw new Error("Invalid nearby private-memory page");
|
|
6263
6625
|
return page;
|
|
6264
6626
|
};
|
|
@@ -6272,13 +6634,13 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
6272
6634
|
unavailable_count: result.unavailable_count
|
|
6273
6635
|
};
|
|
6274
6636
|
};
|
|
6275
|
-
|
|
6276
|
-
...createRemoteTopicPersistence(request),
|
|
6637
|
+
const persistence = {
|
|
6638
|
+
...createRemoteTopicPersistence(request, codec),
|
|
6277
6639
|
...createRemoteWorkPersistence(request),
|
|
6278
6640
|
supportsRealtimeChanges: account.realtime_changes === true,
|
|
6279
6641
|
counts: async () => {
|
|
6280
6642
|
const result = await request("/counts", {});
|
|
6281
|
-
if (!
|
|
6643
|
+
if (!record2(result) || ["live", "archived", "quarantined"].some(
|
|
6282
6644
|
(key3) => !Number.isSafeInteger(result[key3]) || result[key3] < 0
|
|
6283
6645
|
))
|
|
6284
6646
|
throw new Error("Invalid nearby memory counts");
|
|
@@ -6295,8 +6657,8 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
6295
6657
|
method: "POST",
|
|
6296
6658
|
body: JSON.stringify({ ...window2, limit })
|
|
6297
6659
|
});
|
|
6298
|
-
if (!
|
|
6299
|
-
(item) => !
|
|
6660
|
+
if (!record2(result) || !Array.isArray(result.items) || result.items.some(
|
|
6661
|
+
(item) => !record2(item) || typeof item.memory_id !== "string" || !item.memory_id || typeof item.score !== "number" || !Number.isFinite(item.score) || item.score <= 0 || item.score > 1
|
|
6300
6662
|
))
|
|
6301
6663
|
throw new Error("Invalid nearby temporal candidates");
|
|
6302
6664
|
return result.items.map((item) => item.memory_id);
|
|
@@ -6327,7 +6689,7 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
6327
6689
|
if (query[key3] !== void 0) params.set(key3, String(query[key3]));
|
|
6328
6690
|
}
|
|
6329
6691
|
const page = await request("/memories?" + params.toString(), {}, signal);
|
|
6330
|
-
if (!
|
|
6692
|
+
if (!record2(page) || !Array.isArray(page.items) || page.next_cursor !== void 0 && typeof page.next_cursor !== "string") {
|
|
6331
6693
|
throw new Error("Invalid nearby private-memory page");
|
|
6332
6694
|
}
|
|
6333
6695
|
return {
|
|
@@ -6367,7 +6729,7 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
6367
6729
|
},
|
|
6368
6730
|
signal
|
|
6369
6731
|
);
|
|
6370
|
-
if (!
|
|
6732
|
+
if (!record2(result) || !Array.isArray(result.items) || result.items.length !== prepared.length)
|
|
6371
6733
|
throw new Error("Invalid nearby batch response");
|
|
6372
6734
|
return Promise.all(result.items.map((item, i) => decodeCommitted(item, prepared[i])));
|
|
6373
6735
|
},
|
|
@@ -6382,20 +6744,87 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
6382
6744
|
queryMetadata: async (queryOptions = {}) => {
|
|
6383
6745
|
const page = await fetchQueryPage(queryOptions);
|
|
6384
6746
|
return {
|
|
6385
|
-
items:
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
|
|
6392
|
-
|
|
6747
|
+
items: await Promise.all(
|
|
6748
|
+
page.items.map(async (item) => {
|
|
6749
|
+
const {
|
|
6750
|
+
memory: { content: _content, kind_value: _kindValue, topics, ...memory },
|
|
6751
|
+
version,
|
|
6752
|
+
server_updated_at
|
|
6753
|
+
} = memoryRecord(item);
|
|
6754
|
+
const plain2 = topics === void 0 ? void 0 : await codec.decodeTopics(topics).catch(() => null);
|
|
6755
|
+
return {
|
|
6756
|
+
memory: { ...memory, ...typeof plain2 === "string" && { topics: plain2 } },
|
|
6757
|
+
version,
|
|
6758
|
+
server_updated_at
|
|
6759
|
+
};
|
|
6760
|
+
})
|
|
6761
|
+
),
|
|
6393
6762
|
...page.next_cursor !== void 0 && { next_cursor: page.next_cursor }
|
|
6394
6763
|
};
|
|
6395
6764
|
},
|
|
6396
6765
|
candidateSet,
|
|
6397
6766
|
candidates: async (embedding2, candidateOptions = {}) => decodeAll((await fetchCandidates(embedding2, candidateOptions, false)).items)
|
|
6398
6767
|
};
|
|
6768
|
+
let rejectedRows = 0;
|
|
6769
|
+
const rewriteLegacyTopics = async (records, token) => {
|
|
6770
|
+
const write = (batch) => persistence.putMany(
|
|
6771
|
+
batch.map((item) => ({ memory: item.memory, expectedVersion: item })),
|
|
6772
|
+
options.signal,
|
|
6773
|
+
token
|
|
6774
|
+
);
|
|
6775
|
+
try {
|
|
6776
|
+
await write(records);
|
|
6777
|
+
return true;
|
|
6778
|
+
} catch (error) {
|
|
6779
|
+
if (!isVersionConflict(error) && !isRejectedRow(error)) throw error;
|
|
6780
|
+
if (records.length === 1) {
|
|
6781
|
+
if (isRejectedRow(error)) rejectedRows++;
|
|
6782
|
+
return false;
|
|
6783
|
+
}
|
|
6784
|
+
let complete = true;
|
|
6785
|
+
for (const item of records)
|
|
6786
|
+
await write([item]).catch((rowError) => {
|
|
6787
|
+
if (isRejectedRow(rowError)) rejectedRows++;
|
|
6788
|
+
else if (!isVersionConflict(rowError)) throw rowError;
|
|
6789
|
+
complete = false;
|
|
6790
|
+
});
|
|
6791
|
+
return complete;
|
|
6792
|
+
}
|
|
6793
|
+
};
|
|
6794
|
+
const upgradeLegacyTopics = () => withRemoteWorkLease(persistence, "topics", TOPIC_UPGRADE_PROCESSOR, async (token, lease) => {
|
|
6795
|
+
let cursor;
|
|
6796
|
+
let complete = true;
|
|
6797
|
+
do {
|
|
6798
|
+
options.signal?.throwIfAborted();
|
|
6799
|
+
if (lease.aborted) return false;
|
|
6800
|
+
const page = await fetchQueryPage({
|
|
6801
|
+
topics_legacy: true,
|
|
6802
|
+
include_archived: true,
|
|
6803
|
+
include_quarantined: true,
|
|
6804
|
+
include_superseded: true,
|
|
6805
|
+
limit: TOPIC_UPGRADE_PAGE,
|
|
6806
|
+
...cursor !== void 0 && { cursor },
|
|
6807
|
+
signal: options.signal
|
|
6808
|
+
});
|
|
6809
|
+
const { items } = await decodeAll(page.items);
|
|
6810
|
+
const legacy = items.filter((item) => codec.isLegacy(snapshots.get(item)?.encryptedTopics));
|
|
6811
|
+
if (legacy.length && !await rewriteLegacyTopics(legacy, token)) complete = false;
|
|
6812
|
+
cursor = page.next_cursor;
|
|
6813
|
+
} while (cursor);
|
|
6814
|
+
if (rejectedRows)
|
|
6815
|
+
getLogger().warn(
|
|
6816
|
+
`[memory/remote] Nearby rejected ${rejectedRows} rows during the topic upgrade; they keep legacy topics`
|
|
6817
|
+
);
|
|
6818
|
+
return complete;
|
|
6819
|
+
});
|
|
6820
|
+
if (legacyTopicRows)
|
|
6821
|
+
void upgradeLegacyTopics().then((complete) => {
|
|
6822
|
+
if (complete) legacyTopicRows = false;
|
|
6823
|
+
}).catch((error) => {
|
|
6824
|
+
if (!options.signal?.aborted)
|
|
6825
|
+
getLogger().warn("[memory/remote] Topic upgrade failed:", error);
|
|
6826
|
+
});
|
|
6827
|
+
return persistence;
|
|
6399
6828
|
}
|
|
6400
6829
|
|
|
6401
6830
|
// src/lib/chat/inbox.ts
|
|
@@ -6485,6 +6914,67 @@ async function openInboxItem(item, keyPair) {
|
|
|
6485
6914
|
}
|
|
6486
6915
|
return opened;
|
|
6487
6916
|
}
|
|
6917
|
+
function inboxReplaces(row, opened) {
|
|
6918
|
+
if (row.error) return true;
|
|
6919
|
+
return row.wasStopped === true && opened.status === "completed";
|
|
6920
|
+
}
|
|
6921
|
+
async function clearTurnErrors(backend, answer) {
|
|
6922
|
+
const parentId = answer.parentMessageId;
|
|
6923
|
+
if (parentId) {
|
|
6924
|
+
const [parent] = await backend.getMessagesByIds([parentId]);
|
|
6925
|
+
if (parent?.error) await backend.updateMessageError(parentId, null);
|
|
6926
|
+
}
|
|
6927
|
+
if (!answer.error) return answer;
|
|
6928
|
+
return await backend.updateMessageError(answer.uniqueId, null) ?? answer;
|
|
6929
|
+
}
|
|
6930
|
+
async function deliverInboxAnswers(options) {
|
|
6931
|
+
const { inbox, keyPair, backend, store } = options;
|
|
6932
|
+
const results = [];
|
|
6933
|
+
for (const item of await inbox.list()) {
|
|
6934
|
+
let opened;
|
|
6935
|
+
try {
|
|
6936
|
+
opened = await openInboxItem(item, keyPair);
|
|
6937
|
+
} catch (err) {
|
|
6938
|
+
results.push({
|
|
6939
|
+
id: item.id,
|
|
6940
|
+
conversationId: null,
|
|
6941
|
+
status: "unreadable",
|
|
6942
|
+
assistantMessage: null,
|
|
6943
|
+
error: err instanceof Error ? err.message : String(err)
|
|
6944
|
+
});
|
|
6945
|
+
continue;
|
|
6946
|
+
}
|
|
6947
|
+
const base = { id: item.id, conversationId: opened.conversation_id };
|
|
6948
|
+
try {
|
|
6949
|
+
const messageId = opened.assistant_message_id ?? `msg_bg_${opened.inference_id}`;
|
|
6950
|
+
const [found] = await backend.getMessagesByIds([messageId]);
|
|
6951
|
+
const existing = found && inboxReplaces(found, opened) ? void 0 : found;
|
|
6952
|
+
if (!found) {
|
|
6953
|
+
const parent = opened.parent_message_id;
|
|
6954
|
+
const ownsTurn = parent ? (await backend.getMessagesByIds([parent])).length > 0 : await backend.getConversation(opened.conversation_id) !== null;
|
|
6955
|
+
if (!ownsTurn) {
|
|
6956
|
+
results.push({ ...base, status: "elsewhere", assistantMessage: null });
|
|
6957
|
+
continue;
|
|
6958
|
+
}
|
|
6959
|
+
}
|
|
6960
|
+
const stored2 = existing ?? await store(opened, messageId);
|
|
6961
|
+
await inbox.remove(item.id);
|
|
6962
|
+
results.push({
|
|
6963
|
+
...base,
|
|
6964
|
+
status: existing ? "delivered" : "stored",
|
|
6965
|
+
assistantMessage: stored2
|
|
6966
|
+
});
|
|
6967
|
+
} catch (err) {
|
|
6968
|
+
results.push({
|
|
6969
|
+
...base,
|
|
6970
|
+
status: "retry",
|
|
6971
|
+
assistantMessage: null,
|
|
6972
|
+
error: err instanceof Error ? err.message : String(err)
|
|
6973
|
+
});
|
|
6974
|
+
}
|
|
6975
|
+
}
|
|
6976
|
+
return results;
|
|
6977
|
+
}
|
|
6488
6978
|
|
|
6489
6979
|
// src/lib/chat/reservationReceipts.ts
|
|
6490
6980
|
var ACTIONS = [
|
|
@@ -6885,9 +7375,9 @@ function toResponsesFormat(tool) {
|
|
|
6885
7375
|
function getCachedServerTools() {
|
|
6886
7376
|
if (typeof localStorage === "undefined") return null;
|
|
6887
7377
|
try {
|
|
6888
|
-
const
|
|
6889
|
-
if (!
|
|
6890
|
-
const parsed = JSON.parse(
|
|
7378
|
+
const cached2 = localStorage.getItem(SERVER_TOOLS_CACHE_KEY);
|
|
7379
|
+
if (!cached2) return null;
|
|
7380
|
+
const parsed = JSON.parse(cached2);
|
|
6891
7381
|
if (parsed.version !== CACHE_VERSION) {
|
|
6892
7382
|
removeLocalStorageCache();
|
|
6893
7383
|
return null;
|
|
@@ -6931,8 +7421,8 @@ function clearServerToolsCache(cache = localStorageToolsCache) {
|
|
|
6931
7421
|
return cache.clear?.();
|
|
6932
7422
|
}
|
|
6933
7423
|
function getToolsChecksum2(cache = localStorageToolsCache) {
|
|
6934
|
-
const
|
|
6935
|
-
return
|
|
7424
|
+
const cached2 = cache.get();
|
|
7425
|
+
return cached2 instanceof Promise ? cached2.then((c) => c?.checksum) : cached2?.checksum;
|
|
6936
7426
|
}
|
|
6937
7427
|
function shouldRefreshTools(responseChecksum, cache = localStorageToolsCache) {
|
|
6938
7428
|
if (!responseChecksum) {
|
|
@@ -6995,33 +7485,33 @@ async function getServerTools(options) {
|
|
|
6995
7485
|
} catch (error) {
|
|
6996
7486
|
getLogger().warn("[serverTools] Cache read failed; falling through to server fetch:", error);
|
|
6997
7487
|
}
|
|
6998
|
-
const
|
|
6999
|
-
const cacheValid = !isCacheExpired(
|
|
7000
|
-
if (
|
|
7001
|
-
return
|
|
7488
|
+
const cached2 = rawCached && rawCached.version === CACHE_VERSION ? rawCached : null;
|
|
7489
|
+
const cacheValid = !isCacheExpired(cached2, cacheExpirationMs);
|
|
7490
|
+
if (cached2 && cacheValid && !forceRefresh) {
|
|
7491
|
+
return cached2.tools;
|
|
7002
7492
|
}
|
|
7003
7493
|
try {
|
|
7004
7494
|
const { BASE_URL: BASE_URL2 } = await import("./clientConfig-VPOGQRNP.mjs");
|
|
7005
7495
|
const effectiveBaseUrl = baseUrl ?? BASE_URL2;
|
|
7006
|
-
const validator =
|
|
7496
|
+
const validator = cached2 && !forceRefresh ? cached2.etag : void 0;
|
|
7007
7497
|
let authHeaders;
|
|
7008
7498
|
if (apiKey) {
|
|
7009
7499
|
authHeaders = { "X-API-Key": apiKey };
|
|
7010
7500
|
} else {
|
|
7011
7501
|
if (!getToken) {
|
|
7012
7502
|
getLogger().warn("[serverTools] No auth method available for fetching tools");
|
|
7013
|
-
return
|
|
7503
|
+
return cached2?.tools ?? [];
|
|
7014
7504
|
}
|
|
7015
7505
|
const token = await getToken();
|
|
7016
7506
|
if (!token) {
|
|
7017
7507
|
getLogger().warn("[serverTools] No auth token available for fetching tools");
|
|
7018
|
-
return
|
|
7508
|
+
return cached2?.tools ?? [];
|
|
7019
7509
|
}
|
|
7020
7510
|
authHeaders = { Authorization: `Bearer ${token}` };
|
|
7021
7511
|
}
|
|
7022
7512
|
const result = await fetchServerToolsFromApi(effectiveBaseUrl, authHeaders, validator);
|
|
7023
7513
|
if (result.notModified) {
|
|
7024
|
-
const confirmed =
|
|
7514
|
+
const confirmed = cached2;
|
|
7025
7515
|
await persistCache({ ...confirmed, timestamp: Date.now() });
|
|
7026
7516
|
return confirmed.tools;
|
|
7027
7517
|
}
|
|
@@ -7029,9 +7519,9 @@ async function getServerTools(options) {
|
|
|
7029
7519
|
return result.tools;
|
|
7030
7520
|
} catch (error) {
|
|
7031
7521
|
getLogger().error("[serverTools] Failed to fetch server tools:", error);
|
|
7032
|
-
if (
|
|
7522
|
+
if (cached2?.tools) {
|
|
7033
7523
|
getLogger().warn("[serverTools] Using stale cached tools due to fetch error");
|
|
7034
|
-
return
|
|
7524
|
+
return cached2.tools;
|
|
7035
7525
|
}
|
|
7036
7526
|
return [];
|
|
7037
7527
|
}
|
|
@@ -7961,6 +8451,13 @@ function createErrorResult(message, onError) {
|
|
|
7961
8451
|
function isAbortError(err) {
|
|
7962
8452
|
return err instanceof Error && err.name === "AbortError";
|
|
7963
8453
|
}
|
|
8454
|
+
var ProviderStreamError = class extends Error {
|
|
8455
|
+
constructor(message, code) {
|
|
8456
|
+
super(message);
|
|
8457
|
+
this.name = "ProviderStreamError";
|
|
8458
|
+
this.code = code;
|
|
8459
|
+
}
|
|
8460
|
+
};
|
|
7964
8461
|
function getInStreamErrorMessage(chunk) {
|
|
7965
8462
|
if (!chunk || typeof chunk !== "object") return null;
|
|
7966
8463
|
const obj = chunk;
|
|
@@ -8158,13 +8655,13 @@ function extractParamGroups(content) {
|
|
|
8158
8655
|
}
|
|
8159
8656
|
function mergeXaiInlineParameterTags(content, toolCalls) {
|
|
8160
8657
|
if (!content || !content.includes(PARAM_MARKER)) return content;
|
|
8161
|
-
const
|
|
8162
|
-
if (
|
|
8658
|
+
const entries2 = Array.from(toolCalls.values());
|
|
8659
|
+
if (entries2.length === 0) return content;
|
|
8163
8660
|
const groups = extractParamGroups(content);
|
|
8164
8661
|
if (groups.length === 0) return content;
|
|
8165
|
-
const pairCount = Math.min(groups.length,
|
|
8662
|
+
const pairCount = Math.min(groups.length, entries2.length);
|
|
8166
8663
|
for (let i = 0; i < pairCount; i++) {
|
|
8167
|
-
const target =
|
|
8664
|
+
const target = entries2[i];
|
|
8168
8665
|
const params = groups[i];
|
|
8169
8666
|
if (!target || !params) continue;
|
|
8170
8667
|
let args = {};
|
|
@@ -8247,7 +8744,7 @@ var CompletionsStrategy = class {
|
|
|
8247
8744
|
processStreamChunk(chunk, accumulator) {
|
|
8248
8745
|
const result = { content: null, thinking: null };
|
|
8249
8746
|
const inStreamErr = getInStreamErrorMessage(chunk);
|
|
8250
|
-
if (inStreamErr) throw new
|
|
8747
|
+
if (inStreamErr) throw new ProviderStreamError(inStreamErr);
|
|
8251
8748
|
const rawChunk = chunk;
|
|
8252
8749
|
const typedChunk = rawChunk.response && rawChunk.type === "response" ? rawChunk.response : chunk;
|
|
8253
8750
|
if (typedChunk.id && !accumulator.responseId) {
|
|
@@ -9098,7 +9595,7 @@ var ResponsesStrategy = class {
|
|
|
9098
9595
|
const result = { content: null, thinking: null };
|
|
9099
9596
|
const typedChunk = chunk;
|
|
9100
9597
|
const inStreamErr = getInStreamErrorMessage(chunk);
|
|
9101
|
-
if (inStreamErr) throw new
|
|
9598
|
+
if (inStreamErr) throw new ProviderStreamError(inStreamErr);
|
|
9102
9599
|
if (typedChunk.type === "response.failed") {
|
|
9103
9600
|
const resp = typedChunk.response;
|
|
9104
9601
|
const err = resp?.error;
|
|
@@ -9115,9 +9612,12 @@ var ResponsesStrategy = class {
|
|
|
9115
9612
|
}
|
|
9116
9613
|
}
|
|
9117
9614
|
const label = code ? `[${code}] ` : "";
|
|
9118
|
-
throw new
|
|
9615
|
+
throw new ProviderStreamError(
|
|
9616
|
+
`${label}${message || "Upstream request failed"}`,
|
|
9617
|
+
code || void 0
|
|
9618
|
+
);
|
|
9119
9619
|
}
|
|
9120
|
-
throw new
|
|
9620
|
+
throw new ProviderStreamError("Upstream request failed (response.failed)");
|
|
9121
9621
|
}
|
|
9122
9622
|
if (typedChunk.type === "response" && typedChunk.response) {
|
|
9123
9623
|
const resp = typedChunk.response;
|
|
@@ -9741,13 +10241,6 @@ function isRetriableStreamError(err) {
|
|
|
9741
10241
|
if (msg.includes("connection refused") || msg.includes("connect error")) return true;
|
|
9742
10242
|
return false;
|
|
9743
10243
|
}
|
|
9744
|
-
var ProviderStreamError = class extends Error {
|
|
9745
|
-
constructor(message, code) {
|
|
9746
|
-
super(message);
|
|
9747
|
-
this.name = "ProviderStreamError";
|
|
9748
|
-
this.code = code;
|
|
9749
|
-
}
|
|
9750
|
-
};
|
|
9751
10244
|
function extractProviderStreamError(chunk) {
|
|
9752
10245
|
if (!chunk || typeof chunk !== "object") return null;
|
|
9753
10246
|
const errField = chunk.error;
|
|
@@ -10128,6 +10621,7 @@ async function runToolLoop(options) {
|
|
|
10128
10621
|
thinking: redactor.deAnonymize(acc.thinking)
|
|
10129
10622
|
}) : strategy.buildFinalResponse(acc);
|
|
10130
10623
|
const finalContentText = (acc) => redactor ? redactor.deAnonymize(acc.content) : acc.content;
|
|
10624
|
+
let streamingAccumulator = null;
|
|
10131
10625
|
try {
|
|
10132
10626
|
let sseError = null;
|
|
10133
10627
|
let apiTools = toolsToApiFormat(tools, resolved);
|
|
@@ -10279,6 +10773,7 @@ async function runToolLoop(options) {
|
|
|
10279
10773
|
}
|
|
10280
10774
|
});
|
|
10281
10775
|
accumulator = createStreamAccumulator(model || void 0);
|
|
10776
|
+
streamingAccumulator = accumulator;
|
|
10282
10777
|
contentSmoother = new StreamSmoother((text16) => {
|
|
10283
10778
|
if (emitData) emitData(text16);
|
|
10284
10779
|
}, smoothing);
|
|
@@ -10789,6 +11284,7 @@ Executing tool: ${toolInfo}
|
|
|
10789
11284
|
}
|
|
10790
11285
|
});
|
|
10791
11286
|
currentAccumulator = createStreamAccumulator(model || void 0);
|
|
11287
|
+
streamingAccumulator = currentAccumulator;
|
|
10792
11288
|
contContentSmoother = new StreamSmoother((text16) => {
|
|
10793
11289
|
if (emitData) emitData(text16);
|
|
10794
11290
|
}, smoothing);
|
|
@@ -10986,7 +11482,7 @@ Executing tool: ${toolInfo}
|
|
|
10986
11482
|
const statusCode = err instanceof Error && "statusCode" in err ? err.statusCode : void 0;
|
|
10987
11483
|
const connectionLost = !(err instanceof ProviderStreamError) && !(err instanceof SseError);
|
|
10988
11484
|
return {
|
|
10989
|
-
data: null,
|
|
11485
|
+
data: connectionLost && streamingAccumulator ? buildResponseFinal(streamingAccumulator) : null,
|
|
10990
11486
|
error: errorMsg,
|
|
10991
11487
|
statusCode,
|
|
10992
11488
|
...connectionLost ? { connectionLost: true } : {}
|
|
@@ -11487,21 +11983,21 @@ function contextFields(context) {
|
|
|
11487
11983
|
);
|
|
11488
11984
|
}
|
|
11489
11985
|
function conversationContext(data) {
|
|
11490
|
-
const
|
|
11491
|
-
return
|
|
11986
|
+
const entries2 = Object.entries(data).filter(([field10]) => field10.startsWith(CONTEXT_FIELD_PREFIX)).map(([field10, value]) => [field10.slice(CONTEXT_FIELD_PREFIX.length), value]);
|
|
11987
|
+
return entries2.length > 0 ? plain(Object.fromEntries(entries2)) : void 0;
|
|
11492
11988
|
}
|
|
11493
|
-
function toConversation(
|
|
11494
|
-
const pinnedAt = number(
|
|
11495
|
-
const projectId = text3(
|
|
11496
|
-
const context = conversationContext(
|
|
11989
|
+
function toConversation(record3) {
|
|
11990
|
+
const pinnedAt = number(record3.data.pinnedAt);
|
|
11991
|
+
const projectId = text3(record3.data.projectId);
|
|
11992
|
+
const context = conversationContext(record3.data);
|
|
11497
11993
|
return {
|
|
11498
|
-
uniqueId:
|
|
11499
|
-
conversationId:
|
|
11500
|
-
title: text3(
|
|
11994
|
+
uniqueId: record3.id,
|
|
11995
|
+
conversationId: record3.id,
|
|
11996
|
+
title: text3(record3.data.title) ?? "",
|
|
11501
11997
|
...projectId ? { projectId } : {},
|
|
11502
|
-
createdAt: new Date(
|
|
11503
|
-
updatedAt: new Date(
|
|
11504
|
-
isDeleted:
|
|
11998
|
+
createdAt: new Date(record3.createdAt),
|
|
11999
|
+
updatedAt: new Date(record3.updatedAt),
|
|
12000
|
+
isDeleted: record3.isDeleted,
|
|
11505
12001
|
pinnedAt: pinnedAt ? new Date(pinnedAt) : null,
|
|
11506
12002
|
...context ? { context } : {}
|
|
11507
12003
|
};
|
|
@@ -11523,21 +12019,21 @@ function messageData(options) {
|
|
|
11523
12019
|
...anuma ? { anuma } : {}
|
|
11524
12020
|
});
|
|
11525
12021
|
}
|
|
11526
|
-
function toMessage(
|
|
11527
|
-
const { chunkOffsets: _offsets, truncated: _truncated, anuma: rawAnuma, ...fields } =
|
|
12022
|
+
function toMessage(record3) {
|
|
12023
|
+
const { chunkOffsets: _offsets, truncated: _truncated, anuma: rawAnuma, ...fields } = record3.data;
|
|
11528
12024
|
const anuma = readAnumaTurn(rawAnuma);
|
|
11529
12025
|
return {
|
|
11530
12026
|
...anuma ? { anuma } : {},
|
|
11531
12027
|
...fields,
|
|
11532
|
-
uniqueId:
|
|
11533
|
-
messageId:
|
|
11534
|
-
conversationId:
|
|
11535
|
-
createdAt: new Date(
|
|
11536
|
-
updatedAt: new Date(
|
|
12028
|
+
uniqueId: record3.id,
|
|
12029
|
+
messageId: record3.sortKey,
|
|
12030
|
+
conversationId: record3.conversationId,
|
|
12031
|
+
createdAt: new Date(record3.createdAt),
|
|
12032
|
+
updatedAt: new Date(record3.updatedAt)
|
|
11537
12033
|
};
|
|
11538
12034
|
}
|
|
11539
|
-
function chunkOffsets(
|
|
11540
|
-
const offsets =
|
|
12035
|
+
function chunkOffsets(record3) {
|
|
12036
|
+
const offsets = record3.data.chunkOffsets;
|
|
11541
12037
|
return Array.isArray(offsets) ? offsets : void 0;
|
|
11542
12038
|
}
|
|
11543
12039
|
function toSkeletons(records) {
|
|
@@ -11558,15 +12054,15 @@ function toSkeletons(records) {
|
|
|
11558
12054
|
};
|
|
11559
12055
|
});
|
|
11560
12056
|
}
|
|
11561
|
-
function toSummary(
|
|
12057
|
+
function toSummary(record3) {
|
|
11562
12058
|
return {
|
|
11563
|
-
uniqueId:
|
|
11564
|
-
conversationId:
|
|
11565
|
-
summary: text3(
|
|
11566
|
-
summarizedUpTo: text3(
|
|
11567
|
-
tokenCount: number(
|
|
11568
|
-
createdAt: new Date(
|
|
11569
|
-
updatedAt: new Date(
|
|
12059
|
+
uniqueId: record3.id,
|
|
12060
|
+
conversationId: record3.id,
|
|
12061
|
+
summary: text3(record3.data.summary) ?? "",
|
|
12062
|
+
summarizedUpTo: text3(record3.data.summarizedUpTo) ?? "",
|
|
12063
|
+
tokenCount: number(record3.data.tokenCount) ?? 0,
|
|
12064
|
+
createdAt: new Date(record3.createdAt),
|
|
12065
|
+
updatedAt: new Date(record3.updatedAt)
|
|
11570
12066
|
};
|
|
11571
12067
|
}
|
|
11572
12068
|
function links(data) {
|
|
@@ -11592,10 +12088,10 @@ function applyLinkOps(data, ops) {
|
|
|
11592
12088
|
}
|
|
11593
12089
|
return plain({ links: current });
|
|
11594
12090
|
}
|
|
11595
|
-
function toLinks(
|
|
11596
|
-
return links(
|
|
11597
|
-
uniqueId: `${
|
|
11598
|
-
conversationId:
|
|
12091
|
+
function toLinks(record3) {
|
|
12092
|
+
return links(record3.data).map((l) => ({
|
|
12093
|
+
uniqueId: `${record3.id}:${l.memoryId}`,
|
|
12094
|
+
conversationId: record3.id,
|
|
11599
12095
|
memoryId: l.memoryId,
|
|
11600
12096
|
score: l.score,
|
|
11601
12097
|
createdAt: new Date(l.createdAt)
|
|
@@ -11604,24 +12100,24 @@ function toLinks(record2) {
|
|
|
11604
12100
|
function bytes(value) {
|
|
11605
12101
|
return new TextEncoder().encode(JSON.stringify(value)).length;
|
|
11606
12102
|
}
|
|
11607
|
-
function fitRecord(
|
|
11608
|
-
if (
|
|
11609
|
-
const data = { ...
|
|
12103
|
+
function fitRecord(record3) {
|
|
12104
|
+
if (record3.kind !== "message" || bytes(record3) <= recordBudgetBytes) return record3;
|
|
12105
|
+
const data = { ...record3.data };
|
|
11610
12106
|
const truncated = [];
|
|
11611
12107
|
for (const field10 of droppable) {
|
|
11612
|
-
if (bytes({ ...
|
|
12108
|
+
if (bytes({ ...record3, data }) <= recordBudgetBytes) break;
|
|
11613
12109
|
if (data[field10] === void 0) continue;
|
|
11614
12110
|
delete data[field10];
|
|
11615
12111
|
truncated.push(field10);
|
|
11616
12112
|
}
|
|
11617
12113
|
const content = text3(data.content) ?? "";
|
|
11618
|
-
const over = bytes({ ...
|
|
12114
|
+
const over = bytes({ ...record3, data }) - recordBudgetBytes;
|
|
11619
12115
|
if (over > 0) {
|
|
11620
12116
|
const encoded = new TextEncoder().encode(content);
|
|
11621
12117
|
data.content = new TextDecoder().decode(encoded.slice(0, Math.max(0, encoded.length - over - 64))).replace(/�$/, "");
|
|
11622
12118
|
truncated.push("content");
|
|
11623
12119
|
}
|
|
11624
|
-
return { ...
|
|
12120
|
+
return { ...record3, data: { ...data, truncated } };
|
|
11625
12121
|
}
|
|
11626
12122
|
function acceptedVector(vector2) {
|
|
11627
12123
|
if (!vector2 || !acceptedDims.has(vector2.length)) return void 0;
|
|
@@ -11665,8 +12161,8 @@ function anumaTurnContent(bubbles) {
|
|
|
11665
12161
|
return bubbles.join("\n\n");
|
|
11666
12162
|
}
|
|
11667
12163
|
function anumaLastReadSortKey(conversation) {
|
|
11668
|
-
const
|
|
11669
|
-
const state =
|
|
12164
|
+
const record3 = conversation && "record" in conversation ? conversation.record : conversation;
|
|
12165
|
+
const state = record3?.data.anuma;
|
|
11670
12166
|
if (!isObject(state)) return 0;
|
|
11671
12167
|
const sortKey = state.lastReadSortKey;
|
|
11672
12168
|
return Number.isSafeInteger(sortKey) && sortKey > 0 ? sortKey : 0;
|
|
@@ -11719,19 +12215,19 @@ async function markAnumaRead(store, sortKey, options = {}) {
|
|
|
11719
12215
|
const current = await ensureAnumaConversation(store, options);
|
|
11720
12216
|
const read = anumaLastReadSortKey(current);
|
|
11721
12217
|
if (sortKey <= read) return current;
|
|
11722
|
-
const
|
|
11723
|
-
const state = isObject(
|
|
11724
|
-
const data = plain({ ...
|
|
12218
|
+
const record3 = current.record;
|
|
12219
|
+
const state = isObject(record3.data.anuma) ? record3.data.anuma : {};
|
|
12220
|
+
const data = plain({ ...record3.data, anuma: { ...state, lastReadSortKey: sortKey } });
|
|
11725
12221
|
try {
|
|
11726
12222
|
const [written] = await store.putMany(
|
|
11727
12223
|
[
|
|
11728
12224
|
{
|
|
11729
12225
|
expectedVersion: current.version,
|
|
11730
12226
|
record: {
|
|
11731
|
-
...
|
|
12227
|
+
...record3,
|
|
11732
12228
|
data,
|
|
11733
|
-
sortKey: conversationSortKey(data,
|
|
11734
|
-
updatedAt: Math.max(
|
|
12229
|
+
sortKey: conversationSortKey(data, record3.createdAt),
|
|
12230
|
+
updatedAt: Math.max(record3.updatedAt, now())
|
|
11735
12231
|
}
|
|
11736
12232
|
}
|
|
11737
12233
|
],
|
|
@@ -11766,22 +12262,22 @@ function createSummaryContext(database, encryption = {}) {
|
|
|
11766
12262
|
summariesCollection: database.get("conversation_summaries")
|
|
11767
12263
|
};
|
|
11768
12264
|
}
|
|
11769
|
-
function modelToStored(
|
|
12265
|
+
function modelToStored(record3, summary) {
|
|
11770
12266
|
return {
|
|
11771
|
-
uniqueId:
|
|
11772
|
-
conversationId:
|
|
12267
|
+
uniqueId: record3.id,
|
|
12268
|
+
conversationId: record3.conversationId,
|
|
11773
12269
|
summary,
|
|
11774
|
-
summarizedUpTo:
|
|
11775
|
-
tokenCount:
|
|
11776
|
-
createdAt:
|
|
11777
|
-
updatedAt:
|
|
12270
|
+
summarizedUpTo: record3.summarizedUpTo,
|
|
12271
|
+
tokenCount: record3.tokenCount,
|
|
12272
|
+
createdAt: record3.createdAt,
|
|
12273
|
+
updatedAt: record3.updatedAt
|
|
11778
12274
|
};
|
|
11779
12275
|
}
|
|
11780
12276
|
async function getConversationSummaryOp(ctx, conversationId) {
|
|
11781
12277
|
const results = await ctx.summariesCollection.query(Q4.where("conversation_id", conversationId)).fetch();
|
|
11782
12278
|
if (results.length === 0) return null;
|
|
11783
|
-
const
|
|
11784
|
-
const stored2 = modelToStored(
|
|
12279
|
+
const record3 = results[0];
|
|
12280
|
+
const stored2 = modelToStored(record3, record3.summary);
|
|
11785
12281
|
if (ctx.walletAddress && isEncrypted(stored2.summary)) {
|
|
11786
12282
|
if (ctx.signMessage) {
|
|
11787
12283
|
try {
|
|
@@ -11800,7 +12296,7 @@ async function getConversationSummaryOp(ctx, conversationId) {
|
|
|
11800
12296
|
ctx.embeddedWalletSigner
|
|
11801
12297
|
);
|
|
11802
12298
|
await ctx.database.write(async () => {
|
|
11803
|
-
const current = await ctx.summariesCollection.query(Q4.where("id",
|
|
12299
|
+
const current = await ctx.summariesCollection.query(Q4.where("id", record3.id)).fetch();
|
|
11804
12300
|
if (current[0]?.summary === stored2.summary) {
|
|
11805
12301
|
await current[0].update((rec) => {
|
|
11806
12302
|
rec.summary = encryptedSummary;
|
|
@@ -11815,19 +12311,19 @@ async function getConversationSummaryOp(ctx, conversationId) {
|
|
|
11815
12311
|
}
|
|
11816
12312
|
async function upsertConversationSummaryOp(ctx, conversationId, summary, summarizedUpTo, tokenCount) {
|
|
11817
12313
|
const revision2 = getConversationRevision(ctx.database, conversationId);
|
|
11818
|
-
let
|
|
12314
|
+
let record3;
|
|
11819
12315
|
const encryptedSummary = ctx.walletAddress ? await encryptField(summary, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner) : summary;
|
|
11820
12316
|
await ctx.database.write(async () => {
|
|
11821
12317
|
assertConversationRevision(ctx.database, conversationId, revision2);
|
|
11822
12318
|
const existing = await ctx.summariesCollection.query(Q4.where("conversation_id", conversationId)).fetch();
|
|
11823
12319
|
if (existing.length > 0) {
|
|
11824
|
-
|
|
12320
|
+
record3 = await existing[0].update((rec) => {
|
|
11825
12321
|
rec.summary = encryptedSummary;
|
|
11826
12322
|
rec.summarizedUpTo = summarizedUpTo;
|
|
11827
12323
|
rec.tokenCount = tokenCount;
|
|
11828
12324
|
});
|
|
11829
12325
|
} else {
|
|
11830
|
-
|
|
12326
|
+
record3 = await ctx.summariesCollection.create((rec) => {
|
|
11831
12327
|
rec.conversationId = conversationId;
|
|
11832
12328
|
rec.summary = encryptedSummary;
|
|
11833
12329
|
rec.summarizedUpTo = summarizedUpTo;
|
|
@@ -11835,13 +12331,13 @@ async function upsertConversationSummaryOp(ctx, conversationId, summary, summari
|
|
|
11835
12331
|
});
|
|
11836
12332
|
}
|
|
11837
12333
|
});
|
|
11838
|
-
return modelToStored(
|
|
12334
|
+
return modelToStored(record3, summary);
|
|
11839
12335
|
}
|
|
11840
12336
|
async function deleteConversationSummaryOp(ctx, conversationId) {
|
|
11841
12337
|
await ctx.database.write(async () => {
|
|
11842
12338
|
const existing = await ctx.summariesCollection.query(Q4.where("conversation_id", conversationId)).fetch();
|
|
11843
|
-
for (const
|
|
11844
|
-
await
|
|
12339
|
+
for (const record3 of existing) {
|
|
12340
|
+
await record3.destroyPermanently();
|
|
11845
12341
|
}
|
|
11846
12342
|
});
|
|
11847
12343
|
}
|
|
@@ -11917,7 +12413,7 @@ function messageRecord(message) {
|
|
|
11917
12413
|
const fitted = chunks3?.length ? fitChunks(chunks3) : void 0;
|
|
11918
12414
|
const single = fitted ? void 0 : acceptedVector(vector2);
|
|
11919
12415
|
const embeddings2 = fitted?.map((c) => c.vector) ?? (single ? [single] : void 0);
|
|
11920
|
-
const
|
|
12416
|
+
const record3 = fitRecord({
|
|
11921
12417
|
kind: "message",
|
|
11922
12418
|
id: message.uniqueId,
|
|
11923
12419
|
conversationId: message.conversationId,
|
|
@@ -11931,7 +12427,7 @@ function messageRecord(message) {
|
|
|
11931
12427
|
}
|
|
11932
12428
|
});
|
|
11933
12429
|
return {
|
|
11934
|
-
record:
|
|
12430
|
+
record: record3,
|
|
11935
12431
|
...embeddings2 ? { embeddings: embeddings2 } : {},
|
|
11936
12432
|
...embeddings2 && message.embeddingModel ? { embeddingModel: message.embeddingModel } : {}
|
|
11937
12433
|
};
|
|
@@ -12079,15 +12575,15 @@ function ref(value) {
|
|
|
12079
12575
|
function sameMetadata(a, b) {
|
|
12080
12576
|
return metadata.every((key3) => a[key3] === b[key3]);
|
|
12081
12577
|
}
|
|
12082
|
-
function wire(
|
|
12578
|
+
function wire(record3, payload) {
|
|
12083
12579
|
return {
|
|
12084
|
-
kind:
|
|
12085
|
-
id:
|
|
12086
|
-
conversation_id:
|
|
12087
|
-
sort_key:
|
|
12088
|
-
created_at:
|
|
12089
|
-
updated_at:
|
|
12090
|
-
is_deleted:
|
|
12580
|
+
kind: record3.kind,
|
|
12581
|
+
id: record3.id,
|
|
12582
|
+
conversation_id: record3.conversationId,
|
|
12583
|
+
sort_key: record3.sortKey,
|
|
12584
|
+
created_at: record3.createdAt,
|
|
12585
|
+
updated_at: record3.updatedAt,
|
|
12586
|
+
is_deleted: record3.isDeleted,
|
|
12091
12587
|
payload
|
|
12092
12588
|
};
|
|
12093
12589
|
}
|
|
@@ -12144,10 +12640,10 @@ async function createRemoteChatStore(options) {
|
|
|
12144
12640
|
serverUpdatedAt: value.server_updated_at
|
|
12145
12641
|
};
|
|
12146
12642
|
};
|
|
12147
|
-
const seal = async (
|
|
12148
|
-
if (
|
|
12643
|
+
const seal = async (record3, signal) => {
|
|
12644
|
+
if (record3.isDeleted) return "";
|
|
12149
12645
|
const payload = await encrypt(
|
|
12150
|
-
JSON.stringify({ schema: 1, account_id: accountId, key_id: keyId, record:
|
|
12646
|
+
JSON.stringify({ schema: 1, account_id: accountId, key_id: keyId, record: record3 })
|
|
12151
12647
|
);
|
|
12152
12648
|
signal?.throwIfAborted();
|
|
12153
12649
|
if (!cipherPattern.test(payload) || payload.length > maxPayload) invalid();
|
|
@@ -12511,8 +13007,8 @@ var emptyMessage = {
|
|
|
12511
13007
|
var maxPasses = 5;
|
|
12512
13008
|
var verifyBatch = 1e3;
|
|
12513
13009
|
var writeBatch = 25;
|
|
12514
|
-
function key(
|
|
12515
|
-
return `${
|
|
13010
|
+
function key(record3) {
|
|
13011
|
+
return `${record3.kind}/${record3.id}`;
|
|
12516
13012
|
}
|
|
12517
13013
|
function sealed(value) {
|
|
12518
13014
|
if (typeof value === "string") return isEncrypted(value);
|
|
@@ -12641,11 +13137,11 @@ async function missing(store, records, signal) {
|
|
|
12641
13137
|
const out = /* @__PURE__ */ new Set();
|
|
12642
13138
|
for (let i = 0; i < records.length; i += verifyBatch) {
|
|
12643
13139
|
const refs = await store.verify(
|
|
12644
|
-
records.slice(i, i + verifyBatch).map(({ record:
|
|
12645
|
-
kind:
|
|
12646
|
-
id:
|
|
12647
|
-
updatedAt:
|
|
12648
|
-
isDeleted:
|
|
13140
|
+
records.slice(i, i + verifyBatch).map(({ record: record3 }) => ({
|
|
13141
|
+
kind: record3.kind,
|
|
13142
|
+
id: record3.id,
|
|
13143
|
+
updatedAt: record3.updatedAt,
|
|
13144
|
+
isDeleted: record3.isDeleted
|
|
12649
13145
|
})),
|
|
12650
13146
|
signal
|
|
12651
13147
|
);
|
|
@@ -12685,14 +13181,14 @@ async function deletedSinceUpload(store, journal, local, signal) {
|
|
|
12685
13181
|
const live2 = (await store.getMany(gone.map(ref2), signal)).filter((s) => !s.record.isDeleted);
|
|
12686
13182
|
const tombstoning = new Set(live2.map((s) => key(s.record)));
|
|
12687
13183
|
await journal.drop(gone.filter((k) => !tombstoning.has(k)));
|
|
12688
|
-
return live2.map(({ record:
|
|
12689
|
-
const empty = emptied[
|
|
13184
|
+
return live2.map(({ record: record3, version }) => {
|
|
13185
|
+
const empty = emptied[record3.kind];
|
|
12690
13186
|
return {
|
|
12691
13187
|
record: {
|
|
12692
|
-
...
|
|
13188
|
+
...record3,
|
|
12693
13189
|
isDeleted: !empty,
|
|
12694
13190
|
data: empty ?? {},
|
|
12695
|
-
updatedAt: Math.max(Date.now(),
|
|
13191
|
+
updatedAt: Math.max(Date.now(), record3.updatedAt + 1)
|
|
12696
13192
|
},
|
|
12697
13193
|
expectedVersion: version
|
|
12698
13194
|
};
|
|
@@ -13041,8 +13537,8 @@ function createVaultAttachments(options) {
|
|
|
13041
13537
|
},
|
|
13042
13538
|
async read(attachmentId, signal) {
|
|
13043
13539
|
if (!attachmentIdPattern2.test(attachmentId)) invalidAttachment();
|
|
13044
|
-
const
|
|
13045
|
-
if (
|
|
13540
|
+
const cached2 = await cache?.get(attachmentId).catch(() => null);
|
|
13541
|
+
if (cached2) return cached2;
|
|
13046
13542
|
for (let attempt = 0; ; attempt++) {
|
|
13047
13543
|
const found = await withRetry(() => store.attachments.get(attachmentId, signal), signal);
|
|
13048
13544
|
if (!found?.download) return null;
|
|
@@ -13071,8 +13567,8 @@ function validRef(value) {
|
|
|
13071
13567
|
const ref3 = value;
|
|
13072
13568
|
return typeof ref3.attachmentId === "string" && attachmentIdPattern2.test(ref3.attachmentId) && typeof ref3.fileId === "string" && ref3.fileId.length > 0 && typeof ref3.name === "string" && typeof ref3.type === "string" && Number.isSafeInteger(ref3.size) && ref3.size >= 0;
|
|
13073
13569
|
}
|
|
13074
|
-
function vaultAttachmentRefs(
|
|
13075
|
-
const refs =
|
|
13570
|
+
function vaultAttachmentRefs(record3) {
|
|
13571
|
+
const refs = record3.data.vaultAttachments;
|
|
13076
13572
|
return Array.isArray(refs) ? refs.filter(validRef) : [];
|
|
13077
13573
|
}
|
|
13078
13574
|
function journalKey(messageId, fileId) {
|
|
@@ -13280,14 +13776,14 @@ function sameRecord(a, b) {
|
|
|
13280
13776
|
return a.sortKey === b.sortKey && a.isDeleted === b.isDeleted && sameJson(a.data, b.data);
|
|
13281
13777
|
}
|
|
13282
13778
|
function toWrite(base, patch) {
|
|
13283
|
-
const
|
|
13284
|
-
if (!
|
|
13285
|
-
if (base && patch.embeddings === void 0 && sameRecord(base.record,
|
|
13779
|
+
const record3 = applyPatch(base?.record, patch);
|
|
13780
|
+
if (!record3) return void 0;
|
|
13781
|
+
if (base && patch.embeddings === void 0 && sameRecord(base.record, record3)) return null;
|
|
13286
13782
|
return {
|
|
13287
|
-
record: fitRecord(
|
|
13783
|
+
record: fitRecord(record3),
|
|
13288
13784
|
expectedVersion: base?.version ?? 0,
|
|
13289
|
-
...patch.embeddings !== void 0 && !
|
|
13290
|
-
...patch.embeddingModel !== void 0 && !
|
|
13785
|
+
...patch.embeddings !== void 0 && !record3.isDeleted ? { embeddings: patch.embeddings } : {},
|
|
13786
|
+
...patch.embeddingModel !== void 0 && !record3.isDeleted ? { embeddingModel: patch.embeddingModel } : {}
|
|
13291
13787
|
};
|
|
13292
13788
|
}
|
|
13293
13789
|
var maxWrites = 25;
|
|
@@ -13421,11 +13917,11 @@ function createVaultChatBackend(options) {
|
|
|
13421
13917
|
for (const listener of [...listeners]) listener(event);
|
|
13422
13918
|
};
|
|
13423
13919
|
const view = (k) => {
|
|
13424
|
-
let
|
|
13920
|
+
let record3 = confirmed.get(k)?.record;
|
|
13425
13921
|
for (const patch of [inflight.get(k), pending.get(k)]) {
|
|
13426
|
-
if (patch)
|
|
13922
|
+
if (patch) record3 = applyPatch(record3, patch) ?? record3;
|
|
13427
13923
|
}
|
|
13428
|
-
return
|
|
13924
|
+
return record3;
|
|
13429
13925
|
};
|
|
13430
13926
|
const conversationLive = (conversationId) => {
|
|
13431
13927
|
const conversation2 = view(key2("conversation", conversationId));
|
|
@@ -13436,10 +13932,10 @@ function createVaultChatBackend(options) {
|
|
|
13436
13932
|
const out = [];
|
|
13437
13933
|
for (const k of keys) {
|
|
13438
13934
|
if (!k.startsWith(`${kind}/`)) continue;
|
|
13439
|
-
const
|
|
13440
|
-
if (!
|
|
13441
|
-
if (conversationId !== void 0 &&
|
|
13442
|
-
out.push(
|
|
13935
|
+
const record3 = view(k);
|
|
13936
|
+
if (!record3 || record3.isDeleted && !includeDeleted) continue;
|
|
13937
|
+
if (conversationId !== void 0 && record3.conversationId !== conversationId) continue;
|
|
13938
|
+
out.push(record3);
|
|
13443
13939
|
}
|
|
13444
13940
|
return out;
|
|
13445
13941
|
};
|
|
@@ -13450,7 +13946,7 @@ function createVaultChatBackend(options) {
|
|
|
13450
13946
|
account: cache.account,
|
|
13451
13947
|
cursor: cursor ?? "",
|
|
13452
13948
|
records: [...confirmed.values()].filter(
|
|
13453
|
-
({ record:
|
|
13949
|
+
({ record: record3 }) => record3.kind === "conversation" || record3.kind !== "project" && keep.has(record3.conversationId)
|
|
13454
13950
|
),
|
|
13455
13951
|
threads: kept,
|
|
13456
13952
|
absent: [...checked].filter((k) => {
|
|
@@ -13764,17 +14260,17 @@ function createVaultChatBackend(options) {
|
|
|
13764
14260
|
return loading;
|
|
13765
14261
|
};
|
|
13766
14262
|
const applyRemote = (snapshot) => {
|
|
13767
|
-
const { record:
|
|
13768
|
-
const k = key2(
|
|
13769
|
-
if (
|
|
14263
|
+
const { record: record3 } = snapshot;
|
|
14264
|
+
const k = key2(record3.kind, record3.id);
|
|
14265
|
+
if (record3.kind === "conversation") {
|
|
13770
14266
|
if (!merge(snapshot)) return;
|
|
13771
|
-
if (
|
|
13772
|
-
announce([
|
|
14267
|
+
if (record3.isDeleted) forgetConversation(record3.id);
|
|
14268
|
+
announce([record3]);
|
|
13773
14269
|
return;
|
|
13774
14270
|
}
|
|
13775
|
-
if (
|
|
13776
|
-
const relevant2 = threads.has(
|
|
13777
|
-
if (relevant2 && merge(snapshot)) announce([
|
|
14271
|
+
if (record3.kind === "project") return;
|
|
14272
|
+
const relevant2 = threads.has(record3.conversationId) || confirmed.has(k) || checked.has(k) && record3.kind !== "message";
|
|
14273
|
+
if (relevant2 && merge(snapshot)) announce([record3]);
|
|
13778
14274
|
};
|
|
13779
14275
|
const listIndex = async (source) => {
|
|
13780
14276
|
const index = [];
|
|
@@ -13925,8 +14421,8 @@ function createVaultChatBackend(options) {
|
|
|
13925
14421
|
checked.add(k);
|
|
13926
14422
|
if (found) merge(found);
|
|
13927
14423
|
}
|
|
13928
|
-
const
|
|
13929
|
-
return
|
|
14424
|
+
const record3 = view(k);
|
|
14425
|
+
return record3 && !record3.isDeleted && conversationLive(record3.conversationId) ? record3 : void 0;
|
|
13930
14426
|
};
|
|
13931
14427
|
const child = async (kind, conversationId) => {
|
|
13932
14428
|
await available2();
|
|
@@ -13963,19 +14459,19 @@ function createVaultChatBackend(options) {
|
|
|
13963
14459
|
await backend.deleteSummary(conversationId);
|
|
13964
14460
|
};
|
|
13965
14461
|
const storedMessage = async (uniqueId) => {
|
|
13966
|
-
const
|
|
13967
|
-
return
|
|
14462
|
+
const record3 = await message(uniqueId);
|
|
14463
|
+
return record3 ? toMessage(record3) : null;
|
|
13968
14464
|
};
|
|
13969
14465
|
const patchMessage = async (uniqueId, patch) => {
|
|
13970
|
-
const
|
|
13971
|
-
if (!
|
|
14466
|
+
const record3 = await message(uniqueId);
|
|
14467
|
+
if (!record3) return null;
|
|
13972
14468
|
await enqueue({
|
|
13973
14469
|
kind: "message",
|
|
13974
14470
|
id: uniqueId,
|
|
13975
|
-
conversationId:
|
|
14471
|
+
conversationId: record3.conversationId,
|
|
13976
14472
|
...patch
|
|
13977
14473
|
});
|
|
13978
|
-
emit({ type: "messages", conversationId:
|
|
14474
|
+
emit({ type: "messages", conversationId: record3.conversationId, origin: "local" });
|
|
13979
14475
|
const updated = view(key2("message", uniqueId));
|
|
13980
14476
|
return updated && !updated.isDeleted ? toMessage(updated) : null;
|
|
13981
14477
|
};
|
|
@@ -14000,12 +14496,12 @@ function createVaultChatBackend(options) {
|
|
|
14000
14496
|
});
|
|
14001
14497
|
const backend = {
|
|
14002
14498
|
async getConversation(conversationId) {
|
|
14003
|
-
const
|
|
14004
|
-
return
|
|
14499
|
+
const record3 = await conversation(conversationId);
|
|
14500
|
+
return record3 && !record3.isDeleted ? toConversation(record3) : null;
|
|
14005
14501
|
},
|
|
14006
14502
|
async getConversations(query) {
|
|
14007
14503
|
await available2();
|
|
14008
|
-
return all("conversation").filter((
|
|
14504
|
+
return all("conversation").filter((record3) => record3.id !== ANUMA_CONVERSATION_ID).map(toConversation).filter(
|
|
14009
14505
|
(c) => query?.projectId === void 0 || (query.projectId === null ? !c.projectId : c.projectId === query.projectId)
|
|
14010
14506
|
).sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
14011
14507
|
},
|
|
@@ -14044,13 +14540,13 @@ function createVaultChatBackend(options) {
|
|
|
14044
14540
|
async updateConversationContext(conversationId, context) {
|
|
14045
14541
|
const set = contextFields(context);
|
|
14046
14542
|
if (Object.keys(set).length > 0) return updateConversation(conversationId, set);
|
|
14047
|
-
const
|
|
14048
|
-
return !!
|
|
14543
|
+
const record3 = await conversation(conversationId);
|
|
14544
|
+
return !!record3 && !record3.isDeleted;
|
|
14049
14545
|
},
|
|
14050
14546
|
async deleteConversation(conversationId) {
|
|
14051
14547
|
if (conversationId === ANUMA_CONVERSATION_ID) return false;
|
|
14052
|
-
const
|
|
14053
|
-
if (!
|
|
14548
|
+
const record3 = await conversation(conversationId);
|
|
14549
|
+
if (!record3 || record3.isDeleted) return false;
|
|
14054
14550
|
for (const [k, patch] of pending)
|
|
14055
14551
|
if (patch.conversationId === conversationId) pending.delete(k);
|
|
14056
14552
|
await enqueue({ kind: "conversation", id: conversationId, conversationId: "", delete: true });
|
|
@@ -14086,8 +14582,8 @@ function createVaultChatBackend(options) {
|
|
|
14086
14582
|
const unknown = ids.map((id2) => key2("message", id2)).filter((k) => !view(k) && !checked.has(k));
|
|
14087
14583
|
await refresh(unknown);
|
|
14088
14584
|
return ids.flatMap((id2) => {
|
|
14089
|
-
const
|
|
14090
|
-
return
|
|
14585
|
+
const record3 = view(key2("message", id2));
|
|
14586
|
+
return record3 && !record3.isDeleted && conversationLive(record3.conversationId) ? [toMessage(record3)] : [];
|
|
14091
14587
|
});
|
|
14092
14588
|
},
|
|
14093
14589
|
async getMessageCount(conversationId) {
|
|
@@ -14095,8 +14591,8 @@ function createVaultChatBackend(options) {
|
|
|
14095
14591
|
},
|
|
14096
14592
|
async getToolCallEventIds(conversationId) {
|
|
14097
14593
|
const ids = /* @__PURE__ */ new Set();
|
|
14098
|
-
for (const
|
|
14099
|
-
const events =
|
|
14594
|
+
for (const record3 of await thread(conversationId)) {
|
|
14595
|
+
const events = record3.data.toolCallEvents;
|
|
14100
14596
|
if (!Array.isArray(events)) continue;
|
|
14101
14597
|
for (const event of events)
|
|
14102
14598
|
if (event && typeof event === "object" && !Array.isArray(event) && typeof event.id === "string")
|
|
@@ -14189,21 +14685,21 @@ function createVaultChatBackend(options) {
|
|
|
14189
14685
|
},
|
|
14190
14686
|
async clearMessages(conversationId) {
|
|
14191
14687
|
await invalidateSummary(conversationId);
|
|
14192
|
-
for (const
|
|
14193
|
-
await enqueue({ kind: "message", id:
|
|
14688
|
+
for (const record3 of await thread(conversationId))
|
|
14689
|
+
await enqueue({ kind: "message", id: record3.id, conversationId, delete: true });
|
|
14194
14690
|
emit({ type: "messages", conversationId, origin: "local" });
|
|
14195
14691
|
},
|
|
14196
14692
|
async deleteMessage(uniqueId) {
|
|
14197
|
-
const
|
|
14198
|
-
if (!
|
|
14199
|
-
await invalidateSummary(
|
|
14693
|
+
const record3 = await message(uniqueId);
|
|
14694
|
+
if (!record3) return null;
|
|
14695
|
+
await invalidateSummary(record3.conversationId, record3);
|
|
14200
14696
|
await enqueue({
|
|
14201
14697
|
kind: "message",
|
|
14202
14698
|
id: uniqueId,
|
|
14203
|
-
conversationId:
|
|
14699
|
+
conversationId: record3.conversationId,
|
|
14204
14700
|
delete: true
|
|
14205
14701
|
});
|
|
14206
|
-
emit({ type: "messages", conversationId:
|
|
14702
|
+
emit({ type: "messages", conversationId: record3.conversationId, origin: "local" });
|
|
14207
14703
|
return uniqueId;
|
|
14208
14704
|
},
|
|
14209
14705
|
observeMessages(conversationId) {
|
|
@@ -14216,13 +14712,13 @@ function createVaultChatBackend(options) {
|
|
|
14216
14712
|
await available2();
|
|
14217
14713
|
if (query?.conversationId) await loadThread(query.conversationId);
|
|
14218
14714
|
const files = [];
|
|
14219
|
-
for (const
|
|
14220
|
-
if (!conversationLive(
|
|
14221
|
-
const stored2 = toMessage(
|
|
14715
|
+
for (const record3 of all("message", query?.conversationId)) {
|
|
14716
|
+
if (!conversationLive(record3.conversationId)) continue;
|
|
14717
|
+
const stored2 = toMessage(record3);
|
|
14222
14718
|
for (const file of stored2.files ?? [])
|
|
14223
14719
|
files.push({
|
|
14224
14720
|
...file,
|
|
14225
|
-
conversationId:
|
|
14721
|
+
conversationId: record3.conversationId,
|
|
14226
14722
|
createdAt: stored2.createdAt,
|
|
14227
14723
|
messageRole: stored2.role
|
|
14228
14724
|
});
|
|
@@ -14261,8 +14757,8 @@ function createVaultChatBackend(options) {
|
|
|
14261
14757
|
return results;
|
|
14262
14758
|
},
|
|
14263
14759
|
async getSummary(conversationId) {
|
|
14264
|
-
const
|
|
14265
|
-
return
|
|
14760
|
+
const record3 = await child("summary", conversationId);
|
|
14761
|
+
return record3 && !record3.isDeleted && record3.data.summarizedUpTo ? toSummary(record3) : null;
|
|
14266
14762
|
},
|
|
14267
14763
|
async upsertSummary(conversationId, summary, summarizedUpTo, tokenCount) {
|
|
14268
14764
|
await child("summary", conversationId);
|
|
@@ -14278,8 +14774,8 @@ function createVaultChatBackend(options) {
|
|
|
14278
14774
|
return toSummary(view(key2("summary", conversationId)));
|
|
14279
14775
|
},
|
|
14280
14776
|
async deleteSummary(conversationId) {
|
|
14281
|
-
const
|
|
14282
|
-
if (!
|
|
14777
|
+
const record3 = await child("summary", conversationId);
|
|
14778
|
+
if (!record3 || record3.isDeleted) return;
|
|
14283
14779
|
await enqueue({
|
|
14284
14780
|
kind: "summary",
|
|
14285
14781
|
id: conversationId,
|
|
@@ -14289,8 +14785,8 @@ function createVaultChatBackend(options) {
|
|
|
14289
14785
|
emit({ type: "summary", conversationId, origin: "local" });
|
|
14290
14786
|
},
|
|
14291
14787
|
async getMemoryLinks(conversationId) {
|
|
14292
|
-
const
|
|
14293
|
-
return
|
|
14788
|
+
const record3 = await child("memory_links", conversationId);
|
|
14789
|
+
return record3 && !record3.isDeleted ? toLinks(record3) : [];
|
|
14294
14790
|
},
|
|
14295
14791
|
async addMemoryLinks(conversationId, items) {
|
|
14296
14792
|
if (!conversationId || items.length === 0) return;
|
|
@@ -14305,8 +14801,8 @@ function createVaultChatBackend(options) {
|
|
|
14305
14801
|
emit({ type: "links", conversationId, origin: "local" });
|
|
14306
14802
|
},
|
|
14307
14803
|
async clearMemoryLinks(conversationId) {
|
|
14308
|
-
const
|
|
14309
|
-
if (!
|
|
14804
|
+
const record3 = await child("memory_links", conversationId);
|
|
14805
|
+
if (!record3 || record3.isDeleted) return;
|
|
14310
14806
|
await enqueue({
|
|
14311
14807
|
kind: "memory_links",
|
|
14312
14808
|
id: conversationId,
|
|
@@ -14324,8 +14820,8 @@ function createVaultChatBackend(options) {
|
|
|
14324
14820
|
async importChats(chats) {
|
|
14325
14821
|
await ready();
|
|
14326
14822
|
const seen = /* @__PURE__ */ new Set();
|
|
14327
|
-
const unique = (items) => items.filter(({ record:
|
|
14328
|
-
const k = key2(
|
|
14823
|
+
const unique = (items) => items.filter(({ record: record3 }) => {
|
|
14824
|
+
const k = key2(record3.kind, record3.id);
|
|
14329
14825
|
if (seen.has(k)) return false;
|
|
14330
14826
|
seen.add(k);
|
|
14331
14827
|
return true;
|
|
@@ -14349,15 +14845,15 @@ function createVaultChatBackend(options) {
|
|
|
14349
14845
|
for (const batch of batches(messages))
|
|
14350
14846
|
messageCount += await connected.importRecords(batch);
|
|
14351
14847
|
} finally {
|
|
14352
|
-
for (const { record:
|
|
14353
|
-
await refresh(conversations.map(({ record:
|
|
14848
|
+
for (const { record: record3 } of messages) checked.delete(key2("message", record3.id));
|
|
14849
|
+
await refresh(conversations.map(({ record: record3 }) => key2("conversation", record3.id))).catch(
|
|
14354
14850
|
() => void 0
|
|
14355
14851
|
);
|
|
14356
|
-
for (const { record:
|
|
14852
|
+
for (const { record: record3 } of conversations) threads.delete(record3.id);
|
|
14357
14853
|
channel?.postMessage("changed");
|
|
14358
14854
|
emit({ type: "conversations", origin: "local" });
|
|
14359
|
-
for (const { record:
|
|
14360
|
-
emit({ type: "messages", conversationId:
|
|
14855
|
+
for (const { record: record3 } of conversations)
|
|
14856
|
+
emit({ type: "messages", conversationId: record3.id, origin: "local" });
|
|
14361
14857
|
}
|
|
14362
14858
|
return { conversations: conversationCount, messages: messageCount };
|
|
14363
14859
|
},
|
|
@@ -14376,8 +14872,8 @@ function createVaultChatBackend(options) {
|
|
|
14376
14872
|
}
|
|
14377
14873
|
};
|
|
14378
14874
|
const updateConversation = async (conversationId, set) => {
|
|
14379
|
-
const
|
|
14380
|
-
if (!
|
|
14875
|
+
const record3 = await conversation(conversationId);
|
|
14876
|
+
if (!record3 || record3.isDeleted) return false;
|
|
14381
14877
|
await enqueue({ kind: "conversation", id: conversationId, conversationId: "", set });
|
|
14382
14878
|
emit({ type: "conversations", origin: "local" });
|
|
14383
14879
|
return true;
|
|
@@ -14553,10 +15049,10 @@ async function decryptConversationTitle(encryptedTitle, address) {
|
|
|
14553
15049
|
);
|
|
14554
15050
|
}
|
|
14555
15051
|
const cacheKey = buildCacheKey(address, encryptedTitle);
|
|
14556
|
-
const
|
|
14557
|
-
if (
|
|
14558
|
-
touchEntry(cacheKey,
|
|
14559
|
-
return
|
|
15052
|
+
const cached2 = titleCache.get(cacheKey);
|
|
15053
|
+
if (cached2 !== void 0) {
|
|
15054
|
+
touchEntry(cacheKey, cached2);
|
|
15055
|
+
return cached2;
|
|
14560
15056
|
}
|
|
14561
15057
|
const inFlight = pendingDecrypts.get(cacheKey);
|
|
14562
15058
|
if (inFlight) return inFlight;
|
|
@@ -14815,25 +15311,25 @@ async function upsertEntitiesInWrite(ctx, entities) {
|
|
|
14815
15311
|
const kindBackfills = existing.filter((e) => {
|
|
14816
15312
|
const incoming = kindByName.get(e.canonicalName);
|
|
14817
15313
|
return incoming !== void 0 && (e.kind === null || e.kind === void 0 || e.kind === "");
|
|
14818
|
-
}).map((
|
|
15314
|
+
}).map((record3) => ({ record: record3, kind: kindByName.get(record3.canonicalName) }));
|
|
14819
15315
|
const missing2 = unique.filter((n) => !existingNames.has(n));
|
|
14820
15316
|
const created = missing2.map(
|
|
14821
|
-
(name) => ctx.entityCollection.prepareCreate((
|
|
14822
|
-
|
|
15317
|
+
(name) => ctx.entityCollection.prepareCreate((record3) => {
|
|
15318
|
+
record3._setRaw("canonical_name", name);
|
|
14823
15319
|
const kind = kindByName.get(name);
|
|
14824
|
-
if (kind !== void 0)
|
|
15320
|
+
if (kind !== void 0) record3._setRaw("kind", kind);
|
|
14825
15321
|
})
|
|
14826
15322
|
);
|
|
14827
15323
|
for (const e of existing) out.set(e.canonicalName, entityToStored(e));
|
|
14828
|
-
for (const
|
|
14829
|
-
for (const { record:
|
|
14830
|
-
out.set(
|
|
15324
|
+
for (const record3 of created) out.set(record3.canonicalName, entityToStored(record3));
|
|
15325
|
+
for (const { record: record3, kind } of kindBackfills) {
|
|
15326
|
+
out.set(record3.canonicalName, { ...entityToStored(record3), kind });
|
|
14831
15327
|
}
|
|
14832
15328
|
return { entities: out, operations: created, kindBackfills };
|
|
14833
15329
|
}
|
|
14834
15330
|
function prepareKindBackfills(backfills) {
|
|
14835
15331
|
return backfills.map(
|
|
14836
|
-
({ record:
|
|
15332
|
+
({ record: record3, kind }) => record3.prepareUpdate((r) => {
|
|
14837
15333
|
r._setRaw("kind", kind);
|
|
14838
15334
|
})
|
|
14839
15335
|
);
|
|
@@ -14961,10 +15457,10 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
14961
15457
|
return;
|
|
14962
15458
|
}
|
|
14963
15459
|
const linkOps = toCreate.map(
|
|
14964
|
-
(e) => ctx.memoryEntityCollection.prepareCreate((
|
|
14965
|
-
|
|
14966
|
-
|
|
14967
|
-
if (userId !== void 0)
|
|
15460
|
+
(e) => ctx.memoryEntityCollection.prepareCreate((record3) => {
|
|
15461
|
+
record3._setRaw("memory_id", memoryId);
|
|
15462
|
+
record3._setRaw("entity_id", e.uniqueId);
|
|
15463
|
+
if (userId !== void 0) record3._setRaw("user_id", userId);
|
|
14968
15464
|
})
|
|
14969
15465
|
);
|
|
14970
15466
|
await ctx.database.batch(
|
|
@@ -15034,10 +15530,10 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
|
|
|
15034
15530
|
...entityOps,
|
|
15035
15531
|
...prepareKindBackfills(kindBackfills),
|
|
15036
15532
|
...toCreate.map(
|
|
15037
|
-
(e) => ctx.memoryEntityCollection.prepareCreate((
|
|
15038
|
-
|
|
15039
|
-
|
|
15040
|
-
if (userId !== void 0)
|
|
15533
|
+
(e) => ctx.memoryEntityCollection.prepareCreate((record3) => {
|
|
15534
|
+
record3._setRaw("memory_id", memoryId);
|
|
15535
|
+
record3._setRaw("entity_id", e.uniqueId);
|
|
15536
|
+
if (userId !== void 0) record3._setRaw("user_id", userId);
|
|
15041
15537
|
})
|
|
15042
15538
|
),
|
|
15043
15539
|
...toDestroy.map((l) => l.prepareDestroyPermanently()),
|
|
@@ -16371,9 +16867,9 @@ var DatabaseManager = class {
|
|
|
16371
16867
|
*/
|
|
16372
16868
|
getDatabase(walletAddress) {
|
|
16373
16869
|
const dbName = this.getDbName(walletAddress);
|
|
16374
|
-
const
|
|
16375
|
-
if (
|
|
16376
|
-
return
|
|
16870
|
+
const cached2 = this.databases.get(dbName);
|
|
16871
|
+
if (cached2) {
|
|
16872
|
+
return cached2;
|
|
16377
16873
|
}
|
|
16378
16874
|
const needsMigration = this.handleSchemaMigration(walletAddress);
|
|
16379
16875
|
if (needsMigration) {
|
|
@@ -17508,8 +18004,8 @@ function visibilityConditions(requested) {
|
|
|
17508
18004
|
if (excluded.length === 0) return [];
|
|
17509
18005
|
return [Q9.or(Q9.where("visibility", null), Q9.where("visibility", Q9.notIn(excluded)))];
|
|
17510
18006
|
}
|
|
17511
|
-
function isKinded(
|
|
17512
|
-
return
|
|
18007
|
+
function isKinded(record3) {
|
|
18008
|
+
return record3.kind !== null && record3.kind !== void 0;
|
|
17513
18009
|
}
|
|
17514
18010
|
async function assertCanWrite2(ctx) {
|
|
17515
18011
|
if (ctx.canWrite && !await ctx.canWrite()) {
|
|
@@ -17563,8 +18059,8 @@ function levelConditions(requested) {
|
|
|
17563
18059
|
}
|
|
17564
18060
|
return [byLevel];
|
|
17565
18061
|
}
|
|
17566
|
-
function isOwnedByCtxUser(ctx,
|
|
17567
|
-
return ctx.userId === void 0 ||
|
|
18062
|
+
function isOwnedByCtxUser(ctx, record3) {
|
|
18063
|
+
return ctx.userId === void 0 || record3.userId === ctx.userId;
|
|
17568
18064
|
}
|
|
17569
18065
|
function baseVaultConditions(ctx, options) {
|
|
17570
18066
|
return [
|
|
@@ -17647,43 +18143,43 @@ async function vaultMemoryToStored(memory, walletAddress, signMessage, embeddedW
|
|
|
17647
18143
|
}
|
|
17648
18144
|
return raw;
|
|
17649
18145
|
}
|
|
17650
|
-
function populateNewVaultMemory(
|
|
18146
|
+
function populateNewVaultMemory(record3, ctx, opts, encryptedContent, encryptedKindValue) {
|
|
17651
18147
|
const { level, scope } = resolveCreateLevel(opts);
|
|
17652
|
-
|
|
17653
|
-
|
|
17654
|
-
|
|
17655
|
-
|
|
17656
|
-
|
|
17657
|
-
|
|
17658
|
-
|
|
17659
|
-
|
|
18148
|
+
record3._setRaw("content", encryptedContent);
|
|
18149
|
+
record3._setRaw("scope", scope);
|
|
18150
|
+
record3._setRaw("level", level);
|
|
18151
|
+
record3._setRaw("kind", opts.kind ?? null);
|
|
18152
|
+
record3._setRaw("kind_value", encryptedKindValue ?? null);
|
|
18153
|
+
record3._setRaw("folder_id", opts.folderId ?? null);
|
|
18154
|
+
record3._setRaw("user_id", ctx.userId ?? null);
|
|
18155
|
+
record3._setRaw("is_deleted", false);
|
|
17660
18156
|
if (opts.embedding !== void 0) {
|
|
17661
|
-
|
|
17662
|
-
|
|
18157
|
+
record3._setRaw("embedding", opts.embedding);
|
|
18158
|
+
record3._setRaw("embedding_model", opts.embeddingModel ?? null);
|
|
17663
18159
|
}
|
|
17664
18160
|
if (opts.sourceChunkIds !== void 0) {
|
|
17665
|
-
|
|
18161
|
+
record3._setRaw("source_chunk_ids", serializeSourceChunkIds(opts.sourceChunkIds));
|
|
17666
18162
|
}
|
|
17667
|
-
|
|
17668
|
-
|
|
18163
|
+
record3._setRaw("proof_count", opts.proofCount ?? 1);
|
|
18164
|
+
record3._setRaw("source", opts.source ?? "manual");
|
|
17669
18165
|
if (opts.eventTime) {
|
|
17670
|
-
|
|
17671
|
-
|
|
17672
|
-
|
|
18166
|
+
record3._setRaw("event_time_start", opts.eventTime.start ?? null);
|
|
18167
|
+
record3._setRaw("event_time_end", opts.eventTime.end ?? null);
|
|
18168
|
+
record3._setRaw("event_time_kind", opts.eventTime.kind ?? null);
|
|
17673
18169
|
}
|
|
17674
18170
|
if (opts.factType !== void 0) {
|
|
17675
|
-
|
|
18171
|
+
record3._setRaw("fact_type", opts.factType);
|
|
17676
18172
|
}
|
|
17677
18173
|
if (opts.trustTier !== void 0) {
|
|
17678
|
-
|
|
18174
|
+
record3._setRaw("trust_tier", normalizeTrustTier(opts.trustTier));
|
|
17679
18175
|
}
|
|
17680
|
-
|
|
17681
|
-
|
|
18176
|
+
record3._setRaw("visibility", opts.visibility ?? "private");
|
|
18177
|
+
record3._setRaw(
|
|
17682
18178
|
"published_at",
|
|
17683
18179
|
opts.visibility && opts.visibility !== "private" ? opts.publishedAt ?? Date.now() : null
|
|
17684
18180
|
);
|
|
17685
18181
|
if (opts.geohash !== void 0) {
|
|
17686
|
-
|
|
18182
|
+
record3._setRaw("geohash", opts.geohash);
|
|
17687
18183
|
}
|
|
17688
18184
|
}
|
|
17689
18185
|
async function createVaultMemoryOp(ctx, opts) {
|
|
@@ -17698,7 +18194,7 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
17698
18194
|
const created = await ctx.database.write(async () => {
|
|
17699
18195
|
await assertCanWrite2(ctx);
|
|
17700
18196
|
return ctx.vaultMemoryCollection.create(
|
|
17701
|
-
(
|
|
18197
|
+
(record3) => populateNewVaultMemory(record3, ctx, opts, encryptedContent, encryptedKindValue)
|
|
17702
18198
|
);
|
|
17703
18199
|
});
|
|
17704
18200
|
return vaultMemoryToStored(created, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
@@ -17725,7 +18221,7 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
|
17725
18221
|
if (target.isDeleted || target.supersededBy || isKinded(target) || !isOwnedByCtxUser(ctx, target))
|
|
17726
18222
|
return;
|
|
17727
18223
|
createdRecord = await ctx.vaultMemoryCollection.create(
|
|
17728
|
-
(
|
|
18224
|
+
(record3) => populateNewVaultMemory(record3, ctx, opts, encryptedContent, encryptedKindValue)
|
|
17729
18225
|
);
|
|
17730
18226
|
await target.update((r) => {
|
|
17731
18227
|
r._setRaw("superseded_by", createdRecord.id);
|
|
@@ -17810,7 +18306,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
17810
18306
|
await assertCanWrite2(ctx);
|
|
17811
18307
|
const prepared = optionsArray.map(
|
|
17812
18308
|
(opts, i) => ctx.vaultMemoryCollection.prepareCreate(
|
|
17813
|
-
(
|
|
18309
|
+
(record3) => populateNewVaultMemory(record3, ctx, opts, encryptedContents[i], encryptedKindValues[i])
|
|
17814
18310
|
)
|
|
17815
18311
|
);
|
|
17816
18312
|
await ctx.database.batch(...prepared);
|
|
@@ -17818,16 +18314,16 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
17818
18314
|
});
|
|
17819
18315
|
return Promise.all(
|
|
17820
18316
|
created.map(
|
|
17821
|
-
(
|
|
18317
|
+
(record3) => vaultMemoryToStored(record3, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
17822
18318
|
)
|
|
17823
18319
|
);
|
|
17824
18320
|
}
|
|
17825
18321
|
async function getVaultMemoryOp(ctx, id2) {
|
|
17826
18322
|
try {
|
|
17827
|
-
const
|
|
17828
|
-
if (
|
|
18323
|
+
const record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
18324
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return null;
|
|
17829
18325
|
return vaultMemoryToStored(
|
|
17830
|
-
|
|
18326
|
+
record3,
|
|
17831
18327
|
ctx.walletAddress,
|
|
17832
18328
|
ctx.signMessage,
|
|
17833
18329
|
ctx.embeddedWalletSigner
|
|
@@ -18166,29 +18662,29 @@ async function updateVaultMemoryOp(ctx, id2, opts) {
|
|
|
18166
18662
|
ctx.embeddedWalletSigner
|
|
18167
18663
|
) : opts.content;
|
|
18168
18664
|
let stale = false;
|
|
18169
|
-
const
|
|
18665
|
+
const record3 = probe;
|
|
18170
18666
|
await ctx.database.write(async () => {
|
|
18171
18667
|
await assertCanWrite2(ctx);
|
|
18172
|
-
if (
|
|
18668
|
+
if (record3.isDeleted || record3.supersededBy || !isOwnedByCtxUser(ctx, record3) || opts.freeFormOnly && isKinded(record3) || opts.expectedContent !== void 0 && record3._getRaw("content") !== readStoredContent) {
|
|
18173
18669
|
stale = true;
|
|
18174
18670
|
return;
|
|
18175
18671
|
}
|
|
18176
|
-
const originalUpdatedAt =
|
|
18177
|
-
const nextKind = opts.kind !== void 0 ? opts.kind :
|
|
18178
|
-
const nextLevel = levelAfter(
|
|
18672
|
+
const originalUpdatedAt = record3.updatedAt.getTime();
|
|
18673
|
+
const nextKind = opts.kind !== void 0 ? opts.kind : record3.kind;
|
|
18674
|
+
const nextLevel = levelAfter(record3);
|
|
18179
18675
|
assertValidKindLevel(nextKind, nextLevel);
|
|
18180
18676
|
let observedSources = [];
|
|
18181
18677
|
let replayedObservation = false;
|
|
18182
18678
|
if (opts.observationSourceIds?.length) {
|
|
18183
18679
|
try {
|
|
18184
|
-
const parsed = JSON.parse(
|
|
18680
|
+
const parsed = JSON.parse(record3.sourceChunkIds ?? "[]");
|
|
18185
18681
|
if (Array.isArray(parsed))
|
|
18186
18682
|
observedSources = parsed.filter((id3) => typeof id3 === "string");
|
|
18187
18683
|
} catch {
|
|
18188
18684
|
}
|
|
18189
18685
|
replayedObservation = opts.observationSourceIds.every((id3) => observedSources.includes(id3));
|
|
18190
18686
|
}
|
|
18191
|
-
await
|
|
18687
|
+
await record3.update((r) => {
|
|
18192
18688
|
if (encryptedContent !== void 0) r._setRaw("content", encryptedContent);
|
|
18193
18689
|
if (opts.level !== void 0) {
|
|
18194
18690
|
r._setRaw("level", nextLevel);
|
|
@@ -18255,7 +18751,7 @@ async function updateVaultMemoryOp(ctx, id2, opts) {
|
|
|
18255
18751
|
});
|
|
18256
18752
|
if (stale) return null;
|
|
18257
18753
|
return vaultMemoryToStored(
|
|
18258
|
-
|
|
18754
|
+
record3,
|
|
18259
18755
|
ctx.walletAddress,
|
|
18260
18756
|
ctx.signMessage,
|
|
18261
18757
|
ctx.embeddedWalletSigner
|
|
@@ -18270,22 +18766,22 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
18270
18766
|
if (!entityCtx) {
|
|
18271
18767
|
throw new Error("setMemoryEntitiesOp requires ctx.entityCtx (entity collections)");
|
|
18272
18768
|
}
|
|
18273
|
-
let
|
|
18769
|
+
let record3;
|
|
18274
18770
|
try {
|
|
18275
|
-
|
|
18771
|
+
record3 = await ctx.vaultMemoryCollection.find(memoryId);
|
|
18276
18772
|
} catch {
|
|
18277
18773
|
return null;
|
|
18278
18774
|
}
|
|
18279
|
-
if (
|
|
18775
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return null;
|
|
18280
18776
|
let stale = false;
|
|
18281
|
-
const originalUpdatedAt =
|
|
18777
|
+
const originalUpdatedAt = record3.updatedAt.getTime();
|
|
18282
18778
|
await ctx.database.write(async (writer) => {
|
|
18283
18779
|
await assertCanWrite2(ctx);
|
|
18284
|
-
if (
|
|
18780
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) {
|
|
18285
18781
|
stale = true;
|
|
18286
18782
|
return;
|
|
18287
18783
|
}
|
|
18288
|
-
await
|
|
18784
|
+
await record3.update((r) => {
|
|
18289
18785
|
r._setRaw("topics_user_managed", true);
|
|
18290
18786
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
18291
18787
|
});
|
|
@@ -18309,26 +18805,26 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
18309
18805
|
);
|
|
18310
18806
|
});
|
|
18311
18807
|
if (stale) return null;
|
|
18312
|
-
return vaultMemoryToStored(
|
|
18808
|
+
return vaultMemoryToStored(record3, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
18313
18809
|
}
|
|
18314
18810
|
async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
18315
|
-
let
|
|
18811
|
+
let record3;
|
|
18316
18812
|
try {
|
|
18317
|
-
|
|
18813
|
+
record3 = await ctx.vaultMemoryCollection.find(memoryId);
|
|
18318
18814
|
} catch {
|
|
18319
18815
|
return false;
|
|
18320
18816
|
}
|
|
18321
|
-
if (
|
|
18322
|
-
const originalUpdatedAt =
|
|
18817
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return false;
|
|
18818
|
+
const originalUpdatedAt = record3.updatedAt.getTime();
|
|
18323
18819
|
let cleared = false;
|
|
18324
18820
|
await ctx.database.write(async () => {
|
|
18325
18821
|
await assertCanWrite2(ctx);
|
|
18326
|
-
if (options?.unlessTopicsRecorded && parseTopics(
|
|
18822
|
+
if (options?.unlessTopicsRecorded && parseTopics(record3.topics) !== null) return;
|
|
18327
18823
|
cleared = true;
|
|
18328
|
-
await
|
|
18824
|
+
await record3.update((r) => {
|
|
18329
18825
|
r._setRaw("topics_user_managed", false);
|
|
18330
18826
|
r._setRaw("topics_extracted_version", null);
|
|
18331
|
-
if (
|
|
18827
|
+
if (record3.topicsExtractedAt === null) {
|
|
18332
18828
|
r._setRaw("topics_extracted_at", originalUpdatedAt);
|
|
18333
18829
|
}
|
|
18334
18830
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
@@ -18337,23 +18833,23 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
|
18337
18833
|
return cleared;
|
|
18338
18834
|
}
|
|
18339
18835
|
async function setMemoryVisibilityOp(ctx, id2, opts) {
|
|
18340
|
-
let
|
|
18836
|
+
let record3;
|
|
18341
18837
|
try {
|
|
18342
|
-
|
|
18838
|
+
record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
18343
18839
|
} catch {
|
|
18344
18840
|
return null;
|
|
18345
18841
|
}
|
|
18346
|
-
if (
|
|
18842
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return null;
|
|
18347
18843
|
let stale = false;
|
|
18348
18844
|
await ctx.database.write(async () => {
|
|
18349
18845
|
await assertCanWrite2(ctx);
|
|
18350
|
-
if (
|
|
18846
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) {
|
|
18351
18847
|
stale = true;
|
|
18352
18848
|
return;
|
|
18353
18849
|
}
|
|
18354
|
-
const currentUpdatedAt =
|
|
18355
|
-
const currentPublishedAt =
|
|
18356
|
-
await
|
|
18850
|
+
const currentUpdatedAt = record3.updatedAt.getTime();
|
|
18851
|
+
const currentPublishedAt = record3.publishedAt ?? null;
|
|
18852
|
+
await record3.update((r) => {
|
|
18357
18853
|
r._setRaw("visibility", opts.visibility);
|
|
18358
18854
|
if (opts.visibility === "private") {
|
|
18359
18855
|
r._setRaw("published_at", null);
|
|
@@ -18367,20 +18863,20 @@ async function setMemoryVisibilityOp(ctx, id2, opts) {
|
|
|
18367
18863
|
});
|
|
18368
18864
|
});
|
|
18369
18865
|
if (stale) return null;
|
|
18370
|
-
return vaultMemoryToStored(
|
|
18866
|
+
return vaultMemoryToStored(record3, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
18371
18867
|
}
|
|
18372
18868
|
async function deleteVaultMemoryOp(ctx, id2) {
|
|
18373
18869
|
try {
|
|
18374
|
-
const
|
|
18375
|
-
if (
|
|
18870
|
+
const record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
18871
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return false;
|
|
18376
18872
|
let stale = false;
|
|
18377
18873
|
await ctx.database.write(async () => {
|
|
18378
18874
|
await assertCanWrite2(ctx);
|
|
18379
|
-
if (
|
|
18875
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) {
|
|
18380
18876
|
stale = true;
|
|
18381
18877
|
return;
|
|
18382
18878
|
}
|
|
18383
|
-
await
|
|
18879
|
+
await record3.update((r) => {
|
|
18384
18880
|
r._setRaw("is_deleted", true);
|
|
18385
18881
|
});
|
|
18386
18882
|
});
|
|
@@ -18399,9 +18895,9 @@ async function deleteVaultMemoryOp(ctx, id2) {
|
|
|
18399
18895
|
async function supersedeVaultMemoryOp(ctx, id2, supersededById) {
|
|
18400
18896
|
if (id2 === supersededById) return false;
|
|
18401
18897
|
try {
|
|
18402
|
-
const
|
|
18403
|
-
if (
|
|
18404
|
-
if (isKinded(
|
|
18898
|
+
const record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
18899
|
+
if (record3.isDeleted || record3.supersededBy || !isOwnedByCtxUser(ctx, record3)) return false;
|
|
18900
|
+
if (isKinded(record3)) return false;
|
|
18405
18901
|
let successor;
|
|
18406
18902
|
try {
|
|
18407
18903
|
successor = await ctx.vaultMemoryCollection.find(supersededById);
|
|
@@ -18414,7 +18910,7 @@ async function supersedeVaultMemoryOp(ctx, id2, supersededById) {
|
|
|
18414
18910
|
let stale = false;
|
|
18415
18911
|
await ctx.database.write(async () => {
|
|
18416
18912
|
await assertCanWrite2(ctx);
|
|
18417
|
-
if (
|
|
18913
|
+
if (record3.isDeleted || record3.supersededBy || !isOwnedByCtxUser(ctx, record3)) {
|
|
18418
18914
|
stale = true;
|
|
18419
18915
|
return;
|
|
18420
18916
|
}
|
|
@@ -18422,7 +18918,7 @@ async function supersedeVaultMemoryOp(ctx, id2, supersededById) {
|
|
|
18422
18918
|
stale = true;
|
|
18423
18919
|
return;
|
|
18424
18920
|
}
|
|
18425
|
-
await
|
|
18921
|
+
await record3.update((r) => {
|
|
18426
18922
|
r._setRaw("superseded_by", supersededById);
|
|
18427
18923
|
r._setRaw("superseded_at", Date.now());
|
|
18428
18924
|
});
|
|
@@ -18441,7 +18937,7 @@ async function getUnfiledVaultMemoriesOp(ctx) {
|
|
|
18441
18937
|
const results = await ctx.vaultMemoryCollection.query(...conditions).fetch();
|
|
18442
18938
|
return mapInBatches(
|
|
18443
18939
|
results,
|
|
18444
|
-
(
|
|
18940
|
+
(record3) => vaultMemoryToStored(record3, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
18445
18941
|
);
|
|
18446
18942
|
}
|
|
18447
18943
|
var TOPICS_EXTRACTION_VERSION = 3;
|
|
@@ -18602,17 +19098,17 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
|
|
|
18602
19098
|
}
|
|
18603
19099
|
}
|
|
18604
19100
|
const eligible = records.filter(
|
|
18605
|
-
(
|
|
19101
|
+
(record3) => !record3.isDeleted && isOwnedByCtxUser(ctx, record3) && !record3.topicsUserManaged
|
|
18606
19102
|
);
|
|
18607
|
-
const prepared = eligible.map((
|
|
18608
|
-
const originalUpdatedAt =
|
|
18609
|
-
return
|
|
19103
|
+
const prepared = eligible.map((record3) => {
|
|
19104
|
+
const originalUpdatedAt = record3.updatedAt.getTime();
|
|
19105
|
+
return record3.prepareUpdate((r) => {
|
|
18610
19106
|
r._setRaw("topics_extracted_at", extractedAt);
|
|
18611
19107
|
r._setRaw("topics_extracted_version", version);
|
|
18612
19108
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
18613
19109
|
});
|
|
18614
19110
|
});
|
|
18615
|
-
for (const
|
|
19111
|
+
for (const record3 of eligible) stamped.push(record3.id);
|
|
18616
19112
|
if (prepared.length > 0) await ctx.database.batch(...prepared);
|
|
18617
19113
|
});
|
|
18618
19114
|
}
|
|
@@ -18628,14 +19124,14 @@ async function relinkMemoryTopicsOp(ctx, memoryIds) {
|
|
|
18628
19124
|
try {
|
|
18629
19125
|
await ctx.database.write(async (writer) => {
|
|
18630
19126
|
await assertCanWrite2(ctx);
|
|
18631
|
-
let
|
|
19127
|
+
let record3;
|
|
18632
19128
|
try {
|
|
18633
|
-
|
|
19129
|
+
record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
18634
19130
|
} catch {
|
|
18635
19131
|
return;
|
|
18636
19132
|
}
|
|
18637
|
-
if (
|
|
18638
|
-
const topics = parseTopics(
|
|
19133
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return;
|
|
19134
|
+
const topics = parseTopics(record3.topics);
|
|
18639
19135
|
if (topics === null) return;
|
|
18640
19136
|
await writer.callWriter(() => relinkMemoryEntitiesFromTopicsOp(entityCtx, id2, topics));
|
|
18641
19137
|
relinked.push(id2);
|
|
@@ -18661,18 +19157,18 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
|
18661
19157
|
await assertCanWrite2(ctx);
|
|
18662
19158
|
const records = [];
|
|
18663
19159
|
for (const id2 of chunkIds) {
|
|
18664
|
-
let
|
|
19160
|
+
let record3;
|
|
18665
19161
|
try {
|
|
18666
|
-
|
|
19162
|
+
record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
18667
19163
|
} catch {
|
|
18668
19164
|
continue;
|
|
18669
19165
|
}
|
|
18670
|
-
if (
|
|
18671
|
-
if (parseTopics(
|
|
18672
|
-
records.push(
|
|
19166
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) continue;
|
|
19167
|
+
if (parseTopics(record3.topics) !== null) continue;
|
|
19168
|
+
records.push(record3);
|
|
18673
19169
|
}
|
|
18674
19170
|
if (records.length === 0) return;
|
|
18675
|
-
const links2 = await entityCtx.memoryEntityCollection.query(Q9.where("memory_id", Q9.oneOf(records.map((
|
|
19171
|
+
const links2 = await entityCtx.memoryEntityCollection.query(Q9.where("memory_id", Q9.oneOf(records.map((record3) => record3.id)))).unsafeFetchRaw();
|
|
18676
19172
|
const entityIds = Array.from(new Set(links2.map((link) => String(link.entity_id))));
|
|
18677
19173
|
const entitiesById = /* @__PURE__ */ new Map();
|
|
18678
19174
|
for (let j = 0; j < entityIds.length; j += CHUNK) {
|
|
@@ -18692,13 +19188,13 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
|
18692
19188
|
entities.add(entity);
|
|
18693
19189
|
}
|
|
18694
19190
|
const writes = [];
|
|
18695
|
-
for (const
|
|
18696
|
-
const entities = entitiesByMemory.get(
|
|
19191
|
+
for (const record3 of records) {
|
|
19192
|
+
const entities = entitiesByMemory.get(record3.id);
|
|
18697
19193
|
if (!entities?.size) continue;
|
|
18698
|
-
const source =
|
|
19194
|
+
const source = record3.topicsUserManaged ? "user" : "auto";
|
|
18699
19195
|
const write = await resolveMemoryTopicsWrite(
|
|
18700
19196
|
entityCtx,
|
|
18701
|
-
|
|
19197
|
+
record3.id,
|
|
18702
19198
|
Array.from(entities),
|
|
18703
19199
|
[],
|
|
18704
19200
|
source
|
|
@@ -18720,7 +19216,7 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
|
|
|
18720
19216
|
await ctx.database.write(async () => {
|
|
18721
19217
|
await assertCanWrite2(ctx);
|
|
18722
19218
|
const prepared = records.map(
|
|
18723
|
-
(
|
|
19219
|
+
(record3) => record3.prepareUpdate((r) => {
|
|
18724
19220
|
r._setRaw("is_deleted", true);
|
|
18725
19221
|
})
|
|
18726
19222
|
);
|
|
@@ -18791,22 +19287,22 @@ async function applyDecayTransitionsOp(ctx, candidates, opts) {
|
|
|
18791
19287
|
Q9.where("id", Q9.oneOf(ids.slice(i, i + CHUNK))),
|
|
18792
19288
|
...ctx.userId !== void 0 ? [Q9.where("user_id", ctx.userId)] : []
|
|
18793
19289
|
).fetch();
|
|
18794
|
-
const eligible = records.filter((
|
|
18795
|
-
if (
|
|
19290
|
+
const eligible = records.filter((record3) => {
|
|
19291
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return false;
|
|
18796
19292
|
if (opts.transition === "delete") {
|
|
18797
|
-
return
|
|
19293
|
+
return record3.archivedAt !== null && opts.now - record3.archivedAt > opts.hardDeleteWindowMs;
|
|
18798
19294
|
}
|
|
18799
|
-
const candidate = byId.get(
|
|
18800
|
-
return
|
|
19295
|
+
const candidate = byId.get(record3.id);
|
|
19296
|
+
return record3.archivedAt === null && record3.updatedAt.getTime() === candidate.updatedAt && (record3.lastObservedAt ?? null) === (candidate.lastObservedAt ?? null);
|
|
18801
19297
|
});
|
|
18802
19298
|
const prepared = eligible.map(
|
|
18803
|
-
(
|
|
19299
|
+
(record3) => record3.prepareUpdate((row) => {
|
|
18804
19300
|
if (opts.transition === "archive") row._setRaw("archived_at", opts.now);
|
|
18805
19301
|
else row._setRaw("is_deleted", true);
|
|
18806
19302
|
})
|
|
18807
19303
|
);
|
|
18808
19304
|
if (prepared.length > 0) await ctx.database.batch(prepared);
|
|
18809
|
-
applied = eligible.map((
|
|
19305
|
+
applied = eligible.map((record3) => record3.id);
|
|
18810
19306
|
});
|
|
18811
19307
|
} catch {
|
|
18812
19308
|
continue;
|
|
@@ -18824,21 +19320,21 @@ async function applyDecayTransitionsOp(ctx, candidates, opts) {
|
|
|
18824
19320
|
}
|
|
18825
19321
|
async function archiveVaultMemoryOp(ctx, id2, opts) {
|
|
18826
19322
|
try {
|
|
18827
|
-
const
|
|
18828
|
-
if (
|
|
19323
|
+
const record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
19324
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return false;
|
|
18829
19325
|
let stale = false;
|
|
18830
19326
|
const archivedAtValue = opts?.now ?? Date.now();
|
|
18831
19327
|
await ctx.database.write(async () => {
|
|
18832
19328
|
await assertCanWrite2(ctx);
|
|
18833
|
-
if (
|
|
19329
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3) || record3.archivedAt !== null) {
|
|
18834
19330
|
stale = true;
|
|
18835
19331
|
return;
|
|
18836
19332
|
}
|
|
18837
|
-
if (opts?.expectedUpdatedAt !== void 0 &&
|
|
19333
|
+
if (opts?.expectedUpdatedAt !== void 0 && record3.updatedAt.getTime() !== opts.expectedUpdatedAt || opts?.expectedLastObservedAt !== void 0 && (record3.lastObservedAt ?? null) !== opts.expectedLastObservedAt) {
|
|
18838
19334
|
stale = true;
|
|
18839
19335
|
return;
|
|
18840
19336
|
}
|
|
18841
|
-
await
|
|
19337
|
+
await record3.update((r) => {
|
|
18842
19338
|
r._setRaw("archived_at", archivedAtValue);
|
|
18843
19339
|
});
|
|
18844
19340
|
});
|
|
@@ -18849,16 +19345,16 @@ async function archiveVaultMemoryOp(ctx, id2, opts) {
|
|
|
18849
19345
|
}
|
|
18850
19346
|
async function restoreVaultMemoryOp(ctx, id2) {
|
|
18851
19347
|
try {
|
|
18852
|
-
const
|
|
18853
|
-
if (
|
|
19348
|
+
const record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
19349
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return false;
|
|
18854
19350
|
let stale = false;
|
|
18855
19351
|
await ctx.database.write(async () => {
|
|
18856
19352
|
await assertCanWrite2(ctx);
|
|
18857
|
-
if (
|
|
19353
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) {
|
|
18858
19354
|
stale = true;
|
|
18859
19355
|
return;
|
|
18860
19356
|
}
|
|
18861
|
-
await
|
|
19357
|
+
await record3.update((r) => {
|
|
18862
19358
|
r._setRaw("archived_at", null);
|
|
18863
19359
|
});
|
|
18864
19360
|
});
|
|
@@ -18869,18 +19365,18 @@ async function restoreVaultMemoryOp(ctx, id2) {
|
|
|
18869
19365
|
}
|
|
18870
19366
|
async function hardDeleteDecayedOp(ctx, id2, opts) {
|
|
18871
19367
|
try {
|
|
18872
|
-
const
|
|
18873
|
-
if (
|
|
19368
|
+
const record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
19369
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return false;
|
|
18874
19370
|
const now = opts.now ?? Date.now();
|
|
18875
19371
|
let stale = false;
|
|
18876
19372
|
await ctx.database.write(async () => {
|
|
18877
19373
|
await assertCanWrite2(ctx);
|
|
18878
|
-
const archivedAt =
|
|
18879
|
-
if (
|
|
19374
|
+
const archivedAt = record3.archivedAt;
|
|
19375
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
|
|
18880
19376
|
stale = true;
|
|
18881
19377
|
return;
|
|
18882
19378
|
}
|
|
18883
|
-
await
|
|
19379
|
+
await record3.update((r) => {
|
|
18884
19380
|
r._setRaw("is_deleted", true);
|
|
18885
19381
|
});
|
|
18886
19382
|
});
|
|
@@ -18898,14 +19394,14 @@ async function hardDeleteDecayedOp(ctx, id2, opts) {
|
|
|
18898
19394
|
}
|
|
18899
19395
|
async function updateVaultMemoryEmbeddingOp(ctx, id2, embedding2, embeddingModel, expected) {
|
|
18900
19396
|
try {
|
|
18901
|
-
const
|
|
18902
|
-
if (
|
|
18903
|
-
const readUpdatedAt =
|
|
18904
|
-
const readStoredContent =
|
|
19397
|
+
const record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
19398
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return false;
|
|
19399
|
+
const readUpdatedAt = record3.updatedAt.getTime();
|
|
19400
|
+
const readStoredContent = record3._getRaw("content");
|
|
18905
19401
|
if (expected?.updatedAt !== void 0 && expected.updatedAt !== readUpdatedAt) return false;
|
|
18906
19402
|
if (expected?.content !== void 0) {
|
|
18907
19403
|
const current = await vaultMemoryToStored(
|
|
18908
|
-
|
|
19404
|
+
record3,
|
|
18909
19405
|
ctx.walletAddress,
|
|
18910
19406
|
ctx.signMessage,
|
|
18911
19407
|
ctx.embeddedWalletSigner
|
|
@@ -18915,11 +19411,11 @@ async function updateVaultMemoryEmbeddingOp(ctx, id2, embedding2, embeddingModel
|
|
|
18915
19411
|
let written = false;
|
|
18916
19412
|
await ctx.database.write(async () => {
|
|
18917
19413
|
await assertCanWrite2(ctx);
|
|
18918
|
-
if (
|
|
18919
|
-
const originalUpdatedAt =
|
|
18920
|
-
if (originalUpdatedAt !== readUpdatedAt ||
|
|
19414
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return;
|
|
19415
|
+
const originalUpdatedAt = record3.updatedAt.getTime();
|
|
19416
|
+
if (originalUpdatedAt !== readUpdatedAt || record3._getRaw("content") !== readStoredContent)
|
|
18921
19417
|
return;
|
|
18922
|
-
await
|
|
19418
|
+
await record3.update((r) => {
|
|
18923
19419
|
r._setRaw("embedding", embedding2);
|
|
18924
19420
|
r._setRaw("embedding_model", embeddingModel);
|
|
18925
19421
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
@@ -19083,26 +19579,26 @@ async function ingestPublishedPhotoMemoriesOp(ctx, rows) {
|
|
|
19083
19579
|
inserted = writable.length;
|
|
19084
19580
|
if (writable.length === 0) return;
|
|
19085
19581
|
const prepared = writable.map(
|
|
19086
|
-
({ row, content }) => ctx.vaultMemoryCollection.prepareCreate((
|
|
19087
|
-
|
|
19088
|
-
|
|
19089
|
-
|
|
19090
|
-
|
|
19091
|
-
|
|
19092
|
-
|
|
19093
|
-
|
|
19094
|
-
|
|
19095
|
-
|
|
19096
|
-
|
|
19582
|
+
({ row, content }) => ctx.vaultMemoryCollection.prepareCreate((record3) => {
|
|
19583
|
+
record3._raw.id = row.memoryId;
|
|
19584
|
+
record3._setRaw("content", content);
|
|
19585
|
+
record3._setRaw("scope", "shared");
|
|
19586
|
+
record3._setRaw("level", "matching");
|
|
19587
|
+
record3._setRaw("folder_id", null);
|
|
19588
|
+
record3._setRaw("user_id", ctx.userId ?? null);
|
|
19589
|
+
record3._setRaw("is_deleted", false);
|
|
19590
|
+
record3._setRaw("proof_count", 1);
|
|
19591
|
+
record3._setRaw("source", SOURCE_PHOTO);
|
|
19592
|
+
record3._setRaw(
|
|
19097
19593
|
"media",
|
|
19098
19594
|
row.media && row.media.length > 0 ? JSON.stringify(row.media) : null
|
|
19099
19595
|
);
|
|
19100
|
-
|
|
19101
|
-
|
|
19596
|
+
record3._setRaw("visibility", "public");
|
|
19597
|
+
record3._setRaw("published_at", now);
|
|
19102
19598
|
if (row.eventTime) {
|
|
19103
|
-
|
|
19104
|
-
|
|
19105
|
-
|
|
19599
|
+
record3._setRaw("event_time_start", row.eventTime.start ?? null);
|
|
19600
|
+
record3._setRaw("event_time_end", row.eventTime.end ?? null);
|
|
19601
|
+
record3._setRaw("event_time_kind", row.eventTime.kind ?? null);
|
|
19106
19602
|
}
|
|
19107
19603
|
})
|
|
19108
19604
|
);
|
|
@@ -19933,11 +20429,11 @@ function folderToStored(folder) {
|
|
|
19933
20429
|
}
|
|
19934
20430
|
async function createVaultFolderOp(ctx, opts) {
|
|
19935
20431
|
const created = await ctx.database.write(async () => {
|
|
19936
|
-
return ctx.vaultFolderCollection.create((
|
|
19937
|
-
|
|
19938
|
-
|
|
19939
|
-
|
|
19940
|
-
|
|
20432
|
+
return ctx.vaultFolderCollection.create((record3) => {
|
|
20433
|
+
record3._setRaw("name", opts.name);
|
|
20434
|
+
record3._setRaw("scope", opts.scope ?? "private");
|
|
20435
|
+
record3._setRaw("is_system", opts.isSystem ?? false);
|
|
20436
|
+
record3._setRaw("is_deleted", false);
|
|
19941
20437
|
});
|
|
19942
20438
|
});
|
|
19943
20439
|
return folderToStored(created);
|
|
@@ -19948,14 +20444,14 @@ async function getAllVaultFoldersOp(ctx) {
|
|
|
19948
20444
|
}
|
|
19949
20445
|
async function updateVaultFolderOp(ctx, id2, opts) {
|
|
19950
20446
|
try {
|
|
19951
|
-
const
|
|
19952
|
-
if (
|
|
19953
|
-
const scopeChanged = opts.scope !== void 0 && opts.scope !==
|
|
20447
|
+
const record3 = await ctx.vaultFolderCollection.find(id2);
|
|
20448
|
+
if (record3.isDeleted) return null;
|
|
20449
|
+
const scopeChanged = opts.scope !== void 0 && opts.scope !== record3.scope;
|
|
19954
20450
|
const updated = await ctx.database.write(async () => {
|
|
19955
20451
|
const memories = scopeChanged ? await ctx.vaultMemoryCollection.query(Q15.where("folder_id", id2), Q15.where("is_deleted", false)).fetch() : [];
|
|
19956
20452
|
const updates = [];
|
|
19957
20453
|
updates.push(
|
|
19958
|
-
|
|
20454
|
+
record3.prepareUpdate((r) => {
|
|
19959
20455
|
if (opts.name !== void 0) r._setRaw("name", opts.name);
|
|
19960
20456
|
if (opts.scope !== void 0) r._setRaw("scope", opts.scope);
|
|
19961
20457
|
})
|
|
@@ -19978,8 +20474,8 @@ async function updateVaultFolderOp(ctx, id2, opts) {
|
|
|
19978
20474
|
}
|
|
19979
20475
|
async function deleteVaultFolderOp(ctx, id2) {
|
|
19980
20476
|
try {
|
|
19981
|
-
const
|
|
19982
|
-
if (
|
|
20477
|
+
const record3 = await ctx.vaultFolderCollection.find(id2);
|
|
20478
|
+
if (record3.isDeleted) return false;
|
|
19983
20479
|
await ctx.database.write(async () => {
|
|
19984
20480
|
const memories = await ctx.vaultMemoryCollection.query(Q15.where("folder_id", id2), Q15.where("is_deleted", false)).fetch();
|
|
19985
20481
|
const preparedMemories = memories.map(
|
|
@@ -19989,7 +20485,7 @@ async function deleteVaultFolderOp(ctx, id2) {
|
|
|
19989
20485
|
r._setRaw("scope", "private");
|
|
19990
20486
|
})
|
|
19991
20487
|
);
|
|
19992
|
-
const preparedFolder =
|
|
20488
|
+
const preparedFolder = record3.prepareUpdate((r) => {
|
|
19993
20489
|
r._setRaw("is_deleted", true);
|
|
19994
20490
|
});
|
|
19995
20491
|
await ctx.database.batch(...preparedMemories, preparedFolder);
|
|
@@ -20036,11 +20532,11 @@ async function moveMemoriesToFolderOp(ctx, memoryIds, folderId) {
|
|
|
20036
20532
|
}
|
|
20037
20533
|
async function updateVaultFolderContextOp(ctx, id2, context) {
|
|
20038
20534
|
try {
|
|
20039
|
-
const
|
|
20040
|
-
if (
|
|
20535
|
+
const record3 = await ctx.vaultFolderCollection.find(id2);
|
|
20536
|
+
if (record3.isDeleted) return null;
|
|
20041
20537
|
const updated = await ctx.database.write(async () => {
|
|
20042
20538
|
await ctx.database.batch(
|
|
20043
|
-
|
|
20539
|
+
record3.prepareUpdate((r) => {
|
|
20044
20540
|
r._setRaw("context", context);
|
|
20045
20541
|
})
|
|
20046
20542
|
);
|
|
@@ -21134,9 +21630,9 @@ function loadVaultCorpus(ctx, options, preparation) {
|
|
|
21134
21630
|
const key3 = JSON.stringify(options ?? {});
|
|
21135
21631
|
let request = pending.get(key3);
|
|
21136
21632
|
if (!request) {
|
|
21137
|
-
const
|
|
21633
|
+
const entries2 = pending;
|
|
21138
21634
|
request = getAllVaultMemoriesOp(ctx, options).catch((error) => {
|
|
21139
|
-
|
|
21635
|
+
entries2.delete(key3);
|
|
21140
21636
|
throw error;
|
|
21141
21637
|
});
|
|
21142
21638
|
pending.set(key3, request);
|
|
@@ -21177,7 +21673,7 @@ function embedVaultRows(ctx, options, rows, preparation) {
|
|
|
21177
21673
|
if (!pending.has(keys[index]) && !prepared?.has(keys[index])) missing2.set(keys[index], row);
|
|
21178
21674
|
});
|
|
21179
21675
|
if (missing2.size > 0) {
|
|
21180
|
-
const
|
|
21676
|
+
const entries2 = pending;
|
|
21181
21677
|
const batch = Promise.resolve().then(
|
|
21182
21678
|
() => generateEmbeddings(
|
|
21183
21679
|
[...missing2.values()].map((row) => row.content),
|
|
@@ -21194,16 +21690,16 @@ function embedVaultRows(ctx, options, rows, preparation) {
|
|
|
21194
21690
|
});
|
|
21195
21691
|
return vector2;
|
|
21196
21692
|
}).finally(() => {
|
|
21197
|
-
|
|
21198
|
-
if (
|
|
21693
|
+
entries2.delete(key3);
|
|
21694
|
+
if (entries2.size === 0) pendingRows.get(ctx)?.delete(options.maskInput);
|
|
21199
21695
|
});
|
|
21200
21696
|
pending.set(key3, request);
|
|
21201
21697
|
});
|
|
21202
21698
|
}
|
|
21203
21699
|
return Promise.all(
|
|
21204
21700
|
keys.map((key3) => {
|
|
21205
|
-
const
|
|
21206
|
-
if (
|
|
21701
|
+
const cached2 = prepared?.get(key3);
|
|
21702
|
+
if (cached2) return cached2;
|
|
21207
21703
|
const request = pending.get(key3);
|
|
21208
21704
|
if (!prepared) return request;
|
|
21209
21705
|
const retained = request.catch((error) => {
|
|
@@ -21903,10 +22399,10 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
|
|
|
21903
22399
|
const resolvedThisCall = /* @__PURE__ */ new Set();
|
|
21904
22400
|
if (!embeddingsDegraded) {
|
|
21905
22401
|
for (const k2 of keys) {
|
|
21906
|
-
const
|
|
21907
|
-
if (
|
|
22402
|
+
const cached2 = cachedRowVector(cache, k2.uniqueId, k2.updatedAt);
|
|
22403
|
+
if (cached2 && cached2.length === queryEmbedding.length) {
|
|
21908
22404
|
corpusStats.cacheHits++;
|
|
21909
|
-
vectored.push({ uniqueId: k2.uniqueId, embedding:
|
|
22405
|
+
vectored.push({ uniqueId: k2.uniqueId, embedding: cached2, updatedAt: k2.updatedAt });
|
|
21910
22406
|
continue;
|
|
21911
22407
|
}
|
|
21912
22408
|
corpusStats.cacheMisses++;
|
|
@@ -22204,12 +22700,12 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
22204
22700
|
for (let i = 0; queryEmbedding.length > 0 && i < memories.length; i++) {
|
|
22205
22701
|
const content = memories[i].content;
|
|
22206
22702
|
const memoryId = memories[i].uniqueId;
|
|
22207
|
-
const
|
|
22208
|
-
if (
|
|
22209
|
-
resolvedVectors.set(memoryId,
|
|
22703
|
+
const cached2 = cachedRowVector(cache, memoryId, memories[i].updatedAt, content);
|
|
22704
|
+
if (cached2 && cached2.length === queryEmbedding.length) {
|
|
22705
|
+
resolvedVectors.set(memoryId, cached2);
|
|
22210
22706
|
continue;
|
|
22211
22707
|
}
|
|
22212
|
-
if (
|
|
22708
|
+
if (cached2) cache.delete(memoryId);
|
|
22213
22709
|
const storedModel = memories[i].embeddingModel;
|
|
22214
22710
|
const modelCompatible = (storedModel ?? currentModel) === currentModel;
|
|
22215
22711
|
if (memories[i].embedding && modelCompatible) {
|
|
@@ -23893,9 +24389,9 @@ function createDecaySweeperOver(backend, options) {
|
|
|
23893
24389
|
if (ruleVerdict !== "keep") return rule;
|
|
23894
24390
|
if (!classifier || !isBorderline(input)) return rule;
|
|
23895
24391
|
if (input.id) {
|
|
23896
|
-
const
|
|
23897
|
-
if (
|
|
23898
|
-
return { verdict:
|
|
24392
|
+
const cached2 = classifierCache.get(input.id);
|
|
24393
|
+
if (cached2 && cached2.activityAt === lastActivityAt(input))
|
|
24394
|
+
return { verdict: cached2.verdict, source: "classifierDriven" };
|
|
23899
24395
|
}
|
|
23900
24396
|
if (sweep.classifierCalls >= maxClassifierCalls) {
|
|
23901
24397
|
sweep.classifierCapHits++;
|
|
@@ -25744,21 +26240,21 @@ async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
|
|
|
25744
26240
|
};
|
|
25745
26241
|
const inputs = [];
|
|
25746
26242
|
for (const id2 of new Set(memoryIds)) {
|
|
25747
|
-
let
|
|
26243
|
+
let record3;
|
|
25748
26244
|
try {
|
|
25749
|
-
|
|
26245
|
+
record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
25750
26246
|
} catch (err) {
|
|
25751
26247
|
log.warn("[memory/topics] vault lookup failed for extraction", err);
|
|
25752
26248
|
skip(id2, "not-found");
|
|
25753
26249
|
continue;
|
|
25754
26250
|
}
|
|
25755
|
-
if (
|
|
26251
|
+
if (record3.isDeleted || ctx.userId !== void 0 && record3.userId !== ctx.userId || record3.topicsUserManaged) {
|
|
25756
26252
|
skip(id2, "excluded");
|
|
25757
26253
|
continue;
|
|
25758
26254
|
}
|
|
25759
26255
|
try {
|
|
25760
26256
|
const stored2 = await vaultMemoryToStored(
|
|
25761
|
-
|
|
26257
|
+
record3,
|
|
25762
26258
|
ctx.walletAddress,
|
|
25763
26259
|
ctx.signMessage,
|
|
25764
26260
|
ctx.embeddedWalletSigner
|
|
@@ -26065,6 +26561,7 @@ function createLocalMemoryStore(options) {
|
|
|
26065
26561
|
|
|
26066
26562
|
// src/lib/memory/store/memoryKeys.ts
|
|
26067
26563
|
var KEY_ID_DOMAIN = "anuma-private-memory-key-id-v1";
|
|
26564
|
+
var TOPIC_HASH_INFO = "anuma-private-memory-topic-hash-v1";
|
|
26068
26565
|
var MemoryKeyError = class extends Error {
|
|
26069
26566
|
constructor(message) {
|
|
26070
26567
|
super(message);
|
|
@@ -26080,17 +26577,40 @@ async function importAesKey(hex) {
|
|
|
26080
26577
|
["encrypt", "decrypt"]
|
|
26081
26578
|
);
|
|
26082
26579
|
}
|
|
26580
|
+
async function deriveTopicHashKey(hex) {
|
|
26581
|
+
const material = await crypto.subtle.importKey(
|
|
26582
|
+
"raw",
|
|
26583
|
+
hexToBytes(hex).buffer,
|
|
26584
|
+
{ name: "HKDF" },
|
|
26585
|
+
false,
|
|
26586
|
+
["deriveBits"]
|
|
26587
|
+
);
|
|
26588
|
+
const bits = await crypto.subtle.deriveBits(
|
|
26589
|
+
{
|
|
26590
|
+
name: "HKDF",
|
|
26591
|
+
hash: "SHA-256",
|
|
26592
|
+
salt: new Uint8Array(32),
|
|
26593
|
+
info: new TextEncoder().encode(TOPIC_HASH_INFO)
|
|
26594
|
+
},
|
|
26595
|
+
material,
|
|
26596
|
+
256
|
|
26597
|
+
);
|
|
26598
|
+
return crypto.subtle.importKey("raw", bits, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
26599
|
+
}
|
|
26600
|
+
function toHex(bytes4) {
|
|
26601
|
+
return Array.from(new Uint8Array(bytes4), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
26602
|
+
}
|
|
26083
26603
|
async function deriveMemoryKeyRing(signatureHex) {
|
|
26084
26604
|
const v3Hex = await deriveKeyFromSignatureV3(signatureHex);
|
|
26085
26605
|
const digest = await crypto.subtle.digest(
|
|
26086
26606
|
"SHA-256",
|
|
26087
26607
|
new TextEncoder().encode(`${KEY_ID_DOMAIN}:${v3Hex}`)
|
|
26088
26608
|
);
|
|
26089
|
-
const keyId = "v3:" + Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
26090
26609
|
return {
|
|
26091
|
-
keyId,
|
|
26610
|
+
keyId: "v3:" + toHex(digest),
|
|
26092
26611
|
v3: await importAesKey(v3Hex),
|
|
26093
|
-
v2: await importAesKey(await deriveKeyFromSignature(signatureHex))
|
|
26612
|
+
v2: await importAesKey(await deriveKeyFromSignature(signatureHex)),
|
|
26613
|
+
topicHash: await deriveTopicHashKey(v3Hex)
|
|
26094
26614
|
};
|
|
26095
26615
|
}
|
|
26096
26616
|
async function decryptWith(value, rings) {
|
|
@@ -26111,7 +26631,10 @@ function memoryCipher(canonical) {
|
|
|
26111
26631
|
if (!ciphertext.startsWith("enc:v3:") || !isEncrypted(ciphertext))
|
|
26112
26632
|
throw new MemoryKeyError("Remote memory content must be enc:v3 ciphertext");
|
|
26113
26633
|
return decryptWith(ciphertext, [canonical]);
|
|
26114
|
-
}
|
|
26634
|
+
},
|
|
26635
|
+
hashTopic: async (normalized2) => toHex(
|
|
26636
|
+
await crypto.subtle.sign("HMAC", canonical.topicHash, new TextEncoder().encode(normalized2))
|
|
26637
|
+
)
|
|
26115
26638
|
};
|
|
26116
26639
|
}
|
|
26117
26640
|
async function reencryptMemoryField(value, canonical, fallbacks = []) {
|
|
@@ -26543,8 +27066,9 @@ var DEFAULT_RATE_LIMIT_WAIT_MS = 1e4;
|
|
|
26543
27066
|
var MAX_ID_BYTES = 128;
|
|
26544
27067
|
var MAX_CONTENT_BYTES = 32 << 10;
|
|
26545
27068
|
var MAX_TEXT_BYTES = 16 << 10;
|
|
27069
|
+
var MAX_TOPICS_BYTES = 32 << 10;
|
|
26546
27070
|
var MAX_SHORT_BYTES = 256;
|
|
26547
|
-
var TEXT_FIELDS = ["
|
|
27071
|
+
var TEXT_FIELDS = ["media", "source_chunk_ids"];
|
|
26548
27072
|
var SHORT_FIELDS = [
|
|
26549
27073
|
"scope",
|
|
26550
27074
|
"kind",
|
|
@@ -26647,7 +27171,7 @@ function bytes3(value) {
|
|
|
26647
27171
|
return value === void 0 ? 0 : utf82.encode(value).length;
|
|
26648
27172
|
}
|
|
26649
27173
|
function fitsNearby(row) {
|
|
26650
|
-
return bytes3(row.memory_id) <= MAX_ID_BYTES && bytes3(row.content) <= MAX_CONTENT_BYTES && bytes3(row.kind_value) <= MAX_CONTENT_BYTES && TEXT_FIELDS.every((field10) => bytes3(row[field10]) <= MAX_TEXT_BYTES) && SHORT_FIELDS.every((field10) => bytes3(row[field10]) <= MAX_SHORT_BYTES);
|
|
27174
|
+
return bytes3(row.memory_id) <= MAX_ID_BYTES && bytes3(row.content) <= MAX_CONTENT_BYTES && bytes3(row.kind_value) <= MAX_CONTENT_BYTES && bytes3(row.topics) <= MAX_TOPICS_BYTES && sealedTopicNamesFit(row.topics) && TEXT_FIELDS.every((field10) => bytes3(row[field10]) <= MAX_TEXT_BYTES) && SHORT_FIELDS.every((field10) => bytes3(row[field10]) <= MAX_SHORT_BYTES);
|
|
26651
27175
|
}
|
|
26652
27176
|
function invalid2(raw) {
|
|
26653
27177
|
const id2 = raw.id;
|
|
@@ -26691,7 +27215,7 @@ function defined(value) {
|
|
|
26691
27215
|
Object.entries(value).filter(([, field10]) => field10 !== void 0)
|
|
26692
27216
|
);
|
|
26693
27217
|
}
|
|
26694
|
-
async function prepareRow(raw, canonical, rings, model, updatedAt) {
|
|
27218
|
+
async function prepareRow(raw, canonical, codec, rings, model, updatedAt) {
|
|
26695
27219
|
const deleted = bool(raw.is_deleted) ?? false;
|
|
26696
27220
|
const { encrypt } = memoryCipher(canonical);
|
|
26697
27221
|
const localKindValue = text15(raw.kind_value);
|
|
@@ -26705,10 +27229,12 @@ async function prepareRow(raw, canonical, rings, model, updatedAt) {
|
|
|
26705
27229
|
plaintext = void 0;
|
|
26706
27230
|
kindValue = void 0;
|
|
26707
27231
|
}
|
|
27232
|
+
const fields = metadata2(raw, model);
|
|
26708
27233
|
const row = {
|
|
26709
27234
|
...defined({
|
|
26710
|
-
...
|
|
26711
|
-
kind_value: kindValue === void 0 ? void 0 : await encrypt(kindValue)
|
|
27235
|
+
...fields,
|
|
27236
|
+
kind_value: kindValue === void 0 ? void 0 : await encrypt(kindValue),
|
|
27237
|
+
topics: fields.topics === void 0 ? void 0 : await codec.encodeTopics(fields.topics)
|
|
26712
27238
|
}),
|
|
26713
27239
|
memory_id: raw.id,
|
|
26714
27240
|
content: await encrypt(plaintext ?? ""),
|
|
@@ -26752,6 +27278,8 @@ function sameMetadata2(local, remote, model) {
|
|
|
26752
27278
|
if (field10 === "visibility") return (a ?? "private") === (b ?? "private");
|
|
26753
27279
|
if (field10 === "is_deleted" || field10 === "topics_user_managed" || field10 === "twin_opt_in")
|
|
26754
27280
|
return (a ?? false) === (b ?? false);
|
|
27281
|
+
if (field10 === "topics")
|
|
27282
|
+
return JSON.stringify(parseTopics(a)) === JSON.stringify(parseTopics(b));
|
|
26755
27283
|
return a === b;
|
|
26756
27284
|
});
|
|
26757
27285
|
}
|
|
@@ -26807,7 +27335,7 @@ async function missingIds(request, revisions, signal) {
|
|
|
26807
27335
|
}
|
|
26808
27336
|
return missing2;
|
|
26809
27337
|
}
|
|
26810
|
-
async function remoteMetadata(request, ids, signal) {
|
|
27338
|
+
async function remoteMetadata(request, codec, ids, signal) {
|
|
26811
27339
|
const rows = /* @__PURE__ */ new Map();
|
|
26812
27340
|
for (const batch of chunks(ids, QUERY_IDS)) {
|
|
26813
27341
|
let cursor;
|
|
@@ -26831,7 +27359,12 @@ async function remoteMetadata(request, ids, signal) {
|
|
|
26831
27359
|
if (!Array.isArray(page.items)) throw new Error("Invalid nearby private-memory page");
|
|
26832
27360
|
for (const item of page.items)
|
|
26833
27361
|
if (item.memory && typeof item.memory.memory_id === "string")
|
|
26834
|
-
rows.set(item.memory.memory_id,
|
|
27362
|
+
rows.set(item.memory.memory_id, {
|
|
27363
|
+
...item.memory,
|
|
27364
|
+
...typeof item.memory.topics === "string" && {
|
|
27365
|
+
topics: await codec.decodeTopics(item.memory.topics).catch(() => null)
|
|
27366
|
+
}
|
|
27367
|
+
});
|
|
26835
27368
|
cursor = typeof page.next_cursor === "string" ? page.next_cursor : void 0;
|
|
26836
27369
|
} while (cursor);
|
|
26837
27370
|
}
|
|
@@ -26849,6 +27382,7 @@ async function migrateMemoriesToRemote(options) {
|
|
|
26849
27382
|
const rings = [canonical, ...options.fallbacks ?? []];
|
|
26850
27383
|
const model = options.embeddingOptions?.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
26851
27384
|
const request = createNearbyRequest(options);
|
|
27385
|
+
const codec = createTopicCodec(memoryCipher(canonical));
|
|
26852
27386
|
const account = await request("/account", {}, signal);
|
|
26853
27387
|
if (typeof account.key_id === "string" && account.key_id !== canonical.keyId)
|
|
26854
27388
|
throw new RemoteMemoryError(
|
|
@@ -26865,7 +27399,7 @@ async function migrateMemoriesToRemote(options) {
|
|
|
26865
27399
|
...typeof t.kind === "string" && { kind: t.kind }
|
|
26866
27400
|
})).filter((t) => t.name.length > 0) : []);
|
|
26867
27401
|
if (localTopics.length)
|
|
26868
|
-
await createRemoteTopicPersistence(request).importTopics(localTopics, signal);
|
|
27402
|
+
await createRemoteTopicPersistence(request, codec).importTopics(localTopics, signal);
|
|
26869
27403
|
const skipped = /* @__PURE__ */ new Map();
|
|
26870
27404
|
const reembedded = /* @__PURE__ */ new Set();
|
|
26871
27405
|
const unembedded = /* @__PURE__ */ new Set();
|
|
@@ -26884,6 +27418,7 @@ async function migrateMemoriesToRemote(options) {
|
|
|
26884
27418
|
if (pending.size === 0 && !active) {
|
|
26885
27419
|
const remote = await remoteMetadata(
|
|
26886
27420
|
request,
|
|
27421
|
+
codec,
|
|
26887
27422
|
candidates.map((raw) => raw.id),
|
|
26888
27423
|
signal
|
|
26889
27424
|
);
|
|
@@ -26928,7 +27463,7 @@ async function migrateMemoriesToRemote(options) {
|
|
|
26928
27463
|
const updatedAt = pending.get(raw.id);
|
|
26929
27464
|
if (updatedAt === void 0) continue;
|
|
26930
27465
|
try {
|
|
26931
|
-
prepared.push(await prepareRow(raw, canonical, rings, model, updatedAt));
|
|
27466
|
+
prepared.push(await prepareRow(raw, canonical, codec, rings, model, updatedAt));
|
|
26932
27467
|
} catch (error) {
|
|
26933
27468
|
if (!(error instanceof MemoryKeyError)) throw error;
|
|
26934
27469
|
skipped.set(raw.id, "unreadable");
|
|
@@ -27087,7 +27622,7 @@ function topicInputs(topics, source) {
|
|
|
27087
27622
|
function mergeTopics(existing, added) {
|
|
27088
27623
|
const byName = /* @__PURE__ */ new Map();
|
|
27089
27624
|
for (const topic2 of [...existing, ...added]) {
|
|
27090
|
-
const key3 =
|
|
27625
|
+
const key3 = normalizeTopicName(topic2.name);
|
|
27091
27626
|
const kept = byName.get(key3);
|
|
27092
27627
|
if (!kept) byName.set(key3, topic2);
|
|
27093
27628
|
else if (kept.weight !== void 0 && topic2.weight !== void 0 && topic2.weight > kept.weight)
|
|
@@ -27102,7 +27637,7 @@ function sameTopics(stored2, next) {
|
|
|
27102
27637
|
return next.every((t) => keys.has(key3(t)));
|
|
27103
27638
|
}
|
|
27104
27639
|
function canonicalTopics(row) {
|
|
27105
|
-
return new Set((parseTopics(row.topics) ?? []).map((topic2) =>
|
|
27640
|
+
return new Set((parseTopics(row.topics) ?? []).map((topic2) => normalizeTopicName(topic2.name)));
|
|
27106
27641
|
}
|
|
27107
27642
|
function createRemoteMemoryStore(options) {
|
|
27108
27643
|
const { persistence, embeddingOptions } = options;
|
|
@@ -27149,10 +27684,10 @@ function createRemoteMemoryStore(options) {
|
|
|
27149
27684
|
const notify = (change, records = []) => {
|
|
27150
27685
|
invalidateReads();
|
|
27151
27686
|
if (subscribers.size)
|
|
27152
|
-
for (const
|
|
27153
|
-
const previous = seen.get(
|
|
27154
|
-
if ((previous?.version ?? 0) + 1 ===
|
|
27155
|
-
seen.set(
|
|
27687
|
+
for (const record3 of records) {
|
|
27688
|
+
const previous = seen.get(record3.memory.memory_id);
|
|
27689
|
+
if ((previous?.version ?? 0) + 1 === record3.version)
|
|
27690
|
+
seen.set(record3.memory.memory_id, subscriptionState(record3));
|
|
27156
27691
|
}
|
|
27157
27692
|
for (const subscriber of [...subscribers])
|
|
27158
27693
|
if (relevant(change, subscriber.options)) safely(subscriber.onChange);
|
|
@@ -27205,7 +27740,7 @@ function createRemoteMemoryStore(options) {
|
|
|
27205
27740
|
};
|
|
27206
27741
|
const enumerate = (filters, max = Infinity) => pages(decrypted, filters, max);
|
|
27207
27742
|
const memoriesByTopics = async (names) => {
|
|
27208
|
-
const wanted = new Set(names.map(
|
|
27743
|
+
const wanted = new Set(names.map(normalizeTopicName).filter(Boolean));
|
|
27209
27744
|
const out = /* @__PURE__ */ new Map();
|
|
27210
27745
|
const pages2 = await Promise.all(
|
|
27211
27746
|
chunks2([...wanted], MAX_QUERY_TOPICS).map((topics) => enumerate({ topics }))
|
|
@@ -27217,7 +27752,7 @@ function createRemoteMemoryStore(options) {
|
|
|
27217
27752
|
return out;
|
|
27218
27753
|
};
|
|
27219
27754
|
const topicGraphRanking = async (query, recallOptions = {}) => {
|
|
27220
|
-
const wanted = new Set(extractQueryEntities(query).map(
|
|
27755
|
+
const wanted = new Set(extractQueryEntities(query).map(normalizeTopicName).filter(Boolean));
|
|
27221
27756
|
if (wanted.size === 0 || recallOptions.memoryIds?.length === 0) return [];
|
|
27222
27757
|
const rows = await pages(
|
|
27223
27758
|
metadata3,
|
|
@@ -27275,25 +27810,25 @@ function createRemoteMemoryStore(options) {
|
|
|
27275
27810
|
return run;
|
|
27276
27811
|
};
|
|
27277
27812
|
const live2 = async (id2) => {
|
|
27278
|
-
const
|
|
27279
|
-
return
|
|
27813
|
+
const record3 = await persistence.get(id2);
|
|
27814
|
+
return record3 && !record3.memory.is_deleted ? record3 : null;
|
|
27280
27815
|
};
|
|
27281
27816
|
const mutateLocked = async (id2, change, edit, writeOptions) => {
|
|
27282
27817
|
writeOptions?.signal?.throwIfAborted();
|
|
27283
|
-
const
|
|
27284
|
-
if (!
|
|
27285
|
-
if (
|
|
27818
|
+
const record3 = writeOptions?.signal ? await persistence.get(id2, writeOptions.signal) : await live2(id2);
|
|
27819
|
+
if (!record3) return null;
|
|
27820
|
+
if (record3.memory.is_deleted) return null;
|
|
27286
27821
|
if (writeOptions?.canWrite && !await writeOptions.canWrite())
|
|
27287
27822
|
throw new MemorySourceIneligibleError();
|
|
27288
27823
|
writeOptions?.signal?.throwIfAborted();
|
|
27289
|
-
const next = edit(structuredClone(
|
|
27824
|
+
const next = edit(structuredClone(record3.memory));
|
|
27290
27825
|
if (!next) return null;
|
|
27291
27826
|
const saved = writeOptions?.leaseToken ? (await persistence.putMany(
|
|
27292
|
-
[{ memory: next, expectedVersion:
|
|
27827
|
+
[{ memory: next, expectedVersion: record3 }],
|
|
27293
27828
|
writeOptions.signal,
|
|
27294
27829
|
writeOptions.leaseToken
|
|
27295
|
-
))[0] : writeOptions?.signal ? await persistence.put(next,
|
|
27296
|
-
notify(typeof change === "function" ? change(
|
|
27830
|
+
))[0] : writeOptions?.signal ? await persistence.put(next, record3, writeOptions.signal) : await persistence.put(next, record3);
|
|
27831
|
+
notify(typeof change === "function" ? change(record3.memory) : change, [saved]);
|
|
27297
27832
|
return saved;
|
|
27298
27833
|
};
|
|
27299
27834
|
const mutate = (id2, change, edit, writeOptions) => serialized(id2, () => mutateLocked(id2, change, edit, writeOptions));
|
|
@@ -27315,12 +27850,12 @@ function createRemoteMemoryStore(options) {
|
|
|
27315
27850
|
}
|
|
27316
27851
|
const { records, unreadable } = read;
|
|
27317
27852
|
for (const id2 of slice) {
|
|
27318
|
-
const
|
|
27853
|
+
const record3 = records.get(id2);
|
|
27319
27854
|
if (unreadable.has(id2)) failed.set(id2, new Error(`Memory ${id2} could not be decrypted`));
|
|
27320
|
-
else if (!
|
|
27321
|
-
else if (!
|
|
27322
|
-
const memory = edit(structuredClone(
|
|
27323
|
-
if (memory) writes.push({ before:
|
|
27855
|
+
else if (!record3) failed.set(id2, new Error(`Memory ${id2} was not found`));
|
|
27856
|
+
else if (!record3.memory.is_deleted) {
|
|
27857
|
+
const memory = edit(structuredClone(record3.memory));
|
|
27858
|
+
if (memory) writes.push({ before: record3, memory });
|
|
27324
27859
|
}
|
|
27325
27860
|
}
|
|
27326
27861
|
if (writes.length === 0) return;
|
|
@@ -27331,10 +27866,10 @@ function createRemoteMemoryStore(options) {
|
|
|
27331
27866
|
leaseToken
|
|
27332
27867
|
);
|
|
27333
27868
|
const byChange = /* @__PURE__ */ new Map();
|
|
27334
|
-
written.forEach((
|
|
27335
|
-
saved.set(
|
|
27869
|
+
written.forEach((record3, i) => {
|
|
27870
|
+
saved.set(record3.memory.memory_id, record3);
|
|
27336
27871
|
const kind = change(writes[i].before.memory);
|
|
27337
|
-
byChange.set(kind, [...byChange.get(kind) ?? [],
|
|
27872
|
+
byChange.set(kind, [...byChange.get(kind) ?? [], record3]);
|
|
27338
27873
|
});
|
|
27339
27874
|
for (const [kind, changed] of byChange) notify(kind, changed);
|
|
27340
27875
|
} catch (error) {
|
|
@@ -27348,13 +27883,13 @@ function createRemoteMemoryStore(options) {
|
|
|
27348
27883
|
continue;
|
|
27349
27884
|
}
|
|
27350
27885
|
try {
|
|
27351
|
-
const
|
|
27886
|
+
const record3 = await mutateLocked(
|
|
27352
27887
|
id2,
|
|
27353
27888
|
change,
|
|
27354
27889
|
edit,
|
|
27355
27890
|
leaseToken || signal ? { leaseToken, signal } : void 0
|
|
27356
27891
|
);
|
|
27357
|
-
if (
|
|
27892
|
+
if (record3) saved.set(id2, record3);
|
|
27358
27893
|
} catch (rowError) {
|
|
27359
27894
|
signal?.throwIfAborted();
|
|
27360
27895
|
if (isRemoteWorkLeaseExpired(rowError)) throw rowError;
|
|
@@ -27450,12 +27985,12 @@ function createRemoteMemoryStore(options) {
|
|
|
27450
27985
|
const created = (records, inputs) => {
|
|
27451
27986
|
embedInBackground(records.filter((_, i) => inputs[i].embedding === void 0));
|
|
27452
27987
|
notify("membership", records);
|
|
27453
|
-
return records.map((
|
|
27988
|
+
return records.map((record3) => stored(record3.memory));
|
|
27454
27989
|
};
|
|
27455
|
-
const asStored = (
|
|
27990
|
+
const asStored = (record3) => record3 ? stored(record3.memory) : null;
|
|
27456
27991
|
const knownKinds = async (topics, signal) => {
|
|
27457
27992
|
const unkinded = [
|
|
27458
|
-
...new Set(topics.filter((t) => !t.kind).map((t) =>
|
|
27993
|
+
...new Set(topics.filter((t) => !t.kind).map((t) => normalizeTopicName(t.name)))
|
|
27459
27994
|
];
|
|
27460
27995
|
const kinds2 = /* @__PURE__ */ new Map();
|
|
27461
27996
|
for (const names of chunks2(unkinded, MAX_QUERY_TOPICS)) {
|
|
@@ -27467,13 +28002,13 @@ function createRemoteMemoryStore(options) {
|
|
|
27467
28002
|
...signal && { signal }
|
|
27468
28003
|
})) {
|
|
27469
28004
|
for (const topic2 of parseTopics(memory.topics) ?? []) {
|
|
27470
|
-
const name =
|
|
28005
|
+
const name = normalizeTopicName(topic2.name);
|
|
27471
28006
|
if (topic2.kind && !kinds2.has(name)) kinds2.set(name, topic2.kind);
|
|
27472
28007
|
}
|
|
27473
28008
|
}
|
|
27474
28009
|
}
|
|
27475
28010
|
return (topic2) => {
|
|
27476
|
-
const kind = topic2.kind ?? kinds2.get(
|
|
28011
|
+
const kind = topic2.kind ?? kinds2.get(normalizeTopicName(topic2.name));
|
|
27477
28012
|
return kind ? { ...topic2, kind } : topic2;
|
|
27478
28013
|
};
|
|
27479
28014
|
};
|
|
@@ -27496,7 +28031,7 @@ function createRemoteMemoryStore(options) {
|
|
|
27496
28031
|
...cursor2 && { cursor: cursor2 }
|
|
27497
28032
|
});
|
|
27498
28033
|
warnFailed(page.failed);
|
|
27499
|
-
for (const
|
|
28034
|
+
for (const record3 of page.items) records.set(record3.memory.memory_id, record3);
|
|
27500
28035
|
for (const failure of page.failed) unreadable.add(failure.memory_id);
|
|
27501
28036
|
cursor2 = page.next_cursor;
|
|
27502
28037
|
} while (cursor2);
|
|
@@ -27692,8 +28227,8 @@ function createRemoteMemoryStore(options) {
|
|
|
27692
28227
|
const failed = /* @__PURE__ */ new Map();
|
|
27693
28228
|
const collect = (page) => {
|
|
27694
28229
|
warnFailed(page.failed);
|
|
27695
|
-
for (const
|
|
27696
|
-
records.push({ id:
|
|
28230
|
+
for (const record3 of page.items)
|
|
28231
|
+
records.push({ id: record3.memory.memory_id, state: subscriptionState(record3) });
|
|
27697
28232
|
for (const failure of page.failed) failed.set(failure.memory_id, failure.version);
|
|
27698
28233
|
};
|
|
27699
28234
|
let resume = cursor2;
|
|
@@ -27898,7 +28433,7 @@ function createRemoteMemoryStore(options) {
|
|
|
27898
28433
|
result.failed += targets.length;
|
|
27899
28434
|
return finish();
|
|
27900
28435
|
}
|
|
27901
|
-
const writes = targets.flatMap((
|
|
28436
|
+
const writes = targets.flatMap((record3, i) => {
|
|
27902
28437
|
const vector2 = vectors[i];
|
|
27903
28438
|
if (!vector2) {
|
|
27904
28439
|
result.failed++;
|
|
@@ -27908,11 +28443,11 @@ function createRemoteMemoryStore(options) {
|
|
|
27908
28443
|
return [
|
|
27909
28444
|
{
|
|
27910
28445
|
memory: {
|
|
27911
|
-
...
|
|
28446
|
+
...record3.memory,
|
|
27912
28447
|
embedding: storedVector(vector2),
|
|
27913
28448
|
embedding_model: model
|
|
27914
28449
|
},
|
|
27915
|
-
expectedVersion:
|
|
28450
|
+
expectedVersion: record3
|
|
27916
28451
|
}
|
|
27917
28452
|
];
|
|
27918
28453
|
} catch {
|
|
@@ -27927,7 +28462,7 @@ function createRemoteMemoryStore(options) {
|
|
|
27927
28462
|
signal?.throwIfAborted();
|
|
27928
28463
|
const commit = async (slice) => {
|
|
27929
28464
|
const saved = await persistence.putMany(slice, signal, leaseToken);
|
|
27930
|
-
for (const
|
|
28465
|
+
for (const record3 of saved) repaired.add(record3.memory.memory_id);
|
|
27931
28466
|
result.reembedded += saved.length;
|
|
27932
28467
|
notify("embedding", saved);
|
|
27933
28468
|
};
|
|
@@ -28011,7 +28546,7 @@ function createRemoteMemoryStore(options) {
|
|
|
28011
28546
|
if (!topics.length) return;
|
|
28012
28547
|
const existing = new Set((await readTopics()).map((topic2) => topic2.name));
|
|
28013
28548
|
const missing2 = topics.flatMap((topic2) => {
|
|
28014
|
-
const name =
|
|
28549
|
+
const name = normalizeTopicName(topic2.name);
|
|
28015
28550
|
if (existing.has(name)) return [];
|
|
28016
28551
|
existing.add(name);
|
|
28017
28552
|
return [{ ...topic2, name }];
|
|
@@ -28042,7 +28577,7 @@ function createRemoteMemoryStore(options) {
|
|
|
28042
28577
|
include_superseded: true
|
|
28043
28578
|
})) {
|
|
28044
28579
|
for (const topic2 of parseTopics(memory.topics) ?? []) {
|
|
28045
|
-
const name =
|
|
28580
|
+
const name = normalizeTopicName(topic2.name);
|
|
28046
28581
|
if (!name) continue;
|
|
28047
28582
|
const entry = topics.get(name) ?? {
|
|
28048
28583
|
name,
|
|
@@ -28080,7 +28615,7 @@ function createRemoteMemoryStore(options) {
|
|
|
28080
28615
|
},
|
|
28081
28616
|
get: async (id2) => asStored(await live2(id2)),
|
|
28082
28617
|
listArchived: async () => (await enumerate({ archived_only: true, order: "archived", include_embeddings: true })).map(
|
|
28083
|
-
(
|
|
28618
|
+
(record3) => stored(record3.memory)
|
|
28084
28619
|
),
|
|
28085
28620
|
memoriesByTopics,
|
|
28086
28621
|
topicsByMemories: async (memoryIds) => {
|
|
@@ -28096,8 +28631,8 @@ function createRemoteMemoryStore(options) {
|
|
|
28096
28631
|
return out;
|
|
28097
28632
|
},
|
|
28098
28633
|
create: async (input) => {
|
|
28099
|
-
const
|
|
28100
|
-
return created([
|
|
28634
|
+
const record3 = await persistence.put(newRow(input), 0);
|
|
28635
|
+
return created([record3], [input])[0];
|
|
28101
28636
|
},
|
|
28102
28637
|
createMany: async (inputs) => {
|
|
28103
28638
|
const out = [];
|
|
@@ -28184,12 +28719,12 @@ function createRemoteMemoryStore(options) {
|
|
|
28184
28719
|
(memory) => memory.archived_at === void 0 || memory.archived_at === null ? { ...memory, archived_at: Date.now() } : null
|
|
28185
28720
|
),
|
|
28186
28721
|
restore: (id2) => serialized(id2, async () => {
|
|
28187
|
-
const
|
|
28188
|
-
if (!
|
|
28189
|
-
if (
|
|
28722
|
+
const record3 = await live2(id2);
|
|
28723
|
+
if (!record3) return false;
|
|
28724
|
+
if (record3.memory.archived_at === void 0 || record3.memory.archived_at === null)
|
|
28190
28725
|
return true;
|
|
28191
|
-
const { archived_at: _archivedAt, ...memory } =
|
|
28192
|
-
notify("edit", [await persistence.put(memory,
|
|
28726
|
+
const { archived_at: _archivedAt, ...memory } = record3.memory;
|
|
28727
|
+
notify("edit", [await persistence.put(memory, record3)]);
|
|
28193
28728
|
return true;
|
|
28194
28729
|
}),
|
|
28195
28730
|
setTopics: async (memoryId, topics) => {
|
|
@@ -28222,8 +28757,8 @@ function createRemoteMemoryStore(options) {
|
|
|
28222
28757
|
const now = /* @__PURE__ */ new Date();
|
|
28223
28758
|
return mergeTopics([], added).map(
|
|
28224
28759
|
(topic2) => ({
|
|
28225
|
-
uniqueId:
|
|
28226
|
-
canonicalName:
|
|
28760
|
+
uniqueId: normalizeTopicName(topic2.name),
|
|
28761
|
+
canonicalName: normalizeTopicName(topic2.name),
|
|
28227
28762
|
kind: topic2.kind ?? null,
|
|
28228
28763
|
createdAt: now,
|
|
28229
28764
|
updatedAt: now
|
|
@@ -31585,16 +32120,16 @@ var ZipProcessor = class {
|
|
|
31585
32120
|
try {
|
|
31586
32121
|
const arrayBuffer = await dataUrlToArrayBuffer(file.dataUrl);
|
|
31587
32122
|
const zip = await JSZip.loadAsync(arrayBuffer);
|
|
31588
|
-
const
|
|
32123
|
+
const entries2 = [];
|
|
31589
32124
|
const processedContents = [];
|
|
31590
32125
|
zip.forEach((relativePath, zipEntry) => {
|
|
31591
|
-
|
|
32126
|
+
entries2.push({
|
|
31592
32127
|
path: relativePath,
|
|
31593
32128
|
isDirectory: zipEntry.dir,
|
|
31594
32129
|
zipObject: zipEntry
|
|
31595
32130
|
});
|
|
31596
32131
|
});
|
|
31597
|
-
const visibleEntries = this.includeHidden ?
|
|
32132
|
+
const visibleEntries = this.includeHidden ? entries2 : entries2.filter((entry) => !this.isHidden(entry.path));
|
|
31598
32133
|
visibleEntries.sort((a, b) => {
|
|
31599
32134
|
if (a.isDirectory !== b.isDirectory) {
|
|
31600
32135
|
return a.isDirectory ? -1 : 1;
|
|
@@ -31708,17 +32243,17 @@ var ZipProcessor = class {
|
|
|
31708
32243
|
/**
|
|
31709
32244
|
* Format the output with file listing and processed contents
|
|
31710
32245
|
*/
|
|
31711
|
-
formatOutput(
|
|
32246
|
+
formatOutput(entries2, processedContents) {
|
|
31712
32247
|
const lines = [];
|
|
31713
32248
|
lines.push("## Archive Contents\n");
|
|
31714
32249
|
lines.push("```");
|
|
31715
|
-
for (const entry of
|
|
32250
|
+
for (const entry of entries2) {
|
|
31716
32251
|
const icon = entry.isDirectory ? "\u{1F4C1}" : "\u{1F4C4}";
|
|
31717
32252
|
lines.push(`${icon} ${entry.path}`);
|
|
31718
32253
|
}
|
|
31719
32254
|
lines.push("```\n");
|
|
31720
|
-
const fileCount =
|
|
31721
|
-
const dirCount =
|
|
32255
|
+
const fileCount = entries2.filter((e) => !e.isDirectory).length;
|
|
32256
|
+
const dirCount = entries2.filter((e) => e.isDirectory).length;
|
|
31722
32257
|
lines.push(
|
|
31723
32258
|
`**Summary:** ${fileCount} file${fileCount !== 1 ? "s" : ""}, ${dirCount} director${dirCount !== 1 ? "ies" : "y"}
|
|
31724
32259
|
`
|
|
@@ -32901,13 +33436,13 @@ function serializeInline(node) {
|
|
|
32901
33436
|
function openTag(node, indent, depth, selfClose, maxLineWidth) {
|
|
32902
33437
|
const head = `<${tagName(node.tag)}`;
|
|
32903
33438
|
const tail = selfClose ? " />" : ">";
|
|
32904
|
-
const
|
|
32905
|
-
if (
|
|
32906
|
-
const single = `${head} ${
|
|
33439
|
+
const entries2 = Object.entries(node.attrs);
|
|
33440
|
+
if (entries2.length === 0) return `${head}${tail}`;
|
|
33441
|
+
const single = `${head} ${entries2.map(([k, v]) => formatAttr(k, v)).join(" ")}${tail}`;
|
|
32907
33442
|
if (single.length <= maxLineWidth) return single;
|
|
32908
33443
|
const attrPad = indent.repeat(depth + 1);
|
|
32909
33444
|
const closePad = indent.repeat(depth);
|
|
32910
|
-
const body =
|
|
33445
|
+
const body = entries2.map(([k, v]) => `${attrPad}${formatAttr(k, v)}`).join("\n");
|
|
32911
33446
|
return `${head}
|
|
32912
33447
|
${body}
|
|
32913
33448
|
${closePad}${selfClose ? "/>" : ">"}`;
|
|
@@ -32919,13 +33454,13 @@ function formatAttr(name, value) {
|
|
|
32919
33454
|
return `${name}={${formatObjectAttr(value)}}`;
|
|
32920
33455
|
}
|
|
32921
33456
|
function formatObjectAttr(obj) {
|
|
32922
|
-
const
|
|
33457
|
+
const entries2 = Object.entries(obj).map(([k, v]) => {
|
|
32923
33458
|
const key3 = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(k) ? k : JSON.stringify(k);
|
|
32924
33459
|
if (typeof v === "string") return `${key3}: ${JSON.stringify(v)}`;
|
|
32925
33460
|
if (typeof v === "number") return `${key3}: ${String(v)}`;
|
|
32926
33461
|
return `${key3}: ${v ? "true" : "false"}`;
|
|
32927
33462
|
});
|
|
32928
|
-
return `{ ${
|
|
33463
|
+
return `{ ${entries2.join(", ")} }`;
|
|
32929
33464
|
}
|
|
32930
33465
|
function isSafeJsxText(text16) {
|
|
32931
33466
|
if (/[<>{}&]/.test(text16)) return false;
|
|
@@ -34323,7 +34858,7 @@ async function uploadFileToICloud(filename, content, backupRevision) {
|
|
|
34323
34858
|
const recordName = `backup_${filename.replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
34324
34859
|
const arrayBuffer = await content.arrayBuffer();
|
|
34325
34860
|
const base64Data = uint8ArrayToBase64(new Uint8Array(arrayBuffer));
|
|
34326
|
-
const
|
|
34861
|
+
const record3 = {
|
|
34327
34862
|
recordType: RECORD_TYPE,
|
|
34328
34863
|
recordName,
|
|
34329
34864
|
fields: {
|
|
@@ -34334,7 +34869,7 @@ async function uploadFileToICloud(filename, content, backupRevision) {
|
|
|
34334
34869
|
...backupRevision ? { backupRevision: { value: backupRevision } } : {}
|
|
34335
34870
|
}
|
|
34336
34871
|
};
|
|
34337
|
-
const response = await database.saveRecords(
|
|
34872
|
+
const response = await database.saveRecords(record3);
|
|
34338
34873
|
if (!response.records || response.records.length === 0) {
|
|
34339
34874
|
throw new Error("Failed to upload file to iCloud");
|
|
34340
34875
|
}
|
|
@@ -34361,12 +34896,12 @@ async function listICloudFiles() {
|
|
|
34361
34896
|
while (response.continuationMarker) {
|
|
34362
34897
|
break;
|
|
34363
34898
|
}
|
|
34364
|
-
const files = allRecords.map((
|
|
34365
|
-
recordName:
|
|
34366
|
-
filename:
|
|
34367
|
-
modifiedAt: new Date(
|
|
34368
|
-
backupRevision:
|
|
34369
|
-
size: typeof
|
|
34899
|
+
const files = allRecords.map((record3) => ({
|
|
34900
|
+
recordName: record3.recordName,
|
|
34901
|
+
filename: record3.fields.filename?.value ?? "",
|
|
34902
|
+
modifiedAt: new Date(record3.modified?.timestamp ?? Date.now()),
|
|
34903
|
+
backupRevision: record3.fields.backupRevision?.value,
|
|
34904
|
+
size: typeof record3.fields.data?.value === "object" && record3.fields.data?.value !== null ? record3.fields.data.value.size : 0
|
|
34370
34905
|
}));
|
|
34371
34906
|
return files.sort((a, b) => b.modifiedAt.getTime() - a.modifiedAt.getTime());
|
|
34372
34907
|
}
|
|
@@ -34379,8 +34914,8 @@ async function downloadICloudFile(recordName) {
|
|
|
34379
34914
|
if (!response.records || response.records.length === 0) {
|
|
34380
34915
|
throw new Error(`File not found: ${recordName}`);
|
|
34381
34916
|
}
|
|
34382
|
-
const
|
|
34383
|
-
const dataField =
|
|
34917
|
+
const record3 = response.records[0];
|
|
34918
|
+
const dataField = record3.fields.data?.value;
|
|
34384
34919
|
if (!dataField) {
|
|
34385
34920
|
throw new Error("No data in record");
|
|
34386
34921
|
}
|
|
@@ -34414,13 +34949,13 @@ async function findICloudFile(filename) {
|
|
|
34414
34949
|
if (!response.records || response.records.length === 0) {
|
|
34415
34950
|
return null;
|
|
34416
34951
|
}
|
|
34417
|
-
const
|
|
34952
|
+
const record3 = response.records[0];
|
|
34418
34953
|
return {
|
|
34419
|
-
recordName:
|
|
34420
|
-
filename:
|
|
34421
|
-
modifiedAt: new Date(
|
|
34422
|
-
backupRevision:
|
|
34423
|
-
size: typeof
|
|
34954
|
+
recordName: record3.recordName,
|
|
34955
|
+
filename: record3.fields.filename?.value ?? "",
|
|
34956
|
+
modifiedAt: new Date(record3.modified?.timestamp ?? Date.now()),
|
|
34957
|
+
backupRevision: record3.fields.backupRevision?.value,
|
|
34958
|
+
size: typeof record3.fields.data?.value === "object" && record3.fields.data?.value !== null ? record3.fields.data.value.size : 0
|
|
34424
34959
|
};
|
|
34425
34960
|
}
|
|
34426
34961
|
|
|
@@ -35770,13 +36305,13 @@ function useConversationRedactors(database, account, storage, secondaryStorage)
|
|
|
35770
36305
|
return useCallback4(
|
|
35771
36306
|
(conversationId, nerDetector) => {
|
|
35772
36307
|
if (!scope.active) return retiredRedactor;
|
|
35773
|
-
const
|
|
35774
|
-
if (
|
|
36308
|
+
const cached2 = scope.redactors.get(conversationId);
|
|
36309
|
+
if (cached2 && cached2.detector === nerDetector) {
|
|
35775
36310
|
scope.redactors.delete(conversationId);
|
|
35776
|
-
scope.redactors.set(conversationId,
|
|
35777
|
-
return
|
|
36311
|
+
scope.redactors.set(conversationId, cached2);
|
|
36312
|
+
return cached2.redactor;
|
|
35778
36313
|
}
|
|
35779
|
-
if (
|
|
36314
|
+
if (cached2) scope.evicted.push(cached2.redactor);
|
|
35780
36315
|
const redactor = new PiiRedactor({ nerDetector });
|
|
35781
36316
|
scope.redactors.set(conversationId, { redactor, detector: nerDetector });
|
|
35782
36317
|
if (scope.redactors.size > REDACTOR_LIMIT) {
|
|
@@ -38233,82 +38768,45 @@ function useChatStorage(options) {
|
|
|
38233
38768
|
await inbox.putPublicKey(publicKey);
|
|
38234
38769
|
registeredInboxKeyRef.current = { inbox, publicKey };
|
|
38235
38770
|
}
|
|
38236
|
-
|
|
38237
|
-
|
|
38238
|
-
|
|
38239
|
-
|
|
38240
|
-
|
|
38241
|
-
|
|
38242
|
-
|
|
38243
|
-
|
|
38244
|
-
|
|
38245
|
-
|
|
38246
|
-
|
|
38247
|
-
|
|
38771
|
+
return deliverInboxAnswers({
|
|
38772
|
+
inbox,
|
|
38773
|
+
keyPair,
|
|
38774
|
+
backend,
|
|
38775
|
+
store: async (opened, messageId) => {
|
|
38776
|
+
const { redactor } = resolveCallPii(
|
|
38777
|
+
void 0,
|
|
38778
|
+
piiRedaction,
|
|
38779
|
+
() => getConversationRedactor(opened.conversation_id, nerDetectorRef.current)
|
|
38780
|
+
);
|
|
38781
|
+
const knownToolCallEventIds = await backend.getToolCallEventIds(opened.conversation_id);
|
|
38782
|
+
const { fields, fileIds } = await toAssistantMessageFields(
|
|
38783
|
+
opened.response,
|
|
38784
|
+
opened.conversation_id,
|
|
38785
|
+
knownToolCallEventIds
|
|
38786
|
+
);
|
|
38787
|
+
const upserted = await backend.upsertMessage({
|
|
38788
|
+
...fields,
|
|
38789
|
+
content: redactor ? redactor.deAnonymize(fields.content) : fields.content,
|
|
38790
|
+
thinking: redactor && fields.thinking ? redactor.deAnonymize(fields.thinking) : fields.thinking,
|
|
38791
|
+
conversationId: opened.conversation_id,
|
|
38792
|
+
role: "assistant",
|
|
38793
|
+
model: opened.model,
|
|
38794
|
+
parentMessageId: opened.parent_message_id ?? void 0,
|
|
38795
|
+
wasStopped: opened.status === "tool_request",
|
|
38796
|
+
uniqueId: messageId
|
|
38248
38797
|
});
|
|
38249
|
-
|
|
38250
|
-
|
|
38251
|
-
|
|
38252
|
-
|
|
38253
|
-
|
|
38254
|
-
|
|
38255
|
-
if (!existing) {
|
|
38256
|
-
const parent = opened.parent_message_id;
|
|
38257
|
-
const ownsTurn = parent ? (await backend.getMessagesByIds([parent])).length > 0 : await backend.getConversation(opened.conversation_id) !== null;
|
|
38258
|
-
if (!ownsTurn) {
|
|
38259
|
-
results.push({ ...base, status: "elsewhere", assistantMessage: null });
|
|
38260
|
-
continue;
|
|
38261
|
-
}
|
|
38262
|
-
}
|
|
38263
|
-
let stored2 = existing;
|
|
38264
|
-
if (!stored2) {
|
|
38265
|
-
const { redactor } = resolveCallPii(
|
|
38266
|
-
void 0,
|
|
38267
|
-
piiRedaction,
|
|
38268
|
-
() => getConversationRedactor(opened.conversation_id, nerDetectorRef.current)
|
|
38269
|
-
);
|
|
38270
|
-
const knownToolCallEventIds = await backend.getToolCallEventIds(opened.conversation_id);
|
|
38271
|
-
const { fields, fileIds } = await toAssistantMessageFields(
|
|
38272
|
-
opened.response,
|
|
38273
|
-
opened.conversation_id,
|
|
38274
|
-
knownToolCallEventIds
|
|
38275
|
-
);
|
|
38276
|
-
stored2 = await backend.createMessage({
|
|
38277
|
-
...fields,
|
|
38278
|
-
content: redactor ? redactor.deAnonymize(fields.content) : fields.content,
|
|
38279
|
-
thinking: redactor && fields.thinking ? redactor.deAnonymize(fields.thinking) : fields.thinking,
|
|
38280
|
-
conversationId: opened.conversation_id,
|
|
38281
|
-
role: "assistant",
|
|
38282
|
-
model: opened.model,
|
|
38283
|
-
parentMessageId: opened.parent_message_id ?? void 0,
|
|
38284
|
-
wasStopped: opened.status === "tool_request" ? true : void 0,
|
|
38285
|
-
uniqueId: messageId
|
|
38286
|
-
});
|
|
38287
|
-
if (fileIds.length > 0) {
|
|
38288
|
-
try {
|
|
38289
|
-
await updateMediaMessageIdBatchOp(mediaCtx, fileIds, stored2.uniqueId);
|
|
38290
|
-
} catch (err) {
|
|
38291
|
-
getLogger().warn("[useChatStorage] Failed to link inbox media:", err);
|
|
38292
|
-
}
|
|
38798
|
+
const stored2 = await clearTurnErrors(backend, upserted);
|
|
38799
|
+
if (fileIds.length > 0) {
|
|
38800
|
+
try {
|
|
38801
|
+
await updateMediaMessageIdBatchOp(mediaCtx, fileIds, stored2.uniqueId);
|
|
38802
|
+
} catch (err) {
|
|
38803
|
+
getLogger().warn("[useChatStorage] Failed to link inbox media:", err);
|
|
38293
38804
|
}
|
|
38294
|
-
void embedMessageAsync(stored2, (text16) => redactor ? redactor.maskText(text16) : text16);
|
|
38295
38805
|
}
|
|
38296
|
-
|
|
38297
|
-
|
|
38298
|
-
...base,
|
|
38299
|
-
status: existing ? "delivered" : "stored",
|
|
38300
|
-
assistantMessage: stored2
|
|
38301
|
-
});
|
|
38302
|
-
} catch (err) {
|
|
38303
|
-
results.push({
|
|
38304
|
-
...base,
|
|
38305
|
-
status: "retry",
|
|
38306
|
-
assistantMessage: null,
|
|
38307
|
-
error: err instanceof Error ? err.message : String(err)
|
|
38308
|
-
});
|
|
38806
|
+
void embedMessageAsync(stored2, (text16) => redactor ? redactor.maskText(text16) : text16);
|
|
38807
|
+
return stored2;
|
|
38309
38808
|
}
|
|
38310
|
-
}
|
|
38311
|
-
return results;
|
|
38809
|
+
});
|
|
38312
38810
|
}, [
|
|
38313
38811
|
inbox,
|
|
38314
38812
|
walletAddress,
|
|
@@ -39308,11 +39806,11 @@ async function fetchAllModelPages(baseUrl, provider, headers, previous, signal)
|
|
|
39308
39806
|
return { pages, models, fetchedAt: Date.now() };
|
|
39309
39807
|
}
|
|
39310
39808
|
function loadModels(key3, baseUrl, provider, headers, force, signal) {
|
|
39311
|
-
const
|
|
39312
|
-
if (
|
|
39313
|
-
return Promise.resolve([...
|
|
39809
|
+
const cached2 = modelsCache.get(key3);
|
|
39810
|
+
if (cached2 && !force && Date.now() - cached2.fetchedAt < MODELS_CACHE_TTL_MS) {
|
|
39811
|
+
return Promise.resolve([...cached2.models]);
|
|
39314
39812
|
}
|
|
39315
|
-
const shared = (force ? void 0 : modelsInFlight.get(key3)) ?? startSharedRequest(key3, baseUrl, provider, headers,
|
|
39813
|
+
const shared = (force ? void 0 : modelsInFlight.get(key3)) ?? startSharedRequest(key3, baseUrl, provider, headers, cached2);
|
|
39316
39814
|
return waitForSharedRequest(key3, shared, signal).then((models) => [...models]);
|
|
39317
39815
|
}
|
|
39318
39816
|
function startSharedRequest(key3, baseUrl, provider, headers, previous) {
|
|
@@ -40165,20 +40663,20 @@ function startObserve(entry, walletAddress) {
|
|
|
40165
40663
|
"updated_at"
|
|
40166
40664
|
]).subscribe({
|
|
40167
40665
|
next: (records) => {
|
|
40168
|
-
const
|
|
40169
|
-
if (!
|
|
40666
|
+
const record3 = records[0];
|
|
40667
|
+
if (!record3) return;
|
|
40170
40668
|
const patch = {
|
|
40171
40669
|
userPreference: {
|
|
40172
|
-
uniqueId:
|
|
40173
|
-
walletAddress:
|
|
40174
|
-
nickname:
|
|
40175
|
-
occupation:
|
|
40176
|
-
description:
|
|
40177
|
-
models:
|
|
40178
|
-
personality:
|
|
40179
|
-
externalWallets:
|
|
40180
|
-
createdAt:
|
|
40181
|
-
updatedAt:
|
|
40670
|
+
uniqueId: record3.id,
|
|
40671
|
+
walletAddress: record3.walletAddress,
|
|
40672
|
+
nickname: record3.nickname,
|
|
40673
|
+
occupation: record3.occupation,
|
|
40674
|
+
description: record3.description,
|
|
40675
|
+
models: record3.models,
|
|
40676
|
+
personality: record3.personality,
|
|
40677
|
+
externalWallets: record3.externalWallets,
|
|
40678
|
+
createdAt: record3.createdAt,
|
|
40679
|
+
updatedAt: record3.updatedAt
|
|
40182
40680
|
}
|
|
40183
40681
|
};
|
|
40184
40682
|
if (isInitialEmission) {
|