@anuma/sdk 10.10.0 → 11.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/expo/index.cjs +1024 -552
- package/dist/expo/index.d.mts +9 -5
- package/dist/expo/index.d.ts +9 -5
- package/dist/expo/index.mjs +1020 -552
- package/dist/react/index.cjs +1204 -661
- package/dist/react/index.d.mts +9 -5
- package/dist/react/index.d.ts +9 -5
- package/dist/react/index.mjs +1200 -661
- package/dist/tools/index.cjs +36 -2
- package/dist/tools/index.mjs +36 -2
- package/package.json +1 -1
package/dist/react/index.cjs
CHANGED
|
@@ -2394,9 +2394,9 @@ async function refreshEncryptionKeyIfMatches(walletAddress, probeCiphertext, sig
|
|
|
2394
2394
|
return false;
|
|
2395
2395
|
}
|
|
2396
2396
|
const startEpoch = sessionEpoch;
|
|
2397
|
-
const
|
|
2398
|
-
if (
|
|
2399
|
-
return tryCommitCandidatesIfProbeMatches(walletAddress, parsed,
|
|
2397
|
+
const cached2 = refreshCandidatesByAddress.get(walletAddress);
|
|
2398
|
+
if (cached2) {
|
|
2399
|
+
return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, cached2, startEpoch);
|
|
2400
2400
|
}
|
|
2401
2401
|
let derivePromise = pendingCandidateDerives.get(walletAddress);
|
|
2402
2402
|
if (!derivePromise) {
|
|
@@ -2748,10 +2748,10 @@ function parsePlaintextToken(raw, walletAddress) {
|
|
|
2748
2748
|
return null;
|
|
2749
2749
|
}
|
|
2750
2750
|
if (!parsed || typeof parsed !== "object") return null;
|
|
2751
|
-
const
|
|
2752
|
-
const data =
|
|
2751
|
+
const record3 = parsed;
|
|
2752
|
+
const data = record3.token?.accessToken ? record3.token : record3;
|
|
2753
2753
|
if (!data?.accessToken) return null;
|
|
2754
|
-
if (
|
|
2754
|
+
if (record3.wallet && record3.wallet !== walletAddress) return null;
|
|
2755
2755
|
return data;
|
|
2756
2756
|
}
|
|
2757
2757
|
function promoteUnscopedRow(raw, data, store, scopedKey, unscopedKey, walletAddress) {
|
|
@@ -2843,10 +2843,10 @@ async function discoverOAuthMetadata() {
|
|
|
2843
2843
|
}
|
|
2844
2844
|
async function getOAuthMetadata() {
|
|
2845
2845
|
if (typeof window !== "undefined") {
|
|
2846
|
-
const
|
|
2847
|
-
if (
|
|
2846
|
+
const cached2 = sessionStorage.getItem(OAUTH_METADATA_KEY);
|
|
2847
|
+
if (cached2) {
|
|
2848
2848
|
try {
|
|
2849
|
-
return JSON.parse(
|
|
2849
|
+
return JSON.parse(cached2);
|
|
2850
2850
|
} catch {
|
|
2851
2851
|
}
|
|
2852
2852
|
}
|
|
@@ -2950,8 +2950,8 @@ async function storeTokenData(data, walletAddress) {
|
|
|
2950
2950
|
} catch {
|
|
2951
2951
|
}
|
|
2952
2952
|
}
|
|
2953
|
-
const
|
|
2954
|
-
sessionStorage.setItem(getTokenStorageKey(walletAddress), JSON.stringify(
|
|
2953
|
+
const record3 = { wallet: walletAddress, token: data };
|
|
2954
|
+
sessionStorage.setItem(getTokenStorageKey(walletAddress), JSON.stringify(record3));
|
|
2955
2955
|
}
|
|
2956
2956
|
async function getStoredTokenData(walletAddress) {
|
|
2957
2957
|
if (typeof window === "undefined") return null;
|
|
@@ -3355,25 +3355,25 @@ var TRUNCATION_MARKER_HEAD = "... (tool output truncated, ";
|
|
|
3355
3355
|
var TRUNCATION_MARKER_TAIL = " characters omitted)";
|
|
3356
3356
|
var MAX_PERSISTED_TOOL_RESULT_CHARS = 1e5;
|
|
3357
3357
|
function buildToolResultContent(results) {
|
|
3358
|
-
const
|
|
3358
|
+
const entries2 = results.map(
|
|
3359
3359
|
(r) => `Tool "${r.name}" returned: ${JSON.stringify(r.result)}`.replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029")
|
|
3360
3360
|
);
|
|
3361
|
-
const framing = HEADER.length + FOOTER.length + ENTRY_SEPARATOR.length * Math.max(0,
|
|
3362
|
-
const summary = capEntries(
|
|
3361
|
+
const framing = HEADER.length + FOOTER.length + ENTRY_SEPARATOR.length * Math.max(0, entries2.length - 1);
|
|
3362
|
+
const summary = capEntries(entries2, MAX_PERSISTED_TOOL_RESULT_CHARS - framing).join(
|
|
3363
3363
|
ENTRY_SEPARATOR
|
|
3364
3364
|
);
|
|
3365
3365
|
return `${HEADER}${summary}${FOOTER}`;
|
|
3366
3366
|
}
|
|
3367
|
-
function capToolResultEntries(
|
|
3368
|
-
return capEntries(
|
|
3367
|
+
function capToolResultEntries(entries2, budget) {
|
|
3368
|
+
return capEntries(entries2, budget);
|
|
3369
3369
|
}
|
|
3370
|
-
function capEntries(
|
|
3371
|
-
const smallestFirst =
|
|
3372
|
-
const capped = [...
|
|
3370
|
+
function capEntries(entries2, budget) {
|
|
3371
|
+
const smallestFirst = entries2.map((_, index) => index).sort((a, b) => entries2[a].length - entries2[b].length);
|
|
3372
|
+
const capped = [...entries2];
|
|
3373
3373
|
let remaining = budget;
|
|
3374
|
-
let unassigned =
|
|
3374
|
+
let unassigned = entries2.length;
|
|
3375
3375
|
for (const index of smallestFirst) {
|
|
3376
|
-
capped[index] = truncateEntry(
|
|
3376
|
+
capped[index] = truncateEntry(entries2[index], Math.floor(remaining / unassigned));
|
|
3377
3377
|
remaining -= capped[index].length;
|
|
3378
3378
|
unassigned--;
|
|
3379
3379
|
}
|
|
@@ -4265,11 +4265,11 @@ var ToolCallEventIndex = class {
|
|
|
4265
4265
|
this.pending = /* @__PURE__ */ new Map();
|
|
4266
4266
|
this.resetCount = collection.database._resetCount;
|
|
4267
4267
|
collection.experimentalSubscribe((changes) => {
|
|
4268
|
-
for (const { record:
|
|
4268
|
+
for (const { record: record3, type } of changes) {
|
|
4269
4269
|
this.replace(
|
|
4270
|
-
|
|
4271
|
-
type === "destroyed" ? void 0 :
|
|
4272
|
-
type === "destroyed" ? void 0 :
|
|
4270
|
+
record3.id,
|
|
4271
|
+
type === "destroyed" ? void 0 : record3.conversationId,
|
|
4272
|
+
type === "destroyed" ? void 0 : record3._getRaw("tool_call_events")
|
|
4273
4273
|
);
|
|
4274
4274
|
}
|
|
4275
4275
|
});
|
|
@@ -5712,15 +5712,15 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
5712
5712
|
staleSkipped++;
|
|
5713
5713
|
continue;
|
|
5714
5714
|
}
|
|
5715
|
-
const
|
|
5716
|
-
if (!
|
|
5715
|
+
const cached2 = chunkCache?.get(key3.id);
|
|
5716
|
+
if (!cached2 || cached2.version !== key3.version) {
|
|
5717
5717
|
missIds.push(key3.id);
|
|
5718
5718
|
continue;
|
|
5719
5719
|
}
|
|
5720
5720
|
cacheHits++;
|
|
5721
|
-
if (
|
|
5722
|
-
for (let ci = 0; ci <
|
|
5723
|
-
const vec =
|
|
5721
|
+
if (cached2.chunks.length > 0) {
|
|
5722
|
+
for (let ci = 0; ci < cached2.chunks.length; ci++) {
|
|
5723
|
+
const vec = cached2.chunks[ci];
|
|
5724
5724
|
if (vec.length === 0) continue;
|
|
5725
5725
|
const similarity = cosineSimilarity(queryVector, vec);
|
|
5726
5726
|
if (similarity >= minSimilarity) {
|
|
@@ -5733,8 +5733,8 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
5733
5733
|
});
|
|
5734
5734
|
}
|
|
5735
5735
|
}
|
|
5736
|
-
} else if (
|
|
5737
|
-
const similarity = cosineSimilarity(queryVector,
|
|
5736
|
+
} else if (cached2.fallback) {
|
|
5737
|
+
const similarity = cosineSimilarity(queryVector, cached2.fallback);
|
|
5738
5738
|
if (similarity >= minSimilarity) {
|
|
5739
5739
|
candidates.push({
|
|
5740
5740
|
id: key3.id,
|
|
@@ -6550,11 +6550,11 @@ var mergeConfigs = (a, b) => {
|
|
|
6550
6550
|
return config;
|
|
6551
6551
|
};
|
|
6552
6552
|
var headersEntries = (headers) => {
|
|
6553
|
-
const
|
|
6553
|
+
const entries2 = [];
|
|
6554
6554
|
headers.forEach((value, key3) => {
|
|
6555
|
-
|
|
6555
|
+
entries2.push([key3, value]);
|
|
6556
6556
|
});
|
|
6557
|
-
return
|
|
6557
|
+
return entries2;
|
|
6558
6558
|
};
|
|
6559
6559
|
var mergeHeaders = (...headers) => {
|
|
6560
6560
|
const mergedHeaders = new Headers();
|
|
@@ -7034,9 +7034,9 @@ async function embedOne(text16, options, outer) {
|
|
|
7034
7034
|
const { cache } = options;
|
|
7035
7035
|
if (!cache) return Array.from(await requestEmbedding(text16, options, outer));
|
|
7036
7036
|
const model = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
7037
|
-
const
|
|
7038
|
-
const cachedModel =
|
|
7039
|
-
if (
|
|
7037
|
+
const cached2 = cache.get(text16);
|
|
7038
|
+
const cachedModel = cached2 && cachedEmbeddingModels.get(cached2);
|
|
7039
|
+
if (cached2 && (cachedModel === void 0 || cachedModel === model)) return Array.from(cached2);
|
|
7040
7040
|
const inFlight = inFlightByCache.get(cache) ?? /* @__PURE__ */ new Map();
|
|
7041
7041
|
inFlightByCache.set(cache, inFlight);
|
|
7042
7042
|
const requestKey = JSON.stringify([model, text16]);
|
|
@@ -7151,10 +7151,10 @@ async function embedMany(texts, options, outer) {
|
|
|
7151
7151
|
const uncachedTexts = [];
|
|
7152
7152
|
for (let i = 0; i < texts.length; i++) {
|
|
7153
7153
|
if (cache) {
|
|
7154
|
-
const
|
|
7155
|
-
const cachedModel =
|
|
7156
|
-
if (
|
|
7157
|
-
results[i] = Array.from(
|
|
7154
|
+
const cached2 = cache.get(texts[i]);
|
|
7155
|
+
const cachedModel = cached2 && cachedEmbeddingModels.get(cached2);
|
|
7156
|
+
if (cached2 && (cachedModel === void 0 || cachedModel === embeddingModel)) {
|
|
7157
|
+
results[i] = Array.from(cached2);
|
|
7158
7158
|
continue;
|
|
7159
7159
|
}
|
|
7160
7160
|
}
|
|
@@ -7540,8 +7540,12 @@ function createCryptoPricePreProcessor(options = {}) {
|
|
|
7540
7540
|
}
|
|
7541
7541
|
|
|
7542
7542
|
// src/lib/memory/store/remotePersistence.ts
|
|
7543
|
+
init_logger();
|
|
7543
7544
|
init_portalLlm();
|
|
7544
7545
|
|
|
7546
|
+
// src/lib/memory/store/remoteTopics.ts
|
|
7547
|
+
init_logger();
|
|
7548
|
+
|
|
7545
7549
|
// src/lib/db/entities/types.ts
|
|
7546
7550
|
var ENTITY_KINDS = [
|
|
7547
7551
|
"person",
|
|
@@ -7598,58 +7602,337 @@ function parseTopics(value) {
|
|
|
7598
7602
|
return out;
|
|
7599
7603
|
}
|
|
7600
7604
|
|
|
7605
|
+
// src/lib/memory/store/topicCodec.ts
|
|
7606
|
+
var ciphertextPattern = /^enc:v\d+:[0-9a-f]+$/i;
|
|
7607
|
+
var topicHashPattern = /^[0-9a-f]{64}$/;
|
|
7608
|
+
var MAX_SEALED_TOPIC_NAME_BYTES = 1024;
|
|
7609
|
+
function normalizeTopicName(name) {
|
|
7610
|
+
return normalizeEntityName(name).normalize("NFC");
|
|
7611
|
+
}
|
|
7612
|
+
function sealedTopicNamesFit(json5) {
|
|
7613
|
+
return (entries(json5) ?? []).every(
|
|
7614
|
+
(entry) => !hashed(entry) || typeof entry.name !== "string" || entry.name.length <= MAX_SEALED_TOPIC_NAME_BYTES
|
|
7615
|
+
);
|
|
7616
|
+
}
|
|
7617
|
+
function record(value) {
|
|
7618
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7619
|
+
}
|
|
7620
|
+
function hashed(entry) {
|
|
7621
|
+
return record(entry) && typeof entry.name_hash === "string";
|
|
7622
|
+
}
|
|
7623
|
+
function entries(json5) {
|
|
7624
|
+
if (typeof json5 !== "string") return void 0;
|
|
7625
|
+
try {
|
|
7626
|
+
const parsed = JSON.parse(json5);
|
|
7627
|
+
return Array.isArray(parsed) ? parsed : void 0;
|
|
7628
|
+
} catch {
|
|
7629
|
+
return void 0;
|
|
7630
|
+
}
|
|
7631
|
+
}
|
|
7632
|
+
function cached(cache, key3, load) {
|
|
7633
|
+
let pending = cache.get(key3);
|
|
7634
|
+
if (!pending) {
|
|
7635
|
+
const loading = load();
|
|
7636
|
+
pending = loading;
|
|
7637
|
+
cache.set(key3, loading);
|
|
7638
|
+
loading.catch(() => {
|
|
7639
|
+
if (cache.get(key3) === loading) cache.delete(key3);
|
|
7640
|
+
});
|
|
7641
|
+
}
|
|
7642
|
+
return pending;
|
|
7643
|
+
}
|
|
7644
|
+
function createTopicCodec(cipher) {
|
|
7645
|
+
const hashes = /* @__PURE__ */ new Map();
|
|
7646
|
+
const opened = /* @__PURE__ */ new Map();
|
|
7647
|
+
const seals = /* @__PURE__ */ new Map();
|
|
7648
|
+
const legacyNames = /* @__PURE__ */ new Map();
|
|
7649
|
+
const hash = async (name) => {
|
|
7650
|
+
const normalized2 = normalizeTopicName(name);
|
|
7651
|
+
if (!normalized2) return null;
|
|
7652
|
+
return cached(hashes, normalized2, async () => {
|
|
7653
|
+
const digest = await cipher.hashTopic(normalized2);
|
|
7654
|
+
if (!topicHashPattern.test(digest))
|
|
7655
|
+
throw new Error("Topic hashing must return 64 lowercase hex characters");
|
|
7656
|
+
return digest;
|
|
7657
|
+
});
|
|
7658
|
+
};
|
|
7659
|
+
const seal = async (display) => {
|
|
7660
|
+
const nameHash = await hash(display);
|
|
7661
|
+
if (nameHash === null) return null;
|
|
7662
|
+
return cached(seals, display, async () => {
|
|
7663
|
+
const name = await cipher.encrypt(display);
|
|
7664
|
+
if (name === display || !ciphertextPattern.test(name))
|
|
7665
|
+
throw new Error(
|
|
7666
|
+
"Topic encryption must return SDK ciphertext; refusing to upload plaintext"
|
|
7667
|
+
);
|
|
7668
|
+
opened.set(name, Promise.resolve(display));
|
|
7669
|
+
return { name_hash: nameHash, name };
|
|
7670
|
+
});
|
|
7671
|
+
};
|
|
7672
|
+
const plain2 = (name) => {
|
|
7673
|
+
if (!ciphertextPattern.test(name)) return Promise.resolve(name);
|
|
7674
|
+
let pending = legacyNames.get(name);
|
|
7675
|
+
if (!pending) {
|
|
7676
|
+
pending = cipher.decrypt(name).catch(() => name);
|
|
7677
|
+
legacyNames.set(name, pending);
|
|
7678
|
+
}
|
|
7679
|
+
return pending;
|
|
7680
|
+
};
|
|
7681
|
+
const open = async ({ name, name_hash: nameHash }) => {
|
|
7682
|
+
if (nameHash === void 0) return plain2(name);
|
|
7683
|
+
if (typeof name !== "string" || typeof nameHash !== "string" || !topicHashPattern.test(nameHash) || !ciphertextPattern.test(name))
|
|
7684
|
+
throw new Error("Nearby returned a malformed topic name");
|
|
7685
|
+
const plaintext = await cached(opened, name, async () => {
|
|
7686
|
+
const value = await cipher.decrypt(name);
|
|
7687
|
+
if (value === name) throw new Error("Topic decryption failed");
|
|
7688
|
+
return value;
|
|
7689
|
+
});
|
|
7690
|
+
if (await hash(plaintext) !== nameHash) throw new Error("Topic name does not match its hash");
|
|
7691
|
+
if (!seals.has(plaintext)) seals.set(plaintext, Promise.resolve({ name_hash: nameHash, name }));
|
|
7692
|
+
return plaintext;
|
|
7693
|
+
};
|
|
7694
|
+
return {
|
|
7695
|
+
hash,
|
|
7696
|
+
seal,
|
|
7697
|
+
open,
|
|
7698
|
+
encodeTopics: async (json5) => {
|
|
7699
|
+
const list = entries(json5);
|
|
7700
|
+
if (!list) return json5;
|
|
7701
|
+
const sealed2 = await Promise.all(
|
|
7702
|
+
list.map(async (entry) => {
|
|
7703
|
+
if (!record(entry) || typeof entry.name !== "string") return null;
|
|
7704
|
+
const name = await seal(await plain2(entry.name));
|
|
7705
|
+
return name && { ...entry, name: name.name, name_hash: name.name_hash };
|
|
7706
|
+
})
|
|
7707
|
+
);
|
|
7708
|
+
return JSON.stringify(sealed2.filter((entry) => entry !== null));
|
|
7709
|
+
},
|
|
7710
|
+
decodeTopics: async (json5) => {
|
|
7711
|
+
const list = entries(json5);
|
|
7712
|
+
if (!list?.some(
|
|
7713
|
+
(entry) => hashed(entry) || record(entry) && typeof entry.name === "string" && ciphertextPattern.test(entry.name)
|
|
7714
|
+
))
|
|
7715
|
+
return json5;
|
|
7716
|
+
const decoded = await Promise.all(
|
|
7717
|
+
list.map(async (entry) => {
|
|
7718
|
+
if (!hashed(entry))
|
|
7719
|
+
return record(entry) && typeof entry.name === "string" ? { ...entry, name: await plain2(entry.name) } : entry;
|
|
7720
|
+
const { name_hash: nameHash, ...rest } = entry;
|
|
7721
|
+
return { ...rest, name: await open({ name: entry.name, name_hash: nameHash }) };
|
|
7722
|
+
})
|
|
7723
|
+
);
|
|
7724
|
+
return JSON.stringify(decoded);
|
|
7725
|
+
},
|
|
7726
|
+
isLegacy: (json5) => (entries(json5) ?? []).some(
|
|
7727
|
+
(entry) => record(entry) && typeof entry.name === "string" && !hashed(entry)
|
|
7728
|
+
),
|
|
7729
|
+
matchesLegacy: async (json5, names, hashes2) => {
|
|
7730
|
+
const list = typeof json5 === "string" ? entries(json5) ?? [] : [];
|
|
7731
|
+
if (list.some((entry) => hashed(entry) && hashes2.has(entry.name_hash))) return false;
|
|
7732
|
+
const legacy = await Promise.all(
|
|
7733
|
+
list.map(
|
|
7734
|
+
async (entry) => record(entry) && typeof entry.name === "string" && !hashed(entry) ? normalizeTopicName(await plain2(entry.name)) : null
|
|
7735
|
+
)
|
|
7736
|
+
);
|
|
7737
|
+
return legacy.some((name) => name !== null && names.has(name));
|
|
7738
|
+
},
|
|
7739
|
+
encodeCatalog: async (topic2) => {
|
|
7740
|
+
const sealed2 = await seal(normalizeTopicName(await plain2(topic2.name)));
|
|
7741
|
+
return sealed2 && { ...topic2, name: sealed2.name, name_hash: sealed2.name_hash };
|
|
7742
|
+
},
|
|
7743
|
+
decodeCatalog: async (item) => {
|
|
7744
|
+
const { name_hash: nameHash, ...rest } = item;
|
|
7745
|
+
return { ...rest, name: await open({ name: item.name, name_hash: nameHash }) };
|
|
7746
|
+
}
|
|
7747
|
+
};
|
|
7748
|
+
}
|
|
7749
|
+
|
|
7601
7750
|
// src/lib/memory/store/remoteTopics.ts
|
|
7751
|
+
var RETIRE_CONCURRENCY = 8;
|
|
7602
7752
|
function topic(value) {
|
|
7603
7753
|
const t = value;
|
|
7604
|
-
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")
|
|
7754
|
+
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")
|
|
7605
7755
|
throw new Error("Invalid nearby topic");
|
|
7606
7756
|
return t;
|
|
7607
7757
|
}
|
|
7608
|
-
function
|
|
7758
|
+
async function wireTopics(request, signal) {
|
|
7759
|
+
const out = [];
|
|
7760
|
+
let cursor;
|
|
7761
|
+
do {
|
|
7762
|
+
const page = await request(
|
|
7763
|
+
"/topics?limit=200" + (cursor ? `&cursor=${encodeURIComponent(cursor)}` : ""),
|
|
7764
|
+
{},
|
|
7765
|
+
signal
|
|
7766
|
+
);
|
|
7767
|
+
if (!Array.isArray(page.items) || page.next_cursor !== void 0 && typeof page.next_cursor !== "string")
|
|
7768
|
+
throw new Error("Invalid nearby topic page");
|
|
7769
|
+
out.push(...page.items.map(topic));
|
|
7770
|
+
cursor = page.next_cursor;
|
|
7771
|
+
} while (cursor);
|
|
7772
|
+
return out;
|
|
7773
|
+
}
|
|
7774
|
+
function hashesOf(items) {
|
|
7775
|
+
return new Set(items.flatMap((t) => t.name_hash === void 0 ? [] : [t.name_hash]));
|
|
7776
|
+
}
|
|
7777
|
+
async function sealedImport(request, codec, topics, signal) {
|
|
7778
|
+
let oversized = 0;
|
|
7779
|
+
for (let i = 0; i < topics.length; i += 50) {
|
|
7780
|
+
signal?.throwIfAborted();
|
|
7781
|
+
const sealed2 = (await Promise.all(topics.slice(i, i + 50).map((t) => codec.encodeCatalog(t)))).filter((t) => {
|
|
7782
|
+
if (t === null) return false;
|
|
7783
|
+
if (t.name.length <= MAX_SEALED_TOPIC_NAME_BYTES) return true;
|
|
7784
|
+
oversized++;
|
|
7785
|
+
return false;
|
|
7786
|
+
});
|
|
7787
|
+
if (sealed2.length)
|
|
7788
|
+
await request(
|
|
7789
|
+
"/topics/import",
|
|
7790
|
+
{ method: "POST", body: JSON.stringify({ topics: sealed2 }) },
|
|
7791
|
+
signal
|
|
7792
|
+
);
|
|
7793
|
+
}
|
|
7794
|
+
signal?.throwIfAborted();
|
|
7795
|
+
if (oversized)
|
|
7796
|
+
getLogger().warn(
|
|
7797
|
+
`[memory/remote] Skipped ${oversized} topic catalog entries whose sealed name exceeds ${MAX_SEALED_TOPIC_NAME_BYTES} bytes`
|
|
7798
|
+
);
|
|
7799
|
+
}
|
|
7800
|
+
function createRemoteTopicPersistence(request, codec) {
|
|
7801
|
+
let legacyOnly = /* @__PURE__ */ new Set();
|
|
7609
7802
|
return {
|
|
7610
7803
|
topics: async () => {
|
|
7611
|
-
const
|
|
7612
|
-
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
|
|
7620
|
-
|
|
7621
|
-
|
|
7622
|
-
|
|
7623
|
-
|
|
7804
|
+
const items = await wireTopics(request);
|
|
7805
|
+
const hashed2 = hashesOf(items);
|
|
7806
|
+
const legacy = /* @__PURE__ */ new Set();
|
|
7807
|
+
const decoded = await Promise.all(
|
|
7808
|
+
items.map(async (item) => {
|
|
7809
|
+
const plain2 = await codec.decodeCatalog(item);
|
|
7810
|
+
const name = normalizeTopicName(plain2.name);
|
|
7811
|
+
if (item.name_hash === void 0) {
|
|
7812
|
+
const hash = await codec.hash(name);
|
|
7813
|
+
if (hash !== null && hashed2.has(hash)) return null;
|
|
7814
|
+
legacy.add(name);
|
|
7815
|
+
}
|
|
7816
|
+
return { ...plain2, name };
|
|
7817
|
+
})
|
|
7818
|
+
);
|
|
7819
|
+
legacyOnly = legacy;
|
|
7820
|
+
return decoded.filter((t) => t !== null);
|
|
7624
7821
|
},
|
|
7625
7822
|
putTopic: async (value, expectedVersion) => {
|
|
7626
7823
|
if (!Number.isSafeInteger(expectedVersion) || expectedVersion < 0)
|
|
7627
7824
|
throw new Error("Expected topic version must be a nonnegative integer");
|
|
7628
|
-
|
|
7825
|
+
const sealed2 = await codec.encodeCatalog(value);
|
|
7826
|
+
if (!sealed2) throw new Error("Topic name must not be empty");
|
|
7827
|
+
const saved = topic(
|
|
7629
7828
|
await request("/topics", {
|
|
7630
7829
|
method: "PUT",
|
|
7631
|
-
body: JSON.stringify({
|
|
7830
|
+
body: JSON.stringify({
|
|
7831
|
+
topic: sealed2,
|
|
7832
|
+
expected_version: legacyOnly.has(normalizeTopicName(value.name)) ? 0 : expectedVersion
|
|
7833
|
+
})
|
|
7632
7834
|
})
|
|
7633
7835
|
);
|
|
7634
|
-
|
|
7635
|
-
|
|
7636
|
-
|
|
7637
|
-
|
|
7638
|
-
|
|
7639
|
-
|
|
7640
|
-
|
|
7641
|
-
|
|
7642
|
-
|
|
7643
|
-
|
|
7644
|
-
|
|
7645
|
-
|
|
7646
|
-
|
|
7836
|
+
const decoded = await codec.decodeCatalog(saved);
|
|
7837
|
+
legacyOnly.delete(decoded.name);
|
|
7838
|
+
return decoded;
|
|
7839
|
+
},
|
|
7840
|
+
importTopics: (topics, signal) => sealedImport(
|
|
7841
|
+
request,
|
|
7842
|
+
codec,
|
|
7843
|
+
topics.map(({ name, kind }) => ({ name, ...kind !== void 0 && { kind } })),
|
|
7844
|
+
signal
|
|
7845
|
+
)
|
|
7846
|
+
};
|
|
7847
|
+
}
|
|
7848
|
+
async function retireLegacyTopics(request, codec, topics, imported, signal) {
|
|
7849
|
+
const failures = [];
|
|
7850
|
+
const put = async (topic2, expectedVersion) => {
|
|
7851
|
+
try {
|
|
7852
|
+
await request(
|
|
7853
|
+
"/topics",
|
|
7854
|
+
{ method: "PUT", body: JSON.stringify({ topic: topic2, expected_version: expectedVersion }) },
|
|
7855
|
+
signal
|
|
7856
|
+
);
|
|
7857
|
+
return "saved";
|
|
7858
|
+
} catch (error) {
|
|
7859
|
+
if (signal?.aborted) throw error;
|
|
7860
|
+
if (error instanceof RemoteMemoryError && error.status === 409) return "conflict";
|
|
7861
|
+
failures.push(error);
|
|
7862
|
+
return "failed";
|
|
7863
|
+
}
|
|
7864
|
+
};
|
|
7865
|
+
const retire = (item) => put(
|
|
7866
|
+
{ name: item.name, ...item.kind !== void 0 && { kind: item.kind }, is_deleted: true },
|
|
7867
|
+
item.version
|
|
7868
|
+
);
|
|
7869
|
+
const changed = [];
|
|
7870
|
+
let next = 0;
|
|
7871
|
+
const worker = async () => {
|
|
7872
|
+
while (next < topics.length) {
|
|
7647
7873
|
signal?.throwIfAborted();
|
|
7874
|
+
const item = topics[next++];
|
|
7875
|
+
if (await retire(item) === "conflict") changed.push(item);
|
|
7648
7876
|
}
|
|
7649
7877
|
};
|
|
7878
|
+
await Promise.all(
|
|
7879
|
+
Array.from({ length: Math.min(RETIRE_CONCURRENCY, topics.length) }, () => worker())
|
|
7880
|
+
);
|
|
7881
|
+
if (changed.length) {
|
|
7882
|
+
const current = await wireTopics(request, signal);
|
|
7883
|
+
for (const stale of changed) {
|
|
7884
|
+
const legacy = current.find((t) => t.name_hash === void 0 && t.name === stale.name);
|
|
7885
|
+
if (!legacy || legacy.is_deleted) continue;
|
|
7886
|
+
const hash = await codec.hash(await codec.open(legacy));
|
|
7887
|
+
const copy = current.find((t) => t.name_hash !== void 0 && t.name_hash === hash);
|
|
7888
|
+
if (!copy || hash === null) continue;
|
|
7889
|
+
const newer = imported.has(hash) || Date.parse(legacy.server_updated_at) > Date.parse(copy.server_updated_at);
|
|
7890
|
+
if (newer && (copy.is_deleted || legacy.kind !== copy.kind)) {
|
|
7891
|
+
const sealed2 = await codec.encodeCatalog({
|
|
7892
|
+
name: legacy.name,
|
|
7893
|
+
...legacy.kind !== void 0 && { kind: legacy.kind },
|
|
7894
|
+
is_deleted: false
|
|
7895
|
+
});
|
|
7896
|
+
if (!sealed2 || await put(sealed2, copy.version) !== "saved") continue;
|
|
7897
|
+
}
|
|
7898
|
+
await retire(legacy);
|
|
7899
|
+
}
|
|
7900
|
+
}
|
|
7901
|
+
if (failures.length)
|
|
7902
|
+
getLogger().warn(
|
|
7903
|
+
`[memory/remote] Could not retire ${failures.length} upgraded topic catalog entries:`,
|
|
7904
|
+
failures[0]
|
|
7905
|
+
);
|
|
7906
|
+
}
|
|
7907
|
+
async function upgradeLegacyTopicCatalog(request, codec, signal) {
|
|
7908
|
+
const items = await wireTopics(request, signal);
|
|
7909
|
+
const hashed2 = hashesOf(items);
|
|
7910
|
+
const hashes = await Promise.all(
|
|
7911
|
+
items.map(
|
|
7912
|
+
async (item) => item.name_hash === void 0 ? codec.hash(await codec.open(item)) : null
|
|
7913
|
+
)
|
|
7914
|
+
);
|
|
7915
|
+
const sources = /* @__PURE__ */ new Map();
|
|
7916
|
+
const live2 = [];
|
|
7917
|
+
items.forEach((item, i) => {
|
|
7918
|
+
const hash = hashes[i];
|
|
7919
|
+
if (hash === null) return;
|
|
7920
|
+
if (!item.is_deleted) live2.push(item);
|
|
7921
|
+
if (hashed2.has(hash)) return;
|
|
7922
|
+
const source = sources.get(hash);
|
|
7923
|
+
if (!source || source.is_deleted && !item.is_deleted) sources.set(hash, item);
|
|
7924
|
+
});
|
|
7925
|
+
const legacy = [...sources.values()].map((item) => ({
|
|
7926
|
+
name: item.name,
|
|
7927
|
+
...item.kind !== void 0 && { kind: item.kind },
|
|
7928
|
+
...item.is_deleted && { is_deleted: true }
|
|
7929
|
+
}));
|
|
7930
|
+
await sealedImport(request, codec, legacy, signal);
|
|
7931
|
+
await retireLegacyTopics(request, codec, live2, new Set(sources.keys()), signal);
|
|
7932
|
+
return legacy.length;
|
|
7650
7933
|
}
|
|
7651
7934
|
async function createRemoteTopic(persistence, name) {
|
|
7652
|
-
const canonical =
|
|
7935
|
+
const canonical = normalizeTopicName(name);
|
|
7653
7936
|
if (!canonical) return null;
|
|
7654
7937
|
const existing = (await persistence.topics()).find((t) => t.name === canonical);
|
|
7655
7938
|
if (existing && !existing.is_deleted) return canonical;
|
|
@@ -7738,7 +8021,10 @@ var RemoteMemoryError = class extends Error {
|
|
|
7738
8021
|
this.name = "RemoteMemoryError";
|
|
7739
8022
|
}
|
|
7740
8023
|
};
|
|
7741
|
-
var
|
|
8024
|
+
var TOPIC_UPGRADE_PROCESSOR = "topic-hash-v1";
|
|
8025
|
+
var TOPIC_UPGRADE_PAGE = 50;
|
|
8026
|
+
var LEGACY_TOPIC_CURSOR = "legacy-topics:";
|
|
8027
|
+
var LEGACY_TOPIC_RECHECK_MS = 6e4;
|
|
7742
8028
|
var memoryFields = {
|
|
7743
8029
|
memory_id: true,
|
|
7744
8030
|
content: true,
|
|
@@ -7798,7 +8084,8 @@ var queryFields = [
|
|
|
7798
8084
|
"fact_types",
|
|
7799
8085
|
"visibility",
|
|
7800
8086
|
"memory_ids",
|
|
7801
|
-
"
|
|
8087
|
+
"topic_hashes",
|
|
8088
|
+
"topics_legacy",
|
|
7802
8089
|
"updated_after",
|
|
7803
8090
|
"topics_due",
|
|
7804
8091
|
"topics_extracted",
|
|
@@ -7808,11 +8095,17 @@ var queryFields = [
|
|
|
7808
8095
|
"limit",
|
|
7809
8096
|
"include_embeddings"
|
|
7810
8097
|
];
|
|
7811
|
-
function
|
|
8098
|
+
function isVersionConflict(error) {
|
|
8099
|
+
return error instanceof RemoteMemoryError && error.code === "version_conflict";
|
|
8100
|
+
}
|
|
8101
|
+
function isRejectedRow(error) {
|
|
8102
|
+
return error instanceof RemoteMemoryError && error.status === 400;
|
|
8103
|
+
}
|
|
8104
|
+
function record2(value) {
|
|
7812
8105
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7813
8106
|
}
|
|
7814
8107
|
function memoryRecord(value) {
|
|
7815
|
-
if (!
|
|
8108
|
+
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))) {
|
|
7816
8109
|
throw new Error("Invalid nearby private-memory response");
|
|
7817
8110
|
}
|
|
7818
8111
|
return value;
|
|
@@ -7892,14 +8185,14 @@ function createNearbyRequest(options, apiPath = "/api/private-memories") {
|
|
|
7892
8185
|
const body = await response.json().catch(() => null);
|
|
7893
8186
|
const retryAfter = parseRetryAfterMs(response.headers.get("Retry-After"));
|
|
7894
8187
|
const error = new RemoteMemoryError(
|
|
7895
|
-
|
|
8188
|
+
record2(body) && typeof body.detail === "string" ? body.detail : `Nearby request failed (${response.status})`,
|
|
7896
8189
|
response.status,
|
|
7897
|
-
|
|
8190
|
+
record2(body) && typeof body.code === "string" ? body.code : void 0,
|
|
7898
8191
|
retryAfter ?? void 0,
|
|
7899
|
-
|
|
8192
|
+
record2(body) && typeof body.rate_limit_bucket === "string" ? body.rate_limit_bucket : void 0
|
|
7900
8193
|
);
|
|
7901
8194
|
if (response.status === 429 && retryAfter !== null && retryAfter > 0 && (!error.code || error.code === "rate_limited")) {
|
|
7902
|
-
const bucket = error.rateLimitBucket && budgets.includes(error.rateLimitBucket) ? error.rateLimitBucket :
|
|
8195
|
+
const bucket = error.rateLimitBucket && budgets.includes(error.rateLimitBucket) ? error.rateLimitBucket : record2(body) && (body.limit_scope === "account" || body.limit_scope === "ip") && !error.rateLimitBucket ? "*" : route;
|
|
7903
8196
|
cooldowns.set(bucket, { until: Date.now() + retryAfter, error });
|
|
7904
8197
|
}
|
|
7905
8198
|
throw error;
|
|
@@ -7922,7 +8215,7 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
7922
8215
|
throw new Error("A canonical keyId is required");
|
|
7923
8216
|
const request = createNearbyRequest(options);
|
|
7924
8217
|
const account = await request("/account", {}, options.signal);
|
|
7925
|
-
if (!
|
|
8218
|
+
if (!record2(account) || account.state !== "active") {
|
|
7926
8219
|
throw new RemoteMemoryError(
|
|
7927
8220
|
"Complete and verify migration before using remote memories",
|
|
7928
8221
|
409,
|
|
@@ -7936,6 +8229,25 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
7936
8229
|
"key_mismatch"
|
|
7937
8230
|
);
|
|
7938
8231
|
}
|
|
8232
|
+
const codec = createTopicCodec(options);
|
|
8233
|
+
let legacyTopicRows = typeof account.legacy_topic_memories === "number" && account.legacy_topic_memories > 0;
|
|
8234
|
+
if (typeof account.legacy_topic_catalog === "number" && account.legacy_topic_catalog > 0)
|
|
8235
|
+
void upgradeLegacyTopicCatalog(request, codec, options.signal).catch((error) => {
|
|
8236
|
+
if (!options.signal?.aborted)
|
|
8237
|
+
getLogger().warn("[memory/remote] Topic catalog upgrade failed:", error);
|
|
8238
|
+
});
|
|
8239
|
+
let legacyCheckedAt = Date.now();
|
|
8240
|
+
let legacyCheck;
|
|
8241
|
+
const recheckLegacyTopicRows = () => {
|
|
8242
|
+
if (legacyCheck || Date.now() - legacyCheckedAt < LEGACY_TOPIC_RECHECK_MS) return;
|
|
8243
|
+
legacyCheckedAt = Date.now();
|
|
8244
|
+
legacyCheck = request("/account", {}, options.signal).then((current) => {
|
|
8245
|
+
if (record2(current) && current.legacy_topic_memories === 0) legacyTopicRows = false;
|
|
8246
|
+
}).catch(() => {
|
|
8247
|
+
}).finally(() => {
|
|
8248
|
+
legacyCheck = void 0;
|
|
8249
|
+
});
|
|
8250
|
+
};
|
|
7939
8251
|
const snapshots = /* @__PURE__ */ new WeakMap();
|
|
7940
8252
|
const decode = async (value) => {
|
|
7941
8253
|
const item = memoryRecord(value);
|
|
@@ -7953,6 +8265,9 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
7953
8265
|
content: item.memory.is_deleted && item.memory.content === "" ? "" : await decrypt(item.memory.content),
|
|
7954
8266
|
...item.memory.kind_value !== void 0 && {
|
|
7955
8267
|
kind_value: await decrypt(item.memory.kind_value)
|
|
8268
|
+
},
|
|
8269
|
+
...item.memory.topics !== void 0 && {
|
|
8270
|
+
topics: await codec.decodeTopics(item.memory.topics)
|
|
7956
8271
|
}
|
|
7957
8272
|
}
|
|
7958
8273
|
};
|
|
@@ -7964,8 +8279,10 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
7964
8279
|
version: item.version,
|
|
7965
8280
|
content: decoded.memory.content,
|
|
7966
8281
|
kindValue: decoded.memory.kind_value,
|
|
8282
|
+
topics: decoded.memory.topics,
|
|
7967
8283
|
encryptedContent: item.memory.content,
|
|
7968
|
-
encryptedKindValue: item.memory.kind_value
|
|
8284
|
+
encryptedKindValue: item.memory.kind_value,
|
|
8285
|
+
encryptedTopics: item.memory.topics
|
|
7969
8286
|
});
|
|
7970
8287
|
return decoded;
|
|
7971
8288
|
};
|
|
@@ -7987,7 +8304,7 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
7987
8304
|
};
|
|
7988
8305
|
const decodeCommitted = async (value, write) => {
|
|
7989
8306
|
const item = memoryRecord(value);
|
|
7990
|
-
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)
|
|
8307
|
+
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)
|
|
7991
8308
|
return decode(item);
|
|
7992
8309
|
return remember(
|
|
7993
8310
|
{
|
|
@@ -7995,7 +8312,8 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
7995
8312
|
memory: {
|
|
7996
8313
|
...item.memory,
|
|
7997
8314
|
content: write.content,
|
|
7998
|
-
...write.kindValue !== void 0 && { kind_value: write.kindValue }
|
|
8315
|
+
...write.kindValue !== void 0 && { kind_value: write.kindValue },
|
|
8316
|
+
...write.topics !== void 0 && { topics: write.topics }
|
|
7999
8317
|
}
|
|
8000
8318
|
},
|
|
8001
8319
|
item
|
|
@@ -8047,13 +8365,21 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
8047
8365
|
const reusableContent = snapshot?.encryptedContent ?? existing?.memory.content;
|
|
8048
8366
|
const content = reusableContent && (snapshot?.content ?? decoded?.memory.content) === memory.content ? reusableContent : await encryptField2(memory.content);
|
|
8049
8367
|
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);
|
|
8368
|
+
const wireTopics2 = snapshot ? snapshot.encryptedTopics : existing?.memory.topics;
|
|
8369
|
+
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);
|
|
8050
8370
|
return {
|
|
8051
8371
|
body: {
|
|
8052
8372
|
expected_version: expectedVersion,
|
|
8053
|
-
memory: {
|
|
8373
|
+
memory: {
|
|
8374
|
+
...memory,
|
|
8375
|
+
content,
|
|
8376
|
+
...kindValue !== void 0 && { kind_value: kindValue },
|
|
8377
|
+
...topics !== void 0 && { topics }
|
|
8378
|
+
}
|
|
8054
8379
|
},
|
|
8055
8380
|
content: memory.content,
|
|
8056
|
-
kindValue: memory.kind_value
|
|
8381
|
+
kindValue: memory.kind_value,
|
|
8382
|
+
topics: memory.topics
|
|
8057
8383
|
};
|
|
8058
8384
|
};
|
|
8059
8385
|
const fetchCandidates = async (embedding2, candidateOptions, withCounts) => {
|
|
@@ -8102,32 +8428,72 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
8102
8428
|
},
|
|
8103
8429
|
candidateOptions.signal
|
|
8104
8430
|
);
|
|
8105
|
-
if (!
|
|
8431
|
+
if (!record2(result) || !Array.isArray(result.items))
|
|
8106
8432
|
throw new Error("Invalid nearby candidate response");
|
|
8107
8433
|
return result;
|
|
8108
8434
|
};
|
|
8109
8435
|
const fetchQueryPage = async (queryOptions) => {
|
|
8110
|
-
const { signal, ...
|
|
8111
|
-
if (
|
|
8436
|
+
const { signal, topics: names, ...wire2 } = queryOptions;
|
|
8437
|
+
if (wire2.limit !== void 0 && (!Number.isInteger(wire2.limit) || wire2.limit < 1 || wire2.limit > 200))
|
|
8112
8438
|
throw new Error("Page limit must be 1\u2013200");
|
|
8113
8439
|
for (const [key3, max] of queryListLimits) {
|
|
8114
|
-
const values =
|
|
8440
|
+
const values = queryOptions[key3];
|
|
8115
8441
|
if (values && values.length > max)
|
|
8116
8442
|
throw new Error(`Query ${key3} accepts at most ${max} entries (got ${values.length})`);
|
|
8117
8443
|
}
|
|
8444
|
+
const body = wire2;
|
|
8445
|
+
if (names === void 0) return postQuery(body, signal);
|
|
8446
|
+
const hashes = [
|
|
8447
|
+
...new Set(
|
|
8448
|
+
(await Promise.all(names.map((name) => codec.hash(name)))).filter((h) => h !== null)
|
|
8449
|
+
)
|
|
8450
|
+
];
|
|
8451
|
+
if (names.length > 0 && hashes.length === 0) return { items: [] };
|
|
8452
|
+
if (hashes.length > 0 && wire2.cursor?.startsWith(LEGACY_TOPIC_CURSOR)) {
|
|
8453
|
+
const page2 = await postQuery(
|
|
8454
|
+
{
|
|
8455
|
+
...wire2,
|
|
8456
|
+
cursor: wire2.cursor.slice(LEGACY_TOPIC_CURSOR.length) || void 0,
|
|
8457
|
+
topics_legacy: true
|
|
8458
|
+
},
|
|
8459
|
+
signal
|
|
8460
|
+
);
|
|
8461
|
+
const wanted = new Set(names.map(normalizeTopicName));
|
|
8462
|
+
const hashed2 = new Set(hashes);
|
|
8463
|
+
const matches = await Promise.all(
|
|
8464
|
+
page2.items.map(
|
|
8465
|
+
(item) => codec.matchesLegacy(
|
|
8466
|
+
record2(item) && record2(item.memory) ? item.memory.topics : void 0,
|
|
8467
|
+
wanted,
|
|
8468
|
+
hashed2
|
|
8469
|
+
)
|
|
8470
|
+
)
|
|
8471
|
+
);
|
|
8472
|
+
return {
|
|
8473
|
+
...page2,
|
|
8474
|
+
items: page2.items.filter((_, i) => matches[i]),
|
|
8475
|
+
next_cursor: page2.next_cursor === void 0 ? void 0 : LEGACY_TOPIC_CURSOR + page2.next_cursor
|
|
8476
|
+
};
|
|
8477
|
+
}
|
|
8478
|
+
const page = await postQuery({ ...body, topic_hashes: hashes }, signal);
|
|
8479
|
+
if (hashes.length === 0 || page.next_cursor !== void 0 || !legacyTopicRows) return page;
|
|
8480
|
+
recheckLegacyTopicRows();
|
|
8481
|
+
return { ...page, next_cursor: LEGACY_TOPIC_CURSOR };
|
|
8482
|
+
};
|
|
8483
|
+
const postQuery = async (body, signal) => {
|
|
8118
8484
|
const page = await request(
|
|
8119
8485
|
"/memories/query",
|
|
8120
8486
|
{
|
|
8121
8487
|
method: "POST",
|
|
8122
8488
|
body: JSON.stringify(
|
|
8123
8489
|
Object.fromEntries(
|
|
8124
|
-
queryFields.filter((key3) =>
|
|
8490
|
+
queryFields.filter((key3) => body[key3] !== void 0).map((key3) => [key3, body[key3]])
|
|
8125
8491
|
)
|
|
8126
8492
|
)
|
|
8127
8493
|
},
|
|
8128
8494
|
signal
|
|
8129
8495
|
);
|
|
8130
|
-
if (!
|
|
8496
|
+
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")
|
|
8131
8497
|
throw new Error("Invalid nearby private-memory page");
|
|
8132
8498
|
return page;
|
|
8133
8499
|
};
|
|
@@ -8141,13 +8507,13 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
8141
8507
|
unavailable_count: result.unavailable_count
|
|
8142
8508
|
};
|
|
8143
8509
|
};
|
|
8144
|
-
|
|
8145
|
-
...createRemoteTopicPersistence(request),
|
|
8510
|
+
const persistence = {
|
|
8511
|
+
...createRemoteTopicPersistence(request, codec),
|
|
8146
8512
|
...createRemoteWorkPersistence(request),
|
|
8147
8513
|
supportsRealtimeChanges: account.realtime_changes === true,
|
|
8148
8514
|
counts: async () => {
|
|
8149
8515
|
const result = await request("/counts", {});
|
|
8150
|
-
if (!
|
|
8516
|
+
if (!record2(result) || ["live", "archived", "quarantined"].some(
|
|
8151
8517
|
(key3) => !Number.isSafeInteger(result[key3]) || result[key3] < 0
|
|
8152
8518
|
))
|
|
8153
8519
|
throw new Error("Invalid nearby memory counts");
|
|
@@ -8164,8 +8530,8 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
8164
8530
|
method: "POST",
|
|
8165
8531
|
body: JSON.stringify({ ...window2, limit })
|
|
8166
8532
|
});
|
|
8167
|
-
if (!
|
|
8168
|
-
(item) => !
|
|
8533
|
+
if (!record2(result) || !Array.isArray(result.items) || result.items.some(
|
|
8534
|
+
(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
|
|
8169
8535
|
))
|
|
8170
8536
|
throw new Error("Invalid nearby temporal candidates");
|
|
8171
8537
|
return result.items.map((item) => item.memory_id);
|
|
@@ -8196,7 +8562,7 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
8196
8562
|
if (query[key3] !== void 0) params.set(key3, String(query[key3]));
|
|
8197
8563
|
}
|
|
8198
8564
|
const page = await request("/memories?" + params.toString(), {}, signal);
|
|
8199
|
-
if (!
|
|
8565
|
+
if (!record2(page) || !Array.isArray(page.items) || page.next_cursor !== void 0 && typeof page.next_cursor !== "string") {
|
|
8200
8566
|
throw new Error("Invalid nearby private-memory page");
|
|
8201
8567
|
}
|
|
8202
8568
|
return {
|
|
@@ -8236,7 +8602,7 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
8236
8602
|
},
|
|
8237
8603
|
signal
|
|
8238
8604
|
);
|
|
8239
|
-
if (!
|
|
8605
|
+
if (!record2(result) || !Array.isArray(result.items) || result.items.length !== prepared.length)
|
|
8240
8606
|
throw new Error("Invalid nearby batch response");
|
|
8241
8607
|
return Promise.all(result.items.map((item, i) => decodeCommitted(item, prepared[i])));
|
|
8242
8608
|
},
|
|
@@ -8251,20 +8617,87 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
8251
8617
|
queryMetadata: async (queryOptions = {}) => {
|
|
8252
8618
|
const page = await fetchQueryPage(queryOptions);
|
|
8253
8619
|
return {
|
|
8254
|
-
items:
|
|
8255
|
-
|
|
8256
|
-
|
|
8257
|
-
|
|
8258
|
-
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
|
|
8620
|
+
items: await Promise.all(
|
|
8621
|
+
page.items.map(async (item) => {
|
|
8622
|
+
const {
|
|
8623
|
+
memory: { content: _content, kind_value: _kindValue, topics, ...memory },
|
|
8624
|
+
version,
|
|
8625
|
+
server_updated_at
|
|
8626
|
+
} = memoryRecord(item);
|
|
8627
|
+
const plain2 = topics === void 0 ? void 0 : await codec.decodeTopics(topics).catch(() => null);
|
|
8628
|
+
return {
|
|
8629
|
+
memory: { ...memory, ...typeof plain2 === "string" && { topics: plain2 } },
|
|
8630
|
+
version,
|
|
8631
|
+
server_updated_at
|
|
8632
|
+
};
|
|
8633
|
+
})
|
|
8634
|
+
),
|
|
8262
8635
|
...page.next_cursor !== void 0 && { next_cursor: page.next_cursor }
|
|
8263
8636
|
};
|
|
8264
8637
|
},
|
|
8265
8638
|
candidateSet,
|
|
8266
8639
|
candidates: async (embedding2, candidateOptions = {}) => decodeAll((await fetchCandidates(embedding2, candidateOptions, false)).items)
|
|
8267
8640
|
};
|
|
8641
|
+
let rejectedRows = 0;
|
|
8642
|
+
const rewriteLegacyTopics = async (records, token) => {
|
|
8643
|
+
const write = (batch) => persistence.putMany(
|
|
8644
|
+
batch.map((item) => ({ memory: item.memory, expectedVersion: item })),
|
|
8645
|
+
options.signal,
|
|
8646
|
+
token
|
|
8647
|
+
);
|
|
8648
|
+
try {
|
|
8649
|
+
await write(records);
|
|
8650
|
+
return true;
|
|
8651
|
+
} catch (error) {
|
|
8652
|
+
if (!isVersionConflict(error) && !isRejectedRow(error)) throw error;
|
|
8653
|
+
if (records.length === 1) {
|
|
8654
|
+
if (isRejectedRow(error)) rejectedRows++;
|
|
8655
|
+
return false;
|
|
8656
|
+
}
|
|
8657
|
+
let complete = true;
|
|
8658
|
+
for (const item of records)
|
|
8659
|
+
await write([item]).catch((rowError) => {
|
|
8660
|
+
if (isRejectedRow(rowError)) rejectedRows++;
|
|
8661
|
+
else if (!isVersionConflict(rowError)) throw rowError;
|
|
8662
|
+
complete = false;
|
|
8663
|
+
});
|
|
8664
|
+
return complete;
|
|
8665
|
+
}
|
|
8666
|
+
};
|
|
8667
|
+
const upgradeLegacyTopics = () => withRemoteWorkLease(persistence, "topics", TOPIC_UPGRADE_PROCESSOR, async (token, lease) => {
|
|
8668
|
+
let cursor;
|
|
8669
|
+
let complete = true;
|
|
8670
|
+
do {
|
|
8671
|
+
options.signal?.throwIfAborted();
|
|
8672
|
+
if (lease.aborted) return false;
|
|
8673
|
+
const page = await fetchQueryPage({
|
|
8674
|
+
topics_legacy: true,
|
|
8675
|
+
include_archived: true,
|
|
8676
|
+
include_quarantined: true,
|
|
8677
|
+
include_superseded: true,
|
|
8678
|
+
limit: TOPIC_UPGRADE_PAGE,
|
|
8679
|
+
...cursor !== void 0 && { cursor },
|
|
8680
|
+
signal: options.signal
|
|
8681
|
+
});
|
|
8682
|
+
const { items } = await decodeAll(page.items);
|
|
8683
|
+
const legacy = items.filter((item) => codec.isLegacy(snapshots.get(item)?.encryptedTopics));
|
|
8684
|
+
if (legacy.length && !await rewriteLegacyTopics(legacy, token)) complete = false;
|
|
8685
|
+
cursor = page.next_cursor;
|
|
8686
|
+
} while (cursor);
|
|
8687
|
+
if (rejectedRows)
|
|
8688
|
+
getLogger().warn(
|
|
8689
|
+
`[memory/remote] Nearby rejected ${rejectedRows} rows during the topic upgrade; they keep legacy topics`
|
|
8690
|
+
);
|
|
8691
|
+
return complete;
|
|
8692
|
+
});
|
|
8693
|
+
if (legacyTopicRows)
|
|
8694
|
+
void upgradeLegacyTopics().then((complete) => {
|
|
8695
|
+
if (complete) legacyTopicRows = false;
|
|
8696
|
+
}).catch((error) => {
|
|
8697
|
+
if (!options.signal?.aborted)
|
|
8698
|
+
getLogger().warn("[memory/remote] Topic upgrade failed:", error);
|
|
8699
|
+
});
|
|
8700
|
+
return persistence;
|
|
8268
8701
|
}
|
|
8269
8702
|
|
|
8270
8703
|
// src/lib/chat/inbox.ts
|
|
@@ -8826,9 +9259,9 @@ function toResponsesFormat(tool) {
|
|
|
8826
9259
|
function getCachedServerTools() {
|
|
8827
9260
|
if (typeof localStorage === "undefined") return null;
|
|
8828
9261
|
try {
|
|
8829
|
-
const
|
|
8830
|
-
if (!
|
|
8831
|
-
const parsed = JSON.parse(
|
|
9262
|
+
const cached2 = localStorage.getItem(SERVER_TOOLS_CACHE_KEY);
|
|
9263
|
+
if (!cached2) return null;
|
|
9264
|
+
const parsed = JSON.parse(cached2);
|
|
8832
9265
|
if (parsed.version !== CACHE_VERSION) {
|
|
8833
9266
|
removeLocalStorageCache();
|
|
8834
9267
|
return null;
|
|
@@ -8872,8 +9305,8 @@ function clearServerToolsCache(cache = localStorageToolsCache) {
|
|
|
8872
9305
|
return cache.clear?.();
|
|
8873
9306
|
}
|
|
8874
9307
|
function getToolsChecksum2(cache = localStorageToolsCache) {
|
|
8875
|
-
const
|
|
8876
|
-
return
|
|
9308
|
+
const cached2 = cache.get();
|
|
9309
|
+
return cached2 instanceof Promise ? cached2.then((c) => c?.checksum) : cached2?.checksum;
|
|
8877
9310
|
}
|
|
8878
9311
|
function shouldRefreshTools(responseChecksum, cache = localStorageToolsCache) {
|
|
8879
9312
|
if (!responseChecksum) {
|
|
@@ -8936,33 +9369,33 @@ async function getServerTools(options) {
|
|
|
8936
9369
|
} catch (error) {
|
|
8937
9370
|
getLogger().warn("[serverTools] Cache read failed; falling through to server fetch:", error);
|
|
8938
9371
|
}
|
|
8939
|
-
const
|
|
8940
|
-
const cacheValid = !isCacheExpired(
|
|
8941
|
-
if (
|
|
8942
|
-
return
|
|
9372
|
+
const cached2 = rawCached && rawCached.version === CACHE_VERSION ? rawCached : null;
|
|
9373
|
+
const cacheValid = !isCacheExpired(cached2, cacheExpirationMs);
|
|
9374
|
+
if (cached2 && cacheValid && !forceRefresh) {
|
|
9375
|
+
return cached2.tools;
|
|
8943
9376
|
}
|
|
8944
9377
|
try {
|
|
8945
9378
|
const { BASE_URL: BASE_URL2 } = await Promise.resolve().then(() => (init_clientConfig(), clientConfig_exports));
|
|
8946
9379
|
const effectiveBaseUrl = baseUrl ?? BASE_URL2;
|
|
8947
|
-
const validator =
|
|
9380
|
+
const validator = cached2 && !forceRefresh ? cached2.etag : void 0;
|
|
8948
9381
|
let authHeaders;
|
|
8949
9382
|
if (apiKey) {
|
|
8950
9383
|
authHeaders = { "X-API-Key": apiKey };
|
|
8951
9384
|
} else {
|
|
8952
9385
|
if (!getToken) {
|
|
8953
9386
|
getLogger().warn("[serverTools] No auth method available for fetching tools");
|
|
8954
|
-
return
|
|
9387
|
+
return cached2?.tools ?? [];
|
|
8955
9388
|
}
|
|
8956
9389
|
const token = await getToken();
|
|
8957
9390
|
if (!token) {
|
|
8958
9391
|
getLogger().warn("[serverTools] No auth token available for fetching tools");
|
|
8959
|
-
return
|
|
9392
|
+
return cached2?.tools ?? [];
|
|
8960
9393
|
}
|
|
8961
9394
|
authHeaders = { Authorization: `Bearer ${token}` };
|
|
8962
9395
|
}
|
|
8963
9396
|
const result = await fetchServerToolsFromApi(effectiveBaseUrl, authHeaders, validator);
|
|
8964
9397
|
if (result.notModified) {
|
|
8965
|
-
const confirmed =
|
|
9398
|
+
const confirmed = cached2;
|
|
8966
9399
|
await persistCache({ ...confirmed, timestamp: Date.now() });
|
|
8967
9400
|
return confirmed.tools;
|
|
8968
9401
|
}
|
|
@@ -8970,9 +9403,9 @@ async function getServerTools(options) {
|
|
|
8970
9403
|
return result.tools;
|
|
8971
9404
|
} catch (error) {
|
|
8972
9405
|
getLogger().error("[serverTools] Failed to fetch server tools:", error);
|
|
8973
|
-
if (
|
|
9406
|
+
if (cached2?.tools) {
|
|
8974
9407
|
getLogger().warn("[serverTools] Using stale cached tools due to fetch error");
|
|
8975
|
-
return
|
|
9408
|
+
return cached2.tools;
|
|
8976
9409
|
}
|
|
8977
9410
|
return [];
|
|
8978
9411
|
}
|
|
@@ -10110,13 +10543,13 @@ function extractParamGroups(content) {
|
|
|
10110
10543
|
}
|
|
10111
10544
|
function mergeXaiInlineParameterTags(content, toolCalls) {
|
|
10112
10545
|
if (!content || !content.includes(PARAM_MARKER)) return content;
|
|
10113
|
-
const
|
|
10114
|
-
if (
|
|
10546
|
+
const entries2 = Array.from(toolCalls.values());
|
|
10547
|
+
if (entries2.length === 0) return content;
|
|
10115
10548
|
const groups = extractParamGroups(content);
|
|
10116
10549
|
if (groups.length === 0) return content;
|
|
10117
|
-
const pairCount = Math.min(groups.length,
|
|
10550
|
+
const pairCount = Math.min(groups.length, entries2.length);
|
|
10118
10551
|
for (let i = 0; i < pairCount; i++) {
|
|
10119
|
-
const target =
|
|
10552
|
+
const target = entries2[i];
|
|
10120
10553
|
const params = groups[i];
|
|
10121
10554
|
if (!target || !params) continue;
|
|
10122
10555
|
let args = {};
|
|
@@ -13438,21 +13871,21 @@ function contextFields(context) {
|
|
|
13438
13871
|
);
|
|
13439
13872
|
}
|
|
13440
13873
|
function conversationContext(data) {
|
|
13441
|
-
const
|
|
13442
|
-
return
|
|
13874
|
+
const entries2 = Object.entries(data).filter(([field10]) => field10.startsWith(CONTEXT_FIELD_PREFIX)).map(([field10, value]) => [field10.slice(CONTEXT_FIELD_PREFIX.length), value]);
|
|
13875
|
+
return entries2.length > 0 ? plain(Object.fromEntries(entries2)) : void 0;
|
|
13443
13876
|
}
|
|
13444
|
-
function toConversation(
|
|
13445
|
-
const pinnedAt = number(
|
|
13446
|
-
const projectId = text3(
|
|
13447
|
-
const context = conversationContext(
|
|
13877
|
+
function toConversation(record3) {
|
|
13878
|
+
const pinnedAt = number(record3.data.pinnedAt);
|
|
13879
|
+
const projectId = text3(record3.data.projectId);
|
|
13880
|
+
const context = conversationContext(record3.data);
|
|
13448
13881
|
return {
|
|
13449
|
-
uniqueId:
|
|
13450
|
-
conversationId:
|
|
13451
|
-
title: text3(
|
|
13882
|
+
uniqueId: record3.id,
|
|
13883
|
+
conversationId: record3.id,
|
|
13884
|
+
title: text3(record3.data.title) ?? "",
|
|
13452
13885
|
...projectId ? { projectId } : {},
|
|
13453
|
-
createdAt: new Date(
|
|
13454
|
-
updatedAt: new Date(
|
|
13455
|
-
isDeleted:
|
|
13886
|
+
createdAt: new Date(record3.createdAt),
|
|
13887
|
+
updatedAt: new Date(record3.updatedAt),
|
|
13888
|
+
isDeleted: record3.isDeleted,
|
|
13456
13889
|
pinnedAt: pinnedAt ? new Date(pinnedAt) : null,
|
|
13457
13890
|
...context ? { context } : {}
|
|
13458
13891
|
};
|
|
@@ -13474,21 +13907,21 @@ function messageData(options) {
|
|
|
13474
13907
|
...anuma ? { anuma } : {}
|
|
13475
13908
|
});
|
|
13476
13909
|
}
|
|
13477
|
-
function toMessage(
|
|
13478
|
-
const { chunkOffsets: _offsets, truncated: _truncated, anuma: rawAnuma, ...fields } =
|
|
13910
|
+
function toMessage(record3) {
|
|
13911
|
+
const { chunkOffsets: _offsets, truncated: _truncated, anuma: rawAnuma, ...fields } = record3.data;
|
|
13479
13912
|
const anuma = readAnumaTurn(rawAnuma);
|
|
13480
13913
|
return {
|
|
13481
13914
|
...anuma ? { anuma } : {},
|
|
13482
13915
|
...fields,
|
|
13483
|
-
uniqueId:
|
|
13484
|
-
messageId:
|
|
13485
|
-
conversationId:
|
|
13486
|
-
createdAt: new Date(
|
|
13487
|
-
updatedAt: new Date(
|
|
13916
|
+
uniqueId: record3.id,
|
|
13917
|
+
messageId: record3.sortKey,
|
|
13918
|
+
conversationId: record3.conversationId,
|
|
13919
|
+
createdAt: new Date(record3.createdAt),
|
|
13920
|
+
updatedAt: new Date(record3.updatedAt)
|
|
13488
13921
|
};
|
|
13489
13922
|
}
|
|
13490
|
-
function chunkOffsets(
|
|
13491
|
-
const offsets =
|
|
13923
|
+
function chunkOffsets(record3) {
|
|
13924
|
+
const offsets = record3.data.chunkOffsets;
|
|
13492
13925
|
return Array.isArray(offsets) ? offsets : void 0;
|
|
13493
13926
|
}
|
|
13494
13927
|
function toSkeletons(records) {
|
|
@@ -13509,15 +13942,15 @@ function toSkeletons(records) {
|
|
|
13509
13942
|
};
|
|
13510
13943
|
});
|
|
13511
13944
|
}
|
|
13512
|
-
function toSummary(
|
|
13945
|
+
function toSummary(record3) {
|
|
13513
13946
|
return {
|
|
13514
|
-
uniqueId:
|
|
13515
|
-
conversationId:
|
|
13516
|
-
summary: text3(
|
|
13517
|
-
summarizedUpTo: text3(
|
|
13518
|
-
tokenCount: number(
|
|
13519
|
-
createdAt: new Date(
|
|
13520
|
-
updatedAt: new Date(
|
|
13947
|
+
uniqueId: record3.id,
|
|
13948
|
+
conversationId: record3.id,
|
|
13949
|
+
summary: text3(record3.data.summary) ?? "",
|
|
13950
|
+
summarizedUpTo: text3(record3.data.summarizedUpTo) ?? "",
|
|
13951
|
+
tokenCount: number(record3.data.tokenCount) ?? 0,
|
|
13952
|
+
createdAt: new Date(record3.createdAt),
|
|
13953
|
+
updatedAt: new Date(record3.updatedAt)
|
|
13521
13954
|
};
|
|
13522
13955
|
}
|
|
13523
13956
|
function links(data) {
|
|
@@ -13543,10 +13976,10 @@ function applyLinkOps(data, ops) {
|
|
|
13543
13976
|
}
|
|
13544
13977
|
return plain({ links: current });
|
|
13545
13978
|
}
|
|
13546
|
-
function toLinks(
|
|
13547
|
-
return links(
|
|
13548
|
-
uniqueId: `${
|
|
13549
|
-
conversationId:
|
|
13979
|
+
function toLinks(record3) {
|
|
13980
|
+
return links(record3.data).map((l) => ({
|
|
13981
|
+
uniqueId: `${record3.id}:${l.memoryId}`,
|
|
13982
|
+
conversationId: record3.id,
|
|
13550
13983
|
memoryId: l.memoryId,
|
|
13551
13984
|
score: l.score,
|
|
13552
13985
|
createdAt: new Date(l.createdAt)
|
|
@@ -13555,24 +13988,24 @@ function toLinks(record2) {
|
|
|
13555
13988
|
function bytes(value) {
|
|
13556
13989
|
return new TextEncoder().encode(JSON.stringify(value)).length;
|
|
13557
13990
|
}
|
|
13558
|
-
function fitRecord(
|
|
13559
|
-
if (
|
|
13560
|
-
const data = { ...
|
|
13991
|
+
function fitRecord(record3) {
|
|
13992
|
+
if (record3.kind !== "message" || bytes(record3) <= recordBudgetBytes) return record3;
|
|
13993
|
+
const data = { ...record3.data };
|
|
13561
13994
|
const truncated = [];
|
|
13562
13995
|
for (const field10 of droppable) {
|
|
13563
|
-
if (bytes({ ...
|
|
13996
|
+
if (bytes({ ...record3, data }) <= recordBudgetBytes) break;
|
|
13564
13997
|
if (data[field10] === void 0) continue;
|
|
13565
13998
|
delete data[field10];
|
|
13566
13999
|
truncated.push(field10);
|
|
13567
14000
|
}
|
|
13568
14001
|
const content = text3(data.content) ?? "";
|
|
13569
|
-
const over = bytes({ ...
|
|
14002
|
+
const over = bytes({ ...record3, data }) - recordBudgetBytes;
|
|
13570
14003
|
if (over > 0) {
|
|
13571
14004
|
const encoded = new TextEncoder().encode(content);
|
|
13572
14005
|
data.content = new TextDecoder().decode(encoded.slice(0, Math.max(0, encoded.length - over - 64))).replace(/�$/, "");
|
|
13573
14006
|
truncated.push("content");
|
|
13574
14007
|
}
|
|
13575
|
-
return { ...
|
|
14008
|
+
return { ...record3, data: { ...data, truncated } };
|
|
13576
14009
|
}
|
|
13577
14010
|
function acceptedVector(vector2) {
|
|
13578
14011
|
if (!vector2 || !acceptedDims.has(vector2.length)) return void 0;
|
|
@@ -13616,8 +14049,8 @@ function anumaTurnContent(bubbles) {
|
|
|
13616
14049
|
return bubbles.join("\n\n");
|
|
13617
14050
|
}
|
|
13618
14051
|
function anumaLastReadSortKey(conversation) {
|
|
13619
|
-
const
|
|
13620
|
-
const state =
|
|
14052
|
+
const record3 = conversation && "record" in conversation ? conversation.record : conversation;
|
|
14053
|
+
const state = record3?.data.anuma;
|
|
13621
14054
|
if (!isObject(state)) return 0;
|
|
13622
14055
|
const sortKey = state.lastReadSortKey;
|
|
13623
14056
|
return Number.isSafeInteger(sortKey) && sortKey > 0 ? sortKey : 0;
|
|
@@ -13670,19 +14103,19 @@ async function markAnumaRead(store, sortKey, options = {}) {
|
|
|
13670
14103
|
const current = await ensureAnumaConversation(store, options);
|
|
13671
14104
|
const read = anumaLastReadSortKey(current);
|
|
13672
14105
|
if (sortKey <= read) return current;
|
|
13673
|
-
const
|
|
13674
|
-
const state = isObject(
|
|
13675
|
-
const data = plain({ ...
|
|
14106
|
+
const record3 = current.record;
|
|
14107
|
+
const state = isObject(record3.data.anuma) ? record3.data.anuma : {};
|
|
14108
|
+
const data = plain({ ...record3.data, anuma: { ...state, lastReadSortKey: sortKey } });
|
|
13676
14109
|
try {
|
|
13677
14110
|
const [written] = await store.putMany(
|
|
13678
14111
|
[
|
|
13679
14112
|
{
|
|
13680
14113
|
expectedVersion: current.version,
|
|
13681
14114
|
record: {
|
|
13682
|
-
...
|
|
14115
|
+
...record3,
|
|
13683
14116
|
data,
|
|
13684
|
-
sortKey: conversationSortKey(data,
|
|
13685
|
-
updatedAt: Math.max(
|
|
14117
|
+
sortKey: conversationSortKey(data, record3.createdAt),
|
|
14118
|
+
updatedAt: Math.max(record3.updatedAt, now())
|
|
13686
14119
|
}
|
|
13687
14120
|
}
|
|
13688
14121
|
],
|
|
@@ -13718,22 +14151,22 @@ function createSummaryContext(database, encryption = {}) {
|
|
|
13718
14151
|
summariesCollection: database.get("conversation_summaries")
|
|
13719
14152
|
};
|
|
13720
14153
|
}
|
|
13721
|
-
function modelToStored(
|
|
14154
|
+
function modelToStored(record3, summary) {
|
|
13722
14155
|
return {
|
|
13723
|
-
uniqueId:
|
|
13724
|
-
conversationId:
|
|
14156
|
+
uniqueId: record3.id,
|
|
14157
|
+
conversationId: record3.conversationId,
|
|
13725
14158
|
summary,
|
|
13726
|
-
summarizedUpTo:
|
|
13727
|
-
tokenCount:
|
|
13728
|
-
createdAt:
|
|
13729
|
-
updatedAt:
|
|
14159
|
+
summarizedUpTo: record3.summarizedUpTo,
|
|
14160
|
+
tokenCount: record3.tokenCount,
|
|
14161
|
+
createdAt: record3.createdAt,
|
|
14162
|
+
updatedAt: record3.updatedAt
|
|
13730
14163
|
};
|
|
13731
14164
|
}
|
|
13732
14165
|
async function getConversationSummaryOp(ctx, conversationId) {
|
|
13733
14166
|
const results = await ctx.summariesCollection.query(import_watermelondb6.Q.where("conversation_id", conversationId)).fetch();
|
|
13734
14167
|
if (results.length === 0) return null;
|
|
13735
|
-
const
|
|
13736
|
-
const stored2 = modelToStored(
|
|
14168
|
+
const record3 = results[0];
|
|
14169
|
+
const stored2 = modelToStored(record3, record3.summary);
|
|
13737
14170
|
if (ctx.walletAddress && isEncrypted(stored2.summary)) {
|
|
13738
14171
|
if (ctx.signMessage) {
|
|
13739
14172
|
try {
|
|
@@ -13752,7 +14185,7 @@ async function getConversationSummaryOp(ctx, conversationId) {
|
|
|
13752
14185
|
ctx.embeddedWalletSigner
|
|
13753
14186
|
);
|
|
13754
14187
|
await ctx.database.write(async () => {
|
|
13755
|
-
const current = await ctx.summariesCollection.query(import_watermelondb6.Q.where("id",
|
|
14188
|
+
const current = await ctx.summariesCollection.query(import_watermelondb6.Q.where("id", record3.id)).fetch();
|
|
13756
14189
|
if (current[0]?.summary === stored2.summary) {
|
|
13757
14190
|
await current[0].update((rec) => {
|
|
13758
14191
|
rec.summary = encryptedSummary;
|
|
@@ -13767,19 +14200,19 @@ async function getConversationSummaryOp(ctx, conversationId) {
|
|
|
13767
14200
|
}
|
|
13768
14201
|
async function upsertConversationSummaryOp(ctx, conversationId, summary, summarizedUpTo, tokenCount) {
|
|
13769
14202
|
const revision2 = getConversationRevision(ctx.database, conversationId);
|
|
13770
|
-
let
|
|
14203
|
+
let record3;
|
|
13771
14204
|
const encryptedSummary = ctx.walletAddress ? await encryptField(summary, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner) : summary;
|
|
13772
14205
|
await ctx.database.write(async () => {
|
|
13773
14206
|
assertConversationRevision(ctx.database, conversationId, revision2);
|
|
13774
14207
|
const existing = await ctx.summariesCollection.query(import_watermelondb6.Q.where("conversation_id", conversationId)).fetch();
|
|
13775
14208
|
if (existing.length > 0) {
|
|
13776
|
-
|
|
14209
|
+
record3 = await existing[0].update((rec) => {
|
|
13777
14210
|
rec.summary = encryptedSummary;
|
|
13778
14211
|
rec.summarizedUpTo = summarizedUpTo;
|
|
13779
14212
|
rec.tokenCount = tokenCount;
|
|
13780
14213
|
});
|
|
13781
14214
|
} else {
|
|
13782
|
-
|
|
14215
|
+
record3 = await ctx.summariesCollection.create((rec) => {
|
|
13783
14216
|
rec.conversationId = conversationId;
|
|
13784
14217
|
rec.summary = encryptedSummary;
|
|
13785
14218
|
rec.summarizedUpTo = summarizedUpTo;
|
|
@@ -13787,13 +14220,13 @@ async function upsertConversationSummaryOp(ctx, conversationId, summary, summari
|
|
|
13787
14220
|
});
|
|
13788
14221
|
}
|
|
13789
14222
|
});
|
|
13790
|
-
return modelToStored(
|
|
14223
|
+
return modelToStored(record3, summary);
|
|
13791
14224
|
}
|
|
13792
14225
|
async function deleteConversationSummaryOp(ctx, conversationId) {
|
|
13793
14226
|
await ctx.database.write(async () => {
|
|
13794
14227
|
const existing = await ctx.summariesCollection.query(import_watermelondb6.Q.where("conversation_id", conversationId)).fetch();
|
|
13795
|
-
for (const
|
|
13796
|
-
await
|
|
14228
|
+
for (const record3 of existing) {
|
|
14229
|
+
await record3.destroyPermanently();
|
|
13797
14230
|
}
|
|
13798
14231
|
});
|
|
13799
14232
|
}
|
|
@@ -13869,7 +14302,7 @@ function messageRecord(message) {
|
|
|
13869
14302
|
const fitted = chunks3?.length ? fitChunks(chunks3) : void 0;
|
|
13870
14303
|
const single = fitted ? void 0 : acceptedVector(vector2);
|
|
13871
14304
|
const embeddings2 = fitted?.map((c) => c.vector) ?? (single ? [single] : void 0);
|
|
13872
|
-
const
|
|
14305
|
+
const record3 = fitRecord({
|
|
13873
14306
|
kind: "message",
|
|
13874
14307
|
id: message.uniqueId,
|
|
13875
14308
|
conversationId: message.conversationId,
|
|
@@ -13883,7 +14316,7 @@ function messageRecord(message) {
|
|
|
13883
14316
|
}
|
|
13884
14317
|
});
|
|
13885
14318
|
return {
|
|
13886
|
-
record:
|
|
14319
|
+
record: record3,
|
|
13887
14320
|
...embeddings2 ? { embeddings: embeddings2 } : {},
|
|
13888
14321
|
...embeddings2 && message.embeddingModel ? { embeddingModel: message.embeddingModel } : {}
|
|
13889
14322
|
};
|
|
@@ -14031,15 +14464,15 @@ function ref(value) {
|
|
|
14031
14464
|
function sameMetadata(a, b) {
|
|
14032
14465
|
return metadata.every((key3) => a[key3] === b[key3]);
|
|
14033
14466
|
}
|
|
14034
|
-
function wire(
|
|
14467
|
+
function wire(record3, payload) {
|
|
14035
14468
|
return {
|
|
14036
|
-
kind:
|
|
14037
|
-
id:
|
|
14038
|
-
conversation_id:
|
|
14039
|
-
sort_key:
|
|
14040
|
-
created_at:
|
|
14041
|
-
updated_at:
|
|
14042
|
-
is_deleted:
|
|
14469
|
+
kind: record3.kind,
|
|
14470
|
+
id: record3.id,
|
|
14471
|
+
conversation_id: record3.conversationId,
|
|
14472
|
+
sort_key: record3.sortKey,
|
|
14473
|
+
created_at: record3.createdAt,
|
|
14474
|
+
updated_at: record3.updatedAt,
|
|
14475
|
+
is_deleted: record3.isDeleted,
|
|
14043
14476
|
payload
|
|
14044
14477
|
};
|
|
14045
14478
|
}
|
|
@@ -14096,10 +14529,10 @@ async function createRemoteChatStore(options) {
|
|
|
14096
14529
|
serverUpdatedAt: value.server_updated_at
|
|
14097
14530
|
};
|
|
14098
14531
|
};
|
|
14099
|
-
const seal = async (
|
|
14100
|
-
if (
|
|
14532
|
+
const seal = async (record3, signal) => {
|
|
14533
|
+
if (record3.isDeleted) return "";
|
|
14101
14534
|
const payload = await encrypt(
|
|
14102
|
-
JSON.stringify({ schema: 1, account_id: accountId, key_id: keyId, record:
|
|
14535
|
+
JSON.stringify({ schema: 1, account_id: accountId, key_id: keyId, record: record3 })
|
|
14103
14536
|
);
|
|
14104
14537
|
signal?.throwIfAborted();
|
|
14105
14538
|
if (!cipherPattern.test(payload) || payload.length > maxPayload) invalid();
|
|
@@ -14463,8 +14896,8 @@ var emptyMessage = {
|
|
|
14463
14896
|
var maxPasses = 5;
|
|
14464
14897
|
var verifyBatch = 1e3;
|
|
14465
14898
|
var writeBatch = 25;
|
|
14466
|
-
function key(
|
|
14467
|
-
return `${
|
|
14899
|
+
function key(record3) {
|
|
14900
|
+
return `${record3.kind}/${record3.id}`;
|
|
14468
14901
|
}
|
|
14469
14902
|
function sealed(value) {
|
|
14470
14903
|
if (typeof value === "string") return isEncrypted(value);
|
|
@@ -14593,11 +15026,11 @@ async function missing(store, records, signal) {
|
|
|
14593
15026
|
const out = /* @__PURE__ */ new Set();
|
|
14594
15027
|
for (let i = 0; i < records.length; i += verifyBatch) {
|
|
14595
15028
|
const refs = await store.verify(
|
|
14596
|
-
records.slice(i, i + verifyBatch).map(({ record:
|
|
14597
|
-
kind:
|
|
14598
|
-
id:
|
|
14599
|
-
updatedAt:
|
|
14600
|
-
isDeleted:
|
|
15029
|
+
records.slice(i, i + verifyBatch).map(({ record: record3 }) => ({
|
|
15030
|
+
kind: record3.kind,
|
|
15031
|
+
id: record3.id,
|
|
15032
|
+
updatedAt: record3.updatedAt,
|
|
15033
|
+
isDeleted: record3.isDeleted
|
|
14601
15034
|
})),
|
|
14602
15035
|
signal
|
|
14603
15036
|
);
|
|
@@ -14637,14 +15070,14 @@ async function deletedSinceUpload(store, journal, local, signal) {
|
|
|
14637
15070
|
const live2 = (await store.getMany(gone.map(ref2), signal)).filter((s) => !s.record.isDeleted);
|
|
14638
15071
|
const tombstoning = new Set(live2.map((s) => key(s.record)));
|
|
14639
15072
|
await journal.drop(gone.filter((k) => !tombstoning.has(k)));
|
|
14640
|
-
return live2.map(({ record:
|
|
14641
|
-
const empty = emptied[
|
|
15073
|
+
return live2.map(({ record: record3, version }) => {
|
|
15074
|
+
const empty = emptied[record3.kind];
|
|
14642
15075
|
return {
|
|
14643
15076
|
record: {
|
|
14644
|
-
...
|
|
15077
|
+
...record3,
|
|
14645
15078
|
isDeleted: !empty,
|
|
14646
15079
|
data: empty ?? {},
|
|
14647
|
-
updatedAt: Math.max(Date.now(),
|
|
15080
|
+
updatedAt: Math.max(Date.now(), record3.updatedAt + 1)
|
|
14648
15081
|
},
|
|
14649
15082
|
expectedVersion: version
|
|
14650
15083
|
};
|
|
@@ -14993,8 +15426,8 @@ function createVaultAttachments(options) {
|
|
|
14993
15426
|
},
|
|
14994
15427
|
async read(attachmentId, signal) {
|
|
14995
15428
|
if (!attachmentIdPattern2.test(attachmentId)) invalidAttachment();
|
|
14996
|
-
const
|
|
14997
|
-
if (
|
|
15429
|
+
const cached2 = await cache?.get(attachmentId).catch(() => null);
|
|
15430
|
+
if (cached2) return cached2;
|
|
14998
15431
|
for (let attempt = 0; ; attempt++) {
|
|
14999
15432
|
const found = await withRetry(() => store.attachments.get(attachmentId, signal), signal);
|
|
15000
15433
|
if (!found?.download) return null;
|
|
@@ -15023,8 +15456,8 @@ function validRef(value) {
|
|
|
15023
15456
|
const ref3 = value;
|
|
15024
15457
|
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;
|
|
15025
15458
|
}
|
|
15026
|
-
function vaultAttachmentRefs(
|
|
15027
|
-
const refs =
|
|
15459
|
+
function vaultAttachmentRefs(record3) {
|
|
15460
|
+
const refs = record3.data.vaultAttachments;
|
|
15028
15461
|
return Array.isArray(refs) ? refs.filter(validRef) : [];
|
|
15029
15462
|
}
|
|
15030
15463
|
function journalKey(messageId, fileId) {
|
|
@@ -15232,14 +15665,14 @@ function sameRecord(a, b) {
|
|
|
15232
15665
|
return a.sortKey === b.sortKey && a.isDeleted === b.isDeleted && sameJson(a.data, b.data);
|
|
15233
15666
|
}
|
|
15234
15667
|
function toWrite(base, patch) {
|
|
15235
|
-
const
|
|
15236
|
-
if (!
|
|
15237
|
-
if (base && patch.embeddings === void 0 && sameRecord(base.record,
|
|
15668
|
+
const record3 = applyPatch(base?.record, patch);
|
|
15669
|
+
if (!record3) return void 0;
|
|
15670
|
+
if (base && patch.embeddings === void 0 && sameRecord(base.record, record3)) return null;
|
|
15238
15671
|
return {
|
|
15239
|
-
record: fitRecord(
|
|
15672
|
+
record: fitRecord(record3),
|
|
15240
15673
|
expectedVersion: base?.version ?? 0,
|
|
15241
|
-
...patch.embeddings !== void 0 && !
|
|
15242
|
-
...patch.embeddingModel !== void 0 && !
|
|
15674
|
+
...patch.embeddings !== void 0 && !record3.isDeleted ? { embeddings: patch.embeddings } : {},
|
|
15675
|
+
...patch.embeddingModel !== void 0 && !record3.isDeleted ? { embeddingModel: patch.embeddingModel } : {}
|
|
15243
15676
|
};
|
|
15244
15677
|
}
|
|
15245
15678
|
var maxWrites = 25;
|
|
@@ -15373,11 +15806,11 @@ function createVaultChatBackend(options) {
|
|
|
15373
15806
|
for (const listener of [...listeners]) listener(event);
|
|
15374
15807
|
};
|
|
15375
15808
|
const view = (k) => {
|
|
15376
|
-
let
|
|
15809
|
+
let record3 = confirmed.get(k)?.record;
|
|
15377
15810
|
for (const patch of [inflight.get(k), pending.get(k)]) {
|
|
15378
|
-
if (patch)
|
|
15811
|
+
if (patch) record3 = applyPatch(record3, patch) ?? record3;
|
|
15379
15812
|
}
|
|
15380
|
-
return
|
|
15813
|
+
return record3;
|
|
15381
15814
|
};
|
|
15382
15815
|
const conversationLive = (conversationId) => {
|
|
15383
15816
|
const conversation2 = view(key2("conversation", conversationId));
|
|
@@ -15388,10 +15821,10 @@ function createVaultChatBackend(options) {
|
|
|
15388
15821
|
const out = [];
|
|
15389
15822
|
for (const k of keys) {
|
|
15390
15823
|
if (!k.startsWith(`${kind}/`)) continue;
|
|
15391
|
-
const
|
|
15392
|
-
if (!
|
|
15393
|
-
if (conversationId !== void 0 &&
|
|
15394
|
-
out.push(
|
|
15824
|
+
const record3 = view(k);
|
|
15825
|
+
if (!record3 || record3.isDeleted && !includeDeleted) continue;
|
|
15826
|
+
if (conversationId !== void 0 && record3.conversationId !== conversationId) continue;
|
|
15827
|
+
out.push(record3);
|
|
15395
15828
|
}
|
|
15396
15829
|
return out;
|
|
15397
15830
|
};
|
|
@@ -15402,7 +15835,7 @@ function createVaultChatBackend(options) {
|
|
|
15402
15835
|
account: cache.account,
|
|
15403
15836
|
cursor: cursor ?? "",
|
|
15404
15837
|
records: [...confirmed.values()].filter(
|
|
15405
|
-
({ record:
|
|
15838
|
+
({ record: record3 }) => record3.kind === "conversation" || record3.kind !== "project" && keep.has(record3.conversationId)
|
|
15406
15839
|
),
|
|
15407
15840
|
threads: kept,
|
|
15408
15841
|
absent: [...checked].filter((k) => {
|
|
@@ -15716,17 +16149,17 @@ function createVaultChatBackend(options) {
|
|
|
15716
16149
|
return loading;
|
|
15717
16150
|
};
|
|
15718
16151
|
const applyRemote = (snapshot) => {
|
|
15719
|
-
const { record:
|
|
15720
|
-
const k = key2(
|
|
15721
|
-
if (
|
|
16152
|
+
const { record: record3 } = snapshot;
|
|
16153
|
+
const k = key2(record3.kind, record3.id);
|
|
16154
|
+
if (record3.kind === "conversation") {
|
|
15722
16155
|
if (!merge(snapshot)) return;
|
|
15723
|
-
if (
|
|
15724
|
-
announce([
|
|
16156
|
+
if (record3.isDeleted) forgetConversation(record3.id);
|
|
16157
|
+
announce([record3]);
|
|
15725
16158
|
return;
|
|
15726
16159
|
}
|
|
15727
|
-
if (
|
|
15728
|
-
const relevant2 = threads.has(
|
|
15729
|
-
if (relevant2 && merge(snapshot)) announce([
|
|
16160
|
+
if (record3.kind === "project") return;
|
|
16161
|
+
const relevant2 = threads.has(record3.conversationId) || confirmed.has(k) || checked.has(k) && record3.kind !== "message";
|
|
16162
|
+
if (relevant2 && merge(snapshot)) announce([record3]);
|
|
15730
16163
|
};
|
|
15731
16164
|
const listIndex = async (source) => {
|
|
15732
16165
|
const index = [];
|
|
@@ -15877,8 +16310,8 @@ function createVaultChatBackend(options) {
|
|
|
15877
16310
|
checked.add(k);
|
|
15878
16311
|
if (found) merge(found);
|
|
15879
16312
|
}
|
|
15880
|
-
const
|
|
15881
|
-
return
|
|
16313
|
+
const record3 = view(k);
|
|
16314
|
+
return record3 && !record3.isDeleted && conversationLive(record3.conversationId) ? record3 : void 0;
|
|
15882
16315
|
};
|
|
15883
16316
|
const child = async (kind, conversationId) => {
|
|
15884
16317
|
await available2();
|
|
@@ -15915,19 +16348,19 @@ function createVaultChatBackend(options) {
|
|
|
15915
16348
|
await backend.deleteSummary(conversationId);
|
|
15916
16349
|
};
|
|
15917
16350
|
const storedMessage = async (uniqueId) => {
|
|
15918
|
-
const
|
|
15919
|
-
return
|
|
16351
|
+
const record3 = await message(uniqueId);
|
|
16352
|
+
return record3 ? toMessage(record3) : null;
|
|
15920
16353
|
};
|
|
15921
16354
|
const patchMessage = async (uniqueId, patch) => {
|
|
15922
|
-
const
|
|
15923
|
-
if (!
|
|
16355
|
+
const record3 = await message(uniqueId);
|
|
16356
|
+
if (!record3) return null;
|
|
15924
16357
|
await enqueue({
|
|
15925
16358
|
kind: "message",
|
|
15926
16359
|
id: uniqueId,
|
|
15927
|
-
conversationId:
|
|
16360
|
+
conversationId: record3.conversationId,
|
|
15928
16361
|
...patch
|
|
15929
16362
|
});
|
|
15930
|
-
emit({ type: "messages", conversationId:
|
|
16363
|
+
emit({ type: "messages", conversationId: record3.conversationId, origin: "local" });
|
|
15931
16364
|
const updated = view(key2("message", uniqueId));
|
|
15932
16365
|
return updated && !updated.isDeleted ? toMessage(updated) : null;
|
|
15933
16366
|
};
|
|
@@ -15952,12 +16385,12 @@ function createVaultChatBackend(options) {
|
|
|
15952
16385
|
});
|
|
15953
16386
|
const backend = {
|
|
15954
16387
|
async getConversation(conversationId) {
|
|
15955
|
-
const
|
|
15956
|
-
return
|
|
16388
|
+
const record3 = await conversation(conversationId);
|
|
16389
|
+
return record3 && !record3.isDeleted ? toConversation(record3) : null;
|
|
15957
16390
|
},
|
|
15958
16391
|
async getConversations(query) {
|
|
15959
16392
|
await available2();
|
|
15960
|
-
return all("conversation").filter((
|
|
16393
|
+
return all("conversation").filter((record3) => record3.id !== ANUMA_CONVERSATION_ID).map(toConversation).filter(
|
|
15961
16394
|
(c) => query?.projectId === void 0 || (query.projectId === null ? !c.projectId : c.projectId === query.projectId)
|
|
15962
16395
|
).sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
15963
16396
|
},
|
|
@@ -15996,13 +16429,13 @@ function createVaultChatBackend(options) {
|
|
|
15996
16429
|
async updateConversationContext(conversationId, context) {
|
|
15997
16430
|
const set = contextFields(context);
|
|
15998
16431
|
if (Object.keys(set).length > 0) return updateConversation(conversationId, set);
|
|
15999
|
-
const
|
|
16000
|
-
return !!
|
|
16432
|
+
const record3 = await conversation(conversationId);
|
|
16433
|
+
return !!record3 && !record3.isDeleted;
|
|
16001
16434
|
},
|
|
16002
16435
|
async deleteConversation(conversationId) {
|
|
16003
16436
|
if (conversationId === ANUMA_CONVERSATION_ID) return false;
|
|
16004
|
-
const
|
|
16005
|
-
if (!
|
|
16437
|
+
const record3 = await conversation(conversationId);
|
|
16438
|
+
if (!record3 || record3.isDeleted) return false;
|
|
16006
16439
|
for (const [k, patch] of pending)
|
|
16007
16440
|
if (patch.conversationId === conversationId) pending.delete(k);
|
|
16008
16441
|
await enqueue({ kind: "conversation", id: conversationId, conversationId: "", delete: true });
|
|
@@ -16038,8 +16471,8 @@ function createVaultChatBackend(options) {
|
|
|
16038
16471
|
const unknown = ids.map((id2) => key2("message", id2)).filter((k) => !view(k) && !checked.has(k));
|
|
16039
16472
|
await refresh(unknown);
|
|
16040
16473
|
return ids.flatMap((id2) => {
|
|
16041
|
-
const
|
|
16042
|
-
return
|
|
16474
|
+
const record3 = view(key2("message", id2));
|
|
16475
|
+
return record3 && !record3.isDeleted && conversationLive(record3.conversationId) ? [toMessage(record3)] : [];
|
|
16043
16476
|
});
|
|
16044
16477
|
},
|
|
16045
16478
|
async getMessageCount(conversationId) {
|
|
@@ -16047,8 +16480,8 @@ function createVaultChatBackend(options) {
|
|
|
16047
16480
|
},
|
|
16048
16481
|
async getToolCallEventIds(conversationId) {
|
|
16049
16482
|
const ids = /* @__PURE__ */ new Set();
|
|
16050
|
-
for (const
|
|
16051
|
-
const events =
|
|
16483
|
+
for (const record3 of await thread(conversationId)) {
|
|
16484
|
+
const events = record3.data.toolCallEvents;
|
|
16052
16485
|
if (!Array.isArray(events)) continue;
|
|
16053
16486
|
for (const event of events)
|
|
16054
16487
|
if (event && typeof event === "object" && !Array.isArray(event) && typeof event.id === "string")
|
|
@@ -16141,21 +16574,21 @@ function createVaultChatBackend(options) {
|
|
|
16141
16574
|
},
|
|
16142
16575
|
async clearMessages(conversationId) {
|
|
16143
16576
|
await invalidateSummary(conversationId);
|
|
16144
|
-
for (const
|
|
16145
|
-
await enqueue({ kind: "message", id:
|
|
16577
|
+
for (const record3 of await thread(conversationId))
|
|
16578
|
+
await enqueue({ kind: "message", id: record3.id, conversationId, delete: true });
|
|
16146
16579
|
emit({ type: "messages", conversationId, origin: "local" });
|
|
16147
16580
|
},
|
|
16148
16581
|
async deleteMessage(uniqueId) {
|
|
16149
|
-
const
|
|
16150
|
-
if (!
|
|
16151
|
-
await invalidateSummary(
|
|
16582
|
+
const record3 = await message(uniqueId);
|
|
16583
|
+
if (!record3) return null;
|
|
16584
|
+
await invalidateSummary(record3.conversationId, record3);
|
|
16152
16585
|
await enqueue({
|
|
16153
16586
|
kind: "message",
|
|
16154
16587
|
id: uniqueId,
|
|
16155
|
-
conversationId:
|
|
16588
|
+
conversationId: record3.conversationId,
|
|
16156
16589
|
delete: true
|
|
16157
16590
|
});
|
|
16158
|
-
emit({ type: "messages", conversationId:
|
|
16591
|
+
emit({ type: "messages", conversationId: record3.conversationId, origin: "local" });
|
|
16159
16592
|
return uniqueId;
|
|
16160
16593
|
},
|
|
16161
16594
|
observeMessages(conversationId) {
|
|
@@ -16168,13 +16601,13 @@ function createVaultChatBackend(options) {
|
|
|
16168
16601
|
await available2();
|
|
16169
16602
|
if (query?.conversationId) await loadThread(query.conversationId);
|
|
16170
16603
|
const files = [];
|
|
16171
|
-
for (const
|
|
16172
|
-
if (!conversationLive(
|
|
16173
|
-
const stored2 = toMessage(
|
|
16604
|
+
for (const record3 of all("message", query?.conversationId)) {
|
|
16605
|
+
if (!conversationLive(record3.conversationId)) continue;
|
|
16606
|
+
const stored2 = toMessage(record3);
|
|
16174
16607
|
for (const file of stored2.files ?? [])
|
|
16175
16608
|
files.push({
|
|
16176
16609
|
...file,
|
|
16177
|
-
conversationId:
|
|
16610
|
+
conversationId: record3.conversationId,
|
|
16178
16611
|
createdAt: stored2.createdAt,
|
|
16179
16612
|
messageRole: stored2.role
|
|
16180
16613
|
});
|
|
@@ -16213,8 +16646,8 @@ function createVaultChatBackend(options) {
|
|
|
16213
16646
|
return results;
|
|
16214
16647
|
},
|
|
16215
16648
|
async getSummary(conversationId) {
|
|
16216
|
-
const
|
|
16217
|
-
return
|
|
16649
|
+
const record3 = await child("summary", conversationId);
|
|
16650
|
+
return record3 && !record3.isDeleted && record3.data.summarizedUpTo ? toSummary(record3) : null;
|
|
16218
16651
|
},
|
|
16219
16652
|
async upsertSummary(conversationId, summary, summarizedUpTo, tokenCount) {
|
|
16220
16653
|
await child("summary", conversationId);
|
|
@@ -16230,8 +16663,8 @@ function createVaultChatBackend(options) {
|
|
|
16230
16663
|
return toSummary(view(key2("summary", conversationId)));
|
|
16231
16664
|
},
|
|
16232
16665
|
async deleteSummary(conversationId) {
|
|
16233
|
-
const
|
|
16234
|
-
if (!
|
|
16666
|
+
const record3 = await child("summary", conversationId);
|
|
16667
|
+
if (!record3 || record3.isDeleted) return;
|
|
16235
16668
|
await enqueue({
|
|
16236
16669
|
kind: "summary",
|
|
16237
16670
|
id: conversationId,
|
|
@@ -16241,8 +16674,8 @@ function createVaultChatBackend(options) {
|
|
|
16241
16674
|
emit({ type: "summary", conversationId, origin: "local" });
|
|
16242
16675
|
},
|
|
16243
16676
|
async getMemoryLinks(conversationId) {
|
|
16244
|
-
const
|
|
16245
|
-
return
|
|
16677
|
+
const record3 = await child("memory_links", conversationId);
|
|
16678
|
+
return record3 && !record3.isDeleted ? toLinks(record3) : [];
|
|
16246
16679
|
},
|
|
16247
16680
|
async addMemoryLinks(conversationId, items) {
|
|
16248
16681
|
if (!conversationId || items.length === 0) return;
|
|
@@ -16257,8 +16690,8 @@ function createVaultChatBackend(options) {
|
|
|
16257
16690
|
emit({ type: "links", conversationId, origin: "local" });
|
|
16258
16691
|
},
|
|
16259
16692
|
async clearMemoryLinks(conversationId) {
|
|
16260
|
-
const
|
|
16261
|
-
if (!
|
|
16693
|
+
const record3 = await child("memory_links", conversationId);
|
|
16694
|
+
if (!record3 || record3.isDeleted) return;
|
|
16262
16695
|
await enqueue({
|
|
16263
16696
|
kind: "memory_links",
|
|
16264
16697
|
id: conversationId,
|
|
@@ -16276,8 +16709,8 @@ function createVaultChatBackend(options) {
|
|
|
16276
16709
|
async importChats(chats) {
|
|
16277
16710
|
await ready();
|
|
16278
16711
|
const seen = /* @__PURE__ */ new Set();
|
|
16279
|
-
const unique = (items) => items.filter(({ record:
|
|
16280
|
-
const k = key2(
|
|
16712
|
+
const unique = (items) => items.filter(({ record: record3 }) => {
|
|
16713
|
+
const k = key2(record3.kind, record3.id);
|
|
16281
16714
|
if (seen.has(k)) return false;
|
|
16282
16715
|
seen.add(k);
|
|
16283
16716
|
return true;
|
|
@@ -16301,15 +16734,15 @@ function createVaultChatBackend(options) {
|
|
|
16301
16734
|
for (const batch of batches(messages))
|
|
16302
16735
|
messageCount += await connected.importRecords(batch);
|
|
16303
16736
|
} finally {
|
|
16304
|
-
for (const { record:
|
|
16305
|
-
await refresh(conversations.map(({ record:
|
|
16737
|
+
for (const { record: record3 } of messages) checked.delete(key2("message", record3.id));
|
|
16738
|
+
await refresh(conversations.map(({ record: record3 }) => key2("conversation", record3.id))).catch(
|
|
16306
16739
|
() => void 0
|
|
16307
16740
|
);
|
|
16308
|
-
for (const { record:
|
|
16741
|
+
for (const { record: record3 } of conversations) threads.delete(record3.id);
|
|
16309
16742
|
channel?.postMessage("changed");
|
|
16310
16743
|
emit({ type: "conversations", origin: "local" });
|
|
16311
|
-
for (const { record:
|
|
16312
|
-
emit({ type: "messages", conversationId:
|
|
16744
|
+
for (const { record: record3 } of conversations)
|
|
16745
|
+
emit({ type: "messages", conversationId: record3.id, origin: "local" });
|
|
16313
16746
|
}
|
|
16314
16747
|
return { conversations: conversationCount, messages: messageCount };
|
|
16315
16748
|
},
|
|
@@ -16328,8 +16761,8 @@ function createVaultChatBackend(options) {
|
|
|
16328
16761
|
}
|
|
16329
16762
|
};
|
|
16330
16763
|
const updateConversation = async (conversationId, set) => {
|
|
16331
|
-
const
|
|
16332
|
-
if (!
|
|
16764
|
+
const record3 = await conversation(conversationId);
|
|
16765
|
+
if (!record3 || record3.isDeleted) return false;
|
|
16333
16766
|
await enqueue({ kind: "conversation", id: conversationId, conversationId: "", set });
|
|
16334
16767
|
emit({ type: "conversations", origin: "local" });
|
|
16335
16768
|
return true;
|
|
@@ -16505,10 +16938,10 @@ async function decryptConversationTitle(encryptedTitle, address) {
|
|
|
16505
16938
|
);
|
|
16506
16939
|
}
|
|
16507
16940
|
const cacheKey = buildCacheKey(address, encryptedTitle);
|
|
16508
|
-
const
|
|
16509
|
-
if (
|
|
16510
|
-
touchEntry(cacheKey,
|
|
16511
|
-
return
|
|
16941
|
+
const cached2 = titleCache.get(cacheKey);
|
|
16942
|
+
if (cached2 !== void 0) {
|
|
16943
|
+
touchEntry(cacheKey, cached2);
|
|
16944
|
+
return cached2;
|
|
16512
16945
|
}
|
|
16513
16946
|
const inFlight = pendingDecrypts.get(cacheKey);
|
|
16514
16947
|
if (inFlight) return inFlight;
|
|
@@ -16767,25 +17200,25 @@ async function upsertEntitiesInWrite(ctx, entities) {
|
|
|
16767
17200
|
const kindBackfills = existing.filter((e) => {
|
|
16768
17201
|
const incoming = kindByName.get(e.canonicalName);
|
|
16769
17202
|
return incoming !== void 0 && (e.kind === null || e.kind === void 0 || e.kind === "");
|
|
16770
|
-
}).map((
|
|
17203
|
+
}).map((record3) => ({ record: record3, kind: kindByName.get(record3.canonicalName) }));
|
|
16771
17204
|
const missing2 = unique.filter((n) => !existingNames.has(n));
|
|
16772
17205
|
const created = missing2.map(
|
|
16773
|
-
(name) => ctx.entityCollection.prepareCreate((
|
|
16774
|
-
|
|
17206
|
+
(name) => ctx.entityCollection.prepareCreate((record3) => {
|
|
17207
|
+
record3._setRaw("canonical_name", name);
|
|
16775
17208
|
const kind = kindByName.get(name);
|
|
16776
|
-
if (kind !== void 0)
|
|
17209
|
+
if (kind !== void 0) record3._setRaw("kind", kind);
|
|
16777
17210
|
})
|
|
16778
17211
|
);
|
|
16779
17212
|
for (const e of existing) out.set(e.canonicalName, entityToStored(e));
|
|
16780
|
-
for (const
|
|
16781
|
-
for (const { record:
|
|
16782
|
-
out.set(
|
|
17213
|
+
for (const record3 of created) out.set(record3.canonicalName, entityToStored(record3));
|
|
17214
|
+
for (const { record: record3, kind } of kindBackfills) {
|
|
17215
|
+
out.set(record3.canonicalName, { ...entityToStored(record3), kind });
|
|
16783
17216
|
}
|
|
16784
17217
|
return { entities: out, operations: created, kindBackfills };
|
|
16785
17218
|
}
|
|
16786
17219
|
function prepareKindBackfills(backfills) {
|
|
16787
17220
|
return backfills.map(
|
|
16788
|
-
({ record:
|
|
17221
|
+
({ record: record3, kind }) => record3.prepareUpdate((r) => {
|
|
16789
17222
|
r._setRaw("kind", kind);
|
|
16790
17223
|
})
|
|
16791
17224
|
);
|
|
@@ -16913,10 +17346,10 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
16913
17346
|
return;
|
|
16914
17347
|
}
|
|
16915
17348
|
const linkOps = toCreate.map(
|
|
16916
|
-
(e) => ctx.memoryEntityCollection.prepareCreate((
|
|
16917
|
-
|
|
16918
|
-
|
|
16919
|
-
if (userId !== void 0)
|
|
17349
|
+
(e) => ctx.memoryEntityCollection.prepareCreate((record3) => {
|
|
17350
|
+
record3._setRaw("memory_id", memoryId);
|
|
17351
|
+
record3._setRaw("entity_id", e.uniqueId);
|
|
17352
|
+
if (userId !== void 0) record3._setRaw("user_id", userId);
|
|
16920
17353
|
})
|
|
16921
17354
|
);
|
|
16922
17355
|
await ctx.database.batch(
|
|
@@ -16986,10 +17419,10 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
|
|
|
16986
17419
|
...entityOps,
|
|
16987
17420
|
...prepareKindBackfills(kindBackfills),
|
|
16988
17421
|
...toCreate.map(
|
|
16989
|
-
(e) => ctx.memoryEntityCollection.prepareCreate((
|
|
16990
|
-
|
|
16991
|
-
|
|
16992
|
-
if (userId !== void 0)
|
|
17422
|
+
(e) => ctx.memoryEntityCollection.prepareCreate((record3) => {
|
|
17423
|
+
record3._setRaw("memory_id", memoryId);
|
|
17424
|
+
record3._setRaw("entity_id", e.uniqueId);
|
|
17425
|
+
if (userId !== void 0) record3._setRaw("user_id", userId);
|
|
16993
17426
|
})
|
|
16994
17427
|
),
|
|
16995
17428
|
...toDestroy.map((l) => l.prepareDestroyPermanently()),
|
|
@@ -18318,9 +18751,9 @@ var DatabaseManager = class {
|
|
|
18318
18751
|
*/
|
|
18319
18752
|
getDatabase(walletAddress) {
|
|
18320
18753
|
const dbName = this.getDbName(walletAddress);
|
|
18321
|
-
const
|
|
18322
|
-
if (
|
|
18323
|
-
return
|
|
18754
|
+
const cached2 = this.databases.get(dbName);
|
|
18755
|
+
if (cached2) {
|
|
18756
|
+
return cached2;
|
|
18324
18757
|
}
|
|
18325
18758
|
const needsMigration = this.handleSchemaMigration(walletAddress);
|
|
18326
18759
|
if (needsMigration) {
|
|
@@ -19460,8 +19893,8 @@ function visibilityConditions(requested) {
|
|
|
19460
19893
|
if (excluded.length === 0) return [];
|
|
19461
19894
|
return [import_watermelondb24.Q.or(import_watermelondb24.Q.where("visibility", null), import_watermelondb24.Q.where("visibility", import_watermelondb24.Q.notIn(excluded)))];
|
|
19462
19895
|
}
|
|
19463
|
-
function isKinded(
|
|
19464
|
-
return
|
|
19896
|
+
function isKinded(record3) {
|
|
19897
|
+
return record3.kind !== null && record3.kind !== void 0;
|
|
19465
19898
|
}
|
|
19466
19899
|
async function assertCanWrite2(ctx) {
|
|
19467
19900
|
if (ctx.canWrite && !await ctx.canWrite()) {
|
|
@@ -19515,8 +19948,8 @@ function levelConditions(requested) {
|
|
|
19515
19948
|
}
|
|
19516
19949
|
return [byLevel];
|
|
19517
19950
|
}
|
|
19518
|
-
function isOwnedByCtxUser(ctx,
|
|
19519
|
-
return ctx.userId === void 0 ||
|
|
19951
|
+
function isOwnedByCtxUser(ctx, record3) {
|
|
19952
|
+
return ctx.userId === void 0 || record3.userId === ctx.userId;
|
|
19520
19953
|
}
|
|
19521
19954
|
function baseVaultConditions(ctx, options) {
|
|
19522
19955
|
return [
|
|
@@ -19599,43 +20032,43 @@ async function vaultMemoryToStored(memory, walletAddress, signMessage, embeddedW
|
|
|
19599
20032
|
}
|
|
19600
20033
|
return raw;
|
|
19601
20034
|
}
|
|
19602
|
-
function populateNewVaultMemory(
|
|
20035
|
+
function populateNewVaultMemory(record3, ctx, opts, encryptedContent, encryptedKindValue) {
|
|
19603
20036
|
const { level, scope } = resolveCreateLevel(opts);
|
|
19604
|
-
|
|
19605
|
-
|
|
19606
|
-
|
|
19607
|
-
|
|
19608
|
-
|
|
19609
|
-
|
|
19610
|
-
|
|
19611
|
-
|
|
20037
|
+
record3._setRaw("content", encryptedContent);
|
|
20038
|
+
record3._setRaw("scope", scope);
|
|
20039
|
+
record3._setRaw("level", level);
|
|
20040
|
+
record3._setRaw("kind", opts.kind ?? null);
|
|
20041
|
+
record3._setRaw("kind_value", encryptedKindValue ?? null);
|
|
20042
|
+
record3._setRaw("folder_id", opts.folderId ?? null);
|
|
20043
|
+
record3._setRaw("user_id", ctx.userId ?? null);
|
|
20044
|
+
record3._setRaw("is_deleted", false);
|
|
19612
20045
|
if (opts.embedding !== void 0) {
|
|
19613
|
-
|
|
19614
|
-
|
|
20046
|
+
record3._setRaw("embedding", opts.embedding);
|
|
20047
|
+
record3._setRaw("embedding_model", opts.embeddingModel ?? null);
|
|
19615
20048
|
}
|
|
19616
20049
|
if (opts.sourceChunkIds !== void 0) {
|
|
19617
|
-
|
|
20050
|
+
record3._setRaw("source_chunk_ids", serializeSourceChunkIds(opts.sourceChunkIds));
|
|
19618
20051
|
}
|
|
19619
|
-
|
|
19620
|
-
|
|
20052
|
+
record3._setRaw("proof_count", opts.proofCount ?? 1);
|
|
20053
|
+
record3._setRaw("source", opts.source ?? "manual");
|
|
19621
20054
|
if (opts.eventTime) {
|
|
19622
|
-
|
|
19623
|
-
|
|
19624
|
-
|
|
20055
|
+
record3._setRaw("event_time_start", opts.eventTime.start ?? null);
|
|
20056
|
+
record3._setRaw("event_time_end", opts.eventTime.end ?? null);
|
|
20057
|
+
record3._setRaw("event_time_kind", opts.eventTime.kind ?? null);
|
|
19625
20058
|
}
|
|
19626
20059
|
if (opts.factType !== void 0) {
|
|
19627
|
-
|
|
20060
|
+
record3._setRaw("fact_type", opts.factType);
|
|
19628
20061
|
}
|
|
19629
20062
|
if (opts.trustTier !== void 0) {
|
|
19630
|
-
|
|
20063
|
+
record3._setRaw("trust_tier", normalizeTrustTier(opts.trustTier));
|
|
19631
20064
|
}
|
|
19632
|
-
|
|
19633
|
-
|
|
20065
|
+
record3._setRaw("visibility", opts.visibility ?? "private");
|
|
20066
|
+
record3._setRaw(
|
|
19634
20067
|
"published_at",
|
|
19635
20068
|
opts.visibility && opts.visibility !== "private" ? opts.publishedAt ?? Date.now() : null
|
|
19636
20069
|
);
|
|
19637
20070
|
if (opts.geohash !== void 0) {
|
|
19638
|
-
|
|
20071
|
+
record3._setRaw("geohash", opts.geohash);
|
|
19639
20072
|
}
|
|
19640
20073
|
}
|
|
19641
20074
|
async function createVaultMemoryOp(ctx, opts) {
|
|
@@ -19650,7 +20083,7 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
19650
20083
|
const created = await ctx.database.write(async () => {
|
|
19651
20084
|
await assertCanWrite2(ctx);
|
|
19652
20085
|
return ctx.vaultMemoryCollection.create(
|
|
19653
|
-
(
|
|
20086
|
+
(record3) => populateNewVaultMemory(record3, ctx, opts, encryptedContent, encryptedKindValue)
|
|
19654
20087
|
);
|
|
19655
20088
|
});
|
|
19656
20089
|
return vaultMemoryToStored(created, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
@@ -19677,7 +20110,7 @@ async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
|
19677
20110
|
if (target.isDeleted || target.supersededBy || isKinded(target) || !isOwnedByCtxUser(ctx, target))
|
|
19678
20111
|
return;
|
|
19679
20112
|
createdRecord = await ctx.vaultMemoryCollection.create(
|
|
19680
|
-
(
|
|
20113
|
+
(record3) => populateNewVaultMemory(record3, ctx, opts, encryptedContent, encryptedKindValue)
|
|
19681
20114
|
);
|
|
19682
20115
|
await target.update((r) => {
|
|
19683
20116
|
r._setRaw("superseded_by", createdRecord.id);
|
|
@@ -19762,7 +20195,7 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
19762
20195
|
await assertCanWrite2(ctx);
|
|
19763
20196
|
const prepared = optionsArray.map(
|
|
19764
20197
|
(opts, i) => ctx.vaultMemoryCollection.prepareCreate(
|
|
19765
|
-
(
|
|
20198
|
+
(record3) => populateNewVaultMemory(record3, ctx, opts, encryptedContents[i], encryptedKindValues[i])
|
|
19766
20199
|
)
|
|
19767
20200
|
);
|
|
19768
20201
|
await ctx.database.batch(...prepared);
|
|
@@ -19770,16 +20203,16 @@ async function createVaultMemoriesBatchOp(ctx, optionsArray) {
|
|
|
19770
20203
|
});
|
|
19771
20204
|
return Promise.all(
|
|
19772
20205
|
created.map(
|
|
19773
|
-
(
|
|
20206
|
+
(record3) => vaultMemoryToStored(record3, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
19774
20207
|
)
|
|
19775
20208
|
);
|
|
19776
20209
|
}
|
|
19777
20210
|
async function getVaultMemoryOp(ctx, id2) {
|
|
19778
20211
|
try {
|
|
19779
|
-
const
|
|
19780
|
-
if (
|
|
20212
|
+
const record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
20213
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return null;
|
|
19781
20214
|
return vaultMemoryToStored(
|
|
19782
|
-
|
|
20215
|
+
record3,
|
|
19783
20216
|
ctx.walletAddress,
|
|
19784
20217
|
ctx.signMessage,
|
|
19785
20218
|
ctx.embeddedWalletSigner
|
|
@@ -20118,29 +20551,29 @@ async function updateVaultMemoryOp(ctx, id2, opts) {
|
|
|
20118
20551
|
ctx.embeddedWalletSigner
|
|
20119
20552
|
) : opts.content;
|
|
20120
20553
|
let stale = false;
|
|
20121
|
-
const
|
|
20554
|
+
const record3 = probe;
|
|
20122
20555
|
await ctx.database.write(async () => {
|
|
20123
20556
|
await assertCanWrite2(ctx);
|
|
20124
|
-
if (
|
|
20557
|
+
if (record3.isDeleted || record3.supersededBy || !isOwnedByCtxUser(ctx, record3) || opts.freeFormOnly && isKinded(record3) || opts.expectedContent !== void 0 && record3._getRaw("content") !== readStoredContent) {
|
|
20125
20558
|
stale = true;
|
|
20126
20559
|
return;
|
|
20127
20560
|
}
|
|
20128
|
-
const originalUpdatedAt =
|
|
20129
|
-
const nextKind = opts.kind !== void 0 ? opts.kind :
|
|
20130
|
-
const nextLevel = levelAfter(
|
|
20561
|
+
const originalUpdatedAt = record3.updatedAt.getTime();
|
|
20562
|
+
const nextKind = opts.kind !== void 0 ? opts.kind : record3.kind;
|
|
20563
|
+
const nextLevel = levelAfter(record3);
|
|
20131
20564
|
assertValidKindLevel(nextKind, nextLevel);
|
|
20132
20565
|
let observedSources = [];
|
|
20133
20566
|
let replayedObservation = false;
|
|
20134
20567
|
if (opts.observationSourceIds?.length) {
|
|
20135
20568
|
try {
|
|
20136
|
-
const parsed = JSON.parse(
|
|
20569
|
+
const parsed = JSON.parse(record3.sourceChunkIds ?? "[]");
|
|
20137
20570
|
if (Array.isArray(parsed))
|
|
20138
20571
|
observedSources = parsed.filter((id3) => typeof id3 === "string");
|
|
20139
20572
|
} catch {
|
|
20140
20573
|
}
|
|
20141
20574
|
replayedObservation = opts.observationSourceIds.every((id3) => observedSources.includes(id3));
|
|
20142
20575
|
}
|
|
20143
|
-
await
|
|
20576
|
+
await record3.update((r) => {
|
|
20144
20577
|
if (encryptedContent !== void 0) r._setRaw("content", encryptedContent);
|
|
20145
20578
|
if (opts.level !== void 0) {
|
|
20146
20579
|
r._setRaw("level", nextLevel);
|
|
@@ -20207,7 +20640,7 @@ async function updateVaultMemoryOp(ctx, id2, opts) {
|
|
|
20207
20640
|
});
|
|
20208
20641
|
if (stale) return null;
|
|
20209
20642
|
return vaultMemoryToStored(
|
|
20210
|
-
|
|
20643
|
+
record3,
|
|
20211
20644
|
ctx.walletAddress,
|
|
20212
20645
|
ctx.signMessage,
|
|
20213
20646
|
ctx.embeddedWalletSigner
|
|
@@ -20222,22 +20655,22 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
20222
20655
|
if (!entityCtx) {
|
|
20223
20656
|
throw new Error("setMemoryEntitiesOp requires ctx.entityCtx (entity collections)");
|
|
20224
20657
|
}
|
|
20225
|
-
let
|
|
20658
|
+
let record3;
|
|
20226
20659
|
try {
|
|
20227
|
-
|
|
20660
|
+
record3 = await ctx.vaultMemoryCollection.find(memoryId);
|
|
20228
20661
|
} catch {
|
|
20229
20662
|
return null;
|
|
20230
20663
|
}
|
|
20231
|
-
if (
|
|
20664
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return null;
|
|
20232
20665
|
let stale = false;
|
|
20233
|
-
const originalUpdatedAt =
|
|
20666
|
+
const originalUpdatedAt = record3.updatedAt.getTime();
|
|
20234
20667
|
await ctx.database.write(async (writer) => {
|
|
20235
20668
|
await assertCanWrite2(ctx);
|
|
20236
|
-
if (
|
|
20669
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) {
|
|
20237
20670
|
stale = true;
|
|
20238
20671
|
return;
|
|
20239
20672
|
}
|
|
20240
|
-
await
|
|
20673
|
+
await record3.update((r) => {
|
|
20241
20674
|
r._setRaw("topics_user_managed", true);
|
|
20242
20675
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
20243
20676
|
});
|
|
@@ -20261,26 +20694,26 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
20261
20694
|
);
|
|
20262
20695
|
});
|
|
20263
20696
|
if (stale) return null;
|
|
20264
|
-
return vaultMemoryToStored(
|
|
20697
|
+
return vaultMemoryToStored(record3, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
20265
20698
|
}
|
|
20266
20699
|
async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
20267
|
-
let
|
|
20700
|
+
let record3;
|
|
20268
20701
|
try {
|
|
20269
|
-
|
|
20702
|
+
record3 = await ctx.vaultMemoryCollection.find(memoryId);
|
|
20270
20703
|
} catch {
|
|
20271
20704
|
return false;
|
|
20272
20705
|
}
|
|
20273
|
-
if (
|
|
20274
|
-
const originalUpdatedAt =
|
|
20706
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return false;
|
|
20707
|
+
const originalUpdatedAt = record3.updatedAt.getTime();
|
|
20275
20708
|
let cleared = false;
|
|
20276
20709
|
await ctx.database.write(async () => {
|
|
20277
20710
|
await assertCanWrite2(ctx);
|
|
20278
|
-
if (options?.unlessTopicsRecorded && parseTopics(
|
|
20711
|
+
if (options?.unlessTopicsRecorded && parseTopics(record3.topics) !== null) return;
|
|
20279
20712
|
cleared = true;
|
|
20280
|
-
await
|
|
20713
|
+
await record3.update((r) => {
|
|
20281
20714
|
r._setRaw("topics_user_managed", false);
|
|
20282
20715
|
r._setRaw("topics_extracted_version", null);
|
|
20283
|
-
if (
|
|
20716
|
+
if (record3.topicsExtractedAt === null) {
|
|
20284
20717
|
r._setRaw("topics_extracted_at", originalUpdatedAt);
|
|
20285
20718
|
}
|
|
20286
20719
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
@@ -20289,23 +20722,23 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
|
20289
20722
|
return cleared;
|
|
20290
20723
|
}
|
|
20291
20724
|
async function setMemoryVisibilityOp(ctx, id2, opts) {
|
|
20292
|
-
let
|
|
20725
|
+
let record3;
|
|
20293
20726
|
try {
|
|
20294
|
-
|
|
20727
|
+
record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
20295
20728
|
} catch {
|
|
20296
20729
|
return null;
|
|
20297
20730
|
}
|
|
20298
|
-
if (
|
|
20731
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return null;
|
|
20299
20732
|
let stale = false;
|
|
20300
20733
|
await ctx.database.write(async () => {
|
|
20301
20734
|
await assertCanWrite2(ctx);
|
|
20302
|
-
if (
|
|
20735
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) {
|
|
20303
20736
|
stale = true;
|
|
20304
20737
|
return;
|
|
20305
20738
|
}
|
|
20306
|
-
const currentUpdatedAt =
|
|
20307
|
-
const currentPublishedAt =
|
|
20308
|
-
await
|
|
20739
|
+
const currentUpdatedAt = record3.updatedAt.getTime();
|
|
20740
|
+
const currentPublishedAt = record3.publishedAt ?? null;
|
|
20741
|
+
await record3.update((r) => {
|
|
20309
20742
|
r._setRaw("visibility", opts.visibility);
|
|
20310
20743
|
if (opts.visibility === "private") {
|
|
20311
20744
|
r._setRaw("published_at", null);
|
|
@@ -20319,20 +20752,20 @@ async function setMemoryVisibilityOp(ctx, id2, opts) {
|
|
|
20319
20752
|
});
|
|
20320
20753
|
});
|
|
20321
20754
|
if (stale) return null;
|
|
20322
|
-
return vaultMemoryToStored(
|
|
20755
|
+
return vaultMemoryToStored(record3, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
20323
20756
|
}
|
|
20324
20757
|
async function deleteVaultMemoryOp(ctx, id2) {
|
|
20325
20758
|
try {
|
|
20326
|
-
const
|
|
20327
|
-
if (
|
|
20759
|
+
const record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
20760
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return false;
|
|
20328
20761
|
let stale = false;
|
|
20329
20762
|
await ctx.database.write(async () => {
|
|
20330
20763
|
await assertCanWrite2(ctx);
|
|
20331
|
-
if (
|
|
20764
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) {
|
|
20332
20765
|
stale = true;
|
|
20333
20766
|
return;
|
|
20334
20767
|
}
|
|
20335
|
-
await
|
|
20768
|
+
await record3.update((r) => {
|
|
20336
20769
|
r._setRaw("is_deleted", true);
|
|
20337
20770
|
});
|
|
20338
20771
|
});
|
|
@@ -20351,9 +20784,9 @@ async function deleteVaultMemoryOp(ctx, id2) {
|
|
|
20351
20784
|
async function supersedeVaultMemoryOp(ctx, id2, supersededById) {
|
|
20352
20785
|
if (id2 === supersededById) return false;
|
|
20353
20786
|
try {
|
|
20354
|
-
const
|
|
20355
|
-
if (
|
|
20356
|
-
if (isKinded(
|
|
20787
|
+
const record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
20788
|
+
if (record3.isDeleted || record3.supersededBy || !isOwnedByCtxUser(ctx, record3)) return false;
|
|
20789
|
+
if (isKinded(record3)) return false;
|
|
20357
20790
|
let successor;
|
|
20358
20791
|
try {
|
|
20359
20792
|
successor = await ctx.vaultMemoryCollection.find(supersededById);
|
|
@@ -20366,7 +20799,7 @@ async function supersedeVaultMemoryOp(ctx, id2, supersededById) {
|
|
|
20366
20799
|
let stale = false;
|
|
20367
20800
|
await ctx.database.write(async () => {
|
|
20368
20801
|
await assertCanWrite2(ctx);
|
|
20369
|
-
if (
|
|
20802
|
+
if (record3.isDeleted || record3.supersededBy || !isOwnedByCtxUser(ctx, record3)) {
|
|
20370
20803
|
stale = true;
|
|
20371
20804
|
return;
|
|
20372
20805
|
}
|
|
@@ -20374,7 +20807,7 @@ async function supersedeVaultMemoryOp(ctx, id2, supersededById) {
|
|
|
20374
20807
|
stale = true;
|
|
20375
20808
|
return;
|
|
20376
20809
|
}
|
|
20377
|
-
await
|
|
20810
|
+
await record3.update((r) => {
|
|
20378
20811
|
r._setRaw("superseded_by", supersededById);
|
|
20379
20812
|
r._setRaw("superseded_at", Date.now());
|
|
20380
20813
|
});
|
|
@@ -20393,7 +20826,7 @@ async function getUnfiledVaultMemoriesOp(ctx) {
|
|
|
20393
20826
|
const results = await ctx.vaultMemoryCollection.query(...conditions).fetch();
|
|
20394
20827
|
return mapInBatches(
|
|
20395
20828
|
results,
|
|
20396
|
-
(
|
|
20829
|
+
(record3) => vaultMemoryToStored(record3, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
20397
20830
|
);
|
|
20398
20831
|
}
|
|
20399
20832
|
var TOPICS_EXTRACTION_VERSION = 3;
|
|
@@ -20554,17 +20987,17 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
|
|
|
20554
20987
|
}
|
|
20555
20988
|
}
|
|
20556
20989
|
const eligible = records.filter(
|
|
20557
|
-
(
|
|
20990
|
+
(record3) => !record3.isDeleted && isOwnedByCtxUser(ctx, record3) && !record3.topicsUserManaged
|
|
20558
20991
|
);
|
|
20559
|
-
const prepared = eligible.map((
|
|
20560
|
-
const originalUpdatedAt =
|
|
20561
|
-
return
|
|
20992
|
+
const prepared = eligible.map((record3) => {
|
|
20993
|
+
const originalUpdatedAt = record3.updatedAt.getTime();
|
|
20994
|
+
return record3.prepareUpdate((r) => {
|
|
20562
20995
|
r._setRaw("topics_extracted_at", extractedAt);
|
|
20563
20996
|
r._setRaw("topics_extracted_version", version);
|
|
20564
20997
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
20565
20998
|
});
|
|
20566
20999
|
});
|
|
20567
|
-
for (const
|
|
21000
|
+
for (const record3 of eligible) stamped.push(record3.id);
|
|
20568
21001
|
if (prepared.length > 0) await ctx.database.batch(...prepared);
|
|
20569
21002
|
});
|
|
20570
21003
|
}
|
|
@@ -20580,14 +21013,14 @@ async function relinkMemoryTopicsOp(ctx, memoryIds) {
|
|
|
20580
21013
|
try {
|
|
20581
21014
|
await ctx.database.write(async (writer) => {
|
|
20582
21015
|
await assertCanWrite2(ctx);
|
|
20583
|
-
let
|
|
21016
|
+
let record3;
|
|
20584
21017
|
try {
|
|
20585
|
-
|
|
21018
|
+
record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
20586
21019
|
} catch {
|
|
20587
21020
|
return;
|
|
20588
21021
|
}
|
|
20589
|
-
if (
|
|
20590
|
-
const topics = parseTopics(
|
|
21022
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return;
|
|
21023
|
+
const topics = parseTopics(record3.topics);
|
|
20591
21024
|
if (topics === null) return;
|
|
20592
21025
|
await writer.callWriter(() => relinkMemoryEntitiesFromTopicsOp(entityCtx, id2, topics));
|
|
20593
21026
|
relinked.push(id2);
|
|
@@ -20613,18 +21046,18 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
|
20613
21046
|
await assertCanWrite2(ctx);
|
|
20614
21047
|
const records = [];
|
|
20615
21048
|
for (const id2 of chunkIds) {
|
|
20616
|
-
let
|
|
21049
|
+
let record3;
|
|
20617
21050
|
try {
|
|
20618
|
-
|
|
21051
|
+
record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
20619
21052
|
} catch {
|
|
20620
21053
|
continue;
|
|
20621
21054
|
}
|
|
20622
|
-
if (
|
|
20623
|
-
if (parseTopics(
|
|
20624
|
-
records.push(
|
|
21055
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) continue;
|
|
21056
|
+
if (parseTopics(record3.topics) !== null) continue;
|
|
21057
|
+
records.push(record3);
|
|
20625
21058
|
}
|
|
20626
21059
|
if (records.length === 0) return;
|
|
20627
|
-
const links2 = await entityCtx.memoryEntityCollection.query(import_watermelondb24.Q.where("memory_id", import_watermelondb24.Q.oneOf(records.map((
|
|
21060
|
+
const links2 = await entityCtx.memoryEntityCollection.query(import_watermelondb24.Q.where("memory_id", import_watermelondb24.Q.oneOf(records.map((record3) => record3.id)))).unsafeFetchRaw();
|
|
20628
21061
|
const entityIds = Array.from(new Set(links2.map((link) => String(link.entity_id))));
|
|
20629
21062
|
const entitiesById = /* @__PURE__ */ new Map();
|
|
20630
21063
|
for (let j = 0; j < entityIds.length; j += CHUNK) {
|
|
@@ -20644,13 +21077,13 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
|
20644
21077
|
entities.add(entity);
|
|
20645
21078
|
}
|
|
20646
21079
|
const writes = [];
|
|
20647
|
-
for (const
|
|
20648
|
-
const entities = entitiesByMemory.get(
|
|
21080
|
+
for (const record3 of records) {
|
|
21081
|
+
const entities = entitiesByMemory.get(record3.id);
|
|
20649
21082
|
if (!entities?.size) continue;
|
|
20650
|
-
const source =
|
|
21083
|
+
const source = record3.topicsUserManaged ? "user" : "auto";
|
|
20651
21084
|
const write = await resolveMemoryTopicsWrite(
|
|
20652
21085
|
entityCtx,
|
|
20653
|
-
|
|
21086
|
+
record3.id,
|
|
20654
21087
|
Array.from(entities),
|
|
20655
21088
|
[],
|
|
20656
21089
|
source
|
|
@@ -20672,7 +21105,7 @@ async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
|
|
|
20672
21105
|
await ctx.database.write(async () => {
|
|
20673
21106
|
await assertCanWrite2(ctx);
|
|
20674
21107
|
const prepared = records.map(
|
|
20675
|
-
(
|
|
21108
|
+
(record3) => record3.prepareUpdate((r) => {
|
|
20676
21109
|
r._setRaw("is_deleted", true);
|
|
20677
21110
|
})
|
|
20678
21111
|
);
|
|
@@ -20743,22 +21176,22 @@ async function applyDecayTransitionsOp(ctx, candidates, opts) {
|
|
|
20743
21176
|
import_watermelondb24.Q.where("id", import_watermelondb24.Q.oneOf(ids.slice(i, i + CHUNK))),
|
|
20744
21177
|
...ctx.userId !== void 0 ? [import_watermelondb24.Q.where("user_id", ctx.userId)] : []
|
|
20745
21178
|
).fetch();
|
|
20746
|
-
const eligible = records.filter((
|
|
20747
|
-
if (
|
|
21179
|
+
const eligible = records.filter((record3) => {
|
|
21180
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return false;
|
|
20748
21181
|
if (opts.transition === "delete") {
|
|
20749
|
-
return
|
|
21182
|
+
return record3.archivedAt !== null && opts.now - record3.archivedAt > opts.hardDeleteWindowMs;
|
|
20750
21183
|
}
|
|
20751
|
-
const candidate = byId.get(
|
|
20752
|
-
return
|
|
21184
|
+
const candidate = byId.get(record3.id);
|
|
21185
|
+
return record3.archivedAt === null && record3.updatedAt.getTime() === candidate.updatedAt && (record3.lastObservedAt ?? null) === (candidate.lastObservedAt ?? null);
|
|
20753
21186
|
});
|
|
20754
21187
|
const prepared = eligible.map(
|
|
20755
|
-
(
|
|
21188
|
+
(record3) => record3.prepareUpdate((row) => {
|
|
20756
21189
|
if (opts.transition === "archive") row._setRaw("archived_at", opts.now);
|
|
20757
21190
|
else row._setRaw("is_deleted", true);
|
|
20758
21191
|
})
|
|
20759
21192
|
);
|
|
20760
21193
|
if (prepared.length > 0) await ctx.database.batch(prepared);
|
|
20761
|
-
applied = eligible.map((
|
|
21194
|
+
applied = eligible.map((record3) => record3.id);
|
|
20762
21195
|
});
|
|
20763
21196
|
} catch {
|
|
20764
21197
|
continue;
|
|
@@ -20776,21 +21209,21 @@ async function applyDecayTransitionsOp(ctx, candidates, opts) {
|
|
|
20776
21209
|
}
|
|
20777
21210
|
async function archiveVaultMemoryOp(ctx, id2, opts) {
|
|
20778
21211
|
try {
|
|
20779
|
-
const
|
|
20780
|
-
if (
|
|
21212
|
+
const record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
21213
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return false;
|
|
20781
21214
|
let stale = false;
|
|
20782
21215
|
const archivedAtValue = opts?.now ?? Date.now();
|
|
20783
21216
|
await ctx.database.write(async () => {
|
|
20784
21217
|
await assertCanWrite2(ctx);
|
|
20785
|
-
if (
|
|
21218
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3) || record3.archivedAt !== null) {
|
|
20786
21219
|
stale = true;
|
|
20787
21220
|
return;
|
|
20788
21221
|
}
|
|
20789
|
-
if (opts?.expectedUpdatedAt !== void 0 &&
|
|
21222
|
+
if (opts?.expectedUpdatedAt !== void 0 && record3.updatedAt.getTime() !== opts.expectedUpdatedAt || opts?.expectedLastObservedAt !== void 0 && (record3.lastObservedAt ?? null) !== opts.expectedLastObservedAt) {
|
|
20790
21223
|
stale = true;
|
|
20791
21224
|
return;
|
|
20792
21225
|
}
|
|
20793
|
-
await
|
|
21226
|
+
await record3.update((r) => {
|
|
20794
21227
|
r._setRaw("archived_at", archivedAtValue);
|
|
20795
21228
|
});
|
|
20796
21229
|
});
|
|
@@ -20801,16 +21234,16 @@ async function archiveVaultMemoryOp(ctx, id2, opts) {
|
|
|
20801
21234
|
}
|
|
20802
21235
|
async function restoreVaultMemoryOp(ctx, id2) {
|
|
20803
21236
|
try {
|
|
20804
|
-
const
|
|
20805
|
-
if (
|
|
21237
|
+
const record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
21238
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return false;
|
|
20806
21239
|
let stale = false;
|
|
20807
21240
|
await ctx.database.write(async () => {
|
|
20808
21241
|
await assertCanWrite2(ctx);
|
|
20809
|
-
if (
|
|
21242
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) {
|
|
20810
21243
|
stale = true;
|
|
20811
21244
|
return;
|
|
20812
21245
|
}
|
|
20813
|
-
await
|
|
21246
|
+
await record3.update((r) => {
|
|
20814
21247
|
r._setRaw("archived_at", null);
|
|
20815
21248
|
});
|
|
20816
21249
|
});
|
|
@@ -20821,18 +21254,18 @@ async function restoreVaultMemoryOp(ctx, id2) {
|
|
|
20821
21254
|
}
|
|
20822
21255
|
async function hardDeleteDecayedOp(ctx, id2, opts) {
|
|
20823
21256
|
try {
|
|
20824
|
-
const
|
|
20825
|
-
if (
|
|
21257
|
+
const record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
21258
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return false;
|
|
20826
21259
|
const now = opts.now ?? Date.now();
|
|
20827
21260
|
let stale = false;
|
|
20828
21261
|
await ctx.database.write(async () => {
|
|
20829
21262
|
await assertCanWrite2(ctx);
|
|
20830
|
-
const archivedAt =
|
|
20831
|
-
if (
|
|
21263
|
+
const archivedAt = record3.archivedAt;
|
|
21264
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3) || archivedAt === null || now - archivedAt <= opts.hardDeleteWindowMs) {
|
|
20832
21265
|
stale = true;
|
|
20833
21266
|
return;
|
|
20834
21267
|
}
|
|
20835
|
-
await
|
|
21268
|
+
await record3.update((r) => {
|
|
20836
21269
|
r._setRaw("is_deleted", true);
|
|
20837
21270
|
});
|
|
20838
21271
|
});
|
|
@@ -20850,14 +21283,14 @@ async function hardDeleteDecayedOp(ctx, id2, opts) {
|
|
|
20850
21283
|
}
|
|
20851
21284
|
async function updateVaultMemoryEmbeddingOp(ctx, id2, embedding2, embeddingModel, expected) {
|
|
20852
21285
|
try {
|
|
20853
|
-
const
|
|
20854
|
-
if (
|
|
20855
|
-
const readUpdatedAt =
|
|
20856
|
-
const readStoredContent =
|
|
21286
|
+
const record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
21287
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return false;
|
|
21288
|
+
const readUpdatedAt = record3.updatedAt.getTime();
|
|
21289
|
+
const readStoredContent = record3._getRaw("content");
|
|
20857
21290
|
if (expected?.updatedAt !== void 0 && expected.updatedAt !== readUpdatedAt) return false;
|
|
20858
21291
|
if (expected?.content !== void 0) {
|
|
20859
21292
|
const current = await vaultMemoryToStored(
|
|
20860
|
-
|
|
21293
|
+
record3,
|
|
20861
21294
|
ctx.walletAddress,
|
|
20862
21295
|
ctx.signMessage,
|
|
20863
21296
|
ctx.embeddedWalletSigner
|
|
@@ -20867,11 +21300,11 @@ async function updateVaultMemoryEmbeddingOp(ctx, id2, embedding2, embeddingModel
|
|
|
20867
21300
|
let written = false;
|
|
20868
21301
|
await ctx.database.write(async () => {
|
|
20869
21302
|
await assertCanWrite2(ctx);
|
|
20870
|
-
if (
|
|
20871
|
-
const originalUpdatedAt =
|
|
20872
|
-
if (originalUpdatedAt !== readUpdatedAt ||
|
|
21303
|
+
if (record3.isDeleted || !isOwnedByCtxUser(ctx, record3)) return;
|
|
21304
|
+
const originalUpdatedAt = record3.updatedAt.getTime();
|
|
21305
|
+
if (originalUpdatedAt !== readUpdatedAt || record3._getRaw("content") !== readStoredContent)
|
|
20873
21306
|
return;
|
|
20874
|
-
await
|
|
21307
|
+
await record3.update((r) => {
|
|
20875
21308
|
r._setRaw("embedding", embedding2);
|
|
20876
21309
|
r._setRaw("embedding_model", embeddingModel);
|
|
20877
21310
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
@@ -21036,26 +21469,26 @@ async function ingestPublishedPhotoMemoriesOp(ctx, rows) {
|
|
|
21036
21469
|
inserted = writable.length;
|
|
21037
21470
|
if (writable.length === 0) return;
|
|
21038
21471
|
const prepared = writable.map(
|
|
21039
|
-
({ row, content }) => ctx.vaultMemoryCollection.prepareCreate((
|
|
21040
|
-
|
|
21041
|
-
|
|
21042
|
-
|
|
21043
|
-
|
|
21044
|
-
|
|
21045
|
-
|
|
21046
|
-
|
|
21047
|
-
|
|
21048
|
-
|
|
21049
|
-
|
|
21472
|
+
({ row, content }) => ctx.vaultMemoryCollection.prepareCreate((record3) => {
|
|
21473
|
+
record3._raw.id = row.memoryId;
|
|
21474
|
+
record3._setRaw("content", content);
|
|
21475
|
+
record3._setRaw("scope", "shared");
|
|
21476
|
+
record3._setRaw("level", "matching");
|
|
21477
|
+
record3._setRaw("folder_id", null);
|
|
21478
|
+
record3._setRaw("user_id", ctx.userId ?? null);
|
|
21479
|
+
record3._setRaw("is_deleted", false);
|
|
21480
|
+
record3._setRaw("proof_count", 1);
|
|
21481
|
+
record3._setRaw("source", SOURCE_PHOTO);
|
|
21482
|
+
record3._setRaw(
|
|
21050
21483
|
"media",
|
|
21051
21484
|
row.media && row.media.length > 0 ? JSON.stringify(row.media) : null
|
|
21052
21485
|
);
|
|
21053
|
-
|
|
21054
|
-
|
|
21486
|
+
record3._setRaw("visibility", "public");
|
|
21487
|
+
record3._setRaw("published_at", now);
|
|
21055
21488
|
if (row.eventTime) {
|
|
21056
|
-
|
|
21057
|
-
|
|
21058
|
-
|
|
21489
|
+
record3._setRaw("event_time_start", row.eventTime.start ?? null);
|
|
21490
|
+
record3._setRaw("event_time_end", row.eventTime.end ?? null);
|
|
21491
|
+
record3._setRaw("event_time_kind", row.eventTime.kind ?? null);
|
|
21059
21492
|
}
|
|
21060
21493
|
})
|
|
21061
21494
|
);
|
|
@@ -21887,11 +22320,11 @@ function folderToStored(folder) {
|
|
|
21887
22320
|
}
|
|
21888
22321
|
async function createVaultFolderOp(ctx, opts) {
|
|
21889
22322
|
const created = await ctx.database.write(async () => {
|
|
21890
|
-
return ctx.vaultFolderCollection.create((
|
|
21891
|
-
|
|
21892
|
-
|
|
21893
|
-
|
|
21894
|
-
|
|
22323
|
+
return ctx.vaultFolderCollection.create((record3) => {
|
|
22324
|
+
record3._setRaw("name", opts.name);
|
|
22325
|
+
record3._setRaw("scope", opts.scope ?? "private");
|
|
22326
|
+
record3._setRaw("is_system", opts.isSystem ?? false);
|
|
22327
|
+
record3._setRaw("is_deleted", false);
|
|
21895
22328
|
});
|
|
21896
22329
|
});
|
|
21897
22330
|
return folderToStored(created);
|
|
@@ -21902,14 +22335,14 @@ async function getAllVaultFoldersOp(ctx) {
|
|
|
21902
22335
|
}
|
|
21903
22336
|
async function updateVaultFolderOp(ctx, id2, opts) {
|
|
21904
22337
|
try {
|
|
21905
|
-
const
|
|
21906
|
-
if (
|
|
21907
|
-
const scopeChanged = opts.scope !== void 0 && opts.scope !==
|
|
22338
|
+
const record3 = await ctx.vaultFolderCollection.find(id2);
|
|
22339
|
+
if (record3.isDeleted) return null;
|
|
22340
|
+
const scopeChanged = opts.scope !== void 0 && opts.scope !== record3.scope;
|
|
21908
22341
|
const updated = await ctx.database.write(async () => {
|
|
21909
22342
|
const memories = scopeChanged ? await ctx.vaultMemoryCollection.query(import_watermelondb32.Q.where("folder_id", id2), import_watermelondb32.Q.where("is_deleted", false)).fetch() : [];
|
|
21910
22343
|
const updates = [];
|
|
21911
22344
|
updates.push(
|
|
21912
|
-
|
|
22345
|
+
record3.prepareUpdate((r) => {
|
|
21913
22346
|
if (opts.name !== void 0) r._setRaw("name", opts.name);
|
|
21914
22347
|
if (opts.scope !== void 0) r._setRaw("scope", opts.scope);
|
|
21915
22348
|
})
|
|
@@ -21932,8 +22365,8 @@ async function updateVaultFolderOp(ctx, id2, opts) {
|
|
|
21932
22365
|
}
|
|
21933
22366
|
async function deleteVaultFolderOp(ctx, id2) {
|
|
21934
22367
|
try {
|
|
21935
|
-
const
|
|
21936
|
-
if (
|
|
22368
|
+
const record3 = await ctx.vaultFolderCollection.find(id2);
|
|
22369
|
+
if (record3.isDeleted) return false;
|
|
21937
22370
|
await ctx.database.write(async () => {
|
|
21938
22371
|
const memories = await ctx.vaultMemoryCollection.query(import_watermelondb32.Q.where("folder_id", id2), import_watermelondb32.Q.where("is_deleted", false)).fetch();
|
|
21939
22372
|
const preparedMemories = memories.map(
|
|
@@ -21943,7 +22376,7 @@ async function deleteVaultFolderOp(ctx, id2) {
|
|
|
21943
22376
|
r._setRaw("scope", "private");
|
|
21944
22377
|
})
|
|
21945
22378
|
);
|
|
21946
|
-
const preparedFolder =
|
|
22379
|
+
const preparedFolder = record3.prepareUpdate((r) => {
|
|
21947
22380
|
r._setRaw("is_deleted", true);
|
|
21948
22381
|
});
|
|
21949
22382
|
await ctx.database.batch(...preparedMemories, preparedFolder);
|
|
@@ -21990,11 +22423,11 @@ async function moveMemoriesToFolderOp(ctx, memoryIds, folderId) {
|
|
|
21990
22423
|
}
|
|
21991
22424
|
async function updateVaultFolderContextOp(ctx, id2, context) {
|
|
21992
22425
|
try {
|
|
21993
|
-
const
|
|
21994
|
-
if (
|
|
22426
|
+
const record3 = await ctx.vaultFolderCollection.find(id2);
|
|
22427
|
+
if (record3.isDeleted) return null;
|
|
21995
22428
|
const updated = await ctx.database.write(async () => {
|
|
21996
22429
|
await ctx.database.batch(
|
|
21997
|
-
|
|
22430
|
+
record3.prepareUpdate((r) => {
|
|
21998
22431
|
r._setRaw("context", context);
|
|
21999
22432
|
})
|
|
22000
22433
|
);
|
|
@@ -23113,9 +23546,9 @@ function loadVaultCorpus(ctx, options, preparation) {
|
|
|
23113
23546
|
const key3 = JSON.stringify(options ?? {});
|
|
23114
23547
|
let request = pending.get(key3);
|
|
23115
23548
|
if (!request) {
|
|
23116
|
-
const
|
|
23549
|
+
const entries2 = pending;
|
|
23117
23550
|
request = getAllVaultMemoriesOp(ctx, options).catch((error) => {
|
|
23118
|
-
|
|
23551
|
+
entries2.delete(key3);
|
|
23119
23552
|
throw error;
|
|
23120
23553
|
});
|
|
23121
23554
|
pending.set(key3, request);
|
|
@@ -23156,7 +23589,7 @@ function embedVaultRows(ctx, options, rows, preparation) {
|
|
|
23156
23589
|
if (!pending.has(keys[index]) && !prepared?.has(keys[index])) missing2.set(keys[index], row);
|
|
23157
23590
|
});
|
|
23158
23591
|
if (missing2.size > 0) {
|
|
23159
|
-
const
|
|
23592
|
+
const entries2 = pending;
|
|
23160
23593
|
const batch = Promise.resolve().then(
|
|
23161
23594
|
() => generateEmbeddings(
|
|
23162
23595
|
[...missing2.values()].map((row) => row.content),
|
|
@@ -23173,16 +23606,16 @@ function embedVaultRows(ctx, options, rows, preparation) {
|
|
|
23173
23606
|
});
|
|
23174
23607
|
return vector2;
|
|
23175
23608
|
}).finally(() => {
|
|
23176
|
-
|
|
23177
|
-
if (
|
|
23609
|
+
entries2.delete(key3);
|
|
23610
|
+
if (entries2.size === 0) pendingRows.get(ctx)?.delete(options.maskInput);
|
|
23178
23611
|
});
|
|
23179
23612
|
pending.set(key3, request);
|
|
23180
23613
|
});
|
|
23181
23614
|
}
|
|
23182
23615
|
return Promise.all(
|
|
23183
23616
|
keys.map((key3) => {
|
|
23184
|
-
const
|
|
23185
|
-
if (
|
|
23617
|
+
const cached2 = prepared?.get(key3);
|
|
23618
|
+
if (cached2) return cached2;
|
|
23186
23619
|
const request = pending.get(key3);
|
|
23187
23620
|
if (!prepared) return request;
|
|
23188
23621
|
const retained = request.catch((error) => {
|
|
@@ -23882,10 +24315,10 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
|
|
|
23882
24315
|
const resolvedThisCall = /* @__PURE__ */ new Set();
|
|
23883
24316
|
if (!embeddingsDegraded) {
|
|
23884
24317
|
for (const k2 of keys) {
|
|
23885
|
-
const
|
|
23886
|
-
if (
|
|
24318
|
+
const cached2 = cachedRowVector(cache, k2.uniqueId, k2.updatedAt);
|
|
24319
|
+
if (cached2 && cached2.length === queryEmbedding.length) {
|
|
23887
24320
|
corpusStats.cacheHits++;
|
|
23888
|
-
vectored.push({ uniqueId: k2.uniqueId, embedding:
|
|
24321
|
+
vectored.push({ uniqueId: k2.uniqueId, embedding: cached2, updatedAt: k2.updatedAt });
|
|
23889
24322
|
continue;
|
|
23890
24323
|
}
|
|
23891
24324
|
corpusStats.cacheMisses++;
|
|
@@ -24183,12 +24616,12 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
24183
24616
|
for (let i = 0; queryEmbedding.length > 0 && i < memories.length; i++) {
|
|
24184
24617
|
const content = memories[i].content;
|
|
24185
24618
|
const memoryId = memories[i].uniqueId;
|
|
24186
|
-
const
|
|
24187
|
-
if (
|
|
24188
|
-
resolvedVectors.set(memoryId,
|
|
24619
|
+
const cached2 = cachedRowVector(cache, memoryId, memories[i].updatedAt, content);
|
|
24620
|
+
if (cached2 && cached2.length === queryEmbedding.length) {
|
|
24621
|
+
resolvedVectors.set(memoryId, cached2);
|
|
24189
24622
|
continue;
|
|
24190
24623
|
}
|
|
24191
|
-
if (
|
|
24624
|
+
if (cached2) cache.delete(memoryId);
|
|
24192
24625
|
const storedModel = memories[i].embeddingModel;
|
|
24193
24626
|
const modelCompatible = (storedModel ?? currentModel) === currentModel;
|
|
24194
24627
|
if (memories[i].embedding && modelCompatible) {
|
|
@@ -25879,9 +26312,9 @@ function createDecaySweeperOver(backend, options) {
|
|
|
25879
26312
|
if (ruleVerdict !== "keep") return rule;
|
|
25880
26313
|
if (!classifier || !isBorderline(input)) return rule;
|
|
25881
26314
|
if (input.id) {
|
|
25882
|
-
const
|
|
25883
|
-
if (
|
|
25884
|
-
return { verdict:
|
|
26315
|
+
const cached2 = classifierCache.get(input.id);
|
|
26316
|
+
if (cached2 && cached2.activityAt === lastActivityAt(input))
|
|
26317
|
+
return { verdict: cached2.verdict, source: "classifierDriven" };
|
|
25885
26318
|
}
|
|
25886
26319
|
if (sweep.classifierCalls >= maxClassifierCalls) {
|
|
25887
26320
|
sweep.classifierCapHits++;
|
|
@@ -27745,21 +28178,21 @@ async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
|
|
|
27745
28178
|
};
|
|
27746
28179
|
const inputs = [];
|
|
27747
28180
|
for (const id2 of new Set(memoryIds)) {
|
|
27748
|
-
let
|
|
28181
|
+
let record3;
|
|
27749
28182
|
try {
|
|
27750
|
-
|
|
28183
|
+
record3 = await ctx.vaultMemoryCollection.find(id2);
|
|
27751
28184
|
} catch (err) {
|
|
27752
28185
|
log.warn("[memory/topics] vault lookup failed for extraction", err);
|
|
27753
28186
|
skip(id2, "not-found");
|
|
27754
28187
|
continue;
|
|
27755
28188
|
}
|
|
27756
|
-
if (
|
|
28189
|
+
if (record3.isDeleted || ctx.userId !== void 0 && record3.userId !== ctx.userId || record3.topicsUserManaged) {
|
|
27757
28190
|
skip(id2, "excluded");
|
|
27758
28191
|
continue;
|
|
27759
28192
|
}
|
|
27760
28193
|
try {
|
|
27761
28194
|
const stored2 = await vaultMemoryToStored(
|
|
27762
|
-
|
|
28195
|
+
record3,
|
|
27763
28196
|
ctx.walletAddress,
|
|
27764
28197
|
ctx.signMessage,
|
|
27765
28198
|
ctx.embeddedWalletSigner
|
|
@@ -28066,6 +28499,7 @@ function createLocalMemoryStore(options) {
|
|
|
28066
28499
|
|
|
28067
28500
|
// src/lib/memory/store/memoryKeys.ts
|
|
28068
28501
|
var KEY_ID_DOMAIN = "anuma-private-memory-key-id-v1";
|
|
28502
|
+
var TOPIC_HASH_INFO = "anuma-private-memory-topic-hash-v1";
|
|
28069
28503
|
var MemoryKeyError = class extends Error {
|
|
28070
28504
|
constructor(message) {
|
|
28071
28505
|
super(message);
|
|
@@ -28081,17 +28515,40 @@ async function importAesKey(hex) {
|
|
|
28081
28515
|
["encrypt", "decrypt"]
|
|
28082
28516
|
);
|
|
28083
28517
|
}
|
|
28518
|
+
async function deriveTopicHashKey(hex) {
|
|
28519
|
+
const material = await crypto.subtle.importKey(
|
|
28520
|
+
"raw",
|
|
28521
|
+
hexToBytes(hex).buffer,
|
|
28522
|
+
{ name: "HKDF" },
|
|
28523
|
+
false,
|
|
28524
|
+
["deriveBits"]
|
|
28525
|
+
);
|
|
28526
|
+
const bits = await crypto.subtle.deriveBits(
|
|
28527
|
+
{
|
|
28528
|
+
name: "HKDF",
|
|
28529
|
+
hash: "SHA-256",
|
|
28530
|
+
salt: new Uint8Array(32),
|
|
28531
|
+
info: new TextEncoder().encode(TOPIC_HASH_INFO)
|
|
28532
|
+
},
|
|
28533
|
+
material,
|
|
28534
|
+
256
|
|
28535
|
+
);
|
|
28536
|
+
return crypto.subtle.importKey("raw", bits, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
28537
|
+
}
|
|
28538
|
+
function toHex(bytes4) {
|
|
28539
|
+
return Array.from(new Uint8Array(bytes4), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
28540
|
+
}
|
|
28084
28541
|
async function deriveMemoryKeyRing(signatureHex) {
|
|
28085
28542
|
const v3Hex = await deriveKeyFromSignatureV3(signatureHex);
|
|
28086
28543
|
const digest = await crypto.subtle.digest(
|
|
28087
28544
|
"SHA-256",
|
|
28088
28545
|
new TextEncoder().encode(`${KEY_ID_DOMAIN}:${v3Hex}`)
|
|
28089
28546
|
);
|
|
28090
|
-
const keyId = "v3:" + Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
28091
28547
|
return {
|
|
28092
|
-
keyId,
|
|
28548
|
+
keyId: "v3:" + toHex(digest),
|
|
28093
28549
|
v3: await importAesKey(v3Hex),
|
|
28094
|
-
v2: await importAesKey(await deriveKeyFromSignature(signatureHex))
|
|
28550
|
+
v2: await importAesKey(await deriveKeyFromSignature(signatureHex)),
|
|
28551
|
+
topicHash: await deriveTopicHashKey(v3Hex)
|
|
28095
28552
|
};
|
|
28096
28553
|
}
|
|
28097
28554
|
async function decryptWith(value, rings) {
|
|
@@ -28112,7 +28569,10 @@ function memoryCipher(canonical) {
|
|
|
28112
28569
|
if (!ciphertext.startsWith("enc:v3:") || !isEncrypted(ciphertext))
|
|
28113
28570
|
throw new MemoryKeyError("Remote memory content must be enc:v3 ciphertext");
|
|
28114
28571
|
return decryptWith(ciphertext, [canonical]);
|
|
28115
|
-
}
|
|
28572
|
+
},
|
|
28573
|
+
hashTopic: async (normalized2) => toHex(
|
|
28574
|
+
await crypto.subtle.sign("HMAC", canonical.topicHash, new TextEncoder().encode(normalized2))
|
|
28575
|
+
)
|
|
28116
28576
|
};
|
|
28117
28577
|
}
|
|
28118
28578
|
async function reencryptMemoryField(value, canonical, fallbacks = []) {
|
|
@@ -28548,8 +29008,9 @@ var DEFAULT_RATE_LIMIT_WAIT_MS = 1e4;
|
|
|
28548
29008
|
var MAX_ID_BYTES = 128;
|
|
28549
29009
|
var MAX_CONTENT_BYTES = 32 << 10;
|
|
28550
29010
|
var MAX_TEXT_BYTES = 16 << 10;
|
|
29011
|
+
var MAX_TOPICS_BYTES = 32 << 10;
|
|
28551
29012
|
var MAX_SHORT_BYTES = 256;
|
|
28552
|
-
var TEXT_FIELDS = ["
|
|
29013
|
+
var TEXT_FIELDS = ["media", "source_chunk_ids"];
|
|
28553
29014
|
var SHORT_FIELDS = [
|
|
28554
29015
|
"scope",
|
|
28555
29016
|
"kind",
|
|
@@ -28652,7 +29113,7 @@ function bytes3(value) {
|
|
|
28652
29113
|
return value === void 0 ? 0 : utf82.encode(value).length;
|
|
28653
29114
|
}
|
|
28654
29115
|
function fitsNearby(row) {
|
|
28655
|
-
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);
|
|
29116
|
+
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);
|
|
28656
29117
|
}
|
|
28657
29118
|
function invalid2(raw) {
|
|
28658
29119
|
const id2 = raw.id;
|
|
@@ -28696,7 +29157,7 @@ function defined(value) {
|
|
|
28696
29157
|
Object.entries(value).filter(([, field10]) => field10 !== void 0)
|
|
28697
29158
|
);
|
|
28698
29159
|
}
|
|
28699
|
-
async function prepareRow(raw, canonical, rings, model, updatedAt) {
|
|
29160
|
+
async function prepareRow(raw, canonical, codec, rings, model, updatedAt) {
|
|
28700
29161
|
const deleted = bool(raw.is_deleted) ?? false;
|
|
28701
29162
|
const { encrypt } = memoryCipher(canonical);
|
|
28702
29163
|
const localKindValue = text15(raw.kind_value);
|
|
@@ -28710,10 +29171,12 @@ async function prepareRow(raw, canonical, rings, model, updatedAt) {
|
|
|
28710
29171
|
plaintext = void 0;
|
|
28711
29172
|
kindValue = void 0;
|
|
28712
29173
|
}
|
|
29174
|
+
const fields = metadata2(raw, model);
|
|
28713
29175
|
const row = {
|
|
28714
29176
|
...defined({
|
|
28715
|
-
...
|
|
28716
|
-
kind_value: kindValue === void 0 ? void 0 : await encrypt(kindValue)
|
|
29177
|
+
...fields,
|
|
29178
|
+
kind_value: kindValue === void 0 ? void 0 : await encrypt(kindValue),
|
|
29179
|
+
topics: fields.topics === void 0 ? void 0 : await codec.encodeTopics(fields.topics)
|
|
28717
29180
|
}),
|
|
28718
29181
|
memory_id: raw.id,
|
|
28719
29182
|
content: await encrypt(plaintext ?? ""),
|
|
@@ -28757,6 +29220,8 @@ function sameMetadata2(local, remote, model) {
|
|
|
28757
29220
|
if (field10 === "visibility") return (a ?? "private") === (b ?? "private");
|
|
28758
29221
|
if (field10 === "is_deleted" || field10 === "topics_user_managed" || field10 === "twin_opt_in")
|
|
28759
29222
|
return (a ?? false) === (b ?? false);
|
|
29223
|
+
if (field10 === "topics")
|
|
29224
|
+
return JSON.stringify(parseTopics(a)) === JSON.stringify(parseTopics(b));
|
|
28760
29225
|
return a === b;
|
|
28761
29226
|
});
|
|
28762
29227
|
}
|
|
@@ -28812,7 +29277,7 @@ async function missingIds(request, revisions, signal) {
|
|
|
28812
29277
|
}
|
|
28813
29278
|
return missing2;
|
|
28814
29279
|
}
|
|
28815
|
-
async function remoteMetadata(request, ids, signal) {
|
|
29280
|
+
async function remoteMetadata(request, codec, ids, signal) {
|
|
28816
29281
|
const rows = /* @__PURE__ */ new Map();
|
|
28817
29282
|
for (const batch of chunks(ids, QUERY_IDS)) {
|
|
28818
29283
|
let cursor;
|
|
@@ -28836,7 +29301,12 @@ async function remoteMetadata(request, ids, signal) {
|
|
|
28836
29301
|
if (!Array.isArray(page.items)) throw new Error("Invalid nearby private-memory page");
|
|
28837
29302
|
for (const item of page.items)
|
|
28838
29303
|
if (item.memory && typeof item.memory.memory_id === "string")
|
|
28839
|
-
rows.set(item.memory.memory_id,
|
|
29304
|
+
rows.set(item.memory.memory_id, {
|
|
29305
|
+
...item.memory,
|
|
29306
|
+
...typeof item.memory.topics === "string" && {
|
|
29307
|
+
topics: await codec.decodeTopics(item.memory.topics).catch(() => null)
|
|
29308
|
+
}
|
|
29309
|
+
});
|
|
28840
29310
|
cursor = typeof page.next_cursor === "string" ? page.next_cursor : void 0;
|
|
28841
29311
|
} while (cursor);
|
|
28842
29312
|
}
|
|
@@ -28854,6 +29324,7 @@ async function migrateMemoriesToRemote(options) {
|
|
|
28854
29324
|
const rings = [canonical, ...options.fallbacks ?? []];
|
|
28855
29325
|
const model = options.embeddingOptions?.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
28856
29326
|
const request = createNearbyRequest(options);
|
|
29327
|
+
const codec = createTopicCodec(memoryCipher(canonical));
|
|
28857
29328
|
const account = await request("/account", {}, signal);
|
|
28858
29329
|
if (typeof account.key_id === "string" && account.key_id !== canonical.keyId)
|
|
28859
29330
|
throw new RemoteMemoryError(
|
|
@@ -28870,7 +29341,7 @@ async function migrateMemoriesToRemote(options) {
|
|
|
28870
29341
|
...typeof t.kind === "string" && { kind: t.kind }
|
|
28871
29342
|
})).filter((t) => t.name.length > 0) : []);
|
|
28872
29343
|
if (localTopics.length)
|
|
28873
|
-
await createRemoteTopicPersistence(request).importTopics(localTopics, signal);
|
|
29344
|
+
await createRemoteTopicPersistence(request, codec).importTopics(localTopics, signal);
|
|
28874
29345
|
const skipped = /* @__PURE__ */ new Map();
|
|
28875
29346
|
const reembedded = /* @__PURE__ */ new Set();
|
|
28876
29347
|
const unembedded = /* @__PURE__ */ new Set();
|
|
@@ -28889,6 +29360,7 @@ async function migrateMemoriesToRemote(options) {
|
|
|
28889
29360
|
if (pending.size === 0 && !active) {
|
|
28890
29361
|
const remote = await remoteMetadata(
|
|
28891
29362
|
request,
|
|
29363
|
+
codec,
|
|
28892
29364
|
candidates.map((raw) => raw.id),
|
|
28893
29365
|
signal
|
|
28894
29366
|
);
|
|
@@ -28933,7 +29405,7 @@ async function migrateMemoriesToRemote(options) {
|
|
|
28933
29405
|
const updatedAt = pending.get(raw.id);
|
|
28934
29406
|
if (updatedAt === void 0) continue;
|
|
28935
29407
|
try {
|
|
28936
|
-
prepared.push(await prepareRow(raw, canonical, rings, model, updatedAt));
|
|
29408
|
+
prepared.push(await prepareRow(raw, canonical, codec, rings, model, updatedAt));
|
|
28937
29409
|
} catch (error) {
|
|
28938
29410
|
if (!(error instanceof MemoryKeyError)) throw error;
|
|
28939
29411
|
skipped.set(raw.id, "unreadable");
|
|
@@ -29093,7 +29565,7 @@ function topicInputs(topics, source) {
|
|
|
29093
29565
|
function mergeTopics(existing, added) {
|
|
29094
29566
|
const byName = /* @__PURE__ */ new Map();
|
|
29095
29567
|
for (const topic2 of [...existing, ...added]) {
|
|
29096
|
-
const key3 =
|
|
29568
|
+
const key3 = normalizeTopicName(topic2.name);
|
|
29097
29569
|
const kept = byName.get(key3);
|
|
29098
29570
|
if (!kept) byName.set(key3, topic2);
|
|
29099
29571
|
else if (kept.weight !== void 0 && topic2.weight !== void 0 && topic2.weight > kept.weight)
|
|
@@ -29108,7 +29580,7 @@ function sameTopics(stored2, next) {
|
|
|
29108
29580
|
return next.every((t) => keys.has(key3(t)));
|
|
29109
29581
|
}
|
|
29110
29582
|
function canonicalTopics(row) {
|
|
29111
|
-
return new Set((parseTopics(row.topics) ?? []).map((topic2) =>
|
|
29583
|
+
return new Set((parseTopics(row.topics) ?? []).map((topic2) => normalizeTopicName(topic2.name)));
|
|
29112
29584
|
}
|
|
29113
29585
|
function createRemoteMemoryStore(options) {
|
|
29114
29586
|
const { persistence, embeddingOptions } = options;
|
|
@@ -29155,10 +29627,10 @@ function createRemoteMemoryStore(options) {
|
|
|
29155
29627
|
const notify = (change, records = []) => {
|
|
29156
29628
|
invalidateReads();
|
|
29157
29629
|
if (subscribers.size)
|
|
29158
|
-
for (const
|
|
29159
|
-
const previous = seen.get(
|
|
29160
|
-
if ((previous?.version ?? 0) + 1 ===
|
|
29161
|
-
seen.set(
|
|
29630
|
+
for (const record3 of records) {
|
|
29631
|
+
const previous = seen.get(record3.memory.memory_id);
|
|
29632
|
+
if ((previous?.version ?? 0) + 1 === record3.version)
|
|
29633
|
+
seen.set(record3.memory.memory_id, subscriptionState(record3));
|
|
29162
29634
|
}
|
|
29163
29635
|
for (const subscriber of [...subscribers])
|
|
29164
29636
|
if (relevant(change, subscriber.options)) safely(subscriber.onChange);
|
|
@@ -29211,7 +29683,7 @@ function createRemoteMemoryStore(options) {
|
|
|
29211
29683
|
};
|
|
29212
29684
|
const enumerate = (filters, max = Infinity) => pages(decrypted, filters, max);
|
|
29213
29685
|
const memoriesByTopics = async (names) => {
|
|
29214
|
-
const wanted = new Set(names.map(
|
|
29686
|
+
const wanted = new Set(names.map(normalizeTopicName).filter(Boolean));
|
|
29215
29687
|
const out = /* @__PURE__ */ new Map();
|
|
29216
29688
|
const pages2 = await Promise.all(
|
|
29217
29689
|
chunks2([...wanted], MAX_QUERY_TOPICS).map((topics) => enumerate({ topics }))
|
|
@@ -29223,7 +29695,7 @@ function createRemoteMemoryStore(options) {
|
|
|
29223
29695
|
return out;
|
|
29224
29696
|
};
|
|
29225
29697
|
const topicGraphRanking = async (query, recallOptions = {}) => {
|
|
29226
|
-
const wanted = new Set(extractQueryEntities(query).map(
|
|
29698
|
+
const wanted = new Set(extractQueryEntities(query).map(normalizeTopicName).filter(Boolean));
|
|
29227
29699
|
if (wanted.size === 0 || recallOptions.memoryIds?.length === 0) return [];
|
|
29228
29700
|
const rows = await pages(
|
|
29229
29701
|
metadata3,
|
|
@@ -29281,25 +29753,25 @@ function createRemoteMemoryStore(options) {
|
|
|
29281
29753
|
return run;
|
|
29282
29754
|
};
|
|
29283
29755
|
const live2 = async (id2) => {
|
|
29284
|
-
const
|
|
29285
|
-
return
|
|
29756
|
+
const record3 = await persistence.get(id2);
|
|
29757
|
+
return record3 && !record3.memory.is_deleted ? record3 : null;
|
|
29286
29758
|
};
|
|
29287
29759
|
const mutateLocked = async (id2, change, edit, writeOptions) => {
|
|
29288
29760
|
writeOptions?.signal?.throwIfAborted();
|
|
29289
|
-
const
|
|
29290
|
-
if (!
|
|
29291
|
-
if (
|
|
29761
|
+
const record3 = writeOptions?.signal ? await persistence.get(id2, writeOptions.signal) : await live2(id2);
|
|
29762
|
+
if (!record3) return null;
|
|
29763
|
+
if (record3.memory.is_deleted) return null;
|
|
29292
29764
|
if (writeOptions?.canWrite && !await writeOptions.canWrite())
|
|
29293
29765
|
throw new MemorySourceIneligibleError();
|
|
29294
29766
|
writeOptions?.signal?.throwIfAborted();
|
|
29295
|
-
const next = edit(structuredClone(
|
|
29767
|
+
const next = edit(structuredClone(record3.memory));
|
|
29296
29768
|
if (!next) return null;
|
|
29297
29769
|
const saved = writeOptions?.leaseToken ? (await persistence.putMany(
|
|
29298
|
-
[{ memory: next, expectedVersion:
|
|
29770
|
+
[{ memory: next, expectedVersion: record3 }],
|
|
29299
29771
|
writeOptions.signal,
|
|
29300
29772
|
writeOptions.leaseToken
|
|
29301
|
-
))[0] : writeOptions?.signal ? await persistence.put(next,
|
|
29302
|
-
notify(typeof change === "function" ? change(
|
|
29773
|
+
))[0] : writeOptions?.signal ? await persistence.put(next, record3, writeOptions.signal) : await persistence.put(next, record3);
|
|
29774
|
+
notify(typeof change === "function" ? change(record3.memory) : change, [saved]);
|
|
29303
29775
|
return saved;
|
|
29304
29776
|
};
|
|
29305
29777
|
const mutate = (id2, change, edit, writeOptions) => serialized(id2, () => mutateLocked(id2, change, edit, writeOptions));
|
|
@@ -29321,12 +29793,12 @@ function createRemoteMemoryStore(options) {
|
|
|
29321
29793
|
}
|
|
29322
29794
|
const { records, unreadable } = read;
|
|
29323
29795
|
for (const id2 of slice) {
|
|
29324
|
-
const
|
|
29796
|
+
const record3 = records.get(id2);
|
|
29325
29797
|
if (unreadable.has(id2)) failed.set(id2, new Error(`Memory ${id2} could not be decrypted`));
|
|
29326
|
-
else if (!
|
|
29327
|
-
else if (!
|
|
29328
|
-
const memory = edit(structuredClone(
|
|
29329
|
-
if (memory) writes.push({ before:
|
|
29798
|
+
else if (!record3) failed.set(id2, new Error(`Memory ${id2} was not found`));
|
|
29799
|
+
else if (!record3.memory.is_deleted) {
|
|
29800
|
+
const memory = edit(structuredClone(record3.memory));
|
|
29801
|
+
if (memory) writes.push({ before: record3, memory });
|
|
29330
29802
|
}
|
|
29331
29803
|
}
|
|
29332
29804
|
if (writes.length === 0) return;
|
|
@@ -29337,10 +29809,10 @@ function createRemoteMemoryStore(options) {
|
|
|
29337
29809
|
leaseToken
|
|
29338
29810
|
);
|
|
29339
29811
|
const byChange = /* @__PURE__ */ new Map();
|
|
29340
|
-
written.forEach((
|
|
29341
|
-
saved.set(
|
|
29812
|
+
written.forEach((record3, i) => {
|
|
29813
|
+
saved.set(record3.memory.memory_id, record3);
|
|
29342
29814
|
const kind = change(writes[i].before.memory);
|
|
29343
|
-
byChange.set(kind, [...byChange.get(kind) ?? [],
|
|
29815
|
+
byChange.set(kind, [...byChange.get(kind) ?? [], record3]);
|
|
29344
29816
|
});
|
|
29345
29817
|
for (const [kind, changed] of byChange) notify(kind, changed);
|
|
29346
29818
|
} catch (error) {
|
|
@@ -29354,13 +29826,13 @@ function createRemoteMemoryStore(options) {
|
|
|
29354
29826
|
continue;
|
|
29355
29827
|
}
|
|
29356
29828
|
try {
|
|
29357
|
-
const
|
|
29829
|
+
const record3 = await mutateLocked(
|
|
29358
29830
|
id2,
|
|
29359
29831
|
change,
|
|
29360
29832
|
edit,
|
|
29361
29833
|
leaseToken || signal ? { leaseToken, signal } : void 0
|
|
29362
29834
|
);
|
|
29363
|
-
if (
|
|
29835
|
+
if (record3) saved.set(id2, record3);
|
|
29364
29836
|
} catch (rowError) {
|
|
29365
29837
|
signal?.throwIfAborted();
|
|
29366
29838
|
if (isRemoteWorkLeaseExpired(rowError)) throw rowError;
|
|
@@ -29456,12 +29928,12 @@ function createRemoteMemoryStore(options) {
|
|
|
29456
29928
|
const created = (records, inputs) => {
|
|
29457
29929
|
embedInBackground(records.filter((_, i) => inputs[i].embedding === void 0));
|
|
29458
29930
|
notify("membership", records);
|
|
29459
|
-
return records.map((
|
|
29931
|
+
return records.map((record3) => stored(record3.memory));
|
|
29460
29932
|
};
|
|
29461
|
-
const asStored = (
|
|
29933
|
+
const asStored = (record3) => record3 ? stored(record3.memory) : null;
|
|
29462
29934
|
const knownKinds = async (topics, signal) => {
|
|
29463
29935
|
const unkinded = [
|
|
29464
|
-
...new Set(topics.filter((t) => !t.kind).map((t) =>
|
|
29936
|
+
...new Set(topics.filter((t) => !t.kind).map((t) => normalizeTopicName(t.name)))
|
|
29465
29937
|
];
|
|
29466
29938
|
const kinds2 = /* @__PURE__ */ new Map();
|
|
29467
29939
|
for (const names of chunks2(unkinded, MAX_QUERY_TOPICS)) {
|
|
@@ -29473,13 +29945,13 @@ function createRemoteMemoryStore(options) {
|
|
|
29473
29945
|
...signal && { signal }
|
|
29474
29946
|
})) {
|
|
29475
29947
|
for (const topic2 of parseTopics(memory.topics) ?? []) {
|
|
29476
|
-
const name =
|
|
29948
|
+
const name = normalizeTopicName(topic2.name);
|
|
29477
29949
|
if (topic2.kind && !kinds2.has(name)) kinds2.set(name, topic2.kind);
|
|
29478
29950
|
}
|
|
29479
29951
|
}
|
|
29480
29952
|
}
|
|
29481
29953
|
return (topic2) => {
|
|
29482
|
-
const kind = topic2.kind ?? kinds2.get(
|
|
29954
|
+
const kind = topic2.kind ?? kinds2.get(normalizeTopicName(topic2.name));
|
|
29483
29955
|
return kind ? { ...topic2, kind } : topic2;
|
|
29484
29956
|
};
|
|
29485
29957
|
};
|
|
@@ -29502,7 +29974,7 @@ function createRemoteMemoryStore(options) {
|
|
|
29502
29974
|
...cursor2 && { cursor: cursor2 }
|
|
29503
29975
|
});
|
|
29504
29976
|
warnFailed(page.failed);
|
|
29505
|
-
for (const
|
|
29977
|
+
for (const record3 of page.items) records.set(record3.memory.memory_id, record3);
|
|
29506
29978
|
for (const failure of page.failed) unreadable.add(failure.memory_id);
|
|
29507
29979
|
cursor2 = page.next_cursor;
|
|
29508
29980
|
} while (cursor2);
|
|
@@ -29698,8 +30170,8 @@ function createRemoteMemoryStore(options) {
|
|
|
29698
30170
|
const failed = /* @__PURE__ */ new Map();
|
|
29699
30171
|
const collect = (page) => {
|
|
29700
30172
|
warnFailed(page.failed);
|
|
29701
|
-
for (const
|
|
29702
|
-
records.push({ id:
|
|
30173
|
+
for (const record3 of page.items)
|
|
30174
|
+
records.push({ id: record3.memory.memory_id, state: subscriptionState(record3) });
|
|
29703
30175
|
for (const failure of page.failed) failed.set(failure.memory_id, failure.version);
|
|
29704
30176
|
};
|
|
29705
30177
|
let resume = cursor2;
|
|
@@ -29904,7 +30376,7 @@ function createRemoteMemoryStore(options) {
|
|
|
29904
30376
|
result.failed += targets.length;
|
|
29905
30377
|
return finish();
|
|
29906
30378
|
}
|
|
29907
|
-
const writes = targets.flatMap((
|
|
30379
|
+
const writes = targets.flatMap((record3, i) => {
|
|
29908
30380
|
const vector2 = vectors[i];
|
|
29909
30381
|
if (!vector2) {
|
|
29910
30382
|
result.failed++;
|
|
@@ -29914,11 +30386,11 @@ function createRemoteMemoryStore(options) {
|
|
|
29914
30386
|
return [
|
|
29915
30387
|
{
|
|
29916
30388
|
memory: {
|
|
29917
|
-
...
|
|
30389
|
+
...record3.memory,
|
|
29918
30390
|
embedding: storedVector(vector2),
|
|
29919
30391
|
embedding_model: model
|
|
29920
30392
|
},
|
|
29921
|
-
expectedVersion:
|
|
30393
|
+
expectedVersion: record3
|
|
29922
30394
|
}
|
|
29923
30395
|
];
|
|
29924
30396
|
} catch {
|
|
@@ -29933,7 +30405,7 @@ function createRemoteMemoryStore(options) {
|
|
|
29933
30405
|
signal?.throwIfAborted();
|
|
29934
30406
|
const commit = async (slice) => {
|
|
29935
30407
|
const saved = await persistence.putMany(slice, signal, leaseToken);
|
|
29936
|
-
for (const
|
|
30408
|
+
for (const record3 of saved) repaired.add(record3.memory.memory_id);
|
|
29937
30409
|
result.reembedded += saved.length;
|
|
29938
30410
|
notify("embedding", saved);
|
|
29939
30411
|
};
|
|
@@ -30017,7 +30489,7 @@ function createRemoteMemoryStore(options) {
|
|
|
30017
30489
|
if (!topics.length) return;
|
|
30018
30490
|
const existing = new Set((await readTopics()).map((topic2) => topic2.name));
|
|
30019
30491
|
const missing2 = topics.flatMap((topic2) => {
|
|
30020
|
-
const name =
|
|
30492
|
+
const name = normalizeTopicName(topic2.name);
|
|
30021
30493
|
if (existing.has(name)) return [];
|
|
30022
30494
|
existing.add(name);
|
|
30023
30495
|
return [{ ...topic2, name }];
|
|
@@ -30048,7 +30520,7 @@ function createRemoteMemoryStore(options) {
|
|
|
30048
30520
|
include_superseded: true
|
|
30049
30521
|
})) {
|
|
30050
30522
|
for (const topic2 of parseTopics(memory.topics) ?? []) {
|
|
30051
|
-
const name =
|
|
30523
|
+
const name = normalizeTopicName(topic2.name);
|
|
30052
30524
|
if (!name) continue;
|
|
30053
30525
|
const entry = topics.get(name) ?? {
|
|
30054
30526
|
name,
|
|
@@ -30086,7 +30558,7 @@ function createRemoteMemoryStore(options) {
|
|
|
30086
30558
|
},
|
|
30087
30559
|
get: async (id2) => asStored(await live2(id2)),
|
|
30088
30560
|
listArchived: async () => (await enumerate({ archived_only: true, order: "archived", include_embeddings: true })).map(
|
|
30089
|
-
(
|
|
30561
|
+
(record3) => stored(record3.memory)
|
|
30090
30562
|
),
|
|
30091
30563
|
memoriesByTopics,
|
|
30092
30564
|
topicsByMemories: async (memoryIds) => {
|
|
@@ -30102,8 +30574,8 @@ function createRemoteMemoryStore(options) {
|
|
|
30102
30574
|
return out;
|
|
30103
30575
|
},
|
|
30104
30576
|
create: async (input) => {
|
|
30105
|
-
const
|
|
30106
|
-
return created([
|
|
30577
|
+
const record3 = await persistence.put(newRow(input), 0);
|
|
30578
|
+
return created([record3], [input])[0];
|
|
30107
30579
|
},
|
|
30108
30580
|
createMany: async (inputs) => {
|
|
30109
30581
|
const out = [];
|
|
@@ -30190,12 +30662,12 @@ function createRemoteMemoryStore(options) {
|
|
|
30190
30662
|
(memory) => memory.archived_at === void 0 || memory.archived_at === null ? { ...memory, archived_at: Date.now() } : null
|
|
30191
30663
|
),
|
|
30192
30664
|
restore: (id2) => serialized(id2, async () => {
|
|
30193
|
-
const
|
|
30194
|
-
if (!
|
|
30195
|
-
if (
|
|
30665
|
+
const record3 = await live2(id2);
|
|
30666
|
+
if (!record3) return false;
|
|
30667
|
+
if (record3.memory.archived_at === void 0 || record3.memory.archived_at === null)
|
|
30196
30668
|
return true;
|
|
30197
|
-
const { archived_at: _archivedAt, ...memory } =
|
|
30198
|
-
notify("edit", [await persistence.put(memory,
|
|
30669
|
+
const { archived_at: _archivedAt, ...memory } = record3.memory;
|
|
30670
|
+
notify("edit", [await persistence.put(memory, record3)]);
|
|
30199
30671
|
return true;
|
|
30200
30672
|
}),
|
|
30201
30673
|
setTopics: async (memoryId, topics) => {
|
|
@@ -30228,8 +30700,8 @@ function createRemoteMemoryStore(options) {
|
|
|
30228
30700
|
const now = /* @__PURE__ */ new Date();
|
|
30229
30701
|
return mergeTopics([], added).map(
|
|
30230
30702
|
(topic2) => ({
|
|
30231
|
-
uniqueId:
|
|
30232
|
-
canonicalName:
|
|
30703
|
+
uniqueId: normalizeTopicName(topic2.name),
|
|
30704
|
+
canonicalName: normalizeTopicName(topic2.name),
|
|
30233
30705
|
kind: topic2.kind ?? null,
|
|
30234
30706
|
createdAt: now,
|
|
30235
30707
|
updatedAt: now
|
|
@@ -33606,16 +34078,16 @@ var ZipProcessor = class {
|
|
|
33606
34078
|
try {
|
|
33607
34079
|
const arrayBuffer = await dataUrlToArrayBuffer(file.dataUrl);
|
|
33608
34080
|
const zip = await import_jszip.default.loadAsync(arrayBuffer);
|
|
33609
|
-
const
|
|
34081
|
+
const entries2 = [];
|
|
33610
34082
|
const processedContents = [];
|
|
33611
34083
|
zip.forEach((relativePath, zipEntry) => {
|
|
33612
|
-
|
|
34084
|
+
entries2.push({
|
|
33613
34085
|
path: relativePath,
|
|
33614
34086
|
isDirectory: zipEntry.dir,
|
|
33615
34087
|
zipObject: zipEntry
|
|
33616
34088
|
});
|
|
33617
34089
|
});
|
|
33618
|
-
const visibleEntries = this.includeHidden ?
|
|
34090
|
+
const visibleEntries = this.includeHidden ? entries2 : entries2.filter((entry) => !this.isHidden(entry.path));
|
|
33619
34091
|
visibleEntries.sort((a, b) => {
|
|
33620
34092
|
if (a.isDirectory !== b.isDirectory) {
|
|
33621
34093
|
return a.isDirectory ? -1 : 1;
|
|
@@ -33729,17 +34201,17 @@ var ZipProcessor = class {
|
|
|
33729
34201
|
/**
|
|
33730
34202
|
* Format the output with file listing and processed contents
|
|
33731
34203
|
*/
|
|
33732
|
-
formatOutput(
|
|
34204
|
+
formatOutput(entries2, processedContents) {
|
|
33733
34205
|
const lines = [];
|
|
33734
34206
|
lines.push("## Archive Contents\n");
|
|
33735
34207
|
lines.push("```");
|
|
33736
|
-
for (const entry of
|
|
34208
|
+
for (const entry of entries2) {
|
|
33737
34209
|
const icon = entry.isDirectory ? "\u{1F4C1}" : "\u{1F4C4}";
|
|
33738
34210
|
lines.push(`${icon} ${entry.path}`);
|
|
33739
34211
|
}
|
|
33740
34212
|
lines.push("```\n");
|
|
33741
|
-
const fileCount =
|
|
33742
|
-
const dirCount =
|
|
34213
|
+
const fileCount = entries2.filter((e) => !e.isDirectory).length;
|
|
34214
|
+
const dirCount = entries2.filter((e) => e.isDirectory).length;
|
|
33743
34215
|
lines.push(
|
|
33744
34216
|
`**Summary:** ${fileCount} file${fileCount !== 1 ? "s" : ""}, ${dirCount} director${dirCount !== 1 ? "ies" : "y"}
|
|
33745
34217
|
`
|
|
@@ -34923,13 +35395,13 @@ function serializeInline(node) {
|
|
|
34923
35395
|
function openTag(node, indent, depth, selfClose, maxLineWidth) {
|
|
34924
35396
|
const head = `<${tagName(node.tag)}`;
|
|
34925
35397
|
const tail = selfClose ? " />" : ">";
|
|
34926
|
-
const
|
|
34927
|
-
if (
|
|
34928
|
-
const single = `${head} ${
|
|
35398
|
+
const entries2 = Object.entries(node.attrs);
|
|
35399
|
+
if (entries2.length === 0) return `${head}${tail}`;
|
|
35400
|
+
const single = `${head} ${entries2.map(([k, v]) => formatAttr(k, v)).join(" ")}${tail}`;
|
|
34929
35401
|
if (single.length <= maxLineWidth) return single;
|
|
34930
35402
|
const attrPad = indent.repeat(depth + 1);
|
|
34931
35403
|
const closePad = indent.repeat(depth);
|
|
34932
|
-
const body =
|
|
35404
|
+
const body = entries2.map(([k, v]) => `${attrPad}${formatAttr(k, v)}`).join("\n");
|
|
34933
35405
|
return `${head}
|
|
34934
35406
|
${body}
|
|
34935
35407
|
${closePad}${selfClose ? "/>" : ">"}`;
|
|
@@ -34941,13 +35413,13 @@ function formatAttr(name, value) {
|
|
|
34941
35413
|
return `${name}={${formatObjectAttr(value)}}`;
|
|
34942
35414
|
}
|
|
34943
35415
|
function formatObjectAttr(obj) {
|
|
34944
|
-
const
|
|
35416
|
+
const entries2 = Object.entries(obj).map(([k, v]) => {
|
|
34945
35417
|
const key3 = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(k) ? k : JSON.stringify(k);
|
|
34946
35418
|
if (typeof v === "string") return `${key3}: ${JSON.stringify(v)}`;
|
|
34947
35419
|
if (typeof v === "number") return `${key3}: ${String(v)}`;
|
|
34948
35420
|
return `${key3}: ${v ? "true" : "false"}`;
|
|
34949
35421
|
});
|
|
34950
|
-
return `{ ${
|
|
35422
|
+
return `{ ${entries2.join(", ")} }`;
|
|
34951
35423
|
}
|
|
34952
35424
|
function isSafeJsxText(text16) {
|
|
34953
35425
|
if (/[<>{}&]/.test(text16)) return false;
|
|
@@ -35899,6 +36371,12 @@ function cx(...classes) {
|
|
|
35899
36371
|
return classes.filter(Boolean).join(" ");
|
|
35900
36372
|
}
|
|
35901
36373
|
var THEMES = { light: "", dark: ".dark" };
|
|
36374
|
+
var SAFE_CSS_KEY = /^[\w-]+$/;
|
|
36375
|
+
var SAFE_CSS_COLOR = /^(?:#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})|[a-z]+|(?:rgba?|hsla?|hwb|lab|lch|oklab|oklch)\([\w\s.,%/+-]*\)|var\(--[\w-]+\))$/i;
|
|
36376
|
+
function isSafeCssColor(value) {
|
|
36377
|
+
if (typeof value !== "string" || !SAFE_CSS_COLOR.test(value)) return false;
|
|
36378
|
+
return typeof CSS === "undefined" || typeof CSS.supports !== "function" || CSS.supports("color", value);
|
|
36379
|
+
}
|
|
35902
36380
|
var ChartContext = React2.createContext(null);
|
|
35903
36381
|
function useChart() {
|
|
35904
36382
|
const context = React2.useContext(ChartContext);
|
|
@@ -35908,7 +36386,9 @@ function useChart() {
|
|
|
35908
36386
|
return context;
|
|
35909
36387
|
}
|
|
35910
36388
|
function ChartStyle({ id: id2, config }) {
|
|
35911
|
-
const colorConfig = Object.entries(config).filter(
|
|
36389
|
+
const colorConfig = Object.entries(config).filter(
|
|
36390
|
+
([key3, cfg]) => SAFE_CSS_KEY.test(key3) && (cfg.theme || cfg.color)
|
|
36391
|
+
);
|
|
35912
36392
|
if (!colorConfig.length) return null;
|
|
35913
36393
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
35914
36394
|
"style",
|
|
@@ -35919,7 +36399,7 @@ function ChartStyle({ id: id2, config }) {
|
|
|
35919
36399
|
${prefix} [data-chart=${id2}] {
|
|
35920
36400
|
${colorConfig.map(([key3, itemConfig]) => {
|
|
35921
36401
|
const color = itemConfig.theme?.[theme] || itemConfig.color;
|
|
35922
|
-
return color ? ` --color-${key3}: ${color};` : null;
|
|
36402
|
+
return isSafeCssColor(color) ? ` --color-${key3}: ${color};` : null;
|
|
35923
36403
|
}).join("\n")}
|
|
35924
36404
|
}
|
|
35925
36405
|
`
|
|
@@ -36108,12 +36588,37 @@ var DEFAULT_COLORS = [
|
|
|
36108
36588
|
"var(--chart-4)",
|
|
36109
36589
|
"var(--chart-5)"
|
|
36110
36590
|
];
|
|
36591
|
+
function paletteColor(index) {
|
|
36592
|
+
return index < DEFAULT_COLORS.length ? DEFAULT_COLORS[index] : `hsl(${Math.round(index * 137.508 % 360)} 65% 55%)`;
|
|
36593
|
+
}
|
|
36594
|
+
var compactNumber = new Intl.NumberFormat(void 0, {
|
|
36595
|
+
notation: "compact",
|
|
36596
|
+
maximumSignificantDigits: 3
|
|
36597
|
+
});
|
|
36598
|
+
function cellText(value) {
|
|
36599
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? String(value) : "";
|
|
36600
|
+
}
|
|
36601
|
+
function formatTick(value) {
|
|
36602
|
+
return typeof value === "number" ? compactNumber.format(value) : String(value);
|
|
36603
|
+
}
|
|
36604
|
+
var VISUALLY_HIDDEN = {
|
|
36605
|
+
position: "absolute",
|
|
36606
|
+
width: 1,
|
|
36607
|
+
height: 1,
|
|
36608
|
+
padding: 0,
|
|
36609
|
+
margin: -1,
|
|
36610
|
+
overflow: "hidden",
|
|
36611
|
+
clip: "rect(0, 0, 0, 0)",
|
|
36612
|
+
whiteSpace: "nowrap",
|
|
36613
|
+
border: 0
|
|
36614
|
+
};
|
|
36111
36615
|
function buildChartConfig(dataKeys, colors) {
|
|
36112
36616
|
const config = {};
|
|
36113
36617
|
dataKeys.forEach((key3, i) => {
|
|
36618
|
+
const custom = colors?.[key3];
|
|
36114
36619
|
config[key3] = {
|
|
36115
36620
|
label: key3.charAt(0).toUpperCase() + key3.slice(1),
|
|
36116
|
-
color:
|
|
36621
|
+
color: isSafeCssColor(custom) ? custom : paletteColor(i)
|
|
36117
36622
|
};
|
|
36118
36623
|
});
|
|
36119
36624
|
return config;
|
|
@@ -36126,68 +36631,106 @@ function ChartCard({ data }) {
|
|
|
36126
36631
|
return () => cancelAnimationFrame(frame);
|
|
36127
36632
|
}, []);
|
|
36128
36633
|
if ("error" in data) {
|
|
36129
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "my-4 max-w-lg", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "rounded-xl bg-sidebar dark:bg-card px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm text-muted-foreground", children:
|
|
36634
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "my-4 max-w-lg", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "rounded-xl bg-sidebar dark:bg-card px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm text-muted-foreground", children: "Couldn't display this chart." }) }) });
|
|
36130
36635
|
}
|
|
36131
36636
|
const { chartType, title, data: chartData, dataKeys, xAxisKey, colors } = data;
|
|
36132
36637
|
const chartConfig = buildChartConfig(dataKeys, colors);
|
|
36133
|
-
|
|
36134
|
-
|
|
36135
|
-
|
|
36136
|
-
|
|
36137
|
-
|
|
36138
|
-
|
|
36139
|
-
|
|
36140
|
-
|
|
36141
|
-
|
|
36142
|
-
|
|
36143
|
-
|
|
36144
|
-
|
|
36145
|
-
|
|
36146
|
-
|
|
36147
|
-
|
|
36148
|
-
|
|
36149
|
-
|
|
36150
|
-
|
|
36151
|
-
|
|
36152
|
-
|
|
36153
|
-
|
|
36154
|
-
|
|
36155
|
-
|
|
36156
|
-
|
|
36157
|
-
)
|
|
36158
|
-
|
|
36159
|
-
|
|
36160
|
-
|
|
36161
|
-
|
|
36162
|
-
|
|
36163
|
-
|
|
36164
|
-
|
|
36165
|
-
|
|
36166
|
-
|
|
36167
|
-
|
|
36168
|
-
|
|
36169
|
-
|
|
36170
|
-
|
|
36171
|
-
|
|
36172
|
-
|
|
36173
|
-
|
|
36174
|
-
|
|
36175
|
-
|
|
36176
|
-
|
|
36177
|
-
|
|
36178
|
-
|
|
36179
|
-
|
|
36180
|
-
|
|
36181
|
-
|
|
36182
|
-
|
|
36183
|
-
|
|
36184
|
-
|
|
36185
|
-
|
|
36186
|
-
|
|
36187
|
-
|
|
36188
|
-
|
|
36189
|
-
|
|
36190
|
-
|
|
36638
|
+
const seriesColor = (key3) => chartConfig[key3]?.color;
|
|
36639
|
+
const longestTick = chartData.reduce(
|
|
36640
|
+
(longest, point) => dataKeys.reduce((max, key3) => {
|
|
36641
|
+
const value = point[key3];
|
|
36642
|
+
return typeof value === "number" ? Math.max(max, formatTick(value).length) : max;
|
|
36643
|
+
}, longest),
|
|
36644
|
+
0
|
|
36645
|
+
);
|
|
36646
|
+
const yAxisProps = {
|
|
36647
|
+
tickLine: false,
|
|
36648
|
+
axisLine: false,
|
|
36649
|
+
tickFormatter: formatTick,
|
|
36650
|
+
width: Math.min(120, Math.max(40, longestTick * 7 + 16))
|
|
36651
|
+
};
|
|
36652
|
+
const labelKey = chartType === "pie" ? xAxisKey || "name" : xAxisKey;
|
|
36653
|
+
const valueKeys = chartType === "pie" ? dataKeys.slice(0, 1) : dataKeys;
|
|
36654
|
+
const tableColumns = labelKey ? [labelKey, ...valueKeys] : valueKeys;
|
|
36655
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
36656
|
+
"div",
|
|
36657
|
+
{
|
|
36658
|
+
className: "my-4 max-w-lg",
|
|
36659
|
+
ref: containerRef,
|
|
36660
|
+
role: "figure",
|
|
36661
|
+
"aria-label": [title, `${chartType} chart`].filter(Boolean).join(", "),
|
|
36662
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "rounded-xl bg-sidebar dark:bg-card px-5 py-4", children: [
|
|
36663
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm font-medium mb-3", children: title }),
|
|
36664
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("table", { style: VISUALLY_HIDDEN, children: [
|
|
36665
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { children: tableColumns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { scope: "col", children: column }, column)) }) }),
|
|
36666
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tbody", { children: chartData.map((point, row) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { children: tableColumns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: cellText(point[column]) }, column)) }, row)) })
|
|
36667
|
+
] }),
|
|
36668
|
+
ready ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
36669
|
+
ChartContainer,
|
|
36670
|
+
{
|
|
36671
|
+
config: chartConfig,
|
|
36672
|
+
className: "aspect-auto h-[250px] w-full",
|
|
36673
|
+
"aria-hidden": "true",
|
|
36674
|
+
children: chartType === "bar" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_recharts.BarChart, { data: chartData, children: [
|
|
36675
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_recharts.CartesianGrid, { vertical: false }),
|
|
36676
|
+
xAxisKey && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_recharts.XAxis, { dataKey: xAxisKey, tickLine: false, axisLine: false, tickMargin: 8 }),
|
|
36677
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_recharts.YAxis, { ...yAxisProps }),
|
|
36678
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChartTooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChartTooltipContent, {}) }),
|
|
36679
|
+
dataKeys.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChartLegend, { content: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChartLegendContent, {}) }),
|
|
36680
|
+
dataKeys.map((key3) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_recharts.Bar, { dataKey: key3, fill: seriesColor(key3), radius: 4 }, key3))
|
|
36681
|
+
] }) : chartType === "line" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_recharts.LineChart, { data: chartData, children: [
|
|
36682
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_recharts.CartesianGrid, { vertical: false }),
|
|
36683
|
+
xAxisKey && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_recharts.XAxis, { dataKey: xAxisKey, tickLine: false, axisLine: false, tickMargin: 8 }),
|
|
36684
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_recharts.YAxis, { ...yAxisProps }),
|
|
36685
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChartTooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChartTooltipContent, {}) }),
|
|
36686
|
+
dataKeys.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChartLegend, { content: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChartLegendContent, {}) }),
|
|
36687
|
+
dataKeys.map((key3) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
36688
|
+
import_recharts.Line,
|
|
36689
|
+
{
|
|
36690
|
+
dataKey: key3,
|
|
36691
|
+
stroke: seriesColor(key3),
|
|
36692
|
+
strokeWidth: 2,
|
|
36693
|
+
dot: false
|
|
36694
|
+
},
|
|
36695
|
+
key3
|
|
36696
|
+
))
|
|
36697
|
+
] }) : chartType === "area" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_recharts.AreaChart, { data: chartData, children: [
|
|
36698
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_recharts.CartesianGrid, { vertical: false }),
|
|
36699
|
+
xAxisKey && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_recharts.XAxis, { dataKey: xAxisKey, tickLine: false, axisLine: false, tickMargin: 8 }),
|
|
36700
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_recharts.YAxis, { ...yAxisProps }),
|
|
36701
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChartTooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChartTooltipContent, {}) }),
|
|
36702
|
+
dataKeys.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChartLegend, { content: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChartLegendContent, {}) }),
|
|
36703
|
+
dataKeys.map((key3) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
36704
|
+
import_recharts.Area,
|
|
36705
|
+
{
|
|
36706
|
+
dataKey: key3,
|
|
36707
|
+
fill: seriesColor(key3),
|
|
36708
|
+
stroke: seriesColor(key3),
|
|
36709
|
+
fillOpacity: 0.3
|
|
36710
|
+
},
|
|
36711
|
+
key3
|
|
36712
|
+
))
|
|
36713
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_recharts.PieChart, { children: [
|
|
36714
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChartTooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChartTooltipContent, {}) }),
|
|
36715
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
36716
|
+
import_recharts.Pie,
|
|
36717
|
+
{
|
|
36718
|
+
data: chartData,
|
|
36719
|
+
dataKey: dataKeys[0],
|
|
36720
|
+
nameKey: xAxisKey || "name",
|
|
36721
|
+
cx: "50%",
|
|
36722
|
+
cy: "50%",
|
|
36723
|
+
outerRadius: 80,
|
|
36724
|
+
children: chartData.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_recharts.Cell, { fill: paletteColor(index) }, index))
|
|
36725
|
+
}
|
|
36726
|
+
),
|
|
36727
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChartLegend, { content: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChartLegendContent, { nameKey: xAxisKey || "name" }) })
|
|
36728
|
+
] })
|
|
36729
|
+
}
|
|
36730
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-[250px] w-full" })
|
|
36731
|
+
] })
|
|
36732
|
+
}
|
|
36733
|
+
);
|
|
36191
36734
|
}
|
|
36192
36735
|
|
|
36193
36736
|
// src/react/LoggerProvider.tsx
|
|
@@ -36334,7 +36877,7 @@ async function uploadFileToICloud(filename, content, backupRevision) {
|
|
|
36334
36877
|
const recordName = `backup_${filename.replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
36335
36878
|
const arrayBuffer = await content.arrayBuffer();
|
|
36336
36879
|
const base64Data = uint8ArrayToBase64(new Uint8Array(arrayBuffer));
|
|
36337
|
-
const
|
|
36880
|
+
const record3 = {
|
|
36338
36881
|
recordType: RECORD_TYPE,
|
|
36339
36882
|
recordName,
|
|
36340
36883
|
fields: {
|
|
@@ -36345,7 +36888,7 @@ async function uploadFileToICloud(filename, content, backupRevision) {
|
|
|
36345
36888
|
...backupRevision ? { backupRevision: { value: backupRevision } } : {}
|
|
36346
36889
|
}
|
|
36347
36890
|
};
|
|
36348
|
-
const response = await database.saveRecords(
|
|
36891
|
+
const response = await database.saveRecords(record3);
|
|
36349
36892
|
if (!response.records || response.records.length === 0) {
|
|
36350
36893
|
throw new Error("Failed to upload file to iCloud");
|
|
36351
36894
|
}
|
|
@@ -36372,12 +36915,12 @@ async function listICloudFiles() {
|
|
|
36372
36915
|
while (response.continuationMarker) {
|
|
36373
36916
|
break;
|
|
36374
36917
|
}
|
|
36375
|
-
const files = allRecords.map((
|
|
36376
|
-
recordName:
|
|
36377
|
-
filename:
|
|
36378
|
-
modifiedAt: new Date(
|
|
36379
|
-
backupRevision:
|
|
36380
|
-
size: typeof
|
|
36918
|
+
const files = allRecords.map((record3) => ({
|
|
36919
|
+
recordName: record3.recordName,
|
|
36920
|
+
filename: record3.fields.filename?.value ?? "",
|
|
36921
|
+
modifiedAt: new Date(record3.modified?.timestamp ?? Date.now()),
|
|
36922
|
+
backupRevision: record3.fields.backupRevision?.value,
|
|
36923
|
+
size: typeof record3.fields.data?.value === "object" && record3.fields.data?.value !== null ? record3.fields.data.value.size : 0
|
|
36381
36924
|
}));
|
|
36382
36925
|
return files.sort((a, b) => b.modifiedAt.getTime() - a.modifiedAt.getTime());
|
|
36383
36926
|
}
|
|
@@ -36390,8 +36933,8 @@ async function downloadICloudFile(recordName) {
|
|
|
36390
36933
|
if (!response.records || response.records.length === 0) {
|
|
36391
36934
|
throw new Error(`File not found: ${recordName}`);
|
|
36392
36935
|
}
|
|
36393
|
-
const
|
|
36394
|
-
const dataField =
|
|
36936
|
+
const record3 = response.records[0];
|
|
36937
|
+
const dataField = record3.fields.data?.value;
|
|
36395
36938
|
if (!dataField) {
|
|
36396
36939
|
throw new Error("No data in record");
|
|
36397
36940
|
}
|
|
@@ -36425,13 +36968,13 @@ async function findICloudFile(filename) {
|
|
|
36425
36968
|
if (!response.records || response.records.length === 0) {
|
|
36426
36969
|
return null;
|
|
36427
36970
|
}
|
|
36428
|
-
const
|
|
36971
|
+
const record3 = response.records[0];
|
|
36429
36972
|
return {
|
|
36430
|
-
recordName:
|
|
36431
|
-
filename:
|
|
36432
|
-
modifiedAt: new Date(
|
|
36433
|
-
backupRevision:
|
|
36434
|
-
size: typeof
|
|
36973
|
+
recordName: record3.recordName,
|
|
36974
|
+
filename: record3.fields.filename?.value ?? "",
|
|
36975
|
+
modifiedAt: new Date(record3.modified?.timestamp ?? Date.now()),
|
|
36976
|
+
backupRevision: record3.fields.backupRevision?.value,
|
|
36977
|
+
size: typeof record3.fields.data?.value === "object" && record3.fields.data?.value !== null ? record3.fields.data.value.size : 0
|
|
36435
36978
|
};
|
|
36436
36979
|
}
|
|
36437
36980
|
|
|
@@ -37787,13 +38330,13 @@ function useConversationRedactors(database, account, storage, secondaryStorage)
|
|
|
37787
38330
|
return (0, import_react5.useCallback)(
|
|
37788
38331
|
(conversationId, nerDetector) => {
|
|
37789
38332
|
if (!scope.active) return retiredRedactor;
|
|
37790
|
-
const
|
|
37791
|
-
if (
|
|
38333
|
+
const cached2 = scope.redactors.get(conversationId);
|
|
38334
|
+
if (cached2 && cached2.detector === nerDetector) {
|
|
37792
38335
|
scope.redactors.delete(conversationId);
|
|
37793
|
-
scope.redactors.set(conversationId,
|
|
37794
|
-
return
|
|
38336
|
+
scope.redactors.set(conversationId, cached2);
|
|
38337
|
+
return cached2.redactor;
|
|
37795
38338
|
}
|
|
37796
|
-
if (
|
|
38339
|
+
if (cached2) scope.evicted.push(cached2.redactor);
|
|
37797
38340
|
const redactor = new PiiRedactor({ nerDetector });
|
|
37798
38341
|
scope.redactors.set(conversationId, { redactor, detector: nerDetector });
|
|
37799
38342
|
if (scope.redactors.size > REDACTOR_LIMIT) {
|
|
@@ -41285,11 +41828,11 @@ async function fetchAllModelPages(baseUrl, provider, headers, previous, signal)
|
|
|
41285
41828
|
return { pages, models, fetchedAt: Date.now() };
|
|
41286
41829
|
}
|
|
41287
41830
|
function loadModels(key3, baseUrl, provider, headers, force, signal) {
|
|
41288
|
-
const
|
|
41289
|
-
if (
|
|
41290
|
-
return Promise.resolve([...
|
|
41831
|
+
const cached2 = modelsCache.get(key3);
|
|
41832
|
+
if (cached2 && !force && Date.now() - cached2.fetchedAt < MODELS_CACHE_TTL_MS) {
|
|
41833
|
+
return Promise.resolve([...cached2.models]);
|
|
41291
41834
|
}
|
|
41292
|
-
const shared = (force ? void 0 : modelsInFlight.get(key3)) ?? startSharedRequest(key3, baseUrl, provider, headers,
|
|
41835
|
+
const shared = (force ? void 0 : modelsInFlight.get(key3)) ?? startSharedRequest(key3, baseUrl, provider, headers, cached2);
|
|
41293
41836
|
return waitForSharedRequest(key3, shared, signal).then((models) => [...models]);
|
|
41294
41837
|
}
|
|
41295
41838
|
function startSharedRequest(key3, baseUrl, provider, headers, previous) {
|
|
@@ -42146,20 +42689,20 @@ function startObserve(entry, walletAddress) {
|
|
|
42146
42689
|
"updated_at"
|
|
42147
42690
|
]).subscribe({
|
|
42148
42691
|
next: (records) => {
|
|
42149
|
-
const
|
|
42150
|
-
if (!
|
|
42692
|
+
const record3 = records[0];
|
|
42693
|
+
if (!record3) return;
|
|
42151
42694
|
const patch = {
|
|
42152
42695
|
userPreference: {
|
|
42153
|
-
uniqueId:
|
|
42154
|
-
walletAddress:
|
|
42155
|
-
nickname:
|
|
42156
|
-
occupation:
|
|
42157
|
-
description:
|
|
42158
|
-
models:
|
|
42159
|
-
personality:
|
|
42160
|
-
externalWallets:
|
|
42161
|
-
createdAt:
|
|
42162
|
-
updatedAt:
|
|
42696
|
+
uniqueId: record3.id,
|
|
42697
|
+
walletAddress: record3.walletAddress,
|
|
42698
|
+
nickname: record3.nickname,
|
|
42699
|
+
occupation: record3.occupation,
|
|
42700
|
+
description: record3.description,
|
|
42701
|
+
models: record3.models,
|
|
42702
|
+
personality: record3.personality,
|
|
42703
|
+
externalWallets: record3.externalWallets,
|
|
42704
|
+
createdAt: record3.createdAt,
|
|
42705
|
+
updatedAt: record3.updatedAt
|
|
42163
42706
|
}
|
|
42164
42707
|
};
|
|
42165
42708
|
if (isInitialEmission) {
|